From 5b720c2c3dcb228f2c0475d8e5227ba9998d5cc3 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Wed, 29 Jun 2022 13:29:27 +0300 Subject: [PATCH] RED-4305: check if document loaded before drawing annotations --- .../file-preview-screen.component.ts | 4 +- .../services/annotation-draw.service.ts | 13 ++++-- .../services/document-viewer.service.ts | 42 +++++++++---------- .../pdf-viewer/services/pdf-viewer.service.ts | 4 +- libs/common-ui | 2 +- libs/red-domain/src/lib/files/file.ts | 32 +------------- 6 files changed, 35 insertions(+), 62 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index ac04657ff..61d85c707 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -546,7 +546,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni .pipe( switchMap(blob => from(this._documentViewer.lock()).pipe(map(() => blob))), tap(() => this._errorService.clear()), - tap(blob => this.pdf.loadDocument(blob, this.state.file)), + tap(blob => this.pdf.loadDocument(blob, this.state.file, () => this.state.reloadBlob())), ) .subscribe(); @@ -624,7 +624,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni } } - private _setAnnotationsOpacity(annotations: Annotation[], restoreToOriginal: boolean = false) { + private _setAnnotationsOpacity(annotations: Annotation[], restoreToOriginal = false) { annotations.forEach(annotation => { annotation['Opacity'] = restoreToOriginal ? parseFloat(annotation.getCustomData('opacity')) : 1; }); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index bf692cd1e..ee998df83 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -85,9 +85,14 @@ export class AnnotationDrawService { } private async _draw(annotationWrappers: List, dossierTemplateId: string, hideSkipped: boolean) { + const totalPages = await firstValueFrom(this._pdf.totalPages$); const annotations = annotationWrappers - .map(annotation => this._computeAnnotation(annotation, dossierTemplateId, hideSkipped)) - .filter(a => !!a); + .map(annotation => this._computeAnnotation(annotation, dossierTemplateId, hideSkipped, totalPages)) + .filterTruthy(); + const documentLoaded = await firstValueFrom(this._documentViewer.loaded$); + if (!documentLoaded) { + return; + } await this._annotationManager.add(annotations); if (this._userPreferenceService.areDevFeaturesEnabled) { @@ -130,9 +135,9 @@ export class AnnotationDrawService { return rectangleAnnot; } - private _computeAnnotation(annotationWrapper: AnnotationWrapper, dossierTemplateId: string, hideSkipped: boolean) { + private _computeAnnotation(annotationWrapper: AnnotationWrapper, dossierTemplateId: string, hideSkipped: boolean, totalPages: number) { const pageNumber = this._pdf.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber; - if (pageNumber > this._pdf.pageCount) { + if (pageNumber > totalPages) { // skip imported annotations from files that have more pages than the current one return; } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts index f837a286f..22042bfe0 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/document-viewer.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { Core } from '@pdftron/webviewer'; import { NGXLogger } from 'ngx-logger'; import { fromEvent, merge, Observable } from 'rxjs'; @@ -22,12 +22,10 @@ export class REDDocumentViewer { selectedText = ''; #document: DocumentViewer; - constructor( - private readonly _logger: NGXLogger, - private readonly _userPreferenceService: UserPreferenceService, - private readonly _pdf: PdfViewer, - private readonly _activatedRoute: ActivatedRoute, - ) {} + readonly #logger = inject(NGXLogger); + readonly #userPreferenceService = inject(UserPreferenceService); + readonly #pdf = inject(PdfViewer); + readonly #activatedRoute = inject(ActivatedRoute); get PDFDoc() { return this.document?.getPDFDoc(); @@ -41,7 +39,7 @@ export class REDDocumentViewer { const event$ = fromEvent(this.#document, 'documentUnloaded'); const toBool$ = event$.pipe(map(() => false)); - return toBool$.pipe(tap(() => this._logger.info('[PDF] Document unloaded'))); + return toBool$.pipe(tap(() => this.#logger.info('[PDF] Document unloaded'))); } get #documentLoaded$() { @@ -52,7 +50,7 @@ export class REDDocumentViewer { tap(() => this.#setCurrentPage()), tap(() => this.#setInitialDisplayMode()), tap(() => this.updateTooltipsVisibility()), - tap(() => this._logger.info('[PDF] Document loaded')), + tap(() => this.#logger.info('[PDF] Document loaded')), ); } @@ -83,14 +81,14 @@ export class REDDocumentViewer { } close() { - this._logger.info('[PDF] Closing document'); + this.#logger.info('[PDF] Closing document'); this.#document.closeDocument(); - this._pdf.closeCompareMode(); + this.#pdf.closeCompareMode(); } updateTooltipsVisibility(): void { - const current = this._userPreferenceService.getFilePreviewTooltipsPreference(); - this._pdf.instance.UI.setAnnotationContentOverlayHandler(() => (current ? undefined : false)); + const current = this.#userPreferenceService.getFilePreviewTooltipsPreference(); + this.#pdf.instance.UI.setAnnotationContentOverlayHandler(() => (current ? undefined : false)); } init(document: DocumentViewer) { @@ -108,7 +106,7 @@ export class REDDocumentViewer { } await document.lock(); - this._logger.info('[PDF] Locked'); + this.#logger.info('[PDF] Locked'); return true; } @@ -150,7 +148,7 @@ export class REDDocumentViewer { pages.forEach(page => this.#document.setRotation(0, Number(page))); } - rotate(rotation: RotationType, page = this._pdf.currentPage) { + rotate(rotation: RotationType, page = this.#pdf.currentPage) { if (rotation === RotationTypes.LEFT) { this.#document.rotateCounterClockwise(page); } else { @@ -159,23 +157,23 @@ export class REDDocumentViewer { } #disableTextPopupIfCompareMode(pageNumber) { - if (this._pdf.isCompare && pageNumber % 2 === 0) { - return this._pdf.disable('textPopup'); + if (this.#pdf.isCompare && pageNumber % 2 === 0) { + return this.#pdf.disable('textPopup'); } - this._pdf.enable('textPopup'); + this.#pdf.enable('textPopup'); } #setCurrentPage() { - const currentDocPage = this._activatedRoute.snapshot.queryParamMap.get('page'); - this._pdf.navigateTo(currentDocPage ?? 1); + const currentDocPage = this.#activatedRoute.snapshot.queryParamMap.get('page'); + this.#pdf.navigateTo(currentDocPage ?? 1); } #setInitialDisplayMode() { - this._pdf.instance.UI.setFitMode('FitPage'); + this.#pdf.instance.UI.setFitMode('FitPage'); const displayModeManager = this.#document.getDisplayModeManager(); const instanceDisplayMode = displayModeManager.getDisplayMode(); - instanceDisplayMode.mode = this._pdf.isCompare ? 'Facing' : 'Single'; + instanceDisplayMode.mode = this.#pdf.isCompare ? 'Facing' : 'Single'; displayModeManager.setDisplayMode(instanceDisplayMode); } } diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts index 8f4e2d850..b35624d90 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/pdf-viewer.service.ts @@ -166,11 +166,11 @@ export class PdfViewer { this.#compareMode$.next(false); } - async loadDocument(blob: Blob, file: File) { + async loadDocument(blob: Blob, file: File, actionOnError: () => void = () => {}) { const onError = () => { this._injector.get(ErrorService).set(DOCUMENT_LOADING_ERROR); this._logger.error('[PDF] Error while loading document'); - // this.stateService.reloadBlob(); + actionOnError(); }; const document = await this.PDFNet.PDFDoc.createFromBuffer(await blob.arrayBuffer()); diff --git a/libs/common-ui b/libs/common-ui index d5ded3615..45dc0f0f1 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit d5ded3615fdf420ca42c21826654013165279462 +Subproject commit 45dc0f0f1199bc510d477b1e132e098c4c605e3f diff --git a/libs/red-domain/src/lib/files/file.ts b/libs/red-domain/src/lib/files/file.ts index 0d0155445..b7a2efcec 100644 --- a/libs/red-domain/src/lib/files/file.ts +++ b/libs/red-domain/src/lib/files/file.ts @@ -13,17 +13,8 @@ export interface IFile { * Shows if all manual changes have been applied by a reanalysis. */ readonly allManualRedactionsApplied?: boolean; - /** - * Shows how long the last analysis took - */ readonly analysisDuration?: number; - /** - * Shows if the file requires reanalysis. - */ readonly analysisRequired?: boolean; - /** - * Shows the date of approval, if approved. - */ readonly approvalDate?: string; /** * The current reviewer's (if any) user id. @@ -37,35 +28,17 @@ export interface IFile { * Shows which dossier dictionary versions was used during the analysis. */ readonly dossierDictionaryVersion?: number; - /** - * The ID of the dossier the file belongs to. - */ readonly dossierId: string; /** * Shows if the file was excluded from analysis. */ readonly excluded?: boolean; - /** - * Shows if the file was excluded from automatic analysis. - */ readonly excludedFromAutomaticAnalysis?: boolean; - /** - * Set of excluded pages for this file. - */ - readonly excludedPages?: Array; + readonly excludedPages?: number[]; fileAttributes?: FileAttributes; - /** - * The ID of the file. - */ readonly fileId: string; - /** - * The file's name. - */ readonly filename: string; readonly fileSize: number; - /** - * Shows if this file has comments on annotations. - */ readonly hasAnnotationComments?: boolean; /** * Shows if any hints were found during the analysis. @@ -83,9 +56,6 @@ export interface IFile { * Shows if any requests were found during the analysis. */ readonly hasRequests?: boolean; - /** - * Shows if there are any Suggestions in this file. - */ readonly hasSuggestions?: boolean; /** * Shows if there is any change between the previous and current analysis.