improved notifs
This commit is contained in:
parent
fe557f8674
commit
dd1526bf85
@ -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"
|
||||
|
||||
@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user