-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Sams, Roland
authored and
Sams, Roland
committed
Oct 27, 2024
1 parent
b982d6b
commit a19eb18
Showing
5 changed files
with
173 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,148 +1,154 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { UserNotificationAPIService } from './api/user-notifications-api.service'; | ||
import { WebsocketService } from './api/websocket.service'; | ||
import { SubSink } from 'subsink'; | ||
import { UserNotification, UserNotificationType } from '../models/User-Notifications'; | ||
import { BehaviorSubject, map } from 'rxjs'; | ||
import { MenuItem } from 'primeng/api'; | ||
import { Termin } from '../models/Termin'; | ||
import { DatePipe } from '@angular/common'; | ||
import { Router } from '@angular/router'; | ||
import {Injectable} from '@angular/core'; | ||
import {UserNotificationAPIService} from './api/user-notifications-api.service'; | ||
import {WebsocketService} from './api/websocket.service'; | ||
import {SubSink} from 'subsink'; | ||
import {UserNotification, UserNotificationType} from '../models/User-Notifications'; | ||
import {BehaviorSubject, map} from 'rxjs'; | ||
import {MenuItem} from 'primeng/api'; | ||
import {Termin} from '../models/Termin'; | ||
import {DatePipe} from '@angular/common'; | ||
import {Router} from '@angular/router'; | ||
import dayjs from 'dayjs'; | ||
|
||
@Injectable({ | ||
providedIn: 'root', | ||
providedIn: 'root', | ||
}) | ||
export class UserNotificationService { | ||
private _userNotifications = new BehaviorSubject<UserNotification[]>([]); | ||
private _subs = new SubSink(); | ||
private _userNotifications = new BehaviorSubject<UserNotification[]>([]); | ||
private _subs = new SubSink(); | ||
|
||
public readonly userNotifications = this._userNotifications | ||
.asObservable() | ||
.pipe(map((notifications) => notifications.map((n) => this.mapNotificationToMenuItem(n)))); | ||
public readonly userNotifications = this._userNotifications | ||
.asObservable() | ||
.pipe(map((notifications) => notifications.map((n) => this.mapNotificationToMenuItem(n)))); | ||
|
||
constructor( | ||
private apiService: UserNotificationAPIService, | ||
private datePipe: DatePipe, | ||
private router: Router, | ||
webSocketService: WebsocketService | ||
) { | ||
this.getUnreadNotifications(); | ||
constructor( | ||
private apiService: UserNotificationAPIService, | ||
private datePipe: DatePipe, | ||
private router: Router, | ||
webSocketService: WebsocketService | ||
) { | ||
this.getUnreadNotifications(); | ||
|
||
this._subs.add( | ||
webSocketService.getUserNotificationsChannel().subscribe((notification: UserNotification) => { | ||
this.insertNotification(notification); | ||
}) | ||
); | ||
} | ||
this._subs.add( | ||
webSocketService.getUserNotificationsChannel().subscribe((notification: UserNotification) => { | ||
this.insertNotification(notification); | ||
}) | ||
); | ||
} | ||
|
||
public markAllAsRead(): void { | ||
this.apiService.markAllAsRead().subscribe(); | ||
} | ||
|
||
public addNotification(notification: UserNotification): void { | ||
this.insertNotification(notification); | ||
} | ||
public addNotification(notification: UserNotification): void { | ||
this.insertNotification(notification); | ||
} | ||
|
||
private insertNotification(notification: UserNotification): void { | ||
if (notification.created_at == null) { | ||
notification.created_at = dayjs().format('YYYY-MM-DD HH:mm:ss'); | ||
private insertNotification(notification: UserNotification): void { | ||
if (notification.created_at == null) { | ||
notification.created_at = dayjs().format('YYYY-MM-DD HH:mm:ss'); | ||
} | ||
const notifications = this._userNotifications.value; | ||
notifications.push(notification); | ||
notifications.sort((a, b) => { | ||
if (a.created_at < b.created_at) { | ||
return 1; | ||
} | ||
if (a.created_at > b.created_at) { | ||
return -1; | ||
} | ||
return 0; | ||
}); | ||
this._userNotifications.next(notifications); | ||
} | ||
const notifications = this._userNotifications.value; | ||
notifications.push(notification); | ||
notifications.sort((a, b) => { | ||
if (a.created_at < b.created_at) { | ||
return 1; | ||
} | ||
if (a.created_at > b.created_at) { | ||
return -1; | ||
} | ||
return 0; | ||
}); | ||
this._userNotifications.next(notifications); | ||
} | ||
|
||
private getUnreadNotifications(): void { | ||
this.apiService.getUnreadNotifications().subscribe((notifications) => { | ||
this._userNotifications.next(notifications); | ||
}); | ||
} | ||
private getUnreadNotifications(): void { | ||
this.apiService.getUnreadNotifications().subscribe((notifications) => { | ||
this._userNotifications.next(notifications); | ||
}); | ||
} | ||
|
||
private markAsRead(notification: UserNotification): void { | ||
console.log(notification); | ||
if (notification.type === UserNotificationType.SwUpdate || notification.type === UserNotificationType.TestSocket) { | ||
this.removeNotification(notification); | ||
return; | ||
private markAsRead(notification: UserNotification): void { | ||
if (notification.type === UserNotificationType.SwUpdate || notification.type === UserNotificationType.TestSocket) { | ||
this.removeNotification(notification); | ||
return; | ||
} | ||
this.apiService.markAsRead(notification.id).subscribe(() => { | ||
this.removeNotification(notification); | ||
}); | ||
} | ||
this.apiService.markAsRead(notification.id).subscribe(() => { | ||
this.removeNotification(notification); | ||
}); | ||
} | ||
|
||
private removeNotification(notification: UserNotification): void { | ||
const notifications = this._userNotifications.value.filter((n) => n.id !== notification.id); | ||
this._userNotifications.next(notifications); | ||
} | ||
private removeNotification(notification: UserNotification): void { | ||
const notifications = this._userNotifications.value.filter((n) => n.id !== notification.id); | ||
this._userNotifications.next(notifications); | ||
} | ||
|
||
private mapNotificationToMenuItem(notification: UserNotification): MenuItem { | ||
return { | ||
label: this.getLabel(notification), | ||
subLabel: this.getSubLabel(notification), | ||
icon: this.getIcon(notification), | ||
command: () => { | ||
this.markAsRead(notification); | ||
this.invokeCommand(notification); | ||
}, | ||
unread: notification.read_at == null, | ||
notification: notification, | ||
}; | ||
} | ||
private mapNotificationToMenuItem(notification: UserNotification): MenuItem { | ||
return { | ||
label: this.getLabel(notification), | ||
subLabel: this.getSubLabel(notification), | ||
icon: this.getIcon(notification), | ||
command: () => { | ||
this.markAsRead(notification); | ||
this.invokeCommand(notification); | ||
}, | ||
unread: notification.read_at == null, | ||
notification: notification, | ||
}; | ||
} | ||
|
||
private getLabel(notification: UserNotification): string { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminCreated: | ||
return 'Neuer Termin'; | ||
case UserNotificationType.TerminUpdated: | ||
return 'Termin aktualisiert'; | ||
case UserNotificationType.SwUpdate: | ||
return 'Update verfügbar'; | ||
default: | ||
return 'Sonstiges'; | ||
private getLabel(notification: UserNotification): string { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminCreated: | ||
return 'Neuer Termin'; | ||
case UserNotificationType.TerminUpdated: | ||
return 'Termin aktualisiert'; | ||
case UserNotificationType.SwUpdate: | ||
return 'Update verfügbar'; | ||
default: | ||
return 'Sonstiges'; | ||
} | ||
} | ||
} | ||
private getSubLabel(notification: UserNotification): string { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminCreated: | ||
const termin = notification.data as Termin; | ||
return termin?.name + ' ' + this.datePipe.transform(termin.vonDatum, 'd. MMMM YYYY'); | ||
case UserNotificationType.TerminUpdated: | ||
const updatedTermin = notification.data as Termin; | ||
return updatedTermin?.name + ' ' + this.datePipe.transform(updatedTermin.vonDatum, 'd. MMMM YYYY'); | ||
case UserNotificationType.SwUpdate: | ||
return 'Installieren?'; | ||
default: | ||
return 'Sonstiges'; | ||
|
||
private getSubLabel(notification: UserNotification): string { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminCreated: | ||
const termin = notification.data as Termin; | ||
return termin?.name + ' ' + this.datePipe.transform(termin.vonDatum, 'd. MMMM YYYY'); | ||
case UserNotificationType.TerminUpdated: | ||
const updatedTermin = notification.data as Termin; | ||
return updatedTermin?.name + ' ' + this.datePipe.transform(updatedTermin.vonDatum, 'd. MMMM YYYY'); | ||
case UserNotificationType.SwUpdate: | ||
return 'Installieren?'; | ||
default: | ||
return 'Sonstiges'; | ||
} | ||
} | ||
} | ||
private getIcon(notification: UserNotification): string { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminCreated: | ||
return 'pi pi-calendar-plus'; | ||
case UserNotificationType.TerminUpdated: | ||
return 'pi pi-refresh'; | ||
case UserNotificationType.SwUpdate: | ||
return 'pi pi-exclamation-triangle'; | ||
default: | ||
return ''; | ||
|
||
private getIcon(notification: UserNotification): string { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminCreated: | ||
return 'pi pi-calendar-plus'; | ||
case UserNotificationType.TerminUpdated: | ||
return 'pi pi-refresh'; | ||
case UserNotificationType.SwUpdate: | ||
return 'pi pi-exclamation-triangle'; | ||
default: | ||
return ''; | ||
} | ||
} | ||
} | ||
private invokeCommand(notification: UserNotification): void { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminUpdated: | ||
case UserNotificationType.TerminCreated: | ||
this.router.navigate(['/termine/details', (notification.data as Termin).id]); | ||
return; | ||
case UserNotificationType.SwUpdate: | ||
notification.command(); | ||
return; | ||
default: | ||
return void 0; | ||
|
||
private invokeCommand(notification: UserNotification): void { | ||
switch (notification.type) { | ||
case UserNotificationType.TerminUpdated: | ||
case UserNotificationType.TerminCreated: | ||
this.router.navigate(['/termine/details', (notification.data as Termin).id]); | ||
return; | ||
case UserNotificationType.SwUpdate: | ||
notification.command(); | ||
return; | ||
default: | ||
return void 0; | ||
} | ||
} | ||
} | ||
} |
41 changes: 24 additions & 17 deletions
41
src/app/utilities/mkj-user-notifications/mkj-user-notifications.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,28 @@ | ||
<i | ||
pBadge | ||
class="pi pi-bell text-2xl cursor-pointer" | ||
severity="warning" | ||
[value]="this.menuItems.length" | ||
[class.p-disabled]="this.menuItems.length === 0" | ||
[class.hide-badge]="this.menuItems.length === 0" | ||
(click)="this.menuItems.length ? notificationmenu.toggle($event) : null" | ||
pBadge | ||
class="pi pi-bell text-2xl cursor-pointer text-white" | ||
severity="warning" | ||
[value]="this.menuItems.length" | ||
[class.p-disabled]="this.menuItems.length === 0" | ||
[class.hide-badge]="this.menuItems.length === 0" | ||
(click)="this.menuItems.length ? notificationmenu.toggle($event) : null" | ||
></i> | ||
|
||
<p-menu #notificationmenu [model]="menuItems" [popup]="true"> | ||
<ng-template pTemplate="item" let-item> | ||
<div class="flex flex-column gap-2 p-menuitem-link flex align-items-center p-1"> | ||
<div class="flex gap-2"> | ||
<i [class]="item.icon"></i><span>{{ item.label }}</span> | ||
</div> | ||
<div class="opacity-80">{{ item.subLabel }}</div> | ||
<div></div> | ||
|
||
<p-overlayPanel #notificationmenu> | ||
<div class="mb-3"> | ||
<button pButton label="Alle gelesen" icon="mdi mdi-email-open-outline" | ||
class="p-button-outlined p-button-sm" (click)="markAllAsRead(); notificationmenu.hide()"></button> | ||
</div> | ||
</ng-template> | ||
</p-menu> | ||
<p-menu [model]="menuItems" [popup]="false"> | ||
<ng-template pTemplate="item" let-item> | ||
<div class="flex flex-column gap-2 p-menuitem-link align-items-center"> | ||
<div class="flex gap-2"> | ||
<i [class]="item.icon"></i><span>{{ item.label }}</span> | ||
</div> | ||
<div class="opacity-80">{{ item.subLabel }}</div> | ||
<div></div> | ||
</div> | ||
</ng-template> | ||
</p-menu> | ||
</p-overlayPanel> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters