From 19a8ceca0ffe92cf7d9165c8a54836143bf80af8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Sat, 10 Oct 2020 01:38:35 +0300 Subject: [PATCH 1/3] Select annotation --- .../file-preview-screen.component.html | 13 +++++++++--- .../file-preview-screen.component.scss | 17 +++++++++++++++ .../file-preview-screen.component.ts | 20 +++++++++++++++--- .../file/pdf-viewer/pdf-viewer.component.ts | 21 +++++++++++++++++-- .../src/assets/styles/red-page-layout.scss | 1 + 5 files changed, 64 insertions(+), 8 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 7ae087858..241b6d783 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 @@ -21,7 +21,9 @@
+ (fileReady)="fileReady('ANNOTATED')" + (annotationSelected)="handleAnnotationSelected($event)" + (annotationsAdded)="handleAnnotationsAdded($event)">
@@ -47,8 +49,13 @@
-
- {{annotation.Id+ ' '+annotation.getPageNumber() + ' content: ' + annotation.getContents() + 'status: '+annotation.getStatus()}} +
+
{{annotation.Id}}
+
Page {{annotation.getPageNumber()}}
+
{{annotation.getContents()}}
+
{{annotation.getStatus()}}
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss index 4d3c0137c..8b1faef8f 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.scss @@ -17,6 +17,8 @@ redaction-pdf-viewer { .tabs-title-row { border-bottom: 1px solid rgba(226,228,233,0.9); + box-sizing: border-box; + height: 45px; .tab { font-size: 13px; @@ -40,8 +42,12 @@ redaction-pdf-viewer { .actions-row { margin: $right-container-padding $right-container-padding 0; } + .tab-content { padding: $right-container-padding; + overflow-y: scroll; + overflow-x: hidden; + height: calc(100vh - 110px - 40px - 45px - 3*#{$right-container-padding}); } .stats-subtitle { @@ -55,4 +61,15 @@ redaction-pdf-viewer { margin-left: 12px; } + + .annotation { + border: 1px solid $grey-2; + padding: 14px; + font-size: 12px; + cursor: pointer; + + &.active { + border-left: 2px solid $red-1; + } + } } diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index b64dcea75..ac5556b81 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -1,4 +1,4 @@ -import {ChangeDetectorRef, Component, OnInit} from '@angular/core'; +import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; import {ActivatedRoute, Router} from '@angular/router'; import {FileUploadControllerService, ProjectControllerService, StatusControllerService} from '@redaction/red-ui-http'; import {TranslateService} from '@ngx-translate/core'; @@ -8,6 +8,7 @@ import {AppStateService} from '../../../state/app-state.service'; import {FileDetailsDialogComponent} from './file-details-dialog/file-details-dialog.component'; import {ViewerSyncService} from '../service/viwer-sync.service'; import {Annotations} from "@pdftron/webviewer"; +import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component'; @Component({ selector: 'redaction-file-preview-screen', @@ -18,9 +19,14 @@ export class FilePreviewScreenComponent implements OnInit { projectId: string; fileId: string; - annotations: Annotations.Annotation[] = []; + public annotations: Annotations.Annotation[] = []; public selectedTab: 'ANNOTATIONS' | 'INFO' = 'ANNOTATIONS'; private _readyViewers: string[] = []; + public selectedAnnotation: Annotations.Annotation; + + @ViewChild(PdfViewerComponent) + private _viewerComponent: PdfViewerComponent; + constructor( public readonly appStateService: AppStateService, @@ -78,10 +84,18 @@ export class FilePreviewScreenComponent implements OnInit { handleAnnotationsAdded(annotations: Annotations.Annotation[]) { this._changeDetectorRef.detectChanges(); - for(let annotation of annotations){ + for(const annotation of annotations){ if(annotation.Id.indexOf(':')>=0){ this.annotations.push(annotation); } } } + + public handleAnnotationSelected(annotation: Annotations.Annotation) { + this.selectedAnnotation = annotation; + } + + public selectAnnotation(annotation: Annotations.Annotation) { + this._viewerComponent.selectAnnotation(annotation); + } } 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 1894c09c8..bb67b5afd 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 @@ -37,6 +37,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy { @Input() fileStatus: FileStatus; @Output() fileReady = new EventEmitter(); @Output() annotationsAdded = new EventEmitter(); + @Output() annotationSelected = new EventEmitter(); @ViewChild('viewer', {static: true}) viewer: ElementRef; wvInstance: WebViewerInstance; @@ -87,6 +88,14 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy { } }); + instance.annotManager.on('annotationSelected', ((annotationList, action) => { + if (action === 'deselected') { + this.annotationSelected.emit(null); + } else { + this.annotationSelected.emit(annotationList[0]); + } + })); + instance.docViewer.on('documentLoaded', this.wvDocumentLoadedHandler) instance.loadDocument(pdfBlob, {filename: this.fileStatus ? this.fileStatus.filename : 'file.pdf'}); }); @@ -123,8 +132,8 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy { 'textSquigglyToolButton', 'textStrikeoutToolButton', 'linkButton', - // 'toggleNotesButton', - // 'notesPanel' + 'toggleNotesButton', + 'notesPanel' ]); this.wvInstance.textPopup.add({ @@ -147,5 +156,13 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy { this._viewerSyncService.deregisterInstance(this.fileType); } + public selectAnnotation(annotation: Annotations.Annotation) { + this.wvInstance.annotManager.deselectAllAnnotations(); + this.wvInstance.annotManager.selectAnnotation(annotation); + this.wvInstance.docViewer.displayPageLocation( + annotation.getPageNumber(), + 0, + annotation.getY() - 100); + } } diff --git a/apps/red-ui/src/assets/styles/red-page-layout.scss b/apps/red-ui/src/assets/styles/red-page-layout.scss index 75f893978..ca52307e4 100644 --- a/apps/red-ui/src/assets/styles/red-page-layout.scss +++ b/apps/red-ui/src/assets/styles/red-page-layout.scss @@ -38,6 +38,7 @@ html, body { .actions-row { display: flex; + height: 40px; > div { padding: 10px; From e9b5f0d10ea8ae64131dac12f5f584c90f6e6e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Sat, 10 Oct 2020 01:53:40 +0300 Subject: [PATCH 2/3] Sort annotations --- .../file/pdf-viewer/pdf-viewer.component.ts | 7 ++++--- apps/red-ui/src/app/utils/annotation-utils.ts | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 apps/red-ui/src/app/utils/annotation-utils.ts 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 bb67b5afd..4a6933fcb 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 @@ -16,6 +16,7 @@ import {tap} from "rxjs/operators"; import WebViewer, {Annotations, WebViewerInstance} from "@pdftron/webviewer"; import {TranslateService} from "@ngx-translate/core"; import {ViewerSyncService} from "../service/viwer-sync.service"; +import { AnnotationUtils } from '../../../utils/annotation-utils'; @@ -82,9 +83,9 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy { this._viewerSyncService.registerViewer(this.fileType, this.wvInstance); this._configureTextPopup(); this._configureHeader(); - instance.annotManager.on('annotationChanged', (annotations,b,c) => { - if(b === 'add'){ - this.annotationsAdded.emit(annotations); + instance.annotManager.on('annotationChanged', (annotations, action) => { + if(action === 'add'){ + this.annotationsAdded.emit(AnnotationUtils.sortAnnotations(annotations)); } }); diff --git a/apps/red-ui/src/app/utils/annotation-utils.ts b/apps/red-ui/src/app/utils/annotation-utils.ts new file mode 100644 index 000000000..c5881e81d --- /dev/null +++ b/apps/red-ui/src/app/utils/annotation-utils.ts @@ -0,0 +1,18 @@ +import { Annotations } from '@pdftron/webviewer'; + +export class AnnotationUtils { + public static sortAnnotations(annotations: Annotations.Annotation[]): Annotations.Annotation[] { + return annotations.sort((ann1, ann2) => { + if (ann1.getPageNumber() === ann2.getPageNumber()) { + if (ann1.getY() === ann2.getY()) { + if (ann1.getX() === ann2.getY()) { + return 0; + } + return ann1.getX() < ann2.getX() ? -1 : 1; + } + return ann1.getY() < ann2.getY() ? -1 : 1; + } + return ann1.getPageNumber() < ann2.getPageNumber() ? -1 : 1; + }) + } +} From f7bcdf8bc6bb8a8e41a135633bc73e861ff6176f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adina=20=C8=9Aeudan?= Date: Sat, 10 Oct 2020 03:14:48 +0300 Subject: [PATCH 3/3] Sort to selected annotation in sidebar + fixes --- .../file-preview-screen.component.html | 5 +- .../file-preview-screen.component.ts | 66 ++++++++++++++----- .../file/pdf-viewer/pdf-viewer.component.ts | 2 +- apps/red-ui/src/app/utils/annotation-utils.ts | 4 +- 4 files changed, 54 insertions(+), 23 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 241b6d783..89c25f203 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 @@ -48,9 +48,10 @@ Info
-
+
{{annotation.Id}}
Page {{annotation.getPageNumber()}}
diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts index ac5556b81..7126a8644 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.ts @@ -1,14 +1,15 @@ -import { ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core'; -import {ActivatedRoute, Router} from '@angular/router'; -import {FileUploadControllerService, ProjectControllerService, StatusControllerService} from '@redaction/red-ui-http'; -import {TranslateService} from '@ngx-translate/core'; -import {NotificationService} from '../../../notification/notification.service'; -import {MatDialog} from '@angular/material/dialog'; -import {AppStateService} from '../../../state/app-state.service'; -import {FileDetailsDialogComponent} from './file-details-dialog/file-details-dialog.component'; -import {ViewerSyncService} from '../service/viwer-sync.service'; -import {Annotations} from "@pdftron/webviewer"; +import { ChangeDetectorRef, Component, ElementRef, OnInit, ViewChild } from '@angular/core'; +import { ActivatedRoute, Router } from '@angular/router'; +import { FileUploadControllerService, ProjectControllerService, StatusControllerService } from '@redaction/red-ui-http'; +import { TranslateService } from '@ngx-translate/core'; +import { NotificationService } from '../../../notification/notification.service'; +import { MatDialog } from '@angular/material/dialog'; +import { AppStateService } from '../../../state/app-state.service'; +import { FileDetailsDialogComponent } from './file-details-dialog/file-details-dialog.component'; +import { ViewerSyncService } from '../service/viwer-sync.service'; +import { Annotations } from '@pdftron/webviewer'; import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component'; +import { AnnotationUtils } from '../../../utils/annotation-utils'; @Component({ selector: 'redaction-file-preview-screen', @@ -16,17 +17,20 @@ import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component'; styleUrls: ['./file-preview-screen.component.scss'] }) export class FilePreviewScreenComponent implements OnInit { - - projectId: string; - fileId: string; - public annotations: Annotations.Annotation[] = []; - public selectedTab: 'ANNOTATIONS' | 'INFO' = 'ANNOTATIONS'; private _readyViewers: string[] = []; - public selectedAnnotation: Annotations.Annotation; + private _clickedAnnotationInSidebar = false; + private projectId: string; @ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent; + @ViewChild('annotationsContainer') + private _annotationsContainer: ElementRef; + + public fileId: string; + public annotations: Annotations.Annotation[] = []; + public selectedTab: 'ANNOTATIONS' | 'INFO' = 'ANNOTATIONS'; + public selectedAnnotation: Annotations.Annotation; constructor( public readonly appStateService: AppStateService, @@ -84,18 +88,44 @@ export class FilePreviewScreenComponent implements OnInit { handleAnnotationsAdded(annotations: Annotations.Annotation[]) { this._changeDetectorRef.detectChanges(); - for(const annotation of annotations){ - if(annotation.Id.indexOf(':')>=0){ + for (const annotation of annotations) { + if (annotation.Id.indexOf(':') >= 0) { this.annotations.push(annotation); } } + this.annotations = AnnotationUtils.sortAnnotations(this.annotations); } public handleAnnotationSelected(annotation: Annotations.Annotation) { this.selectedAnnotation = annotation; + this.scrollToAnnotation(annotation); } public selectAnnotation(annotation: Annotations.Annotation) { + this._clickedAnnotationInSidebar = true; + setTimeout(() => { + this._clickedAnnotationInSidebar = false; + }, 100); this._viewerComponent.selectAnnotation(annotation); } + + private scrollToAnnotation(annotation: Annotations.Annotation) { + if (!annotation || this._clickedAnnotationInSidebar) { + return; + } + const el = document.getElementById('ann-' + annotation.Id); + + if (!el) { + console.error(`Annotation with id ${annotation.Id} does not exist!`); + return; + } + + const { top, height } = el.getBoundingClientRect(); + const headerHeight = window.innerHeight - this._annotationsContainer.nativeElement.getBoundingClientRect().height; + + if (top < headerHeight || top > window.innerHeight - height - 30) { + const scrollTop = this._annotationsContainer.nativeElement.scrollTop - 30; + this._annotationsContainer.nativeElement.scroll({ top: scrollTop + top - headerHeight, behavior: 'smooth' }); + } + } } 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 4a6933fcb..bb24d6db8 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 @@ -85,7 +85,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy { this._configureHeader(); instance.annotManager.on('annotationChanged', (annotations, action) => { if(action === 'add'){ - this.annotationsAdded.emit(AnnotationUtils.sortAnnotations(annotations)); + this.annotationsAdded.emit(annotations); } }); diff --git a/apps/red-ui/src/app/utils/annotation-utils.ts b/apps/red-ui/src/app/utils/annotation-utils.ts index c5881e81d..d12a5bf59 100644 --- a/apps/red-ui/src/app/utils/annotation-utils.ts +++ b/apps/red-ui/src/app/utils/annotation-utils.ts @@ -1,7 +1,7 @@ import { Annotations } from '@pdftron/webviewer'; export class AnnotationUtils { - public static sortAnnotations(annotations: Annotations.Annotation[]): Annotations.Annotation[] { + public static sortAnnotations(annotations: Annotations.Annotation[]): Annotations.Annotation[] { return annotations.sort((ann1, ann2) => { if (ann1.getPageNumber() === ann2.getPageNumber()) { if (ann1.getY() === ann2.getY()) { @@ -13,6 +13,6 @@ export class AnnotationUtils { return ann1.getY() < ann2.getY() ? -1 : 1; } return ann1.getPageNumber() < ann2.getPageNumber() ? -1 : 1; - }) + }); } }