Completed notification functionality

Minor code cleanup
This commit is contained in:
Isaac Abadi
2022-11-25 17:47:30 -05:00
parent 4583e3e5d4
commit b51f45c704
17 changed files with 232 additions and 99 deletions

View File

@@ -0,0 +1,17 @@
<div *ngFor="let notification of notifications; let i = index;">
<mat-divider class="notification-divider"></mat-divider>
<div style="display: inline-block">
<ng-container *ngIf="NOTIFICATION_PREFIX[notification.type]">
{{NOTIFICATION_PREFIX[notification.type]}}&nbsp;
</ng-container>
<ng-container *ngIf="NOTIFICATION_SUFFIX_KEY[notification.type]">
{{notification['data'][NOTIFICATION_SUFFIX_KEY[notification.type]]}}
</ng-container>
</div>
<div style="margin-left: 10px; float: right;" *ngIf="notification.actions?.length > 0">
<button (click)="emitDeleteNotification(notification.uid)" mat-icon-button><mat-icon>close</mat-icon></button>
<span *ngFor="let action of notification.actions">
<button [matTooltip]="NOTIFICATION_ACTION_TO_STRING[action]" (click)="emitNotificationAction(notification)" mat-icon-button><mat-icon>{{NOTIFICATION_ICON[action]}}</mat-icon></button>
</span>
</div>
</div>

View File

