more corner-cases for actions

This commit is contained in:
Timo 2021-02-24 17:05:02 +02:00
parent 2ae98523f5
commit 10c08bc50f
13 changed files with 54 additions and 27 deletions

View File

@ -110,7 +110,10 @@ export class AnnotationActionsService {
const availableActions = [];
const annotationPermissions = annotations.map((a) => {
return { annotation: a, permissions: AnnotationPermissions.forUser(this._permissionsService.currentUser, a) };
return {
annotation: a,
permissions: AnnotationPermissions.forUser(this._permissionsService.isManagerAndOwner(), this._permissionsService.currentUser, a)
};
});
const canForceRedaction = annotationPermissions.reduce((acc, next) => acc && next.permissions.canForceRedaction, true);

View File

@ -8,6 +8,7 @@
*ngIf="
filter.key === 'suggestion-remove' ||
filter.key === 'suggestion' ||
filter.key === 'suggestion-force-redaction' ||
filter.key === 'suggestion-add' ||
filter.key === 'suggestion-remove-dictionary' ||
filter.key === 'suggestion-add-dictionary'

View File

@ -40,7 +40,12 @@
<mat-select panelClass="description-select" formControlName="dictionary">
<mat-select-trigger>{{ displayedDictionaryLabel }}</mat-select-trigger>
<mat-option *ngFor="let dictionary of redactionDictionaries" [value]="dictionary.type" [matTooltip]="dictionary.description">
<mat-option
*ngFor="let dictionary of redactionDictionaries"
[value]="dictionary.type"
[matTooltip]="dictionary.description"
matTooltipPosition="after"
>
<span>
{{ dictionary.label }}
</span>

View File

@ -22,7 +22,7 @@
<redaction-circle-button
(action)="annotationActionsService.markTextOnlyAsFalsePositive($event, [annotation], annotationsChanged)"
type="dark-bg"
*ngIf="annotationPermissions.canMarkTextOnlyAsFalsePositive"
*ngIf="annotationPermissions.canMarkTextOnlyAsFalsePositive && !annotationPermissions.canPerformMultipleRemoveActions"
tooltipPosition="before"
tooltip="annotation-actions.remove-annotation.false-positive"
icon="red:thumb-down"

View File

@ -4,7 +4,7 @@ import { AppStateService } from '../../../state/app-state.service';
import { PermissionsService } from '../../../common/service/permissions.service';
import { AnnotationPermissions } from '../model/annotation.permissions';
import { AnnotationActionsService } from '../../../common/service/annotation-actions.service';
import { WebViewerInstance, Annotations } from '@pdftron/webviewer';
import { Annotations, WebViewerInstance } from '@pdftron/webviewer';
@Component({
selector: 'redaction-annotation-actions',
@ -28,7 +28,11 @@ export class AnnotationActionsComponent implements OnInit {
) {}
ngOnInit(): void {
this.annotationPermissions = AnnotationPermissions.forUser(this._permissionsService.currentUser, this.annotation);
this.annotationPermissions = AnnotationPermissions.forUser(
this._permissionsService.isManagerAndOwner(),
this._permissionsService.currentUser,
this.annotation
);
}
public get viewerAnnotation(): Annotations.Annotation {

View File

@ -133,7 +133,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
filesAutoUpdateTimer: Subscription;
fileReanalysedSubscription: Subscription;
hideSkipped = true;
hideSkipped = false;
updateViewMode() {
const allAnnotations = this._instance.annotManager.getAnnotationsList();
@ -568,7 +568,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
this._fileDownloadService.loadActiveFileManualAnnotations().subscribe((manualRedactions) => {
this.fileData.manualRedactions = manualRedactions;
this._rebuildFilters();
this._annotationDrawService.drawAnnotations(this._instance, this.annotationData.allAnnotations);
this._annotationDrawService.drawAnnotations(this._instance, this.annotationData.allAnnotations, this.hideSkipped);
});
}
@ -586,7 +586,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
});
const newPageAnnotations = this.annotations.filter((item) => item.pageNumber === page);
this._handleDeltaAnnotationFilters(currentPageAnnotations, newPageAnnotations);
this._annotationDrawService.drawAnnotations(this._instance, newPageAnnotations);
this._annotationDrawService.drawAnnotations(this._instance, newPageAnnotations, this.hideSkipped);
}
});
}

