mesauth-angular 0.1.10 → 0.1.11

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.
Files changed (37) hide show
  1. package/dist/README.md +265 -0
  2. package/dist/esm2020/index.mjs +9 -0
  3. package/dist/esm2020/ma-user.component.mjs +26 -0
  4. package/dist/esm2020/mes-auth.interceptor.mjs +29 -0
  5. package/dist/esm2020/mes-auth.module.mjs +23 -0
  6. package/dist/esm2020/mes-auth.service.mjs +103 -0
  7. package/dist/esm2020/mesauth-angular.mjs +5 -0
  8. package/dist/esm2020/notification-badge.component.mjs +57 -0
  9. package/dist/esm2020/notification-panel.component.mjs +196 -0
  10. package/dist/esm2020/toast-container.component.mjs +60 -0
  11. package/dist/esm2020/toast.service.mjs +41 -0
  12. package/dist/esm2020/user-profile.component.mjs +197 -0
  13. package/dist/fesm2015/mesauth-angular.mjs +701 -0
  14. package/dist/fesm2015/mesauth-angular.mjs.map +1 -0
  15. package/dist/fesm2020/mesauth-angular.mjs +700 -0
  16. package/dist/fesm2020/mesauth-angular.mjs.map +1 -0
  17. package/dist/ma-user.component.d.ts +3 -0
  18. package/dist/mes-auth.interceptor.d.ts +3 -0
  19. package/dist/mes-auth.module.d.ts +4 -0
  20. package/dist/mes-auth.service.d.ts +5 -1
  21. package/dist/notification-badge.component.d.ts +3 -0
  22. package/dist/notification-panel.component.d.ts +3 -0
  23. package/dist/package.json +52 -0
  24. package/dist/toast-container.component.d.ts +3 -0
  25. package/dist/toast.service.d.ts +3 -0
  26. package/dist/user-profile.component.d.ts +3 -0
  27. package/package.json +15 -9
  28. package/dist/index.js +0 -8
  29. package/dist/ma-user.component.js +0 -33
  30. package/dist/mes-auth.interceptor.js +0 -36
  31. package/dist/mes-auth.module.js +0 -33
  32. package/dist/mes-auth.service.js +0 -107
  33. package/dist/notification-badge.component.js +0 -100
  34. package/dist/notification-panel.component.js +0 -327
  35. package/dist/toast-container.component.js +0 -185
  36. package/dist/toast.service.js +0 -43
  37. package/dist/user-profile.component.js +0 -363
