+
{{annotation.Id}}
@@ -89,8 +93,12 @@
[config]="[{ length: 1, label: 'Unassigned', color: 'unassigned'}]">
-
645
-
9
+
+
+ {{appStateService.activeFile.numberOfPages}}
+
+
+ {{annotations.length}}
@@ -102,21 +110,21 @@
Added on
- 22 Sep. 2020, 12:15 PM
+ {{appStateService.activeFile.added | date:'medium'}}
Added by
- Timo Bejan
+ {{user.name}}
Last modified on
- 22 Sep. 2020, 12:15 PM
+ {{appStateService.activeFile.lastUpdated | date:'medium'}}
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 a47da0ef4..16c85ef7b 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
@@ -16,6 +16,7 @@ import {Annotations} from '@pdftron/webviewer';
import {PdfViewerComponent} from '../pdf-viewer/pdf-viewer.component';
import {AnnotationUtils} from '../../../utils/annotation-utils';
import {ManualRedactionDialogComponent} from "../manual-redaction-dialog/manual-redaction-dialog.component";
+import {UserService} from "../../../user/user.service";
@Component({
@@ -35,14 +36,18 @@ export class FilePreviewScreenComponent implements OnInit {
@ViewChild('annotationsContainer')
private _annotationsContainer: ElementRef;
+ @ViewChild('navigationTabElement')
+ private _navigationTabElement: ElementRef;
+
public fileId: string;
public annotations: Annotations.Annotation[] = [];
public selectedAnnotation: Annotations.Annotation;
- public selectedPageNumber: number;
public quickNavigation: { pageNumber: number, redactions: number, hints: number }[] = [];
private _manualRedactionEntry: ManualRedactionEntry;
+ activeViewerPage: number;
+
constructor(
public readonly appStateService: AppStateService,
private readonly _changeDetectorRef: ChangeDetectorRef,
@@ -53,6 +58,7 @@ export class FilePreviewScreenComponent implements OnInit {
private readonly _viewerSyncService: ViewerSyncService,
private readonly _dialog: MatDialog,
private readonly _router: Router,
+ private readonly _userService: UserService,
private readonly _fileUploadControllerService: FileUploadControllerService,
private readonly _projectControllerService: ProjectControllerService) {
this._activatedRoute.params.subscribe(params => {
@@ -62,6 +68,10 @@ export class FilePreviewScreenComponent implements OnInit {
});
}
+ get user() {
+ return this._userService.user;
+ }
+
public ngOnInit(): void {
// PDFTRON cache fix
localStorage.clear();
@@ -96,6 +106,9 @@ export class FilePreviewScreenComponent implements OnInit {
public selectTab(value: 'ANNOTATIONS' | 'INFO' | 'NAVIGATION') {
this._selectedTab = value;
+ setTimeout(() => {
+ this._scrollViews();
+ }, 50);
}
public handleAnnotationsAdded(annotations: Annotations.Annotation[]) {
@@ -123,6 +136,7 @@ export class FilePreviewScreenComponent implements OnInit {
public handleAnnotationSelected(annotation: Annotations.Annotation) {
this.selectedAnnotation = annotation;
this.scrollToAnnotation(annotation);
+ this._changeDetectorRef.detectChanges();
}
public selectAnnotation(annotation: Annotations.Annotation) {
@@ -144,13 +158,7 @@ export class FilePreviewScreenComponent implements OnInit {
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'});
- }
+ el.scrollIntoView({block: 'center', inline: 'center', behavior: 'smooth'});
}
public get navigationTab() {
@@ -166,7 +174,6 @@ export class FilePreviewScreenComponent implements OnInit {
}
public selectPage(pageNumber: number) {
- this.selectedPageNumber = pageNumber;
this._viewerComponent.navigateToPage(pageNumber);
}
@@ -186,4 +193,85 @@ export class FilePreviewScreenComponent implements OnInit {
this._manualRedactionEntry = null;
})
}
+
+ viewerPageChanged(pageNumber: number) {
+ if (Number.isInteger(pageNumber)) {
+ this.activeViewerPage = this._viewerSyncService.activeViewerPage;
+ this._scrollViews();
+ }
+ this._changeDetectorRef.detectChanges();
+ }
+
+ private _scrollViews() {
+ this._scrollQuickNavigation();
+ this._scrollAnnotations();
+ }
+
+ private _scrollQuickNavigation() {
+ const elements: any[] = this._navigationTabElement.nativeElement.querySelectorAll(`#quick-nav-page-${this.activeViewerPage}`);
+ if (elements.length > 0) {
+ elements[0].scrollIntoViewIfNeeded();
+ }
+ }
+
+ private _scrollAnnotations() {
+ const elements: any[] = this._annotationsContainer.nativeElement.querySelectorAll(`div[annotation-page="${this.activeViewerPage}"]`);
+ if (elements.length > 0) {
+ elements[0].scrollIntoViewIfNeeded();
+ }
+ }
+
}
+
+
+(function() {
+ // @ts-ignore
+ if (!Element.prototype.scrollIntoViewIfNeeded) {
+ // @ts-ignore
+ Element.prototype.scrollIntoViewIfNeeded = function(centerIfNeeded) {
+ centerIfNeeded = arguments.length === 0 ? true : !!centerIfNeeded;
+
+ const parent = this.parentNode,
+ parentComputedStyle = window.getComputedStyle(parent, null),
+ parentBorderTopWidth = parseInt(
+ parentComputedStyle.getPropertyValue('border-top-width'),
+ 10
+ ),
+ parentBorderLeftWidth = parseInt(
+ parentComputedStyle.getPropertyValue('border-left-width'),
+ 10
+ ),
+ overTop = this.offsetTop - parent.offsetTop < parent.scrollTop,
+ overBottom =
+ this.offsetTop - parent.offsetTop + this.clientHeight - parentBorderTopWidth >
+ parent.scrollTop + parent.clientHeight,
+ overLeft = this.offsetLeft - parent.offsetLeft < parent.scrollLeft,
+ overRight =
+ this.offsetLeft - parent.offsetLeft + this.clientWidth - parentBorderLeftWidth >
+ parent.scrollLeft + parent.clientWidth,
+ alignWithTop = overTop && !overBottom;
+
+ if ((overTop || overBottom) && centerIfNeeded) {
+ parent.scrollTop =
+ this.offsetTop -
+ parent.offsetTop -
+ parent.clientHeight / 2 -
+ parentBorderTopWidth +
+ this.clientHeight / 2;
+ }
+
+ if ((overLeft || overRight) && centerIfNeeded) {
+ parent.scrollLeft =
+ this.offsetLeft -
+ parent.offsetLeft -
+ parent.clientWidth / 2 -
+ parentBorderLeftWidth +
+ this.clientWidth / 2;
+ }
+
+ if ((overTop || overBottom || overLeft || overRight) && !centerIfNeeded) {
+ this.scrollIntoView(alignWithTop);
+ }
+ };
+ }
+})();
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 991258116..d0a769648 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
@@ -17,7 +17,6 @@ import WebViewer, {Annotations, WebViewerInstance} from '@pdftron/webviewer';
import {TranslateService} from '@ngx-translate/core';
import {ViewerSyncService} from '../service/viewer-sync.service';
import {MatDialog} from "@angular/material/dialog";
-import {ManualRedactionDialogComponent} from "../manual-redaction-dialog/manual-redaction-dialog.component";
export enum FileType {
ORIGINAL = 'ORIGINAL',
@@ -39,6 +38,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy {
@Output() annotationsAdded = new EventEmitter
();
@Output() annotationSelected = new EventEmitter();
@Output() manualAnnotationRequested = new EventEmitter();
+ @Output() pageChanged = new EventEmitter();
@ViewChild('viewer', {static: true}) viewer: ElementRef;
wvInstance: WebViewerInstance;
@@ -95,6 +95,10 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy {
}
}));
+ instance.docViewer.on('pageComplete', (p) => {
+ this.pageChanged.emit(p);
+ });
+
instance.docViewer.on('documentLoaded', this.wvDocumentLoadedHandler);
instance.loadDocument(pdfBlob, {filename: this.fileStatus ? this.fileStatus.filename : 'file.pdf'});
});
@@ -152,7 +156,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy {
const entry: ManualRedactionEntry = {positions: []};
for (const key of Object.keys(selectedQuads)) {
for (const quad of selectedQuads[key]) {
- entry.positions.push(this.toPosition(parseInt(key,10), quad));
+ entry.positions.push(this.toPosition(parseInt(key, 10), quad));
}
}
entry.value = text;
diff --git a/apps/red-ui/src/app/screens/file/service/viewer-sync.service.ts b/apps/red-ui/src/app/screens/file/service/viewer-sync.service.ts
index 548b14ca6..e3dc8887d 100644
--- a/apps/red-ui/src/app/screens/file/service/viewer-sync.service.ts
+++ b/apps/red-ui/src/app/screens/file/service/viewer-sync.service.ts
@@ -1,5 +1,5 @@
-import { Injectable } from '@angular/core';
-import { WebViewerInstance } from '@pdftron/webviewer';
+import {Injectable} from '@angular/core';
+import {WebViewerInstance} from '@pdftron/webviewer';
@Injectable({
providedIn: 'root'
@@ -13,6 +13,14 @@ export class ViewerSyncService {
constructor() {
}
+ get activeViewerPage() {
+ if (this._activeViewer) {
+ const lastActiveViewer = this._viewers[this._activeViewer];
+ return lastActiveViewer.docViewer.getCurrentPage();
+ }
+ return 1;
+ }
+
syncViewers() {
localStorage.clear();
if (this._activeViewer) {
@@ -36,7 +44,7 @@ export class ViewerSyncService {
// sync layout and display mode
instance.docViewer.setCurrentPage(lastPageNumber);
instance.setLayoutMode(lastLayoutMode);
- const displayMode =instance.docViewer.getDisplayModeManager().getDisplayMode();
+ const displayMode = instance.docViewer.getDisplayModeManager().getDisplayMode();
displayMode.mode = lastDisplayMode;
instance.docViewer.getDisplayModeManager().setDisplayMode(displayMode);
// Synchronize zoom - needs to be done before scrolling
diff --git a/apps/red-ui/src/assets/icons/general/bar_chart.svg b/apps/red-ui/src/assets/icons/general/bar_chart.svg
new file mode 100644
index 000000000..41cecdd3b
--- /dev/null
+++ b/apps/red-ui/src/assets/icons/general/bar_chart.svg
@@ -0,0 +1,50 @@
+
+
+
diff --git a/apps/red-ui/src/assets/icons/general/pages.svg b/apps/red-ui/src/assets/icons/general/pages.svg
new file mode 100644
index 000000000..300a88d70
--- /dev/null
+++ b/apps/red-ui/src/assets/icons/general/pages.svg
@@ -0,0 +1,63 @@
+
+
+
+
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 caa588b50..f7dc22bf8 100644
--- a/apps/red-ui/src/assets/styles/red-page-layout.scss
+++ b/apps/red-ui/src/assets/styles/red-page-layout.scss
@@ -188,6 +188,10 @@ html, body {
display: none !important;
}
-.pointer{
+.not-visible {
+ visibility: hidden;
+}
+
+.pointer {
cursor: pointer;
}