diff --git a/src/app/features/notification/model/notification-config.ts b/src/app/features/notification/model/notification-config.ts new file mode 100644 index 0000000000..f861a5e698 --- /dev/null +++ b/src/app/features/notification/model/notification-config.ts @@ -0,0 +1,28 @@ +import { Entity } from "../../../core/entity/model/entity"; +import { DatabaseField } from "../../../core/entity/database-field.decorator"; +import { DatabaseEntity } from "../../../core/entity/database-entity.decorator"; + +/** + * This represents one specific notification config for one specific user, + */ +@DatabaseEntity("NotificationConfig") +export class NotificationConfig extends Entity { + @DatabaseField() channels: { [key: string]: boolean }; + + @DatabaseField() notificationTypes: NotificationType[]; + + constructor(id = null) { + super(id); + } +} + +/** + * Represents a specific notification type configuration. + */ +export class NotificationType { + @DatabaseField() notificationType: string; + @DatabaseField() enabled: boolean; + @DatabaseField() channels: { [key: string]: boolean }; + @DatabaseField() entityType: string; + @DatabaseField() conditions: any; +} diff --git a/src/app/features/notification/notification.component.html b/src/app/features/notification/notification.component.html index a244fbf76c..d53f93db97 100644 --- a/src/app/features/notification/notification.component.html +++ b/src/app/features/notification/notification.component.html @@ -67,7 +67,6 @@

Notifications

-
(); public selectedTab = 0; public hasNotificationEnabled = false; + protected readonly closeOnlySubmenu = closeOnlySubmenu; constructor( private entityMapper: EntityMapperService, - private mockNotificationsService: MockNotificationsService, private sessionInfo: SessionSubject, + private alertService: AlertService, ) {} ngOnInit(): void { + this.notificationsSubject.subscribe((notifications) => { + this.filterUserNotifications(notifications); + }); + this.loadAndProcessNotifications(); } @@ -52,26 +59,37 @@ export class NotificationComponent implements OnInit { * Loads all notifications and processes them to update the list and unread count. */ private async loadAndProcessNotifications(): Promise { - // TODO: Need to uncomment this after the notification list UI testing is completed. - // const notifications = - // await this.entityMapper.loadType(NotificationEvent); - - // TODO: Need to remove this line once the notification list UI tests are completed. const notifications = - this.mockNotificationsService.getNotifications() as unknown as NotificationEvent[]; + await this.entityMapper.loadType(NotificationEvent); + const user = this.sessionInfo.value?.id; + + const notificationConfig = await this.loadNotificationConfig(user); + this.hasNotificationEnabled = notificationConfig?.channels.push ?? false; - // The user is hardcoded for testing purposes, need to remove this. - this.filterUserNotifications(notifications); + this.notificationsSubject.next(notifications); + } + + /** + * Loads the user's notification configuration. + */ + private async loadNotificationConfig( + user: string, + ): Promise { + try { + return await this.entityMapper.load( + NotificationConfig, + user, + ); + } catch (error) { + return null; + } } /** - * Filters notifications based on the sender. - * @param notifications - The list of notifications. - * @param user - The user to filter notifications. + * Filters notifications based on the sender and read status. */ private filterUserNotifications(notifications: NotificationEvent[]) { const user = this.sessionInfo.value?.id; - this.allNotifications = notifications.filter( (notification) => notification.sentBy === user, ); @@ -81,34 +99,75 @@ export class NotificationComponent implements OnInit { ); } - markAllRead() { - // TODO: Implement the logic to mark all notifications as read. - Logging.log("All notifications marked as read"); + /** + * Marks all notifications as read. + */ + async markAllRead(): Promise { + const unreadNotifications = this.allNotifications.filter( + (notification) => !notification.readStatus, + ); + await this.updateReadStatusForNotifications(unreadNotifications, true); + } + + /** + * Toggles the notification setting for the user. + */ + async enableNotificationForUser(): Promise { + this.hasNotificationEnabled = !this.hasNotificationEnabled; + const user = this.sessionInfo.value?.id; + + const notificationConfig = await this.loadNotificationConfig(user); + const notificationChannels = { + push: this.hasNotificationEnabled, + email: false, + }; + + if (notificationConfig) { + notificationConfig.channels = notificationChannels; + await this.entityMapper.save(notificationConfig); + } else { + const newNotificationConfig = new NotificationConfig(user); + newNotificationConfig.channels = notificationChannels; + await this.entityMapper.save(newNotificationConfig); + } + + this.alertService.addInfo( + `Notification ${this.hasNotificationEnabled ? "enabled" : "disabled"}.`, + ); } - enableNotificationForUser() { - // TODO: Need to implement the logic so that the notification is enabled corresponding to the user. - Logging.log("Notification enabled"); + /** + * Updates the read status for multiple notifications. + */ + private async updateReadStatusForNotifications( + notifications: NotificationEvent[], + newStatus: boolean, + ): Promise { + for (const notification of notifications) { + notification.readStatus = newStatus; + await this.entityMapper.save(notification); + } + this.filterUserNotifications(this.allNotifications); } - async updateReadStatus(notification: NotificationEvent, newStatus: boolean) { + /** + * Updates the read status of a single notification. + */ + async updateReadStatus( + notification: NotificationEvent, + newStatus: boolean, + ): Promise { notification.readStatus = newStatus; await this.entityMapper.save(notification); this.filterUserNotifications(this.allNotifications); } - deleteNotification(notification: NotificationEvent) { - // Need to add/update this logic to delete the notification from the CouchDB - this.allNotifications = this.allNotifications.filter( - (n) => n !== notification, - ); - this.unreadNotifications = this.unreadNotifications.filter( - (n) => n !== notification, - ); - Logging.log("Notification deleted"); - - this.filterUserNotifications(this.allNotifications); + /** + * Deletes a user notification. + */ + async deleteNotification(notification: NotificationEvent): Promise { + await this.entityMapper.remove(notification); + this.alertService.addInfo("Notification deleted successfully"); + this.loadAndProcessNotifications(); } - - protected readonly closeOnlySubmenu = closeOnlySubmenu; }