Pull request #132: Quick nav scroll to top/bottom
Merge in RED/ui from RED-897 to master * commit 'a4b3bd498d536bded564e7438531d64b453cf110': Fixed enable/disable quick nav buttons Remove logic from getter Quick nav scroll to top/bottom
This commit is contained in:
commit
11a2f5adb0
@ -44,6 +44,8 @@ export class IconsModule {
|
||||
'lightning',
|
||||
'logout',
|
||||
'menu',
|
||||
'nav-first',
|
||||
'nav-last',
|
||||
'needs-work',
|
||||
'new-tab',
|
||||
'notification',
|
||||
|
||||
@ -217,17 +217,37 @@
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="pagesPanelActive"
|
||||
class="pages"
|
||||
class="quick-navigation"
|
||||
tabindex="0"
|
||||
>
|
||||
<redaction-page-indicator
|
||||
(pageSelected)="pageSelectedByClick($event)"
|
||||
*ngFor="let pageNumber of displayedPages"
|
||||
[active]="pageNumber === activeViewerPage"
|
||||
[number]="pageNumber"
|
||||
[viewedPages]="fileData.viewedPages"
|
||||
<div
|
||||
class="jump"
|
||||
[class.disabled]="!quickScrollFirstEnabled"
|
||||
[matTooltip]="'file-preview.quick-nav.jump-first' | translate"
|
||||
matTooltipPosition="above"
|
||||
(click)="quickScrollFirstEnabled && scrollQuickNavFirst()"
|
||||
>
|
||||
</redaction-page-indicator>
|
||||
<mat-icon svgIcon="red:nav-first"></mat-icon>
|
||||
</div>
|
||||
<div class="pages" (scroll)="computeQuickNavButtonsState()" id="pages">
|
||||
<redaction-page-indicator
|
||||
(pageSelected)="pageSelectedByClick($event)"
|
||||
*ngFor="let pageNumber of displayedPages"
|
||||
[active]="pageNumber === activeViewerPage"
|
||||
[number]="pageNumber"
|
||||
[viewedPages]="fileData.viewedPages"
|
||||
>
|
||||
</redaction-page-indicator>
|
||||
</div>
|
||||
<div
|
||||
class="jump"
|
||||
[class.disabled]="!quickScrollLastEnabled"
|
||||
[matTooltip]="'file-preview.quick-nav.jump-last' | translate"
|
||||
matTooltipPosition="above"
|
||||
(click)="scrollQuickNavLast()"
|
||||
>
|
||||
<mat-icon svgIcon="red:nav-last"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="overflow: hidden; width: 100%;">
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -213,7 +213,7 @@
|
||||
</div>
|
||||
|
||||
<div *ngIf="!fileStatus.isError">
|
||||
<div class="pages">
|
||||
<div class="quick-navigation">
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
{{ fileStatus.numberOfPages }}
|
||||
</div>
|
||||
|
||||
@ -41,7 +41,7 @@ cdk-virtual-scroll-viewport {
|
||||
max-width: 25vw;
|
||||
}
|
||||
|
||||
.pages {
|
||||
.quick-navigation {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
@ -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": {
|
||||
|
||||
15
apps/red-ui/src/assets/icons/general/nav-first.svg
Normal file
15
apps/red-ui/src/assets/icons/general/nav-first.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>ED22EA6D-C390-4471-B1E4-6B17BA55D5F9</title>
|
||||
<g id="Annotations-Jump-to-" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="03.Jump-to-first-annotation" transform="translate(-1109.000000, -181.000000)">
|
||||
<rect x="0" y="0" width="1440" height="750"></rect>
|
||||
<rect id="Rectangle" x="1087" y="173" width="60" height="32"></rect>
|
||||
<g id="right_white" transform="translate(1109.000000, 181.000000)" fill="currentColor" fill-rule="nonzero">
|
||||
<polygon id="Path" transform="translate(8.000000, 7.680000) scale(1, -1) translate(-8.000000, -7.680000) " points="12 6.24 10.88 5.12 8 8 7.2 7.2 5.12 5.12 4 6.24 8 10.24"></polygon>
|
||||
<polygon id="Path" transform="translate(8.000000, 11.840000) scale(1, -1) translate(-8.000000, -11.840000) " points="12 10.4 10.88 9.28 8 12.16 7.2 11.36 5.12 9.28 4 10.4 8 14.4"></polygon>
|
||||
<polygon id="Path" transform="translate(8.000000, 2.720000) scale(1, -1) translate(-8.000000, -2.720000) " points="14.4 1.92 1.6 1.92 1.22124533e-14 1.92 1.22124533e-14 3.52 16 3.52 16 1.92"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
15
apps/red-ui/src/assets/icons/general/nav-last.svg
Normal file
15
apps/red-ui/src/assets/icons/general/nav-last.svg
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>F189455C-659F-4467-9C15-B17B152A29C5</title>
|
||||
<g id="Annotations-Jump-to-" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="03.Jump-to-first-annotation" transform="translate(-1109.000000, -726.000000)">
|
||||
<rect x="0" y="0" width="1440" height="750"></rect>
|
||||
<rect id="Rectangle" x="1087" y="718" width="60" height="32"></rect>
|
||||
<g id="right_white" transform="translate(1117.000000, 734.000000) scale(1, -1) translate(-1117.000000, -734.000000) translate(1109.000000, 726.000000)" fill="currentColor" fill-rule="nonzero">
|
||||
<polygon id="Path" transform="translate(8.000000, 7.680000) scale(1, -1) translate(-8.000000, -7.680000) " points="12 6.24 10.88 5.12 8 8 7.2 7.2 5.12 5.12 4 6.24 8 10.24"></polygon>
|
||||
<polygon id="Path" transform="translate(8.000000, 11.840000) scale(1, -1) translate(-8.000000, -11.840000) " points="12 10.4 10.88 9.28 8 12.16 7.2 11.36 5.12 9.28 4 10.4 8 14.4"></polygon>
|
||||
<polygon id="Path" transform="translate(8.000000, 2.720000) scale(1, -1) translate(-8.000000, -2.720000) " points="14.4 1.92 1.6 1.92 1.22124533e-14 1.92 1.22124533e-14 3.52 16 3.52 16 1.92"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
Loading…
x
Reference in New Issue
Block a user