Accept suggestion menu

This commit is contained in:
Adina Țeudan 2020-11-02 06:34:12 +02:00
parent 4fc0c92753
commit a4bcded240
7 changed files with 167 additions and 90 deletions

View File

@ -99,7 +99,7 @@ export class DialogService {
return ref;
}
public acceptSuggestion(
public openAcceptSuggestionModal(
$event: MouseEvent,
annotation: AnnotationWrapper
): MatDialogRef<ConfirmationDialogComponent> {
@ -115,7 +115,7 @@ export class DialogService {
return ref;
}
public rejectSuggestion(
public openRejectSuggestionModal(
$event: MouseEvent,
annotation: AnnotationWrapper,
rejectCallback: () => void

View File

@ -1,7 +1,7 @@
<section [class.hidden]="!viewReady">
<div class="page-header">
<div class="flex-1">
<mat-slide-toggle color="primary" labelPosition="after" [(ngModel)]="redactedView">
<mat-slide-toggle [(ngModel)]="redactedView" color="primary" labelPosition="after">
{{ 'file-preview.view-toggle.label' | translate }}
</mat-slide-toggle>
</div>
@ -13,9 +13,9 @@
<div class="flex-1 actions-container">
<div class="actions-row">
<button
mat-icon-button
(click)="openDeleteFileDialog($event)"
*ngIf="userService.isManager(user)"
mat-icon-button
>
<mat-icon svgIcon="red:trash"></mat-icon>
</button>
@ -23,49 +23,49 @@
<mat-icon svgIcon="red:report"></mat-icon>
</button>
<button
mat-icon-button
(click)="assignReviewer()"
*ngIf="appStateService.isActiveProjectMember"
mat-icon-button
>
<mat-icon svgIcon="red:assign"></mat-icon>
</button>
<button
mat-icon-button
(click)="reanalyseFile($event)"
*ngIf="userService.isManager(user)"
mat-icon-button
>
<mat-icon svgIcon="red:refresh"></mat-icon>
</button>
<button mat-icon-button (click)="openFileDetailsDialog($event)">
<button (click)="openFileDetailsDialog($event)" mat-icon-button>
<mat-icon svgIcon="red:info"></mat-icon>
</button>
</div>
<button
*ngIf="userService.isManager(user)"
[matMenuTriggerFor]="downloadMenu"
class="arrow-button"
color="primary"
mat-flat-button
class="arrow-button"
[matMenuTriggerFor]="downloadMenu"
>
<span translate="file-preview.download.label"></span>
<mat-icon svgIcon="red:arrow-down"></mat-icon>
</button>
<mat-menu #downloadMenu="matMenu" xPosition="before">
<div
(click)="downloadFile('ORIGINAL')"
mat-menu-item
translate="file-preview.download.dropdown.original.label"
(click)="downloadFile('ORIGINAL')"
></div>
<div
(click)="downloadFile('ANNOTATED')"
mat-menu-item
translate="file-preview.download.dropdown.annotated.label"
(click)="downloadFile('ANNOTATED')"
></div>
<div
(click)="downloadFile('REDACTED')"
mat-menu-item
translate="file-preview.download.dropdown.redacted.label"
(click)="downloadFile('REDACTED')"
></div>
</mat-menu>
</div>
@ -74,68 +74,68 @@
<div class="flex red-content-inner">
<div class="left-container">
<redaction-pdf-viewer
(annotationSelected)="handleAnnotationSelected($event)"
(keyUp)="handleKeyEvent($event)"
(manualAnnotationRequested)="openManualRedactionDialog($event)"
(pageChanged)="viewerPageChanged($event)"
(viewerReady)="viewerReady($event)"
*ngIf="fileData"
[fileData]="redactedView ? fileData.redactedFileData : fileData.annotatedFileData"
[fileStatus]="appStateService.activeFile"
(keyUp)="handleKeyEvent($event)"
(pageChanged)="viewerPageChanged($event)"
(manualAnnotationRequested)="openManualRedactionDialog($event)"
(annotationSelected)="handleAnnotationSelected($event)"
(viewerReady)="viewerReady($event)"
></redaction-pdf-viewer>
</div>
<div class="right-fixed-container">
<div class="right-title heading" translate="file-preview.tabs.annotations.label">
<redaction-filter
(filtersChanged)="filtersChanged($event)"
[filterTemplate]="annotationFilterTemplate"
[filters]="filters"
(filtersChanged)="filtersChanged($event)"
></redaction-filter>
</div>
<div class="right-content">
<div
class="pages"
[class.activePanel]="pagesPanelActive"
tabindex="0"
(keyup)="preventArrowDefault($event)"
(keydown)="preventArrowDefault($event)"
#quickNavigation
(keydown)="preventArrowDefault($event)"
(keyup)="preventArrowDefault($event)"
[class.activePanel]="pagesPanelActive"
class="pages"
tabindex="0"
>
<div
class="page-number pointer"
[ngClass]="{ active: pageNumber === activeViewerPage }"
(click)="selectPage(pageNumber)"
*ngFor="let pageNumber of displayedPages"
[id]="'quick-nav-page-' + pageNumber"
(click)="selectPage(pageNumber)"
[ngClass]="{ active: pageNumber === activeViewerPage }"
class="page-number pointer"
>
{{ pageNumber }}
</div>
</div>
<div
class="annotations"
[class.activePanel]="!pagesPanelActive"
#annotationsElement
tabindex="1"
(keyup)="preventArrowDefault($event)"
(keydown)="preventArrowDefault($event)"
(keyup)="preventArrowDefault($event)"
[class.activePanel]="!pagesPanelActive"
class="annotations"
tabindex="1"
>
<div *ngFor="let page of displayedPages">
<div class="page-separator" attr.anotation-page-header="{{ page }}">
<div attr.anotation-page-header="{{ page }}" class="page-separator">
<span class="all-caps-label"
><span translate="page"></span> {{ page }}</span
>
</div>
<div
(click)="selectAnnotation(annotation)"
*ngFor="let annotation of displayedAnnotations[page].annotations"
class="annotation"
[ngClass]="{ active: selectedAnnotation?.id === annotation.id }"
attr.annotation-id="{{ annotation.id }}"
attr.annotation-page="{{ page }}"
[ngClass]="{ active: selectedAnnotation?.id === annotation.id }"
(click)="selectAnnotation(annotation)"
class="annotation"
>
<div class="details">
<redaction-annotation-icon
@ -169,19 +169,53 @@
></redaction-comments>
<div
class="annotation-actions"
*ngIf="annotation.superType === 'request'"
[class.visible]="isSuggestionVisible(annotation)"
class="annotation-actions"
>
<button
mat-icon-button
(click)="acceptSuggestion($event, annotation)"
(click)="openAcceptSuggestionMenu($event, annotation)"
*ngIf="appStateService.isActiveProjectOwnerAndManager"
[class.active]="isSuggestionVisible(annotation)"
[matMenuTriggerFor]="menu"
class="confirm"
mat-icon-button
>
<mat-icon svgIcon="red:check-alt"></mat-icon>
</button>
<mat-menu
#menu="matMenu"
(closed)="onSuggestionMenuClose()"
xPosition="before"
>
<div
(click)="acceptSuggestion($event, annotation)"
mat-menu-item
>
<!-- TODO -->
<redaction-annotation-icon
[typeValue]="{ hexColor: '#5CE594', type: 'S' }"
></redaction-annotation-icon>
<div
translate="file-preview.tabs.annotations.accept-suggestion.add-to-dict.label"
></div>
</div>
<div
(click)="acceptSuggestion($event, annotation)"
mat-menu-item
>
<!-- TODO -->
<redaction-annotation-icon
[typeValue]="{ hexColor: '#5B97DB', type: 'S' }"
></redaction-annotation-icon>
<div
translate="file-preview.tabs.annotations.accept-suggestion.only-here.label"
></div>
</div>
</mat-menu>
<button
mat-icon-button
(click)="rejectSuggestion($event, annotation)"
mat-icon-button
>
<mat-icon svgIcon="red:trash"></mat-icon>
</button>

View File

@ -104,22 +104,7 @@ redaction-pdf-viewer {
background-color: #f9fafb;
.annotation-actions {
background: linear-gradient(
to right,
transparent 0%,
#f9fafb,
#f9fafb,
#f9fafb
);
display: flex;
align-items: center;
justify-content: flex-end;
width: 120px;
padding-right: 16px;
.confirm {
color: $green-2;
}
}
}
@ -133,7 +118,25 @@ redaction-pdf-viewer {
top: 0;
bottom: 0;
display: none;
width: 40px;
align-items: center;
justify-content: flex-end;
width: 120px;
padding-right: 16px;
background: linear-gradient(
to right,
transparent 0%,
#f9fafb,
#f9fafb,
#f9fafb
);
.confirm.active {
background-color: $grey-2;
}
&.visible {
display: flex;
}
}
}
}

View File

@ -29,6 +29,7 @@ import { FileActionService } from '../service/file-action.service';
import { AnnotationDrawService } from '../service/annotation-draw.service';
import { AnnotationProcessingService } from '../service/annotation-processing.service';
import { FilterModel } from '../../../common/filter/model/filter.model';
import { MatMenuTrigger } from '@angular/material/menu';
const KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
@ -38,24 +39,6 @@ const KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
styleUrls: ['./file-preview-screen.component.scss']
})
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('annotationsElement') private _annotationsElement: ElementRef;
@ViewChild('quickNavigation') private _quickNavigationElement: ElementRef;
public fileData: FileDataModel;
public fileId: string;
public annotations: AnnotationWrapper[] = [];
public displayedAnnotations: { [key: number]: { annotations: AnnotationWrapper[] } } = {};
public selectedAnnotation: AnnotationWrapper;
public pagesPanelActive = true;
public viewReady = false;
filters: FilterModel[];
constructor(
public readonly appStateService: AppStateService,
public readonly userService: UserService,
@ -90,6 +73,38 @@ export class FilePreviewScreenComponent implements OnInit {
this._activeViewer = value ? 'REDACTED' : 'ANNOTATED';
}
public get activeViewer() {
return this.instance;
}
public get displayedPages(): number[] {
return Object.keys(this.displayedAnnotations).map((key) => Number(key));
}
get activeViewerPage() {
return this.instance?.docViewer?.getCurrentPage();
}
private projectId: string;
private _activeViewer: 'ANNOTATED' | 'REDACTED' = 'ANNOTATED';
private instance: WebViewerInstance;
private _dialogRef: MatDialogRef<any>;
@ViewChild(PdfViewerComponent) private _viewerComponent: PdfViewerComponent;
@ViewChild('annotationsElement') private _annotationsElement: ElementRef;
@ViewChild('quickNavigation') private _quickNavigationElement: ElementRef;
@ViewChild('menu') private _matMenuTrigger: MatMenuTrigger;
public fileData: FileDataModel;
public fileId: string;
public annotations: AnnotationWrapper[] = [];
public displayedAnnotations: { [key: number]: { annotations: AnnotationWrapper[] } } = {};
public selectedAnnotation: AnnotationWrapper;
public pagesPanelActive = true;
public viewReady = false;
public filters: FilterModel[];
private _activeSuggestion: AnnotationWrapper;
public ngOnInit(): void {
this._loadFileData();
this.appStateService.fileStatusChanged.subscribe((fileStatus) => {
@ -152,14 +167,6 @@ export class FilePreviewScreenComponent implements OnInit {
this._fileActionService.assignProjectReviewer();
}
public get activeViewer() {
return this.instance;
}
public get displayedPages(): number[] {
return Object.keys(this.displayedAnnotations).map((key) => Number(key));
}
public handleAnnotationSelected(annotationId: string) {
this.selectedAnnotation = this.annotations.find((a) => a.id === annotationId);
this.scrollToSelectedAnnotation();
@ -197,10 +204,6 @@ export class FilePreviewScreenComponent implements OnInit {
});
}
get activeViewerPage() {
return this.instance?.docViewer?.getCurrentPage();
}
@debounce()
private _scrollViews() {
this._scrollQuickNavigation();
@ -242,18 +245,36 @@ export class FilePreviewScreenComponent implements OnInit {
}
}
public isSuggestionVisible(annotation: AnnotationWrapper) {
return annotation.id === this._activeSuggestion?.id;
}
public acceptSuggestion($event: MouseEvent, annotation: AnnotationWrapper) {
this.ngZone.run(() => {
this._dialogRef = this._dialogService.acceptSuggestion($event, annotation);
this._dialogRef = this._dialogService.openAcceptSuggestionModal($event, annotation);
});
}
public openAcceptSuggestionMenu($event: MouseEvent, annotation: AnnotationWrapper) {
$event.preventDefault();
this._activeSuggestion = annotation;
this._matMenuTrigger.openMenu();
}
public onSuggestionMenuClose() {
this._activeSuggestion = null;
}
public rejectSuggestion($event: MouseEvent, annotation: AnnotationWrapper) {
this.ngZone.run(() => {
this._dialogRef = this._dialogService.rejectSuggestion($event, annotation, () => {
// TODO DELETE ANNOTATIOn
//this.activeViewer.annotManager.deleteAnnotation(annotation, false, true);
});
this._dialogRef = this._dialogService.openRejectSuggestionModal(
$event,
annotation,
() => {
// TODO DELETE ANNOTATIOn
//this.activeViewer.annotManager.deleteAnnotation(annotation, false, true);
}
);
});
}

View File

@ -478,7 +478,15 @@
"label": "Quick Navigation"
},
"annotations": {
"label": "Annotations"
"label": "Annotations",
"accept-suggestion": {
"add-to-dict": {
"label": "Approve and add to dictionary"
},
"only-here": {
"label": "Approve only here"
}
}
},
"info": {
"label": "Info",

View File

@ -43,3 +43,10 @@
width: 9px;
margin-left: 3px;
}
.mat-icon-button {
transition: background-color 0.25s ease-in-out;
&:hover {
background-color: $grey-2;
}
}

View File

@ -10,6 +10,10 @@
font-size: 13px;
color: $accent;
display: flex;
align-items: center;
gap: 8px;
.arrow-wrapper {
width: 16px;
margin-right: 8px;