From 5a3f6852ea5d293f8cf69afaacc68a83fcf72d1b Mon Sep 17 00:00:00 2001 From: Timo Bejan Date: Tue, 3 Nov 2020 09:26:30 +0200 Subject: [PATCH] manual redaction actions are now linked in real time to reviewer popup --- .../file-preview-screen.component.html | 1 + .../file-preview-screen.component.ts | 68 ++++++++------ .../file/pdf-viewer/pdf-viewer.component.ts | 89 +++++++++++-------- .../file/service/file-download.service.ts | 23 +++-- .../src/lib/model/manualRedactionEntry.ts | 2 + 5 files changed, 111 insertions(+), 72 deletions(-) diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index e784e9cfe..3e02e32cb 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -74,6 +74,7 @@
{ - this.fileData = fileDataModel; + this._fileDownloadService.loadActiveFileData().subscribe((fileDataModel) => { + this.fileData = fileDataModel; - const manualRedactionAnnotations = fileDataModel.entriesToAdd.map((mr) => - AnnotationWrapper.fromManualRedaction( - mr, - fileDataModel.manualRedactions.comments - ) - ); - const redactionLogAnnotations = fileDataModel.redactionLog.redactionLogEntry.map( - (rde) => - AnnotationWrapper.fromRedactionLog( - rde, - fileDataModel.manualRedactions.comments - ) - ); + const manualRedactionAnnotations = fileDataModel.entriesToAdd.map((mr) => + AnnotationWrapper.fromManualRedaction(mr, fileDataModel.manualRedactions.comments) + ); + const redactionLogAnnotations = fileDataModel.redactionLog.redactionLogEntry.map( + (rde) => + AnnotationWrapper.fromRedactionLog(rde, fileDataModel.manualRedactions.comments) + ); - this.annotations.push(...manualRedactionAnnotations); - this.annotations.push(...redactionLogAnnotations); - this.filters = this._annotationProcessingService.getAnnotationFilter( - this.annotations - ); - this.filtersChanged(this.filters); - this._changeDetectorRef.detectChanges(); - }); + this.annotations.push(...manualRedactionAnnotations); + this.annotations.push(...redactionLogAnnotations); + this.filters = this._annotationProcessingService.getAnnotationFilter(this.annotations); + this.filtersChanged(this.filters); + this._changeDetectorRef.detectChanges(); + }); } public openFileDetailsDialog($event: MouseEvent) { @@ -207,7 +197,7 @@ export class FilePreviewScreenComponent implements OnInit { this._dialogRef = this._dialogService.openManualRedactionDialog( $event, (response: ManualAnnotationResponse) => { - // TODO REDRAW ANNOTATIONS FROM MANUAL REQUESTS + this._cleanupAndRedrawManualAnnotations(); } ); }); @@ -280,8 +270,7 @@ export class FilePreviewScreenComponent implements OnInit { $event, annotation, () => { - // TODO DELETE ANNOTATIOn - //this.activeViewer.annotManager.deleteAnnotation(annotation, false, true); + this._cleanupAndRedrawManualAnnotations(); } ); }); @@ -449,4 +438,27 @@ export class FilePreviewScreenComponent implements OnInit { $event.preventDefault(); } } + + private _cleanupAndRedrawManualAnnotations() { + this._fileDownloadService + .loadActiveFileManualAnnotations() + .subscribe((manualRedactions) => { + this.fileData.manualRedactions = manualRedactions; + + const annotationsToRemove = []; + this.fileData.entriesToAdd.forEach((manuallyAddedEntry) => { + const annotation = this.activeViewer.annotManager.getAnnotationById( + manuallyAddedEntry.id + ); + if (annotation) { + annotationsToRemove.push(annotation); + } + }); + this.activeViewer.annotManager.deleteAnnotations(annotationsToRemove, false, true); + this._annotationDrawService.drawAnnotations( + this.instance, + this.fileData.entriesToAdd + ); + }); + } } diff --git a/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts b/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts index ea2329877..f7b6a3911 100644 --- a/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts +++ b/apps/red-ui/src/app/screens/file/pdf-viewer/pdf-viewer.component.ts @@ -46,6 +46,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { @Input() fileData: Blob; @Input() fileStatus: FileStatus; + @Input() isReviewer = false; @Output() fileReady = new EventEmitter(); @Output() annotationSelected = new EventEmitter(); @@ -55,8 +56,6 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { @Output() viewerReady = new EventEmitter(); - @Input() flag = false; - @ViewChild('viewer', { static: true }) viewer: ElementRef; instance: WebViewerInstance; @@ -77,6 +76,10 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { if (changes.fileData && !changes.fileData.firstChange) { this._changeDocument(); } + if (changes.isReviewer) { + this._handleCustomActions(); + } + console.log(this.isReviewer); } ngAfterViewInit(): void { @@ -169,41 +172,52 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { }, 250); } }); - if (this._appStateService.isActiveFileDocumentReviewer) { - this.instance.textPopup.add({ - type: 'actionButton', - img: '/assets/icons/general/add-dictionary.svg', - title: this._translateService.instant( - this._manualAnnotationService.getTitle('DICTIONARY') - ), - onClick: () => { - const mre = this._getManualRedactionEntry(); - this.manualAnnotationRequested.emit( - new ManualRedactionEntryWrapper( - this.instance.docViewer.getSelectedTextQuads(), - mre, - 'DICTIONARY' - ) - ); - } - }); - this.instance.textPopup.add({ - type: 'actionButton', - img: '/assets/icons/general/add-redaction.svg', - title: this._translateService.instant( - this._manualAnnotationService.getTitle('REDACTION') - ), - onClick: () => { - const mre = this._getManualRedactionEntry(); - this.manualAnnotationRequested.emit( - new ManualRedactionEntryWrapper( - this.instance.docViewer.getSelectedTextQuads(), - mre, - 'REDACTION' - ) - ); - } - }); + this.instance.textPopup.add({ + type: 'actionButton', + dataElement: 'add-dictionary', + img: '/assets/icons/general/add-dictionary.svg', + title: this._translateService.instant( + this._manualAnnotationService.getTitle('DICTIONARY') + ), + onClick: () => { + const mre = this._getManualRedactionEntry(); + this.manualAnnotationRequested.emit( + new ManualRedactionEntryWrapper( + this.instance.docViewer.getSelectedTextQuads(), + mre, + 'DICTIONARY' + ) + ); + } + }); + this.instance.textPopup.add({ + type: 'actionButton', + dataElement: 'add-redaction', + img: '/assets/icons/general/add-redaction.svg', + title: this._translateService.instant( + this._manualAnnotationService.getTitle('REDACTION') + ), + onClick: () => { + const mre = this._getManualRedactionEntry(); + this.manualAnnotationRequested.emit( + new ManualRedactionEntryWrapper( + this.instance.docViewer.getSelectedTextQuads(), + mre, + 'REDACTION' + ) + ); + } + }); + this._handleCustomActions(); + } + + private _handleCustomActions() { + if (this.instance) { + if (this.isReviewer) { + this.instance.enableElements(['add-redaction', 'add-dictionary']); + } else { + this.instance.disableElements(['add-redaction', 'add-dictionary']); + } } } @@ -241,7 +255,6 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges { public selectAnnotation(annotation: AnnotationWrapper) { this.instance.annotManager.deselectAllAnnotations(); const annotationFromViewer = this.instance.annotManager.getAnnotationById(annotation.id); - console.log(annotationFromViewer); this.instance.annotManager.selectAnnotation(annotationFromViewer); this.navigateToPage(annotation.pageNumber); } diff --git a/apps/red-ui/src/app/screens/file/service/file-download.service.ts b/apps/red-ui/src/app/screens/file/service/file-download.service.ts index d01693296..46c2e0898 100644 --- a/apps/red-ui/src/app/screens/file/service/file-download.service.ts +++ b/apps/red-ui/src/app/screens/file/service/file-download.service.ts @@ -8,24 +8,35 @@ import { } from '@redaction/red-ui-http'; import { FileType } from '../model/file-type'; import { FileDataModel } from '../model/file-data.model'; +import { AppStateService } from '../../../state/app-state.service'; @Injectable({ providedIn: 'root' }) export class FileDownloadService { constructor( + private readonly _appStateService: AppStateService, private readonly _fileUploadControllerService: FileUploadControllerService, private readonly _manualRedactionControllerService: ManualRedactionControllerService, private readonly _redactionLogControllerService: RedactionLogControllerService ) {} - public loadFileData(projectId: string, fileId: string): Observable { - const annotatedObs = this.loadFile('ANNOTATED', fileId); - const redactedObs = this.loadFile('REDACTED', fileId); - const reactionLogObs = this._redactionLogControllerService.getRedactionLog(fileId); + public loadActiveFileManualAnnotations() { + return this._manualRedactionControllerService.getManualRedaction( + this._appStateService.activeProjectId, + this._appStateService.activeFileId + ); + } + + public loadActiveFileData(): Observable { + const annotatedObs = this.loadFile('ANNOTATED', this._appStateService.activeFileId); + const redactedObs = this.loadFile('REDACTED', this._appStateService.activeFileId); + const reactionLogObs = this._redactionLogControllerService.getRedactionLog( + this._appStateService.activeFileId + ); const manualRedactionsObs = this._manualRedactionControllerService.getManualRedaction( - projectId, - fileId + this._appStateService.activeProjectId, + this._appStateService.activeFileId ); return forkJoin([annotatedObs, redactedObs, reactionLogObs, manualRedactionsObs]).pipe( diff --git a/libs/red-ui-http/src/lib/model/manualRedactionEntry.ts b/libs/red-ui-http/src/lib/model/manualRedactionEntry.ts index 2f700d8d3..b99671bc7 100644 --- a/libs/red-ui-http/src/lib/model/manualRedactionEntry.ts +++ b/libs/red-ui-http/src/lib/model/manualRedactionEntry.ts @@ -21,6 +21,8 @@ export interface ManualRedactionEntry { type?: string; user?: string; value?: string; + requestDate?: string; + processedDate?: string; } export namespace ManualRedactionEntry { export type StatusEnum = 'REQUESTED' | 'APPROVED' | 'DECLINED';