use pdf viewer instead of instance & extract some methods
This commit is contained in:
parent
f8bbc25c0d
commit
6b38de9892
@ -3,12 +3,12 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { AnnotationActionsService } from '../../services/annotation-actions.service';
|
||||
import { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { AnnotationReferencesService } from '../../services/annotation-references.service';
|
||||
import { MultiSelectService } from '../../services/multi-select.service';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { HelpModeService, ScrollableParentView, ScrollableParentViews } from '@iqser/common-ui';
|
||||
import { PdfViewer } from '../../services/pdf-viewer.service';
|
||||
|
||||
export const AnnotationButtonTypes = {
|
||||
dark: 'dark',
|
||||
@ -26,7 +26,6 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
@Input() buttonType: AnnotationButtonType = AnnotationButtonTypes.dark;
|
||||
@Input() tooltipPosition: 'before' | 'above' = 'before';
|
||||
@Input() canPerformAnnotationActions: boolean;
|
||||
@Input() viewer: WebViewerInstance;
|
||||
@Input() alwaysVisible: boolean;
|
||||
@Output() readonly annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
annotationPermissions: AnnotationPermissions;
|
||||
@ -37,6 +36,7 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
readonly annotationReferencesService: AnnotationReferencesService,
|
||||
readonly helpModeService: HelpModeService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
private readonly _state: FilePreviewStateService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
) {}
|
||||
@ -53,8 +53,8 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
}
|
||||
|
||||
get viewerAnnotations() {
|
||||
if (this.viewer?.Core.annotationManager) {
|
||||
return this._annotations.map(a => this.viewer?.Core.annotationManager?.getAnnotationById(a.id));
|
||||
if (this._pdf.annotationManager) {
|
||||
return this._annotations.map(a => this._pdf.annotationManager.getAnnotationById(a.id));
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@ -76,6 +76,10 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
return ScrollableParentViews.ANNOTATIONS_LIST;
|
||||
}
|
||||
|
||||
get helpModeKey() {
|
||||
return this.annotations[0]?.typeLabel?.split('.')[1];
|
||||
}
|
||||
|
||||
async ngOnChanges(): Promise<void> {
|
||||
await this._setPermissions();
|
||||
}
|
||||
@ -95,28 +99,28 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
|
||||
hideAnnotation($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
this.viewer.Core.annotationManager.hideAnnotations(this.viewerAnnotations);
|
||||
this.viewer.Core.annotationManager.deselectAllAnnotations();
|
||||
this._pdf.annotationManager.hideAnnotations(this.viewerAnnotations);
|
||||
this._pdf.annotationManager.deselectAllAnnotations();
|
||||
this.annotationActionsService.updateHiddenAnnotation(this.annotations, this.viewerAnnotations, true);
|
||||
}
|
||||
|
||||
showAnnotation($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
this.viewer.Core.annotationManager.showAnnotations(this.viewerAnnotations);
|
||||
this.viewer.Core.annotationManager.deselectAllAnnotations();
|
||||
this._pdf.annotationManager.showAnnotations(this.viewerAnnotations);
|
||||
this._pdf.annotationManager.deselectAllAnnotations();
|
||||
this.annotationActionsService.updateHiddenAnnotation(this.annotations, this.viewerAnnotations, false);
|
||||
}
|
||||
|
||||
resize($event: MouseEvent) {
|
||||
this.annotationActionsService.resize($event, this.viewer, this.annotations[0]);
|
||||
this.annotationActionsService.resize($event, this.annotations[0]);
|
||||
}
|
||||
|
||||
acceptResize($event: MouseEvent) {
|
||||
return this.annotationActionsService.acceptResize($event, this.viewer, this.annotations[0], this.annotationsChanged);
|
||||
return this.annotationActionsService.acceptResize($event, this.annotations[0], this.annotationsChanged);
|
||||
}
|
||||
|
||||
cancelResize($event: MouseEvent) {
|
||||
this.annotationActionsService.cancelResize($event, this.viewer, this.annotations[0], this.annotationsChanged);
|
||||
this.annotationActionsService.cancelResize($event, this.annotations[0], this.annotationsChanged);
|
||||
}
|
||||
|
||||
private async _setPermissions() {
|
||||
@ -127,8 +131,4 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
this.annotations,
|
||||
);
|
||||
}
|
||||
|
||||
get helpModeKey() {
|
||||
return this.annotations[0]?.typeLabel?.split('.')[1];
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +60,6 @@
|
||||
[alwaysVisible]="true"
|
||||
[annotations]="selectedAnnotations"
|
||||
[canPerformAnnotationActions]="state.isWritable$ | async"
|
||||
[viewer]="viewer"
|
||||
buttonType="primary"
|
||||
tooltipPosition="above"
|
||||
></redaction-annotation-actions>
|
||||
|
||||
@ -25,7 +25,6 @@ import {
|
||||
shareLast,
|
||||
} from '@iqser/common-ui';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { BehaviorSubject, combineLatest, Observable } from 'rxjs';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import { File } from '@red/domain';
|
||||
@ -36,6 +35,7 @@ import { SkippedService } from '../../services/skipped.service';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { ViewModeService } from '../../services/view-mode.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { PdfViewer } from '../../services/pdf-viewer.service';
|
||||
|
||||
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
||||
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||
@ -56,7 +56,6 @@ export class FileWorkloadComponent {
|
||||
@Input() dialogRef: MatDialogRef<unknown>;
|
||||
@Input() file!: File;
|
||||
@Input() annotationActionsTemplate: TemplateRef<unknown>;
|
||||
@Input() viewer: WebViewerInstance;
|
||||
@Output() readonly selectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() readonly deselectAnnotations = new EventEmitter<AnnotationWrapper[]>();
|
||||
@Output() readonly selectPage = new EventEmitter<number>();
|
||||
@ -73,6 +72,7 @@ export class FileWorkloadComponent {
|
||||
@ViewChild('quickNavigation') private readonly _quickNavigationElement: ElementRef;
|
||||
|
||||
constructor(
|
||||
private readonly _pdf: PdfViewer,
|
||||
readonly filterService: FilterService,
|
||||
readonly skippedService: SkippedService,
|
||||
readonly state: FilePreviewStateService,
|
||||
|
||||
@ -66,7 +66,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
@Output() readonly manualAnnotationRequested = new EventEmitter<ManualRedactionEntryWrapper>();
|
||||
@Output() readonly pageChanged = new EventEmitter<number>();
|
||||
@Output() readonly keyUp = new EventEmitter<KeyboardEvent>();
|
||||
@Output() readonly viewerReady = new EventEmitter<WebViewerInstance>();
|
||||
@Output() readonly viewerReady = new EventEmitter<void>();
|
||||
@Output() readonly annotationsChanged = new EventEmitter<AnnotationWrapper>();
|
||||
@ViewChild('viewer', { static: true }) viewer: ElementRef;
|
||||
@ViewChild('compareFileInput', { static: true }) compareFileInput: ElementRef;
|
||||
@ -118,6 +118,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
this.addActiveScreenSubscription = this.stateService.blob$
|
||||
.pipe(
|
||||
withLatestFrom(this.stateService.file$),
|
||||
tap(() => (this.pdf.ready = false)),
|
||||
tap(([blob, file]) => this._loadDocument(blob, file)),
|
||||
)
|
||||
.subscribe();
|
||||
@ -473,8 +474,8 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
|
||||
this.documentViewer.getTool('AnnotationCreateRectangle').setStyles({
|
||||
StrokeThickness: 2,
|
||||
StrokeColor: this._annotationDrawService.getAndConvertColor(this.instance, dossierTemplateId, 'manual'),
|
||||
FillColor: this._annotationDrawService.getAndConvertColor(this.instance, dossierTemplateId, 'manual'),
|
||||
StrokeColor: this._annotationDrawService.getAndConvertColor(dossierTemplateId, 'manual'),
|
||||
FillColor: this._annotationDrawService.getAndConvertColor(dossierTemplateId, 'manual'),
|
||||
Opacity: 0.6,
|
||||
});
|
||||
}
|
||||
@ -519,12 +520,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
]);
|
||||
}
|
||||
|
||||
const actions = this._annotationActionsService.getViewerAvailableActions(
|
||||
this.instance,
|
||||
this.dossier,
|
||||
annotationWrappers,
|
||||
this.annotationsChanged,
|
||||
);
|
||||
const actions = this._annotationActionsService.getViewerAvailableActions(this.dossier, annotationWrappers, this.annotationsChanged);
|
||||
this.instance.UI.annotationPopup.add(actions);
|
||||
}
|
||||
|
||||
@ -545,7 +541,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
private _addRectangleManualRedaction() {
|
||||
const activeAnnotation = this.annotationManager.getSelectedAnnotations()[0];
|
||||
const activePage = activeAnnotation.getPageNumber();
|
||||
const quads = [this._annotationDrawService.annotationToQuads(activeAnnotation, this.instance)];
|
||||
const quads = [this._annotationDrawService.annotationToQuads(activeAnnotation)];
|
||||
const manualRedaction = this._getManualRedaction({ [activePage]: quads });
|
||||
this._cleanUpSelectionAndButtonState();
|
||||
|
||||
@ -696,7 +692,7 @@ export class PdfViewerComponent extends AutoUnsubscribe implements OnInit, OnCha
|
||||
private _setReadyAndInitialState(): void {
|
||||
this._ngZone.run(() => {
|
||||
this.pdf.ready = true;
|
||||
this.viewerReady.emit(this.instance);
|
||||
this.viewerReady.emit();
|
||||
const routePageNumber: number = this._activatedRoute.snapshot.queryParams.page;
|
||||
this.pageChanged.emit(routePageNumber || 1);
|
||||
this._setInitialDisplayMode();
|
||||
|
||||
@ -66,7 +66,7 @@
|
||||
(keyUp)="handleKeyEvent($event); handleArrowEvent($event)"
|
||||
(manualAnnotationRequested)="openManualAnnotationDialog($event)"
|
||||
(pageChanged)="viewerPageChanged($event)"
|
||||
(viewerReady)="viewerReady($event)"
|
||||
(viewerReady)="viewerReady()"
|
||||
*ngIf="displayPdfViewer"
|
||||
[annotations]="visibleAnnotations"
|
||||
[canPerformActions]="canPerformAnnotationActions$ | async"
|
||||
@ -98,7 +98,6 @@
|
||||
[dialogRef]="dialogRef"
|
||||
[file]="file"
|
||||
[selectedAnnotations]="selectedAnnotations"
|
||||
[viewer]="activeViewer"
|
||||
></redaction-file-workload>
|
||||
</div>
|
||||
</div>
|
||||
@ -110,7 +109,6 @@
|
||||
(annotationsChanged)="annotationsChangedByReviewAction($event)"
|
||||
[annotations]="[annotation]"
|
||||
[canPerformAnnotationActions]="canPerformAnnotationActions$ | async"
|
||||
[viewer]="activeViewer"
|
||||
></redaction-annotation-actions>
|
||||
</ng-template>
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import { ChangeDetectorRef, Component, HostListener, NgZone, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
|
||||
import { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { PdfViewerComponent } from './components/pdf-viewer/pdf-viewer.component';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import {
|
||||
AutoUnsubscribe,
|
||||
CircleButtonTypes,
|
||||
@ -71,13 +70,11 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
selectedAnnotations: AnnotationWrapper[] = [];
|
||||
displayPdfViewer = false;
|
||||
activeViewerPage: number = null;
|
||||
@ViewChild(PdfViewerComponent) readonly viewerComponent: PdfViewerComponent;
|
||||
readonly canPerformAnnotationActions$: Observable<boolean>;
|
||||
readonly fileId = this.stateService.fileId;
|
||||
readonly dossierId = this.stateService.dossierId;
|
||||
readonly file$ = this.stateService.file$.pipe(tap(file => this._fileUpdated(file)));
|
||||
ready = false;
|
||||
private _instance: WebViewerInstance;
|
||||
private _lastPage: string;
|
||||
|
||||
@ViewChild('fileWorkloadComponent') private readonly _workloadComponent: FileWorkloadComponent;
|
||||
@ -140,10 +137,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return this._fileData ? this._fileData.allAnnotations : [];
|
||||
}
|
||||
|
||||
get activeViewer(): WebViewerInstance {
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
private get _fileData(): FileDataModel {
|
||||
return this.stateService.fileData;
|
||||
}
|
||||
@ -162,19 +155,19 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
async updateViewMode(): Promise<void> {
|
||||
if (!this._instance?.Core.documentViewer.getDocument()) {
|
||||
if (!this._pdf.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
const textHighlightAnnotationIds = this._fileData.textHighlightAnnotations.map(a => a.id);
|
||||
const textHighlightAnnotations = this._getAnnotations((a: Core.Annotations.Annotation) =>
|
||||
const textHighlightAnnotations = this._pdf.getAnnotations((a: Core.Annotations.Annotation) =>
|
||||
textHighlightAnnotationIds.includes(a.Id),
|
||||
);
|
||||
|
||||
this._pdf.deleteAnnotations(textHighlightAnnotations);
|
||||
|
||||
const ocrAnnotationIds = this._fileData.allAnnotations.filter(a => a.isOCR).map(a => a.id);
|
||||
const annotations = this._getAnnotations(a => a.getCustomData('redact-manager'));
|
||||
const annotations = this._pdf.getAnnotations(a => a.getCustomData('redact-manager'));
|
||||
const redactions = annotations.filter(a => a.getCustomData('redaction'));
|
||||
|
||||
switch (this._viewModeService.viewMode) {
|
||||
@ -185,8 +178,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
.filter(a => !ocrAnnotationIds.includes(a.Id));
|
||||
const nonStandardEntries = annotations.filter(a => a.getCustomData('changeLogRemoved') === 'true');
|
||||
this._setAnnotationsOpacity(standardEntries, true);
|
||||
this._show(standardEntries);
|
||||
this._hide(nonStandardEntries);
|
||||
this._pdf.showAnnotations(standardEntries);
|
||||
this._pdf.hideAnnotations(nonStandardEntries);
|
||||
break;
|
||||
}
|
||||
case 'DELTA': {
|
||||
@ -194,30 +187,24 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const nonChangeLogEntries = annotations.filter(a => a.getCustomData('changeLog') === 'false');
|
||||
this._setAnnotationsColor(redactions, 'annotationColor');
|
||||
this._setAnnotationsOpacity(changeLogEntries, true);
|
||||
this._show(changeLogEntries);
|
||||
this._hide(nonChangeLogEntries);
|
||||
this._pdf.showAnnotations(changeLogEntries);
|
||||
this._pdf.hideAnnotations(nonChangeLogEntries);
|
||||
break;
|
||||
}
|
||||
case 'REDACTED': {
|
||||
const nonRedactionEntries = annotations.filter(a => a.getCustomData('redaction') === 'false');
|
||||
this._setAnnotationsOpacity(redactions);
|
||||
this._setAnnotationsColor(redactions, 'redactionColor');
|
||||
this._show(redactions);
|
||||
this._hide(nonRedactionEntries);
|
||||
this._pdf.showAnnotations(redactions);
|
||||
this._pdf.hideAnnotations(nonRedactionEntries);
|
||||
break;
|
||||
}
|
||||
case 'TEXT_HIGHLIGHTS': {
|
||||
this._loadingService.start();
|
||||
const textHighlights = await firstValueFrom(this._pdfViewerDataService.loadTextHighlightsFor(this.dossierId, this.fileId));
|
||||
this._hide(annotations);
|
||||
this._pdf.hideAnnotations(annotations);
|
||||
this._fileData.textHighlights = textHighlights;
|
||||
await this._annotationDrawService.drawAnnotations(
|
||||
this.activeViewer,
|
||||
this._fileData.textHighlightAnnotations,
|
||||
this.dossierId,
|
||||
this.fileId,
|
||||
false,
|
||||
);
|
||||
await this._annotationDrawService.drawAnnotations(this._fileData.textHighlightAnnotations);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -264,8 +251,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
rebuildFilters(deletePreviousAnnotations = false): void {
|
||||
const startTime = new Date().getTime();
|
||||
if (deletePreviousAnnotations) {
|
||||
const annotationsToDelete = this._instance?.Core.annotationManager?.getAnnotationsList() || [];
|
||||
this._pdf.deleteAnnotations(annotationsToDelete);
|
||||
this._pdf.deleteAnnotations();
|
||||
|
||||
console.log(`[REDACTION] Delete previous annotations time: ${new Date().getTime() - startTime} ms`);
|
||||
}
|
||||
@ -303,18 +289,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
selectAnnotations(annotations?: AnnotationWrapper[]) {
|
||||
if (annotations) {
|
||||
const annotationsToSelect = this.multiSelectService.isActive ? [...this.selectedAnnotations, ...annotations] : annotations;
|
||||
this.viewerComponent?.pdf?.selectAnnotations(annotationsToSelect, this.multiSelectService.isActive);
|
||||
this._pdf.selectAnnotations(annotationsToSelect, this.multiSelectService.isActive);
|
||||
} else {
|
||||
this.viewerComponent?.pdf?.deselectAllAnnotations();
|
||||
this._pdf.deselectAllAnnotations();
|
||||
}
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
this.viewerComponent.pdf.deselectAnnotations(annotations);
|
||||
this._pdf.deselectAnnotations(annotations);
|
||||
}
|
||||
|
||||
selectPage(pageNumber: number) {
|
||||
this.viewerComponent.pdf.navigateToPage(pageNumber);
|
||||
this._pdf.navigateToPage(pageNumber);
|
||||
this._workloadComponent?.scrollAnnotationsToPage(pageNumber, 'always');
|
||||
this._lastPage = pageNumber.toString();
|
||||
}
|
||||
@ -333,9 +319,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const response = new ManualAnnotationResponse(entryWrapper, addAnnotationResponse);
|
||||
|
||||
if (response?.annotationId) {
|
||||
const annotation = this._instance.Core.annotationManager.getAnnotationById(
|
||||
response.manualRedactionEntryWrapper.rectId,
|
||||
);
|
||||
const annotation = this._pdf.annotationManager.getAnnotationById(response.manualRedactionEntryWrapper.rectId);
|
||||
this._pdf.deleteAnnotations([annotation]);
|
||||
const distinctPages = manualRedactionEntryWrapper.manualRedactionEntry.positions
|
||||
.map(p => p.page)
|
||||
@ -409,19 +393,18 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
};
|
||||
await this._router.navigate([], extras);
|
||||
|
||||
this._setActiveViewerPage();
|
||||
this.activeViewerPage = this._pdf.currentPage;
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
async viewerReady($event: WebViewerInstance) {
|
||||
this._instance = $event;
|
||||
async viewerReady() {
|
||||
this.ready = true;
|
||||
|
||||
await this._stampPDF();
|
||||
await this._reloadAnnotations();
|
||||
this._setExcludedPageStyles();
|
||||
|
||||
this._instance.Core.documentViewer.addEventListener('pageComplete', () => {
|
||||
this._pdf.documentViewer.addEventListener('pageComplete', () => {
|
||||
this._setExcludedPageStyles();
|
||||
});
|
||||
|
||||
@ -430,7 +413,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
if (pageNumber) {
|
||||
setTimeout(() => {
|
||||
this.selectPage(parseInt(pageNumber, 10));
|
||||
this._setActiveViewerPage();
|
||||
this.activeViewerPage = this._pdf.currentPage;
|
||||
this._scrollViews();
|
||||
this._changeDetectorRef.markForCheck();
|
||||
this._loadingService.stop();
|
||||
@ -474,27 +457,14 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
#deactivateMultiSelect(): void {
|
||||
this.multiSelectService.deactivate();
|
||||
this.viewerComponent?.pdf?.deselectAllAnnotations();
|
||||
this._pdf.deselectAllAnnotations();
|
||||
this.handleAnnotationSelected([]);
|
||||
}
|
||||
|
||||
private _setActiveViewerPage() {
|
||||
const currentPage = this._instance?.Core.documentViewer?.getCurrentPage();
|
||||
if (!currentPage) {
|
||||
this.activeViewerPage = 1;
|
||||
} else {
|
||||
this.activeViewerPage = this._viewModeService.isCompare
|
||||
? currentPage % 2 === 0
|
||||
? currentPage / 2
|
||||
: (currentPage + 1) / 2
|
||||
: currentPage;
|
||||
}
|
||||
}
|
||||
|
||||
private _setExcludedPageStyles() {
|
||||
const file = this._filesMapService.get(this.dossierId, this.fileId);
|
||||
setTimeout(() => {
|
||||
const iframeDoc = this._instance.UI.iframeWindow.document;
|
||||
const iframeDoc = this._pdf.UI.iframeWindow.document;
|
||||
const pageContainer = iframeDoc.getElementById(`pageWidgetContainer${this.activeViewerPage}`);
|
||||
if (pageContainer) {
|
||||
if (file.excludedPages.includes(this.activeViewerPage)) {
|
||||
@ -507,15 +477,14 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private async _stampPDF() {
|
||||
if (!this._instance?.Core.documentViewer.getDocument()) {
|
||||
if (!this._pdf.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pdfNet = this._instance.Core.PDFNet;
|
||||
const pdfDoc = await this._instance.Core.documentViewer.getDocument().getPDFDoc();
|
||||
const pdfDoc = await this._pdf.documentViewer.getDocument().getPDFDoc();
|
||||
const file = this._filesMapService.get(this.dossierId, this.fileId);
|
||||
const allPages = [...Array(file.numberOfPages).keys()].map(page => page + 1);
|
||||
await clearStamps(pdfDoc, pdfNet, allPages);
|
||||
await clearStamps(pdfDoc, this._pdf.PDFNet, allPages);
|
||||
|
||||
if (this._viewModeService.isRedacted) {
|
||||
const dossier = this._dossiersService.find(this.dossierId);
|
||||
@ -525,8 +494,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
} else {
|
||||
await this._stampExcludedPages(pdfDoc, file.excludedPages);
|
||||
}
|
||||
this._instance.Core.documentViewer.refreshAll();
|
||||
this._instance.Core.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage);
|
||||
this._pdf.documentViewer.refreshAll();
|
||||
this._pdf.documentViewer.updateView([this.activeViewerPage], this.activeViewerPage);
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
@ -534,7 +503,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
const watermark = await this._watermarkService.getWatermark(dossierTemplateId).toPromise();
|
||||
await stampPDFPage(
|
||||
document,
|
||||
this._instance.Core.PDFNet,
|
||||
this._pdf.PDFNet,
|
||||
watermark.text,
|
||||
watermark.fontSize,
|
||||
watermark.fontType,
|
||||
@ -549,7 +518,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
if (excludedPages && excludedPages.length > 0) {
|
||||
await stampPDFPage(
|
||||
document,
|
||||
this._instance.Core.PDFNet,
|
||||
this._pdf.PDFNet,
|
||||
this._translateService.instant('file-preview.excluded-from-redaction') as string,
|
||||
17,
|
||||
'courier',
|
||||
@ -642,7 +611,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private _deleteAnnotations(annotationsToDelete?: AnnotationWrapper[]) {
|
||||
if (!this._instance?.Core.documentViewer.getDocument()) {
|
||||
if (!this._pdf.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -655,7 +624,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private async _cleanupAndRedrawAnnotations(newAnnotationsFilter?: (annotation: AnnotationWrapper) => boolean) {
|
||||
if (!this._instance?.Core.documentViewer.getDocument()) {
|
||||
if (!this._pdf.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -669,20 +638,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
if (currentFilters) {
|
||||
this._handleDeltaAnnotationFilters(currentFilters, this.visibleAnnotations);
|
||||
}
|
||||
await this._redrawAnnotations(newAnnotations);
|
||||
await this._annotationDrawService.drawAnnotations(newAnnotations);
|
||||
console.log(`[REDACTION] Annotations redraw time: ${new Date().getTime() - startTime} ms for ${newAnnotations.length} annotations`);
|
||||
}
|
||||
|
||||
private _redrawAnnotations(annotations = this.allAnnotations) {
|
||||
return this._annotationDrawService.drawAnnotations(
|
||||
this._instance,
|
||||
annotations,
|
||||
this.fileId,
|
||||
this.dossierId,
|
||||
!!this._viewModeService.isCompare,
|
||||
);
|
||||
}
|
||||
|
||||
private _handleDeltaAnnotationFilters(currentFilters: NestedFilter[], newAnnotations: AnnotationWrapper[]) {
|
||||
const primaryFilterGroup = this._filterService.getGroup('primaryFilters');
|
||||
const primaryFilters = primaryFilterGroup.filters;
|
||||
@ -703,7 +662,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private _findAndDeleteAnnotation(id: string) {
|
||||
const viewerAnnotation = this._instance?.Core.annotationManager.getAnnotationById(id);
|
||||
const viewerAnnotation = this._pdf.annotationManager.getAnnotationById(id);
|
||||
if (viewerAnnotation) {
|
||||
this._pdf.deleteAnnotations([viewerAnnotation]);
|
||||
}
|
||||
@ -717,27 +676,14 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
private _handleIgnoreAnnotationsDrawing(hideSkipped: boolean): void {
|
||||
const ignored = this._getAnnotations(a => a.getCustomData('skipped'));
|
||||
const ignored = this._pdf.getAnnotations(a => a.getCustomData('skipped'));
|
||||
if (hideSkipped) {
|
||||
this._hide(ignored);
|
||||
this._pdf.hideAnnotations(ignored);
|
||||
} else {
|
||||
this._show(ignored);
|
||||
this._pdf.showAnnotations(ignored);
|
||||
}
|
||||
}
|
||||
|
||||
private _getAnnotations(predicate: (value) => boolean) {
|
||||
const annotations = this._instance.Core.annotationManager.getAnnotationsList();
|
||||
return predicate ? annotations.filter(predicate) : annotations;
|
||||
}
|
||||
|
||||
private _hide(annotations: Annotation[]): void {
|
||||
this._instance.Core.annotationManager.hideAnnotations(annotations);
|
||||
}
|
||||
|
||||
private _show(annotations: Annotation[]): void {
|
||||
this._instance.Core.annotationManager.showAnnotations(annotations);
|
||||
}
|
||||
|
||||
private _setAnnotationsOpacity(annotations: Annotation[], restoreToOriginal: boolean = false) {
|
||||
annotations.forEach(annotation => {
|
||||
annotation['Opacity'] = restoreToOriginal ? parseFloat(annotation.getCustomData('opacity')) : 1;
|
||||
@ -746,7 +692,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
private _setAnnotationsColor(annotations: Annotation[], customData: string) {
|
||||
annotations.forEach(annotation => {
|
||||
const color = this._annotationDrawService.convertColor(this._instance, annotation.getCustomData(customData));
|
||||
const color = this._annotationDrawService.convertColor(annotation.getCustomData(customData));
|
||||
annotation['StrokeColor'] = color;
|
||||
annotation['FillColor'] = color;
|
||||
});
|
||||
|
||||
@ -9,7 +9,7 @@ import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { BASE_HREF } from '../../../../../tokens';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import { Dossier, IAddRedactionRequest, ILegalBasisChangeRequest, IRectangle, IResizeRequest } from '@red/domain';
|
||||
import { toPosition } from '../../../utils/pdf-calculation.utils';
|
||||
import { AnnotationDrawService } from './annotation-draw.service';
|
||||
@ -24,6 +24,7 @@ import { defaultDialogConfig } from '@iqser/common-ui';
|
||||
import { filter } from 'rxjs/operators';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { PdfViewer } from './pdf-viewer.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@Injectable()
|
||||
@ -37,6 +38,7 @@ export class AnnotationActionsService {
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _pdf: PdfViewer,
|
||||
private readonly _annotationDrawService: AnnotationDrawService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _screenStateService: FilePreviewStateService,
|
||||
@ -211,7 +213,6 @@ export class AnnotationActionsService {
|
||||
}
|
||||
|
||||
getViewerAvailableActions(
|
||||
viewer: WebViewerInstance,
|
||||
dossier: Dossier,
|
||||
annotations: AnnotationWrapper[],
|
||||
annotationsChanged: EventEmitter<AnnotationWrapper>,
|
||||
@ -238,7 +239,7 @@ export class AnnotationActionsService {
|
||||
title: this._translateService.instant('annotation-actions.resize-accept.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.acceptResize(null, viewer, firstAnnotation, annotationsChanged);
|
||||
this.acceptResize(null, firstAnnotation, annotationsChanged);
|
||||
}),
|
||||
});
|
||||
availableActions.push({
|
||||
@ -247,7 +248,7 @@ export class AnnotationActionsService {
|
||||
title: this._translateService.instant('annotation-actions.resize-cancel.label'),
|
||||
onClick: () =>
|
||||
this._ngZone.run(() => {
|
||||
this.cancelResize(null, viewer, firstAnnotation, annotationsChanged);
|
||||
this.cancelResize(null, firstAnnotation, annotationsChanged);
|
||||
}),
|
||||
});
|
||||
return availableActions;
|
||||
@ -257,7 +258,7 @@ export class AnnotationActionsService {
|
||||
type: 'actionButton',
|
||||
img: this._convertPath('/assets/icons/general/resize.svg'),
|
||||
title: this._translateService.instant('annotation-actions.resize.label'),
|
||||
onClick: () => this._ngZone.run(() => this.resize(null, viewer, annotations[0])),
|
||||
onClick: () => this._ngZone.run(() => this.resize(null, annotations[0])),
|
||||
});
|
||||
}
|
||||
|
||||
@ -419,32 +420,26 @@ export class AnnotationActionsService {
|
||||
annotationToBeUpdated.hidden = hidden;
|
||||
}
|
||||
|
||||
resize($event: MouseEvent, viewer: WebViewerInstance, annotationWrapper: AnnotationWrapper) {
|
||||
resize($event: MouseEvent, annotationWrapper: AnnotationWrapper) {
|
||||
$event?.stopPropagation();
|
||||
|
||||
annotationWrapper.resizing = true;
|
||||
|
||||
const annotationManager = viewer.Core.annotationManager;
|
||||
const viewerAnnotation = annotationManager.getAnnotationById(annotationWrapper.id);
|
||||
const viewerAnnotation = this._pdf.annotationManager.getAnnotationById(annotationWrapper.id);
|
||||
viewerAnnotation.ReadOnly = false;
|
||||
viewerAnnotation.Hidden = false;
|
||||
viewerAnnotation.disableRotationControl();
|
||||
annotationManager.redrawAnnotation(viewerAnnotation);
|
||||
annotationManager.selectAnnotation(viewerAnnotation);
|
||||
this._pdf.annotationManager.redrawAnnotation(viewerAnnotation);
|
||||
this._pdf.annotationManager.selectAnnotation(viewerAnnotation);
|
||||
|
||||
this._annotationDrawService.annotationToQuads(viewerAnnotation, viewer);
|
||||
this._annotationDrawService.annotationToQuads(viewerAnnotation);
|
||||
}
|
||||
|
||||
acceptResize(
|
||||
$event: MouseEvent,
|
||||
viewer: WebViewerInstance,
|
||||
annotationWrapper: AnnotationWrapper,
|
||||
annotationsChanged?: EventEmitter<AnnotationWrapper>,
|
||||
) {
|
||||
acceptResize($event: MouseEvent, annotationWrapper: AnnotationWrapper, annotationsChanged?: EventEmitter<AnnotationWrapper>) {
|
||||
const data = { dossier: this._dossier };
|
||||
const fileId = this._screenStateService.fileId;
|
||||
this._dialogService.openDialog('resizeAnnotation', $event, data, async (result: { comment: string }) => {
|
||||
const textAndPositions = await this._extractTextAndPositions(viewer, annotationWrapper.id);
|
||||
const textAndPositions = await this._extractTextAndPositions(annotationWrapper.id);
|
||||
const text =
|
||||
annotationWrapper.value === 'Rectangle' ? 'Rectangle' : annotationWrapper.isImage ? 'Image' : textAndPositions.text;
|
||||
|
||||
@ -463,21 +458,15 @@ export class AnnotationActionsService {
|
||||
});
|
||||
}
|
||||
|
||||
cancelResize(
|
||||
$event: MouseEvent,
|
||||
viewer: WebViewerInstance,
|
||||
annotationWrapper: AnnotationWrapper,
|
||||
annotationsChanged: EventEmitter<AnnotationWrapper>,
|
||||
) {
|
||||
cancelResize($event: MouseEvent, annotationWrapper: AnnotationWrapper, annotationsChanged: EventEmitter<AnnotationWrapper>) {
|
||||
$event?.stopPropagation();
|
||||
|
||||
annotationWrapper.resizing = false;
|
||||
|
||||
const annotationManager = viewer.Core.annotationManager;
|
||||
const viewerAnnotation = annotationManager.getAnnotationById(annotationWrapper.id);
|
||||
const viewerAnnotation = this._pdf.annotationManager.getAnnotationById(annotationWrapper.id);
|
||||
viewerAnnotation.ReadOnly = false;
|
||||
annotationManager.redrawAnnotation(viewerAnnotation);
|
||||
annotationManager.deselectAllAnnotations();
|
||||
this._pdf.annotationManager.redrawAnnotation(viewerAnnotation);
|
||||
this._pdf.annotationManager.deselectAllAnnotations();
|
||||
annotationsChanged.emit(annotationWrapper);
|
||||
}
|
||||
|
||||
@ -540,19 +529,19 @@ export class AnnotationActionsService {
|
||||
return this._baseHref + path;
|
||||
}
|
||||
|
||||
private async _extractTextAndPositions(viewer: WebViewerInstance, annotationId: string) {
|
||||
const viewerAnnotation = viewer.Core.annotationManager.getAnnotationById(annotationId);
|
||||
private async _extractTextAndPositions(annotationId: string) {
|
||||
const viewerAnnotation = this._pdf.annotationManager.getAnnotationById(annotationId);
|
||||
|
||||
const document = await viewer.Core.documentViewer.getDocument().getPDFDoc();
|
||||
const document = await this._pdf.documentViewer.getDocument().getPDFDoc();
|
||||
const page = await document.getPage(viewerAnnotation.getPageNumber());
|
||||
if (viewerAnnotation instanceof viewer.Core.Annotations.TextHighlightAnnotation) {
|
||||
if (viewerAnnotation instanceof this._pdf.Annotations.TextHighlightAnnotation) {
|
||||
const words = [];
|
||||
const rectangles: IRectangle[] = [];
|
||||
for (const quad of viewerAnnotation.Quads) {
|
||||
const rect = toPosition(
|
||||
viewerAnnotation.getPageNumber(),
|
||||
viewer.Core.documentViewer.getPageHeight(viewerAnnotation.getPageNumber()),
|
||||
this._translateQuads(viewer, viewerAnnotation.getPageNumber(), quad),
|
||||
this._pdf.documentViewer.getPageHeight(viewerAnnotation.getPageNumber()),
|
||||
this._translateQuads(viewerAnnotation.getPageNumber(), quad),
|
||||
);
|
||||
rectangles.push(rect);
|
||||
|
||||
@ -560,13 +549,13 @@ export class AnnotationActionsService {
|
||||
// TODO: so that we do not extract text from line above/line below
|
||||
const percentHeightOffset = rect.height / 10;
|
||||
|
||||
const pdfNetRect = new viewer.Core.PDFNet.Rect(
|
||||
const pdfNetRect = new this._pdf.instance.Core.PDFNet.Rect(
|
||||
rect.topLeft.x,
|
||||
rect.topLeft.y + percentHeightOffset,
|
||||
rect.topLeft.x + rect.width,
|
||||
rect.topLeft.y + rect.height - percentHeightOffset,
|
||||
);
|
||||
const quadWords = await this._extractTextFromRect(viewer, page, pdfNetRect);
|
||||
const quadWords = await this._extractTextFromRect(page, pdfNetRect);
|
||||
words.push(...quadWords);
|
||||
}
|
||||
|
||||
@ -579,8 +568,8 @@ export class AnnotationActionsService {
|
||||
} else {
|
||||
const rect = toPosition(
|
||||
viewerAnnotation.getPageNumber(),
|
||||
viewer.Core.documentViewer.getPageHeight(viewerAnnotation.getPageNumber()),
|
||||
this._annotationDrawService.annotationToQuads(viewerAnnotation, viewer),
|
||||
this._pdf.documentViewer.getPageHeight(viewerAnnotation.getPageNumber()),
|
||||
this._annotationDrawService.annotationToQuads(viewerAnnotation),
|
||||
);
|
||||
return {
|
||||
positions: [rect],
|
||||
@ -589,16 +578,16 @@ export class AnnotationActionsService {
|
||||
}
|
||||
}
|
||||
|
||||
private _translateQuads(viewer: WebViewerInstance, page: number, quads: any) {
|
||||
const rotation = viewer.Core.documentViewer.getCompleteRotation(page);
|
||||
private _translateQuads(page: number, quads: any) {
|
||||
const rotation = this._pdf.documentViewer.getCompleteRotation(page);
|
||||
return translateQuads(page, rotation, quads);
|
||||
}
|
||||
|
||||
private async _extractTextFromRect(viewer: WebViewerInstance, page: Core.PDFNet.Page, rect: Core.PDFNet.Rect) {
|
||||
const txt = await viewer.Core.PDFNet.TextExtractor.create();
|
||||
private async _extractTextFromRect(page: Core.PDFNet.Page, rect: Core.PDFNet.Rect) {
|
||||
const txt = await this._pdf.PDFNet.TextExtractor.create();
|
||||
txt.begin(page, rect); // Read the page.
|
||||
|
||||
const words = [];
|
||||
const words: string[] = [];
|
||||
// Extract words one by one.
|
||||
let line = await txt.getFirstLine();
|
||||
for (; await line.isValid(); line = await line.getNextLine()) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import { hexToRgb } from '@utils/functions';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
@ -11,6 +11,9 @@ import { SkippedService } from './skipped.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { DossiersService } from '../../../../../services/dossiers/dossiers.service';
|
||||
import { PdfViewer } from './pdf-viewer.service';
|
||||
import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { ViewModeService } from './view-mode.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@Injectable()
|
||||
@ -25,57 +28,54 @@ export class AnnotationDrawService {
|
||||
private readonly _redactionLogService: RedactionLogService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _skippedService: SkippedService,
|
||||
private readonly _pdf: PdfViewer,
|
||||
private readonly _state: FilePreviewStateService,
|
||||
private readonly _viewModeService: ViewModeService,
|
||||
) {}
|
||||
|
||||
async drawAnnotations(
|
||||
activeViewer: WebViewerInstance,
|
||||
annotationWrappers: AnnotationWrapper[],
|
||||
fileId: string,
|
||||
dossierId: string,
|
||||
compareMode = false,
|
||||
) {
|
||||
if (!activeViewer) {
|
||||
async drawAnnotations(annotationWrappers: AnnotationWrapper[]) {
|
||||
if (!this._pdf.instance || !this._pdf.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
const pdfNet = activeViewer.Core.PDFNet;
|
||||
const pdfNet = this._pdf.instance.Core.PDFNet;
|
||||
|
||||
await pdfNet.runWithCleanup(
|
||||
async () => {
|
||||
await this._drawAnnotations(activeViewer, annotationWrappers, fileId, dossierId, compareMode);
|
||||
await this._drawAnnotations(annotationWrappers);
|
||||
},
|
||||
environment.licenseKey ? atob(environment.licenseKey) : null,
|
||||
);
|
||||
}
|
||||
|
||||
getColor(activeViewer: WebViewerInstance, dossierTemplateId: string, superType: string, dictionary?: string) {
|
||||
getColor(superType: string, dictionary?: string) {
|
||||
let color: string;
|
||||
switch (superType) {
|
||||
case 'hint':
|
||||
case 'redaction':
|
||||
case 'recommendation':
|
||||
color = this._dictionariesMapService.getDictionaryColor(dictionary, dossierTemplateId);
|
||||
color = this._dictionariesMapService.getDictionaryColor(dictionary, this._state.dossierTemplateId);
|
||||
break;
|
||||
case 'skipped':
|
||||
color = this._dictionariesMapService.getDictionaryColor(superType, dossierTemplateId);
|
||||
color = this._dictionariesMapService.getDictionaryColor(superType, this._state.dossierTemplateId);
|
||||
break;
|
||||
default:
|
||||
color = this._dictionariesMapService.getDictionaryColor(superType, dossierTemplateId);
|
||||
color = this._dictionariesMapService.getDictionaryColor(superType, this._state.dossierTemplateId);
|
||||
break;
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
||||
getAndConvertColor(activeViewer: WebViewerInstance, dossierTemplateId: string, superType: string, dictionary?: string) {
|
||||
return this.convertColor(activeViewer, this.getColor(activeViewer, dossierTemplateId, superType, dictionary));
|
||||
getAndConvertColor(superType: string, dictionary?: string) {
|
||||
return this.convertColor(this.getColor(superType, dictionary));
|
||||
}
|
||||
|
||||
convertColor(activeViewer: WebViewerInstance, hexColor: string) {
|
||||
convertColor(hexColor: string) {
|
||||
const rgbColor = hexToRgb(hexColor);
|
||||
return new activeViewer.Core.Annotations.Color(rgbColor.r, rgbColor.g, rgbColor.b);
|
||||
return new this._pdf.Annotations.Color(rgbColor.r, rgbColor.g, rgbColor.b);
|
||||
}
|
||||
|
||||
annotationToQuads(annotation: Annotation, activeViewer: WebViewerInstance) {
|
||||
annotationToQuads(annotation: Annotation) {
|
||||
const x1 = annotation.getRect().x1;
|
||||
const y1 = annotation.getRect().y1 + annotation.getRect().getHeight();
|
||||
|
||||
@ -88,51 +88,42 @@ export class AnnotationDrawService {
|
||||
const x4 = annotation.getRect().x1;
|
||||
const y4 = annotation.getRect().y1;
|
||||
|
||||
return new activeViewer.Core.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
return new this._pdf.instance.Core.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
private async _drawAnnotations(
|
||||
activeViewer: WebViewerInstance,
|
||||
annotationWrappers: AnnotationWrapper[],
|
||||
fileId: string,
|
||||
dossierId: string,
|
||||
compareMode: boolean,
|
||||
) {
|
||||
const annotations = annotationWrappers
|
||||
.map(annotation => this._computeAnnotation(activeViewer, annotation, dossierId, compareMode))
|
||||
.filter(a => !!a);
|
||||
const annotationManager = activeViewer.Core.annotationManager;
|
||||
private async _drawAnnotations(annotationWrappers: AnnotationWrapper[]) {
|
||||
const annotations = annotationWrappers.map(annotation => this._computeAnnotation(annotation)).filter(a => !!a);
|
||||
const annotationManager = this._pdf.annotationManager;
|
||||
annotationManager.addAnnotations(annotations, { imported: true });
|
||||
await annotationManager.drawAnnotationsFromList(annotations);
|
||||
|
||||
if (this._userPreferenceService.areDevFeaturesEnabled) {
|
||||
const sectionsGrid = await firstValueFrom(this._redactionLogService.getSectionGrid(dossierId, fileId)).catch(() => ({
|
||||
rectanglesPerPage: {},
|
||||
}));
|
||||
await this._drawSections(activeViewer, sectionsGrid, dossierId);
|
||||
const { dossierId, fileId } = this._state;
|
||||
const sectionsGrid$ = this._redactionLogService.getSectionGrid(dossierId, fileId);
|
||||
const sectionsGrid = await firstValueFrom(sectionsGrid$).catch(() => ({ rectanglesPerPage: {} }));
|
||||
await this._drawSections(sectionsGrid);
|
||||
}
|
||||
}
|
||||
|
||||
private async _drawSections(activeViewer: WebViewerInstance, sectionGrid: ISectionGrid, dossierId: string) {
|
||||
private async _drawSections(sectionGrid: ISectionGrid) {
|
||||
const sections: Core.Annotations.RectangleAnnotation[] = [];
|
||||
for (const page of Object.keys(sectionGrid.rectanglesPerPage)) {
|
||||
const sectionRectangles = sectionGrid.rectanglesPerPage[page];
|
||||
sectionRectangles.forEach(sectionRectangle => {
|
||||
sections.push(this._computeSection(activeViewer, parseInt(page, 10), sectionRectangle, dossierId));
|
||||
sections.push(this._computeSection(parseInt(page, 10), sectionRectangle));
|
||||
// sectionRectangle.tableCells?.forEach(cell =>{
|
||||
// sections.push(this.computeSection(activeViewer, parseInt(page, 10), cell));
|
||||
// })
|
||||
});
|
||||
}
|
||||
const annotationManager = activeViewer.Core.annotationManager;
|
||||
const annotationManager = this._pdf.annotationManager;
|
||||
annotationManager.addAnnotations(sections, { imported: true });
|
||||
await annotationManager.drawAnnotationsFromList(sections);
|
||||
}
|
||||
|
||||
private _computeSection(activeViewer: WebViewerInstance, pageNumber: number, sectionRectangle: ISectionRectangle, dossierId: string) {
|
||||
const dossierTemplateId = this._dossiersService.find(dossierId).dossierTemplateId;
|
||||
const rectangleAnnot = new activeViewer.Core.Annotations.RectangleAnnotation();
|
||||
const pageHeight = activeViewer.Core.documentViewer.getPageHeight(pageNumber);
|
||||
private _computeSection(pageNumber: number, sectionRectangle: ISectionRectangle) {
|
||||
const rectangleAnnot = new this._pdf.Annotations.RectangleAnnotation();
|
||||
const pageHeight = this._pdf.documentViewer.getPageHeight(pageNumber);
|
||||
const rectangle: IRectangle = {
|
||||
topLeft: sectionRectangle.topLeft,
|
||||
page: pageNumber,
|
||||
@ -145,27 +136,22 @@ export class AnnotationDrawService {
|
||||
rectangleAnnot.Width = rectangle.width + 2;
|
||||
rectangleAnnot.Height = rectangle.height + 2;
|
||||
rectangleAnnot.ReadOnly = true;
|
||||
rectangleAnnot.StrokeColor = this.getAndConvertColor(activeViewer, dossierTemplateId, 'analysis', 'analysis');
|
||||
rectangleAnnot.StrokeColor = this.getAndConvertColor('analysis', 'analysis');
|
||||
rectangleAnnot.StrokeThickness = 1;
|
||||
|
||||
return rectangleAnnot;
|
||||
}
|
||||
|
||||
private _computeAnnotation(
|
||||
activeViewer: WebViewerInstance,
|
||||
annotationWrapper: AnnotationWrapper,
|
||||
dossierId: string,
|
||||
compareMode: boolean,
|
||||
) {
|
||||
const pageNumber = compareMode ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
|
||||
if (pageNumber > activeViewer.Core.documentViewer.getPageCount()) {
|
||||
private _computeAnnotation(annotationWrapper: AnnotationWrapper) {
|
||||
const pageNumber = this._viewModeService.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
|
||||
if (pageNumber > this._pdf.documentViewer.getPageCount()) {
|
||||
// skip imported annotations from files that have more pages than the current one
|
||||
return;
|
||||
}
|
||||
|
||||
if (annotationWrapper.superType === 'text-highlight') {
|
||||
const rectangleAnnot = new activeViewer.Core.Annotations.RectangleAnnotation();
|
||||
const pageHeight = activeViewer.Core.documentViewer.getPageHeight(pageNumber);
|
||||
const rectangleAnnot = new this._pdf.Annotations.RectangleAnnotation();
|
||||
const pageHeight = this._pdf.documentViewer.getPageHeight(pageNumber);
|
||||
const rectangle: IRectangle = annotationWrapper.positions[0];
|
||||
rectangleAnnot.PageNumber = pageNumber;
|
||||
rectangleAnnot.X = rectangle.topLeft.x;
|
||||
@ -173,37 +159,30 @@ export class AnnotationDrawService {
|
||||
rectangleAnnot.Width = rectangle.width;
|
||||
rectangleAnnot.Height = rectangle.height;
|
||||
rectangleAnnot.ReadOnly = true;
|
||||
rectangleAnnot.StrokeColor = this.convertColor(activeViewer, annotationWrapper.color);
|
||||
rectangleAnnot.StrokeColor = this.convertColor(annotationWrapper.color);
|
||||
rectangleAnnot.StrokeThickness = 1;
|
||||
rectangleAnnot.Id = annotationWrapper.id;
|
||||
|
||||
return rectangleAnnot;
|
||||
}
|
||||
|
||||
const dossierTemplateId = this._dossiersService.find(dossierId).dossierTemplateId;
|
||||
|
||||
let annotation: Core.Annotations.RectangleAnnotation | Core.Annotations.TextHighlightAnnotation;
|
||||
if (annotationWrapper.rectangle || annotationWrapper.isImage) {
|
||||
annotation = new activeViewer.Core.Annotations.RectangleAnnotation();
|
||||
const pageHeight = activeViewer.Core.documentViewer.getPageHeight(pageNumber);
|
||||
annotation = new this._pdf.Annotations.RectangleAnnotation();
|
||||
const pageHeight = this._pdf.documentViewer.getPageHeight(pageNumber);
|
||||
const firstPosition = annotationWrapper.positions[0];
|
||||
annotation.X = firstPosition.topLeft.x;
|
||||
annotation.Y = pageHeight - (firstPosition.topLeft.y + firstPosition.height);
|
||||
annotation.Width = firstPosition.width;
|
||||
annotation.FillColor = this.getAndConvertColor(
|
||||
activeViewer,
|
||||
dossierTemplateId,
|
||||
annotationWrapper.superType,
|
||||
annotationWrapper.type,
|
||||
);
|
||||
annotation.FillColor = this.getAndConvertColor(annotationWrapper.superType, annotationWrapper.type);
|
||||
annotation.Opacity = annotationWrapper.isChangeLogRemoved
|
||||
? AnnotationDrawService.DEFAULT_REMOVED_ANNOTATION_OPACITY
|
||||
: AnnotationDrawService.DEFAULT_RECTANGLE_ANNOTATION_OPACITY;
|
||||
annotation.Height = firstPosition.height;
|
||||
annotation.Intensity = 100;
|
||||
} else {
|
||||
annotation = new activeViewer.Core.Annotations.TextHighlightAnnotation();
|
||||
annotation.Quads = this._rectanglesToQuads(annotationWrapper.positions, activeViewer, pageNumber);
|
||||
annotation = new this._pdf.Annotations.TextHighlightAnnotation();
|
||||
annotation.Quads = this._rectanglesToQuads(annotationWrapper.positions, pageNumber);
|
||||
annotation.Opacity = annotationWrapper.isChangeLogRemoved
|
||||
? AnnotationDrawService.DEFAULT_REMOVED_ANNOTATION_OPACITY
|
||||
: AnnotationDrawService.DEFAULT_TEXT_ANNOTATION_OPACITY;
|
||||
@ -212,12 +191,7 @@ export class AnnotationDrawService {
|
||||
annotation.setContents(annotationWrapper.content);
|
||||
|
||||
annotation.PageNumber = pageNumber;
|
||||
annotation.StrokeColor = this.getAndConvertColor(
|
||||
activeViewer,
|
||||
dossierTemplateId,
|
||||
annotationWrapper.superType,
|
||||
annotationWrapper.type,
|
||||
);
|
||||
annotation.StrokeColor = this.getAndConvertColor(annotationWrapper.superType, annotationWrapper.type);
|
||||
annotation.Id = annotationWrapper.id;
|
||||
annotation.ReadOnly = true;
|
||||
// change log entries are drawn lighter
|
||||
@ -233,21 +207,18 @@ export class AnnotationDrawService {
|
||||
annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry));
|
||||
annotation.setCustomData('changeLogRemoved', String(annotationWrapper.isChangeLogRemoved));
|
||||
annotation.setCustomData('opacity', String(annotation.Opacity));
|
||||
annotation.setCustomData('redactionColor', String(this.getColor(activeViewer, dossierTemplateId, 'redaction', 'preview')));
|
||||
annotation.setCustomData(
|
||||
'annotationColor',
|
||||
String(this.getColor(activeViewer, dossierTemplateId, annotationWrapper.superType, annotationWrapper.type)),
|
||||
);
|
||||
annotation.setCustomData('redactionColor', String(this.getColor('redaction', 'redaction')));
|
||||
annotation.setCustomData('annotationColor', String(this.getColor(annotationWrapper.superType, annotationWrapper.type)));
|
||||
|
||||
return annotation;
|
||||
}
|
||||
|
||||
private _rectanglesToQuads(positions: IRectangle[], activeViewer: WebViewerInstance, pageNumber: number): any[] {
|
||||
const pageHeight = activeViewer.Core.documentViewer.getPageHeight(pageNumber);
|
||||
return positions.map(p => this._rectangleToQuad(p, activeViewer, pageHeight));
|
||||
private _rectanglesToQuads(positions: IRectangle[], pageNumber: number): any[] {
|
||||
const pageHeight = this._pdf.documentViewer.getPageHeight(pageNumber);
|
||||
return positions.map(p => this._rectangleToQuad(p, pageHeight));
|
||||
}
|
||||
|
||||
private _rectangleToQuad(rectangle: IRectangle, activeViewer: WebViewerInstance, pageHeight: number): any {
|
||||
private _rectangleToQuad(rectangle: IRectangle, pageHeight: number): any {
|
||||
const x1 = rectangle.topLeft.x;
|
||||
const y1 = pageHeight - (rectangle.topLeft.y + rectangle.height);
|
||||
|
||||
@ -260,6 +231,6 @@ export class AnnotationDrawService {
|
||||
const x4 = rectangle.topLeft.x;
|
||||
const y4 = pageHeight - rectangle.topLeft.y;
|
||||
|
||||
return new activeViewer.Core.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
return new this._pdf.instance.Core.Math.Quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,16 +56,20 @@ export class PdfViewer {
|
||||
return this.instance.UI;
|
||||
}
|
||||
|
||||
get Annotations() {
|
||||
return this.instance.Core.Annotations;
|
||||
}
|
||||
|
||||
get PDFNet() {
|
||||
return this.instance.Core.PDFNet;
|
||||
}
|
||||
|
||||
get paginationOffset() {
|
||||
return this.viewModeService.isCompare ? 2 : 1;
|
||||
}
|
||||
|
||||
get currentPage() {
|
||||
try {
|
||||
return this.viewModeService.isCompare ? Math.ceil(this._currentInternalPage / 2) : this._currentInternalPage;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
return this.viewModeService.isCompare ? Math.ceil(this._currentInternalPage / 2) : this._currentInternalPage;
|
||||
}
|
||||
|
||||
get totalPages() {
|
||||
@ -73,19 +77,36 @@ export class PdfViewer {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return this.viewModeService.isCompare ? Math.ceil(this._totalInternalPages / 2) : this._totalInternalPages;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
return this.viewModeService.isCompare ? Math.ceil(this._totalInternalPages / 2) : this._totalInternalPages;
|
||||
}
|
||||
|
||||
private get _currentInternalPage() {
|
||||
return this.instance?.Core.documentViewer?.getCurrentPage();
|
||||
return this.documentViewer?.getCurrentPage() ?? 1;
|
||||
}
|
||||
|
||||
private get _totalInternalPages() {
|
||||
return this.instance?.Core.documentViewer?.getPageCount();
|
||||
return this.documentViewer?.getPageCount() ?? 1;
|
||||
}
|
||||
|
||||
hideAnnotations(annotations: Annotation[]): void {
|
||||
this.annotationManager.hideAnnotations(annotations);
|
||||
}
|
||||
|
||||
showAnnotations(annotations: Annotation[]): void {
|
||||
this.annotationManager.showAnnotations(annotations);
|
||||
}
|
||||
|
||||
getAnnotations(predicate?: (value) => boolean) {
|
||||
const annotations = this.annotationManager?.getAnnotationsList() ?? [];
|
||||
return predicate ? annotations.filter(predicate) : annotations;
|
||||
}
|
||||
|
||||
getAnnotationsById(ids: readonly string[]) {
|
||||
if (this.annotationManager) {
|
||||
return ids.map(id => this.annotationManager.getAnnotationById(id));
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
async loadViewer(htmlElement: HTMLElement) {
|
||||
@ -140,6 +161,10 @@ export class PdfViewer {
|
||||
}
|
||||
|
||||
deselectAllAnnotations() {
|
||||
if (!this.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.annotationManager.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
@ -147,16 +172,21 @@ export class PdfViewer {
|
||||
if (!annotations) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!multiSelectActive) {
|
||||
this.deselectAllAnnotations();
|
||||
}
|
||||
|
||||
const annotationsFromViewer = annotations.map(ann => this._getAnnotationById(ann.id));
|
||||
const annotationsFromViewer = this.getAnnotationsById(annotations.map(a => a.id));
|
||||
this.annotationManager.jumpToAnnotation(annotationsFromViewer[0]);
|
||||
this.annotationManager.selectAnnotations(annotationsFromViewer);
|
||||
}
|
||||
|
||||
deleteAnnotations(annotations: Annotation[] = this.annotationManager?.getAnnotationsList() ?? []) {
|
||||
deleteAnnotations(annotations: Annotation[] = this.getAnnotations()) {
|
||||
if (!this.ready) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.annotationManager.deleteAnnotations(annotations, {
|
||||
imported: true,
|
||||
@ -168,7 +198,7 @@ export class PdfViewer {
|
||||
}
|
||||
|
||||
deselectAnnotations(annotations: AnnotationWrapper[]) {
|
||||
const ann = annotations.map(a => this._getAnnotationById(a.id));
|
||||
const ann = this.getAnnotationsById(annotations.map(a => a.id));
|
||||
this.annotationManager.deselectAnnotations(ann);
|
||||
}
|
||||
|
||||
@ -178,10 +208,6 @@ export class PdfViewer {
|
||||
}
|
||||
}
|
||||
|
||||
private _getAnnotationById(id: string): Annotation {
|
||||
return this.annotationManager.getAnnotationById(id);
|
||||
}
|
||||
|
||||
#convertPath(path: string) {
|
||||
return `${this._baseHref}${path}`;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user