Merge branch 'master' into VM/RED-2614
This commit is contained in:
commit
d8af3d687a
@ -1,3 +1,4 @@
|
||||
<router-outlet></router-outlet>
|
||||
<iqser-full-page-loading-indicator></iqser-full-page-loading-indicator>
|
||||
<iqser-connection-status></iqser-connection-status>
|
||||
<iqser-full-page-error></iqser-full-page-error>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Debounce, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -38,6 +38,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _rulesService: RulesService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _toaster: Toaster,
|
||||
protected readonly _translateService: TranslateService,
|
||||
@ -74,6 +75,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit
|
||||
},
|
||||
});
|
||||
(window as any).monaco.editor.setTheme('redaction');
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
|
||||
@Debounce()
|
||||
@ -106,6 +108,7 @@ export class RulesScreenComponent extends ComponentHasChanges implements OnInit
|
||||
revert(): void {
|
||||
this.currentLines = this.initialLines;
|
||||
this._decorations = this._codeEditor?.deltaDecorations(this._decorations, []) || [];
|
||||
this._changeDetectorRef.detectChanges();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
|
||||
@ -100,7 +100,7 @@
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
|
||||
</section>
|
||||
|
||||
<ng-template #reportTemplateOptionTemplate let-option="option">
|
||||
|
||||
@ -15,19 +15,19 @@ import { FileDropOverlayService } from '@upload-download/services/file-drop-over
|
||||
import { FileUploadModel } from '@upload-download/model/file-upload.model';
|
||||
import { FileUploadService } from '@upload-download/services/file-upload.service';
|
||||
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
|
||||
import * as moment from 'moment';
|
||||
import { Observable, timer } from 'rxjs';
|
||||
import { Observable, Subscription } from 'rxjs';
|
||||
import { filter, skip, switchMap, tap } from 'rxjs/operators';
|
||||
import { convertFiles, Files, handleFileDrop } from '@utils/index';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
CustomError,
|
||||
DefaultListingServices,
|
||||
ErrorService,
|
||||
ListingComponent,
|
||||
ListingModes,
|
||||
LoadingService,
|
||||
NestedFilter,
|
||||
OnAttach,
|
||||
OnDetach,
|
||||
TableColumnConfig,
|
||||
TableComponent,
|
||||
WorkflowConfig,
|
||||
@ -45,7 +45,7 @@ import { LongPressEvent } from '@shared/directives/long-press.directive';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-overview-screen.component.html',
|
||||
@ -53,7 +53,7 @@ import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DossierOverviewScreenComponent) }],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierOverviewScreenComponent extends ListingComponent<File> implements OnInit, OnDestroy, OnDetach, OnAttach {
|
||||
export class DossierOverviewScreenComponent extends ListingComponent<File> implements OnInit, OnDestroy, OnAttach {
|
||||
readonly listingModes = ListingModes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
|
||||
@ -74,6 +74,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
@ViewChild('fileInput', { static: true }) private readonly _fileInput: ElementRef;
|
||||
@ViewChild(TableComponent) private readonly _tableComponent: TableComponent<Dossier>;
|
||||
private _fileAttributeConfigs: IFileAttributeConfig[];
|
||||
private readonly _removableSubscriptions = new Subscription();
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
@ -81,6 +82,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _dossierStatsService: DossierStatsService,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _fileUploadService: FileUploadService,
|
||||
@ -92,6 +94,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
readonly configService: ConfigService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _fileMapService: FilesMapService,
|
||||
private readonly _errorService: ErrorService,
|
||||
activatedRoute: ActivatedRoute,
|
||||
) {
|
||||
super(_injector);
|
||||
@ -128,18 +131,17 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
|
||||
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
|
||||
|
||||
this.addSubscription = timer(CHANGED_CHECK_INTERVAL, CHANGED_CHECK_INTERVAL)
|
||||
.pipe(
|
||||
switchMap(() => this._filesService.hasChanges$(this.dossierId)),
|
||||
filter(changed => changed),
|
||||
switchMap(() => this._reloadFiles()),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
this.addSubscription = this.configService.listingMode$.subscribe(() => {
|
||||
this._computeAllFilters();
|
||||
});
|
||||
|
||||
this.addSubscription = this._dossiersService.dossierFileChanges$
|
||||
.pipe(
|
||||
filter(dossierId => dossierId === this.dossierId),
|
||||
switchMap(dossierId => this._filesService.loadAll(dossierId)),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
this.addSubscription = this._dossierTemplatesService
|
||||
.getEntityChanged$(this.currentDossier.dossierTemplateId)
|
||||
.pipe(
|
||||
@ -166,11 +168,10 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
|
||||
ngOnAttach() {
|
||||
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
|
||||
this._setRemovableSubscriptions();
|
||||
this._tableComponent?.scrollToLastIndex();
|
||||
}
|
||||
|
||||
ngOnDetach() {}
|
||||
|
||||
forceReanalysisAction($event: LongPressEvent) {
|
||||
this.analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled;
|
||||
}
|
||||
@ -192,8 +193,20 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
(this._fileInput as any).nativeElement.value = null;
|
||||
}
|
||||
|
||||
recentlyModifiedChecker = (file: File) =>
|
||||
moment(file.lastUpdated).add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment());
|
||||
private _setRemovableSubscriptions(): void {
|
||||
this._removableSubscriptions.add(
|
||||
this._dossiersService
|
||||
.getEntityDeleted$(this.dossierId)
|
||||
.pipe(tap(() => this._handleDeletedDossier()))
|
||||
.subscribe(),
|
||||
);
|
||||
}
|
||||
|
||||
private _handleDeletedDossier(): void {
|
||||
this._errorService.set(
|
||||
new CustomError(_('error.deleted-entity.dossier.label'), _('error.deleted-entity.dossier.action'), 'iqser:expand'),
|
||||
);
|
||||
}
|
||||
|
||||
private _updateFileAttributes(): void {
|
||||
this._fileAttributeConfigs =
|
||||
@ -204,11 +217,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
this._computeAllFilters();
|
||||
}
|
||||
|
||||
private async _reloadFiles() {
|
||||
await this._filesService.loadAll(this.dossierId).toPromise();
|
||||
this._computeAllFilters();
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
this.currentDossier = this._dossiersService.find(this.dossierId);
|
||||
this._computeAllFilters();
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
*ngIf="currentUser.isUser"
|
||||
[tooltip]="(currentUser.isManager ? 'dossier-listing.edit.action' : 'dossier-listing.dossier-info.action') | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
[icon]="currentUser.isManager ? 'iqser:edit' : 'iqser:dossier-info'"
|
||||
[icon]="currentUser.isManager ? 'iqser:edit' : 'red:info'"
|
||||
iqserHelpMode="edit-dossier-from-list"
|
||||
></iqser-circle-button>
|
||||
|
||||
|
||||
@ -9,28 +9,28 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-label stats-subtitle">
|
||||
<div>
|
||||
<div class="stats-subtitle">
|
||||
<div class="small-label">
|
||||
<mat-icon svgIcon="iqser:document"></mat-icon>
|
||||
{{ dossierStats.numberOfFiles }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="small-label">
|
||||
<mat-icon svgIcon="iqser:pages"></mat-icon>
|
||||
{{ dossierStats.numberOfPages }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="small-label">
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
{{ dossier.memberIds.length }}
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="small-label">
|
||||
<mat-icon svgIcon="red:calendar"></mat-icon>
|
||||
{{ dossier.date | date: 'mediumDate' }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="dossier.dueDate">
|
||||
<div *ngIf="dossier.dueDate" [class.error]="passedDueDate" [class.warn]="approachingDueDate" class="small-label">
|
||||
<mat-icon svgIcon="red:lightning"></mat-icon>
|
||||
{{ dossier.dueDate | date: 'mediumDate' }}
|
||||
</div>
|
||||
|
||||
@ -3,6 +3,9 @@ import { Dossier, DossierStats } from '@red/domain';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import * as moment from 'moment';
|
||||
|
||||
const DUE_DATE_WARN_DAYS = 14;
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-dossier-name',
|
||||
@ -20,6 +23,18 @@ export class DossiersListingDossierNameComponent {
|
||||
private readonly _dossiersService: DossiersService,
|
||||
) {}
|
||||
|
||||
get approachingDueDate(): boolean {
|
||||
return this._dueDateDaysDiff >= 0 && this._dueDateDaysDiff <= DUE_DATE_WARN_DAYS;
|
||||
}
|
||||
|
||||
get passedDueDate(): boolean {
|
||||
return this._dueDateDaysDiff < 0;
|
||||
}
|
||||
|
||||
private get _dueDateDaysDiff(): number {
|
||||
return moment(this.dossier.dueDate).diff(moment().startOf('day'), 'days');
|
||||
}
|
||||
|
||||
getDossierTemplateNameFor(dossierTemplateId: string): string {
|
||||
return this._dossierTemplatesService.find(dossierTemplateId).name;
|
||||
}
|
||||
|
||||
@ -1,19 +1,17 @@
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { Dossier } from '@red/domain';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { timer } from 'rxjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { DefaultListingServicesTmp, EntitiesService, ListingComponent, OnAttach, OnDetach, TableComponent } from '@iqser/common-ui';
|
||||
import { DefaultListingServicesTmp, EntitiesService, ListingComponent, OnAttach, TableComponent } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { switchMap, tap } from 'rxjs/operators';
|
||||
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||
import { tap } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossiers-listing-screen.component.html',
|
||||
@ -25,7 +23,7 @@ import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossiersListingScreenComponent extends ListingComponent<Dossier> implements OnInit, OnDestroy, OnAttach, OnDetach {
|
||||
export class DossiersListingScreenComponent extends ListingComponent<Dossier> implements OnInit, OnAttach {
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableColumnConfigs = this._configService.tableConfig;
|
||||
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
@ -57,22 +55,13 @@ export class DossiersListingScreenComponent extends ListingComponent<Dossier> im
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.addSubscription = timer(CHANGED_CHECK_INTERVAL, CHANGED_CHECK_INTERVAL)
|
||||
.pipe(switchMap(() => this._dossiersService.loadAllIfChanged()))
|
||||
.subscribe();
|
||||
|
||||
this.addSubscription = this._dossiersService.all$.pipe(tap(() => this._computeAllFilters())).subscribe();
|
||||
}
|
||||
|
||||
ngOnAttach(): void {
|
||||
this.ngOnInit();
|
||||
this._tableComponent?.scrollToLastIndex();
|
||||
}
|
||||
|
||||
ngOnDetach(): void {
|
||||
this.ngOnDestroy();
|
||||
}
|
||||
|
||||
openAddDossierDialog(): void {
|
||||
this._dialogService.openDialog('addDossier', null, null, async (addResponse: { dossier: Dossier; addMembers: boolean }) => {
|
||||
await this._router.navigate([addResponse.dossier.routerLink]);
|
||||
|
||||
@ -5,7 +5,9 @@ import { PdfViewerComponent } from './components/pdf-viewer/pdf-viewer.component
|
||||
import {
|
||||
AutoUnsubscribe,
|
||||
CircleButtonTypes,
|
||||
CustomError,
|
||||
Debounce,
|
||||
ErrorService,
|
||||
FilterService,
|
||||
LoadingService,
|
||||
OnAttach,
|
||||
@ -43,19 +45,12 @@ import { ViewModeService } from './services/view-mode.service';
|
||||
import { MultiSelectService } from './services/multi-select.service';
|
||||
import { DocumentInfoService } from './services/document-info.service';
|
||||
import { ReanalysisService } from '../../../../services/reanalysis.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
import PDFNet = Core.PDFNet;
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f', 'ArrowUp', 'ArrowDown'];
|
||||
|
||||
function diff<T>(first: readonly T[], second: readonly T[]): T[] {
|
||||
// symmetrical difference between two arrays
|
||||
const a = new Set(first);
|
||||
const b = new Set(second);
|
||||
|
||||
return [...first.filter(x => !b.has(x)), ...second.filter(x => !a.has(x))];
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: './file-preview-screen.component.html',
|
||||
styleUrls: ['./file-preview-screen.component.scss'],
|
||||
@ -108,6 +103,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _reanalysisService: ReanalysisService,
|
||||
private readonly _errorService: ErrorService,
|
||||
readonly excludedPagesService: ExcludedPagesService,
|
||||
readonly viewModeService: ViewModeService,
|
||||
readonly multiSelectService: MultiSelectService,
|
||||
@ -190,7 +186,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
ngOnDetach(): void {
|
||||
this.displayPdfViewer = false;
|
||||
super.ngOnDestroy();
|
||||
super.ngOnDetach();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
@ -529,10 +525,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.addSubscription = timer(0, 5000)
|
||||
this.addActiveScreenSubscription = timer(0, 5000)
|
||||
.pipe(switchMap(() => this._filesService.reload(this.dossierId, this.fileId)))
|
||||
.subscribe();
|
||||
this.addSubscription = this._filesMapService.fileReanalysed$
|
||||
this.addActiveScreenSubscription = this._filesMapService.fileReanalysed$
|
||||
.pipe(filter(file => file.fileId === this.fileId))
|
||||
.subscribe(async file => {
|
||||
if (file.lastProcessed !== this.fileData?.file.lastProcessed) {
|
||||
@ -541,6 +537,28 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
this._loadingService.stop();
|
||||
});
|
||||
|
||||
this.addActiveScreenSubscription = this._dossiersService
|
||||
.getEntityDeleted$(this.dossierId)
|
||||
.pipe(tap(() => this._handleDeletedDossier()))
|
||||
.subscribe();
|
||||
|
||||
this.addActiveScreenSubscription = this._filesMapService
|
||||
.watchDeleted$(this.fileId)
|
||||
.pipe(tap(() => this._handleDeletedFile()))
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
private _handleDeletedDossier(): void {
|
||||
this._errorService.set(
|
||||
new CustomError(_('error.deleted-entity.file-dossier.label'), _('error.deleted-entity.file-dossier.action'), 'iqser:expand'),
|
||||
);
|
||||
}
|
||||
|
||||
private _handleDeletedFile(): void {
|
||||
this._errorService.set(
|
||||
new CustomError(_('error.deleted-entity.file.label'), _('error.deleted-entity.file.action'), 'iqser:expand'),
|
||||
);
|
||||
}
|
||||
|
||||
private async _loadFileData(file: File): Promise<void | boolean> {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
EventEmitter,
|
||||
HostBinding,
|
||||
@ -96,6 +97,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _reanalysisService: ReanalysisService,
|
||||
private readonly _router: Router,
|
||||
private readonly _changeRef: ChangeDetectorRef,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@ -224,7 +226,10 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this._dossiersService.getEntityChanged$(this.file.dossierId).pipe(tap(() => this._setup()));
|
||||
this.addSubscription = this._dossiersService
|
||||
.getEntityChanged$(this.file.dossierId)
|
||||
.pipe(tap(() => this._setup()))
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
@ -353,6 +358,8 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
|
||||
this.showReanalyseDossierOverview = this.canReanalyse && this.isDossierOverview && this.analysisForced;
|
||||
|
||||
this.buttons = this._buttons;
|
||||
|
||||
this._changeRef.markForCheck();
|
||||
}
|
||||
|
||||
private async _setFileApproved() {
|
||||
|
||||
@ -2,16 +2,27 @@ import { Injectable, Injector } from '@angular/core';
|
||||
import { EntitiesService, List, mapEach, QueryParam, RequiredParam, shareLast, Toaster, Validate } from '@iqser/common-ui';
|
||||
import { Dossier, IDossier, IDossierRequest } from '@red/domain';
|
||||
import { catchError, filter, map, mapTo, switchMap, tap } from 'rxjs/operators';
|
||||
import { combineLatest, iif, Observable, of, throwError } from 'rxjs';
|
||||
import { combineLatest, Observable, of, Subject, throwError, timer } from 'rxjs';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||
|
||||
export interface IDossiersStats {
|
||||
totalPeople: number;
|
||||
totalAnalyzedPages: number;
|
||||
}
|
||||
|
||||
interface ChangesDetails {
|
||||
dossierChanges: [
|
||||
{
|
||||
dossierChanges: boolean;
|
||||
dossierId: string;
|
||||
fileChanges: boolean;
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const DOSSIER_EXISTS_MSG = _('add-dossier-dialog.errors.dossier-already-exists');
|
||||
const GENERIC_MGS = _('add-dossier-dialog.errors.generic');
|
||||
|
||||
@ -20,6 +31,7 @@ const GENERIC_MGS = _('add-dossier-dialog.errors.generic');
|
||||
})
|
||||
export class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
readonly generalStats$ = this.all$.pipe(switchMap(entities => this._generalStats$(entities)));
|
||||
readonly dossierFileChanges$ = new Subject<string>();
|
||||
|
||||
constructor(
|
||||
private readonly _toaster: Toaster,
|
||||
@ -27,6 +39,13 @@ export class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
private readonly _dossierStatsService: DossierStatsService,
|
||||
) {
|
||||
super(_injector, Dossier, 'dossier');
|
||||
|
||||
timer(CHANGED_CHECK_INTERVAL, CHANGED_CHECK_INTERVAL)
|
||||
.pipe(
|
||||
switchMap(() => this.loadAllIfChanged()),
|
||||
tap(changes => this._emitFileChanges(changes)),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
loadAll(): Observable<Dossier[]> {
|
||||
@ -39,8 +58,15 @@ export class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
);
|
||||
}
|
||||
|
||||
loadAllIfChanged(): Observable<boolean> {
|
||||
return this.hasChanges$().pipe(switchMap(changed => iif(() => changed, this.loadAll()).pipe(mapTo(changed))));
|
||||
loadAllIfChanged(): Observable<ChangesDetails> {
|
||||
return this.hasChangesDetails$().pipe(switchMap(changes => this.loadAll().pipe(mapTo(changes))));
|
||||
}
|
||||
|
||||
hasChangesDetails$(): Observable<ChangesDetails> {
|
||||
const body = { value: this._lastCheckedForChanges.get('root') ?? '0' };
|
||||
return this._post<ChangesDetails>(body, `${this._defaultModelPath}/changes/details`).pipe(
|
||||
filter(changes => changes.dossierChanges.length > 0),
|
||||
);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
@ -82,6 +108,10 @@ export class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
return super.delete(body, 'deleted-dossiers/hard-delete', body).toPromise();
|
||||
}
|
||||
|
||||
private _emitFileChanges(changes: ChangesDetails): void {
|
||||
changes.dossierChanges.filter(change => change.fileChanges).forEach(change => this.dossierFileChanges$.next(change.dossierId));
|
||||
}
|
||||
|
||||
private _computeStats(entities: List<Dossier>): IDossiersStats {
|
||||
let totalAnalyzedPages = 0;
|
||||
const totalPeople = new Set<string>();
|
||||
|
||||
@ -7,6 +7,7 @@ import { filter, startWith } from 'rxjs/operators';
|
||||
export class FilesMapService {
|
||||
readonly fileReanalysed$ = new Subject<File>();
|
||||
private readonly _entityChanged$ = new Subject<File>();
|
||||
private readonly _entityDeleted$ = new Subject<File>();
|
||||
private readonly _map = new Map<string, BehaviorSubject<File[]>>();
|
||||
|
||||
get$(dossierId: string) {
|
||||
@ -39,6 +40,7 @@ export class FilesMapService {
|
||||
|
||||
const reanalysedEntities = [];
|
||||
const changedEntities = [];
|
||||
const deletedEntities = this.get(key).filter(oldEntity => !entities.find(newEntity => newEntity.id === oldEntity.id));
|
||||
|
||||
// Keep old object references for unchanged entities
|
||||
const newEntities = entities.map(newEntity => {
|
||||
@ -67,6 +69,10 @@ export class FilesMapService {
|
||||
for (const file of changedEntities) {
|
||||
this._entityChanged$.next(file);
|
||||
}
|
||||
|
||||
for (const file of deletedEntities) {
|
||||
this._entityDeleted$.next(file);
|
||||
}
|
||||
}
|
||||
|
||||
replace(entity: File) {
|
||||
@ -83,4 +89,8 @@ export class FilesMapService {
|
||||
startWith(this.get(key, entityId)),
|
||||
);
|
||||
}
|
||||
|
||||
watchDeleted$(entityId: string): Observable<File> {
|
||||
return this._entityDeleted$.pipe(filter(entity => entity.id === entityId));
|
||||
}
|
||||
}
|
||||
|
||||
@ -944,6 +944,20 @@
|
||||
"side-nav-title": "Configurations"
|
||||
},
|
||||
"error": {
|
||||
"deleted-entity": {
|
||||
"dossier": {
|
||||
"action": "Back to overview",
|
||||
"label": "This dossier has been deleted!"
|
||||
},
|
||||
"file-dossier": {
|
||||
"action": "Back to overview",
|
||||
"label": "The dossier of this file has been deleted!"
|
||||
},
|
||||
"file": {
|
||||
"action": "Back to dossier",
|
||||
"label": "This file has been deleted!"
|
||||
}
|
||||
},
|
||||
"http": {
|
||||
"generic": "Action failed with code {status}"
|
||||
},
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit afed414030f936da36aa993a1945591b5c451861
|
||||
Subproject commit f7004520a71b36a00109115a5f4e860f918dcca9
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "redaction",
|
||||
"version": "3.143.0",
|
||||
"version": "3.148.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user