@@ -0,0 +1,4 @@
.notification-divider {
margin-bottom: 10px;
margin-top: 10px;
}

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { NotificationsListComponent } from './notifications-list.component';
describe('NotificationsListComponent', () => {
let component: NotificationsListComponent;
let fixture: ComponentFixture<NotificationsListComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ NotificationsListComponent ]
})
.compileComponents();
fixture = TestBed.createComponent(NotificationsListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,52 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { Notification } from 'api-types';
import { NotificationAction } from 'api-types/models/NotificationAction';
import { NotificationType } from 'api-types/models/NotificationType';
@Component({
selector: 'app-notifications-list',
templateUrl: './notifications-list.component.html',
styleUrls: ['./notifications-list.component.scss']
})
export class NotificationsListComponent {
@Input() notifications = null;
@Output() deleteNotification = new EventEmitter<string>();
@Output() notificationAction = new EventEmitter<{notification: Notification, action: NotificationAction}>();
NOTIFICATION_PREFIX: { [key in NotificationType]: string } = {
download_complete: $localize`Finished downloading:`,
download_error: $localize`Download failed:`
}
// Attaches string to the end of the notification text
NOTIFICATION_SUFFIX_KEY: { [key in NotificationType]: string } = {
download_complete: 'file_title',
download_error: 'file_url'
}
NOTIFICATION_ACTION_TO_STRING: { [key in NotificationAction]: string } = {
play: $localize`Play`,
retry_download: $localize`Retry download`,
view_download_error: $localize`View error`
}
NOTIFICATION_COLOR: { [key in NotificationAction]: string } = {
play: 'primary',
retry_download: 'primary',
view_download_error: 'warn'
}
NOTIFICATION_ICON: { [key in NotificationAction]: string } = {
play: 'smart_display',
retry_download: 'restart_alt',
view_download_error: 'warning'
}
emitNotificationAction(notification: Notification, action: NotificationAction): void {
this.notificationAction.emit({notification: notification, action: action});
}
emitDeleteNotification(uid: string): void {
this.deleteNotification.emit(uid);
}
}

View File

@@ -1,8 +1,3 @@
.notification-divider {
margin-bottom: 10px;
margin-top: 10px;
}
.notification-title {
margin-bottom: 6px;
text-align: center

View File

@@ -1,32 +1,10 @@
<h4 *ngIf="notifications !== null && notifications.length === 0 && read_notifications.length === 0" style="text-align: center; margin: 10px;">No notifications available</h4>
<h4 *ngIf="notifications !== null && notifications.length === 0 && read_notifications.length === 0" style="text-align: center; margin: 10px;" i18n="No notifications available">No notifications available</h4>
<div style="margin: 10px;" *ngIf="notifications?.length > 0">
<h4 class="notification-title">New notifications</h4>
<div *ngFor="let notification of appService.notifications; let i = index;">
<mat-divider class="notification-divider"></mat-divider>
<div style="display: inline-block;">
<button (click)="deleteNotification(notification.id, i, false)" mat-icon-button><mat-icon>close</mat-icon></button>
</div>
<div style="display: inline-block">
{{notification.title}}
</div>
<div style="margin-left: 10px; float: right;" *ngIf="notification.action">
<button (click)="notificationAction(notification)" [color]="notification.action.warn ? 'warn' : 'primary'" mat-raised-button>{{notification.action.title}}</button>
</div>
</div>
<h4 class="notification-title" i18n="New notifications">New notifications</h4>
<app-notifications-list (notificationAction)="notificationAction($event)" (deleteNotification)="deleteNotification($event)" [notifications]="notifications"></app-notifications-list>
</div>
<div style="margin: 10px;" *ngIf="read_notifications?.length > 0">
<h4 class="notification-title">Old notifications</h4>
<div *ngFor="let notification of appService.read_notifications; let i = index">
<mat-divider class="notification-divider"></mat-divider>
<div style="display: inline-block;">
<button (click)="deleteNotification(notification.id, i, true)" mat-icon-button><mat-icon>close</mat-icon></button>
</div>
<div style="display: inline-block">
{{notification.title}}
</div>
<div style="margin-left: 10px; float: right" *ngIf="notification.action">
<button (click)="notificationAction(notification)" [color]="notification.action.warn ? 'warn' : 'primary'" mat-raised-button>{{notification.action.title}}</button>
</div>
</div>
<h4 class="notification-title" i18n="Old notifications">Old notifications</h4>
<app-notifications-list (notificationAction)="notificationAction($event)" (deleteNotification)="deleteNotification($event)" [notifications]="read_notifications"></app-notifications-list>
</div>

View File

@@ -1,11 +1,9 @@
import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { MatMenu, MatMenuTrigger } from '@angular/material/menu';
import { MatMenuTrigger } from '@angular/material/menu';
import { Router } from '@angular/router';
import { PostsService } from 'app/posts.services';
import { Notification } from 'api-types';
// TODO: fill this out
const NOTIFICATION_ACTION_TO_STRING = {}
import { NotificationAction } from 'api-types/models/NotificationAction';
@Component({
selector: 'app-notifications',
@@ -17,7 +15,6 @@ export class NotificationsComponent implements OnInit {
notifications = null;
read_notifications = null;
@Input() menu: MatMenuTrigger;
@Output() notificationCount = new EventEmitter<number>();
constructor(public postsService: PostsService, private router: Router, private elRef: ElementRef) { }
@@ -37,21 +34,35 @@ export class NotificationsComponent implements OnInit {
getNotifications(): void {
this.postsService.getNotifications().subscribe(res => {
this.notifications = res['notifications'].filter(notification => notification.read == false);
this.read_notifications = res['notifications'].filter(notification => notification.read == true);
this.notifications = res['notifications'].filter(notification => !notification.read);
this.read_notifications = res['notifications'].filter(notification => notification.read);
this.notificationCount.emit(this.notifications.length);
});
}
notificationAction(notification: Notification): void {
// TODO: implement
notificationAction(action_info: {notification: Notification, action: NotificationAction}): void {
switch (action_info['action']) {
case NotificationAction.PLAY:
this.router.navigate(['player', {uid: action_info['notification']['data']['file_uid']}]);
break;
case NotificationAction.VIEW_DOWNLOAD_ERROR:
this.router.navigate(['downloads']);
break;
case NotificationAction.RETRY_DOWNLOAD:
this.postsService.restartDownload(action_info['notification']['data']['download_uid'])
break;
default:
console.error(`Notification action ${action_info['action']} does not exist!`);
break;
}
}
deleteNotification(uid: string, index: number): void {
deleteNotification(uid: string): void {
this.postsService.deleteNotification(uid).subscribe(res => {
console.log(res);
// TODO: remove from array
this.notifications.filter(notification => notification['uid'] !== uid);
this.read_notifications.filter(read_notification => read_notification['uid'] !== uid);
this.notificationCount.emit(this.notifications.length);
this.getNotifications();
});
}
@@ -73,4 +84,10 @@ export class NotificationsComponent implements OnInit {
this.notificationCount.emit(0);
}
notificationMenuClosed(): void {
if (this.notifications.length > 0) {
this.setNotificationsToRead();
}
}
}