RED-3988: fix other compare mode & reload issues
This commit is contained in:
parent
95efa62f27
commit
f7e0fbc9ff
@ -3,11 +3,9 @@ import {
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
HostListener,
|
||||
Input,
|
||||
OnDestroy,
|
||||
Output,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
@ -60,7 +58,6 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
@Input() dialogRef: MatDialogRef<unknown>;
|
||||
@Input() file!: File;
|
||||
@Input() annotationActionsTemplate: TemplateRef<unknown>;
|
||||
@Output() readonly selectPage = new EventEmitter<number>();
|
||||
displayedPages: number[] = [];
|
||||
pagesPanelActive = true;
|
||||
readonly displayedAnnotations$: Observable<Map<number, AnnotationWrapper[]>>;
|
||||
@ -275,16 +272,16 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
}
|
||||
|
||||
scrollQuickNavFirst(): void {
|
||||
this.selectPage.emit(1);
|
||||
this.pdf.navigateTo(1);
|
||||
}
|
||||
|
||||
scrollQuickNavLast(): Promise<void> {
|
||||
return firstValueFrom(this.state.file$).then(file => this.selectPage.emit(file.numberOfPages));
|
||||
return firstValueFrom(this.state.file$).then(file => this.pdf.navigateTo(file.numberOfPages));
|
||||
}
|
||||
|
||||
pageSelectedByClick($event: number): void {
|
||||
this.pagesPanelActive = true;
|
||||
this.selectPage.emit($event);
|
||||
this.pdf.navigateTo($event);
|
||||
}
|
||||
|
||||
preventKeyDefault($event: KeyboardEvent): void {
|
||||
@ -294,11 +291,11 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
}
|
||||
|
||||
jumpToPreviousWithAnnotations(): void {
|
||||
this.selectPage.emit(this._prevPageWithAnnotations());
|
||||
this.pdf.navigateTo(this._prevPageWithAnnotations());
|
||||
}
|
||||
|
||||
jumpToNextWithAnnotations(): void {
|
||||
this.selectPage.emit(this._nextPageWithAnnotations());
|
||||
this.pdf.navigateTo(this._nextPageWithAnnotations());
|
||||
}
|
||||
|
||||
navigateAnnotations($event: KeyboardEvent) {
|
||||
@ -419,26 +416,26 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
||||
if (pageIdx !== -1) {
|
||||
// If active page has annotations
|
||||
if (pageIdx !== this.displayedPages.length - 1) {
|
||||
this.selectPage.emit(this.displayedPages[pageIdx + 1]);
|
||||
this.pdf.navigateTo(this.displayedPages[pageIdx + 1]);
|
||||
}
|
||||
} else {
|
||||
// If active page doesn't have annotations
|
||||
const nextPage = this._nextPageWithAnnotations();
|
||||
if (nextPage) {
|
||||
this.selectPage.emit(nextPage);
|
||||
this.pdf.navigateTo(nextPage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pageIdx !== -1) {
|
||||
// If active page has annotations
|
||||
if (pageIdx !== 0) {
|
||||
this.selectPage.emit(this.displayedPages[pageIdx - 1]);
|
||||
this.pdf.navigateTo(this.displayedPages[pageIdx - 1]);
|
||||
}
|
||||
} else {
|
||||
// If active page doesn't have annotations
|
||||
const prevPage = this._prevPageWithAnnotations();
|
||||
if (prevPage) {
|
||||
this.selectPage.emit(prevPage);
|
||||
this.pdf.navigateTo(prevPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +75,6 @@
|
||||
<redaction-document-info *ngIf="documentInfoService.shown$ | async"></redaction-document-info>
|
||||
|
||||
<redaction-file-workload
|
||||
(selectPage)="selectPage($event)"
|
||||
*ngIf="!file.excluded"
|
||||
[activeViewerPage]="pdf.currentPage$ | async"
|
||||
[annotationActionsTemplate]="annotationActionsTemplate"
|
||||
|
||||
@ -73,7 +73,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
readonly fileId = this.state.fileId;
|
||||
readonly dossierId = this.state.dossierId;
|
||||
readonly file$ = this.state.file$.pipe(tap(file => this._fileDataService.loadAnnotations(file)));
|
||||
private _lastPage: string;
|
||||
@ViewChild('annotationFilterTemplate', {
|
||||
read: TemplateRef,
|
||||
static: false,
|
||||
@ -205,9 +204,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this.#rebuildFilters();
|
||||
}
|
||||
|
||||
async ngOnDetach() {
|
||||
await this._documentViewer.lock();
|
||||
this._documentViewer.close();
|
||||
ngOnDetach() {
|
||||
this._viewerHeaderService.resetCompareButtons();
|
||||
super.ngOnDetach();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
@ -222,7 +220,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
await this.ngOnInit();
|
||||
await this._fileDataService.loadRedactionLog();
|
||||
this._viewerHeaderService.updateElements();
|
||||
this._lastPage = previousRoute.queryParams.page;
|
||||
await this.#updateQueryParamsPage(Number(previousRoute.queryParams.page ?? '1'));
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
@ -242,12 +240,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const reanalyzeFiles = reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
|
||||
await firstValueFrom(reanalyzeFiles);
|
||||
}
|
||||
this.pdfProxyService.loadViewer();
|
||||
}
|
||||
|
||||
selectPage(pageNumber: number) {
|
||||
this.pdf.navigateTo(pageNumber);
|
||||
this._lastPage = pageNumber.toString();
|
||||
this.pdfProxyService.loadViewer();
|
||||
}
|
||||
|
||||
openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
|
||||
@ -320,7 +314,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
@Debounce(100)
|
||||
async viewerReady() {
|
||||
// Go to initial page from query params
|
||||
const pageNumber: string = this._lastPage || this._activatedRoute.snapshot.queryParams.page;
|
||||
const pageNumber: string = this._activatedRoute.snapshot.queryParams.page;
|
||||
if (pageNumber) {
|
||||
const file = this.state.file;
|
||||
let page = parseInt(pageNumber, 10);
|
||||
@ -332,7 +326,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
page = file.numberOfPages;
|
||||
}
|
||||
|
||||
this.selectPage(page);
|
||||
this.pdf.navigateTo(page);
|
||||
}
|
||||
|
||||
this._loadingService.stop();
|
||||
@ -358,20 +352,22 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
loadAnnotations() {
|
||||
const documentLoaded$ = this._documentViewer.loaded$.pipe(
|
||||
tap(() => {
|
||||
tap(loaded => {
|
||||
if (!loaded) {
|
||||
return;
|
||||
}
|
||||
this._pageRotationService.clearRotations();
|
||||
this._viewerHeaderService.disable(ROTATION_ACTION_BUTTONS);
|
||||
return this.viewerReady();
|
||||
}),
|
||||
filter(s => s),
|
||||
tap(() => this.viewerReady()),
|
||||
);
|
||||
|
||||
const currentPageAnnotations$ = combineLatest([this.pdf.currentPage$, this._fileDataService.annotations$]).pipe(
|
||||
map(([page, annotations]) => annotations.filter(annotation => annotation.pageNumber === page)),
|
||||
);
|
||||
|
||||
let start;
|
||||
return combineLatest([currentPageAnnotations$, documentLoaded$]).pipe(
|
||||
filter(([, loaded]) => loaded),
|
||||
tap(() => (start = new Date().getTime())),
|
||||
map(([annotations]) => annotations),
|
||||
startWith([] as AnnotationWrapper[]),
|
||||
@ -548,7 +544,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this.openManualAnnotationDialog($event);
|
||||
});
|
||||
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page => this.viewerPageChanged(page));
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.pageChanged$.subscribe(page =>
|
||||
this._ngZone.run(() => this.viewerPageChanged(page)),
|
||||
);
|
||||
this.addActiveScreenSubscription = this.pdfProxyService.annotationSelected$.subscribe();
|
||||
}
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ import { ManualRedactionService } from './services/manual-redaction.service';
|
||||
import { AnnotationWrapperComponent } from './components/annotation-wrapper/annotation-wrapper.component';
|
||||
import { AnnotationReferenceComponent } from './components/annotation-reference/annotation-reference.component';
|
||||
import { ImportRedactionsDialogComponent } from './dialogs/import-redactions-dialog/import-redactions-dialog';
|
||||
import { DocumentUnloadedGuard } from './services/document-unloaded.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -45,7 +46,7 @@ const routes: Routes = [
|
||||
component: FilePreviewScreenComponent,
|
||||
pathMatch: 'full',
|
||||
data: { reuse: true },
|
||||
canDeactivate: [PendingChangesGuard],
|
||||
canDeactivate: [PendingChangesGuard, DocumentUnloadedGuard],
|
||||
},
|
||||
];
|
||||
|
||||
@ -95,6 +96,6 @@ const components = [
|
||||
OverlayModule,
|
||||
ColorPickerModule,
|
||||
],
|
||||
providers: [FilePreviewDialogService, ManualRedactionService],
|
||||
providers: [FilePreviewDialogService, ManualRedactionService, DocumentUnloadedGuard],
|
||||
})
|
||||
export class FilePreviewModule {}
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanDeactivate } from '@angular/router';
|
||||
import { filter, map, Observable } from 'rxjs';
|
||||
import { REDDocumentViewer } from '../../pdf-viewer/services/document-viewer.service';
|
||||
|
||||
@Injectable()
|
||||
export class DocumentUnloadedGuard implements CanDeactivate<unknown> {
|
||||
constructor(private readonly _documentViewer: REDDocumentViewer) {}
|
||||
|
||||
canDeactivate(): Observable<boolean> {
|
||||
this._documentViewer.close();
|
||||
|
||||
return this._documentViewer.loaded$.pipe(
|
||||
filter(loaded => !loaded),
|
||||
map(() => true),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,6 @@ import { HeaderElements } from '../../../file-preview/utils/constants';
|
||||
import { ConfirmationDialogInput, ConfirmOptions, LoadingService } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FilesMapService } from '@services/files/files-map.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { SharedDialogService } from '@shared/services/dialog.service';
|
||||
import { PdfViewer } from '../../services/pdf-viewer.service';
|
||||
import { ViewerHeaderService } from '../../services/viewer-header.service';
|
||||
@ -28,7 +27,6 @@ export class CompareFileInputComponent {
|
||||
private readonly _logger: NGXLogger,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _documentViewer: REDDocumentViewer,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _dialogService: SharedDialogService,
|
||||
private readonly _viewerHeaderService: ViewerHeaderService,
|
||||
@ -44,9 +42,7 @@ export class CompareFileInputComponent {
|
||||
return this._filesMapService.get(dossierId, fileId)?.filename ?? 'document.pdf';
|
||||
}
|
||||
|
||||
async upload(files: FileList) {
|
||||
await this._documentViewer.lock();
|
||||
|
||||
upload(files: FileList) {
|
||||
const fileToCompare = files[0];
|
||||
this.input.nativeElement.value = null;
|
||||
|
||||
@ -61,11 +57,14 @@ export class CompareFileInputComponent {
|
||||
fileReader.readAsArrayBuffer(fileToCompare);
|
||||
}
|
||||
|
||||
async #createDocumentsAndCompare(blob: ArrayBuffer, fileName: string) {
|
||||
async #createDocumentsAndCompare(buffer: ArrayBuffer, fileName: string) {
|
||||
const currentBlob = await this._documentViewer.blob();
|
||||
this._documentViewer.close();
|
||||
|
||||
const pdfNet = this._pdf.PDFNet;
|
||||
|
||||
const compareDocument = await pdfNet.PDFDoc.createFromBuffer(blob);
|
||||
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await this._pdf.blob.arrayBuffer());
|
||||
const compareDocument = await pdfNet.PDFDoc.createFromBuffer(buffer);
|
||||
const currentDocument = await pdfNet.PDFDoc.createFromBuffer(await currentBlob.arrayBuffer());
|
||||
|
||||
const currentDocumentPageCount = await currentDocument.getPageCount();
|
||||
const compareDocumentPageCount = await compareDocument.getPageCount();
|
||||
|
||||
@ -33,13 +33,11 @@ export class AnnotationDrawService {
|
||||
) {}
|
||||
|
||||
async draw(annotations: List<AnnotationWrapper>, dossierTemplateId: string, hideSkipped: boolean) {
|
||||
await this._documentViewer.lock();
|
||||
try {
|
||||
await this._draw(annotations, dossierTemplateId, hideSkipped);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
await this._documentViewer.unlock();
|
||||
}
|
||||
|
||||
getAndConvertColor(superType: string, dossierTemplateId: string, dictionary?: string) {
|
||||
|
||||
@ -19,9 +19,7 @@ export class REDDocumentViewer {
|
||||
pageComplete$: Observable<boolean>;
|
||||
keyUp$: Observable<KeyboardEvent>;
|
||||
textSelected$: Observable<string>;
|
||||
|
||||
selectedText = '';
|
||||
|
||||
#document: DocumentViewer;
|
||||
|
||||
constructor(
|
||||
@ -120,15 +118,9 @@ export class REDDocumentViewer {
|
||||
return true;
|
||||
}
|
||||
|
||||
async unlock() {
|
||||
const document = await this.PDFDoc;
|
||||
if (!document) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await document.unlock();
|
||||
this._logger.info('[PDF] Unlocked');
|
||||
return true;
|
||||
async blob() {
|
||||
const data = await this.document.getFileData();
|
||||
return new Blob([new Uint8Array(data)], { type: 'application/pdf' });
|
||||
}
|
||||
|
||||
setRectangleToolStyles(color: Color) {
|
||||
|
||||
@ -37,7 +37,6 @@ export class PdfViewer {
|
||||
totalPages$: Observable<number>;
|
||||
|
||||
#instance: WebViewerInstance;
|
||||
#currentBlob: Blob;
|
||||
readonly #compareMode$ = new BehaviorSubject(false);
|
||||
readonly #searchButton: IHeaderElement = {
|
||||
type: 'actionButton',
|
||||
@ -62,10 +61,6 @@ export class PdfViewer {
|
||||
return this.#instance;
|
||||
}
|
||||
|
||||
get blob() {
|
||||
return this.#currentBlob;
|
||||
}
|
||||
|
||||
get PDFNet(): typeof Core.PDFNet {
|
||||
return this.#instance.Core.PDFNet;
|
||||
}
|
||||
@ -157,10 +152,12 @@ export class PdfViewer {
|
||||
}
|
||||
|
||||
openCompareMode() {
|
||||
this._logger.info('[PDF] Open compare mode');
|
||||
this.#compareMode$.next(true);
|
||||
}
|
||||
|
||||
closeCompareMode() {
|
||||
this._logger.info('[PDF] Close compare mode');
|
||||
this.#compareMode$.next(false);
|
||||
}
|
||||
|
||||
@ -173,7 +170,6 @@ export class PdfViewer {
|
||||
|
||||
const document = await this.PDFNet.PDFDoc.createFromBuffer(await blob.arrayBuffer());
|
||||
await document.flattenAnnotations(false);
|
||||
this.#currentBlob = blob;
|
||||
this.fileId = file.fileId;
|
||||
this.dossierId = file.dossierId;
|
||||
|
||||
|
||||
@ -7,8 +7,8 @@ import { TooltipsService } from './tooltips.service';
|
||||
import { PageRotationService } from './page-rotation.service';
|
||||
import { PdfViewer } from './pdf-viewer.service';
|
||||
import { ROTATION_ACTION_BUTTONS } from '../utils/constants';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FilesMapService } from '@services/files/files-map.service';
|
||||
import { REDDocumentViewer } from './document-viewer.service';
|
||||
|
||||
const divider: IHeaderElement = {
|
||||
type: 'divider',
|
||||
@ -34,6 +34,7 @@ export class ViewerHeaderService {
|
||||
private readonly _injector: Injector,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
private readonly _documentViewer: REDDocumentViewer,
|
||||
private readonly _rotationService: PageRotationService,
|
||||
private readonly _tooltipsService: TooltipsService,
|
||||
) {}
|
||||
@ -186,6 +187,11 @@ export class ViewerHeaderService {
|
||||
});
|
||||
}
|
||||
|
||||
resetCompareButtons() {
|
||||
this.disable([HeaderElements.CLOSE_COMPARE_BUTTON]);
|
||||
this.enable([HeaderElements.COMPARE_BUTTON]);
|
||||
}
|
||||
|
||||
#toggleRotationActionButtons() {
|
||||
if (this._rotationService.hasRotations) {
|
||||
this.enable(ROTATION_ACTION_BUTTONS);
|
||||
@ -196,16 +202,13 @@ export class ViewerHeaderService {
|
||||
|
||||
private _closeCompareMode() {
|
||||
this._pdf.closeCompareMode();
|
||||
const activatedRoute = this._injector.get(ActivatedRoute);
|
||||
const dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
|
||||
const fileId = activatedRoute.snapshot.paramMap.get('fileId');
|
||||
const { dossierId, fileId } = this._pdf;
|
||||
const file = this._injector.get(FilesMapService).get(dossierId, fileId);
|
||||
const filename = file.filename ?? 'document.pdf';
|
||||
|
||||
this._pdf.instance.UI.loadDocument(this.#docBeforeCompare, { filename });
|
||||
|
||||
this.disable([HeaderElements.CLOSE_COMPARE_BUTTON]);
|
||||
this.enable([HeaderElements.COMPARE_BUTTON]);
|
||||
this.resetCompareButtons();
|
||||
|
||||
this._pdf.navigateTo(1);
|
||||
}
|
||||
@ -217,10 +220,10 @@ export class ViewerHeaderService {
|
||||
dataElement: HeaderElements.COMPARE_BUTTON,
|
||||
img: this._convertPath('/assets/icons/general/pdftron-action-compare.svg'),
|
||||
title: 'Compare',
|
||||
onClick: () => {
|
||||
onClick: async () => {
|
||||
const element = compareFileInput.nativeElement as HTMLElement;
|
||||
element.click();
|
||||
this.#docBeforeCompare = this._pdf.blob;
|
||||
this.#docBeforeCompare = await this._documentViewer.blob();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user