mesauth-angular 1.3.3 → 1.3.4
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.
- package/fesm2022/mesauth-angular.mjs +360 -127
- package/fesm2022/mesauth-angular.mjs.map +1 -1
- package/index.d.ts +4 -0
- package/package.json +1 -1
|
@@ -2,8 +2,8 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { InjectionToken, makeEnvironmentProviders, provideAppInitializer, inject, NgZone, Injectable, NgModule, EventEmitter, signal, HostListener, HostBinding, Output, Component, ViewChild } from '@angular/core';
|
|
3
3
|
import { HttpClient } from '@angular/common/http';
|
|
4
4
|
import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';
|
|
5
|
-
import { BehaviorSubject, Subject, EMPTY, of, throwError } from 'rxjs';
|
|
6
|
-
import { tap, catchError, takeUntil } from 'rxjs/operators';
|
|
5
|
+
import { BehaviorSubject, Subject, EMPTY, of, timer, throwError } from 'rxjs';
|
|
6
|
+
import { tap, catchError, switchMap, takeUntil } from 'rxjs/operators';
|
|
7
7
|
import * as i2 from '@angular/router';
|
|
8
8
|
import { Router } from '@angular/router';
|
|
9
9
|
import * as i3 from '@angular/common';
|
|
@@ -303,12 +303,16 @@ const mesAuthInterceptor = (req, next) => {
|
|
|
303
303
|
// Skip redirect for the initial /auth/me check (app startup when not logged in)
|
|
304
304
|
const isMeAuthPage = req.url.includes('/auth/me');
|
|
305
305
|
if (status === 401 && !isLoginPage && !isAuthPage && !isMeAuthPage && !isPublicPage) {
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
306
|
+
// Wait 1.5s for the concurrent refresh's Set-Cookie to be processed, then retry once.
|
|
307
|
+
// If retry also gets 401, redirect to login.
|
|
308
|
+
return timer(1500).pipe(switchMap(() => next(req)), catchError((retryError) => {
|
|
309
|
+
if (retryError.status === 401) {
|
|
310
|
+
isRedirecting = true;
|
|
311
|
+
setTimeout(() => { isRedirecting = false; }, 5000);
|
|
312
|
+
window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;
|
|
313
|
+
}
|
|
314
|
+
return throwError(() => retryError);
|
|
315
|
+
}));
|
|
312
316
|
}
|
|
313
317
|
else if (status === 403 && !is403Page) {
|
|
314
318
|
isRedirecting = true;
|
|
@@ -545,40 +549,74 @@ class UserProfileComponent {
|
|
|
545
549
|
<div class="user-profile-container">
|
|
546
550
|
<!-- Not logged in -->
|
|
547
551
|
<ng-container *ngIf="!currentUser()">
|
|
548
|
-
<button class="login-btn" (click)="onLogin()">
|
|
549
|
-
Login
|
|
550
|
-
</button>
|
|
552
|
+
<button class="login-btn" (click)="onLogin()">Login</button>
|
|
551
553
|
</ng-container>
|
|
552
554
|
|
|
553
555
|
<!-- Logged in -->
|
|
554
556
|
<ng-container *ngIf="currentUser()">
|
|
555
557
|
<div class="user-header">
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
<
|
|
558
|
+
<!-- Notification Bell -->
|
|
559
|
+
<button class="notification-btn" [class.has-unread]="unreadCount > 0" (click)="onNotificationClick()" title="Notifications">
|
|
560
|
+
<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">
|
|
561
|
+
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
562
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
563
|
+
</svg>
|
|
564
|
+
<span class="badge" *ngIf="unreadCount > 0">{{ unreadCount > 99 ? '99+' : unreadCount }}</span>
|
|
559
565
|
</button>
|
|
560
566
|
|
|
567
|
+
<!-- User Avatar + Dropdown -->
|
|
561
568
|
<div class="user-menu-wrapper">
|
|
562
569
|
<button class="user-menu-btn" (click)="toggleDropdown()">
|
|
563
|
-
<
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
570
|
+
<div class="avatar-ring" [class.active]="dropdownOpen">
|
|
571
|
+
<img
|
|
572
|
+
*ngIf="currentUser().fullName || currentUser().userName"
|
|
573
|
+
[src]="getAvatarUrl(currentUser())"
|
|
574
|
+
[alt]="currentUser().fullName || currentUser().userName"
|
|
575
|
+
class="avatar"
|
|
576
|
+
/>
|
|
577
|
+
<span *ngIf="!(currentUser().fullName || currentUser().userName)" class="avatar-initial">
|
|
578
|
+
{{ getLastNameInitial(currentUser()) }}
|
|
579
|
+
</span>
|
|
580
|
+
</div>
|
|
572
581
|
</button>
|
|
573
582
|
|
|
574
583
|
<div class="mes-dropdown-menu" *ngIf="dropdownOpen">
|
|
584
|
+
<!-- User info header -->
|
|
575
585
|
<div class="mes-dropdown-header">
|
|
576
|
-
|
|
586
|
+
<div class="dropdown-avatar-wrap">
|
|
587
|
+
<img
|
|
588
|
+
*ngIf="currentUser().fullName || currentUser().userName"
|
|
589
|
+
[src]="getAvatarUrl(currentUser())"
|
|
590
|
+
[alt]="currentUser().fullName || currentUser().userName"
|
|
591
|
+
class="dropdown-avatar"
|
|
592
|
+
/>
|
|
593
|
+
<span *ngIf="!(currentUser().fullName || currentUser().userName)" class="dropdown-avatar-initial">
|
|
594
|
+
{{ getLastNameInitial(currentUser()) }}
|
|
595
|
+
</span>
|
|
596
|
+
</div>
|
|
597
|
+
<div class="dropdown-user-info">
|
|
598
|
+
<span class="dropdown-user-name">{{ currentUser().fullName || currentUser().userName }}</span>
|
|
599
|
+
<span class="dropdown-user-sub" *ngIf="currentUser().position || currentUser().department">
|
|
600
|
+
{{ currentUser().position || currentUser().department }}
|
|
601
|
+
</span>
|
|
602
|
+
</div>
|
|
577
603
|
</div>
|
|
604
|
+
|
|
605
|
+
<div class="mes-dropdown-divider"></div>
|
|
606
|
+
|
|
578
607
|
<button class="mes-dropdown-item profile-link" (click)="onViewProfile()">
|
|
608
|
+
<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">
|
|
609
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
|
|
610
|
+
</svg>
|
|
579
611
|
View Profile
|
|
580
612
|
</button>
|
|
613
|
+
|
|
614
|
+
<div class="mes-dropdown-divider"></div>
|
|
615
|
+
|
|
581
616
|
<button class="mes-dropdown-item logout-item" (click)="onLogout()">
|
|
617
|
+
<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">
|
|
618
|
+
<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"/>
|
|
619
|
+
</svg>
|
|
582
620
|
Logout
|
|
583
621
|
</button>
|
|
584
622
|
</div>
|
|
@@ -586,7 +624,7 @@ class UserProfileComponent {
|
|
|
586
624
|
</div>
|
|
587
625
|
</ng-container>
|
|
588
626
|
</div>
|
|
589
|
-
`, isInline: true, styles: [":host{--primary-color: #1976d2;--primary-hover: #1565c0;--primary-light: rgba(25, 118, 210, .
|
|
627
|
+
`, isInline: true, styles: [":host{--primary-color: #1976d2;--primary-hover: #1565c0;--primary-light: rgba(25, 118, 210, .12);--primary-glow: rgba(25, 118, 210, .3);--error-color: #f44336;--error-light: rgba(244, 67, 54, .1);--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f8f9fa;--bg-hover: #f0f4ff;--border-color: #e0e0e0;--shadow: rgba(0, 0, 0, .12);--shadow-lg: rgba(0, 0, 0, .18)}:host(.theme-dark){--primary-color: #90caf9;--primary-hover: #64b5f6;--primary-light: rgba(144, 202, 249, .12);--primary-glow: rgba(144, 202, 249, .25);--error-color: #ef5350;--error-light: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--border-color: #383850;--shadow: rgba(0, 0, 0, .35);--shadow-lg: rgba(0, 0, 0, .5)}.user-profile-container{display:flex;align-items:center;gap:4px}.login-btn{padding:7px 18px;background-color:var(--primary-color);color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:500;font-size:13px;letter-spacing:.2px;transition:background-color .2s,transform .15s}.login-btn:hover{background-color:var(--primary-hover);transform:translateY(-1px)}.user-header{display:flex;align-items:center;gap:4px}.notification-btn{position:relative;background:none;border:none;cursor:pointer;padding:8px;border-radius:10px;color:var(--text-secondary);display:flex;align-items:center;justify-content:center;transition:color .2s,background-color .2s}.notification-btn:hover{background-color:var(--primary-light);color:var(--primary-color)}.notification-btn.has-unread{color:var(--primary-color)}.bell-icon{display:block;transition:transform .35s cubic-bezier(.34,1.56,.64,1)}.notification-btn:hover .bell-icon{transform:rotate(-20deg) scale(1.15)}.badge{position:absolute;top:2px;right:2px;background-color:var(--error-color);color:#fff;border-radius:10px;min-width:17px;height:17px;padding:0 4px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;line-height:1;box-shadow:0 0 0 2px var(--bg-primary);animation:badge-pop .25s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(0)}to{transform:scale(1)}}.user-menu-wrapper{position:relative}.user-menu-btn{background:none;border:none;cursor:pointer;padding:2px;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:transform .2s}.user-menu-btn:hover{transform:scale(1.06)}.avatar-ring{border-radius:50%;padding:2px;border:2px solid transparent;transition:border-color .25s,box-shadow .25s}.avatar-ring.active,.user-menu-btn:hover .avatar-ring{border-color:var(--primary-color);box-shadow:0 0 0 3px var(--primary-glow)}.avatar{width:36px;height:36px;border-radius:50%;object-fit:cover;display:block}.avatar-initial{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color),var(--primary-hover));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:15px}.mes-dropdown-menu{position:absolute;top:calc(100% + 10px);right:0;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:14px;box-shadow:0 8px 32px var(--shadow-lg),0 2px 8px var(--shadow);min-width:220px;z-index:1000;overflow:hidden;animation:dropdown-in .16s cubic-bezier(.16,1,.3,1)}@keyframes dropdown-in{0%{opacity:0;transform:translateY(-8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.mes-dropdown-header{display:flex;align-items:center;gap:12px;padding:16px;background:var(--bg-secondary)}.dropdown-avatar-wrap{flex-shrink:0}.dropdown-avatar{width:46px;height:46px;border-radius:50%;object-fit:cover;border:2px solid var(--primary-color);display:block}.dropdown-avatar-initial{width:46px;height:46px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color),var(--primary-hover));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:18px;border:2px solid var(--primary-color)}.dropdown-user-info{display:flex;flex-direction:column;gap:3px;min-width:0}.dropdown-user-name{font-weight:600;font-size:14px;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-user-sub{font-size:11px;color:var(--primary-color);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mes-dropdown-divider{height:1px;background:var(--border-color)}.mes-dropdown-item{display:flex;align-items:center;gap:10px;width:100%;padding:11px 16px;border:none;background:none;text-align:left;cursor:pointer;font-size:13.5px;font-weight:500;transition:background-color .15s}.item-icon{flex-shrink:0;opacity:.8}.profile-link{color:var(--primary-color)}.profile-link:hover{background-color:var(--primary-light)}.logout-item{color:var(--error-color)}.logout-item:hover{background-color:var(--error-light)}@media(max-width:768px){.avatar,.avatar-initial{width:32px;height:32px;font-size:13px}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
590
628
|
}
|
|
591
629
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: UserProfileComponent, decorators: [{
|
|
592
630
|
type: Component,
|
|
@@ -594,40 +632,74 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
594
632
|
<div class="user-profile-container">
|
|
595
633
|
<!-- Not logged in -->
|
|
596
634
|
<ng-container *ngIf="!currentUser()">
|
|
597
|
-
<button class="login-btn" (click)="onLogin()">
|
|
598
|
-
Login
|
|
599
|
-
</button>
|
|
635
|
+
<button class="login-btn" (click)="onLogin()">Login</button>
|
|
600
636
|
</ng-container>
|
|
601
637
|
|
|
602
638
|
<!-- Logged in -->
|
|
603
639
|
<ng-container *ngIf="currentUser()">
|
|
604
640
|
<div class="user-header">
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
<
|
|
641
|
+
<!-- Notification Bell -->
|
|
642
|
+
<button class="notification-btn" [class.has-unread]="unreadCount > 0" (click)="onNotificationClick()" title="Notifications">
|
|
643
|
+
<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">
|
|
644
|
+
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
645
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
646
|
+
</svg>
|
|
647
|
+
<span class="badge" *ngIf="unreadCount > 0">{{ unreadCount > 99 ? '99+' : unreadCount }}</span>
|
|
608
648
|
</button>
|
|
609
649
|
|
|
650
|
+
<!-- User Avatar + Dropdown -->
|
|
610
651
|
<div class="user-menu-wrapper">
|
|
611
652
|
<button class="user-menu-btn" (click)="toggleDropdown()">
|
|
612
|
-
<
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
653
|
+
<div class="avatar-ring" [class.active]="dropdownOpen">
|
|
654
|
+
<img
|
|
655
|
+
*ngIf="currentUser().fullName || currentUser().userName"
|
|
656
|
+
[src]="getAvatarUrl(currentUser())"
|
|
657
|
+
[alt]="currentUser().fullName || currentUser().userName"
|
|
658
|
+
class="avatar"
|
|
659
|
+
/>
|
|
660
|
+
<span *ngIf="!(currentUser().fullName || currentUser().userName)" class="avatar-initial">
|
|
661
|
+
{{ getLastNameInitial(currentUser()) }}
|
|
662
|
+
</span>
|
|
663
|
+
</div>
|
|
621
664
|
</button>
|
|
622
665
|
|
|
623
666
|
<div class="mes-dropdown-menu" *ngIf="dropdownOpen">
|
|
667
|
+
<!-- User info header -->
|
|
624
668
|
<div class="mes-dropdown-header">
|
|
625
|
-
|
|
669
|
+
<div class="dropdown-avatar-wrap">
|
|
670
|
+
<img
|
|
671
|
+
*ngIf="currentUser().fullName || currentUser().userName"
|
|
672
|
+
[src]="getAvatarUrl(currentUser())"
|
|
673
|
+
[alt]="currentUser().fullName || currentUser().userName"
|
|
674
|
+
class="dropdown-avatar"
|
|
675
|
+
/>
|
|
676
|
+
<span *ngIf="!(currentUser().fullName || currentUser().userName)" class="dropdown-avatar-initial">
|
|
677
|
+
{{ getLastNameInitial(currentUser()) }}
|
|
678
|
+
</span>
|
|
679
|
+
</div>
|
|
680
|
+
<div class="dropdown-user-info">
|
|
681
|
+
<span class="dropdown-user-name">{{ currentUser().fullName || currentUser().userName }}</span>
|
|
682
|
+
<span class="dropdown-user-sub" *ngIf="currentUser().position || currentUser().department">
|
|
683
|
+
{{ currentUser().position || currentUser().department }}
|
|
684
|
+
</span>
|
|
685
|
+
</div>
|
|
626
686
|
</div>
|
|
687
|
+
|
|
688
|
+
<div class="mes-dropdown-divider"></div>
|
|
689
|
+
|
|
627
690
|
<button class="mes-dropdown-item profile-link" (click)="onViewProfile()">
|
|
691
|
+
<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">
|
|
692
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>
|
|
693
|
+
</svg>
|
|
628
694
|
View Profile
|
|
629
695
|
</button>
|
|
696
|
+
|
|
697
|
+
<div class="mes-dropdown-divider"></div>
|
|
698
|
+
|
|
630
699
|
<button class="mes-dropdown-item logout-item" (click)="onLogout()">
|
|
700
|
+
<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">
|
|
701
|
+
<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"/>
|
|
702
|
+
</svg>
|
|
631
703
|
Logout
|
|
632
704
|
</button>
|
|
633
705
|
</div>
|
|
@@ -635,7 +707,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
635
707
|
</div>
|
|
636
708
|
</ng-container>
|
|
637
709
|
</div>
|
|
638
|
-
`, styles: [":host{--primary-color: #1976d2;--primary-hover: #1565c0;--primary-light: rgba(25, 118, 210, .
|
|
710
|
+
`, styles: [":host{--primary-color: #1976d2;--primary-hover: #1565c0;--primary-light: rgba(25, 118, 210, .12);--primary-glow: rgba(25, 118, 210, .3);--error-color: #f44336;--error-light: rgba(244, 67, 54, .1);--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f8f9fa;--bg-hover: #f0f4ff;--border-color: #e0e0e0;--shadow: rgba(0, 0, 0, .12);--shadow-lg: rgba(0, 0, 0, .18)}:host(.theme-dark){--primary-color: #90caf9;--primary-hover: #64b5f6;--primary-light: rgba(144, 202, 249, .12);--primary-glow: rgba(144, 202, 249, .25);--error-color: #ef5350;--error-light: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--border-color: #383850;--shadow: rgba(0, 0, 0, .35);--shadow-lg: rgba(0, 0, 0, .5)}.user-profile-container{display:flex;align-items:center;gap:4px}.login-btn{padding:7px 18px;background-color:var(--primary-color);color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:500;font-size:13px;letter-spacing:.2px;transition:background-color .2s,transform .15s}.login-btn:hover{background-color:var(--primary-hover);transform:translateY(-1px)}.user-header{display:flex;align-items:center;gap:4px}.notification-btn{position:relative;background:none;border:none;cursor:pointer;padding:8px;border-radius:10px;color:var(--text-secondary);display:flex;align-items:center;justify-content:center;transition:color .2s,background-color .2s}.notification-btn:hover{background-color:var(--primary-light);color:var(--primary-color)}.notification-btn.has-unread{color:var(--primary-color)}.bell-icon{display:block;transition:transform .35s cubic-bezier(.34,1.56,.64,1)}.notification-btn:hover .bell-icon{transform:rotate(-20deg) scale(1.15)}.badge{position:absolute;top:2px;right:2px;background-color:var(--error-color);color:#fff;border-radius:10px;min-width:17px;height:17px;padding:0 4px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;line-height:1;box-shadow:0 0 0 2px var(--bg-primary);animation:badge-pop .25s cubic-bezier(.34,1.56,.64,1)}@keyframes badge-pop{0%{transform:scale(0)}to{transform:scale(1)}}.user-menu-wrapper{position:relative}.user-menu-btn{background:none;border:none;cursor:pointer;padding:2px;border-radius:50%;display:flex;align-items:center;justify-content:center;transition:transform .2s}.user-menu-btn:hover{transform:scale(1.06)}.avatar-ring{border-radius:50%;padding:2px;border:2px solid transparent;transition:border-color .25s,box-shadow .25s}.avatar-ring.active,.user-menu-btn:hover .avatar-ring{border-color:var(--primary-color);box-shadow:0 0 0 3px var(--primary-glow)}.avatar{width:36px;height:36px;border-radius:50%;object-fit:cover;display:block}.avatar-initial{width:36px;height:36px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color),var(--primary-hover));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:15px}.mes-dropdown-menu{position:absolute;top:calc(100% + 10px);right:0;background:var(--bg-primary);border:1px solid var(--border-color);border-radius:14px;box-shadow:0 8px 32px var(--shadow-lg),0 2px 8px var(--shadow);min-width:220px;z-index:1000;overflow:hidden;animation:dropdown-in .16s cubic-bezier(.16,1,.3,1)}@keyframes dropdown-in{0%{opacity:0;transform:translateY(-8px) scale(.96)}to{opacity:1;transform:translateY(0) scale(1)}}.mes-dropdown-header{display:flex;align-items:center;gap:12px;padding:16px;background:var(--bg-secondary)}.dropdown-avatar-wrap{flex-shrink:0}.dropdown-avatar{width:46px;height:46px;border-radius:50%;object-fit:cover;border:2px solid var(--primary-color);display:block}.dropdown-avatar-initial{width:46px;height:46px;border-radius:50%;background:linear-gradient(135deg,var(--primary-color),var(--primary-hover));color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:18px;border:2px solid var(--primary-color)}.dropdown-user-info{display:flex;flex-direction:column;gap:3px;min-width:0}.dropdown-user-name{font-weight:600;font-size:14px;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.dropdown-user-sub{font-size:11px;color:var(--primary-color);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mes-dropdown-divider{height:1px;background:var(--border-color)}.mes-dropdown-item{display:flex;align-items:center;gap:10px;width:100%;padding:11px 16px;border:none;background:none;text-align:left;cursor:pointer;font-size:13.5px;font-weight:500;transition:background-color .15s}.item-icon{flex-shrink:0;opacity:.8}.profile-link{color:var(--primary-color)}.profile-link:hover{background-color:var(--primary-light)}.logout-item{color:var(--error-color)}.logout-item:hover{background-color:var(--error-light)}@media(max-width:768px){.avatar,.avatar-initial{width:32px;height:32px;font-size:13px}}\n"] }]
|
|
639
711
|
}], ctorParameters: () => [{ type: MesAuthService }, { type: i2.Router }, { type: ThemeService }, { type: i0.ChangeDetectorRef }], propDecorators: { notificationClick: [{
|
|
640
712
|
type: Output
|
|
641
713
|
}], themeClass: [{
|
|
@@ -717,43 +789,83 @@ class ToastContainerComponent {
|
|
|
717
789
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ToastContainerComponent, deps: [{ token: ToastService }, { token: ThemeService }], target: i0.ɵɵFactoryTarget.Component });
|
|
718
790
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.18", type: ToastContainerComponent, isStandalone: true, selector: "ma-toast-container", host: { properties: { "class": "this.themeClass" } }, ngImport: i0, template: `
|
|
719
791
|
<div class="toast-container">
|
|
720
|
-
<div
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
792
|
+
<div *ngFor="let toast of toasts" class="toast toast-{{ toast.type }}">
|
|
793
|
+
|
|
794
|
+
<!-- Type icon -->
|
|
795
|
+
<div class="toast-icon">
|
|
796
|
+
<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">
|
|
797
|
+
<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"/>
|
|
798
|
+
</svg>
|
|
799
|
+
<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">
|
|
800
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>
|
|
801
|
+
</svg>
|
|
802
|
+
<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">
|
|
803
|
+
<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"/>
|
|
804
|
+
</svg>
|
|
805
|
+
<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">
|
|
806
|
+
<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"/>
|
|
807
|
+
</svg>
|
|
808
|
+
</div>
|
|
809
|
+
|
|
810
|
+
<!-- Content -->
|
|
726
811
|
<div class="toast-content">
|
|
727
812
|
<div *ngIf="toast.title" class="toast-title">{{ toast.title }}</div>
|
|
728
813
|
<div class="toast-message" [innerHTML]="toast.message"></div>
|
|
729
814
|
</div>
|
|
815
|
+
|
|
816
|
+
<!-- Close -->
|
|
730
817
|
<button class="toast-close" (click)="close(toast.id)" aria-label="Close">
|
|
731
|
-
|
|
818
|
+
<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">
|
|
819
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
820
|
+
</svg>
|
|
732
821
|
</button>
|
|
822
|
+
|
|
823
|
+
<!-- Auto-dismiss progress bar -->
|
|
824
|
+
<div class="toast-progress" [style.animation-duration]="(toast.duration || 5000) + 'ms'"></div>
|
|
733
825
|
</div>
|
|
734
826
|
</div>
|
|
735
|
-
`, isInline: true, styles: [":host{--info-color: #2196f3;--success-color: #
|
|
827
|
+
`, isInline: true, styles: [":host{--info-color: #2196f3;--info-bg: rgba(33, 150, 243, .1);--success-color: #43a047;--success-bg: rgba(67, 160, 71, .1);--warning-color: #f57c00;--warning-bg: rgba(245, 124, 0, .1);--error-color: #e53935;--error-bg: rgba(229, 57, 53, .1);--text-primary: #212121;--text-secondary: #757575;--bg-primary: #ffffff;--border-color: rgba(0, 0, 0, .08);--shadow: rgba(0, 0, 0, .1);--shadow-lg: rgba(0, 0, 0, .18)}:host(.theme-dark){--info-color: #64b5f6;--info-bg: rgba(100, 181, 246, .12);--success-color: #66bb6a;--success-bg: rgba(102, 187, 106, .12);--warning-color: #ffb74d;--warning-bg: rgba(255, 183, 77, .12);--error-color: #ef5350;--error-bg: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #9e9e9e;--bg-primary: #1e1e2e;--border-color: rgba(255, 255, 255, .08);--shadow: rgba(0, 0, 0, .35);--shadow-lg: rgba(0, 0, 0, .5)}.toast-container{position:fixed;top:20px;right:20px;z-index:9999;pointer-events:none;display:flex;flex-direction:column;gap:10px}.toast{position:relative;display:flex;align-items:flex-start;gap:11px;padding:13px 13px 16px 16px;border-radius:12px;background:var(--bg-primary);border:1px solid var(--border-color);box-shadow:0 8px 28px var(--shadow-lg),0 2px 8px var(--shadow);pointer-events:auto;min-width:300px;max-width:420px;overflow:hidden;animation:toast-in .35s cubic-bezier(.16,1,.3,1)}@keyframes toast-in{0%{opacity:0;transform:translate(36px) scale(.96)}to{opacity:1;transform:translate(0) scale(1)}}.toast:before{content:\"\";position:absolute;left:0;top:0;bottom:0;width:4px;border-radius:12px 0 0 12px}.toast-info:before{background:var(--info-color)}.toast-success:before{background:var(--success-color)}.toast-warning:before{background:var(--warning-color)}.toast-error:before{background:var(--error-color)}.toast-icon{flex-shrink:0;width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;margin-left:2px}.toast-info .toast-icon{color:var(--info-color);background:var(--info-bg)}.toast-success .toast-icon{color:var(--success-color);background:var(--success-bg)}.toast-warning .toast-icon{color:var(--warning-color);background:var(--warning-bg)}.toast-error .toast-icon{color:var(--error-color);background:var(--error-bg)}.toast-content{flex:1;min-width:0;padding-top:1px}.toast-title{font-weight:700;font-size:13.5px;margin-bottom:3px;line-height:1.3}.toast-info .toast-title{color:var(--info-color)}.toast-success .toast-title{color:var(--success-color)}.toast-warning .toast-title{color:var(--warning-color)}.toast-error .toast-title{color:var(--error-color)}.toast-message{font-size:12.5px;line-height:1.45;color:var(--text-secondary)}.toast-close{background:none;border:none;cursor:pointer;color:var(--text-secondary);width:26px;height:26px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;transition:color .15s,background-color .15s}.toast-close:hover{color:var(--text-primary);background:var(--border-color)}.toast-progress{position:absolute;bottom:0;left:4px;right:0;height:3px;border-radius:0 0 12px;animation:toast-progress linear forwards;opacity:.7}.toast-info .toast-progress{background:var(--info-color)}.toast-success .toast-progress{background:var(--success-color)}.toast-warning .toast-progress{background:var(--warning-color)}.toast-error .toast-progress{background:var(--error-color)}@keyframes toast-progress{0%{width:calc(100% - 4px)}to{width:0}}@media(max-width:600px){.toast-container{top:10px;right:10px;left:10px}.toast{min-width:auto;max-width:100%}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
736
828
|
}
|
|
737
829
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: ToastContainerComponent, decorators: [{
|
|
738
830
|
type: Component,
|
|
739
831
|
args: [{ selector: 'ma-toast-container', standalone: true, imports: [CommonModule], template: `
|
|
740
832
|
<div class="toast-container">
|
|
741
|
-
<div
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
833
|
+
<div *ngFor="let toast of toasts" class="toast toast-{{ toast.type }}">
|
|
834
|
+
|
|
835
|
+
<!-- Type icon -->
|
|
836
|
+
<div class="toast-icon">
|
|
837
|
+
<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">
|
|
838
|
+
<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"/>
|
|
839
|
+
</svg>
|
|
840
|
+
<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">
|
|
841
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>
|
|
842
|
+
</svg>
|
|
843
|
+
<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">
|
|
844
|
+
<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"/>
|
|
845
|
+
</svg>
|
|
846
|
+
<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">
|
|
847
|
+
<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"/>
|
|
848
|
+
</svg>
|
|
849
|
+
</div>
|
|
850
|
+
|
|
851
|
+
<!-- Content -->
|
|
747
852
|
<div class="toast-content">
|
|
748
853
|
<div *ngIf="toast.title" class="toast-title">{{ toast.title }}</div>
|
|
749
854
|
<div class="toast-message" [innerHTML]="toast.message"></div>
|
|
750
855
|
</div>
|
|
856
|
+
|
|
857
|
+
<!-- Close -->
|
|
751
858
|
<button class="toast-close" (click)="close(toast.id)" aria-label="Close">
|
|
752
|
-
|
|
859
|
+
<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">
|
|
860
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
861
|
+
</svg>
|
|
753
862
|
</button>
|
|
863
|
+
|
|
864
|
+
<!-- Auto-dismiss progress bar -->
|
|
865
|
+
<div class="toast-progress" [style.animation-duration]="(toast.duration || 5000) + 'ms'"></div>
|
|
754
866
|
</div>
|
|
755
867
|
</div>
|
|
756
|
-
`, styles: [":host{--info-color: #2196f3;--success-color: #
|
|
868
|
+
`, styles: [":host{--info-color: #2196f3;--info-bg: rgba(33, 150, 243, .1);--success-color: #43a047;--success-bg: rgba(67, 160, 71, .1);--warning-color: #f57c00;--warning-bg: rgba(245, 124, 0, .1);--error-color: #e53935;--error-bg: rgba(229, 57, 53, .1);--text-primary: #212121;--text-secondary: #757575;--bg-primary: #ffffff;--border-color: rgba(0, 0, 0, .08);--shadow: rgba(0, 0, 0, .1);--shadow-lg: rgba(0, 0, 0, .18)}:host(.theme-dark){--info-color: #64b5f6;--info-bg: rgba(100, 181, 246, .12);--success-color: #66bb6a;--success-bg: rgba(102, 187, 106, .12);--warning-color: #ffb74d;--warning-bg: rgba(255, 183, 77, .12);--error-color: #ef5350;--error-bg: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #9e9e9e;--bg-primary: #1e1e2e;--border-color: rgba(255, 255, 255, .08);--shadow: rgba(0, 0, 0, .35);--shadow-lg: rgba(0, 0, 0, .5)}.toast-container{position:fixed;top:20px;right:20px;z-index:9999;pointer-events:none;display:flex;flex-direction:column;gap:10px}.toast{position:relative;display:flex;align-items:flex-start;gap:11px;padding:13px 13px 16px 16px;border-radius:12px;background:var(--bg-primary);border:1px solid var(--border-color);box-shadow:0 8px 28px var(--shadow-lg),0 2px 8px var(--shadow);pointer-events:auto;min-width:300px;max-width:420px;overflow:hidden;animation:toast-in .35s cubic-bezier(.16,1,.3,1)}@keyframes toast-in{0%{opacity:0;transform:translate(36px) scale(.96)}to{opacity:1;transform:translate(0) scale(1)}}.toast:before{content:\"\";position:absolute;left:0;top:0;bottom:0;width:4px;border-radius:12px 0 0 12px}.toast-info:before{background:var(--info-color)}.toast-success:before{background:var(--success-color)}.toast-warning:before{background:var(--warning-color)}.toast-error:before{background:var(--error-color)}.toast-icon{flex-shrink:0;width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;margin-left:2px}.toast-info .toast-icon{color:var(--info-color);background:var(--info-bg)}.toast-success .toast-icon{color:var(--success-color);background:var(--success-bg)}.toast-warning .toast-icon{color:var(--warning-color);background:var(--warning-bg)}.toast-error .toast-icon{color:var(--error-color);background:var(--error-bg)}.toast-content{flex:1;min-width:0;padding-top:1px}.toast-title{font-weight:700;font-size:13.5px;margin-bottom:3px;line-height:1.3}.toast-info .toast-title{color:var(--info-color)}.toast-success .toast-title{color:var(--success-color)}.toast-warning .toast-title{color:var(--warning-color)}.toast-error .toast-title{color:var(--error-color)}.toast-message{font-size:12.5px;line-height:1.45;color:var(--text-secondary)}.toast-close{background:none;border:none;cursor:pointer;color:var(--text-secondary);width:26px;height:26px;border-radius:6px;display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:0;transition:color .15s,background-color .15s}.toast-close:hover{color:var(--text-primary);background:var(--border-color)}.toast-progress{position:absolute;bottom:0;left:4px;right:0;height:3px;border-radius:0 0 12px;animation:toast-progress linear forwards;opacity:.7}.toast-info .toast-progress{background:var(--info-color)}.toast-success .toast-progress{background:var(--success-color)}.toast-warning .toast-progress{background:var(--warning-color)}.toast-error .toast-progress{background:var(--error-color)}@keyframes toast-progress{0%{width:calc(100% - 4px)}to{width:0}}@media(max-width:600px){.toast-container{top:10px;right:10px;left:10px}.toast{min-width:auto;max-width:100%}}\n"] }]
|
|
757
869
|
}], ctorParameters: () => [{ type: ToastService }, { type: ThemeService }], propDecorators: { themeClass: [{
|
|
758
870
|
type: HostBinding,
|
|
759
871
|
args: ['class']
|
|
@@ -794,6 +906,23 @@ class NotificationPanelComponent {
|
|
|
794
906
|
getNotificationMessage(notification) {
|
|
795
907
|
return notification.message || '';
|
|
796
908
|
}
|
|
909
|
+
// Normalize type to string — API may return integer (0/1/2/3) or string ('Info'/'Warning'/'Error'/'Success')
|
|
910
|
+
typeOf(notification) {
|
|
911
|
+
const t = notification.type;
|
|
912
|
+
if (t === 0 || t === 'Info')
|
|
913
|
+
return 'Info';
|
|
914
|
+
if (t === 1 || t === 'Warning')
|
|
915
|
+
return 'Warning';
|
|
916
|
+
if (t === 2 || t === 'Error')
|
|
917
|
+
return 'Error';
|
|
918
|
+
if (t === 3 || t === 'Success')
|
|
919
|
+
return 'Success';
|
|
920
|
+
return 'Info';
|
|
921
|
+
}
|
|
922
|
+
toastType(type) {
|
|
923
|
+
const t = this.typeOf({ type });
|
|
924
|
+
return t.toLowerCase();
|
|
925
|
+
}
|
|
797
926
|
sanitizer = inject(DomSanitizer);
|
|
798
927
|
constructor(authService, toastService, themeService) {
|
|
799
928
|
this.authService = authService;
|
|
@@ -814,7 +943,7 @@ class NotificationPanelComponent {
|
|
|
814
943
|
.pipe(takeUntil(this.destroy$))
|
|
815
944
|
.subscribe((notification) => {
|
|
816
945
|
// Show toast for new notification
|
|
817
|
-
this.toastService.show(notification.messageHtml || notification.message || '', notification.title,
|
|
946
|
+
this.toastService.show(notification.messageHtml || notification.message || '', notification.title, this.toastType(notification.type), 5000);
|
|
818
947
|
// Reload notifications list
|
|
819
948
|
this.loadNotifications();
|
|
820
949
|
});
|
|
@@ -997,25 +1126,29 @@ class NotificationPanelComponent {
|
|
|
997
1126
|
<div class="notification-panel" [class.open]="isOpen">
|
|
998
1127
|
<!-- Header -->
|
|
999
1128
|
<div class="panel-header">
|
|
1000
|
-
<
|
|
1001
|
-
|
|
1129
|
+
<div class="panel-header-left">
|
|
1130
|
+
<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">
|
|
1131
|
+
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
1132
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
1133
|
+
</svg>
|
|
1134
|
+
<h3>Notifications</h3>
|
|
1135
|
+
</div>
|
|
1136
|
+
<button class="close-btn" (click)="close()" title="Close">
|
|
1137
|
+
<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">
|
|
1138
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
1139
|
+
</svg>
|
|
1140
|
+
</button>
|
|
1002
1141
|
</div>
|
|
1003
1142
|
|
|
1004
1143
|
<!-- Tabs -->
|
|
1005
1144
|
<div class="tabs">
|
|
1006
|
-
<button
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
(click)="switchTab('unread')"
|
|
1010
|
-
>
|
|
1011
|
-
Unread ({{ unreadNotifications.length }})
|
|
1145
|
+
<button class="tab-btn" [class.active]="activeTab === 'unread'" (click)="switchTab('unread')">
|
|
1146
|
+
Unread
|
|
1147
|
+
<span class="tab-count" *ngIf="unreadNotifications.length > 0">{{ unreadNotifications.length }}</span>
|
|
1012
1148
|
</button>
|
|
1013
|
-
<button
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
(click)="switchTab('read')"
|
|
1017
|
-
>
|
|
1018
|
-
Read ({{ readNotifications.length }})
|
|
1149
|
+
<button class="tab-btn" [class.active]="activeTab === 'read'" (click)="switchTab('read')">
|
|
1150
|
+
Read
|
|
1151
|
+
<span class="tab-count read-count" *ngIf="readNotifications.length > 0">{{ readNotifications.length }}</span>
|
|
1019
1152
|
</button>
|
|
1020
1153
|
</div>
|
|
1021
1154
|
|
|
@@ -1028,6 +1161,29 @@ class NotificationPanelComponent {
|
|
|
1028
1161
|
[class.unread]="!notification.isRead"
|
|
1029
1162
|
(click)="openDetails(notification)"
|
|
1030
1163
|
>
|
|
1164
|
+
<div class="notif-accent"
|
|
1165
|
+
[class.type-info]="typeOf(notification) === 'Info'"
|
|
1166
|
+
[class.type-success]="typeOf(notification) === 'Success'"
|
|
1167
|
+
[class.type-warning]="typeOf(notification) === 'Warning'"
|
|
1168
|
+
[class.type-error]="typeOf(notification) === 'Error'"></div>
|
|
1169
|
+
<div class="notif-type-icon"
|
|
1170
|
+
[class.type-info]="typeOf(notification) === 'Info'"
|
|
1171
|
+
[class.type-success]="typeOf(notification) === 'Success'"
|
|
1172
|
+
[class.type-warning]="typeOf(notification) === 'Warning'"
|
|
1173
|
+
[class.type-error]="typeOf(notification) === 'Error'">
|
|
1174
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1175
|
+
<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"/>
|
|
1176
|
+
</svg>
|
|
1177
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1178
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1179
|
+
</svg>
|
|
1180
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1181
|
+
<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"/>
|
|
1182
|
+
</svg>
|
|
1183
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1184
|
+
<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"/>
|
|
1185
|
+
</svg>
|
|
1186
|
+
</div>
|
|
1031
1187
|
<div class="notification-content">
|
|
1032
1188
|
<div class="notification-title">{{ notification.title }}</div>
|
|
1033
1189
|
<div class="notification-message">{{ getNotificationMessage(notification) }}</div>
|
|
@@ -1036,28 +1192,26 @@ class NotificationPanelComponent {
|
|
|
1036
1192
|
<span class="time">{{ dateLabels.get(notification.id) }}</span>
|
|
1037
1193
|
</div>
|
|
1038
1194
|
</div>
|
|
1039
|
-
<button
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
*ngIf="!notification.isRead"
|
|
1044
|
-
>
|
|
1045
|
-
✓
|
|
1195
|
+
<button class="icon-btn read-btn" (click)="markAsRead(notification.id, $event)" title="Mark as read" *ngIf="!notification.isRead">
|
|
1196
|
+
<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">
|
|
1197
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1198
|
+
</svg>
|
|
1046
1199
|
</button>
|
|
1047
|
-
<button
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
*ngIf="notification.isRead"
|
|
1052
|
-
>
|
|
1053
|
-
🗑
|
|
1200
|
+
<button class="icon-btn delete-btn" (click)="delete(notification.id, $event)" title="Delete" *ngIf="notification.isRead">
|
|
1201
|
+
<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">
|
|
1202
|
+
<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"/>
|
|
1203
|
+
</svg>
|
|
1054
1204
|
</button>
|
|
1055
1205
|
</div>
|
|
1056
1206
|
</ng-container>
|
|
1057
1207
|
|
|
1058
1208
|
<ng-container *ngIf="currentNotifications.length === 0">
|
|
1059
1209
|
<div class="empty-state">
|
|
1060
|
-
|
|
1210
|
+
<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">
|
|
1211
|
+
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
1212
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
1213
|
+
</svg>
|
|
1214
|
+
<p>No {{ activeTab }} notifications</p>
|
|
1061
1215
|
</div>
|
|
1062
1216
|
</ng-container>
|
|
1063
1217
|
</div>
|
|
@@ -1066,13 +1220,16 @@ class NotificationPanelComponent {
|
|
|
1066
1220
|
<div class="panel-footer" *ngIf="currentNotifications.length > 0">
|
|
1067
1221
|
<div class="footer-actions" *ngIf="activeTab === 'unread'">
|
|
1068
1222
|
<button class="action-btn" (click)="markAllAsRead()" *ngIf="unreadNotifications.length > 0">
|
|
1069
|
-
|
|
1223
|
+
<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>
|
|
1224
|
+
Mark all read
|
|
1070
1225
|
</button>
|
|
1071
1226
|
<button class="action-btn delete-all-btn" (click)="deleteAllUnread()" *ngIf="unreadNotifications.length > 0">
|
|
1227
|
+
<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>
|
|
1072
1228
|
Delete all
|
|
1073
1229
|
</button>
|
|
1074
1230
|
</div>
|
|
1075
1231
|
<button class="action-btn delete-all-btn" (click)="deleteAllRead()" *ngIf="activeTab === 'read' && readNotifications.length > 0">
|
|
1232
|
+
<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>
|
|
1076
1233
|
Delete all
|
|
1077
1234
|
</button>
|
|
1078
1235
|
</div>
|
|
@@ -1081,9 +1238,33 @@ class NotificationPanelComponent {
|
|
|
1081
1238
|
<!-- Details Modal -->
|
|
1082
1239
|
<div class="modal-overlay" *ngIf="selectedNotification" (click)="closeDetails()">
|
|
1083
1240
|
<div class="modal-container" (click)="$event.stopPropagation()">
|
|
1084
|
-
<div class="modal-header"
|
|
1085
|
-
|
|
1086
|
-
|
|
1241
|
+
<div class="modal-header"
|
|
1242
|
+
[class.modal-type-info]="typeOf(selectedNotification) === 'Info'"
|
|
1243
|
+
[class.modal-type-success]="typeOf(selectedNotification) === 'Success'"
|
|
1244
|
+
[class.modal-type-warning]="typeOf(selectedNotification) === 'Warning'"
|
|
1245
|
+
[class.modal-type-error]="typeOf(selectedNotification) === 'Error'">
|
|
1246
|
+
<div class="modal-header-left">
|
|
1247
|
+
<div class="modal-type-icon">
|
|
1248
|
+
<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">
|
|
1249
|
+
<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"/>
|
|
1250
|
+
</svg>
|
|
1251
|
+
<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">
|
|
1252
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>
|
|
1253
|
+
</svg>
|
|
1254
|
+
<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">
|
|
1255
|
+
<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"/>
|
|
1256
|
+
</svg>
|
|
1257
|
+
<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">
|
|
1258
|
+
<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"/>
|
|
1259
|
+
</svg>
|
|
1260
|
+
</div>
|
|
1261
|
+
<h3>{{ selectedNotification.title }}</h3>
|
|
1262
|
+
</div>
|
|
1263
|
+
<button class="close-btn" (click)="closeDetails()" title="Close">
|
|
1264
|
+
<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">
|
|
1265
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
1266
|
+
</svg>
|
|
1267
|
+
</button>
|
|
1087
1268
|
</div>
|
|
1088
1269
|
<div class="modal-meta">
|
|
1089
1270
|
<span class="app-name">{{ selectedNotification.sourceAppName }}</span>
|
|
@@ -1095,7 +1276,7 @@ class NotificationPanelComponent {
|
|
|
1095
1276
|
</div>
|
|
1096
1277
|
</div>
|
|
1097
1278
|
</div>
|
|
1098
|
-
`, isInline: true, styles: [":host{display:block;position:relative;--primary-color: #1976d2;--primary-hover: #1565c0;--success-color: #
|
|
1279
|
+
`, isInline: true, styles: [":host{display:block;position:relative;--primary-color: #1976d2;--primary-hover: #1565c0;--primary-light: rgba(25, 118, 210, .1);--success-color: #43a047;--error-color: #f44336;--error-hover: #d32f2f;--unread-accent: #1976d2;--info-color: #2196f3;--info-bg: rgba(33, 150, 243, .1);--success-bg: rgba(67, 160, 71, .1);--warning-color: #f57c00;--warning-bg: rgba(245, 124, 0, .1);--error-bg: rgba(244, 67, 54, .1);--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f8f9fa;--bg-hover: #f0f4ff;--bg-unread: rgba(25, 118, 210, .06);--border-color: #e0e0e0;--border-light: #eeeeee;--shadow: rgba(0, 0, 0, .15)}:host(.theme-dark){display:block;position:relative;--primary-color: #90caf9;--primary-hover: #64b5f6;--primary-light: rgba(144, 202, 249, .1);--success-color: #66bb6a;--error-color: #ef5350;--error-hover: #c62828;--unread-accent: #90caf9;--info-color: #64b5f6;--info-bg: rgba(100, 181, 246, .12);--success-bg: rgba(102, 187, 106, .12);--warning-color: #ffb74d;--warning-bg: rgba(255, 183, 77, .12);--error-bg: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--bg-unread: rgba(144, 202, 249, .08);--border-color: #383850;--border-light: #2e2e42;--shadow: rgba(0, 0, 0, .4)}.notification-panel{position:fixed;top:0;right:-360px;width:360px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 24px var(--shadow);display:flex;flex-direction:column;z-index:1030;transition:right .3s cubic-bezier(.16,1,.3,1)}.notification-panel.open{right:0}.panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px 18px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.panel-header-left{display:flex;align-items:center;gap:9px;color:var(--primary-color)}.panel-header h3{margin:0;font-size:16px;font-weight:700;color:var(--text-primary);letter-spacing:.1px}.close-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:color .2s,background-color .2s}.close-btn:hover{color:var(--text-primary);background-color:var(--bg-hover)}.tabs{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.tab-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:7px 12px;background:none;border:1px solid var(--border-color);border-radius:20px;color:var(--text-secondary);cursor:pointer;font-size:13px;font-weight:500;transition:all .18s}.tab-btn:hover{background:var(--bg-hover);color:var(--primary-color);border-color:var(--primary-color)}.tab-btn.active{background:var(--primary-color);border-color:var(--primary-color);color:#fff}.tab-count{background:#ffffff40;border-radius:10px;min-width:18px;height:18px;padding:0 5px;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center}.tab-btn:not(.active) .tab-count{background:var(--error-color);color:#fff}.read-count{background:#ffffff40}.tab-btn:not(.active) .read-count{background:var(--text-muted)}.notifications-list{flex:1;overflow-y:auto}.notification-item{display:flex;align-items:flex-start;gap:0;border-bottom:1px solid var(--border-light);cursor:pointer;background:var(--bg-primary);transition:background-color .15s;position:relative}.notification-item:hover{background:var(--bg-hover)}.notification-item.unread{background:var(--bg-unread)}.notif-accent{width:3px;align-self:stretch;flex-shrink:0;background:transparent;border-radius:0 2px 2px 0;opacity:.3}.notification-item.unread .notif-accent{opacity:1}.notif-accent.type-info{background:var(--info-color)}.notif-accent.type-success{background:var(--success-color)}.notif-accent.type-warning{background:var(--warning-color)}.notif-accent.type-error{background:var(--error-color)}.notif-type-icon{flex-shrink:0;width:26px;height:26px;border-radius:7px;display:flex;align-items:center;justify-content:center;align-self:center;margin-left:10px}.notif-type-icon.type-info{color:var(--info-color);background:var(--info-bg)}.notif-type-icon.type-success{color:var(--success-color);background:var(--success-bg)}.notif-type-icon.type-warning{color:var(--warning-color);background:var(--warning-bg)}.notif-type-icon.type-error{color:var(--error-color);background:var(--error-bg)}.notification-content{flex:1;min-width:0;padding:12px 8px 12px 12px}.notification-title{font-weight:600;color:var(--text-primary);font-size:13.5px;margin-bottom:3px;line-height:1.35}.notification-message{color:var(--text-secondary);font-size:12px;line-height:1.45;margin-bottom:7px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-meta{display:flex;justify-content:space-between;font-size:11px;color:var(--text-muted)}.app-name{font-weight:600;color:var(--primary-color)}.icon-btn{background:none;border:none;cursor:pointer;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center;margin-right:8px;transition:color .15s,background-color .15s;color:var(--text-muted)}.read-btn:hover{color:var(--success-color);background:#43a0471a}.delete-btn:hover{color:var(--error-color);background:#f443361a}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;height:100%;padding:40px 20px;color:var(--text-muted)}.empty-icon{opacity:.35}.empty-state p{margin:0;font-size:13px}.panel-footer{padding:10px 14px;border-top:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.footer-actions{display:flex;gap:8px}.footer-actions .action-btn{flex:1}.action-btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:8px 12px;background:var(--primary-color);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:600;transition:background-color .18s,transform .12s}.action-btn:hover{background:var(--primary-hover);transform:translateY(-1px)}.delete-all-btn{background:var(--error-color)}.delete-all-btn:hover{background:var(--error-hover)}.modal-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1060;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.modal-container{background:var(--bg-primary);border-radius:14px;width:90%;max-width:580px;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 16px 48px #00000040;animation:modal-in .2s cubic-bezier(.16,1,.3,1)}@keyframes modal-in{0%{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:scale(1) translateY(0)}}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);border-radius:14px 14px 0 0;border-top:3px solid transparent}.modal-header.modal-type-info{border-top-color:var(--info-color)}.modal-header.modal-type-success{border-top-color:var(--success-color)}.modal-header.modal-type-warning{border-top-color:var(--warning-color)}.modal-header.modal-type-error{border-top-color:var(--error-color)}.modal-header-left{display:flex;align-items:center;gap:10px;min-width:0}.modal-type-icon{flex-shrink:0;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center}.modal-type-info .modal-type-icon{color:var(--info-color);background:var(--info-bg)}.modal-type-success .modal-type-icon{color:var(--success-color);background:var(--success-bg)}.modal-type-warning .modal-type-icon{color:var(--warning-color);background:var(--warning-bg)}.modal-type-error .modal-type-icon{color:var(--error-color);background:var(--error-bg)}.modal-header h3{margin:0;font-size:15px;font-weight:700;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.modal-meta{display:flex;justify-content:space-between;padding:8px 20px;font-size:11.5px;color:var(--text-muted);border-bottom:1px solid var(--border-light)}.modal-body{padding:20px;overflow-y:auto;flex:1;color:var(--text-primary);font-size:14px;line-height:1.65}.modal-footer{padding:12px 20px;border-top:1px solid var(--border-color);background:var(--bg-secondary);border-radius:0 0 14px 14px;display:flex;justify-content:flex-end}.modal-footer .action-btn{width:auto;padding:8px 24px}@media(max-width:600px){.notification-panel{width:100%;right:-100%}.modal-container{width:95%;max-height:90vh}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
|
|
1099
1280
|
}
|
|
1100
1281
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NotificationPanelComponent, decorators: [{
|
|
1101
1282
|
type: Component,
|
|
@@ -1103,25 +1284,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1103
1284
|
<div class="notification-panel" [class.open]="isOpen">
|
|
1104
1285
|
<!-- Header -->
|
|
1105
1286
|
<div class="panel-header">
|
|
1106
|
-
<
|
|
1107
|
-
|
|
1287
|
+
<div class="panel-header-left">
|
|
1288
|
+
<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">
|
|
1289
|
+
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
1290
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
1291
|
+
</svg>
|
|
1292
|
+
<h3>Notifications</h3>
|
|
1293
|
+
</div>
|
|
1294
|
+
<button class="close-btn" (click)="close()" title="Close">
|
|
1295
|
+
<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">
|
|
1296
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
1297
|
+
</svg>
|
|
1298
|
+
</button>
|
|
1108
1299
|
</div>
|
|
1109
1300
|
|
|
1110
1301
|
<!-- Tabs -->
|
|
1111
1302
|
<div class="tabs">
|
|
1112
|
-
<button
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
(click)="switchTab('unread')"
|
|
1116
|
-
>
|
|
1117
|
-
Unread ({{ unreadNotifications.length }})
|
|
1303
|
+
<button class="tab-btn" [class.active]="activeTab === 'unread'" (click)="switchTab('unread')">
|
|
1304
|
+
Unread
|
|
1305
|
+
<span class="tab-count" *ngIf="unreadNotifications.length > 0">{{ unreadNotifications.length }}</span>
|
|
1118
1306
|
</button>
|
|
1119
|
-
<button
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
(click)="switchTab('read')"
|
|
1123
|
-
>
|
|
1124
|
-
Read ({{ readNotifications.length }})
|
|
1307
|
+
<button class="tab-btn" [class.active]="activeTab === 'read'" (click)="switchTab('read')">
|
|
1308
|
+
Read
|
|
1309
|
+
<span class="tab-count read-count" *ngIf="readNotifications.length > 0">{{ readNotifications.length }}</span>
|
|
1125
1310
|
</button>
|
|
1126
1311
|
</div>
|
|
1127
1312
|
|
|
@@ -1134,6 +1319,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1134
1319
|
[class.unread]="!notification.isRead"
|
|
1135
1320
|
(click)="openDetails(notification)"
|
|
1136
1321
|
>
|
|
1322
|
+
<div class="notif-accent"
|
|
1323
|
+
[class.type-info]="typeOf(notification) === 'Info'"
|
|
1324
|
+
[class.type-success]="typeOf(notification) === 'Success'"
|
|
1325
|
+
[class.type-warning]="typeOf(notification) === 'Warning'"
|
|
1326
|
+
[class.type-error]="typeOf(notification) === 'Error'"></div>
|
|
1327
|
+
<div class="notif-type-icon"
|
|
1328
|
+
[class.type-info]="typeOf(notification) === 'Info'"
|
|
1329
|
+
[class.type-success]="typeOf(notification) === 'Success'"
|
|
1330
|
+
[class.type-warning]="typeOf(notification) === 'Warning'"
|
|
1331
|
+
[class.type-error]="typeOf(notification) === 'Error'">
|
|
1332
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1333
|
+
<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"/>
|
|
1334
|
+
</svg>
|
|
1335
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1336
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1337
|
+
</svg>
|
|
1338
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1339
|
+
<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"/>
|
|
1340
|
+
</svg>
|
|
1341
|
+
<svg *ngIf="typeOf(notification) === '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">
|
|
1342
|
+
<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"/>
|
|
1343
|
+
</svg>
|
|
1344
|
+
</div>
|
|
1137
1345
|
<div class="notification-content">
|
|
1138
1346
|
<div class="notification-title">{{ notification.title }}</div>
|
|
1139
1347
|
<div class="notification-message">{{ getNotificationMessage(notification) }}</div>
|
|
@@ -1142,28 +1350,26 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1142
1350
|
<span class="time">{{ dateLabels.get(notification.id) }}</span>
|
|
1143
1351
|
</div>
|
|
1144
1352
|
</div>
|
|
1145
|
-
<button
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
*ngIf="!notification.isRead"
|
|
1150
|
-
>
|
|
1151
|
-
✓
|
|
1353
|
+
<button class="icon-btn read-btn" (click)="markAsRead(notification.id, $event)" title="Mark as read" *ngIf="!notification.isRead">
|
|
1354
|
+
<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">
|
|
1355
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1356
|
+
</svg>
|
|
1152
1357
|
</button>
|
|
1153
|
-
<button
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
*ngIf="notification.isRead"
|
|
1158
|
-
>
|
|
1159
|
-
🗑
|
|
1358
|
+
<button class="icon-btn delete-btn" (click)="delete(notification.id, $event)" title="Delete" *ngIf="notification.isRead">
|
|
1359
|
+
<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">
|
|
1360
|
+
<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"/>
|
|
1361
|
+
</svg>
|
|
1160
1362
|
</button>
|
|
1161
1363
|
</div>
|
|
1162
1364
|
</ng-container>
|
|
1163
1365
|
|
|
1164
1366
|
<ng-container *ngIf="currentNotifications.length === 0">
|
|
1165
1367
|
<div class="empty-state">
|
|
1166
|
-
|
|
1368
|
+
<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">
|
|
1369
|
+
<path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
1370
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
1371
|
+
</svg>
|
|
1372
|
+
<p>No {{ activeTab }} notifications</p>
|
|
1167
1373
|
</div>
|
|
1168
1374
|
</ng-container>
|
|
1169
1375
|
</div>
|
|
@@ -1172,13 +1378,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1172
1378
|
<div class="panel-footer" *ngIf="currentNotifications.length > 0">
|
|
1173
1379
|
<div class="footer-actions" *ngIf="activeTab === 'unread'">
|
|
1174
1380
|
<button class="action-btn" (click)="markAllAsRead()" *ngIf="unreadNotifications.length > 0">
|
|
1175
|
-
|
|
1381
|
+
<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>
|
|
1382
|
+
Mark all read
|
|
1176
1383
|
</button>
|
|
1177
1384
|
<button class="action-btn delete-all-btn" (click)="deleteAllUnread()" *ngIf="unreadNotifications.length > 0">
|
|
1385
|
+
<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>
|
|
1178
1386
|
Delete all
|
|
1179
1387
|
</button>
|
|
1180
1388
|
</div>
|
|
1181
1389
|
<button class="action-btn delete-all-btn" (click)="deleteAllRead()" *ngIf="activeTab === 'read' && readNotifications.length > 0">
|
|
1390
|
+
<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>
|
|
1182
1391
|
Delete all
|
|
1183
1392
|
</button>
|
|
1184
1393
|
</div>
|
|
@@ -1187,9 +1396,33 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1187
1396
|
<!-- Details Modal -->
|
|
1188
1397
|
<div class="modal-overlay" *ngIf="selectedNotification" (click)="closeDetails()">
|
|
1189
1398
|
<div class="modal-container" (click)="$event.stopPropagation()">
|
|
1190
|
-
<div class="modal-header"
|
|
1191
|
-
|
|
1192
|
-
|
|
1399
|
+
<div class="modal-header"
|
|
1400
|
+
[class.modal-type-info]="typeOf(selectedNotification) === 'Info'"
|
|
1401
|
+
[class.modal-type-success]="typeOf(selectedNotification) === 'Success'"
|
|
1402
|
+
[class.modal-type-warning]="typeOf(selectedNotification) === 'Warning'"
|
|
1403
|
+
[class.modal-type-error]="typeOf(selectedNotification) === 'Error'">
|
|
1404
|
+
<div class="modal-header-left">
|
|
1405
|
+
<div class="modal-type-icon">
|
|
1406
|
+
<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">
|
|
1407
|
+
<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"/>
|
|
1408
|
+
</svg>
|
|
1409
|
+
<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">
|
|
1410
|
+
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/>
|
|
1411
|
+
</svg>
|
|
1412
|
+
<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">
|
|
1413
|
+
<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"/>
|
|
1414
|
+
</svg>
|
|
1415
|
+
<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">
|
|
1416
|
+
<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"/>
|
|
1417
|
+
</svg>
|
|
1418
|
+
</div>
|
|
1419
|
+
<h3>{{ selectedNotification.title }}</h3>
|
|
1420
|
+
</div>
|
|
1421
|
+
<button class="close-btn" (click)="closeDetails()" title="Close">
|
|
1422
|
+
<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">
|
|
1423
|
+
<line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/>
|
|
1424
|
+
</svg>
|
|
1425
|
+
</button>
|
|
1193
1426
|
</div>
|
|
1194
1427
|
<div class="modal-meta">
|
|
1195
1428
|
<span class="app-name">{{ selectedNotification.sourceAppName }}</span>
|
|
@@ -1201,7 +1434,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
|
|
|
1201
1434
|
</div>
|
|
1202
1435
|
</div>
|
|
1203
1436
|
</div>
|
|
1204
|
-
`, styles: [":host{display:block;position:relative;--primary-color: #1976d2;--primary-hover: #1565c0;--success-color: #
|
|
1437
|
+
`, styles: [":host{display:block;position:relative;--primary-color: #1976d2;--primary-hover: #1565c0;--primary-light: rgba(25, 118, 210, .1);--success-color: #43a047;--error-color: #f44336;--error-hover: #d32f2f;--unread-accent: #1976d2;--info-color: #2196f3;--info-bg: rgba(33, 150, 243, .1);--success-bg: rgba(67, 160, 71, .1);--warning-color: #f57c00;--warning-bg: rgba(245, 124, 0, .1);--error-bg: rgba(244, 67, 54, .1);--text-primary: #212121;--text-secondary: #616161;--text-muted: #9e9e9e;--bg-primary: #ffffff;--bg-secondary: #f8f9fa;--bg-hover: #f0f4ff;--bg-unread: rgba(25, 118, 210, .06);--border-color: #e0e0e0;--border-light: #eeeeee;--shadow: rgba(0, 0, 0, .15)}:host(.theme-dark){display:block;position:relative;--primary-color: #90caf9;--primary-hover: #64b5f6;--primary-light: rgba(144, 202, 249, .1);--success-color: #66bb6a;--error-color: #ef5350;--error-hover: #c62828;--unread-accent: #90caf9;--info-color: #64b5f6;--info-bg: rgba(100, 181, 246, .12);--success-bg: rgba(102, 187, 106, .12);--warning-color: #ffb74d;--warning-bg: rgba(255, 183, 77, .12);--error-bg: rgba(239, 83, 80, .12);--text-primary: #e0e0e0;--text-secondary: #b0b0b0;--text-muted: #757575;--bg-primary: #1e1e2e;--bg-secondary: #27273a;--bg-hover: #2a2d4a;--bg-unread: rgba(144, 202, 249, .08);--border-color: #383850;--border-light: #2e2e42;--shadow: rgba(0, 0, 0, .4)}.notification-panel{position:fixed;top:0;right:-360px;width:360px;height:100vh;background:var(--bg-primary);box-shadow:-4px 0 24px var(--shadow);display:flex;flex-direction:column;z-index:1030;transition:right .3s cubic-bezier(.16,1,.3,1)}.notification-panel.open{right:0}.panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px 18px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.panel-header-left{display:flex;align-items:center;gap:9px;color:var(--primary-color)}.panel-header h3{margin:0;font-size:16px;font-weight:700;color:var(--text-primary);letter-spacing:.1px}.close-btn{background:none;border:none;cursor:pointer;color:var(--text-muted);width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;transition:color .2s,background-color .2s}.close-btn:hover{color:var(--text-primary);background-color:var(--bg-hover)}.tabs{display:flex;gap:6px;padding:10px 14px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.tab-btn{flex:1;display:flex;align-items:center;justify-content:center;gap:6px;padding:7px 12px;background:none;border:1px solid var(--border-color);border-radius:20px;color:var(--text-secondary);cursor:pointer;font-size:13px;font-weight:500;transition:all .18s}.tab-btn:hover{background:var(--bg-hover);color:var(--primary-color);border-color:var(--primary-color)}.tab-btn.active{background:var(--primary-color);border-color:var(--primary-color);color:#fff}.tab-count{background:#ffffff40;border-radius:10px;min-width:18px;height:18px;padding:0 5px;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center}.tab-btn:not(.active) .tab-count{background:var(--error-color);color:#fff}.read-count{background:#ffffff40}.tab-btn:not(.active) .read-count{background:var(--text-muted)}.notifications-list{flex:1;overflow-y:auto}.notification-item{display:flex;align-items:flex-start;gap:0;border-bottom:1px solid var(--border-light);cursor:pointer;background:var(--bg-primary);transition:background-color .15s;position:relative}.notification-item:hover{background:var(--bg-hover)}.notification-item.unread{background:var(--bg-unread)}.notif-accent{width:3px;align-self:stretch;flex-shrink:0;background:transparent;border-radius:0 2px 2px 0;opacity:.3}.notification-item.unread .notif-accent{opacity:1}.notif-accent.type-info{background:var(--info-color)}.notif-accent.type-success{background:var(--success-color)}.notif-accent.type-warning{background:var(--warning-color)}.notif-accent.type-error{background:var(--error-color)}.notif-type-icon{flex-shrink:0;width:26px;height:26px;border-radius:7px;display:flex;align-items:center;justify-content:center;align-self:center;margin-left:10px}.notif-type-icon.type-info{color:var(--info-color);background:var(--info-bg)}.notif-type-icon.type-success{color:var(--success-color);background:var(--success-bg)}.notif-type-icon.type-warning{color:var(--warning-color);background:var(--warning-bg)}.notif-type-icon.type-error{color:var(--error-color);background:var(--error-bg)}.notification-content{flex:1;min-width:0;padding:12px 8px 12px 12px}.notification-title{font-weight:600;color:var(--text-primary);font-size:13.5px;margin-bottom:3px;line-height:1.35}.notification-message{color:var(--text-secondary);font-size:12px;line-height:1.45;margin-bottom:7px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-meta{display:flex;justify-content:space-between;font-size:11px;color:var(--text-muted)}.app-name{font-weight:600;color:var(--primary-color)}.icon-btn{background:none;border:none;cursor:pointer;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;flex-shrink:0;align-self:center;margin-right:8px;transition:color .15s,background-color .15s;color:var(--text-muted)}.read-btn:hover{color:var(--success-color);background:#43a0471a}.delete-btn:hover{color:var(--error-color);background:#f443361a}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;height:100%;padding:40px 20px;color:var(--text-muted)}.empty-icon{opacity:.35}.empty-state p{margin:0;font-size:13px}.panel-footer{padding:10px 14px;border-top:1px solid var(--border-color);background:var(--bg-secondary);flex-shrink:0}.footer-actions{display:flex;gap:8px}.footer-actions .action-btn{flex:1}.action-btn{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;padding:8px 12px;background:var(--primary-color);color:#fff;border:none;border-radius:8px;cursor:pointer;font-size:12.5px;font-weight:600;transition:background-color .18s,transform .12s}.action-btn:hover{background:var(--primary-hover);transform:translateY(-1px)}.delete-all-btn{background:var(--error-color)}.delete-all-btn:hover{background:var(--error-hover)}.modal-overlay{position:fixed;inset:0;background:#00000080;display:flex;align-items:center;justify-content:center;z-index:1060;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}.modal-container{background:var(--bg-primary);border-radius:14px;width:90%;max-width:580px;max-height:80vh;display:flex;flex-direction:column;box-shadow:0 16px 48px #00000040;animation:modal-in .2s cubic-bezier(.16,1,.3,1)}@keyframes modal-in{0%{opacity:0;transform:scale(.94) translateY(8px)}to{opacity:1;transform:scale(1) translateY(0)}}.modal-header{display:flex;justify-content:space-between;align-items:center;padding:16px 20px;border-bottom:1px solid var(--border-color);background:var(--bg-secondary);border-radius:14px 14px 0 0;border-top:3px solid transparent}.modal-header.modal-type-info{border-top-color:var(--info-color)}.modal-header.modal-type-success{border-top-color:var(--success-color)}.modal-header.modal-type-warning{border-top-color:var(--warning-color)}.modal-header.modal-type-error{border-top-color:var(--error-color)}.modal-header-left{display:flex;align-items:center;gap:10px;min-width:0}.modal-type-icon{flex-shrink:0;width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center}.modal-type-info .modal-type-icon{color:var(--info-color);background:var(--info-bg)}.modal-type-success .modal-type-icon{color:var(--success-color);background:var(--success-bg)}.modal-type-warning .modal-type-icon{color:var(--warning-color);background:var(--warning-bg)}.modal-type-error .modal-type-icon{color:var(--error-color);background:var(--error-bg)}.modal-header h3{margin:0;font-size:15px;font-weight:700;color:var(--text-primary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.modal-meta{display:flex;justify-content:space-between;padding:8px 20px;font-size:11.5px;color:var(--text-muted);border-bottom:1px solid var(--border-light)}.modal-body{padding:20px;overflow-y:auto;flex:1;color:var(--text-primary);font-size:14px;line-height:1.65}.modal-footer{padding:12px 20px;border-top:1px solid var(--border-color);background:var(--bg-secondary);border-radius:0 0 14px 14px;display:flex;justify-content:flex-end}.modal-footer .action-btn{width:auto;padding:8px 24px}@media(max-width:600px){.notification-panel{width:100%;right:-100%}.modal-container{width:95%;max-height:90vh}}\n"] }]
|
|
1205
1438
|
}], ctorParameters: () => [{ type: MesAuthService }, { type: ToastService }, { type: ThemeService }], propDecorators: { notificationRead: [{
|
|
1206
1439
|
type: Output
|
|
1207
1440
|
}], themeClass: [{
|