improved notifs

This commit is contained in:
Timo Bejan 2021-08-16 17:43:11 +03:00
parent fe557f8674
commit dd1526bf85
4 changed files with 83 additions and 24 deletions

View File

@ -1,9 +1,10 @@
<iqser-circle-button [matMenuTriggerFor]="overlay" [showDot]="!!notifications?.length" icon="red:notification"></iqser-circle-button>
<iqser-circle-button [matMenuTriggerFor]="overlay" [showDot]="hasUnreadNotifications" icon="red:notification"></iqser-circle-button>
<mat-menu #overlay="matMenu" backdropClass="notifications-backdrop" class="notifications-menu" xPosition="before">
<div *ngFor="let group of groupedNotifications">
<div class="all-caps-label">{{ group.dateString }}</div>
<div
*ngFor="let notification of group.notifications | sortBy: 'desc':'creationDate'"
(click)="markRead(notification, $event)"
[class.unread]="!notification.readDate"
class="notification"
mat-menu-item
@ -14,7 +15,7 @@
<div class="small-label mt-2">{{ getTime(notification.creationDate) }}</div>
</div>
<div
(click)="toggleRead(notification, $event)"
(click)="markRead(notification, $event, !notification.readDate)"
[matTooltip]="(notification.readDate ? 'notifications.mark-unread' : 'notifications.mark-read') | translate"
class="dot"
matTooltipPosition="before"

View File

