rework of annotations
This commit is contained in:
parent
3f7237993d
commit
959bde335c
@ -26,19 +26,13 @@ export class AnnotationActionsService {
|
||||
|
||||
public canRejectSuggestion(annotation: AnnotationWrapper): boolean {
|
||||
// i can reject whatever i may not undo
|
||||
return (
|
||||
!this.canUndoAnnotation(annotation) &&
|
||||
((this.canAcceptSuggestion(annotation) && !annotation.isDeclinedSuggestion) || (annotation.isModifyDictionary && !annotation.isDeclinedSuggestion))
|
||||
);
|
||||
return !this.canUndoAnnotation(annotation) && this.canAcceptSuggestion(annotation) && !annotation.isDeclinedSuggestion;
|
||||
}
|
||||
|
||||
public canDirectlySuggestToRemoveAnnotation(annotation: AnnotationWrapper): boolean {
|
||||
return (
|
||||
// annotation.isHint || // HINTS CAN NO LONGER BE REMOVED DIRECTLY ONLY VIA DICTIONARY ACTION
|
||||
annotation.isManual &&
|
||||
this._permissionsService.isManagerAndOwner() &&
|
||||
!this.canUndoAnnotation(annotation) &&
|
||||
!annotation.isRecommendation
|
||||
annotation.isManualRedaction && this._permissionsService.isManagerAndOwner() && !this.canUndoAnnotation(annotation) && !annotation.isRecommendation
|
||||
);
|
||||
}
|
||||
|
||||
@ -47,7 +41,8 @@ export class AnnotationActionsService {
|
||||
}
|
||||
|
||||
public canConvertRecommendationToAnnotation(annotation: AnnotationWrapper): boolean {
|
||||
return annotation.isRecommendation;
|
||||
// recommendations that have not already been turned into a suggestion
|
||||
return annotation.isRecommendation && !annotation.isConvertedRecommendation;
|
||||
}
|
||||
|
||||
public canUndoAnnotation(annotation: AnnotationWrapper): boolean {
|
||||
@ -60,6 +55,7 @@ export class AnnotationActionsService {
|
||||
|
||||
public acceptSuggestion($event: MouseEvent, annotation: AnnotationWrapper, annotationsChanged: EventEmitter<AnnotationWrapper>) {
|
||||
$event?.stopPropagation();
|
||||
console.log(annotation.isModifyDictionary);
|
||||
this._processObsAndEmit(this._manualAnnotationService.approveRequest(annotation.id, annotation.isModifyDictionary), annotation, annotationsChanged);
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { TypeValue } from '@redaction/red-ui-http';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -18,13 +18,7 @@ export class TypeAnnotationIconComponent implements OnChanges {
|
||||
|
||||
ngOnChanges(): void {
|
||||
if (this.annotation) {
|
||||
if (
|
||||
this.annotation.isSuggestion ||
|
||||
this.annotation.isDeclinedSuggestion ||
|
||||
this.annotation.isModifyDictionary ||
|
||||
this.annotation.isIgnored ||
|
||||
this.annotation.isReadyForAnalysis
|
||||
) {
|
||||
if (this.annotation.isSuperTypeBasedColor) {
|
||||
this.color = this._appStateService.getDictionaryColor(this.annotation.superType);
|
||||
} else {
|
||||
this.color = this._appStateService.getDictionaryColor(this.annotation.dictionary);
|
||||
|
||||
@ -150,12 +150,12 @@ export class DialogService {
|
||||
const ref = this._dialog.open(ConfirmationDialogComponent, {
|
||||
...dialogConfig,
|
||||
data: new ConfirmationDialogInput({
|
||||
title: annotation.isManual
|
||||
title: annotation.isManualRedaction
|
||||
? 'confirmation-dialog.remove-manual-redaction.title'
|
||||
: removeFromDictionary
|
||||
? 'confirmation-dialog.remove-from-dictionary.title'
|
||||
: 'confirmation-dialog.remove-only-here.title',
|
||||
question: annotation.isManual
|
||||
question: annotation.isManualRedaction
|
||||
? 'confirmation-dialog.remove-manual-redaction.question'
|
||||
: removeFromDictionary
|
||||
? 'confirmation-dialog.remove-from-dictionary.question'
|
||||
|
||||
@ -206,7 +206,7 @@
|
||||
</redaction-page-indicator>
|
||||
</div>
|
||||
|
||||
<div style="overflow: hidden;">
|
||||
<div style="overflow: hidden; width: 100%;">
|
||||
<div attr.anotation-page-header="{{ activeViewerPage }}" class="page-separator">
|
||||
<span *ngIf="!!activeViewerPage" class="all-caps-label"
|
||||
><span translate="page"></span> {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }}
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Comment, IdRemoval, ManualRedactionEntry, Point, Rectangle, RedactionLogEntry, TypeValue } from '@redaction/red-ui-http';
|
||||
import { UserWrapper } from '../../../user/user.service';
|
||||
import { FileStatusWrapper } from './file-status.wrapper';
|
||||
import { Comment, Point, Rectangle } from '@redaction/red-ui-http';
|
||||
import { RedactionLogEntryWrapper } from './redaction-log-entry.wrapper';
|
||||
|
||||
export class AnnotationWrapper {
|
||||
superType:
|
||||
@ -12,17 +11,16 @@ export class AnnotationWrapper {
|
||||
| 'suggestion-remove'
|
||||
| 'ignore'
|
||||
| 'redaction'
|
||||
| 'manual'
|
||||
| 'manual-redaction'
|
||||
| 'hint'
|
||||
| 'declined-suggestion';
|
||||
dictionary: string;
|
||||
color: string;
|
||||
comments: Comment[] = [];
|
||||
firstTopLeftPoint: Point;
|
||||
id: string;
|
||||
annotationId: string;
|
||||
content: string;
|
||||
value: string;
|
||||
manual: boolean;
|
||||
userId: string;
|
||||
typeLabel: string;
|
||||
pageNumber: number;
|
||||
@ -30,14 +28,19 @@ export class AnnotationWrapper {
|
||||
redaction: boolean;
|
||||
status: string;
|
||||
dictionaryOperation: boolean;
|
||||
recommendation: boolean;
|
||||
positions: Rectangle[];
|
||||
|
||||
recommendation: boolean;
|
||||
recommendationType: string;
|
||||
pendingRecommendationAnnotationId: string;
|
||||
|
||||
textAfter?: string;
|
||||
textBefore?: string;
|
||||
|
||||
constructor() {}
|
||||
|
||||
get isDictionaryBased() {
|
||||
return (this.isHint || this.isRedacted) && !this.isManual;
|
||||
return (this.isHint || this.isRedacted) && !this.isManualRedaction;
|
||||
}
|
||||
|
||||
get descriptor() {
|
||||
@ -58,6 +61,10 @@ export class AnnotationWrapper {
|
||||
return this.isRedacted && (this.hasTextAfter || this.hasTextBefore);
|
||||
}
|
||||
|
||||
get isSuperTypeBasedColor() {
|
||||
return this.isIgnored || this.isSuggestion || this.isReadyForAnalysis || this.isDeclinedSuggestion;
|
||||
}
|
||||
|
||||
get isIgnored() {
|
||||
return this.superType === 'ignore';
|
||||
}
|
||||
@ -66,8 +73,8 @@ export class AnnotationWrapper {
|
||||
return this.dictionary === 'false_positive' && (this.superType === 'ignore' || this.superType === 'hint' || this.superType === 'redaction');
|
||||
}
|
||||
|
||||
get isManual() {
|
||||
return this.superType === 'manual';
|
||||
get isManualRedaction() {
|
||||
return this.superType === 'manual-redaction';
|
||||
}
|
||||
|
||||
get isRedactedOrIgnored() {
|
||||
@ -110,127 +117,18 @@ export class AnnotationWrapper {
|
||||
return this.dictionaryOperation;
|
||||
}
|
||||
|
||||
get isConvertedRecommendation() {
|
||||
return this.isRecommendation && (this.superType === 'suggestion-add-dictionary' || this.superType === 'add-dictionary');
|
||||
}
|
||||
|
||||
get isRecommendation() {
|
||||
return this.recommendation;
|
||||
}
|
||||
|
||||
static fromData(
|
||||
user: UserWrapper,
|
||||
dictionaryData: { [p: string]: TypeValue },
|
||||
fileStatus: FileStatusWrapper,
|
||||
redactionLogEntry?: RedactionLogEntry,
|
||||
manualRedactionEntry?: ManualRedactionEntry,
|
||||
idRemoval?: IdRemoval,
|
||||
comments?: Comment[]
|
||||
) {
|
||||
// manual annotations that have been undone
|
||||
if (redactionLogEntry?.type === 'manual' && redactionLogEntry?.manual === true && !manualRedactionEntry) {
|
||||
return;
|
||||
}
|
||||
|
||||
// for declined manual add to dict requests
|
||||
if (manualRedactionEntry?.status === 'DECLINED' && manualRedactionEntry?.type !== 'manual') {
|
||||
manualRedactionEntry.addToDictionary = true;
|
||||
}
|
||||
|
||||
// there has been an undo on a redaction remove
|
||||
if (redactionLogEntry?.manualRedactionType === 'REMOVE' && !idRemoval && !redactionLogEntry.hint) {
|
||||
redactionLogEntry.redacted = true;
|
||||
}
|
||||
|
||||
const annotationWrapper = new AnnotationWrapper();
|
||||
|
||||
annotationWrapper.recommendation = redactionLogEntry ? redactionLogEntry.recommendation : false;
|
||||
if (annotationWrapper.recommendation) {
|
||||
// if we have a manual redaction entry for a recommendation, hide the recommendation
|
||||
if (manualRedactionEntry) {
|
||||
return;
|
||||
}
|
||||
annotationWrapper.recommendationType = redactionLogEntry.type.substr('recommendation_'.length);
|
||||
}
|
||||
annotationWrapper.comments = comments ? comments : [];
|
||||
annotationWrapper.userId = manualRedactionEntry?.user || idRemoval?.user;
|
||||
|
||||
if (redactionLogEntry) {
|
||||
annotationWrapper.id = redactionLogEntry.id;
|
||||
annotationWrapper.redaction = redactionLogEntry.redacted;
|
||||
annotationWrapper.hint = redactionLogEntry.hint;
|
||||
annotationWrapper.dictionary = redactionLogEntry.type;
|
||||
annotationWrapper.value = redactionLogEntry.value;
|
||||
annotationWrapper.firstTopLeftPoint = redactionLogEntry.positions[0]?.topLeft;
|
||||
annotationWrapper.pageNumber = redactionLogEntry.positions[0]?.page;
|
||||
annotationWrapper.positions = redactionLogEntry.positions;
|
||||
annotationWrapper.content = AnnotationWrapper.createContent(redactionLogEntry);
|
||||
annotationWrapper.status = redactionLogEntry.status;
|
||||
annotationWrapper.textBefore = redactionLogEntry.textBefore;
|
||||
annotationWrapper.textAfter = redactionLogEntry.textAfter;
|
||||
} else {
|
||||
// no redaction log entry - not yet processed
|
||||
const dictionary = dictionaryData[manualRedactionEntry.type];
|
||||
annotationWrapper.id = manualRedactionEntry.id;
|
||||
annotationWrapper.redaction = !dictionary.hint;
|
||||
annotationWrapper.hint = dictionary.hint;
|
||||
annotationWrapper.dictionary = manualRedactionEntry.type;
|
||||
annotationWrapper.firstTopLeftPoint = manualRedactionEntry.positions[0]?.topLeft;
|
||||
annotationWrapper.pageNumber = manualRedactionEntry.positions[0]?.page;
|
||||
annotationWrapper.positions = manualRedactionEntry.positions;
|
||||
annotationWrapper.content = manualRedactionEntry.addToDictionary ? null : AnnotationWrapper.createContent(manualRedactionEntry);
|
||||
annotationWrapper.manual = true;
|
||||
annotationWrapper.userId = manualRedactionEntry.user;
|
||||
}
|
||||
|
||||
AnnotationWrapper._setSuperType(annotationWrapper, redactionLogEntry, manualRedactionEntry, idRemoval);
|
||||
|
||||
annotationWrapper.typeLabel = 'annotation-type.' + annotationWrapper.superType;
|
||||
|
||||
return annotationWrapper;
|
||||
get id() {
|
||||
return this.isConvertedRecommendation ? this.pendingRecommendationAnnotationId : this.annotationId;
|
||||
}
|
||||
|
||||
private static _setSuperType(
|
||||
annotationWrapper: AnnotationWrapper,
|
||||
redactionLogEntry?: RedactionLogEntry,
|
||||
manualRedactionEntry?: ManualRedactionEntry,
|
||||
idRemoval?: IdRemoval
|
||||
) {
|
||||
if (idRemoval) {
|
||||
annotationWrapper.dictionaryOperation = idRemoval.removeFromDictionary;
|
||||
if (idRemoval.status === 'DECLINED') {
|
||||
annotationWrapper.superType = 'declined-suggestion';
|
||||
} else {
|
||||
if (idRemoval.removeFromDictionary) {
|
||||
annotationWrapper.superType = idRemoval.status === 'REQUESTED' ? 'suggestion-remove-dictionary' : 'remove-dictionary';
|
||||
} else {
|
||||
// TODO check me
|
||||
annotationWrapper.superType = idRemoval.status === 'REQUESTED' ? 'suggestion-remove' : 'ignore';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manualRedactionEntry) {
|
||||
annotationWrapper.dictionaryOperation = manualRedactionEntry.addToDictionary;
|
||||
if (manualRedactionEntry.status === 'DECLINED') {
|
||||
annotationWrapper.superType = 'declined-suggestion';
|
||||
} else {
|
||||
if (manualRedactionEntry.addToDictionary) {
|
||||
annotationWrapper.superType = manualRedactionEntry.status === 'REQUESTED' ? 'suggestion-add-dictionary' : 'add-dictionary';
|
||||
} else {
|
||||
// TODO check me
|
||||
annotationWrapper.superType = manualRedactionEntry.status === 'REQUESTED' ? 'suggestion-add' : 'manual';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!annotationWrapper.superType) {
|
||||
annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'ignore';
|
||||
}
|
||||
}
|
||||
|
||||
private static _setTypeLabel(annotationWrapper: AnnotationWrapper) {
|
||||
annotationWrapper.typeLabel = annotationWrapper.superType;
|
||||
}
|
||||
|
||||
constructor() {}
|
||||
|
||||
get x() {
|
||||
return this.firstTopLeftPoint.x;
|
||||
}
|
||||
@ -239,6 +137,76 @@ export class AnnotationWrapper {
|
||||
return this.firstTopLeftPoint.y;
|
||||
}
|
||||
|
||||
static fromData(redactionLogEntry?: RedactionLogEntryWrapper) {
|
||||
const annotationWrapper = new AnnotationWrapper();
|
||||
|
||||
annotationWrapper.annotationId = redactionLogEntry.id;
|
||||
annotationWrapper.redaction = redactionLogEntry.redacted;
|
||||
annotationWrapper.hint = redactionLogEntry.hint;
|
||||
annotationWrapper.dictionary = redactionLogEntry.type;
|
||||
annotationWrapper.value = redactionLogEntry.value;
|
||||
annotationWrapper.firstTopLeftPoint = redactionLogEntry.positions[0]?.topLeft;
|
||||
annotationWrapper.pageNumber = redactionLogEntry.positions[0]?.page;
|
||||
annotationWrapper.positions = redactionLogEntry.positions;
|
||||
annotationWrapper.status = redactionLogEntry.status;
|
||||
annotationWrapper.textBefore = redactionLogEntry.textBefore;
|
||||
annotationWrapper.textAfter = redactionLogEntry.textAfter;
|
||||
annotationWrapper.dictionaryOperation = redactionLogEntry.dictionaryEntry;
|
||||
annotationWrapper.userId = redactionLogEntry.userId;
|
||||
annotationWrapper.content = AnnotationWrapper.createContent(redactionLogEntry);
|
||||
AnnotationWrapper._setSuperType(annotationWrapper, redactionLogEntry);
|
||||
AnnotationWrapper._handleRecommendations(annotationWrapper, redactionLogEntry);
|
||||
|
||||
annotationWrapper.content = annotationWrapper.id;
|
||||
|
||||
if (annotationWrapper.dictionary === 'PII') {
|
||||
annotationWrapper.content = annotationWrapper.id;
|
||||
console.log(annotationWrapper, redactionLogEntry, annotationWrapper.id);
|
||||
}
|
||||
|
||||
return annotationWrapper;
|
||||
}
|
||||
|
||||
private static _handleRecommendations(annotationWrapper: AnnotationWrapper, redactionLogEntry: RedactionLogEntryWrapper) {
|
||||
annotationWrapper.recommendation = !!redactionLogEntry?.recommendation;
|
||||
if (annotationWrapper.recommendation) {
|
||||
annotationWrapper.recommendationType = redactionLogEntry.type.substr('recommendation_'.length);
|
||||
if (annotationWrapper.isConvertedRecommendation) {
|
||||
annotationWrapper.dictionary = annotationWrapper.recommendationType;
|
||||
annotationWrapper.pendingRecommendationAnnotationId = redactionLogEntry.pendingRecommendationAnnotationId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static _setSuperType(annotationWrapper: AnnotationWrapper, redactionLogEntryWrapper: RedactionLogEntryWrapper) {
|
||||
if (redactionLogEntryWrapper.manual && redactionLogEntryWrapper.status === 'DECLINED') {
|
||||
annotationWrapper.superType = 'declined-suggestion';
|
||||
return;
|
||||
}
|
||||
|
||||
if (redactionLogEntryWrapper.type === 'manual') {
|
||||
annotationWrapper.superType = redactionLogEntryWrapper.status === 'REQUESTED' ? 'suggestion-add' : 'manual-redaction';
|
||||
} else {
|
||||
if (redactionLogEntryWrapper.status === 'REQUESTED') {
|
||||
if (redactionLogEntryWrapper.dictionaryEntry) {
|
||||
annotationWrapper.superType =
|
||||
redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'suggestion-add-dictionary' : 'suggestion-remove-dictionary';
|
||||
} else {
|
||||
annotationWrapper.superType = redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'suggestion-add' : 'suggestion-remove';
|
||||
}
|
||||
}
|
||||
if (redactionLogEntryWrapper.status === 'APPROVED') {
|
||||
annotationWrapper.superType = redactionLogEntryWrapper.manualRedactionType === 'ADD' ? 'add-dictionary' : 'remove-dictionary';
|
||||
}
|
||||
}
|
||||
|
||||
if (!annotationWrapper.superType) {
|
||||
annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'ignore';
|
||||
}
|
||||
|
||||
annotationWrapper.typeLabel = 'annotation-type.' + annotationWrapper.superType;
|
||||
}
|
||||
|
||||
private static createContent(entry: any) {
|
||||
let content = '';
|
||||
if (entry.matchedRule) {
|
||||
|
||||
@ -2,6 +2,7 @@ import { Comment, IdRemoval, ManualRedactionEntry, ManualRedactions, RedactionLo
|
||||
import { FileStatusWrapper } from './file-status.wrapper';
|
||||
import { UserWrapper } from '../../../user/user.service';
|
||||
import { AnnotationWrapper } from './annotation.wrapper';
|
||||
import { RedactionLogEntryWrapper } from './redaction-log-entry.wrapper';
|
||||
|
||||
export interface AnnotationPair {
|
||||
redactionLogEntry?: RedactionLogEntry;
|
||||
@ -26,85 +27,149 @@ export class FileDataModel {
|
||||
}
|
||||
|
||||
getAnnotations(dictionaryData: { [p: string]: TypeValue }, currentUser: UserWrapper, areDevFeaturesEnabled: boolean): AnnotationWrapper[] {
|
||||
const annotations = [];
|
||||
const entries: RedactionLogEntryWrapper[] = this._convertData(dictionaryData);
|
||||
|
||||
const pairs: AnnotationPair[] = this._createPairs();
|
||||
let annotations = entries.map((entry) => AnnotationWrapper.fromData(entry));
|
||||
|
||||
pairs.forEach((pair) => {
|
||||
const annotation = AnnotationWrapper.fromData(
|
||||
currentUser,
|
||||
dictionaryData,
|
||||
this.fileStatus,
|
||||
pair.redactionLogEntry,
|
||||
pair.manualRedactionEntry,
|
||||
pair.idRemoval,
|
||||
pair.comments
|
||||
);
|
||||
if (annotation) {
|
||||
// skip annotations that were marked as false positive
|
||||
if (pair.manualRedactionEntry?.type === 'false_positive' && pair.redactionLogEntry) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (annotation.isIgnored && !areDevFeaturesEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (annotation.isFalsePositive && !areDevFeaturesEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (annotation.isReadyForAnalysis && annotation.isApproved) {
|
||||
//
|
||||
} else {
|
||||
annotations.push(annotation);
|
||||
}
|
||||
// filter based on dev-mode
|
||||
annotations = annotations.filter((annotation) => {
|
||||
if (!areDevFeaturesEnabled) {
|
||||
return !annotation.isIgnored && !annotation.isFalsePositive;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
return annotations;
|
||||
}
|
||||
|
||||
private _createPairs(): AnnotationPair[] {
|
||||
const pairs: AnnotationPair[] = [];
|
||||
private _convertData(dictionaryData: { [p: string]: TypeValue }): RedactionLogEntryWrapper[] {
|
||||
let result: RedactionLogEntryWrapper[] = [];
|
||||
|
||||
this.redactionLog.redactionLogEntry.forEach((rdl) => {
|
||||
pairs.push({
|
||||
redactionLogEntry: rdl,
|
||||
// only not declined
|
||||
manualRedactionEntry: this.manualRedactions.entriesToAdd.find(
|
||||
(eta) => (eta.id === rdl.id || eta.reason === rdl.id) && this._validateEntry(eta)
|
||||
),
|
||||
// only not declined
|
||||
idRemoval: this.manualRedactions.idsToRemove.find((idr) => idr.id === rdl.id && this._dateValid(idr)),
|
||||
comments: this.manualRedactions.comments[rdl.id]
|
||||
});
|
||||
this.redactionLog.redactionLogEntry.forEach((redactionLogEntry) => {
|
||||
// copy the redactionLog Entry
|
||||
const wrapper: RedactionLogEntryWrapper = {};
|
||||
Object.assign(wrapper, redactionLogEntry);
|
||||
wrapper.comments = this.manualRedactions.comments[wrapper.id];
|
||||
result.push(wrapper);
|
||||
});
|
||||
|
||||
this.manualRedactions.entriesToAdd.forEach((eta) => {
|
||||
// only not declined
|
||||
if (this._dateValid(eta)) {
|
||||
const redactionLogEntry = this.redactionLog.redactionLogEntry.find((rdl) => rdl.id === eta.id);
|
||||
if (!redactionLogEntry) {
|
||||
pairs.push({
|
||||
redactionLogEntry: null,
|
||||
manualRedactionEntry: eta,
|
||||
// only not declined
|
||||
idRemoval: this.manualRedactions.idsToRemove.find((idr) => idr.id === eta.id),
|
||||
comments: this.manualRedactions.comments[eta.id]
|
||||
});
|
||||
this.manualRedactions.entriesToAdd.forEach((manual) => {
|
||||
if (this._hasAlreadyBeenProcessed(manual) && this._isAcceptedOrRejected(manual)) {
|
||||
let wrapper = result.find((r) => r.id === manual.id);
|
||||
if (wrapper) {
|
||||
wrapper.userId = manual.user;
|
||||
} else {
|
||||
wrapper = result.find((r) => r.id === manual.reason);
|
||||
// if we found it
|
||||
if (wrapper) {
|
||||
wrapper.userId = manual.user;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// normal case
|
||||
let wrapper = result.find((r) => r.id === manual.id);
|
||||
if (!wrapper) {
|
||||
// false positive and recommendation case
|
||||
// if we mark Annotation N as false positive -> it's reason is the original annotations Id
|
||||
// if we confirm a recommendation, it's reason is the original annotations Id
|
||||
wrapper = result.find((r) => r.id === manual.reason);
|
||||
// if we found it
|
||||
if (wrapper) {
|
||||
// it's a recommendation if it's not a false positive
|
||||
|
||||
wrapper.recommendation = manual.type !== 'false_positive';
|
||||
if (wrapper.recommendation) {
|
||||
wrapper.pendingRecommendationAnnotationId = manual.id;
|
||||
}
|
||||
wrapper.manual = true;
|
||||
wrapper.manualRedactionType = 'ADD';
|
||||
wrapper.status = manual.status;
|
||||
} else {
|
||||
const dictionary = dictionaryData[manual.type];
|
||||
|
||||
wrapper = {};
|
||||
|
||||
wrapper.id = manual.id;
|
||||
wrapper.dictionaryEntry = manual.addToDictionary;
|
||||
wrapper.legalBasis = manual.legalBasis;
|
||||
wrapper.positions = manual.positions;
|
||||
wrapper.reason = manual.reason;
|
||||
wrapper.status = manual.status;
|
||||
wrapper.type = manual.type;
|
||||
wrapper.userId = manual.user;
|
||||
wrapper.value = manual.value;
|
||||
wrapper.redacted = !dictionary.hint;
|
||||
wrapper.hint = dictionary.hint;
|
||||
wrapper.manualRedactionType = 'ADD';
|
||||
wrapper.manual = true;
|
||||
wrapper.comments = this.manualRedactions.comments[wrapper.id];
|
||||
|
||||
result.push(wrapper);
|
||||
}
|
||||
} else {
|
||||
wrapper.confirmed = true;
|
||||
}
|
||||
});
|
||||
|
||||
return pairs;
|
||||
this.manualRedactions.idsToRemove.forEach((idToRemove) => {
|
||||
if (this._hasAlreadyBeenProcessed(idToRemove) && this._isAcceptedOrRejected(idToRemove)) {
|
||||
const wrapper = result.find((r) => r.id === idToRemove.id);
|
||||
if (wrapper && wrapper.dictionaryEntry) {
|
||||
wrapper.manual = false;
|
||||
wrapper.manualRedactionType = null;
|
||||
wrapper.status = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const wrapper = result.find((r) => r.id === idToRemove.id);
|
||||
if (wrapper) {
|
||||
wrapper.manual = true;
|
||||
wrapper.dictionaryEntry = idToRemove.removeFromDictionary;
|
||||
wrapper.userId = idToRemove.user;
|
||||
wrapper.status = idToRemove.status;
|
||||
wrapper.manualRedactionType = 'REMOVE';
|
||||
}
|
||||
});
|
||||
|
||||
result.forEach((id) => {
|
||||
if (id.id === '57205cfd183653d4d159dc8d07f86a4c') {
|
||||
console.log(' ========= ', id);
|
||||
}
|
||||
});
|
||||
|
||||
// remove undone entriesToAdd and idsToRemove
|
||||
result = result.filter((redactionLogEntry) => {
|
||||
if (redactionLogEntry.manual) {
|
||||
if (redactionLogEntry.manualRedactionType === 'ADD') {
|
||||
const foundManualEntry = this.manualRedactions.entriesToAdd.find((me) => me.id === redactionLogEntry.id);
|
||||
if (!foundManualEntry) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (redactionLogEntry.manualRedactionType === 'REMOVE') {
|
||||
const foundManualEntry = this.manualRedactions.idsToRemove.find((me) => me.id === redactionLogEntry.id);
|
||||
if (!foundManualEntry) {
|
||||
redactionLogEntry.manual = false;
|
||||
redactionLogEntry.manualRedactionType = null;
|
||||
redactionLogEntry.status = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private _validateEntry(entry: ManualRedactionEntry): boolean {
|
||||
return this._dateValid(entry) || entry.type === 'manual';
|
||||
private _isAcceptedOrRejected(entry: ManualRedactionEntry | IdRemoval): boolean {
|
||||
return entry.status === 'APPROVED' || entry.status === 'DECLINED';
|
||||
}
|
||||
|
||||
private _dateValid(entry: ManualRedactionEntry | IdRemoval): boolean {
|
||||
return new Date(entry.processedDate).getTime() > new Date(this.fileStatus.lastProcessed).getTime() || !entry.processedDate;
|
||||
private _hasAlreadyBeenProcessed(entry: ManualRedactionEntry | IdRemoval): boolean {
|
||||
return !entry.processedDate ? false : new Date(entry.processedDate).getTime() < new Date(this.fileStatus.lastProcessed).getTime();
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,27 @@
|
||||
import { Rectangle, Comment } from '@redaction/red-ui-http';
|
||||
|
||||
export interface RedactionLogEntryWrapper {
|
||||
color?: Array<number>;
|
||||
dictionaryEntry?: boolean;
|
||||
hint?: boolean;
|
||||
id?: string;
|
||||
legalBasis?: string;
|
||||
manual?: boolean;
|
||||
manualRedactionType?: 'ADD' | 'REMOVE';
|
||||
matchedRule?: number;
|
||||
positions?: Array<Rectangle>;
|
||||
reason?: string;
|
||||
recommendation?: boolean;
|
||||
pendingRecommendationAnnotationId?: string;
|
||||
redacted?: boolean;
|
||||
section?: string;
|
||||
sectionNumber?: number;
|
||||
status?: 'REQUESTED' | 'APPROVED' | 'DECLINED';
|
||||
textAfter?: string;
|
||||
textBefore?: string;
|
||||
type?: string;
|
||||
value?: string;
|
||||
userId?: string;
|
||||
comments?: Comment[];
|
||||
confirmed?: boolean;
|
||||
}
|
||||
@ -463,7 +463,7 @@
|
||||
"ignore": "Ignore",
|
||||
"hint": "Hint",
|
||||
"redaction": "Redaction",
|
||||
"manual": "Manual Redaction",
|
||||
"manual-redaction": "Manual Redaction",
|
||||
"declined-suggestion": "Declined Suggestion"
|
||||
},
|
||||
"manual-annotation": {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user