RED-10583 - WIP on adding web sockets to be notified when there are backend updates for dossiers and files

This commit is contained in:
Valentin Mihai 2024-12-16 11:26:32 +02:00
parent 82552b1748
commit d3eaa66515
10 changed files with 40 additions and 36 deletions

View File

@ -123,7 +123,7 @@ export default class DossierOverviewScreenComponent extends ListingComponent<Fil
this.dossierTemplateId = this.#dossier.dossierTemplateId;
const hasRss = iqserPermissionsService.has(Roles.getRss);
this.workflowConfig = hasRss ? configService.workflowConfigRss() : configService.workflowConfig();
this.files$ = merge(this.#files$, this.#dossierFilesChange$).pipe(shareLast());
this.files$ = this.#files$.pipe(shareLast());
this.#updateFileAttributes();
}

View File

@ -2,9 +2,20 @@ import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angu
import { computed, effect, inject, Injectable, signal, Signal, WritableSignal } from '@angular/core';
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
import { LoadingService, wipeCache } from '@iqser/common-ui';
import { getParam } from '@iqser/common-ui/lib/utils';
import { getParam, log } from '@iqser/common-ui/lib/utils';
import { TranslateService } from '@ngx-translate/core';
import { Dictionary, Dossier, DOSSIER_ID, DOSSIER_TEMPLATE_ID, File, FILE_ID, ViewModes } from '@red/domain';
import {
Dictionary,
Dossier,
DOSSIER_ID,
DOSSIER_TEMPLATE_ID,
File,
FILE_ID,
FileEvent,
FileEventTypes,
ViewModes,
WsTopics,
} from '@red/domain';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
@ -14,9 +25,10 @@ import { FilesMapService } from '@services/files/files-map.service';
import { FilesService } from '@services/files/files.service';
import { PermissionsService } from '@services/permissions.service';
import { NGXLogger } from 'ngx-logger';
import { firstValueFrom, from, merge, Observable, of, pairwise, Subject, switchMap } from 'rxjs';
import { firstValueFrom, from, merge, Observable, of, pairwise, Subject, Subscription, switchMap } from 'rxjs';
import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators';
import { ViewModeService } from './view-mode.service';
import { WebSocketService } from '@services/web-socket.service';
const ONE_MEGABYTE = 1024 * 1024;
@ -60,6 +72,7 @@ export class FilePreviewStateService {
private readonly _loadingService: LoadingService,
private readonly _viewModeService: ViewModeService,
private readonly _logger: NGXLogger,
private readonly _webSocketService: WebSocketService,
) {
this.dossier = toSignal(dossiersServiceResolver().getEntityChanged$(this.dossierId));
this.file$ = inject(FilesMapService).watch$(this.dossierId, this.fileId);
@ -76,12 +89,17 @@ export class FilePreviewStateService {
this.blob$ = this.#blob$;
this.dossierDictionary = toSignal(inject(DossierDictionariesMapService).watch$(this.dossierId, 'dossier_redaction'));
this.#dossierFilesChange$
_webSocketService
.listen<FileEvent>(WsTopics.FILE)
.pipe(
log('[WS] file events'),
filter(event => event.fileEventType === FileEventTypes.UPDATE),
switchMap(() => this._filesService.loadAll(this.dossierId)),
takeUntilDestroyed(),
)
.subscribe();
effect(
() => {
if (this._viewModeService.isEarmarks() && !this.file().hasHighlights) {
@ -122,14 +140,6 @@ export class FilePreviewStateService {
);
}
get #dossierFilesChange$() {
return this._dossiersService.dossierFileChanges$.pipe(
map(changes => changes[this.dossierId]),
filter(fileIds => fileIds && fileIds.length > 0),
map(() => true),
);
}
reloadBlob(): void {
this.#reloadBlob$.next(true);
}

View File

@ -62,10 +62,6 @@ export class DossiersChangesService extends GenericService<Dossier> implements O
const subscription = timer(CHANGED_CHECK_INTERVAL, CHANGED_CHECK_INTERVAL).pipe(
filterEventsOnPages(this.#router),
switchMap(() => this.loadOnlyChanged()),
tap(changes => {
this.#activeDossiersService.emitFileChanges(changes);
this.#archivedDossiersService.emitFileChanges(changes);
}),
);
this.#subscription.add(subscription.subscribe());
}

View File

@ -47,23 +47,7 @@ export abstract class DossiersService extends EntitiesService<IDossier, Dossier>
);
}
updateDossier(dossier: Dossier): Observable<DossierStats[]> {
this.replace(dossier);
return this._dossierStatsService.getFor([dossier.id]);
}
updateDossiers(dossier: Dossier[]): void {
dossier.forEach(d => this.replace(d));
}
emitFileChanges(changes: IChangesDetails): void {
const changeModel: DossierFileChanges = {};
changes.fileChanges.forEach(change => {
if (!changeModel[change.dossierId]) {
changeModel[change.dossierId] = [];
}
changeModel[change.dossierId].push(change.fileId);
});
this.dossierFileChanges$.next(changeModel);
}
}

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { EntitiesService, isArray, QueryParam } from '@iqser/common-ui';
import { List, mapEach } from '@iqser/common-ui/lib/utils';
import { ApproveResponse, Dossier, DossierFileChanges, File, IFile } from '@red/domain';
import { ApproveResponse, DossierFileChanges, File, IFile } from '@red/domain';
import { UserService } from '@users/user.service';
import { NGXLogger } from 'ngx-logger';
import { firstValueFrom } from 'rxjs';

@ -1 +1 @@
Subproject commit fc8be33dc6d33642ae207b6ae4c17a6ec254d11a
Subproject commit 4ed7215292cb4d00c9c94b94ec1e6bf1182146bf

View File

@ -0,0 +1,11 @@
export const FileEventTypes = {
UPDATE: 'UPDATE',
} as const;
export type FileEventType = keyof typeof FileEventTypes;
export interface FileEvent {
dossierId: string;
fileId: string;
fileEventType: FileEventType;
}

View File

@ -1,2 +1,3 @@
export * from './analysis-event';
export * from './events/analysis-event';
export * from './events/file-event';
export * from './topics';

View File

@ -1,3 +1,5 @@
export const WsTopics = {
ANALYSIS: 'analysis-events',
FILE: 'file-events',
DOSSIER: 'dossier-events',
} as const;