Some arrow navigation fixes

This commit is contained in:
Adina Țeudan 2020-10-27 04:02:15 +02:00
parent 56c1147d5f
commit 2a6859b584
4 changed files with 93 additions and 58 deletions

View File

@ -1,6 +1,6 @@
import {Injectable} from '@angular/core';
import {FileDetailsDialogComponent} from './file-details-dialog/file-details-dialog.component';
import {MatDialog} from '@angular/material/dialog';
import { Injectable } from '@angular/core';
import { FileDetailsDialogComponent } from './file-details-dialog/file-details-dialog.component';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import {
FileStatus,
FileUploadControllerService,
@ -8,15 +8,15 @@ import {
ManualRedactionEntry,
Project
} from '@redaction/red-ui-http';
import {ConfirmationDialogComponent} from '../common/confirmation-dialog/confirmation-dialog.component';
import {NotificationService, NotificationType} from '../notification/notification.service';
import {TranslateService} from '@ngx-translate/core';
import {AppStateService, ProjectWrapper} from '../state/app-state.service';
import {AddEditProjectDialogComponent} from './add-edit-project-dialog/add-edit-project-dialog.component';
import {AssignOwnerDialogComponent} from './assign-owner-dialog/assign-owner-dialog.component';
import {ProjectDetailsDialogComponent} from './project-details-dialog/project-details-dialog.component';
import {ManualRedactionDialogComponent} from './manual-redaction-dialog/manual-redaction-dialog.component';
import {Annotations} from '@pdftron/webviewer';
import { ConfirmationDialogComponent } from '../common/confirmation-dialog/confirmation-dialog.component';
import { NotificationService, NotificationType } from '../notification/notification.service';
import { TranslateService } from '@ngx-translate/core';
import { AppStateService, ProjectWrapper } from '../state/app-state.service';
import { AddEditProjectDialogComponent } from './add-edit-project-dialog/add-edit-project-dialog.component';
import { AssignOwnerDialogComponent } from './assign-owner-dialog/assign-owner-dialog.component';
import { ProjectDetailsDialogComponent } from './project-details-dialog/project-details-dialog.component';
import { ManualRedactionDialogComponent } from './manual-redaction-dialog/manual-redaction-dialog.component';
import { Annotations } from '@pdftron/webviewer';
const dialogConfig = {
width: '600px',
@ -38,17 +38,19 @@ export class DialogService {
}
public openFileDetailsDialog($event: MouseEvent, file: FileStatus) {
public openFileDetailsDialog($event: MouseEvent, file: FileStatus): MatDialogRef<FileDetailsDialogComponent> {
$event.stopPropagation();
this._dialog.open(FileDetailsDialogComponent, {
return this._dialog.open(FileDetailsDialogComponent, {
...dialogConfig,
data: file
});
}
public openDeleteFileDialog($event: MouseEvent, projectId: string, fileId: string, cb?: Function) {
public openDeleteFileDialog($event: MouseEvent, projectId: string, fileId: string, cb?: Function): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation();
this._dialog.open(ConfirmationDialogComponent, dialogConfig).afterClosed().subscribe(result => {
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
ref.afterClosed().subscribe(result => {
if (result) {
const file = this._appStateService.getFileById(projectId, fileId);
this._fileUploadControllerService.deleteFile(file.projectId, file.fileId).subscribe(async () => {
@ -62,28 +64,34 @@ export class DialogService {
});
}
});
return ref;
}
public openManualRedactionDialog($event: ManualRedactionEntry, cb?: Function) {
this._dialog.open(ManualRedactionDialogComponent, {
public openManualRedactionDialog($event: ManualRedactionEntry, cb?: Function): MatDialogRef<ManualRedactionDialogComponent> {
const ref = this._dialog.open(ManualRedactionDialogComponent, {
...dialogConfig,
autoFocus: true,
data: $event
}).afterClosed().subscribe(result => {
});
ref.afterClosed().subscribe(result => {
if (cb) {
cb(result);
}
});
return ref;
}
public acceptSuggestionAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string) {
public acceptSuggestionAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation();
const parts = annotation.Id.split(':');
const annotationId = parts[parts.length - 1];
this._dialog.open(ConfirmationDialogComponent, dialogConfig)
.afterClosed().subscribe(result => {
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
ref.afterClosed().subscribe(result => {
if (result) {
this._manualRedactionControllerService.approveRequest(projectId, fileId, annotationId).subscribe(() => {
this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.confirm-annotation.success.label'), null, NotificationType.SUCCESS);
@ -92,18 +100,22 @@ export class DialogService {
});
}
});
return ref;
}
public suggestRemoveAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string) {
public suggestRemoveAnnotation($event: MouseEvent, annotation: Annotations.Annotation, projectId: string, fileId: string): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation();
const parts = annotation.Id.split(':');
const annotationId = parts[parts.length - 1];
this._dialog.open(ConfirmationDialogComponent, {
const ref = this._dialog.open(ConfirmationDialogComponent, {
width: '400px',
maxWidth: '90vw'
}).afterClosed().subscribe(result => {
});
ref.afterClosed().subscribe(result => {
if (result) {
this._manualRedactionControllerService.undo(projectId, fileId, annotationId).subscribe(ok => {
this._notificationService.showToastNotification(this._translateService.instant('manual-redaction.remove-annotation.success.label'), null, NotificationType.SUCCESS);
@ -113,63 +125,74 @@ export class DialogService {
}
});
return ref;
}
public openEditProjectDialog($event: MouseEvent, project: Project) {
public openEditProjectDialog($event: MouseEvent, project: Project): MatDialogRef<AddEditProjectDialogComponent> {
$event.stopPropagation();
this._dialog.open(AddEditProjectDialogComponent, {
return this._dialog.open(AddEditProjectDialogComponent, {
...dialogConfig,
autoFocus: true,
data: project
});
}
public openDeleteProjectDialog($event: MouseEvent, project: Project, cb?: Function) {
public openDeleteProjectDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef<ConfirmationDialogComponent> {
$event.stopPropagation();
this._dialog.open(ConfirmationDialogComponent, dialogConfig)
.afterClosed().subscribe(async result => {
const ref = this._dialog.open(ConfirmationDialogComponent, dialogConfig);
ref.afterClosed().subscribe(async result => {
if (result) {
await this._appStateService.deleteProject(project);
if (cb) cb();
}
});
return ref;
}
public openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: Project, cb?: Function) {
public openAssignProjectMembersAndOwnerDialog($event: MouseEvent, project: Project, cb?: Function): MatDialogRef<AssignOwnerDialogComponent> {
$event?.stopPropagation();
this._dialog.open(AssignOwnerDialogComponent, {
const ref = this._dialog.open(AssignOwnerDialogComponent, {
...dialogConfig,
data: {type: 'project', project: project}
}).afterClosed().subscribe(result => {
data: { type: 'project', project: project }
});
ref.afterClosed().subscribe(result => {
if (result && cb) cb();
});
return ref;
}
public openAssignFileOwnerDialog($event: MouseEvent, file: FileStatus, cb?: Function) {
public openAssignFileOwnerDialog($event: MouseEvent, file: FileStatus, cb?: Function): MatDialogRef<AssignOwnerDialogComponent> {
$event.stopPropagation();
this._dialog.open(AssignOwnerDialogComponent, {
const ref = this._dialog.open(AssignOwnerDialogComponent, {
...dialogConfig,
data: {type: 'file', file: file}
}).afterClosed().subscribe(() => {
data: { type: 'file', file: file }
});
ref.afterClosed().subscribe(() => {
if (cb) cb();
});
return ref;
}
public openProjectDetailsDialog($event: MouseEvent, project: ProjectWrapper) {
public openProjectDetailsDialog($event: MouseEvent, project: ProjectWrapper): MatDialogRef<ProjectDetailsDialogComponent> {
$event.stopPropagation();
this._dialog.open(ProjectDetailsDialogComponent, {
return this._dialog.open(ProjectDetailsDialogComponent, {
...dialogConfig,
data: project
});
}
public openAddProjectDialog(cb?: Function): void {
this._dialog.open(AddEditProjectDialogComponent, {
public openAddProjectDialog(cb?: Function): MatDialogRef<AddEditProjectDialogComponent> {
const ref = this._dialog.open(AddEditProjectDialogComponent, {
...dialogConfig,
autoFocus: true
}).afterClosed().subscribe(result => {
});
ref.afterClosed().subscribe(result => {
if (result && cb) cb();
});
}
return ref;
}
}

View File

@ -127,7 +127,9 @@
<div class="right-content">
<div class="pages" [class.activePanel]="pagesPanelActive"
(keyup)="$event.preventDefault();"
tabindex="0"
(keyup)="$event.preventDefault()"
(keydown)="$event.preventDefault();"
#quickNavigation>
<div class="page-number pointer"
[ngClass]="{ active: pageNumber === activeViewerPage }"
@ -138,7 +140,9 @@
</div>
<div class="annotations" [class.activePanel]="!pagesPanelActive" #annotations
(keyup)="$event.preventDefault();"
tabindex="1"
(keyup)="$event.preventDefault()"
(keydown)="$event.preventDefault();"
>
<div *ngFor="let page of displayedPages">
<div class="page-separator" attr.anotation-page-header="{{page}}">

View File

@ -63,6 +63,7 @@ redaction-pdf-viewer {
.pages, .annotations {
overflow-y: scroll;
@include no-scroll-bar();
outline: none;
&.activePanel {
background-color: #FAFAFA;

View File

@ -14,6 +14,7 @@ import { FileDownloadService } from '../service/file-download.service';
import { saveAs } from 'file-saver';
import { FileType } from '../model/file-type';
import { DialogService } from '../../../dialogs/dialog.service';
import { MatDialogRef, MatDialogState } from '@angular/material/dialog';
@Component({
selector: 'redaction-file-preview-screen',
@ -25,6 +26,7 @@ export class FilePreviewScreenComponent implements OnInit {
private projectId: string;
private _activeViewer: 'ANNOTATED' | 'REDACTED' = 'ANNOTATED';
private instance: WebViewerInstance;
private _dialogRef: MatDialogRef<any>;
@ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent;
@ViewChild('annotations') private _annotationsElement: ElementRef;
@ -37,7 +39,7 @@ export class FilePreviewScreenComponent implements OnInit {
public displayedAnnotations: { [key: number]: { annotations: Annotations.Annotation[] } } = {};
public selectedAnnotation: Annotations.Annotation;
public filters: AnnotationFilters;
public expandedFilters: AnnotationFilters = {hint: false};
public expandedFilters: AnnotationFilters = { hint: false };
public pagesPanelActive = true;
constructor(
@ -84,11 +86,11 @@ export class FilePreviewScreenComponent implements OnInit {
localStorage.clear();
this._reloadFiles();
this.appStateService.fileStatusChanged.subscribe((fileStatus) => {
if(fileStatus.fileId === this.fileId) {
if (fileStatus.fileId === this.fileId) {
console.log(fileStatus);
this._reloadFiles();
}
})
});
}
private _reloadFiles() {
@ -103,7 +105,7 @@ export class FilePreviewScreenComponent implements OnInit {
}
public openFileDetailsDialog($event: MouseEvent) {
this._dialogService.openFileDetailsDialog($event, this.appStateService.activeFile);
this._dialogRef = this._dialogService.openFileDetailsDialog($event, this.appStateService.activeFile);
}
public reanalyseFile($event: MouseEvent) {
@ -114,17 +116,16 @@ export class FilePreviewScreenComponent implements OnInit {
}
public openDeleteFileDialog($event: MouseEvent) {
this._dialogService.openDeleteFileDialog($event, this.projectId, this.fileId, () => {
this._dialogRef = this._dialogService.openDeleteFileDialog($event, this.projectId, this.fileId, () => {
this._router.navigate([`/ui/projects/${this.projectId}`]);
});
}
public openAssignFileOwnerDialog($event: MouseEvent) {
const file = this.appStateService.getFileById(this.projectId, this.fileId);
this._dialogService.openAssignFileOwnerDialog($event, file);
this._dialogRef = this._dialogService.openAssignFileOwnerDialog($event, file);
}
public get activeViewer() {
return this.instance;
}
@ -162,7 +163,7 @@ export class FilePreviewScreenComponent implements OnInit {
public openManualRedactionDialog($event: ManualRedactionEntry) {
this.ngZone.run(() => {
this._dialogService.openManualRedactionDialog($event, () => {
this._dialogRef = this._dialogService.openManualRedactionDialog($event, () => {
});
});
@ -212,13 +213,13 @@ export class FilePreviewScreenComponent implements OnInit {
public acceptSuggestionAnnotation($event: MouseEvent, annotation: Annotations.Annotation) {
this.ngZone.run(() => {
this._dialogService.acceptSuggestionAnnotation($event, annotation, this.projectId, this.fileId);
this._dialogRef = this._dialogService.acceptSuggestionAnnotation($event, annotation, this.projectId, this.fileId);
});
}
public suggestRemoveAnnotation($event: MouseEvent, annotation: Annotations.Annotation) {
this.ngZone.run(() => {
this._dialogService.suggestRemoveAnnotation($event, annotation, this.projectId, this.fileId);
this._dialogRef = this._dialogService.suggestRemoveAnnotation($event, annotation, this.projectId, this.fileId);
});
}
@ -272,6 +273,12 @@ export class FilePreviewScreenComponent implements OnInit {
@HostListener('window:keyup', ['$event'])
handleKeyEvent($event: KeyboardEvent) {
const keyArray = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
if (!keyArray.includes($event.key) || this._dialogRef?.getState() === MatDialogState.OPEN) {
return;
}
if ($event.key === 'ArrowLeft' || $event.key === 'ArrowRight') {
this.pagesPanelActive = !this.pagesPanelActive;
this._changeDetectorRef.detectChanges();
@ -391,9 +398,9 @@ export class FilePreviewScreenComponent implements OnInit {
// handle comments
annotations.forEach(a => {
a['comments'] = a['Mi'] ? a['Mi'].map(m => {
return {value: m.eC}
return { value: m.eC };
}) : [];
})
});
AnnotationUtils.addAnnotations(this.annotations, annotations);
this.applyFilters();