diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html
index 41a6d5db2..580c995a8 100644
--- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html
+++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.html
@@ -26,8 +26,8 @@
-
-
+
+
@@ -87,15 +87,15 @@
*ngFor="let pageNumber of displayedPages"
[activeSelection]="pageHasSelection(pageNumber)"
[active]="pageNumber === activeViewerPage"
- [file]="fileData?.file"
+ [file]="file"
[number]="pageNumber"
[showDottedIcon]="hasOnlyManualRedactionsAndNotExcluded(pageNumber)"
- [viewedPages]="fileData?.viewedPages"
+ [viewedPages]="viewedPages"
>
diff --git a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts
index d5c52e16f..e99fd1d58 100644
--- a/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/components/file-workload/file-workload.component.ts
@@ -1,14 +1,25 @@
-import { ChangeDetectorRef, Component, ElementRef, EventEmitter, HostListener, Input, Output, TemplateRef, ViewChild } from '@angular/core';
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ EventEmitter,
+ HostListener,
+ Input,
+ Output,
+ TemplateRef,
+ ViewChild,
+} from '@angular/core';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
import scrollIntoView from 'scroll-into-view-if-needed';
import { CircleButtonTypes, Debounce, FilterService, IconButtonTypes, INestedFilter, IqserEventTarget } from '@iqser/common-ui';
-import { FileDataModel } from '@models/file/file-data.model';
import { PermissionsService } from '@services/permissions.service';
import { WebViewerInstance } from '@pdftron/webviewer';
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
import { map } from 'rxjs/operators';
+import { File, IViewedPage } from '@red/domain';
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
@@ -17,6 +28,7 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
selector: 'redaction-file-workload',
templateUrl: './file-workload.component.html',
styleUrls: ['./file-workload.component.scss'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
})
export class FileWorkloadComponent {
readonly iconButtonTypes = IconButtonTypes;
@@ -27,7 +39,8 @@ export class FileWorkloadComponent {
@Input() activeViewerPage: number;
@Input() shouldDeselectAnnotationsOnPageChange: boolean;
@Input() dialogRef: MatDialogRef
;
- @Input() fileData: FileDataModel;
+ @Input() viewedPages: IViewedPage[];
+ @Input() file: File;
@Input() hideSkipped: boolean;
@Input() excludePages: boolean;
@Input() annotationActionsTemplate: TemplateRef;
@@ -78,20 +91,16 @@ export class FileWorkloadComponent {
}
}
- get isProcessing(): boolean {
- return this.fileData?.file?.isProcessing;
- }
-
get activeAnnotations(): AnnotationWrapper[] | undefined {
return this.displayedAnnotations.get(this.activeViewerPage);
}
get isReadOnly(): boolean {
- return !this._permissionsService.canPerformAnnotationActions(this.fileData?.file);
+ return !this._permissionsService.canPerformAnnotationActions(this.file);
}
get currentPageIsExcluded(): boolean {
- return this.fileData?.file?.excludedPages?.includes(this.activeViewerPage);
+ return this.file?.excludedPages?.includes(this.activeViewerPage);
}
private get _firstSelectedAnnotation() {
@@ -120,7 +129,7 @@ export class FileWorkloadComponent {
hasOnlyManualRedactionsAndNotExcluded(pageNumber: number): boolean {
const hasOnlyManualRedactions = this.displayedAnnotations.get(pageNumber).every(annotation => annotation.manual);
- return hasOnlyManualRedactions && this.fileData.file.excludedPages.includes(pageNumber);
+ return hasOnlyManualRedactions && this.file.excludedPages.includes(pageNumber);
}
pageHasSelection(page: number) {
@@ -171,7 +180,7 @@ export class FileWorkloadComponent {
this._navigatePages($event);
}
- this._changeDetectorRef.detectChanges();
+ this._changeDetectorRef.markForCheck();
}
scrollAnnotations(): void {
@@ -212,7 +221,7 @@ export class FileWorkloadComponent {
}
scrollQuickNavLast(): void {
- this.selectPage.emit(this.fileData.file.numberOfPages);
+ this.selectPage.emit(this.file.numberOfPages);
}
pageSelectedByClick($event: number): void {
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html
index 8fa70a529..b722b788c 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.html
@@ -19,9 +19,9 @@
{{ 'file-preview.delta' | translate }}
@@ -32,11 +32,11 @@
-
+
{{ translations[file.workflowStatus] | translate }}
- {{ 'by' | translate }}:
+ {{ 'by' | translate }}:
@@ -48,7 +48,7 @@
>
@@ -56,9 +56,9 @@
@@ -66,13 +66,13 @@
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts
index c1a8f8cf4..ab39b0e99 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/file-preview-screen.component.ts
@@ -86,7 +86,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
readonly dossier$: Observable
;
readonly file$: Observable;
readonly fileId: string;
- file: File;
private _instance: WebViewerInstance;
private _lastPage: string;
private _reloadFileOnReanalysis = false;
@@ -126,7 +125,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
this.dossierId = _activatedRoute.snapshot.paramMap.get('dossierId');
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId);
this.fileId = _activatedRoute.snapshot.paramMap.get('fileId');
- this.file = _filesMapService.get(this.dossierId, this.fileId);
this.file$ = _filesMapService.watch$(this.dossierId, this.fileId);
document.documentElement.addEventListener('fullscreenchange', () => {
if (!document.fullscreenElement) {
@@ -135,12 +133,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
});
}
- get assignTooltip(): string {
- return this.file.isUnderApproval
- ? this._translateService.instant('dossier-overview.assign-approver')
- : this.assignOrChangeReviewerTooltip;
- }
-
get annotations(): AnnotationWrapper[] {
return this.annotationData ? this.annotationData.visibleAnnotations : [];
}
@@ -161,10 +153,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
: (currentPage + 1) / 2;
}
- get canSwitchToRedactedView(): boolean {
- return this.fileData && !this.fileData.file.analysisRequired && !this.fileData.file.excluded;
- }
-
get canSwitchToDeltaView(): boolean {
return this.fileData?.hasChangeLog;
}
@@ -177,18 +165,28 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
return !!this._workloadComponent?.multiSelectActive;
}
- get assignOrChangeReviewerTooltip(): string {
- return this.file.currentReviewer
+ assignTooltip(file: File): string {
+ return file.isUnderApproval
+ ? this._translateService.instant('dossier-overview.assign-approver')
+ : this.assignOrChangeReviewerTooltip(file);
+ }
+
+ canSwitchToRedactedView(file: File): boolean {
+ return this.fileData && !file.analysisRequired && !file.excluded;
+ }
+
+ assignOrChangeReviewerTooltip(file: File): string {
+ return file.currentReviewer
? this._translateService.instant('file-preview.change-reviewer')
: this._translateService.instant('file-preview.assign-reviewer');
}
- get statusBarConfig(): [{ length: number; color: WorkflowFileStatus }] {
- return [{ length: 1, color: this.file.workflowStatus }];
+ statusBarConfig(file: File): [{ length: number; color: WorkflowFileStatus }] {
+ return [{ length: 1, color: file.workflowStatus }];
}
- get isUnderReviewOrApproval(): boolean {
- return this.file.isUnderReview || this.file.isUnderApproval;
+ isUnderReviewOrApproval(file: File): boolean {
+ return file.isUnderReview || file.isUnderApproval;
}
canAssign(file: File): boolean {
@@ -200,13 +198,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
);
}
- singleUsersSelectOptions(dossier: Dossier): List {
- const unassignUser = this.permissionsService.canUnassignUser(this.file) ? [undefined] : [];
- return this.file?.isUnderApproval ? [...dossier.approverIds, ...unassignUser] : [...dossier.memberIds, ...unassignUser];
+ usersOptions(file: File, dossier: Dossier): List {
+ const unassignUser = this.permissionsService.canUnassignUser(file) ? [undefined] : [];
+ return file.isUnderApproval ? [...dossier.approverIds, ...unassignUser] : [...dossier.memberIds, ...unassignUser];
}
- canAssignReviewer(dossier: Dossier): boolean {
- return !this.file.currentReviewer && this.permissionsService.canAssignUser(this.file) && dossier.hasReviewers;
+ canAssignReviewer(file: File, dossier: Dossier): boolean {
+ return !file.currentReviewer && this.permissionsService.canAssignUser(file) && dossier.hasReviewers;
}
updateViewMode(): void {
@@ -250,7 +248,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
async ngOnAttach(previousRoute: ActivatedRouteSnapshot): Promise {
- if (!this.file.canBeOpened) {
+ const file = this._filesMapService.get(this.dossierId, this.fileId);
+ if (!file.canBeOpened) {
return this._router.navigate([this.dossiersService.find(this.dossierId)?.routerLink]);
}
@@ -264,7 +263,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
this._updateCanPerformActions();
this._subscribeToFileUpdates();
- if (this.fileData?.file?.analysisRequired) {
+ const file = this._filesMapService.get(this.dossierId, this.fileId);
+ if (file?.analysisRequired) {
this.fileActions.reanalyseFile();
}
}
@@ -358,7 +358,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
response.manualRedactionEntryWrapper.rectId,
);
this._instance.Core.annotationManager.deleteAnnotation(annotation);
- this.fileData.file = await this.appStateService.reloadFile(this.dossierId, this.fileId);
+ await this.appStateService.reloadFile(this.dossierId, this.fileId);
const distinctPages = entryWrapper.manualRedactionEntry.positions
.map(p => p.page)
.filter((item, pos, self) => self.indexOf(item) === pos);
@@ -497,18 +497,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
}
- async assignToMe() {
- await this._fileActionService.assignToMe([this.fileData.file], async () => {
+ async assignToMe(file: File) {
+ await this._fileActionService.assignToMe([file], async () => {
await this.appStateService.reloadFile(this.dossierId, this.fileId);
this._updateCanPerformActions();
});
}
- async assignReviewer(user: User | string) {
+ async assignReviewer(file: File, user: User | string) {
const reviewerId = typeof user === 'string' ? user : user?.id;
const reviewerName = this.userService.getNameForId(reviewerId);
- const { dossierId, fileId, filename } = this.fileData.file;
+ const { dossierId, fileId, filename } = file;
await this._filesService.setReviewerFor([fileId], dossierId, reviewerId).toPromise();
this._toaster.info(_('assignment.reviewer'), { params: { reviewerName, filename } });
@@ -529,11 +529,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
this._scrollViews();
}
- async downloadOriginalFile() {
+ async downloadOriginalFile(file: File) {
const data = await this._fileManagementService
- .downloadOriginalFile(this.fileData.file.dossierId, this.fileId, 'response', true, this.fileData.file.cacheIdentifier)
+ .downloadOriginalFile(this.dossierId, this.fileId, 'response', true, file.cacheIdentifier)
.toPromise();
- download(data, this.fileData.file.filename);
+ download(data, file.filename);
}
toggleSkipped($event) {
@@ -555,14 +555,15 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
});
}
- private async _doStampExcludedPages(excludedPages: number[]) {
+ private async _doStampExcludedPages() {
const pdfNet = this._instance.Core.PDFNet;
const document = await this._instance.Core.documentViewer.getDocument().getPDFDoc();
- const allPages = [...Array(this.fileData.file.numberOfPages).keys()].map(page => page + 1);
+ const file = this._filesMapService.get(this.dossierId, this.fileId);
+ const allPages = [...Array(file.numberOfPages).keys()].map(page => page + 1);
await clearStamps(document, pdfNet, allPages);
- if (excludedPages && excludedPages.length > 0) {
- this.viewerComponent.utils.excludedPages = excludedPages;
+ if (file.excludedPages && file.excludedPages.length > 0) {
+ this.viewerComponent.utils.excludedPages = file.excludedPages;
await stampPDFPage(
document,
pdfNet,
@@ -572,13 +573,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
'DIAGONAL',
33,
'#283241',
- excludedPages,
+ file.excludedPages,
);
}
}
private async _stampExcludedPages() {
- await this._doStampExcludedPages(this.fileData.file.excludedPages);
+ await this._doStampExcludedPages();
this._instance.Core.documentViewer.refreshAll();
this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage);
this._changeDetectorRef.markForCheck();
@@ -600,20 +601,21 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
private _updateCanPerformActions() {
+ const file = this._filesMapService.get(this.dossierId, this.fileId);
this.canPerformAnnotationActions =
- this.permissionsService.canPerformAnnotationActions(this.file) &&
+ this.permissionsService.canPerformAnnotationActions(file) &&
this.viewMode === 'STANDARD' &&
!this.viewerComponent?.utils.isCompareMode;
}
private async _loadFileData(performUpdate = false): Promise {
- const fileData = await this._fileDownloadService.loadDataFor(this.file).toPromise();
+ const file = this._filesMapService.get(this.dossierId, this.fileId);
+ const fileData = await this._fileDownloadService.loadDataFor(file).toPromise();
- if (!fileData.file?.isPending && !fileData.file?.isError) {
+ if (!file?.isPending && !file?.isError) {
if (performUpdate) {
this.fileData.redactionLog = fileData.redactionLog;
this.fileData.viewedPages = fileData.viewedPages;
- this.fileData.file = fileData.file;
this.rebuildFilters(true);
} else {
this.fileData = fileData;
@@ -623,7 +625,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
return;
}
- if (fileData.file.isError) {
+ if (file.isError) {
await this._router.navigate([this.dossiersService.find(this.dossierId).routerLink]);
}
}
@@ -647,7 +649,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
const currentPageAnnotations = this.annotations.filter(a => a.pageNumber === page);
const currentPageAnnotationIds = currentPageAnnotations.map(a => a.id);
- this.fileData.file = await this.appStateService.reloadFile(this.dossierId, this.fileId);
+ await this.appStateService.reloadFile(this.dossierId, this.fileId);
this.fileData.redactionLog = await this._fileDownloadService.loadRedactionLogFor(this.dossierId, this.fileId).toPromise();
this.rebuildFilters();