@@ -0,0 +1,700 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Injectable, NgModule, EventEmitter, Component, Output } from '@angular/core';
3
+ import { HubConnectionBuilder, LogLevel } from '@microsoft/signalr';
4
+ import { BehaviorSubject, Subject, throwError } from 'rxjs';
5
+ import * as i1 from '@angular/common/http';
6
+ import { HTTP_INTERCEPTORS } from '@angular/common/http';
7
+ import { catchError, takeUntil } from 'rxjs/operators';
8
+ import * as i2 from '@angular/router';
9
+ import * as i2$1 from '@angular/common';
10
+ import { NgIf, CommonModule, NgFor } from '@angular/common';
11
+
12
+ var NotificationType;
13
+ (function (NotificationType) {
14
+ NotificationType["Info"] = "Info";
15
+ NotificationType["Warning"] = "Warning";
16
+ NotificationType["Error"] = "Error";
17
+ NotificationType["Success"] = "Success";
18
+ })(NotificationType || (NotificationType = {}));
19
+ class MesAuthService {
20
+ constructor(http) {
21
+ this.http = http;
22
+ this.hubConnection = null;
23
+ this._currentUser = new BehaviorSubject(null);
24
+ this.currentUser$ = this._currentUser.asObservable();
25
+ this._notifications = new Subject();
26
+ this.notifications$ = this._notifications.asObservable();
27
+ this.apiBase = '';
28
+ this.config = null;
29
+ }
30
+ init(config) {
31
+ this.config = config;
32
+ this.apiBase = config.apiBaseUrl.replace(/\/$/, '');
33
+ this.fetchCurrentUser();
34
+ this.fetchInitialNotifications();
35
+ this.startConnection(config);
36
+ }
37
+ getConfig() {
38
+ return this.config;
39
+ }
40
+ fetchCurrentUser() {
41
+ if (!this.apiBase)
42
+ return;
43
+ this.http.get(`${this.apiBase}/auth/me`).subscribe({
44
+ next: (u) => this._currentUser.next(u),
45
+ error: (err) => console.error('fetchCurrentUser error', err)
46
+ });
47
+ }
48
+ fetchInitialNotifications() {
49
+ if (!this.apiBase)
50
+ return;
51
+ this.http.get(`${this.apiBase}/notif/me`).subscribe({
52
+ next: (notifications) => {
53
+ if (Array.isArray(notifications?.items)) {
54
+ notifications.items.forEach((n) => this._notifications.next(n));
55
+ }
56
+ },
57
+ error: (err) => console.error('fetchInitialNotifications error', err)
58
+ });
59
+ }
60
+ getUnreadCount() {
61
+ return this.http.get(`${this.apiBase}/notif/me/unread-count`);
62
+ }
63
+ getNotifications(page = 1, pageSize = 20, includeRead = false, type) {
64
+ let url = `${this.apiBase}/notif/me?page=${page}&pageSize=${pageSize}&includeRead=${includeRead}`;
65
+ if (type) {
66
+ url += `&type=${type}`;
67
+ }
68
+ return this.http.get(url);
69
+ }
70
+ markAsRead(notificationId) {
71
+ return this.http.patch(`${this.apiBase}/notif/${notificationId}/read`, {});
72
+ }
73
+ markAllAsRead() {
74
+ return this.http.patch(`${this.apiBase}/notif/me/read-all`, {});
75
+ }
76
+ deleteNotification(notificationId) {
77
+ return this.http.delete(`${this.apiBase}/notif/${notificationId}`);
78
+ }
79
+ startConnection(config) {
80
+ if (this.hubConnection)
81
+ return;
82
+ const signalrUrl = config.apiBaseUrl.replace(/\/$/, '') + '/hub/notification';
83
+ const builder = new HubConnectionBuilder()
84
+ .withUrl(signalrUrl, { withCredentials: config.withCredentials ?? true })
85
+ .withAutomaticReconnect()
86
+ .configureLogging(LogLevel.Warning);
87
+ this.hubConnection = builder.build();
88
+ this.hubConnection.on('ReceiveNotification', (n) => this._notifications.next(n));
89
+ this.hubConnection.start().catch((err) => console.error('SignalR start error', err));
90
+ }
91
+ stop() {
92
+ if (!this.hubConnection)
93
+ return;
94
+ this.hubConnection.stop().catch(() => { });
95
+ this.hubConnection = null;
96
+ }
97
+ logout() {
98
+ return this.http.post(`${this.apiBase}/auth/logout`, {});
99
+ }
100
+ refreshUser() {
101
+ this.fetchCurrentUser();
102
+ }
103
+ }
104
+ MesAuthService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthService, deps: [{ token: i1.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
105
+ MesAuthService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthService });
106
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthService, decorators: [{
107
+ type: Injectable
108
+ }], ctorParameters: function () { return [{ type: i1.HttpClient }]; } });
109
+
110
+ class MesAuthInterceptor {
111
+ constructor(authService, router) {
112
+ this.authService = authService;
113
+ this.router = router;
114
+ }
115
+ intercept(req, next) {
116
+ return next.handle(req).pipe(catchError((error) => {
117
+ if (error.status === 403) {
118
+ const config = this.authService.getConfig();
119
+ const baseUrl = config?.userBaseUrl || '';
120
+ const returnUrl = encodeURIComponent(window.location.href);
121
+ window.location.href = `${baseUrl}/403?returnUrl=${returnUrl}`;
122
+ }
123
+ return throwError(error);
124
+ }));
125
+ }
126
+ }
127
+ MesAuthInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthInterceptor, deps: [{ token: MesAuthService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
128
+ MesAuthInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthInterceptor });
129
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthInterceptor, decorators: [{
130
+ type: Injectable
131
+ }], ctorParameters: function () { return [{ type: MesAuthService }, { type: i2.Router }]; } });
132
+
133
+ class MesAuthModule {
134
+ }
135
+ MesAuthModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
136
+ MesAuthModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: MesAuthModule });
137
+ MesAuthModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthModule, providers: [
138
+ MesAuthService,
139
+ { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
140
+ ] });
141
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MesAuthModule, decorators: [{
142
+ type: NgModule,
143
+ args: [{
144
+ providers: [
145
+ MesAuthService,
146
+ { provide: HTTP_INTERCEPTORS, useClass: MesAuthInterceptor, multi: true }
147
+ ]
148
+ }]
149
+ }] });
150
+
151
+ class UserProfileComponent {
152
+ constructor(authService, router) {
153
+ this.authService = authService;
154
+ this.router = router;
155
+ this.notificationClick = new EventEmitter();
156
+ this.currentUser = null;
157
+ this.unreadCount = 0;
158
+ this.dropdownOpen = false;
159
+ this.destroy$ = new Subject();
160
+ }
161
+ ngOnInit() {
162
+ console.log('UserProfileComponent: Service injected?', !!this.authService);
163
+ this.authService.currentUser$
164
+ .pipe(takeUntil(this.destroy$))
165
+ .subscribe(user => {
166
+ console.log('UserProfileComponent: currentUser', user);
167
+ this.currentUser = user;
168
+ });
169
+ this.loadUnreadCount();
170
+ // Listen for new notifications
171
+ this.authService.notifications$
172
+ .pipe(takeUntil(this.destroy$))
173
+ .subscribe(() => {
174
+ this.loadUnreadCount();
175
+ });
176
+ }
177
+ ngOnDestroy() {
178
+ this.destroy$.next();
179
+ this.destroy$.complete();
180
+ }
181
+ loadUnreadCount() {
182
+ this.authService.getUnreadCount().subscribe({
183
+ next: (response) => {
184
+ this.unreadCount = response.unreadCount || 0;
185
+ },
186
+ error: (err) => console.error('Error loading unread count:', err)
187
+ });
188
+ }
189
+ getAvatarUrl(user) {
190
+ const config = this.authService.getConfig();
191
+ const baseUrl = config?.avatarUrl || 'https://ui-avatars.com/api/';
192
+ // Use userName first, fallback to userId, final fallback to 'User'
193
+ const displayName = user.userName || user.userId || 'User';
194
+ return `${baseUrl}?name=${encodeURIComponent(displayName)}&background=1976d2&color=fff`;
195
+ }
196
+ getLastNameInitial(user) {
197
+ const fullName = user.fullName || user.userName || 'U';
198
+ const parts = fullName.split(' ');
199
+ const lastPart = parts[parts.length - 1];
200
+ return lastPart.charAt(0).toUpperCase();
201
+ }
202
+ toggleDropdown() {
203
+ this.dropdownOpen = !this.dropdownOpen;
204
+ }
205
+ onLogin() {
206
+ const config = this.authService.getConfig();
207
+ const baseUrl = config?.userBaseUrl || '';
208
+ const returnUrl = encodeURIComponent(this.router.url);
209
+ window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;
210
+ }
211
+ onViewProfile() {
212
+ const config = this.authService.getConfig();
213
+ const baseUrl = config?.userBaseUrl || '';
214
+ window.location.href = `${baseUrl}/profile`;
215
+ this.dropdownOpen = false;
216
+ }
217
+ onLogout() {
218
+ this.authService.logout().subscribe({
219
+ next: () => {
220
+ // Clear current user after successful logout
221
+ this.currentUser = null;
222
+ this.dropdownOpen = false;
223
+ // Navigate to login with return URL
224
+ const config = this.authService.getConfig();
225
+ const baseUrl = config?.userBaseUrl || '';
226
+ const returnUrl = encodeURIComponent(window.location.href);
227
+ window.location.href = `${baseUrl}/login?returnUrl=${returnUrl}`;
228
+ },
229
+ error: (err) => {
230
+ console.error('Logout error:', err);
231
+ // Still navigate to login even if logout fails
232
+ const config = this.authService.getConfig();
233
+ const baseUrl = config?.userBaseUrl || '';
234
+ window.location.href = `${baseUrl}/login`;
235
+ }
236
+ });
237
+ }
238
+ onNotificationClick() {
239
+ this.notificationClick.emit();
240
+ }
241
+ }
242
+ UserProfileComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: UserProfileComponent, deps: [{ token: MesAuthService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Component });
243
+ UserProfileComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: UserProfileComponent, isStandalone: true, selector: "ma-user-profile", outputs: { notificationClick: "notificationClick" }, ngImport: i0, template: `
244
+ <div class="user-profile-container">
245
+ <!-- Not logged in -->
246
+ <ng-container *ngIf="!currentUser">
247
+ <button class="login-btn" (click)="onLogin()">
248
+ Login
249
+ </button>
250
+ </ng-container>
251
+
252
+ <!-- Logged in -->
253
+ <ng-container *ngIf="currentUser">
254
+ <div class="user-header">
255
+ <button class="notification-btn" (click)="onNotificationClick()" title="Notifications">
256
+ <span class="icon">🔔</span>
257
+ <span class="badge" *ngIf="unreadCount > 0">{{ unreadCount }}</span>
258
+ </button>
259
+
260
+ <div class="user-menu-wrapper">
261
+ <button class="user-menu-btn" (click)="toggleDropdown()">
262
+ <img
263
+ *ngIf="currentUser.fullName || currentUser.userName"
264
+ [src]="getAvatarUrl(currentUser)"
265
+ [alt]="currentUser.fullName || currentUser.userName"
266
+ class="avatar"
267
+ />
268
+ <span *ngIf="!(currentUser.fullName || currentUser.userName)" class="avatar-initial">
269
+ {{ getLastNameInitial(currentUser) }}
270
+ </span>
271
+ </button>
272
+
273
+ <div class="dropdown-menu" *ngIf="dropdownOpen">
274
+ <div class="dropdown-header">
275
+ {{ currentUser.fullName || currentUser.userName }}
276
+ </div>
277
+ <button class="dropdown-item profile-link" (click)="onViewProfile()">
278
+ View Profile
279
+ </button>
280
+ <button class="dropdown-item logout-item" (click)="onLogout()">
281
+ Logout
282
+ </button>
283
+ </div>
284
+ </div>
285
+ </div>
286
+ </ng-container>
287
+ </div>
288
+ `, isInline: true, styles: [".user-profile-container{display:flex;align-items:center;gap:16px;padding:0 16px}.login-btn{padding:8px 16px;background-color:#1976d2;color:#fff;border:none;border-radius:4px;cursor:pointer;font-weight:500;transition:background-color .3s}.login-btn:hover{background-color:#1565c0}.user-header{display:flex;align-items:center;gap:16px}.notification-btn{position:relative;background:none;border:none;font-size:24px;cursor:pointer;padding:8px;transition:opacity .2s}.notification-btn:hover{opacity:.7}.icon{display:inline-block}.badge{position:absolute;top:0;right:0;background-color:#f44336;color:#fff;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}.user-menu-wrapper{position:relative}.user-menu-btn{background:none;border:none;cursor:pointer;padding:4px;border-radius:50%;transition:background-color .2s;display:flex;align-items:center;justify-content:center}.user-menu-btn:hover{background-color:#1976d21a}.avatar{width:40px;height:40px;border-radius:50%;object-fit:cover;background-color:#e0e0e0}.avatar-initial{width:40px;height:40px;border-radius:50%;background-color:#1976d2;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px}.dropdown-menu{position:absolute;top:calc(100% + 8px);right:0;background:white;border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 2px 8px #00000026;min-width:200px;z-index:1000;overflow:hidden}.dropdown-header{padding:12px 16px;border-bottom:1px solid #f0f0f0;font-weight:600;color:#333;font-size:14px}.dropdown-item{display:block;width:100%;padding:12px 16px;border:none;background:none;text-align:left;cursor:pointer;font-size:14px;color:#333;text-decoration:none;transition:background-color .2s}.dropdown-item:hover{background-color:#f5f5f5}.profile-link{color:#1976d2}.logout-item{border-top:1px solid #f0f0f0;color:#f44336}.logout-item:hover{background-color:#ffebee}.user-info{display:flex;flex-direction:column;gap:2px}.user-name{font-weight:500;font-size:14px;color:#333}.user-position{font-size:12px;color:#666}.logout-btn{background:none;border:none;font-size:20px;cursor:pointer;color:#666;padding:4px 8px;transition:color .2s}.logout-btn:hover{color:#1976d2}@media (max-width: 768px){.user-info{display:none}.avatar{width:32px;height:32px}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
289
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: UserProfileComponent, decorators: [{
290
+ type: Component,
291
+ args: [{ selector: 'ma-user-profile', standalone: true, imports: [NgIf], template: `
292
+ <div class="user-profile-container">
293
+ <!-- Not logged in -->
294
+ <ng-container *ngIf="!currentUser">
295
+ <button class="login-btn" (click)="onLogin()">
296
+ Login
297
+ </button>
298
+ </ng-container>
299
+
300
+ <!-- Logged in -->
301
+ <ng-container *ngIf="currentUser">
302
+ <div class="user-header">
303
+ <button class="notification-btn" (click)="onNotificationClick()" title="Notifications">
304
+ <span class="icon">🔔</span>
305
+ <span class="badge" *ngIf="unreadCount > 0">{{ unreadCount }}</span>
306
+ </button>
307
+
308
+ <div class="user-menu-wrapper">
309
+ <button class="user-menu-btn" (click)="toggleDropdown()">
310
+ <img
311
+ *ngIf="currentUser.fullName || currentUser.userName"
312
+ [src]="getAvatarUrl(currentUser)"
313
+ [alt]="currentUser.fullName || currentUser.userName"
314
+ class="avatar"
315
+ />
316
+ <span *ngIf="!(currentUser.fullName || currentUser.userName)" class="avatar-initial">
317
+ {{ getLastNameInitial(currentUser) }}
318
+ </span>
319
+ </button>
320
+
321
+ <div class="dropdown-menu" *ngIf="dropdownOpen">
322
+ <div class="dropdown-header">
323
+ {{ currentUser.fullName || currentUser.userName }}
324
+ </div>
325
+ <button class="dropdown-item profile-link" (click)="onViewProfile()">
326
+ View Profile
327
+ </button>
328
+ <button class="dropdown-item logout-item" (click)="onLogout()">
329
+ Logout
330
+ </button>
331
+ </div>
332
+ </div>
333
+ </div>
334
+ </ng-container>
335
+ </div>
336
+ `, styles: [".user-profile-container{display:flex;align-items:center;gap:16px;padding:0 16px}.login-btn{padding:8px 16px;background-color:#1976d2;color:#fff;border:none;border-radius:4px;cursor:pointer;font-weight:500;transition:background-color .3s}.login-btn:hover{background-color:#1565c0}.user-header{display:flex;align-items:center;gap:16px}.notification-btn{position:relative;background:none;border:none;font-size:24px;cursor:pointer;padding:8px;transition:opacity .2s}.notification-btn:hover{opacity:.7}.icon{display:inline-block}.badge{position:absolute;top:0;right:0;background-color:#f44336;color:#fff;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}.user-menu-wrapper{position:relative}.user-menu-btn{background:none;border:none;cursor:pointer;padding:4px;border-radius:50%;transition:background-color .2s;display:flex;align-items:center;justify-content:center}.user-menu-btn:hover{background-color:#1976d21a}.avatar{width:40px;height:40px;border-radius:50%;object-fit:cover;background-color:#e0e0e0}.avatar-initial{width:40px;height:40px;border-radius:50%;background-color:#1976d2;color:#fff;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px}.dropdown-menu{position:absolute;top:calc(100% + 8px);right:0;background:white;border:1px solid #e0e0e0;border-radius:4px;box-shadow:0 2px 8px #00000026;min-width:200px;z-index:1000;overflow:hidden}.dropdown-header{padding:12px 16px;border-bottom:1px solid #f0f0f0;font-weight:600;color:#333;font-size:14px}.dropdown-item{display:block;width:100%;padding:12px 16px;border:none;background:none;text-align:left;cursor:pointer;font-size:14px;color:#333;text-decoration:none;transition:background-color .2s}.dropdown-item:hover{background-color:#f5f5f5}.profile-link{color:#1976d2}.logout-item{border-top:1px solid #f0f0f0;color:#f44336}.logout-item:hover{background-color:#ffebee}.user-info{display:flex;flex-direction:column;gap:2px}.user-name{font-weight:500;font-size:14px;color:#333}.user-position{font-size:12px;color:#666}.logout-btn{background:none;border:none;font-size:20px;cursor:pointer;color:#666;padding:4px 8px;transition:color .2s}.logout-btn:hover{color:#1976d2}@media (max-width: 768px){.user-info{display:none}.avatar{width:32px;height:32px}}\n"] }]
337
+ }], ctorParameters: function () { return [{ type: MesAuthService }, { type: i2.Router }]; }, propDecorators: { notificationClick: [{
338
+ type: Output
339
+ }] } });
340
+
341
+ class ToastService {
342
+ constructor() {
343
+ this.toasts$ = new BehaviorSubject([]);
344
+ this.toasts = this.toasts$.asObservable();
345
+ }
346
+ show(message, title, type = 'info', duration = 5000) {
347
+ const id = Math.random().toString(36).substr(2, 9);
348
+ const toast = {
349
+ id,
350
+ message,
351
+ title,
352
+ type,
353
+ duration
354
+ };
355
+ const currentToasts = this.toasts$.value;
356
+ this.toasts$.next([...currentToasts, toast]);
357
+ if (duration > 0) {
358
+ setTimeout(() => {
359
+ this.remove(id);
360
+ }, duration);
361
+ }
362
+ return id;
363
+ }
364
+ remove(id) {
365
+ const currentToasts = this.toasts$.value;
366
+ this.toasts$.next(currentToasts.filter(t => t.id !== id));
367
+ }
368
+ clear() {
369
+ this.toasts$.next([]);
370
+ }
371
+ }
372
+ ToastService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ToastService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
373
+ ToastService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ToastService, providedIn: 'root' });
374
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ToastService, decorators: [{
375
+ type: Injectable,
376
+ args: [{ providedIn: 'root' }]
377
+ }] });
378
+
379
+ class ToastContainerComponent {
380
+ constructor(toastService) {
381
+ this.toastService = toastService;
382
+ this.toasts = [];
383
+ }
384
+ ngOnInit() {
385
+ this.toastService.toasts.subscribe(toasts => {
386
+ this.toasts = toasts;
387
+ });
388
+ }
389
+ close(id) {
390
+ this.toastService.remove(id);
391
+ }
392
+ }
393
+ ToastContainerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ToastContainerComponent, deps: [{ token: ToastService }], target: i0.ɵɵFactoryTarget.Component });
394
+ ToastContainerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: ToastContainerComponent, isStandalone: true, selector: "ma-toast-container", ngImport: i0, template: `
395
+ <div class="toast-container">
396
+ <div
397
+ *ngFor="let toast of toasts"
398
+ class="toast"
399
+ [class]="'toast-' + toast.type"
400
+ [@slideIn]
401
+ >
402
+ <div class="toast-content">
403
+ <div *ngIf="toast.title" class="toast-title">{{ toast.title }}</div>
404
+ <div class="toast-message">{{ toast.message }}</div>
405
+ </div>
406
+ <button class="toast-close" (click)="close(toast.id)" aria-label="Close">
407
+
408
+ </button>
409
+ </div>
410
+ </div>
411
+ `, isInline: true, styles: [".toast-container{position:fixed;top:20px;right:20px;z-index:9999;pointer-events:none}.toast{display:flex;align-items:flex-start;gap:12px;padding:12px 16px;margin-bottom:12px;border-radius:4px;background-color:#fff;box-shadow:0 4px 12px #00000026;pointer-events:auto;min-width:300px;max-width:500px;animation:slideIn .3s ease-out}.toast-content{flex:1}.toast-title{font-weight:600;font-size:14px;margin-bottom:4px}.toast-message{font-size:13px;line-height:1.4}.toast-close{background:none;border:none;cursor:pointer;font-size:18px;color:#999;padding:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color .2s}.toast-close:hover{color:#333}.toast-info{border-left:4px solid #2196f3}.toast-info .toast-title{color:#2196f3}.toast-info .toast-message{color:#333}.toast-success{border-left:4px solid #4caf50}.toast-success .toast-title{color:#4caf50}.toast-success .toast-message{color:#333}.toast-warning{border-left:4px solid #ff9800}.toast-warning .toast-title{color:#ff9800}.toast-warning .toast-message{color:#333}.toast-error{border-left:4px solid #f44336}.toast-error .toast-title{color:#f44336}.toast-error .toast-message{color:#333}@keyframes slideIn{0%{transform:translate(400px);opacity:0}to{transform:translate(0);opacity:1}}@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: i2$1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
412
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ToastContainerComponent, decorators: [{
413
+ type: Component,
414
+ args: [{ selector: 'ma-toast-container', standalone: true, imports: [CommonModule], template: `
415
+ <div class="toast-container">
416
+ <div
417
+ *ngFor="let toast of toasts"
418
+ class="toast"
419
+ [class]="'toast-' + toast.type"
420
+ [@slideIn]
421
+ >
422
+ <div class="toast-content">
423
+ <div *ngIf="toast.title" class="toast-title">{{ toast.title }}</div>
424
+ <div class="toast-message">{{ toast.message }}</div>
425
+ </div>
426
+ <button class="toast-close" (click)="close(toast.id)" aria-label="Close">
427
+
428
+ </button>
429
+ </div>
430
+ </div>
431
+ `, styles: [".toast-container{position:fixed;top:20px;right:20px;z-index:9999;pointer-events:none}.toast{display:flex;align-items:flex-start;gap:12px;padding:12px 16px;margin-bottom:12px;border-radius:4px;background-color:#fff;box-shadow:0 4px 12px #00000026;pointer-events:auto;min-width:300px;max-width:500px;animation:slideIn .3s ease-out}.toast-content{flex:1}.toast-title{font-weight:600;font-size:14px;margin-bottom:4px}.toast-message{font-size:13px;line-height:1.4}.toast-close{background:none;border:none;cursor:pointer;font-size:18px;color:#999;padding:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color .2s}.toast-close:hover{color:#333}.toast-info{border-left:4px solid #2196f3}.toast-info .toast-title{color:#2196f3}.toast-info .toast-message{color:#333}.toast-success{border-left:4px solid #4caf50}.toast-success .toast-title{color:#4caf50}.toast-success .toast-message{color:#333}.toast-warning{border-left:4px solid #ff9800}.toast-warning .toast-title{color:#ff9800}.toast-warning .toast-message{color:#333}.toast-error{border-left:4px solid #f44336}.toast-error .toast-title{color:#f44336}.toast-error .toast-message{color:#333}@keyframes slideIn{0%{transform:translate(400px);opacity:0}to{transform:translate(0);opacity:1}}@media (max-width: 600px){.toast-container{top:10px;right:10px;left:10px}.toast{min-width:auto;max-width:100%}}\n"] }]
432
+ }], ctorParameters: function () { return [{ type: ToastService }]; } });
433
+
434
+ class NotificationPanelComponent {
435
+ constructor(authService, toastService) {
436
+ this.authService = authService;
437
+ this.toastService = toastService;
438
+ this.isOpen = false;
439
+ this.notifications = [];
440
+ this.destroy$ = new Subject();
441
+ }
442
+ ngOnInit() {
443
+ this.loadNotifications();
444
+ // Listen for new real-time notifications
445
+ this.authService.notifications$
446
+ .pipe(takeUntil(this.destroy$))
447
+ .subscribe((notification) => {
448
+ // Show toast for new notification
449
+ this.toastService.show(notification.message, notification.title, 'info', 5000);
450
+ // Reload notifications list
451
+ this.loadNotifications();
452
+ });
453
+ }
454
+ ngOnDestroy() {
455
+ this.destroy$.next();
456
+ this.destroy$.complete();
457
+ }
458
+ loadNotifications() {
459
+ this.authService.getNotifications(1, 50, false).subscribe({
460
+ next: (response) => {
461
+ this.notifications = response.items || [];
462
+ },
463
+ error: (err) => console.error('Error loading notifications:', err)
464
+ });
465
+ }
466
+ open() {
467
+ this.isOpen = true;
468
+ }
469
+ close() {
470
+ this.isOpen = false;
471
+ }
472
+ markAsRead(notificationId) {
473
+ this.authService.markAsRead(notificationId).subscribe({
474
+ next: () => {
475
+ const notification = this.notifications.find(n => n.id === notificationId);
476
+ if (notification) {
477
+ notification.isRead = true;
478
+ }
479
+ },
480
+ error: (err) => console.error('Error marking as read:', err)
481
+ });
482
+ }
483
+ markAllAsRead() {
484
+ this.authService.markAllAsRead().subscribe({
485
+ next: () => {
486
+ this.notifications.forEach(n => n.isRead = true);
487
+ },
488
+ error: (err) => console.error('Error marking all as read:', err)
489
+ });
490
+ }
491
+ delete(notificationId, event) {
492
+ event.stopPropagation();
493
+ this.authService.deleteNotification(notificationId).subscribe({
494
+ next: () => {
495
+ this.notifications = this.notifications.filter(n => n.id !== notificationId);
496
+ },
497
+ error: (err) => console.error('Error deleting notification:', err)
498
+ });
499
+ }
500
+ formatDate(dateString) {
501
+ const date = new Date(dateString);
502
+ const now = new Date();
503
+ const diffMs = now.getTime() - date.getTime();
504
+ const diffMins = Math.floor(diffMs / 60000);
505
+ const diffHours = Math.floor(diffMs / 3600000);
506
+ const diffDays = Math.floor(diffMs / 86400000);
507
+ if (diffMins < 1)
508
+ return 'Now';
509
+ if (diffMins < 60)
510
+ return `${diffMins}m ago`;
511
+ if (diffHours < 24)
512
+ return `${diffHours}h ago`;
513
+ if (diffDays < 7)
514
+ return `${diffDays}d ago`;
515
+ return date.toLocaleDateString();
516
+ }
517
+ }
518
+ NotificationPanelComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationPanelComponent, deps: [{ token: MesAuthService }, { token: ToastService }], target: i0.ɵɵFactoryTarget.Component });
519
+ NotificationPanelComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NotificationPanelComponent, isStandalone: true, selector: "ma-notification-panel", ngImport: i0, template: `
520
+ <div class="notification-panel" [class.open]="isOpen">
521
+ <!-- Header -->
522
+ <div class="panel-header">
523
+ <h3>Notifications</h3>
524
+ <button class="close-btn" (click)="close()" title="Close">✕</button>
525
+ </div>
526
+
527
+ <!-- Notifications List -->
528
+ <div class="notifications-list">
529
+ <ng-container *ngIf="notifications.length > 0">
530
+ <div
531
+ *ngFor="let notification of notifications"
532
+ class="notification-item"
533
+ [class.unread]="!notification.isRead"
534
+ (click)="markAsRead(notification.id)"
535
+ >
536
+ <div class="notification-content">
537
+ <div class="notification-title">{{ notification.title }}</div>
538
+ <div class="notification-message">{{ notification.message }}</div>
539
+ <div class="notification-meta">
540
+ <span class="app-name">{{ notification.sourceAppName }}</span>
541
+ <span class="time">{{ formatDate(notification.createdAt) }}</span>
542
+ </div>
543
+ </div>
544
+ <button
545
+ class="delete-btn"
546
+ (click)="delete(notification.id, $event)"
547
+ title="Delete"
548
+ >
549
+
550
+ </button>
551
+ </div>
552
+ </ng-container>
553
+
554
+ <ng-container *ngIf="notifications.length === 0">
555
+ <div class="empty-state">
556
+ No notifications
557
+ </div>
558
+ </ng-container>
559
+ </div>
560
+
561
+ <!-- Footer Actions -->
562
+ <div class="panel-footer" *ngIf="notifications.length > 0">
563
+ <button class="action-btn" (click)="markAllAsRead()">
564
+ Mark all as read
565
+ </button>
566
+ </div>
567
+ </div>
568
+ `, isInline: true, styles: [".notification-panel{position:fixed;top:0;right:-350px;width:350px;height:100vh;background:white;box-shadow:-2px 0 8px #0000001a;display:flex;flex-direction:column;z-index:1000;transition:right .3s ease}.notification-panel.open{right:0}.panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px;border-bottom:1px solid #e0e0e0;background-color:#f5f5f5}.panel-header h3{margin:0;font-size:18px;color:#333}.close-btn{background:none;border:none;font-size:20px;cursor:pointer;color:#666;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:color .2s}.close-btn:hover{color:#333}.notifications-list{flex:1;overflow-y:auto}.notification-item{display:flex;gap:12px;padding:12px 16px;border-bottom:1px solid #f0f0f0;cursor:pointer;background-color:#fafafa;transition:background-color .2s}.notification-item:hover{background-color:#f5f5f5}.notification-item.unread{background-color:#e3f2fd}.notification-content{flex:1;min-width:0}.notification-title{font-weight:600;color:#333;font-size:14px;margin-bottom:4px}.notification-message{color:#666;font-size:13px;line-height:1.4;margin-bottom:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-meta{display:flex;justify-content:space-between;font-size:12px;color:#999}.app-name{font-weight:500;color:#1976d2}.delete-btn{background:none;border:none;color:#999;cursor:pointer;font-size:14px;padding:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color .2s}.delete-btn:hover{color:#f44336}.empty-state{display:flex;align-items:center;justify-content:center;height:100%;color:#999;font-size:14px}.panel-footer{padding:12px 16px;border-top:1px solid #e0e0e0;background-color:#f5f5f5}.action-btn{width:100%;padding:8px;background-color:#1976d2;color:#fff;border:none;border-radius:4px;cursor:pointer;font-weight:500;transition:background-color .2s}.action-btn:hover{background-color:#1565c0}@media (max-width: 600px){.notification-panel{width:100%;right:-100%}}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }] });
569
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationPanelComponent, decorators: [{
570
+ type: Component,
571
+ args: [{ selector: 'ma-notification-panel', standalone: true, imports: [NgIf, NgFor], template: `
572
+ <div class="notification-panel" [class.open]="isOpen">
573
+ <!-- Header -->
574
+ <div class="panel-header">
575
+ <h3>Notifications</h3>
576
+ <button class="close-btn" (click)="close()" title="Close">✕</button>
577
+ </div>
578
+
579
+ <!-- Notifications List -->
580
+ <div class="notifications-list">
581
+ <ng-container *ngIf="notifications.length > 0">
582
+ <div
583
+ *ngFor="let notification of notifications"
584
+ class="notification-item"
585
+ [class.unread]="!notification.isRead"
586
+ (click)="markAsRead(notification.id)"
587
+ >
588
+ <div class="notification-content">
589
+ <div class="notification-title">{{ notification.title }}</div>
590
+ <div class="notification-message">{{ notification.message }}</div>
591
+ <div class="notification-meta">
592
+ <span class="app-name">{{ notification.sourceAppName }}</span>
593
+ <span class="time">{{ formatDate(notification.createdAt) }}</span>
594
+ </div>
595
+ </div>
596
+ <button
597
+ class="delete-btn"
598
+ (click)="delete(notification.id, $event)"
599
+ title="Delete"
600
+ >
601
+
602
+ </button>
603
+ </div>
604
+ </ng-container>
605
+
606
+ <ng-container *ngIf="notifications.length === 0">
607
+ <div class="empty-state">
608
+ No notifications
609
+ </div>
610
+ </ng-container>
611
+ </div>
612
+
613
+ <!-- Footer Actions -->
614
+ <div class="panel-footer" *ngIf="notifications.length > 0">
615
+ <button class="action-btn" (click)="markAllAsRead()">
616
+ Mark all as read
617
+ </button>
618
+ </div>
619
+ </div>
620
+ `, styles: [".notification-panel{position:fixed;top:0;right:-350px;width:350px;height:100vh;background:white;box-shadow:-2px 0 8px #0000001a;display:flex;flex-direction:column;z-index:1000;transition:right .3s ease}.notification-panel.open{right:0}.panel-header{display:flex;justify-content:space-between;align-items:center;padding:16px;border-bottom:1px solid #e0e0e0;background-color:#f5f5f5}.panel-header h3{margin:0;font-size:18px;color:#333}.close-btn{background:none;border:none;font-size:20px;cursor:pointer;color:#666;padding:0;width:32px;height:32px;display:flex;align-items:center;justify-content:center;transition:color .2s}.close-btn:hover{color:#333}.notifications-list{flex:1;overflow-y:auto}.notification-item{display:flex;gap:12px;padding:12px 16px;border-bottom:1px solid #f0f0f0;cursor:pointer;background-color:#fafafa;transition:background-color .2s}.notification-item:hover{background-color:#f5f5f5}.notification-item.unread{background-color:#e3f2fd}.notification-content{flex:1;min-width:0}.notification-title{font-weight:600;color:#333;font-size:14px;margin-bottom:4px}.notification-message{color:#666;font-size:13px;line-height:1.4;margin-bottom:6px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notification-meta{display:flex;justify-content:space-between;font-size:12px;color:#999}.app-name{font-weight:500;color:#1976d2}.delete-btn{background:none;border:none;color:#999;cursor:pointer;font-size:14px;padding:0;width:24px;height:24px;display:flex;align-items:center;justify-content:center;flex-shrink:0;transition:color .2s}.delete-btn:hover{color:#f44336}.empty-state{display:flex;align-items:center;justify-content:center;height:100%;color:#999;font-size:14px}.panel-footer{padding:12px 16px;border-top:1px solid #e0e0e0;background-color:#f5f5f5}.action-btn{width:100%;padding:8px;background-color:#1976d2;color:#fff;border:none;border-radius:4px;cursor:pointer;font-weight:500;transition:background-color .2s}.action-btn:hover{background-color:#1565c0}@media (max-width: 600px){.notification-panel{width:100%;right:-100%}}\n"] }]
621
+ }], ctorParameters: function () { return [{ type: MesAuthService }, { type: ToastService }]; } });
622
+
623
+ class MaUserComponent {
624
+ }
625
+ MaUserComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MaUserComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
626
+ MaUserComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: MaUserComponent, isStandalone: true, selector: "ma-user", ngImport: i0, template: `
627
+ <ma-toast-container></ma-toast-container>
628
+ <div class="user-header">
629
+ <ma-user-profile (notificationClick)="notificationPanel.open()"></ma-user-profile>
630
+ </div>
631
+ <ma-notification-panel #notificationPanel></ma-notification-panel>
632
+ `, isInline: true, styles: [".user-header{display:flex;justify-content:flex-end}\n"], dependencies: [{ kind: "component", type: ToastContainerComponent, selector: "ma-toast-container" }, { kind: "component", type: UserProfileComponent, selector: "ma-user-profile", outputs: ["notificationClick"] }, { kind: "component", type: NotificationPanelComponent, selector: "ma-notification-panel" }] });
633
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: MaUserComponent, decorators: [{
634
+ type: Component,
635
+ args: [{ selector: 'ma-user', standalone: true, imports: [ToastContainerComponent, UserProfileComponent, NotificationPanelComponent], template: `
636
+ <ma-toast-container></ma-toast-container>
637
+ <div class="user-header">
638
+ <ma-user-profile (notificationClick)="notificationPanel.open()"></ma-user-profile>
639
+ </div>
640
+ <ma-notification-panel #notificationPanel></ma-notification-panel>
641
+ `, styles: [".user-header{display:flex;justify-content:flex-end}\n"] }]
642
+ }] });
643
+
644
+ class NotificationBadgeComponent {
645
+ constructor(authService) {
646
+ this.authService = authService;
647
+ this.notificationClick = new EventEmitter();
648
+ this.unreadCount = 0;
649
+ this.destroy$ = new Subject();
650
+ }
651
+ ngOnInit() {
652
+ this.loadUnreadCount();
653
+ // Listen for new notifications
654
+ this.authService.notifications$
655
+ .pipe(takeUntil(this.destroy$))
656
+ .subscribe(() => {
657
+ this.loadUnreadCount();
658
+ });
659
+ }
660
+ ngOnDestroy() {
661
+ this.destroy$.next();
662
+ this.destroy$.complete();
663
+ }
664
+ loadUnreadCount() {
665
+ this.authService.getUnreadCount().subscribe({
666
+ next: (response) => {
667
+ this.unreadCount = response.unreadCount || 0;
668
+ },
669
+ error: (err) => console.error('Error loading unread count:', err)
670
+ });
671
+ }
672
+ onNotificationClick() {
673
+ this.notificationClick.emit();
674
+ }
675
+ }
676
+ NotificationBadgeComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationBadgeComponent, deps: [{ token: MesAuthService }], target: i0.ɵɵFactoryTarget.Component });
677
+ NotificationBadgeComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: NotificationBadgeComponent, isStandalone: true, selector: "ma-notification-badge", outputs: { notificationClick: "notificationClick" }, ngImport: i0, template: `
678
+ <button class="notification-btn" (click)="onNotificationClick()" title="Notifications">
679
+ <span class="icon">🔔</span>
680
+ <span class="badge" *ngIf="unreadCount > 0">{{ unreadCount }}</span>
681
+ </button>
682
+ `, isInline: true, styles: [".notification-btn{position:relative;background:none;border:none;font-size:24px;cursor:pointer;padding:8px;transition:opacity .2s}.notification-btn:hover{opacity:.7}.icon{display:inline-block}.badge{position:absolute;top:0;right:0;background-color:#f44336;color:#fff;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: NotificationBadgeComponent, decorators: [{
684
+ type: Component,
685
+ args: [{ selector: 'ma-notification-badge', standalone: true, imports: [NgIf], template: `
686
+ <button class="notification-btn" (click)="onNotificationClick()" title="Notifications">
687
+ <span class="icon">🔔</span>
688
+ <span class="badge" *ngIf="unreadCount > 0">{{ unreadCount }}</span>
689
+ </button>
690
+ `, styles: [".notification-btn{position:relative;background:none;border:none;font-size:24px;cursor:pointer;padding:8px;transition:opacity .2s}.notification-btn:hover{opacity:.7}.icon{display:inline-block}.badge{position:absolute;top:0;right:0;background-color:#f44336;color:#fff;border-radius:50%;width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:700}\n"] }]
691
+ }], ctorParameters: function () { return [{ type: MesAuthService }]; }, propDecorators: { notificationClick: [{
692
+ type: Output
693
+ }] } });
694
+
695
+ /**
696
+ * Generated bundle index. Do not edit.
697
+ */
698
+
699
+ export { MaUserComponent, MesAuthInterceptor, MesAuthModule, MesAuthService, NotificationBadgeComponent, NotificationPanelComponent, NotificationType, ToastContainerComponent, UserProfileComponent };
700
+ //# sourceMappingURL=mesauth-angular.mjs.map