diff --git a/apps/red-ui/src/app/icons/icons.module.ts b/apps/red-ui/src/app/icons/icons.module.ts index 0c8622230..7a0945248 100644 --- a/apps/red-ui/src/app/icons/icons.module.ts +++ b/apps/red-ui/src/app/icons/icons.module.ts @@ -44,6 +44,8 @@ export class IconsModule { 'lightning', 'logout', 'menu', + 'nav-first', + 'nav-last', 'needs-work', 'new-tab', 'notification', 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 70834b8bc..94f66155c 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 @@ -217,17 +217,37 @@ (keydown)="preventKeyDefault($event)" (keyup)="preventKeyDefault($event)" [class.active-panel]="pagesPanelActive" - class="pages" + class="quick-navigation" tabindex="0" > - - + + +
+ + +
+
+ +
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 55c647921..965a39992 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 @@ -58,7 +58,7 @@ box-sizing: border-box; display: flex; - .pages, + .quick-navigation, .annotations { overflow-y: scroll; outline: none; @@ -68,10 +68,44 @@ } } - .pages { + .quick-navigation { border-right: 1px solid $separator; min-width: 61px; - @include no-scroll-bar(); + overflow: hidden; + display: flex; + flex-direction: column; + + .jump { + min-height: 32px; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + transition: background-color 0.25s; + + &:not(.disabled):hover { + background-color: $grey-6; + } + + mat-icon { + width: 16px; + height: 16px; + } + + &.disabled { + cursor: default; + + mat-icon { + opacity: 0.3; + } + } + } + + .pages { + @include no-scroll-bar(); + overflow: auto; + flex: 1; + } } .page-separator { 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 11c7055f5..54111d07d 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 @@ -29,7 +29,6 @@ import { FormBuilder, FormGroup } from '@angular/forms'; import { FileManagementControllerService, StatusControllerService } from '@redaction/red-ui-http'; import { PdfViewerDataService } from '../service/pdf-viewer-data.service'; import { download } from '../../../utils/file-download-utils'; -import { MatButtonToggleChange } from '@angular/material/button-toggle'; import { ViewMode } from '../model/view-mode'; const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape']; @@ -81,10 +80,6 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { return this._instance; } - get displayedPages(): number[] { - return Object.keys(this.displayedAnnotations).map((key) => Number(key)); - } - get activeViewerPage() { return this._instance?.docViewer?.getCurrentPage(); } @@ -119,6 +114,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { public analysisProgress: number; public analysisInterval: number; + public quickScrollFirstEnabled = false; + public quickScrollLastEnabled = false; + + public displayedPages: number[] = []; + get indeterminateMode() { return ( this.analysisProgress > 100 || this.appStateService.activeFile.analysisDuration < 3 * 1000 // it takes longer than usual - switch to indeterminate @@ -342,11 +342,31 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { this._scrollToFirstElement(elements); } - private _scrollQuickNavigation() { - const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${this.activeViewerPage}`); + private _scrollQuickNavigationToPage(page: number) { + const elements: any[] = this._quickNavigationElement.nativeElement.querySelectorAll(`#quick-nav-page-${page}`); this._scrollToFirstElement(elements); } + private _scrollQuickNavigation() { + let quickNavPageIndex = this.displayedPages.findIndex((p) => p >= this.activeViewerPage); + if (quickNavPageIndex === -1 || this.displayedPages[quickNavPageIndex] !== this.activeViewerPage) { + quickNavPageIndex = Math.max(0, quickNavPageIndex - 1); + } + this._scrollQuickNavigationToPage(this.displayedPages[quickNavPageIndex]); + } + + public scrollQuickNavFirst() { + if (this.displayedPages.length > 0) { + this._scrollQuickNavigationToPage(this.displayedPages[0]); + } + } + + public scrollQuickNavLast() { + if (this.displayedPages.length > 0) { + this._scrollQuickNavigationToPage(this.displayedPages[this.displayedPages.length - 1]); + } + } + private _scrollAnnotations() { if (this.firstSelectedAnnotation?.pageNumber === this.activeViewerPage) { return; @@ -570,6 +590,8 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { filtersChanged(filters: FilterModel[]) { this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(this.annotations, filters); + this.displayedPages = Object.keys(this.displayedAnnotations).map((key) => Number(key)); + this.computeQuickNavButtonsState(); this._changeDetectorRef.markForCheck(); } @@ -579,6 +601,13 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy { } } + public computeQuickNavButtonsState() { + const element: HTMLElement = this._quickNavigationElement.nativeElement.querySelector(`#pages`); + const { scrollTop, scrollHeight, clientHeight } = element; + this.quickScrollFirstEnabled = scrollTop !== 0; + this.quickScrollLastEnabled = scrollHeight !== scrollTop + clientHeight; + } + private _cleanupAndRedrawManualAnnotations() { this._fileDownloadService.loadActiveFileManualAnnotations().subscribe((manualRedactions) => { this.fileData.manualRedactions = manualRedactions; diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html index 871bb552a..876718855 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.html @@ -213,7 +213,7 @@
-
+
{{ fileStatus.numberOfPages }}
diff --git a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss index ec491ef19..34b886b01 100644 --- a/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss +++ b/apps/red-ui/src/app/screens/project-overview-screen/project-overview-screen.component.scss @@ -41,7 +41,7 @@ cdk-virtual-scroll-viewport { max-width: 25vw; } - .pages { + .quick-navigation { display: flex; flex-direction: row; align-items: center; diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index a777c282e..1f94de8db 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -306,7 +306,11 @@ "new-tab-ssr": "Open Document in Server Side Rendering Mode", "html-debug": "Open Document HTML Debug", "download-original-file": "Download Original File", - "exit-fullscreen": "Exit Full Screen (F)" + "exit-fullscreen": "Exit Full Screen (F)", + "quick-nav": { + "jump-first": "Jump to first annotation", + "jump-last": "Jump to last annotation" + } }, "annotation-actions": { "message": { diff --git a/apps/red-ui/src/assets/icons/general/nav-first.svg b/apps/red-ui/src/assets/icons/general/nav-first.svg new file mode 100644 index 000000000..685ffebac --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/nav-first.svg @@ -0,0 +1,15 @@ + + + ED22EA6D-C390-4471-B1E4-6B17BA55D5F9 + + + + + + + + + + + + diff --git a/apps/red-ui/src/assets/icons/general/nav-last.svg b/apps/red-ui/src/assets/icons/general/nav-last.svg new file mode 100644 index 000000000..1c0697770 --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/nav-last.svg @@ -0,0 +1,15 @@ + + + F189455C-659F-4467-9C15-B17B152A29C5 + + + + + + + + + + + +