RED-7619 wip migration to entity log
This commit is contained in:
parent
e3463907f6
commit
c94ef48844
@ -156,7 +156,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
||||
enabled: false,
|
||||
},
|
||||
REDACTION_LOG: {
|
||||
enabled: false,
|
||||
enabled: true,
|
||||
},
|
||||
VIEWED_PAGES: {
|
||||
enabled: false,
|
||||
|
||||
@ -9,13 +9,15 @@ import {
|
||||
DefaultColors,
|
||||
Dictionary,
|
||||
Earmark,
|
||||
EntryStates,
|
||||
EntryTypes,
|
||||
FalsePositiveSuperTypes,
|
||||
IComment,
|
||||
IEntityLogEntry,
|
||||
ILegalBasis,
|
||||
IManualChange,
|
||||
IPoint,
|
||||
IRectangle,
|
||||
IRedactionLogEntry,
|
||||
LogEntryEngine,
|
||||
LogEntryEngines,
|
||||
LogEntryStatuses,
|
||||
@ -296,7 +298,7 @@ export class AnnotationWrapper implements IListable {
|
||||
}
|
||||
|
||||
static fromData(
|
||||
redactionLogEntry: IRedactionLogEntry,
|
||||
logEntry: IEntityLogEntry,
|
||||
dictionaries: Dictionary[],
|
||||
defaultColors: DefaultColors,
|
||||
changeLogType: ChangeType,
|
||||
@ -306,56 +308,61 @@ export class AnnotationWrapper implements IListable {
|
||||
) {
|
||||
const annotationWrapper = new AnnotationWrapper();
|
||||
|
||||
annotationWrapper.id = redactionLogEntry.id;
|
||||
annotationWrapper.id = logEntry.id;
|
||||
annotationWrapper.isChangeLogEntry = !!changeLogType;
|
||||
annotationWrapper.changeLogType = changeLogType;
|
||||
annotationWrapper.legalBasisList = legalBasisList;
|
||||
annotationWrapper.redaction = redactionLogEntry.redacted;
|
||||
annotationWrapper.hint = redactionLogEntry.hint;
|
||||
annotationWrapper.typeValue = redactionLogEntry.type;
|
||||
annotationWrapper.value = redactionLogEntry.value;
|
||||
annotationWrapper.firstTopLeftPoint = redactionLogEntry.positions[0]?.topLeft;
|
||||
annotationWrapper.pageNumber = redactionLogEntry.positions[0]?.page;
|
||||
annotationWrapper.positions = redactionLogEntry.positions;
|
||||
annotationWrapper.textBefore = redactionLogEntry.textBefore;
|
||||
annotationWrapper.textAfter = redactionLogEntry.textAfter;
|
||||
annotationWrapper.dictionaryOperation = redactionLogEntry.dictionaryEntry;
|
||||
annotationWrapper.image = redactionLogEntry.image;
|
||||
annotationWrapper.imported = redactionLogEntry.imported;
|
||||
annotationWrapper.legalBasisValue = redactionLogEntry.legalBasis;
|
||||
annotationWrapper.comments = redactionLogEntry.comments || [];
|
||||
annotationWrapper.manual = redactionLogEntry.manualChanges?.length > 0;
|
||||
annotationWrapper.engines = redactionLogEntry.engines;
|
||||
annotationWrapper.section = redactionLogEntry.section;
|
||||
annotationWrapper.reference = redactionLogEntry.reference || [];
|
||||
annotationWrapper.rectangle = redactionLogEntry.rectangle;
|
||||
annotationWrapper.redaction = logEntry.entryType === EntryTypes.ENTITY;
|
||||
annotationWrapper.hint = logEntry.entryType === EntryTypes.HINT;
|
||||
annotationWrapper.typeValue = logEntry.type;
|
||||
annotationWrapper.value = logEntry.value;
|
||||
annotationWrapper.firstTopLeftPoint = { x: logEntry.positions[0].rectangle[0], y: logEntry.positions[0].rectangle[1] };
|
||||
annotationWrapper.pageNumber = logEntry.positions[0].pageNumber;
|
||||
annotationWrapper.positions = logEntry.positions.map(p => ({
|
||||
page: p.pageNumber,
|
||||
height: p.rectangle[3],
|
||||
width: p.rectangle[2],
|
||||
topLeft: { x: p.rectangle[0], y: p.rectangle[1] },
|
||||
}));
|
||||
annotationWrapper.textBefore = logEntry.textBefore;
|
||||
annotationWrapper.textAfter = logEntry.textAfter;
|
||||
annotationWrapper.dictionaryOperation = logEntry.dictionaryEntry;
|
||||
annotationWrapper.image = logEntry.entryType === EntryTypes.IMAGE;
|
||||
annotationWrapper.imported = logEntry.imported;
|
||||
annotationWrapper.legalBasisValue = logEntry.legalBasis;
|
||||
annotationWrapper.comments = []; //logEntry.comments || [];
|
||||
annotationWrapper.manual = logEntry.manualChanges?.length > 0;
|
||||
annotationWrapper.engines = logEntry.engines;
|
||||
annotationWrapper.section = logEntry.section;
|
||||
annotationWrapper.reference = logEntry.reference || [];
|
||||
annotationWrapper.rectangle = logEntry.entryType === EntryTypes.AREA;
|
||||
annotationWrapper.hintDictionary = hintDictionary;
|
||||
annotationWrapper.hasBeenResized = !!redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.hasBeenResized = !!logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.RESIZE && c.annotationStatus === LogEntryStatuses.APPROVED,
|
||||
);
|
||||
annotationWrapper.hasBeenRecategorized = !!redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.hasBeenRecategorized = !!logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.RECATEGORIZE && c.annotationStatus === LogEntryStatuses.APPROVED,
|
||||
);
|
||||
annotationWrapper.hasLegalBasisChanged = !!redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.hasLegalBasisChanged = !!logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE && c.annotationStatus === LogEntryStatuses.APPROVED,
|
||||
);
|
||||
annotationWrapper.hasBeenForcedHint = !!redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.hasBeenForcedHint = !!logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.FORCE_HINT && c.annotationStatus === LogEntryStatuses.APPROVED,
|
||||
);
|
||||
annotationWrapper.hasBeenForcedRedaction = !!redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.hasBeenForcedRedaction = !!logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.FORCE_REDACT && c.annotationStatus === LogEntryStatuses.APPROVED,
|
||||
);
|
||||
annotationWrapper.hasBeenRemovedByManualOverride = !!redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.hasBeenRemovedByManualOverride = !!logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.REMOVE_LOCALLY && c.annotationStatus === LogEntryStatuses.APPROVED,
|
||||
);
|
||||
annotationWrapper.legalBasisChangeValue = redactionLogEntry.manualChanges?.find(
|
||||
annotationWrapper.legalBasisChangeValue = logEntry.manualChanges?.find(
|
||||
c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE && c.annotationStatus === LogEntryStatuses.REQUESTED,
|
||||
)?.propertyChanges.legalBasis;
|
||||
|
||||
this.#createContent(annotationWrapper, redactionLogEntry, isDocumine);
|
||||
this.#setSuperType(annotationWrapper, redactionLogEntry);
|
||||
this.#handleRecommendations(annotationWrapper, redactionLogEntry);
|
||||
annotationWrapper.typeLabel = this.#getTypeLabel(redactionLogEntry, annotationWrapper);
|
||||
this.#createContent(annotationWrapper, logEntry, isDocumine);
|
||||
this.#setSuperType(annotationWrapper, logEntry);
|
||||
this.#handleRecommendations(annotationWrapper, logEntry);
|
||||
annotationWrapper.typeLabel = this.#getTypeLabel(logEntry, annotationWrapper);
|
||||
|
||||
const entity = dictionaries.find(d => d.type === annotationWrapper.typeValue);
|
||||
annotationWrapper.entity = entity?.virtual ? null : entity;
|
||||
@ -373,8 +380,8 @@ export class AnnotationWrapper implements IListable {
|
||||
return annotationWrapper;
|
||||
}
|
||||
|
||||
static #getTypeLabel(redactionLogEntry: IRedactionLogEntry, annotation: AnnotationWrapper): string {
|
||||
if (redactionLogEntry.reason?.toLowerCase() === 'false positive') {
|
||||
static #getTypeLabel(logEntry: IEntityLogEntry, annotation: AnnotationWrapper): string {
|
||||
if (logEntry.reason?.toLowerCase() === 'false positive') {
|
||||
return annotationTypesTranslations[SuggestionAddFalsePositive];
|
||||
}
|
||||
if (annotation.superType === SuperTypes.ManualRedaction && annotation.hintDictionary) {
|
||||
@ -383,38 +390,48 @@ export class AnnotationWrapper implements IListable {
|
||||
return annotationTypesTranslations[annotation.superType];
|
||||
}
|
||||
|
||||
static #handleRecommendations(annotationWrapper: AnnotationWrapper, redactionLogEntry: IRedactionLogEntry) {
|
||||
static #handleRecommendations(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry) {
|
||||
if (annotationWrapper.superType === SuperTypes.Recommendation) {
|
||||
annotationWrapper.recommendationType = redactionLogEntry.type;
|
||||
annotationWrapper.recommendationType = logEntry.type;
|
||||
}
|
||||
}
|
||||
|
||||
static #setSuperType(annotationWrapper: AnnotationWrapper, entry: IRedactionLogEntry) {
|
||||
if (entry.manualChanges?.length) {
|
||||
const lastRelevantManualChange = entry.manualChanges?.at(-1);
|
||||
const viableChanges = entry.changes.filter(c => c.analysisNumber > 1);
|
||||
static #setSuperType(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry) {
|
||||
if (logEntry.manualChanges?.length) {
|
||||
const lastRelevantManualChange = logEntry.manualChanges?.at(-1);
|
||||
const viableChanges = logEntry.changes.filter(c => c.analysisNumber > 1);
|
||||
const lastChange = viableChanges.sort(chronologicallyBy(x => x.dateTime)).at(-1);
|
||||
const lastChangeOccurredAfterLastManualChange =
|
||||
lastChange && timestampOf(lastChange.dateTime) > timestampOf(lastRelevantManualChange.processedDate);
|
||||
|
||||
if (lastChangeOccurredAfterLastManualChange && lastChange.type === ChangeTypes.ADDED && entry.redacted) {
|
||||
if (
|
||||
lastChangeOccurredAfterLastManualChange &&
|
||||
lastChange.type === ChangeTypes.ADDED &&
|
||||
logEntry.entryType === EntryTypes.ENTITY
|
||||
) {
|
||||
annotationWrapper.superType = SuperTypes.Redaction;
|
||||
return;
|
||||
}
|
||||
|
||||
annotationWrapper.pending = !lastRelevantManualChange.processed;
|
||||
|
||||
annotationWrapper.superType = this.#selectSuperType(entry, lastRelevantManualChange, annotationWrapper.hintDictionary);
|
||||
annotationWrapper.superType = this.#selectSuperType(logEntry, lastRelevantManualChange, annotationWrapper.hintDictionary);
|
||||
|
||||
if (lastRelevantManualChange.annotationStatus === LogEntryStatuses.REQUESTED) {
|
||||
annotationWrapper.recategorizationType = lastRelevantManualChange.propertyChanges.type;
|
||||
}
|
||||
} else {
|
||||
if (entry.recommendation) {
|
||||
if (logEntry.state === EntryStates.SKIPPED) {
|
||||
if (logEntry.entryType === EntryTypes.HINT) {
|
||||
annotationWrapper.superType = SuperTypes.Hint;
|
||||
} else {
|
||||
annotationWrapper.superType = SuperTypes.Skipped;
|
||||
}
|
||||
} else if (logEntry.entryType === EntryTypes.RECOMMENDATION) {
|
||||
annotationWrapper.superType = SuperTypes.Recommendation;
|
||||
} else if (entry.redacted) {
|
||||
} else if (logEntry.entryType === EntryTypes.ENTITY) {
|
||||
annotationWrapper.superType = SuperTypes.Redaction;
|
||||
} else if (entry.hint) {
|
||||
} else if (logEntry.entryType === EntryTypes.HINT) {
|
||||
annotationWrapper.superType = SuperTypes.Hint;
|
||||
} else {
|
||||
annotationWrapper.superType = SuperTypes.Skipped;
|
||||
@ -422,18 +439,18 @@ export class AnnotationWrapper implements IListable {
|
||||
}
|
||||
}
|
||||
|
||||
static #createContent(annotationWrapper: AnnotationWrapper, entry: IRedactionLogEntry, isDocumine: boolean) {
|
||||
static #createContent(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry, isDocumine: boolean) {
|
||||
let content = '';
|
||||
if (entry.matchedRule) {
|
||||
content += `Rule ${entry.matchedRule} matched${isDocumine ? ':' : ''} \n\n`;
|
||||
if (logEntry.matchedRule) {
|
||||
content += `Rule ${logEntry.matchedRule} matched${isDocumine ? ':' : ''} \n\n`;
|
||||
}
|
||||
|
||||
if (entry.reason) {
|
||||
if (isDocumine && entry.reason.slice(-1) === '.') {
|
||||
entry.reason = entry.reason.slice(0, -1);
|
||||
if (logEntry.reason) {
|
||||
if (isDocumine && logEntry.reason.slice(-1) === '.') {
|
||||
logEntry.reason = logEntry.reason.slice(0, -1);
|
||||
}
|
||||
|
||||
content += entry.reason + '\n\n';
|
||||
content += logEntry.reason + '\n\n';
|
||||
//remove leading and trailing commas and whitespaces
|
||||
content = content.replace(/(^[, ]*)|([, ]*$)/g, '');
|
||||
content = content.substring(0, 1).toUpperCase() + content.substring(1);
|
||||
@ -447,12 +464,12 @@ export class AnnotationWrapper implements IListable {
|
||||
content += 'Removed by manual override';
|
||||
}
|
||||
|
||||
if (entry.section) {
|
||||
if (logEntry.section) {
|
||||
let prefix = `In section${isDocumine ? '' : ':'} `;
|
||||
if (content.length) {
|
||||
prefix = ` ${prefix.toLowerCase()}`;
|
||||
}
|
||||
content += `${prefix} "${entry.section}"`;
|
||||
content += `${prefix} "${logEntry.section}"`;
|
||||
}
|
||||
|
||||
annotationWrapper.shortContent = this.#getShortContent(annotationWrapper) || content;
|
||||
@ -472,7 +489,7 @@ export class AnnotationWrapper implements IListable {
|
||||
return annotationWrapper.legalBasis;
|
||||
}
|
||||
|
||||
static #selectSuperType(redactionLogEntry: IRedactionLogEntry, lastManualChange: IManualChange, isHintDictionary: boolean): SuperType {
|
||||
static #selectSuperType(logEntry: IEntityLogEntry, lastManualChange: IManualChange, isHintDictionary: boolean): SuperType {
|
||||
switch (lastManualChange.manualRedactionType) {
|
||||
case ManualRedactionTypes.ADD_LOCALLY:
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
@ -503,7 +520,7 @@ export class AnnotationWrapper implements IListable {
|
||||
return SuperTypes.Hint;
|
||||
}
|
||||
|
||||
if (redactionLogEntry.redacted) {
|
||||
if (logEntry.entryType === EntryTypes.ENTITY) {
|
||||
return SuperTypes.Redaction;
|
||||
}
|
||||
|
||||
@ -514,7 +531,7 @@ export class AnnotationWrapper implements IListable {
|
||||
}
|
||||
break;
|
||||
case ManualRedactionTypes.REMOVE_FROM_DICTIONARY:
|
||||
if (redactionLogEntry.redacted) {
|
||||
if (logEntry.entryType === EntryTypes.ENTITY) {
|
||||
if (lastManualChange.processed) {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
@ -524,35 +541,34 @@ export class AnnotationWrapper implements IListable {
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
} else {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return SuperTypes.Redaction;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (lastManualChange.processed) {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
return redactionLogEntry.recommendation ? SuperTypes.Recommendation : SuperTypes.Skipped;
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
} else {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return SuperTypes.Redaction;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastManualChange.processed) {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
return logEntry.entryType === EntryTypes.RECOMMENDATION ? SuperTypes.Recommendation : SuperTypes.Skipped;
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
}
|
||||
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionRemoveDictionary;
|
||||
}
|
||||
break;
|
||||
case ManualRedactionTypes.FORCE_REDACT:
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
@ -578,13 +594,18 @@ export class AnnotationWrapper implements IListable {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED: {
|
||||
if (redactionLogEntry.recommendation) {
|
||||
if (logEntry.entryType === EntryTypes.RECOMMENDATION) {
|
||||
return SuperTypes.Recommendation;
|
||||
} else if (redactionLogEntry.redacted) {
|
||||
}
|
||||
|
||||
if (logEntry.entryType === EntryTypes.ENTITY) {
|
||||
return SuperTypes.Redaction;
|
||||
} else if (redactionLogEntry.hint) {
|
||||
}
|
||||
|
||||
if (logEntry.entryType === EntryTypes.HINT) {
|
||||
return SuperTypes.Hint;
|
||||
}
|
||||
|
||||
return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped;
|
||||
}
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
@ -595,7 +616,7 @@ export class AnnotationWrapper implements IListable {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED:
|
||||
return redactionLogEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction;
|
||||
return logEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction;
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionChangeLegalBasis;
|
||||
}
|
||||
@ -604,17 +625,18 @@ export class AnnotationWrapper implements IListable {
|
||||
switch (lastManualChange.annotationStatus) {
|
||||
case LogEntryStatuses.APPROVED:
|
||||
case LogEntryStatuses.DECLINED:
|
||||
if (redactionLogEntry.recommendation) {
|
||||
if (logEntry.entryType === EntryTypes.RECOMMENDATION) {
|
||||
return SuperTypes.Recommendation;
|
||||
} else if (redactionLogEntry.redacted) {
|
||||
return redactionLogEntry.type === SuperTypes.ManualRedaction
|
||||
? SuperTypes.ManualRedaction
|
||||
: SuperTypes.Redaction;
|
||||
} else if (redactionLogEntry.hint) {
|
||||
}
|
||||
|
||||
if (logEntry.entryType === EntryTypes.ENTITY) {
|
||||
return logEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction;
|
||||
}
|
||||
|
||||
if (logEntry.entryType === EntryTypes.HINT) {
|
||||
return SuperTypes.Hint;
|
||||
}
|
||||
return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped;
|
||||
|
||||
case LogEntryStatuses.REQUESTED:
|
||||
return SuperTypes.SuggestionResize;
|
||||
}
|
||||
|
||||
@ -3,17 +3,7 @@ import { toObservable } from '@angular/core/rxjs-interop';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { EntitiesService, getConfig, Toaster } from '@iqser/common-ui';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import {
|
||||
ChangeType,
|
||||
ChangeTypes,
|
||||
File,
|
||||
IRedactionLog,
|
||||
IRedactionLogEntry,
|
||||
LogEntryStatuses,
|
||||
ViewedPage,
|
||||
ViewMode,
|
||||
ViewModes,
|
||||
} from '@red/domain';
|
||||
import { ChangeType, ChangeTypes, File, IEntityLog, IEntityLogEntry, LogEntryStatuses, ViewedPage, ViewMode, ViewModes } from '@red/domain';
|
||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { EarmarksService } from '@services/files/earmarks.service';
|
||||
@ -132,7 +122,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
|
||||
async loadRedactionLog() {
|
||||
this._logger.info('[REDACTION_LOG] Loading redaction log...');
|
||||
const redactionLog = await this._redactionLogService.getRedactionLog(this._state.dossierId, this._state.fileId);
|
||||
const redactionLog = await this._redactionLogService.getEntityLog(this._state.dossierId, this._state.fileId);
|
||||
|
||||
this._logger.info('[REDACTION_LOG] Redaction log loaded', redactionLog);
|
||||
let annotations = await this.#convertData(redactionLog);
|
||||
@ -177,8 +167,8 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
});
|
||||
}
|
||||
|
||||
async #convertData(redactionLog: IRedactionLog) {
|
||||
if (!redactionLog.redactionLogEntry) {
|
||||
async #convertData(entityLog: IEntityLog) {
|
||||
if (!entityLog.entityLogEntry) {
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -189,8 +179,8 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
const defaultColors = this._defaultColorsService.find(this._state.dossierTemplateId);
|
||||
let checkDictionary = true;
|
||||
|
||||
for (const entry of redactionLog.redactionLogEntry) {
|
||||
const pageNumber = entry.positions[0]?.page;
|
||||
for (const entry of entityLog.entityLogEntry) {
|
||||
const pageNumber = entry.positions[0].pageNumber;
|
||||
const manual = entry.manualChanges?.length > 0;
|
||||
if (!manual && file.excludedPages.includes(pageNumber)) {
|
||||
continue;
|
||||
@ -219,17 +209,17 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
dictionaries,
|
||||
defaultColors,
|
||||
changeLogValues.changeLogType,
|
||||
redactionLog.legalBasis ?? [],
|
||||
entityLog.legalBasis ?? [],
|
||||
!!dictionary?.hint,
|
||||
this.#isDocumine,
|
||||
);
|
||||
|
||||
if (entry.sourceId) {
|
||||
if (!sourceIds[entry.sourceId]) {
|
||||
sourceIds[entry.sourceId] = [];
|
||||
}
|
||||
sourceIds[entry.sourceId].push(annotation);
|
||||
}
|
||||
// if (entry.sourceId) {
|
||||
// if (!sourceIds[entry.sourceId]) {
|
||||
// sourceIds[entry.sourceId] = [];
|
||||
// }
|
||||
// sourceIds[entry.sourceId].push(annotation);
|
||||
// }
|
||||
|
||||
annotations.push(annotation);
|
||||
}
|
||||
@ -239,13 +229,13 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
}
|
||||
|
||||
#getChangeLogValues(
|
||||
redactionLogEntry: IRedactionLogEntry,
|
||||
entityLogEntry: IEntityLogEntry,
|
||||
file: File,
|
||||
): {
|
||||
hidden: boolean;
|
||||
changeLogType?: ChangeType;
|
||||
} {
|
||||
const hasManualChanges = redactionLogEntry.manualChanges?.length > 0;
|
||||
const hasManualChanges = entityLogEntry.manualChanges?.length > 0;
|
||||
if (file.numberOfAnalyses <= 1 && !file.hasUpdates && !hasManualChanges) {
|
||||
return {
|
||||
changeLogType: undefined,
|
||||
@ -253,10 +243,10 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
};
|
||||
}
|
||||
|
||||
const viableChanges = redactionLogEntry.changes?.filter(c => c.analysisNumber > 1);
|
||||
const viableChanges = entityLogEntry.changes?.filter(c => c.analysisNumber > 1);
|
||||
const lastChange = viableChanges?.sort(chronologicallyBy(x => x.dateTime)).at(-1);
|
||||
|
||||
const page = redactionLogEntry.positions?.[0].page;
|
||||
const page = entityLogEntry.positions?.[0].pageNumber;
|
||||
const viewedPage = this.#originalViewedPages.find(p => p.page === page);
|
||||
|
||||
if (!viewedPage) {
|
||||
@ -279,7 +269,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
||||
}
|
||||
|
||||
const visibleStatuses: string[] = [LogEntryStatuses.APPROVED, LogEntryStatuses.REQUESTED];
|
||||
const viableManualChanges = redactionLogEntry.manualChanges.filter(change => visibleStatuses.includes(change.annotationStatus));
|
||||
const viableManualChanges = entityLogEntry.manualChanges.filter(change => visibleStatuses.includes(change.annotationStatus));
|
||||
viableManualChanges.sort(chronologicallyBy(x => x.processedDate));
|
||||
const lastManualChange = viableManualChanges.at(-1);
|
||||
const isSuggestion = lastManualChange?.annotationStatus === LogEntryStatuses.REQUESTED;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { GenericService, QueryParam } from '@iqser/common-ui';
|
||||
import { IRedactionLog, ISectionGrid } from '@red/domain';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { GenericService } from '@iqser/common-ui';
|
||||
import { IEntityLog, ISectionGrid } from '@red/domain';
|
||||
import { firstValueFrom, of } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@ -10,16 +10,11 @@ import { firstValueFrom, of } from 'rxjs';
|
||||
export class RedactionLogService extends GenericService<unknown> {
|
||||
protected readonly _defaultModelPath = '';
|
||||
|
||||
async getRedactionLog(dossierId: string, fileId: string, withManualRedactions?: boolean) {
|
||||
const queryParams: QueryParam[] = [];
|
||||
if (withManualRedactions) {
|
||||
queryParams.push({ key: 'withManualRedactions', value: withManualRedactions });
|
||||
}
|
||||
|
||||
const redactionLog$ = this._getOne<IRedactionLog>([dossierId, fileId], 'redactionLog', queryParams);
|
||||
const redactionLog = await firstValueFrom(redactionLog$.pipe(catchError(() => of({} as IRedactionLog))));
|
||||
redactionLog.redactionLogEntry.sort((a, b) => a.positions[0].page - b.positions[0].page);
|
||||
return redactionLog;
|
||||
async getEntityLog(dossierId: string, fileId: string) {
|
||||
const entityLog$ = this._getOne<IEntityLog>([dossierId, fileId], 'entityLog');
|
||||
const entityLog = await firstValueFrom(entityLog$.pipe(catchError(() => of({} as IEntityLog))));
|
||||
entityLog.entityLogEntry.sort((a, b) => a.positions[0].pageNumber - b.positions[0].pageNumber);
|
||||
return entityLog;
|
||||
}
|
||||
|
||||
getSectionGrid(dossierId: string, fileId: string) {
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit a6383c1dbc840115897a31567c3f5633ba78b43a
|
||||
Subproject commit 85fba4a1dd57ecbb133d938552d75fceffa1099c
|
||||
@ -1,5 +1,5 @@
|
||||
export interface ILegalBasis {
|
||||
name: string;
|
||||
description?: string;
|
||||
reason?: string;
|
||||
readonly name: string;
|
||||
readonly description?: string;
|
||||
readonly reason?: string;
|
||||
}
|
||||
|
||||
40
libs/red-domain/src/lib/redaction-log/entity-log-entry.ts
Normal file
40
libs/red-domain/src/lib/redaction-log/entity-log-entry.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { ITrackable } from '@iqser/common-ui';
|
||||
import { IChange } from './change';
|
||||
import { EntryState } from './entity-states';
|
||||
import { EntryType } from './entry-types';
|
||||
import { IManualChange } from './manual-change';
|
||||
import { LogEntryEngine } from './types';
|
||||
|
||||
export interface IEntityLogEntryPosition {
|
||||
readonly pageNumber: number;
|
||||
readonly rectangle: readonly [number, number, number, number];
|
||||
}
|
||||
|
||||
export interface IEntityLogEntry extends ITrackable {
|
||||
type: string;
|
||||
entryType: EntryType;
|
||||
state: EntryState;
|
||||
value: string;
|
||||
reason: string;
|
||||
matchedRule: string;
|
||||
legalBasis: string;
|
||||
imported: boolean;
|
||||
containingNodeId: number[];
|
||||
closestHeadline: string;
|
||||
section: string;
|
||||
color: number[];
|
||||
positions: IEntityLogEntryPosition[];
|
||||
textAfter?: string;
|
||||
textBefore?: string;
|
||||
startOffset?: number;
|
||||
endOffset?: number;
|
||||
imageHasTransparency: boolean;
|
||||
dictionaryEntry: boolean;
|
||||
dossierDictionaryEntry: boolean;
|
||||
excluded: boolean;
|
||||
changes: IChange[];
|
||||
manualChanges: IManualChange[];
|
||||
engines: LogEntryEngine[];
|
||||
reference: string[];
|
||||
importedRedactionIntersections: string[];
|
||||
}
|
||||
13
libs/red-domain/src/lib/redaction-log/entity-log.ts
Normal file
13
libs/red-domain/src/lib/redaction-log/entity-log.ts
Normal file
@ -0,0 +1,13 @@
|
||||
import { ILegalBasis } from '../legal-basis';
|
||||
import { IEntityLogEntry } from './entity-log-entry';
|
||||
|
||||
export interface IEntityLog {
|
||||
analysisVersion: number;
|
||||
analysisNumber: number;
|
||||
entityLogEntry: IEntityLogEntry[];
|
||||
legalBasis: ILegalBasis[];
|
||||
dictionaryVersion: number;
|
||||
dossierDictionaryVersion: number;
|
||||
rulesVersion: number;
|
||||
legalBasisVersion: number;
|
||||
}
|
||||
8
libs/red-domain/src/lib/redaction-log/entity-states.ts
Normal file
8
libs/red-domain/src/lib/redaction-log/entity-states.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export const EntryStates = {
|
||||
APPLIED: 'APPLIED',
|
||||
SKIPPED: 'SKIPPED',
|
||||
IGNORED: 'IGNORED',
|
||||
REMOVED: 'REMOVED',
|
||||
} as const;
|
||||
|
||||
export type EntryState = (typeof EntryStates)[keyof typeof EntryStates];
|
||||
11
libs/red-domain/src/lib/redaction-log/entry-types.ts
Normal file
11
libs/red-domain/src/lib/redaction-log/entry-types.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export const EntryTypes = {
|
||||
ENTITY: 'ENTITY',
|
||||
HINT: 'HINT',
|
||||
FALSE_POSITIVE: 'FALSE_POSITIVE',
|
||||
RECOMMENDATION: 'RECOMMENDATION',
|
||||
FALSE_RECOMMENDATION: 'FALSE_RECOMMENDATION',
|
||||
AREA: 'AREA',
|
||||
IMAGE: 'IMAGE',
|
||||
} as const;
|
||||
|
||||
export type EntryType = (typeof EntryTypes)[keyof typeof EntryTypes];
|
||||
@ -12,3 +12,7 @@ export * from './recategorization.request';
|
||||
export * from './resize.request';
|
||||
export * from './manual-change';
|
||||
export * from './dictionary-entry-types';
|
||||
export * from './entity-log';
|
||||
export * from './entity-log-entry';
|
||||
export * from './entity-states';
|
||||
export * from './entry-types';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user