diff --git a/apps/red-ui/src/app/common/service/annotation-actions.service.ts b/apps/red-ui/src/app/common/service/annotation-actions.service.ts index 65ae7b988..4fed588b5 100644 --- a/apps/red-ui/src/app/common/service/annotation-actions.service.ts +++ b/apps/red-ui/src/app/common/service/annotation-actions.service.ts @@ -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); diff --git a/apps/red-ui/src/app/components/type-filter/type-filter.component.html b/apps/red-ui/src/app/components/type-filter/type-filter.component.html index 00663d6dd..16f989ec5 100644 --- a/apps/red-ui/src/app/components/type-filter/type-filter.component.html +++ b/apps/red-ui/src/app/components/type-filter/type-filter.component.html @@ -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' diff --git a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html index 016d1cfbf..d6004e929 100644 --- a/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html +++ b/apps/red-ui/src/app/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html @@ -40,7 +40,12 @@ {{ displayedDictionaryLabel }} - + {{ dictionary.label }} diff --git a/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html b/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html index ae4f620d1..842d6efe9 100644 --- a/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html +++ b/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html @@ -22,7 +22,7 @@ { 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); } }); } diff --git a/apps/red-ui/src/app/screens/file/model/annotation.permissions.ts b/apps/red-ui/src/app/screens/file/model/annotation.permissions.ts index f1e9b4d42..7ba795427 100644 --- a/apps/red-ui/src/app/screens/file/model/annotation.permissions.ts +++ b/apps/red-ui/src/app/screens/file/model/annotation.permissions.ts @@ -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 this.canMarkAsFalsePositive + this.canRemoveOrSuggestToRemoveFromDictionary + this.canRemoveOrSuggestToRemoveOnlyHere >= 2; + return ( + this.canMarkTextOnlyAsFalsePositive + + this.canMarkAsFalsePositive + + this.canRemoveOrSuggestToRemoveFromDictionary + + this.canRemoveOrSuggestToRemoveOnlyHere >= + 2 + ); } } diff --git a/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts b/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts index 674093aca..678b69923 100644 --- a/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts +++ b/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts @@ -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) { diff --git a/apps/red-ui/src/app/screens/file/model/file-data.model.ts b/apps/red-ui/src/app/screens/file/model/file-data.model.ts index d008f6ef6..1381e4bfb 100644 --- a/apps/red-ui/src/app/screens/file/model/file-data.model.ts +++ b/apps/red-ui/src/app/screens/file/model/file-data.model.ts @@ -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) { diff --git a/apps/red-ui/src/app/screens/file/model/redaction-log-entry.wrapper.ts b/apps/red-ui/src/app/screens/file/model/redaction-log-entry.wrapper.ts index 1afadd4b1..38c59a134 100644 --- a/apps/red-ui/src/app/screens/file/model/redaction-log-entry.wrapper.ts +++ b/apps/red-ui/src/app/screens/file/model/redaction-log-entry.wrapper.ts @@ -19,6 +19,7 @@ export interface RedactionLogEntryWrapper { textBefore?: string; type?: string; value?: string; + force?: boolean; recommendation?: boolean; recommendationAnnotationId?: string; diff --git a/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts b/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts index aa30fea72..64c39f020 100644 --- a/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts +++ b/apps/red-ui/src/app/screens/file/service/annotation-draw.service.ts @@ -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); diff --git a/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts b/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts index 7bb8caf1b..b8237d1b0 100644 --- a/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts +++ b/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts @@ -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'; diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index 8ce911a7d..63013ba2f 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -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",