80 lines
3.2 KiB
TypeScript
80 lines
3.2 KiB
TypeScript
import { Component } from '@angular/core';
|
|
import { DatePipe } from '@shared/pipes/date.pipe';
|
|
import { NotificationsService } from '@services/notifications.service';
|
|
import { Notification } from '@red/domain';
|
|
import { distinctUntilChanged, map } from 'rxjs/operators';
|
|
import { Observable } from 'rxjs';
|
|
import { isToday, shareLast, trackByFactory } from '@iqser/common-ui';
|
|
import dayjs, { Dayjs } from 'dayjs';
|
|
import { TranslateService } from '@ngx-translate/core';
|
|
|
|
interface NotificationsGroup {
|
|
date: string;
|
|
notifications: Notification[];
|
|
}
|
|
|
|
export function isOlderThan(date: string | Date | Dayjs, years: number) {
|
|
return dayjs(date).year() <= dayjs(Date.now()).subtract(years, 'year').year();
|
|
}
|
|
|
|
function chronologically(first: string, second: string) {
|
|
return dayjs(first).isAfter(second) ? -1 : 1;
|
|
}
|
|
|
|
@Component({
|
|
selector: 'redaction-notifications',
|
|
templateUrl: './notifications.component.html',
|
|
styleUrls: ['./notifications.component.scss'],
|
|
})
|
|
export class NotificationsComponent {
|
|
readonly hasUnreadNotifications$: Observable<boolean>;
|
|
readonly groupedNotifications$: Observable<NotificationsGroup[]>;
|
|
readonly trackBy = trackByFactory();
|
|
|
|
constructor(
|
|
private readonly _notificationsService: NotificationsService,
|
|
private readonly _datePipe: DatePipe,
|
|
private readonly _translateService: TranslateService,
|
|
) {
|
|
this.groupedNotifications$ = this._notificationsService.all$.pipe(map(notifications => this.#groupNotifications(notifications)));
|
|
this.hasUnreadNotifications$ = this.#hasUnreadNotifications$;
|
|
}
|
|
|
|
get #hasUnreadNotifications$(): Observable<boolean> {
|
|
return this._notificationsService.all$.pipe(
|
|
map(notifications => notifications.filter(n => !n.readDate).length > 0),
|
|
distinctUntilChanged(),
|
|
shareLast(),
|
|
);
|
|
}
|
|
|
|
async markRead(notifications: Notification[] = this._notificationsService.all, isRead = true): Promise<void> {
|
|
if (!notifications.find(notification => !!notification.readDate !== isRead)) {
|
|
// If no notification changes status after the request, abort
|
|
return;
|
|
}
|
|
|
|
const notificationsIds = notifications.map(n => n.id);
|
|
await this._notificationsService.toggleNotificationRead(notificationsIds, isRead);
|
|
}
|
|
|
|
#groupNotifications(notifications: Notification[]): NotificationsGroup[] {
|
|
const todayTranslation = this._translateService.instant('today');
|
|
const groupedMap = notifications.groupBy(n => {
|
|
if (isOlderThan(n.creationDate, 2)) {
|
|
return dayjs(n.creationDate).year().toString();
|
|
} else if (isOlderThan(n.creationDate, 1)) {
|
|
return dayjs(n.creationDate).format('YYYY-MM');
|
|
}
|
|
|
|
return n.creationDate.split('T')[0];
|
|
});
|
|
|
|
const sortedGroups = [...groupedMap.entries()].sort(([aDate], [bDate]) => chronologically(aDate, bDate));
|
|
return sortedGroups.map(([date, _notifications]) => ({
|
|
date: isToday(date) ? todayTranslation : this._datePipe.transform(date, 'sophisticatedDate'),
|
|
notifications: [..._notifications].sort((a, b) => chronologically(a.creationDate, b.creationDate)),
|
|
}));
|
|
}
|
|
}
|