View File

@ -16,10 +16,10 @@ export class AnnotationPermissions {
canForceRedaction: boolean;
public static forUser(user: UserWrapper, annotation: AnnotationWrapper) {
public static forUser(isManagerAndOwner: boolean, user: UserWrapper, annotation: AnnotationWrapper) {
const permissions: AnnotationPermissions = new AnnotationPermissions();
permissions.canUndo = annotation.userId === user.id && annotation.isUndoableSuperType;
permissions.canUndo = annotation.isUndoableSuperType && (annotation.userId === user.id || (annotation.userId && isManagerAndOwner));
permissions.canForceRedaction = annotation.isSkipped && !permissions.canUndo;
permissions.canAcceptRecommendation = annotation.isRecommendation;
@ -30,15 +30,21 @@ export class AnnotationPermissions {
permissions.canRemoveOrSuggestToRemoveOnlyHere = annotation.isRedacted;
permissions.canRemoveOrSuggestToRemoveFromDictionary = annotation.isRedacted && !annotation.isManualRedaction && annotation.isModifyDictionary;
permissions.canAcceptSuggestion = user.isManager && (annotation.isSuggestion || annotation.isDeclinedSuggestion);
permissions.canAcceptSuggestion = isManagerAndOwner && (annotation.isSuggestion || annotation.isDeclinedSuggestion);
permissions.canRejectSuggestion =
user.isManager &&
isManagerAndOwner &&
(annotation.isSuggestion || (annotation.isReadyForAnalysis && !permissions.canUndo && annotation.superType !== 'pending-analysis'));
return permissions;
}
public get canPerformMultipleRemoveActions() {
return <any>this.canMarkAsFalsePositive + <any>this.canRemoveOrSuggestToRemoveFromDictionary + <any>this.canRemoveOrSuggestToRemoveOnlyHere >= 2;
return (
<any>this.canMarkTextOnlyAsFalsePositive +
<any>this.canMarkAsFalsePositive +
<any>this.canRemoveOrSuggestToRemoveFromDictionary +
<any>this.canRemoveOrSuggestToRemoveOnlyHere >=
2
);
}
}

View File

@ -7,6 +7,7 @@ export class AnnotationWrapper {
| 'remove-dictionary'
| 'remove-only-here'
| 'suggestion-add-dictionary'
| 'suggestion-force-redaction'
| 'suggestion-remove-dictionary'
| 'suggestion-add'
| 'suggestion-remove'
@ -48,10 +49,13 @@ export class AnnotationWrapper {
this.superType === 'add-dictionary' ||
this.superType === 'remove-dictionary' ||
this.superType === 'suggestion-add-dictionary' ||
this.superType === 'suggestion-force-redaction' ||
this.superType === 'suggestion-remove-dictionary' ||
this.superType === 'suggestion-add' ||
this.superType === 'suggestion-remove' ||
this.superType === 'skipped'
this.superType === 'skipped' ||
this.superType === 'redaction' ||
this.superType === 'manual-redaction'
);
}
@ -129,7 +133,7 @@ export class AnnotationWrapper {
}
get isSuggestionAdd() {
return this.superType === 'suggestion-add' || this.superType === 'suggestion-add-dictionary';
return this.superType === 'suggestion-add' || this.superType === 'suggestion-add-dictionary' || this.superType === 'suggestion-force-redaction';
}
get isSuggestionRemove() {
@ -218,7 +222,9 @@ export class AnnotationWrapper {
}
} else {
if (redactionLogEntryWrapper.redacted) {
if (redactionLogEntryWrapper.type === 'manual') {
if (redactionLogEntryWrapper.force) {
annotationWrapper.superType = redactionLogEntryWrapper.status === 'REQUESTED' ? 'suggestion-add' : 'redaction';
} else if (redactionLogEntryWrapper.type === 'manual') {
annotationWrapper.superType = redactionLogEntryWrapper.status === 'REQUESTED' ? 'suggestion-add' : 'manual-redaction';
} else {
if (redactionLogEntryWrapper.status === 'REQUESTED') {
@ -252,6 +258,11 @@ export class AnnotationWrapper {
annotationWrapper.superType = 'pending-analysis';
return;
}
} else {
if (redactionLogEntryWrapper.status === 'REQUESTED') {
annotationWrapper.superType = 'suggestion-force-redaction';
return;
}
}
if (redactionLogEntryWrapper.actionPendingReanalysis) {

View File

@ -111,6 +111,7 @@ export class FileDataModel {
if (!!relevantRedactionLogEntry) {
relevantRedactionLogEntry.userId = forceRedaction.user;
relevantRedactionLogEntry.dictionaryEntry = false;
relevantRedactionLogEntry.force = true;
// if statuses differ
if (!forceRedaction.processedDate || forceRedaction.status !== relevantRedactionLogEntry.status) {

View File

@ -19,6 +19,7 @@ export interface RedactionLogEntryWrapper {
textBefore?: string;
type?: string;
value?: string;
force?: boolean;
recommendation?: boolean;
recommendationAnnotationId?: string;

View File

@ -16,10 +16,10 @@ export class AnnotationDrawService {
private readonly _userPreferenceService: UserPreferenceService
) {}
public drawAnnotations(activeViewer: WebViewerInstance, annotationWrappers: AnnotationWrapper[], drawSkipped: boolean = false) {
public drawAnnotations(activeViewer: WebViewerInstance, annotationWrappers: AnnotationWrapper[], hideSkipped: boolean = false) {
const annotations = [];
annotationWrappers.forEach((annotation) => {
annotations.push(this.computeAnnotation(activeViewer, annotation));
annotations.push(this.computeAnnotation(activeViewer, annotation, hideSkipped));
});
const annotationManager = activeViewer.annotManager;
@ -72,7 +72,7 @@ export class AnnotationDrawService {
return rectangleAnnot;
}
public computeAnnotation(activeViewer: WebViewerInstance, annotationWrapper: AnnotationWrapper) {
public computeAnnotation(activeViewer: WebViewerInstance, annotationWrapper: AnnotationWrapper, hideSkipped: boolean = false) {
const pageNumber = annotationWrapper.pageNumber;
const highlight = new activeViewer.Annotations.TextHighlightAnnotation();
highlight.PageNumber = pageNumber;
@ -83,7 +83,7 @@ export class AnnotationDrawService {
highlight.ReadOnly = true;
// change log entries are drawn lighter
highlight.Opacity = annotationWrapper.isChangeLogRemoved ? 0.2 : 1;
highlight.Hidden = annotationWrapper.isChangeLogRemoved || annotationWrapper.isSkipped;
highlight.Hidden = annotationWrapper.isChangeLogRemoved || (hideSkipped && annotationWrapper.isSkipped);
highlight.setCustomData('redaction', annotationWrapper.isRedacted);
highlight.setCustomData('skipped', annotationWrapper.isSkipped);

View File

@ -1,12 +1,6 @@
import { Injectable } from '@angular/core';
import { AppStateService } from '../../../state/app-state.service';
import {
AddRedactionRequest,
DictionaryControllerService,
ForceRedactionRequest,
ManualRedactionControllerService,
ManualRedactionEntry
} from '@redaction/red-ui-http';
import { AddRedactionRequest, DictionaryControllerService, ForceRedactionRequest, ManualRedactionControllerService } from '@redaction/red-ui-http';
import { AnnotationWrapper } from '../model/annotation.wrapper';
import { NotificationService, NotificationType } from '../../../notification/notification.service';
import { TranslateService } from '@ngx-translate/core';

View File

@ -491,6 +491,7 @@
"add-dictionary": "Pending add to dictionary",
"remove-dictionary": "Pending remove from dictionary",
"suggestion-add-dictionary": "Suggested dictionary add",
"suggestion-force-redaction": "Suggestion force redaction",
"suggestion-remove-dictionary": "Suggested dictionary removal",
"suggestion-add": "Suggested redaction",
"suggestion-remove": "Suggested redaction removal",