RED-7619 wip migration to entity log

This commit is contained in:
Dan Percic 2023-10-23 17:58:18 +03:00
parent e3463907f6
commit c94ef48844
11 changed files with 224 additions and 141 deletions

View File

@ -156,7 +156,7 @@ export const appModuleFactory = (config: AppConfig) => {
enabled: false,
},
REDACTION_LOG: {
enabled: false,
enabled: true,
},
VIEWED_PAGES: {
enabled: false,

View File

@ -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;
}

View File

@ -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;

View File

@ -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

View File

@ -1,5 +1,5 @@
export interface ILegalBasis {
name: string;
description?: string;
reason?: string;
readonly name: string;
readonly description?: string;
readonly reason?: string;
}

View 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[];
}

View 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;
}

View 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];

View 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];

View File

@ -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';