RED-3796: Dossiers cache for notifications
This commit is contained in:
parent
e1be225c17
commit
3739e7a468
@ -12,6 +12,7 @@ import { FeaturesGuard } from '@guards/features-guard.service';
|
||||
import { ARCHIVE_ROUTE, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@utils/constants';
|
||||
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { DossierTemplateExistsGuard } from '@guards/dossier-template-exists.guard';
|
||||
import { DashboardGuard } from '@guards/dashboard-guard.service';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -41,7 +42,7 @@ const routes: Routes = [
|
||||
loadChildren: () => import('./modules/dashboard/dashboard.module').then(m => m.DashboardModule),
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard],
|
||||
requiredRoles: ['RED_USER', 'RED_MANAGER'],
|
||||
},
|
||||
},
|
||||
@ -75,7 +76,7 @@ const routes: Routes = [
|
||||
],
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DossierTemplateExistsGuard],
|
||||
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard, DossierTemplateExistsGuard],
|
||||
requiredRoles: ['RED_USER', 'RED_MANAGER'],
|
||||
},
|
||||
},
|
||||
|
||||
@ -5,6 +5,7 @@ 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';
|
||||
|
||||
interface NotificationsGroup {
|
||||
date: string;
|
||||
@ -21,7 +22,11 @@ export class NotificationsComponent {
|
||||
readonly hasUnreadNotifications$: Observable<boolean>;
|
||||
readonly groupedNotifications$: Observable<NotificationsGroup[]>;
|
||||
|
||||
constructor(private readonly _notificationsService: NotificationsService, private readonly _datePipe: DatePipe) {
|
||||
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$;
|
||||
}
|
||||
|
||||
@ -4,20 +4,15 @@ import { DashboardScreenComponent } from './dashboard-screen/dashboard-screen.co
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { TemplateStatsComponent } from './components/template-stats/template-stats.component';
|
||||
import { CompositeRouteGuard } from '@iqser/common-ui';
|
||||
import { SharedDossiersModule } from '../dossier/shared/shared-dossiers.module';
|
||||
import { BreadcrumbTypes } from '@red/domain';
|
||||
import { DossierTemplatesGuard } from '../../guards/dossier-templates.guard';
|
||||
import { DashboardGuard } from '../../guards/dashboard-guard.service';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '',
|
||||
component: DashboardScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
breadcrumbs: [BreadcrumbTypes.dashboard],
|
||||
routeGuards: [DossierTemplatesGuard, DashboardGuard],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
import { EventEmitter, Injectable } from '@angular/core';
|
||||
import { ActiveDossiersService } from './active-dossiers.service';
|
||||
import { ArchivedDossiersService } from './archived-dossiers.service';
|
||||
import { firstValueFrom, forkJoin, merge } from 'rxjs';
|
||||
import { map, skip, take } from 'rxjs/operators';
|
||||
import { flatten } from 'lodash-es';
|
||||
import { Dossier } from '@red/domain';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DossiersCacheService {
|
||||
readonly changed$ = new EventEmitter<void>();
|
||||
private _dossiers: Dossier[] = JSON.parse(localStorage.getItem('dossiers')) || [];
|
||||
|
||||
constructor(
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
) {
|
||||
// Skip 1 to avoid clearing the cache when the dossier services are initialized
|
||||
merge(_activeDossiersService.all$.pipe(skip(1)), _archivedDossiersService.all$.pipe(skip(1))).subscribe(() => {
|
||||
this.set();
|
||||
});
|
||||
}
|
||||
|
||||
get empty(): boolean {
|
||||
return !localStorage.getItem('dossiers');
|
||||
}
|
||||
|
||||
async load(): Promise<void> {
|
||||
await firstValueFrom(
|
||||
forkJoin([this._activeDossiersService.loadAll().pipe(take(1)), this._archivedDossiersService.loadAll().pipe(take(1))]).pipe(
|
||||
map(list => flatten(list)),
|
||||
),
|
||||
);
|
||||
this.set();
|
||||
}
|
||||
|
||||
set(): void {
|
||||
const dossiers = flatten([this._activeDossiersService.all, this._archivedDossiersService.all]);
|
||||
this._dossiers = dossiers;
|
||||
localStorage.setItem('dossiers', JSON.stringify(dossiers));
|
||||
this.changed$.emit();
|
||||
}
|
||||
|
||||
get(dossierId: string) {
|
||||
return this._dossiers.find(dossier => dossier.dossierId === dossierId);
|
||||
}
|
||||
}
|
||||
@ -6,12 +6,11 @@ import { Dossier, INotification, Notification, NotificationTypes } from '@red/do
|
||||
import { map, switchMap, tap } from 'rxjs/operators';
|
||||
import { notificationsTranslations } from '../translations/notifications-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ActiveDossiersService } from './dossiers/active-dossiers.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import dayjs from 'dayjs';
|
||||
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||
import { BASE_HREF } from '../tokens';
|
||||
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
|
||||
import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service';
|
||||
|
||||
const INCLUDE_SEEN = false;
|
||||
|
||||
@ -23,19 +22,22 @@ export class NotificationsService extends EntitiesService<Notification, INotific
|
||||
@Inject(BASE_HREF) private readonly _baseHref: string,
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _dossiersCacheService: DossiersCacheService,
|
||||
) {
|
||||
super(_injector, Notification, 'notification');
|
||||
|
||||
timer(0, CHANGED_CHECK_INTERVAL)
|
||||
.pipe(
|
||||
switchMap(() => (this._activeDossiersService.all.length ? of(null) : this._activeDossiersService.loadAll())),
|
||||
switchMap(() => (this._archivedDossiersService.all.length ? of(null) : this._archivedDossiersService.loadAll())),
|
||||
switchMap(() => (this._dossiersCacheService.empty ? this._dossiersCacheService.load() : of(null))),
|
||||
switchMap(() => this.#loadNotificationsIfChanged()),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
// Rebuild notifications when cached dossiers are updated
|
||||
this._dossiersCacheService.changed$.subscribe(() => {
|
||||
this.setEntities(this.all.map(e => this._new(e)));
|
||||
});
|
||||
}
|
||||
|
||||
@Validate()
|
||||
@ -75,7 +77,7 @@ export class NotificationsService extends EntitiesService<Notification, INotific
|
||||
private _translate(notification: INotification, translation: string): string {
|
||||
const fileId = notification.target.fileId;
|
||||
const dossierId = notification.target.dossierId;
|
||||
const dossier = this._activeDossiersService.find(dossierId) || this._archivedDossiersService.find(dossierId);
|
||||
const dossier = this._dossiersCacheService.get(dossierId);
|
||||
const fileName = notification.target.fileName;
|
||||
|
||||
return this._translateService.instant(translation, {
|
||||
|
||||
@ -23,6 +23,8 @@ export class Dossier implements IDossier, IListable {
|
||||
readonly watermarkPreviewEnabled: boolean;
|
||||
readonly archivedTime: string;
|
||||
readonly hasReviewers: boolean;
|
||||
readonly routerLink: string;
|
||||
readonly dossiersListRouterLink: string;
|
||||
|
||||
constructor(dossier: IDossier) {
|
||||
this.dossierId = dossier.dossierId;
|
||||
@ -44,21 +46,16 @@ export class Dossier implements IDossier, IListable {
|
||||
this.watermarkPreviewEnabled = dossier.watermarkPreviewEnabled;
|
||||
this.archivedTime = dossier.archivedTime;
|
||||
this.hasReviewers = !!this.memberIds && this.memberIds.length > 1;
|
||||
|
||||
const routerPath = (this.isArchived ? ARCHIVE_ROUTE : DOSSIERS_ROUTE) as string;
|
||||
this.dossiersListRouterLink = `/main/${this.dossierTemplateId}/${routerPath}`;
|
||||
this.routerLink = `${this.dossiersListRouterLink}/${this.dossierId}`;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this.dossierId;
|
||||
}
|
||||
|
||||
get routerLink(): string {
|
||||
return `${this.dossiersListRouterLink}/${this.dossierId}`;
|
||||
}
|
||||
|
||||
get dossiersListRouterLink(): string {
|
||||
const routerPath = this.isArchived ? ARCHIVE_ROUTE : DOSSIERS_ROUTE;
|
||||
return `/main/${this.dossierTemplateId}/${routerPath}`;
|
||||
}
|
||||
|
||||
get searchKey(): string {
|
||||
return this.dossierName;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user