diff --git a/apps/red-ui/src/app/components/notifications/notifications.component.html b/apps/red-ui/src/app/components/notifications/notifications.component.html index ad7259a20..14b238b10 100644 --- a/apps/red-ui/src/app/components/notifications/notifications.component.html +++ b/apps/red-ui/src/app/components/notifications/notifications.component.html @@ -18,7 +18,7 @@
diff --git a/apps/red-ui/src/app/components/notifications/notifications.component.ts b/apps/red-ui/src/app/components/notifications/notifications.component.ts index ea129b453..305801583 100644 --- a/apps/red-ui/src/app/components/notifications/notifications.component.ts +++ b/apps/red-ui/src/app/components/notifications/notifications.component.ts @@ -1,37 +1,36 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +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 { firstValueFrom, Observable } from 'rxjs'; -import { shareLast } from '@iqser/common-ui'; -import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service'; +import { Observable } from 'rxjs'; +import { isToday, shareLast } from '@iqser/common-ui'; +import dayjs from 'dayjs'; interface NotificationsGroup { date: string; notifications: Notification[]; } +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'], - changeDetection: ChangeDetectionStrategy.OnPush, }) export class NotificationsComponent { readonly hasUnreadNotifications$: Observable; readonly groupedNotifications$: Observable; - constructor( - private readonly _notificationsService: NotificationsService, - private readonly _datePipe: DatePipe, - private readonly _dossiersCacheService: DossiersCacheService, - ) { - this.groupedNotifications$ = this._notificationsService.all$.pipe(map(notifications => this._groupNotifications(notifications))); - this.hasUnreadNotifications$ = this._hasUnreadNotifications$; + constructor(private readonly _notificationsService: NotificationsService, private readonly _datePipe: DatePipe) { + this.groupedNotifications$ = this._notificationsService.all$.pipe(map(notifications => this.#groupNotifications(notifications))); + this.hasUnreadNotifications$ = this.#hasUnreadNotifications$; } - private get _hasUnreadNotifications$(): Observable { + get #hasUnreadNotifications$(): Observable { return this._notificationsService.all$.pipe( map(notifications => notifications.filter(n => !n.readDate).length > 0), distinctUntilChanged(), @@ -41,29 +40,24 @@ export class NotificationsComponent { async markRead($event, notifications: Notification[] = this._notificationsService.all, isRead = true): Promise { $event.stopPropagation(); + if (!notifications.find(notification => !!notification.readDate !== isRead)) { // If no notification changes status after the request, abort return; } - await firstValueFrom( - this._notificationsService.toggleNotificationRead( - notifications.map(n => n.id), - isRead, - ), - ); + + const notificationsIds = notifications.map(n => n.id); + await this._notificationsService.toggleNotificationRead(notificationsIds, isRead); } - private _groupNotifications(notifications: Notification[]): NotificationsGroup[] { - const res = {}; - - for (const notification of notifications) { - const date = this._datePipe.transform(notification.creationDate, 'sophisticatedDate'); - if (!res[date]) { - res[date] = []; - } - res[date].push(notification); - } - - return Object.keys(res).map(key => ({ date: key, notifications: res[key] })); + #groupNotifications(notifications: Notification[]): NotificationsGroup[] { + const grouped = [ + ...notifications.groupBy(n => (isToday(n.creationDate) ? n.creationDate : n.creationDate.split('T')[0])).entries(), + ]; + const sorted = grouped.sort(([aDate], [bDate]) => chronologically(aDate, bDate)); + return sorted.map(([date, _notifications]) => ({ + date: this._datePipe.transform(date, 'sophisticatedDate'), + notifications: _notifications.sort((a, b) => chronologically(a.creationDate, b.creationDate)), + })); } } diff --git a/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts b/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts index 6284c47e4..315d9de5d 100644 --- a/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts +++ b/apps/red-ui/src/app/modules/shared/pipes/date.pipe.ts @@ -72,7 +72,7 @@ export class DatePipe extends BaseDatePipe implements PipeTransform { const isTodayFormat = date.isSame(new Date(), 'day'); if (isTodayFormat) { - return dayjs(date, ['h:mm A']).format('HH:mm'); + return dayjs(date, ['h:mm A']).format('hh:mm A'); } const isYesterdayFormat = date.isSame(yesterday, 'day'); diff --git a/apps/red-ui/src/app/services/notifications.service.ts b/apps/red-ui/src/app/services/notifications.service.ts index 2adbd489f..86d468ba5 100644 --- a/apps/red-ui/src/app/services/notifications.service.ts +++ b/apps/red-ui/src/app/services/notifications.service.ts @@ -1,7 +1,7 @@ import { Inject, Injectable } from '@angular/core'; import { BASE_HREF, EntitiesService, List, mapEach, QueryParam, RequiredParam, Validate } from '@iqser/common-ui'; import { TranslateService } from '@ngx-translate/core'; -import { EMPTY, iif, Observable, of, timer } from 'rxjs'; +import { EMPTY, firstValueFrom, iif, Observable, of, timer } from 'rxjs'; import { Dossier, INotification, Notification, NotificationTypes } from '@red/domain'; import { map, switchMap, tap } from 'rxjs/operators'; import { notificationsTranslations } from '@translations/notifications-translations'; @@ -45,13 +45,14 @@ export class NotificationsService extends EntitiesService { + async toggleNotificationRead(@RequiredParam() body: List, @RequiredParam() setRead: boolean) { let queryParam: QueryParam; if (setRead !== undefined && setRead !== null) { queryParam = { key: 'setRead', value: setRead }; } - return this._post(body, `${this._defaultModelPath}/toggle-read`, [queryParam]).pipe(switchMap(() => this.loadAll())); + await firstValueFrom(this._post(body, `${this._defaultModelPath}/toggle-read`, [queryParam])); + await firstValueFrom(this.loadAll()); } loadAll(includeSeen = INCLUDE_SEEN): Observable { diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index c2b4d2dfb..f4b69417a 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dev-04.iqser.cloud/redaction-gateway-v1", + "API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1", "APP_NAME": "RedactManager", "AUTO_READ_TIME": 3, "BACKEND_APP_VERSION": "4.4.40", @@ -11,7 +11,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dev-04.iqser.cloud/auth/realms/redaction", + "OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", diff --git a/libs/common-ui b/libs/common-ui index b8c3b76e5..9891c2bf6 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit b8c3b76e56ee888a93d62d7a8fd8fbcaec1a7153 +Subproject commit 9891c2bf67285a4e2a46fdeadd2999919e5dcaf4