@ -3,6 +3,9 @@ import * as moment from 'moment';
import { TranslateService } from '@ngx-translate/core';
import { NotificationControllerService, Notification, NotificationResponse } from '@redaction/red-ui-http';
import { DatePipe } from '@shared/pipes/date.pipe';
import { AppStateService } from '@state/app-state.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { UserService } from '@services/user.service';
enum NotificationType {
ASSIGN_REVIEWER = 'ASSIGN_REVIEWER',
@ -17,9 +20,6 @@ enum NotificationType {
USER_DEGRADED_TO_REVIEWER = 'USER_DEGRADED_TO_REVIEWER',
DOSSIER_OWNER_DELETED = 'DOSSIER_OWNER_DELETED'
}
// For each you have a different set of target Ids - I.E. a projectId, fileId or userId of the user who did the action
// we need to create some templated i18n message which also include links
// to the file or project that was affected ( see mock notifications )
@Component({
selector: 'redaction-notifications',
@ -31,16 +31,22 @@ export class NotificationsComponent {
groupedNotifications: { dateString: string; notifications: Notification[] }[] = [];
constructor(
private _translateService: TranslateService,
private _notificationControllerService: NotificationControllerService,
private readonly _translateService: TranslateService,
private readonly _userService: UserService,
private readonly _notificationControllerService: NotificationControllerService,
private readonly _appStateService: AppStateService,
private readonly _datePipe: DatePipe
) {
this._notificationControllerService.getNotifications(false).subscribe((response: NotificationResponse) => {
this.notifications = response.notifications;
this.notifications = response.notifications.filter(notification => this._isSupportedType(notification));
this._groupNotifications(this.notifications);
});
}
get hasUnreadNotifications() {
return this.notifications?.filter(n => !n.readDate).length > 0;
}
getTime(date: string): string {
moment.locale(this._translateService.currentLang);
return moment(date).format('hh:mm A');
@ -49,26 +55,39 @@ export class NotificationsComponent {
getNotificationMessage(notification: Notification) {
switch (notification.notificationType) {
case NotificationType.ASSIGN_REVIEWER:
return this._translate(notification, 'notification.assign-reviewer');
return this._translate(notification, _('notification.assign-reviewer'));
case NotificationType.ASSIGN_APPROVER:
return this._translate(notification, 'notification.assign-approver');
return this._translate(notification, _('notification.assign-approver'));
case NotificationType.DOCUMENT_APPROVED:
return this._translate(notification, _('notification.document-approved'));
case NotificationType.UNASSIGNED_FROM_FILE:
return this._translate(notification, 'notification.unassigned-from-file');
return this._translate(notification, _('notification.unassigned-from-file'));
case NotificationType.DOSSIER_OWNER_SET:
return this._translate(notification, _('notification.dossier-owner-set'));
case NotificationType.DOSSIER_OWNER_REMOVED:
return this._translate(notification, _('notification.dossier-owner-removed'));
case NotificationType.DOSSIER_OWNER_DELETED:
return this._translate(notification, _('notification.dossier-owner-deleted'));
case NotificationType.USER_BECOMES_DOSSIER_MEMBER:
return this._translate(notification, _('notification.user-becomes-dossier-member'));
case NotificationType.USER_REMOVED_AS_DOSSIER_MEMBER:
return this._translate(notification, _('notification.user-removed-as-dossier-member'));
case NotificationType.USER_PROMOTED_TO_APPROVER:
return this._translate(notification, _('notification.user-promoted-to-approver'));
case NotificationType.USER_DEGRADED_TO_REVIEWER:
return this._translate(notification, _('notification.user-denoted-to-reviewer'));
default:
return '';
}
}
toggleRead(notification: Notification, $event) {
$event.stopPropagation();
notification.readDate = !notification.readDate ? moment().format('YYYY-MM-DDTHH:mm:ss Z') : null;
const ids = [notification.notificationId];
const isRead = !!notification.readDate;
this._notificationControllerService.toggleNotificationRead(ids, isRead);
private _isSupportedType(notification: Notification) {
return Object.values(<any>NotificationType).includes(notification.notificationType);
}
private _getDossierHref(dossierId: string) {
return `main/dossiers/${dossierId}`;
return `/ui/main/dossiers/${dossierId}`;
}
private _getFileHref(dossierId: string, fileId: string) {
@ -81,7 +100,10 @@ export class NotificationsComponent {
const dossierId = notification.target.dossierId;
return this._translateService.instant(translation, {
fileHref: this._getFileHref(dossierId, fileId),
dossierHref: this._getDossierHref(dossierId)
dossierHref: this._getDossierHref(dossierId),
dossierName: this._getDossierName(notification.target?.dossierId),
fileName: this._getFileName(notification.target?.dossierId, notification.target?.fileId),
user: this._getUsername(notification.userId)
});
}
@ -97,4 +119,29 @@ export class NotificationsComponent {
}
this.groupedNotifications = this.groupedNotifications.reverse();
}
async markRead(notification: Notification, $event, isRead: boolean = true) {
$event.stopPropagation();
const ids = [notification.notificationId];
await this._notificationControllerService.toggleNotificationRead(ids, isRead).toPromise();
if (isRead) {
notification.readDate = moment().format('YYYY-MM-DDTHH:mm:ss Z');
} else {
notification.readDate = null;
}
}
private _getDossierName(dossierId: string | undefined) {
const dossier = this._appStateService.getDossierById(dossierId);
return dossier?.dossierName || this._translateService.instant(_('dossier'));
}
private _getFileName(dossierId: string | undefined, fileId: string | undefined) {
const file = this._appStateService.getFileById(dossierId, fileId);
return file?.filename || this._translateService.instant(_('file'));
}
private _getUsername(userId: string | undefined) {
return this._userService.getNameForId(userId) || this._translateService.instant(_('unknown'));
}
}

View File

@ -277,7 +277,7 @@ export class AppStateService {
return;
}
await this.updateDossierDictionary(this.activeDossier.dossierTemplateId, dossierId);
this.updateDossierDictionary(this.activeDossier.dossierTemplateId, dossierId);
}
async updateDossierDictionary(dossierTemplateId: string, dossierId: string) {

View File

@ -337,6 +337,9 @@
"title": "Confirm Action"
}
},
"unknown": "Unknown",
"dossier": "Dossier",
"file": "File",
"configurations": "Configurations",
"confirm-delete-file-attribute": {
"cancel": "Keep {type, select, single{Attribute} bulk{Attributes} other{}}",
@ -1026,7 +1029,7 @@
},
"filters": {
"assigned-people": "Assignee(s)",
"dossier-templates": "Rule Sets",
"dossier-templates": "Dossier Templates",
"filter-by": "Filter:",
"needs-work": "Workload",
"people": "Dossier Member(s)",
@ -1169,9 +1172,17 @@
"sep": "Sep."
},
"notification": {
"assign-approver": "You have been assigned as approver for <b><a href=\"{fileHref}\" target=\"_blank\">file</a></b> in the <b><a href=\"{dossierHref}\" target=\"_blank\">dossier</a><b>!",
"assign-reviewer": "You have been assigned as reviewer for <b><a href=\"{fileHref}\" target=\"_blank\">file</a></b> in the <b><a href=\"{dossierHref}\" target=\"_blank\">dossier</a><b>!",
"unassigned-from-file": "You have been unassigned from <b><a href=\"{fileHref}\" target=\"_blank\">file</a></b> in the <b><a href=\"{dossierHref}\" target=\"_blank\">dossier</a><b>!"
"assign-approver": "You have been assigned as approver for <b><a href=\"{fileHref}\" target=\"_blank\">{fileName}</a></b> in the <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a><b>!",
"assign-reviewer": "You have been assigned as reviewer for <b><a href=\"{fileHref}\" target=\"_blank\">{fileName}</a></b> in the <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a><b>!",
"unassigned-from-file": "You have been unassigned from <b><a href=\"{fileHref}\" target=\"_blank\">{fileName}</a></b> in the <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a><b>!",
"document-approved": " <b><a href=\"{fileHref}\" target=\"_blank\">{fileName}</a></b> has been approved!",
"dossier-owner-set": " <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b> owner changed to <b>{user}</b>!",
"dossier-owner-removed": "<b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b> owner removed!",
"dossier-owner-deleted": "<b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b> owner removed!",
"user-becomes-dossier-member": "<b>{user}</b> joined dossier: <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b>!",
"user-removed-as-dossier-member": "<b>{user}</b> removed as a member of: <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b> !",
"user-promoted-to-approver": "<b>{user}</b> promoted to approver in dossier: <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b>!",
"user-denoted-to-reviewer": "<b>{user}</b> denoted to reviewer in dossier: <b><a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a></b>!"
},
"notifications": {
"mark-read": "Mark as read",