From c94ef488446dfddfe16ad48461fd60edd51c8539 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Mon, 23 Oct 2023 17:58:18 +0300 Subject: [PATCH 01/10] RED-7619 wip migration to entity log --- apps/red-ui/src/app/app.module.ts | 2 +- .../src/app/models/file/annotation.wrapper.ts | 212 ++++++++++-------- .../services/file-data.service.ts | 46 ++-- .../services/files/redaction-log.service.ts | 21 +- libs/common-ui | 2 +- .../src/lib/legal-basis/legal-basis.ts | 6 +- .../src/lib/redaction-log/entity-log-entry.ts | 40 ++++ .../src/lib/redaction-log/entity-log.ts | 13 ++ .../src/lib/redaction-log/entity-states.ts | 8 + .../src/lib/redaction-log/entry-types.ts | 11 + .../red-domain/src/lib/redaction-log/index.ts | 4 + 11 files changed, 224 insertions(+), 141 deletions(-) create mode 100644 libs/red-domain/src/lib/redaction-log/entity-log-entry.ts create mode 100644 libs/red-domain/src/lib/redaction-log/entity-log.ts create mode 100644 libs/red-domain/src/lib/redaction-log/entity-states.ts create mode 100644 libs/red-domain/src/lib/redaction-log/entry-types.ts diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index d6d506950..66a4c04cd 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -156,7 +156,7 @@ export const appModuleFactory = (config: AppConfig) => { enabled: false, }, REDACTION_LOG: { - enabled: false, + enabled: true, }, VIEWED_PAGES: { enabled: false, diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index 91c88b5bc..f27200460 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -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; } diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index f69410fe2..9ab30726b 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -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 0; if (!manual && file.excludedPages.includes(pageNumber)) { continue; @@ -219,17 +209,17 @@ export class FileDataService extends EntitiesService 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 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 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; diff --git a/apps/red-ui/src/app/services/files/redaction-log.service.ts b/apps/red-ui/src/app/services/files/redaction-log.service.ts index 8e9133564..f8a4cf55f 100644 --- a/apps/red-ui/src/app/services/files/redaction-log.service.ts +++ b/apps/red-ui/src/app/services/files/redaction-log.service.ts @@ -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 { 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([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([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) { diff --git a/libs/common-ui b/libs/common-ui index a6383c1db..85fba4a1d 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit a6383c1dbc840115897a31567c3f5633ba78b43a +Subproject commit 85fba4a1dd57ecbb133d938552d75fceffa1099c diff --git a/libs/red-domain/src/lib/legal-basis/legal-basis.ts b/libs/red-domain/src/lib/legal-basis/legal-basis.ts index 3ec087e3a..2e750f84d 100644 --- a/libs/red-domain/src/lib/legal-basis/legal-basis.ts +++ b/libs/red-domain/src/lib/legal-basis/legal-basis.ts @@ -1,5 +1,5 @@ export interface ILegalBasis { - name: string; - description?: string; - reason?: string; + readonly name: string; + readonly description?: string; + readonly reason?: string; } diff --git a/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts b/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts new file mode 100644 index 000000000..9b47d1645 --- /dev/null +++ b/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts @@ -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[]; +} diff --git a/libs/red-domain/src/lib/redaction-log/entity-log.ts b/libs/red-domain/src/lib/redaction-log/entity-log.ts new file mode 100644 index 000000000..e53d2b900 --- /dev/null +++ b/libs/red-domain/src/lib/redaction-log/entity-log.ts @@ -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; +} diff --git a/libs/red-domain/src/lib/redaction-log/entity-states.ts b/libs/red-domain/src/lib/redaction-log/entity-states.ts new file mode 100644 index 000000000..2507f1bdb --- /dev/null +++ b/libs/red-domain/src/lib/redaction-log/entity-states.ts @@ -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]; diff --git a/libs/red-domain/src/lib/redaction-log/entry-types.ts b/libs/red-domain/src/lib/redaction-log/entry-types.ts new file mode 100644 index 000000000..d14b051b4 --- /dev/null +++ b/libs/red-domain/src/lib/redaction-log/entry-types.ts @@ -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]; diff --git a/libs/red-domain/src/lib/redaction-log/index.ts b/libs/red-domain/src/lib/redaction-log/index.ts index 3ae3bf570..5ebab18b3 100644 --- a/libs/red-domain/src/lib/redaction-log/index.ts +++ b/libs/red-domain/src/lib/redaction-log/index.ts @@ -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'; From 94ba0e5470a7a8fe1d9c26b667d839ad372144ef Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Wed, 25 Oct 2023 14:53:19 +0300 Subject: [PATCH 02/10] RED-7619 little cleanup --- .../src/app/models/file/annotation.wrapper.ts | 8 ------- .../annotation-card.component.html | 2 +- .../accept-recommendation-dialog.component.ts | 24 ++++++++----------- .../services/manual-redaction.service.ts | 24 ------------------- 4 files changed, 11 insertions(+), 47 deletions(-) diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index f27200460..1bd215125 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -215,18 +215,10 @@ export class AnnotationWrapper implements IListable { return !!SuggestionAddSuperTypes[this.superType]; } - get isSuggestionAddDictionary() { - return this.superType === SuperTypes.SuggestionAddDictionary; - } - get isSuggestionRemove() { return !!SuggestionRemoveSuperTypes[this.superType]; } - get isSuggestionRemoveDictionary() { - return this.superType === SuperTypes.SuggestionRemoveDictionary; - } - get isSuggestionLegalBasisChange() { return this.superType === SuperTypes.SuggestionChangeLegalBasis; } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index 06eaabe85..b822419ff 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -1,7 +1,7 @@
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts index 74f3c2cac..c5b7a91a6 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts @@ -1,12 +1,12 @@ -import { Component, Inject, OnInit } from '@angular/core'; -import { UntypedFormGroup, Validators } from '@angular/forms'; +import { Component, inject, Inject, OnInit } from '@angular/core'; +import { Validators } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { PermissionsService } from '@services/permissions.service'; -import { Dictionary, Dossier } from '@red/domain'; -import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { BaseDialogComponent } from '@iqser/common-ui'; -import { DictionaryService } from '@services/entity-services/dictionary.service'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; +import { Dictionary } from '@red/domain'; +import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; +import { DictionaryService } from '@services/entity-services/dictionary.service'; +import { PermissionsService } from '@services/permissions.service'; import { acceptRecommendationTranslations } from '@translations/accept-recommendation-translations'; export interface AcceptRecommendationData { @@ -23,22 +23,18 @@ export interface AcceptRecommendationReturnType { templateUrl: './accept-recommendation-dialog.component.html', }) export class AcceptRecommendationDialogComponent extends BaseDialogComponent implements OnInit { + readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId); readonly dialogHeader: string; - possibleDictionaries: Dictionary[] = []; - private readonly _dossier: Dossier; - constructor( permissionsService: PermissionsService, - activeDossiersService: ActiveDossiersService, private readonly _dictionaryService: DictionaryService, protected readonly _dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) readonly data: AcceptRecommendationData, ) { super(_dialogRef); - this._dossier = activeDossiersService.find(this.data.dossierId); - const isDocumentAdmin = permissionsService.isApprover(this._dossier); + const isDocumentAdmin = permissionsService.isApprover(this.#dossier); this.dialogHeader = isDocumentAdmin ? acceptRecommendationTranslations.addToDictionary : acceptRecommendationTranslations.requestAddToDictionary; @@ -55,7 +51,7 @@ export class AcceptRecommendationDialogComponent extends BaseDialogComponent imp } async ngOnInit() { - this.possibleDictionaries = await this._dictionaryService.getDictionariesOptions(this._dossier.dossierTemplateId, this._dossier.id); + this.possibleDictionaries = await this._dictionaryService.getDictionariesOptions(this.#dossier.dossierTemplateId, this.#dossier.id); this.form.patchValue({ dictionary: this.possibleDictionaries.find(dict => dict.type === this.data.annotations[0].recommendationType)?.type, }); @@ -78,7 +74,7 @@ export class AcceptRecommendationDialogComponent extends BaseDialogComponent imp ); } - private _getForm(): UntypedFormGroup { + private _getForm() { return this._formBuilder.group({ dictionary: [Validators.required], comment: [null], diff --git a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts index 2329b4354..6a6748e88 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts @@ -7,7 +7,6 @@ import { type AnnotationWrapper } from '@models/file/annotation.wrapper'; import { type ManualRedactionEntryType } from '@models/file/manual-redaction-entry.wrapper'; import type { DictionaryActions, - Dossier, IAddRedactionRequest, ILegalBasisChangeRequest, IManualAddResponse, @@ -16,8 +15,6 @@ import type { IResizeRequest, ManualRedactionActions, } from '@red/domain'; -import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; -import { PermissionsService } from '@services/permissions.service'; import { dictionaryActionsTranslations, manualRedactionActionsTranslations } from '@translations/annotation-actions-translations'; import { Roles } from '@users/roles'; import { NGXLogger } from 'ngx-logger'; @@ -41,15 +38,12 @@ function getMessage(action: ManualRedactionActions, isDictionary = false, error @Injectable() export class ManualRedactionService extends GenericService { protected readonly _defaultModelPath = 'manualRedaction'; - readonly #bulkRequest = `${this._defaultModelPath}/bulk/request`; readonly #bulkRedaction = `${this._defaultModelPath}/bulk/redaction`; constructor( private readonly _toaster: Toaster, private readonly _logger: NGXLogger, - private readonly _permissionsService: PermissionsService, private readonly _iqaerPermissionsService: IqserPermissionsService, - private readonly _activeDossiersService: ActiveDossiersService, ) { super(); } @@ -112,14 +106,6 @@ export class ManualRedactionService extends GenericService { return this.undo(annotationIds, dossierId, fileId).pipe(this.#showToast('undo', modifyDictionary)); } - declineOrRemove(annotationIds: List, dossierId: string, fileId: string, modifyDictionary = false) { - if (this._permissionsService.isApprover(this.#dossier(dossierId))) { - return this.decline(annotationIds, dossierId, fileId).pipe(this.#showToast('decline', modifyDictionary)); - } - - return this.undo(annotationIds, dossierId, fileId).pipe(this.#showToast('undo', modifyDictionary)); - } - removeRedaction(body: List, dossierId: string, fileId: string, removeFromDictionary = false, isHint = false) { return this.remove(body, dossierId, fileId).pipe(this.#showToast(!isHint ? 'remove' : 'remove-hint', removeFromDictionary)); } @@ -151,12 +137,6 @@ export class ManualRedactionService extends GenericService { ); } - requestLegalBasisChange(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRequest}/legalBasis/${dossierId}/${fileId}`).pipe( - this.#log('Request legal basis change', body), - ); - } - approve(annotationIds: List, dossierId: string, fileId: string) { return this._post(annotationIds, `${this._defaultModelPath}/bulk/approve/${dossierId}/${fileId}`).pipe( this.#log('Approve', annotationIds), @@ -222,8 +202,4 @@ export class ManualRedactionService extends GenericService { }, }); } - - #dossier(dossierId: string): Dossier { - return this._activeDossiersService.find(dossierId); - } } From 871f0feac11ac3c44ea7022571bd995bebf428ce Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Wed, 25 Oct 2023 20:36:06 +0300 Subject: [PATCH 03/10] RED-7619 remove useless suggestions. god this fel good --- .../file/annotation-permissions.utils.ts | 12 +- .../app/models/file/annotation.permissions.ts | 5 +- .../src/app/models/file/annotation.wrapper.ts | 112 +-------- .../file-workload.component.html | 8 +- .../file-workload/file-workload.component.ts | 37 ++- .../dossier-overview/config.service.ts | 39 ++- .../dossier-workload-column.component.html | 7 - .../dossier-workload-column.component.ts | 8 +- .../dossiers-listing/config.service.ts | 30 +-- .../annotation-actions.component.html | 10 +- .../annotation-actions.component.ts | 22 +- .../annotation-card.component.html | 2 +- .../view-switch/view-switch.component.ts | 52 +--- .../services/file-data.service.ts | 22 +- .../services/manual-redaction.service.ts | 17 +- .../services/annotation-draw.service.ts | 8 +- .../services/readable-redactions.service.ts | 17 +- .../type-filter/type-filter.component.ts | 21 +- .../annotation-actions-translations.ts | 54 +---- .../annotation-types-translations.ts | 10 - .../app/translations/workload-translations.ts | 1 - .../src/app/users/user-preference.service.ts | 1 - apps/red-ui/src/app/utils/filter-utils.ts | 5 +- .../utils/sorters/redaction-filter-sorter.ts | 1 - .../app/utils/sorters/super-type-sorter.ts | 10 - apps/red-ui/src/assets/config/config.json | 4 +- apps/red-ui/src/assets/i18n/redact/de.json | 229 ++++++------------ apps/red-ui/src/assets/i18n/redact/en.json | 85 +------ apps/red-ui/src/assets/i18n/scm/de.json | 85 +------ apps/red-ui/src/assets/i18n/scm/en.json | 87 +------ libs/red-domain/src/lib/annotations/types.ts | 12 +- .../src/lib/colors/annotation-color-config.ts | 16 +- .../lib/dossier-stats/dossier-stats.model.ts | 4 +- .../src/lib/dossier-stats/dossier-stats.ts | 1 - libs/red-domain/src/lib/files/file.model.ts | 19 +- libs/red-domain/src/lib/files/file.ts | 3 +- libs/red-domain/src/lib/files/super-types.ts | 34 --- .../red-domain/src/lib/redaction-log/types.ts | 1 - 38 files changed, 197 insertions(+), 894 deletions(-) diff --git a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts index 2729dcad0..4a70ac52c 100644 --- a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts +++ b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts @@ -2,8 +2,7 @@ import { AnnotationPermissions } from '@models/file/annotation.permissions'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { Dictionary } from '@red/domain'; -export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) => - !isApprover && (annotation.isSuggestion || annotation.pending); +export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) => !isApprover && annotation.pending; export const canForceHint = (annotation: AnnotationWrapper, canAddRedaction: boolean) => canAddRedaction && annotation.isIgnoredHint && !annotation.pending; @@ -33,15 +32,10 @@ export const canChangeLegalBasis = (annotation: AnnotationWrapper, canAddRedacti canAddRedaction && annotation.isRedacted && !annotation.pending; export const canRecategorizeAnnotation = (annotation: AnnotationWrapper, canRecategorize: boolean) => - canRecategorize && - ((annotation.isImage && !annotation.isSuggestion) || annotation.isSuggestionRecategorizeImage || annotation.hintDictionary) && - !annotation.pending; + canRecategorize && (annotation.isImage || annotation.hintDictionary) && !annotation.pending; export const canResizeAnnotation = (annotation: AnnotationWrapper, canAddRedaction: boolean) => canAddRedaction && !annotation.isSkipped && !annotation.pending && - (((annotation.isRedacted || annotation.isImage) && !annotation.isSuggestion) || - annotation.isSuggestionResize || - annotation.isDictBasedHint || - annotation.isRecommendation); + (annotation.isRedacted || annotation.isImage || annotation.isDictBasedHint || annotation.isRecommendation); diff --git a/apps/red-ui/src/app/models/file/annotation.permissions.ts b/apps/red-ui/src/app/models/file/annotation.permissions.ts index 87ffb175e..cddebeb9a 100644 --- a/apps/red-ui/src/app/models/file/annotation.permissions.ts +++ b/apps/red-ui/src/app/models/file/annotation.permissions.ts @@ -2,6 +2,7 @@ import { IqserPermissionsService } from '@iqser/common-ui'; import { Dictionary } from '@red/domain'; import { Roles } from '@users/roles'; import { isArray } from 'lodash-es'; +import { IMAGE_CATEGORIES } from '../../modules/file-preview/utils/constants'; import { canAcceptRecommendation, canChangeLegalBasis, @@ -16,7 +17,6 @@ import { canUndo, } from './annotation-permissions.utils'; import { AnnotationWrapper } from './annotation.wrapper'; -import { IMAGE_CATEGORIES } from '../../modules/file-preview/utils/constants'; export class AnnotationPermissions { canUndo = true; @@ -63,8 +63,7 @@ export class AnnotationPermissions { permissions.canResizeAnnotation = canResizeAnnotation(annotation, canAddRedaction); permissions.canEditAnnotations = (annotation.isSkipped || annotation.isRedacted) && !annotation.isImage; - permissions.canEditHints = - annotation.isIgnoredHint || annotation.isDictBasedHint || annotation.isHint || annotation.isSuggestionForceHint; + permissions.canEditHints = annotation.isIgnoredHint || annotation.isDictBasedHint || annotation.isHint; permissions.canEditImages = [...IMAGE_CATEGORIES, 'ocr'].includes(annotation.type); summedPermissions._merge(permissions); diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index 1bd215125..da0afdd50 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -1,12 +1,10 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { IListable } from '@iqser/common-ui'; import { - annotationDefaultColorConfig, annotationEntityColorConfig, AnnotationIconType, ChangeType, ChangeTypes, - DefaultColors, Dictionary, Earmark, EntryStates, @@ -23,9 +21,6 @@ import { LogEntryStatuses, LowLevelFilterTypes, ManualRedactionTypes, - SuggestionAddSuperTypes, - SuggestionRemoveSuperTypes, - SuggestionsSuperTypes, SuperType, SuperTypes, } from '@red/domain'; @@ -55,7 +50,6 @@ export class AnnotationWrapper implements IListable { positions: IRectangle[]; recommendationType: string; legalBasisValue: string; - legalBasisChangeValue?: string; rectangle?: boolean; section?: string; reference: string[]; @@ -107,10 +101,6 @@ export class AnnotationWrapper implements IListable { ); } - get isSuperTypeBasedColor() { - return this.isSuggestion || this.isDeclinedSuggestion; - } - get isSkipped() { return this.superType === SuperTypes.Skipped; } @@ -147,18 +137,6 @@ export class AnnotationWrapper implements IListable { return this.type?.toLowerCase() === 'false_positive' && !!FalsePositiveSuperTypes[this.superType]; } - get isSuggestionAddToFalsePositive() { - return this.typeLabel === annotationTypesTranslations[SuggestionAddFalsePositive]; - } - - get isDeclinedSuggestion() { - return this.superType === SuperTypes.DeclinedSuggestion; - } - - get isApproved() { - return this.status === 'APPROVED'; - } - get isHint() { return this.superType === SuperTypes.Hint; } @@ -176,10 +154,6 @@ export class AnnotationWrapper implements IListable { return 'circle'; } - if (this.isSuggestion || this.isDeclinedSuggestion) { - return 'rhombus'; - } - return 'square'; } @@ -195,34 +169,6 @@ export class AnnotationWrapper implements IListable { return this.superType === SuperTypes.Redaction || this.superType === SuperTypes.ManualRedaction; } - get isSuggestion() { - return !!SuggestionsSuperTypes[this.superType]; - } - - get isSuggestionResize() { - return this.superType === SuperTypes.SuggestionResize; - } - - get isSuggestionRecategorizeImage() { - return this.superType === SuperTypes.SuggestionRecategorizeImage; - } - - get isSuggestionForceHint() { - return this.superType === SuperTypes.SuggestionForceHint; - } - - get isSuggestionAdd() { - return !!SuggestionAddSuperTypes[this.superType]; - } - - get isSuggestionRemove() { - return !!SuggestionRemoveSuperTypes[this.superType]; - } - - get isSuggestionLegalBasisChange() { - return this.superType === SuperTypes.SuggestionChangeLegalBasis; - } - get isModifyDictionary() { return this.dictionaryOperation; } @@ -251,7 +197,7 @@ export class AnnotationWrapper implements IListable { } get legalBasis() { - return this.legalBasisChangeValue || this.legalBasisValue; + return this.legalBasisValue; } get width(): number { @@ -263,14 +209,7 @@ export class AnnotationWrapper implements IListable { } get previewAnnotation() { - return ( - this.isRedacted || - this.isSuggestionAdd || - this.isSuggestionRemove || - this.isSuggestionResize || - this.isSuggestionLegalBasisChange || - this.isSuggestionRecategorizeImage - ); + return this.isRedacted; } static fromEarmark(earmark: Earmark) { @@ -292,7 +231,6 @@ export class AnnotationWrapper implements IListable { static fromData( logEntry: IEntityLogEntry, dictionaries: Dictionary[], - defaultColors: DefaultColors, changeLogType: ChangeType, legalBasisList: ILegalBasis[], hintDictionary: boolean, @@ -347,9 +285,6 @@ export class AnnotationWrapper implements IListable { annotationWrapper.hasBeenRemovedByManualOverride = !!logEntry.manualChanges?.find( c => c.manualRedactionType === ManualRedactionTypes.REMOVE_LOCALLY && c.annotationStatus === LogEntryStatuses.APPROVED, ); - annotationWrapper.legalBasisChangeValue = logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE && c.annotationStatus === LogEntryStatuses.REQUESTED, - )?.propertyChanges.legalBasis; this.#createContent(annotationWrapper, logEntry, isDocumine); this.#setSuperType(annotationWrapper, logEntry); @@ -359,15 +294,8 @@ export class AnnotationWrapper implements IListable { const entity = dictionaries.find(d => d.type === annotationWrapper.typeValue); annotationWrapper.entity = entity?.virtual ? null : entity; - let colorKey = annotationWrapper.isSuperTypeBasedColor - ? annotationDefaultColorConfig[annotationWrapper.superType] - : annotationEntityColorConfig[annotationWrapper.superType]; - - if (annotationWrapper.isSuperTypeBasedColor && annotationWrapper.isSuggestionResize && !annotationWrapper.isModifyDictionary) { - colorKey = annotationDefaultColorConfig[SuperTypes.SuggestionAdd]; - } - - annotationWrapper.color = annotationWrapper.isSuperTypeBasedColor ? defaultColors[colorKey] : (entity[colorKey] as string); + const colorKey = annotationEntityColorConfig[annotationWrapper.superType]; + annotationWrapper.color = entity[colorKey] as string; return annotationWrapper; } @@ -408,10 +336,6 @@ export class AnnotationWrapper implements IListable { annotationWrapper.pending = !lastRelevantManualChange.processed; annotationWrapper.superType = this.#selectSuperType(logEntry, lastRelevantManualChange, annotationWrapper.hintDictionary); - - if (lastRelevantManualChange.annotationStatus === LogEntryStatuses.REQUESTED) { - annotationWrapper.recategorizationType = lastRelevantManualChange.propertyChanges.type; - } } else { if (logEntry.state === EntryStates.SKIPPED) { if (logEntry.entryType === EntryTypes.HINT) { @@ -487,20 +411,12 @@ export class AnnotationWrapper implements IListable { switch (lastManualChange.annotationStatus) { case LogEntryStatuses.APPROVED: return SuperTypes.ManualRedaction; - case LogEntryStatuses.DECLINED: - return SuperTypes.DeclinedSuggestion; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionAdd; } break; case ManualRedactionTypes.ADD_TO_DICTIONARY: switch (lastManualChange.annotationStatus) { case LogEntryStatuses.APPROVED: return isHintDictionary ? SuperTypes.Hint : SuperTypes.Redaction; - case LogEntryStatuses.DECLINED: - return SuperTypes.DeclinedSuggestion; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionAddDictionary; } break; case ManualRedactionTypes.REMOVE_LOCALLY: @@ -518,8 +434,6 @@ export class AnnotationWrapper implements IListable { return SuperTypes.Skipped; } - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionRemove; } break; case ManualRedactionTypes.REMOVE_FROM_DICTIONARY: @@ -530,16 +444,12 @@ export class AnnotationWrapper implements IListable { return SuperTypes.Skipped; case LogEntryStatuses.DECLINED: return SuperTypes.Redaction; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionRemoveDictionary; } } switch (lastManualChange.annotationStatus) { case LogEntryStatuses.APPROVED: case LogEntryStatuses.DECLINED: return SuperTypes.Redaction; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionRemoveDictionary; } } @@ -549,8 +459,6 @@ export class AnnotationWrapper implements IListable { return logEntry.entryType === EntryTypes.RECOMMENDATION ? SuperTypes.Recommendation : SuperTypes.Skipped; case LogEntryStatuses.DECLINED: return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionRemoveDictionary; } } @@ -558,8 +466,6 @@ export class AnnotationWrapper implements IListable { case LogEntryStatuses.APPROVED: case LogEntryStatuses.DECLINED: return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionRemoveDictionary; } break; case ManualRedactionTypes.FORCE_REDACT: @@ -568,8 +474,6 @@ export class AnnotationWrapper implements IListable { return SuperTypes.Redaction; case LogEntryStatuses.DECLINED: return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionForceRedaction; } break; case ManualRedactionTypes.FORCE_HINT: @@ -578,8 +482,6 @@ export class AnnotationWrapper implements IListable { return SuperTypes.Hint; case LogEntryStatuses.DECLINED: return SuperTypes.IgnoredHint; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionForceHint; } break; case ManualRedactionTypes.RECATEGORIZE: @@ -600,8 +502,6 @@ export class AnnotationWrapper implements IListable { return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; } - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionRecategorizeImage; } break; case ManualRedactionTypes.LEGAL_BASIS_CHANGE: @@ -609,8 +509,6 @@ export class AnnotationWrapper implements IListable { case LogEntryStatuses.APPROVED: case LogEntryStatuses.DECLINED: return logEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionChangeLegalBasis; } break; case ManualRedactionTypes.RESIZE: @@ -629,8 +527,6 @@ export class AnnotationWrapper implements IListable { return SuperTypes.Hint; } return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; - case LogEntryStatuses.REQUESTED: - return SuperTypes.SuggestionResize; } break; } diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.html b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.html index e27ba5621..18a3391fa 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.html +++ b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.html @@ -14,12 +14,6 @@ > - - - + -
diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts index 38cae9777..69865f1c6 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-workload/file-workload.component.ts @@ -1,10 +1,10 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; import { annotationDefaultColorConfig, DefaultBasedColorType, File } from '@red/domain'; -import { UserService } from '@users/user.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { Observable } from 'rxjs'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; +import { UserService } from '@users/user.service'; +import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; @Component({ @@ -14,17 +14,14 @@ import { map } from 'rxjs/operators'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class FileWorkloadComponent implements OnInit { + #dossierTemplateId: string; @Input() file: File; - - suggestionColor$: Observable; imageColor$: Observable; updatedColor$: Observable; analysisColor$: Observable; hintColor$: Observable; redactionColor$: Observable; - #dossierTemplateId: string; - constructor( private readonly _userService: UserService, private readonly _defaultColorsService: DefaultColorsService, @@ -32,20 +29,6 @@ export class FileWorkloadComponent implements OnInit { private readonly _dictionariesMapService: DictionariesMapService, ) {} - ngOnInit() { - this.#dossierTemplateId = this._dossiersService.find(this.file.dossierId).dossierTemplateId; - this.suggestionColor$ = this.#getDefaultColor$('suggestion'); - this.updatedColor$ = this.#getDefaultColor$('updated'); - this.analysisColor$ = this.#getDefaultColor$('analysis'); - this.hintColor$ = this.#getDefaultColor$('hint'); - this.redactionColor$ = this.#getDefaultColor$('redaction'); - this.imageColor$ = this._dictionariesMapService.watch$(this.#dossierTemplateId, 'image').pipe(map(e => e.hexColor)); - } - - #getDefaultColor$(type: DefaultBasedColorType): Observable { - return this._defaultColorsService.getColor$(this.#dossierTemplateId, annotationDefaultColorConfig[type]); - } - get updated(): boolean { return this.file.hasUpdates && this.file.assignee === this._userService.currentUser.id && !this.file.isApproved; } @@ -57,8 +40,20 @@ export class FileWorkloadComponent implements OnInit { !this.file.hasRedactions && !this.file.hasImages && !this.file.hintsOnly && - !this.file.hasSuggestions && !this.file.hasAnnotationComments ); } + + ngOnInit() { + this.#dossierTemplateId = this._dossiersService.find(this.file.dossierId).dossierTemplateId; + this.updatedColor$ = this.#getDefaultColor$('updated'); + this.analysisColor$ = this.#getDefaultColor$('analysis'); + this.hintColor$ = this.#getDefaultColor$('hint'); + this.redactionColor$ = this.#getDefaultColor$('redaction'); + this.imageColor$ = this._dictionariesMapService.watch$(this.#dossierTemplateId, 'image').pipe(map(e => e.hexColor)); + } + + #getDefaultColor$(type: DefaultBasedColorType): Observable { + return this._defaultColorsService.getColor$(this.#dossierTemplateId, annotationDefaultColorConfig[type]); + } } diff --git a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts index cc550b4bc..691258434 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts @@ -1,4 +1,5 @@ import { Injectable, TemplateRef } from '@angular/core'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ActionConfig, getConfig, @@ -9,6 +10,10 @@ import { WorkflowColumn, WorkflowConfig, } from '@iqser/common-ui'; +import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; +import { getCurrentUser } from '@iqser/common-ui/lib/users'; +import { getParam, List } from '@iqser/common-ui/lib/utils'; +import { TranslateService } from '@ngx-translate/core'; import { annotationDefaultColorConfig, AnnotationShapeMap, @@ -22,26 +27,21 @@ import { WorkflowFileStatus, WorkflowFileStatuses, } from '@red/domain'; -import { workflowFileStatusTranslations } from '@translations/file-status-translations'; -import { PermissionsService } from '@services/permissions.service'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { TranslateService } from '@ngx-translate/core'; -import { UserService } from '@users/user.service'; -import { DossiersDialogService } from '../shared-dossiers/services/dossiers-dialog.service'; -import { annotationFilterChecker, RedactionFilterSorter } from '../../utils'; -import { workloadTranslations } from '@translations/workload-translations'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { BulkActionsService } from './services/bulk-actions.service'; -import dayjs from 'dayjs'; -import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { map } from 'rxjs/operators'; -import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; -import { UserPreferenceService } from '@users/user-preference.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; +import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; +import { PermissionsService } from '@services/permissions.service'; +import { workflowFileStatusTranslations } from '@translations/file-status-translations'; +import { workloadTranslations } from '@translations/workload-translations'; import { Roles } from '@users/roles'; -import { getCurrentUser } from '@iqser/common-ui/lib/users'; -import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; -import { getParam, List } from '@iqser/common-ui/lib/utils'; +import { UserPreferenceService } from '@users/user-preference.service'; +import { UserService } from '@users/user.service'; +import dayjs from 'dayjs'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { annotationFilterChecker, RedactionFilterSorter } from '../../utils'; +import { DossiersDialogService } from '../shared-dossiers/services/dossiers-dialog.service'; +import { BulkActionsService } from './services/bulk-actions.service'; @Injectable() export class ConfigService { @@ -198,9 +198,6 @@ export class ConfigService { if (file.hasRedactions) { allDistinctNeedsWork.add('redaction'); } - if (file.hasSuggestions) { - allDistinctNeedsWork.add('suggestion'); - } if (file.hasUpdates && file.assignee === this._userService.currentUser.id && !file.isApproved) { allDistinctNeedsWork.add('updated'); } diff --git a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.html b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.html index 2eaec1625..597091def 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.html +++ b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.html @@ -12,11 +12,4 @@ label="H" type="circle" > - - diff --git a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts index 1ea343253..a3c9eca39 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/components/dossier-workload-column/dossier-workload-column.component.ts @@ -10,19 +10,13 @@ import { BehaviorSubject, Observable, switchMap } from 'rxjs'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class DossierWorkloadColumnComponent implements OnChanges { + readonly #dossierTemplateId$ = new BehaviorSubject(null); @Input() dossier: Dossier; @Input() dossierStats: DossierStats; - - readonly suggestionColor$: Observable; readonly hintColor$: Observable; readonly redactionColor$: Observable; - readonly #dossierTemplateId$ = new BehaviorSubject(null); - constructor(private readonly _defaultColorsService: DefaultColorsService) { - this.suggestionColor$ = this.#dossierTemplateId$.pipe( - switchMap(dossierTemplateId => this.#getColor$(dossierTemplateId, 'requestAddColor')), - ); this.hintColor$ = this.#dossierTemplateId$.pipe(switchMap(dossierTemplateId => this.#getColor$(dossierTemplateId, 'hintColor'))); this.redactionColor$ = this.#dossierTemplateId$.pipe( switchMap(dossierTemplateId => this.#getColor$(dossierTemplateId, 'redactionColor')), diff --git a/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts b/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts index 5f6490ad0..0bf3c3da2 100644 --- a/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts +++ b/apps/red-ui/src/app/modules/dossiers-listing/config.service.ts @@ -1,5 +1,8 @@ import { Injectable, TemplateRef } from '@angular/core'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ButtonConfig, getConfig, TableColumnConfig } from '@iqser/common-ui'; +import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; +import { TranslateService } from '@ngx-translate/core'; import { annotationDefaultColorConfig, AnnotationShapeMap, @@ -9,11 +12,15 @@ import { User, WorkflowFileStatus, } from '@red/domain'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { TranslateService } from '@ngx-translate/core'; +import { DossierStatsService } from '@services/dossiers/dossier-stats.service'; +import { DefaultColorsService } from '@services/entity-services/default-colors.service'; +import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service'; +import { PermissionsService } from '@services/permissions.service'; +import { SharedDialogService } from '@shared/services/dialog.service'; +import { workflowFileStatusTranslations } from '@translations/file-status-translations'; +import { workloadTranslations } from '@translations/workload-translations'; import { UserPreferenceService } from '@users/user-preference.service'; import { UserService } from '@users/user.service'; -import { workflowFileStatusTranslations } from '@translations/file-status-translations'; import { dossierMemberChecker, dossierMemberQuickChecker, @@ -21,17 +28,11 @@ import { dossierStateChecker, RedactionFilterSorter, } from '../../utils'; -import { workloadTranslations } from '@translations/workload-translations'; -import { DossierStatsService } from '@services/dossiers/dossier-stats.service'; -import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service'; -import { PermissionsService } from '@services/permissions.service'; -import { SharedDialogService } from '@shared/services/dialog.service'; -import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { IFilterGroup, INestedFilter, keyChecker, NestedFilter } from '@iqser/common-ui/lib/filtering'; @Injectable() export class ConfigService { readonly #isDocumine = getConfig().IS_DOCUMINE; + constructor( private readonly _translateService: TranslateService, private readonly _userPreferenceService: UserPreferenceService, @@ -106,9 +107,6 @@ export class ConfigService { if (stats.hasRedactionsFilePresent) { allDistinctNeedsWork.add('redaction'); } - if (stats.hasSuggestionsFilePresent) { - allDistinctNeedsWork.add('suggestion'); - } if (stats.hasNoFlagsFilePresent) { allDistinctNeedsWork.add('none'); } @@ -246,12 +244,6 @@ export class ConfigService { private _annotationFilterChecker = (dossier: Dossier, filter: INestedFilter) => { const stats = this._dossierStatsService.get(dossier.id); switch (filter.id) { - // case 'analysis': { - // return stats.reanalysisRequired; - // } - case 'suggestion': { - return stats.hasSuggestionsFilePresent; - } case 'redaction': { return stats.hasRedactionsFilePresent; } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html index cfaff2b27..17e2a2fce 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.html @@ -7,10 +7,10 @@ @@ -28,20 +28,20 @@ @@ -136,12 +136,12 @@ > diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts index 24cf21584..31f329f08 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts @@ -24,6 +24,9 @@ export type AnnotationButtonType = keyof typeof AnnotationButtonTypes; styleUrls: ['./annotation-actions.component.scss'], }) export class AnnotationActionsComponent implements OnChanges { + #annotations: AnnotationWrapper[] = []; + readonly #isDocumine = getConfig().IS_DOCUMINE; + protected _annotationId = ''; @Input() buttonType: AnnotationButtonType = AnnotationButtonTypes.default; @Input() tooltipPosition: 'before' | 'above' = 'before'; @Input() canPerformAnnotationActions: boolean; @@ -31,13 +34,10 @@ export class AnnotationActionsComponent implements OnChanges { readonly roles = Roles; annotationPermissions: AnnotationPermissions; isImage = true; - protected _annotationId = ''; - #annotations: AnnotationWrapper[] = []; readonly isVisible = computed(() => { const hidden = this._annotationManager.hidden(); return this.#annotations.reduce((acc, annotation) => !hidden.has(annotation.id) && acc, true); }); - readonly #isDocumine = getConfig().IS_DOCUMINE; constructor( readonly viewModeService: ViewModeService, @@ -55,6 +55,13 @@ export class AnnotationActionsComponent implements OnChanges { return this.#annotations; } + @Input() + set annotations(annotations: AnnotationWrapper[]) { + this.#annotations = annotations.filter(a => a !== undefined); + this.isImage = this.#annotations?.reduce((accumulator, annotation) => annotation.isImage && accumulator, true); + this._annotationId = this.#annotations[0]?.id; + } + get canEdit(): boolean { const canEditRedactions = this.annotationPermissions.canChangeLegalBasis || @@ -91,18 +98,11 @@ export class AnnotationActionsComponent implements OnChanges { return this.annotations.every(a => a.superType === type); } - @Input() - set annotations(annotations: AnnotationWrapper[]) { - this.#annotations = annotations.filter(a => a !== undefined); - this.isImage = this.#annotations?.reduce((accumulator, annotation) => annotation.isImage && accumulator, true); - this._annotationId = this.#annotations[0]?.id; - } - ngOnChanges(): void { this.#setPermissions(); } - removeOrSuggestRemoveRedaction() { + removeRedaction() { this.annotationActionsService.removeRedaction(this.annotations, this.annotationPermissions); } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index b822419ff..920c5d427 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -10,7 +10,7 @@
{{ annotation.typeLabel | translate }}   - + {{ 'annotation.pending' | translate }}
diff --git a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts index 8fcf65a93..340effd47 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts @@ -1,13 +1,10 @@ import { Component, computed, Inject } from '@angular/core'; -import { ViewMode, ViewModes } from '@red/domain'; -import { ViewModeService } from '../../services/view-mode.service'; -import { FilePreviewStateService } from '../../services/file-preview-state.service'; -import { FileDataService } from '../../services/file-data.service'; -import { ConfirmOptions, IConfirmationDialogData, Toaster } from '@iqser/common-ui'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; -import { Roles } from '@users/roles'; import { BASE_HREF } from '@iqser/common-ui/lib/utils'; +import { ViewMode, ViewModes } from '@red/domain'; +import { Roles } from '@users/roles'; +import { FileDataService } from '../../services/file-data.service'; +import { FilePreviewStateService } from '../../services/file-preview-state.service'; +import { ViewModeService } from '../../services/view-mode.service'; @Component({ selector: 'redaction-view-switch', @@ -37,49 +34,12 @@ export class ViewSwitchComponent { readonly viewModeService: ViewModeService, private readonly _state: FilePreviewStateService, private readonly _fileDataService: FileDataService, - private readonly _dialogService: FilePreviewDialogService, - private readonly _toaster: Toaster, ) {} switchView(viewMode: ViewMode) { if (viewMode === ViewModes.REDACTED) { - return this.#switchToRedactedView(); + return this.viewModeService.switchToRedacted(); } this.viewModeService.switchTo(viewMode); } - - async #switchToRedactedView() { - const suggestions = this._fileDataService.annotations().filter(a => a.isSuggestion); - if (!suggestions.length) { - return this.viewModeService.switchToRedacted(); - } - - const question = _('unapproved-suggestions.confirmation-dialog.not-displayed-question'); - const data: IConfirmationDialogData = { - title: _('unapproved-suggestions.confirmation-dialog.title'), - question: question, - confirmationText: _('unapproved-suggestions.confirmation-dialog.confirmation-text'), - denyText: _('unapproved-suggestions.confirmation-dialog.deny-text'), - checkboxes: [ - { - label: _('unapproved-suggestions.confirmation-dialog.checkbox-text'), - value: false, - }, - ], - checkboxesValidation: false, - }; - - return this._dialogService.openDialog('confirm', data, result => { - if (!result) { - return; - } - - if (result === ConfirmOptions.SECOND_CONFIRM) { - this._toaster.success(_('unapproved-suggestions.confirmation-dialog.success-confirmation-text'), { - params: { settingsUrl: `${this._baseHref}/main/account/warnings-preferences` }, - }); - } - this.viewModeService.switchToRedacted(); - }); - } } diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index 9ab30726b..202f26ea3 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -4,7 +4,6 @@ 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, 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'; import { FilesService } from '@services/files/files.service'; @@ -56,7 +55,6 @@ export class FileDataService extends EntitiesService = {}; const dictionaries = this._state.dictionaries; - const defaultColors = this._defaultColorsService.find(this._state.dossierTemplateId); let checkDictionary = true; for (const entry of entityLog.entityLogEntry) { @@ -207,25 +203,16 @@ export class FileDataService extends EntitiesService !sourceKeys.includes(r.id)); + return annotations; } #getChangeLogValues( @@ -268,12 +255,11 @@ export class FileDataService extends EntitiesService visibleStatuses.includes(change.annotationStatus)); viableManualChanges.sort(chronologicallyBy(x => x.processedDate)); const lastManualChange = viableManualChanges.at(-1); - const isSuggestion = lastManualChange?.annotationStatus === LogEntryStatuses.REQUESTED; - const processedTime = isSuggestion ? lastManualChange.requestedDate : lastManualChange?.processedDate; + const processedTime = lastManualChange?.processedDate; changeOccurredAfterPageIsViewed = processedTime && timestampOf(processedTime) > viewTime; if (changeOccurredAfterPageIsViewed) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts index 6a6748e88..b1bc55056 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts @@ -43,7 +43,7 @@ export class ManualRedactionService extends GenericService { constructor( private readonly _toaster: Toaster, private readonly _logger: NGXLogger, - private readonly _iqaerPermissionsService: IqserPermissionsService, + private readonly _iqserPermissionsService: IqserPermissionsService, ) { super(); } @@ -90,7 +90,7 @@ export class ManualRedactionService extends GenericService { const toast = requests[0].addToDictionary ? this.#showAddToDictionaryToast(requests, options?.dictionaryLabel) : this.#showToast(options?.hint ? 'force-hint' : 'add'); - const canAddRedaction = this._iqaerPermissionsService.has(Roles.redactions.write); + const canAddRedaction = this._iqserPermissionsService.has(Roles.redactions.write); if (canAddRedaction) { return this.add(requests, dossierId, fileId).pipe(toast); } @@ -137,19 +137,6 @@ export class ManualRedactionService extends GenericService { ); } - approve(annotationIds: List, dossierId: string, fileId: string) { - return this._post(annotationIds, `${this._defaultModelPath}/bulk/approve/${dossierId}/${fileId}`).pipe( - this.#log('Approve', annotationIds), - this.#showToast('approve'), - ); - } - - decline(annotationIds: List, dossierId: string, fileId: string) { - return this._post(annotationIds, `${this._defaultModelPath}/bulk/decline/${dossierId}/${fileId}`).pipe( - this.#log('Decline', annotationIds), - ); - } - undo(annotationIds: List, dossierId: string, fileId: string) { const url = `${this._defaultModelPath}/bulk/undo/${dossierId}/${fileId}`; return super.delete(annotationIds, url).pipe(this.#log('Undo', annotationIds)); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index 80eabfe1f..cea94509f 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -154,7 +154,7 @@ export class AnnotationDrawService { annotation.Id = annotationWrapper.id; annotation.ReadOnly = true; - const isOCR = annotationWrapper.isOCR && !annotationWrapper.isSuggestionResize; + const isOCR = annotationWrapper.isOCR; if (isOCR && !this._annotationManager.isHidden(annotationWrapper.id)) { this._annotationManager.addToHidden(annotationWrapper.id); } @@ -164,12 +164,6 @@ export class AnnotationDrawService { this._annotationManager.isHidden(annotationWrapper.id); annotation.setCustomData('redact-manager', 'true'); annotation.setCustomData('redaction', String(annotationWrapper.previewAnnotation)); - annotation.setCustomData('suggestion', String(annotationWrapper.isSuggestion)); - annotation.setCustomData('suggestionAdd', String(annotationWrapper.isSuggestionAdd)); - annotation.setCustomData('suggestionAddToFalsePositive', String(annotationWrapper.isSuggestionAddToFalsePositive)); - annotation.setCustomData('suggestionRemove', String(annotationWrapper.isSuggestionRemove)); - annotation.setCustomData('suggestionRecategorizeImage', String(annotationWrapper.isSuggestionRecategorizeImage)); - annotation.setCustomData('suggestionForceHint', String(annotationWrapper.isSuggestionForceHint)); annotation.setCustomData('skipped', String(annotationWrapper.isSkipped)); annotation.setCustomData('notSignatureImage', String(annotationWrapper.isNotSignatureImage)); annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry)); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts index d0bbfbbb7..e1160d5a7 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/readable-redactions.service.ts @@ -1,13 +1,12 @@ import { inject, Injectable } from '@angular/core'; -import { TranslateService } from '@ngx-translate/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { HeaderElements } from '../../file-preview/utils/constants'; -import { PdfViewer } from './pdf-viewer.service'; -import { REDAnnotationManager } from './annotation-manager.service'; -import { AnnotationDrawService } from './annotation-draw.service'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { Core } from '@pdftron/webviewer'; import { BASE_HREF_FN } from '@iqser/common-ui/lib/utils'; +import { TranslateService } from '@ngx-translate/core'; +import { Core } from '@pdftron/webviewer'; +import { BehaviorSubject, Observable } from 'rxjs'; +import { HeaderElements } from '../../file-preview/utils/constants'; +import { AnnotationDrawService } from './annotation-draw.service'; +import { PdfViewer } from './pdf-viewer.service'; import Annotation = Core.Annotations.Annotation; @Injectable() @@ -21,7 +20,6 @@ export class ReadableRedactionsService { constructor( private readonly _pdf: PdfViewer, private readonly _translateService: TranslateService, - private readonly _annotationManager: REDAnnotationManager, private readonly _annotationDrawService: AnnotationDrawService, ) { this.active$ = this.#active$.asObservable(); @@ -79,8 +77,7 @@ export class ReadableRedactionsService { setAnnotationsOpacity(annotations: Annotation[], restoreToOriginal = false) { annotations.forEach(annotation => { - const isSuggestion = annotation.getCustomData('suggestion'); - annotation['Opacity'] = restoreToOriginal || isSuggestion ? parseFloat(annotation.getCustomData('opacity')) : 0.5; + annotation['Opacity'] = restoreToOriginal ? parseFloat(annotation.getCustomData('opacity')) : 0.5; }); } diff --git a/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts b/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts index 1df39b876..197352b41 100644 --- a/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/type-filter/type-filter.component.ts @@ -1,31 +1,20 @@ import { Component, Input, OnChanges } from '@angular/core'; -import { SuperTypes } from '@red/domain'; -import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { TranslateService } from '@ngx-translate/core'; import { INestedFilter } from '@iqser/common-ui/lib/filtering'; +import { TranslateService } from '@ngx-translate/core'; @Component({ - selector: 'redaction-type-filter [dossierTemplateId]', + selector: 'redaction-type-filter', templateUrl: './type-filter.component.html', styleUrls: ['./type-filter.component.scss'], }) export class TypeFilterComponent implements OnChanges { - private _suggestionsKeys: string[] = [ - SuperTypes.SuggestionRemove, - SuperTypes.SuggestionForceRedaction, - SuperTypes.SuggestionAdd, - SuperTypes.SuggestionRemoveDictionary, - SuperTypes.SuggestionAddDictionary, - SuperTypes.DeclinedSuggestion, - 'suggestion', - ]; private _needsAnalysisKeys: string[] = ['remove-only-here', 'analysis']; @Input() filter: INestedFilter; - @Input() dossierTemplateId: string; + @Input({ required: true }) dossierTemplateId: string; @Input() dossierId: string; label: string; - constructor(private readonly _defaultColorsService: DefaultColorsService, private readonly _translateService: TranslateService) {} + constructor(private readonly _translateService: TranslateService) {} ngOnChanges(): void { this.label = @@ -35,8 +24,6 @@ export class TypeFilterComponent implements OnChanges { ? '-' : this._needsAnalysisKeys.includes(this.filter.id) ? 'A' - : this._suggestionsKeys.includes(this.filter.id) - ? 'S' : this.filter.skipTranslation ? this.filter.label.charAt(0) : this._translateService.instant(this.filter.label).charAt(0); diff --git a/apps/red-ui/src/app/translations/annotation-actions-translations.ts b/apps/red-ui/src/app/translations/annotation-actions-translations.ts index 8e622a17f..fe1b0f8b6 100644 --- a/apps/red-ui/src/app/translations/annotation-actions-translations.ts +++ b/apps/red-ui/src/app/translations/annotation-actions-translations.ts @@ -1,5 +1,5 @@ -import { DictionaryActions, ManualRedactionActions } from '@red/domain'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { DictionaryActions, ManualRedactionActions } from '@red/domain'; interface AnnotationActionResponses { error: string; @@ -13,26 +13,10 @@ export const dictionaryActionsTranslations: Record = { [SuperTypes.TextHighlight]: _('annotation-type.text-highlight'), - [SuperTypes.DeclinedSuggestion]: _('annotation-type.declined-suggestion'), [SuperTypes.Hint]: _('annotation-type.hint'), [SuperTypes.IgnoredHint]: _('annotation-type.ignored-hint'), [SuperTypes.ManualRedaction]: _('annotation-type.manual-redaction'), [SuperTypes.Recommendation]: _('annotation-type.recommendation'), [SuperTypes.Redaction]: _('annotation-type.redaction'), [SuperTypes.Skipped]: _('annotation-type.skipped'), - [SuperTypes.SuggestionAdd]: _('annotation-type.suggestion-add'), - [SuperTypes.SuggestionAddDictionary]: _('annotation-type.suggestion-add-dictionary'), - [SuperTypes.SuggestionChangeLegalBasis]: _('annotation-type.suggestion-change-legal-basis'), - [SuperTypes.SuggestionRecategorizeImage]: _('annotation-type.suggestion-recategorize-image'), - [SuperTypes.SuggestionForceRedaction]: _('annotation-type.suggestion-force-redaction'), - [SuperTypes.SuggestionForceHint]: _('annotation-type.suggestion-force-hint'), - [SuperTypes.SuggestionRemove]: _('annotation-type.suggestion-remove'), - [SuperTypes.SuggestionRemoveDictionary]: _('annotation-type.suggestion-remove-dictionary'), - [SuperTypes.SuggestionResize]: _('annotation-type.suggestion-resize'), [SuggestionAddFalsePositive]: _('annotation-type.suggestion-add-false-positive'), } as const; diff --git a/apps/red-ui/src/app/translations/workload-translations.ts b/apps/red-ui/src/app/translations/workload-translations.ts index 84d912e7c..efa994d66 100644 --- a/apps/red-ui/src/app/translations/workload-translations.ts +++ b/apps/red-ui/src/app/translations/workload-translations.ts @@ -6,7 +6,6 @@ export const workloadTranslations: { [key: string]: string } = { image: _('filter.image'), none: _('filter.none'), redaction: _('filter.redaction'), - suggestion: _('filter.suggestion'), updated: _('filter.updated'), comment: _('filter.comment'), }; diff --git a/apps/red-ui/src/app/users/user-preference.service.ts b/apps/red-ui/src/app/users/user-preference.service.ts index 0c4315c4d..27f412574 100644 --- a/apps/red-ui/src/app/users/user-preference.service.ts +++ b/apps/red-ui/src/app/users/user-preference.service.ts @@ -7,7 +7,6 @@ export const PreferencesKeys = { lastDossierTemplate: 'Last-Dossier-Template', filesListingMode: 'Files-Listing-Mode', autoExpandFiltersOnActions: 'Auto-Expand-Filters-On-Actions', - displaySuggestionsInPreview: 'Display-Suggestions-In-Preview', loadAllAnnotationsWarning: 'Load-All-Annotations-Warning', openScmDialogByDefault: 'Open-Structured-Component-Management-By-Default', tableExtractionType: 'Table-Extraction-Type', diff --git a/apps/red-ui/src/app/utils/filter-utils.ts b/apps/red-ui/src/app/utils/filter-utils.ts index 939bde6a2..68bf58595 100644 --- a/apps/red-ui/src/app/utils/filter-utils.ts +++ b/apps/red-ui/src/app/utils/filter-utils.ts @@ -1,5 +1,5 @@ -import { Dossier, File, User, UserType } from '@red/domain'; import { handleCheckedValue, INestedFilter } from '@iqser/common-ui/lib/filtering'; +import { Dossier, File, User, UserType } from '@red/domain'; export function handleFilterDelta(oldFilters: INestedFilter[], newFilters: INestedFilter[], allFilters: INestedFilter[]) { const newFiltersDelta = {}; @@ -52,9 +52,6 @@ export const annotationFilterChecker = (file: File, filter: INestedFilter, curre case 'analysis': { return file.analysisRequired; } - case 'suggestion': { - return file.hasSuggestions; - } case 'redaction': { return file.hasRedactions; } diff --git a/apps/red-ui/src/app/utils/sorters/redaction-filter-sorter.ts b/apps/red-ui/src/app/utils/sorters/redaction-filter-sorter.ts index 092b35c76..c20c57375 100644 --- a/apps/red-ui/src/app/utils/sorters/redaction-filter-sorter.ts +++ b/apps/red-ui/src/app/utils/sorters/redaction-filter-sorter.ts @@ -4,7 +4,6 @@ export const RedactionFilterSorter = { redaction: 2, image: 3, hint: 4, - suggestion: 5, none: 6, byKey: (a: { id: string }, b: { id: string }): number => RedactionFilterSorter[a.id] - RedactionFilterSorter[b.id], }; diff --git a/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts index 419a3d205..2305bc13c 100644 --- a/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts +++ b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts @@ -2,20 +2,10 @@ import { SuperType, SuperTypes } from '@red/domain'; export const SuperTypeSorter: { [key in SuperType]: number } = { [SuperTypes.TextHighlight]: 100, - [SuperTypes.SuggestionChangeLegalBasis]: 14, - [SuperTypes.SuggestionForceRedaction]: 15, - [SuperTypes.SuggestionForceHint]: 16, - [SuperTypes.SuggestionRecategorizeImage]: 17, - [SuperTypes.SuggestionResize]: 18, [SuperTypes.Recommendation]: 7, - [SuperTypes.SuggestionAddDictionary]: 12, - [SuperTypes.SuggestionRemoveDictionary]: 13, - [SuperTypes.SuggestionAdd]: 10, - [SuperTypes.SuggestionRemove]: 11, [SuperTypes.IgnoredHint]: 45, [SuperTypes.Skipped]: 50, [SuperTypes.Redaction]: 1, [SuperTypes.ManualRedaction]: 2, [SuperTypes.Hint]: 19, - [SuperTypes.DeclinedSuggestion]: 20, }; diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index 42bf5941f..deb14e6da 100644 --- a/apps/red-ui/src/assets/config/config.json +++ b/apps/red-ui/src/assets/config/config.json @@ -1,7 +1,7 @@ { "ADMIN_CONTACT_NAME": null, "ADMIN_CONTACT_URL": null, - "API_URL": "https://dan.iqser.cloud", + "API_URL": "https://dan1.iqser.cloud", "APP_NAME": "RedactManager", "IS_DOCUMINE": false, "RULE_EDITOR_DEV_ONLY": false, @@ -13,7 +13,7 @@ "MAX_RETRIES_ON_SERVER_ERROR": 3, "OAUTH_CLIENT_ID": "redaction", "OAUTH_IDP_HINT": null, - "OAUTH_URL": "https://dan.iqser.cloud/auth", + "OAUTH_URL": "https://dan1.iqser.cloud/auth", "RECENT_PERIOD_IN_HOURS": 24, "SELECTION_MODE": "structural", "MANUAL_BASE_URL": "https://docs.redactmanager.com/preview", diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 9cb057632..139c584d1 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -56,8 +56,7 @@ }, "add-edit-clone-dossier-template": { "error": { - "conflict": "Dossiervorlage konnte nicht erstellt werden: Es existiert bereits eine Dossiervorlage mit demselben Namen.", - "generic": "Fehler beim Erstellen der Dossiervorlage." + "conflict": "Dossiervorlage konnte nicht erstellt werden: Es existiert bereits eine Dossiervorlage mit demselben Namen." }, "form": { "apply-updates-default": { @@ -256,9 +255,6 @@ "user-management": "User Management", "watermarks": "Watermarks" }, - "annotation": { - "pending": "(Pending Analysis)" - }, "annotation-actions": { "accept-recommendation": { "label": "Empfehlung annehmen" @@ -283,26 +279,10 @@ "error": "Fehler beim Hinzufügen des neuen Wörterbucheintrags: {error}", "success": "Eintrag zum Wörterbuch hinzugefügt. Änderungen nach der Reanalyse sichtbar." }, - "approve": { - "error": "Fehler beim Genehmigen des Wörterbucheintrags: {error}", - "success": "Neuer Wörterbucheintrag wurde genehmigt. Änderungen sind nach der Reanalyse sichtbar." - }, - "decline": { - "error": "Fehler beim Ablehnen des neuen Wörterbucheintrags: {error}", - "success": "Vorschlag für das Wörterbuch abgelehnt." - }, "remove": { "error": "Fehler beim Entfernen des Wörterbucheintrags: {error}", "success": "Wörterbucheintrag wurde gelöscht!" }, - "request-remove": { - "error": "Dossier-Vorlage", - "success": "Löschung des Wörterbucheintrags wurde vorgeschlagen!" - }, - "suggest": { - "error": "Vorschlag für Änderung des Wörterbuchs konnte nicht gespeichert werden: {error}", - "success": "Vorschlag für die Änderung des Wörterbuchs gespeichert!" - }, "undo": { "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", "success": "Rückgängigmachen erfolgreich" @@ -313,10 +293,6 @@ "error": "Fehler beim Speichern der Schwärzung: {error}", "success": "Schwärzung hinzugefügt!" }, - "approve": { - "error": "Fehler beim Genehmigen des Vorschlags: {error}", - "success": "Vorschlag genehmigt" - }, "change-legal-basis": { "error": "Fehler beim Bearbeiten der in der Anmerkung genannten Begründung: {error}", "success": "In der Anmerkung genannte Begründung wurde bearbeitet." @@ -325,10 +301,6 @@ "error": "Failed to edit type: {error}", "success": "Type was edited." }, - "decline": { - "error": "Fehler beim Ablehnen des Vorschlags: {error}", - "success": "Vorschlag abgelehnt" - }, "force-hint": { "error": "Failed to save hint: {error}", "success": "Hint added!" @@ -341,41 +313,13 @@ "error": "Rekategorisierung des Bildes gescheitert: {error}", "success": "Bild wurde einer neuen Kategorie zugeordnet." }, - "remove": { - "error": "Fehler beim Entfernen der Schwärzung: {error}", - "success": "Schwärzung entfernt!" - }, "remove-hint": { "error": "Failed to remove hint: {error}", "success": "Hint removed!" }, - "request-change-legal-basis": { - "error": "Fehler beim Vorschlagen der Änderung der Begründung:", - "success": "Die Änderung der in der Anmerkung genannten Begründung wurde beantragt." - }, - "request-force-hint": { - "error": "Failed to save hint suggestion: {error}", - "success": "Hint suggestion saved" - }, - "request-force-redaction": { - "error": "Fehler beim Speichern des Schwärzungsvorschlags: {error}", - "success": "Vorschlag einer Schwärzung gespeichert" - }, - "request-image-recategorization": { - "error": "Fehler beim Vorschlagen der Neukategorisierung des Bilds: {error}", - "success": "Bild-Neuklassifizierung angefordert." - }, - "request-remove": { - "error": "Fehler beim Erstellen des Vorschlags für das Entfernen der Schwärzung: {error}", - "success": "Entfernen der Schwärzung wurde vorgeschlagen!" - }, - "request-remove-hint": { - "error": "Failed to request removal of hint: {error}", - "success": "Requested to remove hint!" - }, - "suggest": { - "error": "Vorschlag einer Schwärzung wurde nicht gespeichert: {error}", - "success": "Vorschlag einer Schwärzung gespeichert" + "remove": { + "error": "Fehler beim Entfernen der Schwärzung: {error}", + "success": "Schwärzung entfernt!" }, "undo": { "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", @@ -389,15 +333,15 @@ "remove-highlights": { "label": "Remove Selected Earmarks" }, - "resize": { - "label": "Größe ändern" - }, "resize-accept": { "label": "Größe speichern" }, "resize-cancel": { "label": "Größenänderung abbrechen" }, + "resize": { + "label": "Größe ändern" + }, "see-references": { "label": "See References" }, @@ -419,7 +363,6 @@ "rule": "Schwärzung basierend auf Regel {rule}" }, "annotation-type": { - "declined-suggestion": "Abgelehnter Vorschlag", "hint": "Hinweis", "ignored-hint": "Ignorierter Hinweis", "manual-hint": "Manual Hint", @@ -427,18 +370,12 @@ "recommendation": "Empfehlung", "redaction": "Schwärzung", "skipped": "Übersprungen", - "suggestion-add": "Vorschlag für Schwärzung", - "suggestion-add-dictionary": "Vorschlag für neuen Wörterbucheintrag", "suggestion-add-false-positive": "Suggested add to false positive", - "suggestion-change-legal-basis": "Vorschlag für Änderung der Rechtsgrundlage", - "suggestion-force-hint": "Suggestion force hint", - "suggestion-force-redaction": "Vorschlag für erzwungene Schwärzung", - "suggestion-recategorize-image": "Vorschlag für Rekategorisierung eines Bilds", - "suggestion-remove": "Vorschlagen, die Schwärzung zu entfernen", - "suggestion-remove-dictionary": "Vorschlag für Löschung eines Wörterbucheintrags", - "suggestion-resize": "Vorgeschlagene Größenänderung", "text-highlight": "Earmark" }, + "annotation": { + "pending": "(Pending Analysis)" + }, "archived-dossiers-listing": { "no-data": { "title": "No archived dossiers." @@ -638,18 +575,14 @@ "warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!" }, "confirmation-dialog": { - "approve-file": { - "question": "Dieses Dokument enthält ungesehene Änderungen. Möchten Sie es trotzdem genehmigen?", - "title": "Warnung!" - }, "approve-file-without-analysis": { "confirmationText": "Approve without analysis", "denyText": "Cancel", "question": "Analysis required to detect new redactions.", "title": "Warning!" }, - "approve-multiple-files": { - "question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen. Möchten Sie sie trotzdem genehmigen?", + "approve-file": { + "question": "Dieses Dokument enthält ungesehene Änderungen. Möchten Sie es trotzdem genehmigen?", "title": "Warnung!" }, "approve-multiple-files-without-analysis": { @@ -658,6 +591,10 @@ "question": "Analysis required to detect new redactions for at least one file.", "title": "Warning" }, + "approve-multiple-files": { + "question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen. Möchten Sie sie trotzdem genehmigen?", + "title": "Warnung!" + }, "assign-file-to-me": { "question": { "multiple": "Dieses Dokument wird gerade von einer anderen Person geprüft. Möchten Sie Reviewer werden und sich selbst dem Dokument zuweisen?", @@ -1003,13 +940,13 @@ "recent": "Neu ({hours} h)", "unassigned": "Niemandem zugewiesen" }, - "reanalyse": { - "action": "Datei analysieren" - }, "reanalyse-dossier": { "error": "Die Dateien konnten nicht für eine Reanalyse eingeplant werden. Bitte versuchen Sie es erneut.", "success": "Dateien für Reanalyse vorgesehen." }, + "reanalyse": { + "action": "Datei analysieren" + }, "start-auto-analysis": "Enable auto-analysis", "stop-auto-analysis": "Stop auto-analysis", "table-col-names": { @@ -1078,14 +1015,6 @@ "total-documents": "Anzahl der Dokumente", "total-people": "{count} {count, plural, one{User} other {Users}}" }, - "dossier-templates": { - "label": "Dossier-Vorlagen", - "status": { - "active": "Active", - "inactive": "Inactive", - "incomplete": "Incomplete" - } - }, "dossier-templates-listing": { "action": { "clone": "Clone Template", @@ -1121,6 +1050,14 @@ "title": "{length} {length, plural, one{Dossier-Vorlage} other{Dossier-Vorlagen}}" } }, + "dossier-templates": { + "label": "Dossier-Vorlagen", + "status": { + "active": "Active", + "inactive": "Inactive", + "incomplete": "Incomplete" + } + }, "dossier-watermark-selector": { "heading": "Watermarks on documents", "no-watermark": "There is no watermark defined for the dossier template.
Contact your app admin to define one.", @@ -1304,15 +1241,6 @@ "title": "{length} {length, plural, one{Wörterbuch} other{Wörterbücher}}" } }, - "entity": { - "info": { - "actions": { - "revert": "Revert", - "save": "Save Changes" - }, - "heading": "Edit Entity" - } - }, "entity-rules-screen": { "error": { "generic": "Something went wrong... Entity rules update failed!" @@ -1326,19 +1254,28 @@ "title": "Entity Rule Editor", "warning-text": "Warning: experimental feature!" }, + "entity": { + "info": { + "actions": { + "revert": "Revert", + "save": "Save Changes" + }, + "heading": "Edit Entity" + } + }, "error": { "deleted-entity": { "dossier": { "action": "Zurück zur Übersicht", "label": "Dieses Dossier wurde gelöscht!" }, - "file": { - "action": "Zurück zum Dossier", - "label": "Diese Datei wurde gelöscht!" - }, "file-dossier": { "action": "Zurück zur Übersicht", "label": "Das Dossier dieser Datei wurde gelöscht!" + }, + "file": { + "action": "Zurück zum Dossier", + "label": "Diese Datei wurde gelöscht!" } }, "file-preview": { @@ -1356,12 +1293,6 @@ }, "exact-date": "{day} {month} {year} um {hour}:{minute} Uhr", "file": "Datei", - "file-attribute": { - "update": { - "error": "Failed to update file attribute value!", - "success": "File attribute value has been updated successfully!" - } - }, "file-attribute-encoding-types": { "ascii": "ASCII", "iso": "ISO-8859-1", @@ -1372,6 +1303,12 @@ "number": "Nummer", "text": "Freier Text" }, + "file-attribute": { + "update": { + "error": "Failed to update file attribute value!", + "success": "File attribute value has been updated successfully!" + } + }, "file-attributes-configurations": { "cancel": "Cancel", "form": { @@ -1585,16 +1522,6 @@ "csv": "File attributes were imported successfully from uploaded CSV file." } }, - "filter": { - "analysis": "Analyse erforderlich", - "comment": "Kommentare", - "hint": "Nut Hinweise", - "image": "Bilder", - "none": "Keine Anmerkungen", - "redaction": "Geschwärzt", - "suggestion": "Vorgeschlagene Schwärzung", - "updated": "Aktualisiert" - }, "filter-menu": { "filter-options": "Filteroptionen", "filter-types": "Filter", @@ -1604,6 +1531,15 @@ "unseen-pages": "Nur Anmerkungen auf unsichtbaren Seiten", "with-comments": "Nur Anmerkungen mit Kommentaren" }, + "filter": { + "analysis": "Analyse erforderlich", + "comment": "Kommentare", + "hint": "Nut Hinweise", + "image": "Bilder", + "none": "Keine Anmerkungen", + "redaction": "Geschwärzt", + "updated": "Aktualisiert" + }, "filters": { "assigned-people": "Beauftragt", "documents-status": "Documents State", @@ -1671,13 +1607,6 @@ }, "title": "SMTP-Konto konfigurieren" }, - "generic-errors": { - "400": "The sent request is not valid.", - "403": "Access to the requested resource is not allowed.", - "404": "The requested resource could not be found.", - "409": "The request is incompatible with the current state.", - "500": "The server encountered an unexpected condition that prevented it from fulfilling the request." - }, "help-mode": { "bottom-text": "Hilfe-Modus", "button-text": "Help Mode (H)", @@ -1789,6 +1718,7 @@ "copyright-claim-text": "Copyright © 2020 - {currentYear} knecon", "copyright-claim-title": "Copyright", "custom-app-title": "Name der Anwendung", + "email-report": "E-Mail-Bericht", "email": { "body": { "analyzed": "Im aktuellen Lizenzzeitraum insgesamt analysierte Seiten: {pages}.", @@ -1796,7 +1726,6 @@ }, "title": "Lizenzbericht {licenseCustomer}" }, - "email-report": "E-Mail-Bericht", "end-user-license-text": "Die Nutzung dieses Produkts unterliegt den Bedingungen der Endbenutzer-Lizenzvereinbarung für den RedactManager, sofern darin nichts anderweitig festgelegt.", "end-user-license-title": "Endbenutzer-Lizenzvereinbarung", "licensing-details": { @@ -1889,13 +1818,6 @@ "user-promoted-to-approver": "{user} wurde im Dossier {dossierHref, select, null{{dossierName}} other{{dossierName}}} zum Genehmiger ernannt!", "user-removed-as-dossier-member": "{user} wurde als Mitglied von: {dossierHref, select, null{{dossierName}} other{{dossierName}}} entfernt!" }, - "notifications": { - "button-text": "Notifications", - "deleted-dossier": "Deleted Dossier", - "label": "Benachrichtigungen", - "mark-all-as-read": "Alle als gelesen markieren", - "mark-as": "Mark as {type, select, read{read} unread{unread} other{}}" - }, "notifications-screen": { "category": { "email-notifications": "E-Mail Benachrichtigungen", @@ -1909,6 +1831,7 @@ "dossier": "Dossierbezogene Benachrichtigungen", "other": "Andere Benachrichtigungen" }, + "options-title": "Wählen Sie aus, in welcher Kategorie Sie benachrichtigt werden möchten", "options": { "ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen bin", "ASSIGN_REVIEWER": "Wenn ich einem Dokument als Überprüfer zugewiesen bin", @@ -1926,7 +1849,6 @@ "USER_PROMOTED_TO_APPROVER": "Wenn ich Genehmiger in einem Dossier werde", "USER_REMOVED_AS_DOSSIER_MEMBER": "Wenn ich die Dossier-Mitgliedschaft verliere" }, - "options-title": "Wählen Sie aus, in welcher Kategorie Sie benachrichtigt werden möchten", "schedule": { "daily": "Tägliche Zusammenfassung", "instant": "Sofortig", @@ -1934,6 +1856,13 @@ }, "title": "Benachrichtigungseinstellungen" }, + "notifications": { + "button-text": "Notifications", + "deleted-dossier": "Deleted Dossier", + "label": "Benachrichtigungen", + "mark-all-as-read": "Alle als gelesen markieren", + "mark-as": "Mark as {type, select, read{read} unread{unread} other{}}" + }, "ocr": { "confirmation-dialog": { "cancel": "Cancel", @@ -2025,16 +1954,16 @@ "warnings-subtitle": "Do not show again options", "warnings-title": "Prompts and Dialogs Settings" }, - "processing": { - "basic": "Processing", - "ocr": "OCR" - }, "processing-status": { "ocr": "OCR", "pending": "Pending", "processed": "Processed", "processing": "Processing" }, + "processing": { + "basic": "Processing", + "ocr": "OCR" + }, "readonly": "Lesemodus", "readonly-archived": "Read only (archived)", "redact-text": { @@ -2264,12 +2193,6 @@ "red-user-admin": "Benutzer-Admin", "regular": "Regulär" }, - "search": { - "active-dossiers": "ganze Plattform", - "all-dossiers": "all documents", - "placeholder": "Nach Dokumenten oder Dokumenteninhalt suchen", - "this-dossier": "in diesem Dossier" - }, "search-screen": { "cols": { "assignee": "Bevollmächtigter", @@ -2293,6 +2216,12 @@ "no-match": "Keine Dokumente entsprechen Ihren aktuellen Filtern.", "table-header": "{length} {length, plural, one{Suchergebnis} other{Suchergebnisse}}" }, + "search": { + "active-dossiers": "ganze Plattform", + "all-dossiers": "all documents", + "placeholder": "Nach Dokumenten oder Dokumenteninhalt suchen", + "this-dossier": "in diesem Dossier" + }, "seconds": "seconds", "size": "Size", "smtp-auth-config": { @@ -2379,16 +2308,6 @@ } }, "type": "Typ", - "unapproved-suggestions": { - "confirmation-dialog": { - "checkbox-text": "Do not show this message again", - "confirmation-text": "Continue to Preview", - "deny-text": "Cancel", - "not-displayed-question": "The document contains unapproved suggestions that are not included in the preview.", - "success-confirmation-text": "Prompts about unapproved suggestions were disabled. Change this preference in account settings.", - "title": "Document with unapproved suggestions" - } - }, "unknown": "Unbekannt", "update-profile": { "errors": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 5714e28ab..52c1ed2f8 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -56,8 +56,7 @@ }, "add-edit-clone-dossier-template": { "error": { - "conflict": "Failed to create dossier template: a dossier template with the same name already exists.", - "generic": "Failed to create dossier template." + "conflict": "Failed to create dossier template: a dossier template with the same name already exists." }, "form": { "apply-updates-default": { @@ -280,26 +279,10 @@ "error": "Failed to add entry to dictionary: {error}", "success": "Entry added to dictionary. Changes will be visible after reanalysis." }, - "approve": { - "error": "Failed to approve dictionary entry: {error}", - "success": "Dictionary entry approved. Changes will be visible after reanalysis." - }, - "decline": { - "error": "Failed to decline dictionary suggestion: {error}", - "success": "Dictionary suggestion declined." - }, "remove": { "error": "Failed to remove dictionary entry: {error}", "success": "Dictionary entry removed!" }, - "request-remove": { - "error": "Failed to request removal of dictionary entry: {error}", - "success": "Requested to remove dictionary entry!" - }, - "suggest": { - "error": "Failed to save suggestion for dictionary modification: {error}", - "success": "Suggestion for dictionary modification saved!" - }, "undo": { "error": "Failed to undo: {error}", "success": "Undo successful" @@ -310,10 +293,6 @@ "error": "Failed to save redaction: {error}", "success": "Redaction added!" }, - "approve": { - "error": "Failed to approve suggestion: {error}", - "success": "Suggestion approved." - }, "change-legal-basis": { "error": "Failed to edit annotation reason: {error}", "success": "Annotation reason was edited." @@ -322,10 +301,6 @@ "error": "Failed to edit type: {error}", "success": "Type was edited." }, - "decline": { - "error": "Failed to decline suggestion: {error}", - "success": "Suggestion declined." - }, "force-hint": { "error": "Failed to save hint: {error}", "success": "Hint added!" @@ -346,34 +321,6 @@ "error": "Failed to remove redaction: {error}", "success": "Redaction removed!" }, - "request-change-legal-basis": { - "error": "Failed to request annotation reason change: {error}", - "success": "Annotation reason change requested." - }, - "request-force-hint": { - "error": "Failed to save hint suggestion: {error}", - "success": "Hint suggestion saved" - }, - "request-force-redaction": { - "error": "Failed to save redaction suggestion: {error}", - "success": "Redaction suggestion saved" - }, - "request-image-recategorization": { - "error": "Failed to request image recategorization: {error}", - "success": "Image recategorization requested." - }, - "request-remove-hint": { - "error": "Failed to request removal of hint: {error}", - "success": "Requested to remove hint!" - }, - "request-remove": { - "error": "Failed to request removal of redaction: {error}", - "success": "Requested to remove redaction!" - }, - "suggest": { - "error": "Failed to save redaction suggestion: {error}", - "success": "Redaction suggestion saved" - }, "undo": { "error": "Failed to undo: {error}", "success": "Undo successful" @@ -416,7 +363,6 @@ "rule": "Redaction based on rule {rule}" }, "annotation-type": { - "declined-suggestion": "Declined Suggestion", "hint": "Hint", "ignored-hint": "Ignored Hint", "manual-hint": "Manual Hint", @@ -424,16 +370,7 @@ "recommendation": "Recommendation", "redaction": "Redaction", "skipped": "Skipped", - "suggestion-add": "Suggested redaction", - "suggestion-add-dictionary": "Suggested add to Dictionary", "suggestion-add-false-positive": "Suggested add to false positive", - "suggestion-change-legal-basis": "Suggested change legal basis", - "suggestion-force-hint": "Suggestion force hint", - "suggestion-force-redaction": "Suggestion force redaction", - "suggestion-recategorize-image": "Suggested recategorize image", - "suggestion-remove": "Suggested local removal", - "suggestion-remove-dictionary": "Suggested dictionary removal", - "suggestion-resize": "Suggested Resize", "text-highlight": "Earmark" }, "annotation": { @@ -1601,7 +1538,6 @@ "image": "Images", "none": "No Annotations", "redaction": "Redacted", - "suggestion": "Suggested Redaction", "updated": "Updated" }, "filters": { @@ -2372,16 +2308,6 @@ } }, "type": "Type", - "unapproved-suggestions": { - "confirmation-dialog": { - "checkbox-text": "Do not show this message again", - "confirmation-text": "Continue to Preview", - "deny-text": "Cancel", - "not-displayed-question": "The document contains unapproved suggestions that are not included in the preview.", - "success-confirmation-text": "Prompts about unapproved suggestions were disabled. Change this preference in account settings.", - "title": "Document with unapproved suggestions" - } - }, "unknown": "Unknown", "update-profile": { "errors": { @@ -2545,12 +2471,5 @@ "select": "Select" } }, - "yesterday": "Yesterday", - "generic-errors": { - "400": "The sent request is not valid.", - "403": "Access to the requested resource is not allowed.", - "404": "The requested resource could not be found.", - "409": "The request is incompatible with the current state.", - "500": "The server encountered an unexpected condition that prevented it from fulfilling the request." - } + "yesterday": "Yesterday" } diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index dc15fc295..dd5a5e771 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -56,8 +56,7 @@ }, "add-edit-clone-dossier-template": { "error": { - "conflict": "Dossiervorlage konnte nicht erstellt werden: Es existiert bereits eine Dossiervorlage mit demselben Namen.", - "generic": "Fehler beim Erstellen der Dossiervorlage." + "conflict": "Dossiervorlage konnte nicht erstellt werden: Es existiert bereits eine Dossiervorlage mit demselben Namen." }, "form": { "apply-updates-default": { @@ -280,26 +279,10 @@ "error": "Fehler beim Hinzufügen des neuen Wörterbucheintrags: {error}", "success": "Eintrag zum Wörterbuch hinzugefügt. Änderungen nach der Reanalyse sichtbar." }, - "approve": { - "error": "Fehler beim Genehmigen des Wörterbucheintrags: {error}", - "success": "Neuer Wörterbucheintrag wurde genehmigt. Änderungen sind nach der Reanalyse sichtbar." - }, - "decline": { - "error": "Fehler beim Ablehnen des neuen Wörterbucheintrags: {error}", - "success": "Vorschlag für das Wörterbuch abgelehnt." - }, "remove": { "error": "Fehler beim Entfernen des Wörterbucheintrags: {error}", "success": "Wörterbucheintrag wurde gelöscht!" }, - "request-remove": { - "error": "Dossier-Vorlage", - "success": "Löschung des Wörterbucheintrags wurde vorgeschlagen!" - }, - "suggest": { - "error": "Vorschlag für Änderung des Wörterbuchs konnte nicht gespeichert werden: {error}", - "success": "Vorschlag für die Änderung des Wörterbuchs gespeichert!" - }, "undo": { "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", "success": "Rückgängigmachen erfolgreich" @@ -310,10 +293,6 @@ "error": "Fehler beim Speichern der Schwärzung: {error}", "success": "Schwärzung hinzugefügt!" }, - "approve": { - "error": "Fehler beim Genehmigen des Vorschlags: {error}", - "success": "Vorschlag genehmigt" - }, "change-legal-basis": { "error": "Fehler beim Bearbeiten der in der Anmerkung genannten Begründung: {error}", "success": "In der Anmerkung genannte Begründung wurde bearbeitet." @@ -322,10 +301,6 @@ "error": "", "success": "" }, - "decline": { - "error": "Fehler beim Ablehnen des Vorschlags: {error}", - "success": "Vorschlag abgelehnt" - }, "force-hint": { "error": "", "success": "" @@ -346,34 +321,6 @@ "error": "Fehler beim Entfernen der Schwärzung: {error}", "success": "Schwärzung entfernt!" }, - "request-change-legal-basis": { - "error": "Fehler beim Vorschlagen der Änderung der Begründung:", - "success": "Die Änderung der in der Anmerkung genannten Begründung wurde beantragt." - }, - "request-force-hint": { - "error": "", - "success": "" - }, - "request-force-redaction": { - "error": "Fehler beim Speichern des Schwärzungsvorschlags: {error}", - "success": "Vorschlag einer Schwärzung gespeichert" - }, - "request-image-recategorization": { - "error": "Fehler beim Vorschlagen der Neukategorisierung des Bilds: {error}", - "success": "Bild-Neuklassifizierung angefordert." - }, - "request-remove-hint": { - "error": "", - "success": "" - }, - "request-remove": { - "error": "Fehler beim Erstellen des Vorschlags für das Entfernen der Schwärzung: {error}", - "success": "Entfernen der Schwärzung wurde vorgeschlagen!" - }, - "suggest": { - "error": "Vorschlag einer Schwärzung wurde nicht gespeichert: {error}", - "success": "Vorschlag einer Schwärzung gespeichert" - }, "undo": { "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", "success": "erfolgreich Rückgängig gemacht" @@ -416,7 +363,6 @@ "rule": "Schwärzung basierend auf Regel {rule}" }, "annotation-type": { - "declined-suggestion": "Abgelehnter Vorschlag", "hint": "Hinweis", "ignored-hint": "Ignorierter Hinweis", "manual-hint": "", @@ -424,16 +370,7 @@ "recommendation": "Empfehlung", "redaction": "Schwärzung", "skipped": "Übersprungen", - "suggestion-add": "Vorschlag für Schwärzung", - "suggestion-add-dictionary": "Vorschlag für neuen Wörterbucheintrag", "suggestion-add-false-positive": "", - "suggestion-change-legal-basis": "Vorschlag für Änderung der Rechtsgrundlage", - "suggestion-force-hint": "", - "suggestion-force-redaction": "Vorschlag für erzwungene Schwärzung", - "suggestion-recategorize-image": "Vorschlag für Rekategorisierung eines Bilds", - "suggestion-remove": "Vorschlagen, die Schwärzung zu entfernen", - "suggestion-remove-dictionary": "Vorschlag für Löschung eines Wörterbucheintrags", - "suggestion-resize": "Vorgeschlagene Größenänderung", "text-highlight": "" }, "annotation": { @@ -1601,7 +1538,6 @@ "image": "Bilder", "none": "Keine Anmerkungen", "redaction": "Geschwärzt", - "suggestion": "Vorgeschlagene Schwärzung", "updated": "Aktualisiert" }, "filters": { @@ -2372,16 +2308,6 @@ } }, "type": "Typ", - "unapproved-suggestions": { - "confirmation-dialog": { - "checkbox-text": "", - "confirmation-text": "", - "deny-text": "", - "not-displayed-question": "", - "success-confirmation-text": "", - "title": "" - } - }, "unknown": "Unbekannt", "update-profile": { "errors": { @@ -2545,12 +2471,5 @@ "select": "Wählen" } }, - "yesterday": "Gestern", - "generic-errors": { - "400": "", - "403": "", - "404": "", - "409": "", - "500": "" - } + "yesterday": "Gestern" } diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 97a19f6b2..5bedda4dc 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -56,8 +56,7 @@ }, "add-edit-clone-dossier-template": { "error": { - "conflict": "Failed to create dossier template: a dossier template with the same name already exists.", - "generic": "Failed to create dossier template." + "conflict": "Failed to create dossier template: a dossier template with the same name already exists." }, "form": { "apply-updates-default": { @@ -280,26 +279,10 @@ "error": "Failed to add entry to dictionary: {error}", "success": "Entry added to dictionary. Changes will be visible after reanalysis." }, - "approve": { - "error": "Failed to approve dictionary entry: {error}", - "success": "Dictionary entry approved. Changes will be visible after reanalysis." - }, - "decline": { - "error": "Failed to decline dictionary suggestion: {error}", - "success": "Dictionary suggestion declined." - }, "remove": { "error": "Failed to remove dictionary entry: {error}", "success": "Dictionary entry removed!" }, - "request-remove": { - "error": "Failed to request removal of dictionary entry: {error}", - "success": "Requested to remove dictionary entry!" - }, - "suggest": { - "error": "Failed to save suggestion for dictionary modification: {error}", - "success": "Suggestion for dictionary modification saved!" - }, "undo": { "error": "Failed to undo: {error}", "success": "Undo successful" @@ -310,10 +293,6 @@ "error": "Failed to save annotation: {error}", "success": "Annotation added!" }, - "approve": { - "error": "Failed to approve suggestion: {error}", - "success": "Suggestion approved." - }, "change-legal-basis": { "error": "Failed to edit annotation reason: {error}", "success": "Annotation reason was edited." @@ -322,10 +301,6 @@ "error": "", "success": "" }, - "decline": { - "error": "Failed to decline suggestion: {error}", - "success": "Suggestion declined." - }, "force-hint": { "error": "Failed to save hint: {error}", "success": "Hint added!" @@ -346,34 +321,6 @@ "error": "Failed to remove annotation: {error}", "success": "Annotation removed!" }, - "request-change-legal-basis": { - "error": "Failed to request annotation reason change: {error}", - "success": "Annotation reason change requested." - }, - "request-force-hint": { - "error": "Failed to save hint suggestion: {error}", - "success": "Hint suggestion saved" - }, - "request-force-redaction": { - "error": "Failed to save annotation suggestion: {error}", - "success": "Annotation suggestion saved" - }, - "request-image-recategorization": { - "error": "Failed to request image recategorization: {error}", - "success": "Image recategorization requested." - }, - "request-remove-hint": { - "error": "Failed to request removal of hint: {error}", - "success": "Requested to remove hint!" - }, - "request-remove": { - "error": "Failed to request removal of annotation: {error}", - "success": "Requested to remove annotation!" - }, - "suggest": { - "error": "Failed to save annotation suggestion: {error}", - "success": "Annotation suggestion saved" - }, "undo": { "error": "Failed to undo: {error}", "success": "Undo successful" @@ -416,7 +363,6 @@ "rule": "Annotation based on rule {rule}" }, "annotation-type": { - "declined-suggestion": "Declined Suggestion", "hint": "Hint", "ignored-hint": "Ignored Hint", "manual-hint": "Manual Hint", @@ -424,16 +370,7 @@ "recommendation": "Recommendation", "redaction": "Annotation", "skipped": "Skipped", - "suggestion-add": "Suggested annotation", - "suggestion-add-dictionary": "Suggested add to Dictionary", "suggestion-add-false-positive": "Suggested add to false positive", - "suggestion-change-legal-basis": "Suggested change legal basis", - "suggestion-force-hint": "Suggestion force hint", - "suggestion-force-redaction": "Suggestion force Annotation", - "suggestion-recategorize-image": "Suggested recategorize image", - "suggestion-remove": "Suggested local removal", - "suggestion-remove-dictionary": "Suggested dictionary removal", - "suggestion-resize": "Suggested Resize", "text-highlight": "Earmark" }, "annotation": { @@ -1508,7 +1445,7 @@ "redacted": "Preview", "redacted-tooltip": "Component preview shows only annotations. Consider this a preview for the final version. This view is only available if the file has no pending changes & doesn't require a reanalysis", "standard": "Standard", - "standard-tooltip": "Standard Workload view shows all hints, annotations, recommendations & suggestions. This view allows editing.", + "standard-tooltip": "Standard Workload view shows all hints, annotations & recommendations. This view allows editing.", "tabs": { "annotations": { "jump-to-next": "Jump to Next", @@ -1601,7 +1538,6 @@ "image": "Images", "none": "No Annotations", "redaction": "Annotations", - "suggestion": "Suggested Annotation", "updated": "Updated" }, "filters": { @@ -2372,16 +2308,6 @@ } }, "type": "Type", - "unapproved-suggestions": { - "confirmation-dialog": { - "checkbox-text": "Do not show this message again", - "confirmation-text": "Continue to Preview", - "deny-text": "Cancel", - "not-displayed-question": "The document contains unapproved suggestions that are not included in the preview.", - "success-confirmation-text": "Prompts about unapproved suggestions were disabled. Change this preference in account settings.", - "title": "Document with unapproved suggestions" - } - }, "unknown": "Unknown", "update-profile": { "errors": { @@ -2545,12 +2471,5 @@ "select": "Select" } }, - "yesterday": "Yesterday", - "generic-errors": { - "400": "The sent request is not valid.", - "403": "Access to the requested resource is not allowed.", - "404": "The requested resource could not be found.", - "409": "The request is incompatible with the current state.", - "500": "The server encountered an unexpected condition that prevented it from fulfilling the request." - } + "yesterday": "Yesterday" } diff --git a/libs/red-domain/src/lib/annotations/types.ts b/libs/red-domain/src/lib/annotations/types.ts index 068a256ed..b9c5f79b0 100644 --- a/libs/red-domain/src/lib/annotations/types.ts +++ b/libs/red-domain/src/lib/annotations/types.ts @@ -1,25 +1,16 @@ export type ImageCategory = 'signature' | 'logo' | 'formula' | 'image'; -export type DictionaryActions = 'add' | 'approve' | 'remove' | 'decline' | 'request-remove' | 'suggest' | 'undo'; +export type DictionaryActions = 'add' | 'remove' | 'undo'; export type ManualRedactionActions = | 'add' - | 'approve' | 'remove' | 'remove-hint' | 'change-legal-basis' - | 'decline' - | 'request-remove' - | 'request-remove-hint' - | 'request-change-legal-basis' | 'recategorize-image' - | 'request-image-recategorization' - | 'suggest' | 'undo' | 'force-redaction' | 'force-hint' - | 'request-force-redaction' - | 'request-force-hint' | 'change-type'; export const AnnotationIconTypes = { @@ -36,7 +27,6 @@ export const AnnotationShapeMap: Record = { analysis: AnnotationIconTypes.square, hint: AnnotationIconTypes.circle, redaction: AnnotationIconTypes.square, - suggestion: AnnotationIconTypes.rhombus, updated: AnnotationIconTypes.square, image: AnnotationIconTypes.square, none: AnnotationIconTypes.none, diff --git a/libs/red-domain/src/lib/colors/annotation-color-config.ts b/libs/red-domain/src/lib/colors/annotation-color-config.ts index 55b0f087c..449a09075 100644 --- a/libs/red-domain/src/lib/colors/annotation-color-config.ts +++ b/libs/red-domain/src/lib/colors/annotation-color-config.ts @@ -1,22 +1,11 @@ -import { DefaultColorType } from './default-color-type'; import { SuperType, SuperTypes } from '../files'; +import { DefaultColorType } from './default-color-type'; -export type DefaultBasedColorType = SuperType | 'updated' | 'suggestion' | 'analysis'; +export type DefaultBasedColorType = SuperType | 'updated' | 'analysis'; export const annotationDefaultColorConfig: Record = { [SuperTypes.TextHighlight]: 'redactionColor', // not actually used - [SuperTypes.SuggestionChangeLegalBasis]: 'requestAddColor', - [SuperTypes.SuggestionRecategorizeImage]: 'requestAddColor', - [SuperTypes.SuggestionAddDictionary]: 'dictionaryRequestColor', - [SuperTypes.SuggestionForceRedaction]: 'requestAddColor', - [SuperTypes.SuggestionForceHint]: 'requestAddColor', - [SuperTypes.SuggestionResize]: 'dictionaryRequestColor', - [SuperTypes.SuggestionRemoveDictionary]: 'dictionaryRequestColor', - [SuperTypes.SuggestionAdd]: 'requestAddColor', - [SuperTypes.SuggestionRemove]: 'requestRemoveColor', - [SuperTypes.DeclinedSuggestion]: 'skippedColor', - [SuperTypes.IgnoredHint]: 'ignoredHintColor', [SuperTypes.Skipped]: 'skippedColor', [SuperTypes.Redaction]: 'redactionColor', @@ -25,7 +14,6 @@ export const annotationDefaultColorConfig: Record implements IFile { readonly added?: string; @@ -51,7 +51,6 @@ export class File extends Entity implements IFile { readonly rulesVersion?: number; readonly uploader?: string; readonly excludedPages: number[]; - readonly hasSuggestions: boolean; readonly processingStatus: ProcessingFileStatus; readonly workflowStatus: WorkflowFileStatus; readonly fileManipulationDate: string; @@ -83,7 +82,10 @@ export class File extends Entity implements IFile { readonly processingType: ProcessingType; - constructor(file: IFile, readonly reviewerName: string) { + constructor( + file: IFile, + readonly reviewerName: string, + ) { super(file); this.added = file.added; this.allManualRedactionsApplied = !!file.allManualRedactionsApplied; @@ -122,7 +124,6 @@ export class File extends Entity implements IFile { this.rulesVersion = file.rulesVersion; this.uploader = file.uploader; this.excludedPages = file.excludedPages || []; - this.hasSuggestions = !!file.hasSuggestions; this.fileManipulationDate = file.fileManipulationDate ?? ''; this.redactionModificationDate = file.redactionModificationDate ?? ''; this.lastManualChangeDate = file.lastManualChangeDate; @@ -135,7 +136,7 @@ export class File extends Entity implements IFile { this.statusSort = StatusSorter[this.workflowStatus]; this.cacheIdentifier = btoa(`${this.fileManipulationDate}${file.lastOCRTime}${file.ocrEndTime}${file.lastLayoutProcessed}`); this.hintsOnly = this.hasHints && !this.hasRedactions; - this.hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions; + this.hasNone = !this.hasRedactions && !this.hasHints; this.isProcessing = isProcessingStatuses.includes(this.processingStatus); this.isFullProcessing = isFullProcessingStatuses.includes(this.processingStatus); this.isOcrProcessing = this.processingStatus === ProcessingFileStatuses.OCR_PROCESSING; @@ -144,7 +145,7 @@ export class File extends Entity implements IFile { this.isNew = this.workflowStatus === WorkflowFileStatuses.NEW; this.isUnderReview = this.workflowStatus === WorkflowFileStatuses.UNDER_REVIEW; this.isUnderApproval = this.workflowStatus === WorkflowFileStatuses.UNDER_APPROVAL; - this.canBeApproved = !this.hasSuggestions && !this.isProcessing && !this.isError; + this.canBeApproved = !this.isProcessing && !this.isError; this.canBeOpened = (!this.isError && !this.isUnprocessed && this.numberOfAnalyses > 0) || this.excluded; this.canBeOCRed = !this.excluded && diff --git a/libs/red-domain/src/lib/files/file.ts b/libs/red-domain/src/lib/files/file.ts index 083bc5c8a..1a06145ea 100644 --- a/libs/red-domain/src/lib/files/file.ts +++ b/libs/red-domain/src/lib/files/file.ts @@ -1,8 +1,8 @@ /** * Object containing information on a specific file. */ -import { ProcessingFileStatus, WorkflowFileStatus } from './types'; import { FileAttributes } from '../file-attributes'; +import { ProcessingFileStatus, WorkflowFileStatus } from './types'; export interface IFile { /** @@ -56,7 +56,6 @@ export interface IFile { * Shows if any requests were found during the analysis. */ readonly hasRequests?: boolean; - readonly hasSuggestions?: boolean; /** * Shows if there is any change between the previous and current analysis. */ diff --git a/libs/red-domain/src/lib/files/super-types.ts b/libs/red-domain/src/lib/files/super-types.ts index f8794e157..29a38db2d 100644 --- a/libs/red-domain/src/lib/files/super-types.ts +++ b/libs/red-domain/src/lib/files/super-types.ts @@ -2,16 +2,6 @@ import { ValuesOf } from '@iqser/common-ui/lib/utils'; export const SuperTypes = { TextHighlight: 'text-highlight', - SuggestionChangeLegalBasis: 'suggestion-change-legal-basis', - SuggestionRecategorizeImage: 'suggestion-recategorize-image', - SuggestionAddDictionary: 'suggestion-add-dictionary', - SuggestionForceRedaction: 'suggestion-force-redaction', - SuggestionForceHint: 'suggestion-force-hint', - SuggestionResize: 'suggestion-resize', - SuggestionRemoveDictionary: 'suggestion-remove-dictionary', - SuggestionAdd: 'suggestion-add', - SuggestionRemove: 'suggestion-remove', - DeclinedSuggestion: 'suggestion-declined', IgnoredHint: 'hint-ignored', Skipped: 'skipped', Redaction: 'redaction', @@ -36,27 +26,3 @@ export const FalsePositiveSuperTypes = { [SuperTypes.IgnoredHint]: true, [SuperTypes.Skipped]: true, } as const; - -export const SuggestionAddSuperTypes = { - [SuperTypes.SuggestionAdd]: true, - [SuperTypes.SuggestionAddDictionary]: true, - [SuperTypes.SuggestionForceRedaction]: true, - [SuperTypes.SuggestionForceHint]: true, -} as const; - -export const SuggestionRemoveSuperTypes = { - [SuperTypes.SuggestionRemove]: true, - [SuperTypes.SuggestionRemoveDictionary]: true, -} as const; - -export const SuggestionsSuperTypes = { - [SuperTypes.SuggestionAdd]: true, - [SuperTypes.SuggestionAddDictionary]: true, - [SuperTypes.SuggestionForceRedaction]: true, - [SuperTypes.SuggestionForceHint]: true, - [SuperTypes.SuggestionChangeLegalBasis]: true, - [SuperTypes.SuggestionRecategorizeImage]: true, - [SuperTypes.SuggestionRemove]: true, - [SuperTypes.SuggestionRemoveDictionary]: true, - [SuperTypes.SuggestionResize]: true, -} as const; diff --git a/libs/red-domain/src/lib/redaction-log/types.ts b/libs/red-domain/src/lib/redaction-log/types.ts index 41116c670..ff114eff4 100644 --- a/libs/red-domain/src/lib/redaction-log/types.ts +++ b/libs/red-domain/src/lib/redaction-log/types.ts @@ -25,7 +25,6 @@ export type ManualRedactionType = ValuesOf; export const LogEntryStatuses = { APPROVED: 'APPROVED', DECLINED: 'DECLINED', - REQUESTED: 'REQUESTED', } as const; export type LogEntryStatus = ValuesOf; From d31d57a2ca2fd8b7ea88946f2ccb31a6f3427e7a Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Thu, 26 Oct 2023 12:47:12 +0300 Subject: [PATCH 04/10] RED-7619 remove other useless stuff --- .../src/app/models/file/annotation.wrapper.ts | 128 ++++++------------ .../annotation-card.component.html | 2 +- .../annotation-details.component.ts | 8 +- .../change-legal-basis-dialog.component.ts | 10 +- .../edit-annotation-dialog.component.ts | 10 +- .../edit-redaction-dialog.component.ts | 2 +- .../remove-redaction-dialog.component.ts | 4 +- .../resize-redaction-dialog.component.html | 4 +- .../services/annotation-actions.service.ts | 4 +- .../services/pdf-proxy.service.ts | 2 +- .../file-preview/utils/dialog-options.ts | 4 +- .../services/annotation-draw.service.ts | 1 - .../annotation-types-translations.ts | 5 +- apps/red-ui/src/assets/i18n/redact/de.json | 1 - apps/red-ui/src/assets/i18n/redact/en.json | 1 - apps/red-ui/src/assets/i18n/scm/de.json | 1 - apps/red-ui/src/assets/i18n/scm/en.json | 1 - .../src/lib/dictionaries/dictionary.model.ts | 9 +- .../src/lib/redaction-log/entry-types.ts | 1 + 19 files changed, 77 insertions(+), 121 deletions(-) diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index da0afdd50..a4807fed9 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -24,7 +24,7 @@ import { SuperType, SuperTypes, } from '@red/domain'; -import { annotationTypesTranslations, SuggestionAddFalsePositive } from '@translations/annotation-types-translations'; +import { annotationTypesTranslations } from '@translations/annotation-types-translations'; import { chronologicallyBy, timestampOf } from '../../modules/file-preview/services/file-data.service'; export class AnnotationWrapper implements IListable { @@ -32,7 +32,6 @@ export class AnnotationWrapper implements IListable { superType: SuperType; typeValue: string; - recategorizationType: string; color: string; entity: Dictionary; comments: IComment[] = []; @@ -43,19 +42,20 @@ export class AnnotationWrapper implements IListable { value: string; typeLabel: string; pageNumber: number; - hint: boolean; - redaction: boolean; + HINT = false; + redaction = false; status: string; - dictionaryOperation: boolean; + dictionaryOperation = false; positions: IRectangle[]; recommendationType: string; legalBasisValue: string; - rectangle?: boolean; + // AREA === rectangle + AREA = false; section?: string; reference: string[]; - imported?: boolean; - image?: boolean; - manual?: boolean; + imported = false; + IMAGE = false; + manual = false; pending = false; hintDictionary = false; textAfter?: string; @@ -106,11 +106,7 @@ export class AnnotationWrapper implements IListable { } get isImage() { - return this.type?.toLowerCase() === 'image' || this.image; - } - - get isNotSignatureImage() { - return this.isImage && this.recategorizationType === 'signature'; + return this.type?.toLowerCase() === 'image' || this.IMAGE; } get isOCR() { @@ -118,7 +114,7 @@ export class AnnotationWrapper implements IListable { } get type() { - return this.recategorizationType || this.typeValue; + return this.typeValue; } get topLevelFilter() { @@ -243,7 +239,7 @@ export class AnnotationWrapper implements IListable { annotationWrapper.changeLogType = changeLogType; annotationWrapper.legalBasisList = legalBasisList; annotationWrapper.redaction = logEntry.entryType === EntryTypes.ENTITY; - annotationWrapper.hint = logEntry.entryType === EntryTypes.HINT; + 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] }; @@ -257,7 +253,7 @@ export class AnnotationWrapper implements IListable { annotationWrapper.textBefore = logEntry.textBefore; annotationWrapper.textAfter = logEntry.textAfter; annotationWrapper.dictionaryOperation = logEntry.dictionaryEntry; - annotationWrapper.image = logEntry.entryType === EntryTypes.IMAGE; + annotationWrapper.IMAGE = logEntry.entryType === EntryTypes.IMAGE; annotationWrapper.imported = logEntry.imported; annotationWrapper.legalBasisValue = logEntry.legalBasis; annotationWrapper.comments = []; //logEntry.comments || []; @@ -265,7 +261,7 @@ export class AnnotationWrapper implements IListable { annotationWrapper.engines = logEntry.engines; annotationWrapper.section = logEntry.section; annotationWrapper.reference = logEntry.reference || []; - annotationWrapper.rectangle = logEntry.entryType === EntryTypes.AREA; + annotationWrapper.AREA = logEntry.entryType === EntryTypes.AREA; annotationWrapper.hintDictionary = hintDictionary; annotationWrapper.hasBeenResized = !!logEntry.manualChanges?.find( c => c.manualRedactionType === ManualRedactionTypes.RESIZE && c.annotationStatus === LogEntryStatuses.APPROVED, @@ -289,7 +285,7 @@ export class AnnotationWrapper implements IListable { this.#createContent(annotationWrapper, logEntry, isDocumine); this.#setSuperType(annotationWrapper, logEntry); this.#handleRecommendations(annotationWrapper, logEntry); - annotationWrapper.typeLabel = this.#getTypeLabel(logEntry, annotationWrapper); + annotationWrapper.typeLabel = this.#getTypeLabel(annotationWrapper); const entity = dictionaries.find(d => d.type === annotationWrapper.typeValue); annotationWrapper.entity = entity?.virtual ? null : entity; @@ -300,10 +296,7 @@ export class AnnotationWrapper implements IListable { return annotationWrapper; } - static #getTypeLabel(logEntry: IEntityLogEntry, annotation: AnnotationWrapper): string { - if (logEntry.reason?.toLowerCase() === 'false positive') { - return annotationTypesTranslations[SuggestionAddFalsePositive]; - } + static #getTypeLabel(annotation: AnnotationWrapper): string { if (annotation.superType === SuperTypes.ManualRedaction && annotation.hintDictionary) { return _('annotation-type.manual-hint'); } @@ -408,17 +401,9 @@ export class AnnotationWrapper implements IListable { static #selectSuperType(logEntry: IEntityLogEntry, lastManualChange: IManualChange, isHintDictionary: boolean): SuperType { switch (lastManualChange.manualRedactionType) { case ManualRedactionTypes.ADD_LOCALLY: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - return SuperTypes.ManualRedaction; - } - break; + return SuperTypes.ManualRedaction; case ManualRedactionTypes.ADD_TO_DICTIONARY: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - return isHintDictionary ? SuperTypes.Hint : SuperTypes.Redaction; - } - break; + return isHintDictionary ? SuperTypes.Hint : SuperTypes.Redaction; case ManualRedactionTypes.REMOVE_LOCALLY: switch (lastManualChange.annotationStatus) { case LogEntryStatuses.APPROVED: @@ -446,11 +431,7 @@ export class AnnotationWrapper implements IListable { return SuperTypes.Redaction; } } - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - case LogEntryStatuses.DECLINED: - return SuperTypes.Redaction; - } + return SuperTypes.Redaction; } if (lastManualChange.processed) { @@ -462,12 +443,7 @@ export class AnnotationWrapper implements IListable { } } - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - case LogEntryStatuses.DECLINED: - return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped; - } - break; + return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped; case ManualRedactionTypes.FORCE_REDACT: switch (lastManualChange.annotationStatus) { case LogEntryStatuses.APPROVED: @@ -485,50 +461,34 @@ export class AnnotationWrapper implements IListable { } break; case ManualRedactionTypes.RECATEGORIZE: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - case LogEntryStatuses.DECLINED: { - if (logEntry.entryType === EntryTypes.RECOMMENDATION) { - return SuperTypes.Recommendation; - } - - if (logEntry.entryType === EntryTypes.ENTITY) { - return SuperTypes.Redaction; - } - - if (logEntry.entryType === EntryTypes.HINT) { - return SuperTypes.Hint; - } - - return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; - } + if (logEntry.entryType === EntryTypes.RECOMMENDATION) { + return SuperTypes.Recommendation; } - break; + + if (logEntry.entryType === EntryTypes.ENTITY) { + return SuperTypes.Redaction; + } + + if (logEntry.entryType === EntryTypes.HINT) { + return SuperTypes.Hint; + } + + return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; case ManualRedactionTypes.LEGAL_BASIS_CHANGE: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - case LogEntryStatuses.DECLINED: - return logEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction; - } - break; + return logEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction; case ManualRedactionTypes.RESIZE: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - case LogEntryStatuses.DECLINED: - if (logEntry.entryType === EntryTypes.RECOMMENDATION) { - return SuperTypes.Recommendation; - } - - 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; + if (logEntry.entryType === EntryTypes.RECOMMENDATION) { + return SuperTypes.Recommendation; } - break; + + 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; } } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index 920c5d427..1b5004da6 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -20,7 +20,7 @@ {{ annotation.descriptor | translate }}:
- {{ annotation.recategorizationType ?? annotation.entity.label }} + {{ annotation.entity.label }}
acc && a.rectangle, true); + return this._data.annotations.reduce((acc, a) => acc && a.AREA, true); } async ngOnInit() { diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts index 598e79cb3..d70a3e4cf 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/edit-annotation-dialog/edit-annotation-dialog.component.ts @@ -1,11 +1,11 @@ import { Component, OnInit } from '@angular/core'; +import { FormBuilder, UntypedFormGroup } from '@angular/forms'; import { IconButtonTypes, IqserDialogComponent, IqserPermissionsService } from '@iqser/common-ui'; import { Dictionary, Dossier, SuperTypes } from '@red/domain'; -import { FormBuilder, UntypedFormGroup } from '@angular/forms'; -import { Roles } from '@users/roles'; -import { JustificationsService } from '@services/entity-services/justifications.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; +import { JustificationsService } from '@services/entity-services/justifications.service'; +import { Roles } from '@users/roles'; import { EditRedactionData, EditRedactResult } from '../../../utils/dialog-types'; @Component({ @@ -16,12 +16,12 @@ export class EditAnnotationDialogComponent extends IqserDialogComponent implements OnInit { + readonly #dossier: Dossier; readonly roles = Roles; readonly iconButtonTypes = IconButtonTypes; readonly redactedTexts: string[]; dictionaries: Dictionary[] = []; form: UntypedFormGroup; - readonly #dossier: Dossier; constructor( private readonly _justificationsService: JustificationsService, @@ -79,6 +79,6 @@ export class EditAnnotationDialogComponent } #allRectangles() { - return this.data.annotations.reduce((acc, a) => acc && a.rectangle, true); + return this.data.annotations.reduce((acc, a) => acc && a.AREA, true); } } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/edit-redaction-dialog/edit-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/edit-redaction-dialog/edit-redaction-dialog.component.ts index 5c7270793..c9e1733b7 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/edit-redaction-dialog/edit-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/edit-redaction-dialog/edit-redaction-dialog.component.ts @@ -27,7 +27,7 @@ export class EditRedactionDialogComponent readonly isImage: boolean; readonly isManualRedaction: boolean; readonly isHint: boolean; - readonly allRectangles = this.data.annotations.reduce((acc, a) => acc && a.rectangle, true); + readonly allRectangles = this.data.annotations.reduce((acc, a) => acc && a.AREA, true); readonly showExtras: boolean; options: DetailsRadioOption[] | undefined; legalOptions: LegalBasisOption[] = []; diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts index c2eb54f67..6c5746a77 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts @@ -15,18 +15,18 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< RemoveRedactionData, RemoveRedactionResult > { + #applyToAllDossiers: boolean; readonly iconButtonTypes = IconButtonTypes; readonly options: DetailsRadioOption[]; readonly recommendation; readonly hint: boolean; readonly redactedTexts: string[]; form!: UntypedFormGroup; - #applyToAllDossiers: boolean; constructor(private readonly _formBuilder: FormBuilder) { super(); this.recommendation = this.data.redactions[0].isRecommendation; - this.hint = this.data.redactions[0].hint; + this.hint = this.data.redactions[0].HINT; this.options = getRemoveRedactionOptions(this.data); this.redactedTexts = this.data.redactions.map(annotation => annotation.value); this.form = this.#getForm(); diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html index 8c7c04d43..20f694aa0 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html @@ -1,12 +1,12 @@
- +
{{ redaction.value }} diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index 33a65fcdd..328f9ae47 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -208,7 +208,7 @@ export class AnnotationActionsService { resize(annotationWrapper: AnnotationWrapper) { this._annotationManager.resizingAnnotationId = annotationWrapper.id; - if (annotationWrapper.rectangle || annotationWrapper.imported || annotationWrapper.isImage) { + if (annotationWrapper.AREA || annotationWrapper.imported || annotationWrapper.isImage) { this._annotationManager.delete(annotationWrapper); const rectangleAnnotation = this.#generateRectangle(annotationWrapper); return this._annotationManager.add(rectangleAnnotation); @@ -236,7 +236,7 @@ export class AnnotationActionsService { const dossier = this._state.dossier(); const isImageText = annotation.isImage ? 'Image' : textAndPositions.text; - const text = annotation.rectangle ? annotation.value : isImageText; + const text = annotation.AREA ? annotation.value : isImageText; const isApprover = this._permissionsService.isApprover(dossier); const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index efc7871cf..4e492a607 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -344,7 +344,7 @@ export class PdfProxyService { } if ( - (wrapper.rectangle || wrapper.isImage || wrapper.imported) && + (wrapper.AREA || wrapper.isImage || wrapper.imported) && annotation.ToolName !== AnnotationToolNames.AnnotationCreateRectangle ) { return; diff --git a/apps/red-ui/src/app/modules/file-preview/utils/dialog-options.ts b/apps/red-ui/src/app/modules/file-preview/utils/dialog-options.ts index dde15aeac..2e53166f2 100644 --- a/apps/red-ui/src/app/modules/file-preview/utils/dialog-options.ts +++ b/apps/red-ui/src/app/modules/file-preview/utils/dialog-options.ts @@ -159,7 +159,7 @@ export const getRemoveRedactionOptions = ( description: isBulk ? translations.ONLY_HERE.descriptionBulk : translations.ONLY_HERE.description, descriptionParams: { value: redactions[0].value, - type: redactions[0].hint ? 'hint' : redactions[0].type, + type: redactions[0].HINT ? 'hint' : redactions[0].type, }, icon: PIN_ICON, value: RemoveRedactionOptions.ONLY_HERE, @@ -169,7 +169,7 @@ export const getRemoveRedactionOptions = ( options.push({ label: isBulk ? translations.IN_DOSSIER.labelBulk : translations.IN_DOSSIER.label, description: isBulk ? translations.IN_DOSSIER.descriptionBulk : translations.IN_DOSSIER.description, - descriptionParams: { value: redactions[0].value, type: redactions[0].hint ? 'hint' : redactions[0].type }, + descriptionParams: { value: redactions[0].value, type: redactions[0].HINT ? 'hint' : redactions[0].type }, icon: FOLDER_ICON, value: RemoveRedactionOptions.IN_DOSSIER, extraOption: !isDocumine diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index cea94509f..85e18bdea 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -165,7 +165,6 @@ export class AnnotationDrawService { annotation.setCustomData('redact-manager', 'true'); annotation.setCustomData('redaction', String(annotationWrapper.previewAnnotation)); annotation.setCustomData('skipped', String(annotationWrapper.isSkipped)); - annotation.setCustomData('notSignatureImage', String(annotationWrapper.isNotSignatureImage)); annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry)); annotation.setCustomData('changeLogRemoved', String(annotationWrapper.isChangeLogRemoved)); annotation.setCustomData('opacity', String(annotation.Opacity)); diff --git a/apps/red-ui/src/app/translations/annotation-types-translations.ts b/apps/red-ui/src/app/translations/annotation-types-translations.ts index 1a1667759..a5a9e370c 100644 --- a/apps/red-ui/src/app/translations/annotation-types-translations.ts +++ b/apps/red-ui/src/app/translations/annotation-types-translations.ts @@ -1,9 +1,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { SuperType, SuperTypes } from '@red/domain'; -export const SuggestionAddFalsePositive = 'suggestion-add-false-positive' as const; - -type TranslationKey = SuperType & typeof SuggestionAddFalsePositive; +type TranslationKey = SuperType; export const annotationTypesTranslations: Record = { [SuperTypes.TextHighlight]: _('annotation-type.text-highlight'), @@ -13,5 +11,4 @@ export const annotationTypesTranslations: Record = { [SuperTypes.Recommendation]: _('annotation-type.recommendation'), [SuperTypes.Redaction]: _('annotation-type.redaction'), [SuperTypes.Skipped]: _('annotation-type.skipped'), - [SuggestionAddFalsePositive]: _('annotation-type.suggestion-add-false-positive'), } as const; diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 139c584d1..c8b2efd8a 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -370,7 +370,6 @@ "recommendation": "Empfehlung", "redaction": "Schwärzung", "skipped": "Übersprungen", - "suggestion-add-false-positive": "Suggested add to false positive", "text-highlight": "Earmark" }, "annotation": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 52c1ed2f8..675a077c9 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -370,7 +370,6 @@ "recommendation": "Recommendation", "redaction": "Redaction", "skipped": "Skipped", - "suggestion-add-false-positive": "Suggested add to false positive", "text-highlight": "Earmark" }, "annotation": { diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index dd5a5e771..374482c65 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -370,7 +370,6 @@ "recommendation": "Empfehlung", "redaction": "Schwärzung", "skipped": "Übersprungen", - "suggestion-add-false-positive": "", "text-highlight": "" }, "annotation": { diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 5bedda4dc..83af62c38 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -370,7 +370,6 @@ "recommendation": "Recommendation", "redaction": "Annotation", "skipped": "Skipped", - "suggestion-add-false-positive": "Suggested add to false positive", "text-highlight": "Earmark" }, "annotation": { diff --git a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts index 9c20bec42..f1d35940c 100644 --- a/libs/red-domain/src/lib/dictionaries/dictionary.model.ts +++ b/libs/red-domain/src/lib/dictionaries/dictionary.model.ts @@ -1,7 +1,7 @@ import { Entity } from '@iqser/common-ui'; -import { IDictionary } from './dictionary'; -import { DICTIONARY_TYPE_KEY_MAP, DictionaryType } from '../redaction-log'; import { List } from '@iqser/common-ui/lib/utils'; +import { DICTIONARY_TYPE_KEY_MAP, DictionaryType } from '../redaction-log'; +import { IDictionary } from './dictionary'; export class Dictionary extends Entity implements IDictionary { readonly addToDictionaryAction: boolean; @@ -24,7 +24,10 @@ export class Dictionary extends Entity implements IDictionary { falsePositiveEntries: List; falseRecommendationEntries: List; - constructor(entity: IDictionary, readonly virtual = false) { + constructor( + entity: IDictionary, + readonly virtual = false, + ) { super(entity); this.addToDictionaryAction = !!entity.addToDictionaryAction; this.caseInsensitive = !!entity.caseInsensitive; diff --git a/libs/red-domain/src/lib/redaction-log/entry-types.ts b/libs/red-domain/src/lib/redaction-log/entry-types.ts index d14b051b4..fdc77d152 100644 --- a/libs/red-domain/src/lib/redaction-log/entry-types.ts +++ b/libs/red-domain/src/lib/redaction-log/entry-types.ts @@ -6,6 +6,7 @@ export const EntryTypes = { FALSE_RECOMMENDATION: 'FALSE_RECOMMENDATION', AREA: 'AREA', IMAGE: 'IMAGE', + IMAGE_HINT: 'IMAGE_HINT', } as const; export type EntryType = (typeof EntryTypes)[keyof typeof EntryTypes]; From e40a975ac353b62e18309dc7e50142b00b2c47d7 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 27 Oct 2023 21:27:50 +0300 Subject: [PATCH 05/10] RED-7619 remove unused dialog --- ...ccept-recommendation-dialog.component.html | 52 ------------ .../accept-recommendation-dialog.component.ts | 83 ------------------- .../file-preview/file-preview.module.ts | 4 +- 3 files changed, 1 insertion(+), 138 deletions(-) delete mode 100644 apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.html delete mode 100644 apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.html deleted file mode 100644 index 2c2099576..000000000 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.html +++ /dev/null @@ -1,52 +0,0 @@ -
- -
- -
-
- -
- {{ - data.annotations.length === 1 - ? format(data.annotations[0].value) - : ('accept-recommendation-dialog.multiple-values' | translate) - }} - -
- - - - - {{ displayedDictionaryLabel }} - - - {{ dictionary.label }} - - - - -
- -
- - -
-
- -
- -
- - - -
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts deleted file mode 100644 index c5b7a91a6..000000000 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Component, inject, Inject, OnInit } from '@angular/core'; -import { Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { BaseDialogComponent } from '@iqser/common-ui'; -import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { Dictionary } from '@red/domain'; -import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; -import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { PermissionsService } from '@services/permissions.service'; -import { acceptRecommendationTranslations } from '@translations/accept-recommendation-translations'; - -export interface AcceptRecommendationData { - readonly annotations: AnnotationWrapper[]; - readonly dossierId: string; -} - -export interface AcceptRecommendationReturnType { - readonly annotations: AnnotationWrapper[]; - readonly comment: string; -} - -@Component({ - templateUrl: './accept-recommendation-dialog.component.html', -}) -export class AcceptRecommendationDialogComponent extends BaseDialogComponent implements OnInit { - readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId); - readonly dialogHeader: string; - possibleDictionaries: Dictionary[] = []; - - constructor( - permissionsService: PermissionsService, - private readonly _dictionaryService: DictionaryService, - protected readonly _dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) readonly data: AcceptRecommendationData, - ) { - super(_dialogRef); - const isDocumentAdmin = permissionsService.isApprover(this.#dossier); - this.dialogHeader = isDocumentAdmin - ? acceptRecommendationTranslations.addToDictionary - : acceptRecommendationTranslations.requestAddToDictionary; - this.form = this._getForm(); - this.initialFormValue = this.form.getRawValue(); - } - - get displayedDictionaryLabel() { - const dictType = this.form.get('dictionary').value as string; - if (dictType && this.possibleDictionaries.length) { - return this.possibleDictionaries.find(d => d.type === dictType)?.label; - } - return null; - } - - async ngOnInit() { - this.possibleDictionaries = await this._dictionaryService.getDictionariesOptions(this.#dossier.dossierTemplateId, this.#dossier.id); - this.form.patchValue({ - dictionary: this.possibleDictionaries.find(dict => dict.type === this.data.annotations[0].recommendationType)?.type, - }); - } - - save() { - const recommendationType = this.form.get('dictionary').value; - this.data.annotations.forEach(a => (a.recommendationType = recommendationType)); - this._dialogRef.close({ - annotations: this.data.annotations, - comment: this.form.get('comment').value as string, - }); - } - - format(value: string) { - return value.replace( - // eslint-disable-next-line no-control-regex,max-len - /([^\s\d-]{2,})[-\u00AD]\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]/gi, - '$1', - ); - } - - private _getForm() { - return this._formBuilder.group({ - dictionary: [Validators.required], - comment: [null], - }); - } -} diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts index d5201841e..611fdc5c7 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview.module.ts @@ -2,6 +2,7 @@ import { OverlayModule } from '@angular/cdk/overlay'; import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; +import { ReplaceNbspPipe } from '@common-ui/pipes/replace-nbsp.pipe'; import { PendingChangesGuard } from '@guards/can-deactivate.guard'; import { CapitalizePipe, @@ -49,7 +50,6 @@ import { ReadonlyBannerComponent } from './components/readonly-banner/readonly-b import { FilePreviewRightContainerComponent } from './components/right-container/file-preview-right-container.component'; import { UserManagementComponent } from './components/user-management/user-management.component'; import { ViewSwitchComponent } from './components/view-switch/view-switch.component'; -import { AcceptRecommendationDialogComponent } from './dialogs/accept-recommendation-dialog/accept-recommendation-dialog.component'; import { AddHintDialogComponent } from './dialogs/add-hint-dialog/add-hint-dialog.component'; import { ChangeLegalBasisDialogComponent } from './dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component'; import { AddAnnotationDialogComponent } from './dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component'; @@ -71,7 +71,6 @@ import { DocumentUnloadedGuard } from './services/document-unloaded.guard'; import { FilePreviewDialogService } from './services/file-preview-dialog.service'; import { ManualRedactionService } from './services/manual-redaction.service'; import { TablesService } from './services/tables.service'; -import { ReplaceNbspPipe } from '@common-ui/pipes/replace-nbsp.pipe'; const routes: IqserRoutes = [ { @@ -88,7 +87,6 @@ const dialogs = [ ResizeRedactionDialogComponent, ChangeLegalBasisDialogComponent, HighlightActionDialogComponent, - AcceptRecommendationDialogComponent, DocumentInfoDialogComponent, ImportRedactionsDialogComponent, RedactTextDialogComponent, From ffa9a5830fa6042ab4ad246ca3112a038b7454de Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 27 Oct 2023 21:30:27 +0300 Subject: [PATCH 06/10] RED-7619 remove old super type logic, add new --- .../file/annotation-permissions.utils.ts | 2 +- .../src/app/models/file/annotation.wrapper.ts | 255 ++++-------------- .../annotation-card.component.html | 6 +- .../annotation-wrapper.component.html | 4 +- .../annotation-wrapper.component.ts | 10 +- .../file-workload/file-workload.component.ts | 2 +- .../resize-annotation-dialog.component.html | 2 +- .../resize-annotation-dialog.component.ts | 55 +--- .../resize-redaction-dialog.component.html | 4 +- .../resize-redaction-dialog.component.ts | 26 +- .../services/annotation-processing.service.ts | 2 +- .../services/file-data.service.ts | 58 +--- .../services/annotation-draw.service.ts | 6 +- .../annotation-types-translations.ts | 1 + .../app/utils/sorters/super-type-sorter.ts | 1 + .../src/lib/colors/annotation-color-config.ts | 19 +- libs/red-domain/src/lib/files/super-types.ts | 61 +++++ .../src/lib/redaction-log/entity-log-entry.ts | 4 +- .../{entry-types.ts => entity-types.ts} | 4 +- .../red-domain/src/lib/redaction-log/index.ts | 2 +- 20 files changed, 180 insertions(+), 344 deletions(-) rename libs/red-domain/src/lib/redaction-log/{entry-types.ts => entity-types.ts} (70%) diff --git a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts index 4a70ac52c..5d64803f6 100644 --- a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts +++ b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts @@ -32,7 +32,7 @@ export const canChangeLegalBasis = (annotation: AnnotationWrapper, canAddRedacti canAddRedaction && annotation.isRedacted && !annotation.pending; export const canRecategorizeAnnotation = (annotation: AnnotationWrapper, canRecategorize: boolean) => - canRecategorize && (annotation.isImage || annotation.hintDictionary) && !annotation.pending; + canRecategorize && (annotation.isImage || annotation.HINT) && !annotation.pending; export const canResizeAnnotation = (annotation: AnnotationWrapper, canAddRedaction: boolean) => canAddRedaction && diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index a4807fed9..996bb68c8 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -4,81 +4,67 @@ import { annotationEntityColorConfig, AnnotationIconType, ChangeType, - ChangeTypes, Dictionary, Earmark, + EntityTypes, EntryStates, - EntryTypes, FalsePositiveSuperTypes, IComment, IEntityLogEntry, ILegalBasis, - IManualChange, IPoint, IRectangle, LogEntryEngine, LogEntryEngines, - LogEntryStatuses, LowLevelFilterTypes, ManualRedactionTypes, SuperType, + SuperTypeMapper, SuperTypes, } from '@red/domain'; import { annotationTypesTranslations } from '@translations/annotation-types-translations'; -import { chronologicallyBy, timestampOf } from '../../modules/file-preview/services/file-data.service'; export class AnnotationWrapper implements IListable { - [x: string]: unknown; - + id: string; superType: SuperType; - typeValue: string; + superTypeLabel: string; + type: string; + typeLabel?: string; color: string; - entity: Dictionary; comments: IComment[] = []; firstTopLeftPoint: IPoint; - id: string; shortContent: string; content: string; value: string; - typeLabel: string; pageNumber: number; - HINT = false; - redaction = false; - status: string; dictionaryOperation = false; - positions: IRectangle[]; - recommendationType: string; + positions: IRectangle[] = []; legalBasisValue: string; // AREA === rectangle AREA = false; - section?: string; - reference: string[]; - imported = false; + HINT = false; IMAGE = false; + section?: string; + reference: string[] = []; + imported = false; manual = false; pending = false; - hintDictionary = false; textAfter?: string; textBefore?: string; isChangeLogEntry = false; - changeLogType?: 'ADDED' | 'REMOVED' | 'CHANGED'; - engines?: LogEntryEngine[]; + engines: LogEntryEngine[] = []; hasBeenResized: boolean; hasBeenRecategorized: boolean; hasLegalBasisChanged: boolean; hasBeenForcedHint: boolean; hasBeenForcedRedaction: boolean; hasBeenRemovedByManualOverride: boolean; - legalBasisList: ILegalBasis[] = []; + isIgnored = false; get searchKey(): string { return this.id; } - get isChangeLogRemoved() { - return this.changeLogType === 'REMOVED'; - } - get descriptor() { return this.isModifyDictionary ? _('dictionary') : _('type'); } @@ -113,10 +99,6 @@ export class AnnotationWrapper implements IListable { return this.type?.toLowerCase() === 'ocr'; } - get type() { - return this.typeValue; - } - get topLevelFilter() { return !LowLevelFilterTypes[this.superType]; } @@ -146,7 +128,7 @@ export class AnnotationWrapper implements IListable { return 'hexagon'; } - if (this.isHint || this.isIgnoredHint) { + if (this.HINT) { return 'circle'; } @@ -214,33 +196,28 @@ export class AnnotationWrapper implements IListable { annotationWrapper.id = earmark.id; annotationWrapper.pageNumber = earmark.positions[0].page; annotationWrapper.superType = SuperTypes.TextHighlight; - annotationWrapper.typeValue = SuperTypes.TextHighlight; + annotationWrapper.type = SuperTypes.TextHighlight; annotationWrapper.value = 'Imported'; annotationWrapper.color = earmark.hexColor; annotationWrapper.positions = earmark.positions; annotationWrapper.firstTopLeftPoint = earmark.positions[0]?.topLeft; - annotationWrapper.typeLabel = annotationTypesTranslations[annotationWrapper.superType]; + annotationWrapper.superTypeLabel = annotationTypesTranslations[annotationWrapper.superType]; return annotationWrapper; } static fromData( logEntry: IEntityLogEntry, - dictionaries: Dictionary[], + dictionary: Dictionary, changeLogType: ChangeType, legalBasisList: ILegalBasis[], - hintDictionary: boolean, isDocumine: boolean, ) { const annotationWrapper = new AnnotationWrapper(); annotationWrapper.id = logEntry.id; annotationWrapper.isChangeLogEntry = !!changeLogType; - annotationWrapper.changeLogType = changeLogType; - annotationWrapper.legalBasisList = legalBasisList; - annotationWrapper.redaction = logEntry.entryType === EntryTypes.ENTITY; - annotationWrapper.HINT = logEntry.entryType === EntryTypes.HINT; - annotationWrapper.typeValue = logEntry.type; + annotationWrapper.type = 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; @@ -253,102 +230,64 @@ export class AnnotationWrapper implements IListable { annotationWrapper.textBefore = logEntry.textBefore; annotationWrapper.textAfter = logEntry.textAfter; annotationWrapper.dictionaryOperation = logEntry.dictionaryEntry; - annotationWrapper.IMAGE = logEntry.entryType === EntryTypes.IMAGE; + + annotationWrapper.HINT = logEntry.entryType === EntityTypes.HINT; + annotationWrapper.IMAGE = logEntry.entryType === EntityTypes.IMAGE; + annotationWrapper.AREA = logEntry.entryType === EntityTypes.AREA; + + annotationWrapper.isIgnored = logEntry.state === EntryStates.IGNORED; + annotationWrapper.imported = logEntry.imported; annotationWrapper.legalBasisValue = logEntry.legalBasis; annotationWrapper.comments = []; //logEntry.comments || []; annotationWrapper.manual = logEntry.manualChanges?.length > 0; - annotationWrapper.engines = logEntry.engines; + annotationWrapper.engines = logEntry.engines ?? []; annotationWrapper.section = logEntry.section; annotationWrapper.reference = logEntry.reference || []; - annotationWrapper.AREA = logEntry.entryType === EntryTypes.AREA; - annotationWrapper.hintDictionary = hintDictionary; annotationWrapper.hasBeenResized = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.RESIZE && c.annotationStatus === LogEntryStatuses.APPROVED, + c => c.manualRedactionType === ManualRedactionTypes.RESIZE && c.processed, ); annotationWrapper.hasBeenRecategorized = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.RECATEGORIZE && c.annotationStatus === LogEntryStatuses.APPROVED, + c => c.manualRedactionType === ManualRedactionTypes.RECATEGORIZE && c.processed, ); annotationWrapper.hasLegalBasisChanged = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE && c.annotationStatus === LogEntryStatuses.APPROVED, + c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE && c.processed, ); annotationWrapper.hasBeenForcedHint = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.FORCE_HINT && c.annotationStatus === LogEntryStatuses.APPROVED, + c => c.manualRedactionType === ManualRedactionTypes.FORCE_HINT && c.processed, ); annotationWrapper.hasBeenForcedRedaction = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.FORCE_REDACT && c.annotationStatus === LogEntryStatuses.APPROVED, + c => c.manualRedactionType === ManualRedactionTypes.FORCE_REDACT && c.processed, ); annotationWrapper.hasBeenRemovedByManualOverride = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.REMOVE_LOCALLY && c.annotationStatus === LogEntryStatuses.APPROVED, + c => c.manualRedactionType === ManualRedactionTypes.REMOVE_LOCALLY && c.processed, ); - this.#createContent(annotationWrapper, logEntry, isDocumine); + this.#createContent(annotationWrapper, logEntry, isDocumine, legalBasisList); this.#setSuperType(annotationWrapper, logEntry); - this.#handleRecommendations(annotationWrapper, logEntry); - annotationWrapper.typeLabel = this.#getTypeLabel(annotationWrapper); + annotationWrapper.superTypeLabel = annotationTypesTranslations[annotationWrapper.superType]; - const entity = dictionaries.find(d => d.type === annotationWrapper.typeValue); - annotationWrapper.entity = entity?.virtual ? null : entity; + annotationWrapper.typeLabel = dictionary.virtual ? undefined : dictionary.label; const colorKey = annotationEntityColorConfig[annotationWrapper.superType]; - annotationWrapper.color = entity[colorKey] as string; + annotationWrapper.color = dictionary[colorKey] as string; + annotationWrapper['entry'] = logEntry; return annotationWrapper; } - static #getTypeLabel(annotation: AnnotationWrapper): string { - if (annotation.superType === SuperTypes.ManualRedaction && annotation.hintDictionary) { - return _('annotation-type.manual-hint'); - } - return annotationTypesTranslations[annotation.superType]; - } - - static #handleRecommendations(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry) { - if (annotationWrapper.superType === SuperTypes.Recommendation) { - annotationWrapper.recommendationType = logEntry.type; - } - } - 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 && - logEntry.entryType === EntryTypes.ENTITY - ) { - annotationWrapper.superType = SuperTypes.Redaction; - return; - } - - annotationWrapper.pending = !lastRelevantManualChange.processed; - - annotationWrapper.superType = this.#selectSuperType(logEntry, lastRelevantManualChange, annotationWrapper.hintDictionary); - } else { - 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 (logEntry.entryType === EntryTypes.ENTITY) { - annotationWrapper.superType = SuperTypes.Redaction; - } else if (logEntry.entryType === EntryTypes.HINT) { - annotationWrapper.superType = SuperTypes.Hint; - } else { - annotationWrapper.superType = SuperTypes.Skipped; - } - } + const lastRelevantManualChange = logEntry.manualChanges?.at(-1); + annotationWrapper.pending = lastRelevantManualChange && !lastRelevantManualChange.processed; + annotationWrapper.superType = SuperTypeMapper[logEntry.entryType][logEntry.state](logEntry); } - static #createContent(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry, isDocumine: boolean) { + static #createContent( + annotationWrapper: AnnotationWrapper, + logEntry: IEntityLogEntry, + isDocumine: boolean, + legalBasisList: ILegalBasis[], + ) { let content = ''; if (logEntry.matchedRule) { content += `Rule ${logEntry.matchedRule} matched${isDocumine ? ':' : ''} \n\n`; @@ -381,15 +320,13 @@ export class AnnotationWrapper implements IListable { content += `${prefix} "${logEntry.section}"`; } - annotationWrapper.shortContent = this.#getShortContent(annotationWrapper) || content; + annotationWrapper.shortContent = this.#getShortContent(annotationWrapper, legalBasisList) || content; annotationWrapper.content = content; } - static #getShortContent(annotationWrapper: AnnotationWrapper) { + static #getShortContent(annotationWrapper: AnnotationWrapper, legalBasisList: ILegalBasis[]) { if (annotationWrapper.legalBasis) { - const lb = annotationWrapper.legalBasisList.find( - lbm => lbm.reason?.toLowerCase().includes(annotationWrapper.legalBasis.toLowerCase()), - ); + const lb = legalBasisList.find(lbm => lbm.reason?.toLowerCase().includes(annotationWrapper.legalBasis.toLowerCase())); if (lb) { return lb.name; } @@ -397,98 +334,4 @@ export class AnnotationWrapper implements IListable { return annotationWrapper.legalBasis; } - - static #selectSuperType(logEntry: IEntityLogEntry, lastManualChange: IManualChange, isHintDictionary: boolean): SuperType { - switch (lastManualChange.manualRedactionType) { - case ManualRedactionTypes.ADD_LOCALLY: - return SuperTypes.ManualRedaction; - case ManualRedactionTypes.ADD_TO_DICTIONARY: - return isHintDictionary ? SuperTypes.Hint : SuperTypes.Redaction; - case ManualRedactionTypes.REMOVE_LOCALLY: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; - case LogEntryStatuses.DECLINED: { - if (isHintDictionary) { - return SuperTypes.Hint; - } - - if (logEntry.entryType === EntryTypes.ENTITY) { - return SuperTypes.Redaction; - } - - return SuperTypes.Skipped; - } - } - break; - case ManualRedactionTypes.REMOVE_FROM_DICTIONARY: - if (logEntry.entryType === EntryTypes.ENTITY) { - if (lastManualChange.processed) { - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - return SuperTypes.Skipped; - case LogEntryStatuses.DECLINED: - return SuperTypes.Redaction; - } - } - return SuperTypes.Redaction; - } - - 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; - } - } - - return isHintDictionary ? SuperTypes.Hint : SuperTypes.Skipped; - case ManualRedactionTypes.FORCE_REDACT: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - return SuperTypes.Redaction; - case LogEntryStatuses.DECLINED: - return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; - } - break; - case ManualRedactionTypes.FORCE_HINT: - switch (lastManualChange.annotationStatus) { - case LogEntryStatuses.APPROVED: - return SuperTypes.Hint; - case LogEntryStatuses.DECLINED: - return SuperTypes.IgnoredHint; - } - break; - case ManualRedactionTypes.RECATEGORIZE: - if (logEntry.entryType === EntryTypes.RECOMMENDATION) { - return SuperTypes.Recommendation; - } - - if (logEntry.entryType === EntryTypes.ENTITY) { - return SuperTypes.Redaction; - } - - if (logEntry.entryType === EntryTypes.HINT) { - return SuperTypes.Hint; - } - - return isHintDictionary ? SuperTypes.IgnoredHint : SuperTypes.Skipped; - case ManualRedactionTypes.LEGAL_BASIS_CHANGE: - return logEntry.type === SuperTypes.ManualRedaction ? SuperTypes.ManualRedaction : SuperTypes.Redaction; - case ManualRedactionTypes.RESIZE: - if (logEntry.entryType === EntryTypes.RECOMMENDATION) { - return SuperTypes.Recommendation; - } - - 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; - } - } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html index 1b5004da6..50a482417 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.html @@ -8,19 +8,19 @@
- {{ annotation.typeLabel | translate }} + {{ annotation.superTypeLabel | translate }}   {{ 'annotation.pending' | translate }}
-
+
{{ annotation.descriptor | translate }}: - {{ annotation.entity.label }} + {{ annotation.typeLabel }}
-
+
!bool(a.isChangeLogRemoved)); + annotations = annotations.filter(a => !bool(a.isIgnored)); } if (this.#isDocumine && !this.#isIqserDevMode) { diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.html index 43e9c5abc..87bb9d9af 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.html @@ -5,7 +5,7 @@
- {{ redaction.value }} + {{ data.redaction.value }}
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.ts index 91070e5c6..fb6d55108 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/resize-annotation-dialog/resize-annotation-dialog.component.ts @@ -1,8 +1,6 @@ -import { Component, OnInit } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; -import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { Dictionary, Dossier } from '@red/domain'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { ResizeAnnotationData, ResizeAnnotationResult } from '../../../utils/dialog-types'; @@ -10,51 +8,26 @@ import { ResizeAnnotationData, ResizeAnnotationResult } from '../../../utils/dia @Component({ templateUrl: './resize-annotation-dialog.component.html', }) -export class ResizeAnnotationDialogComponent - extends IqserDialogComponent - implements OnInit -{ - readonly #dossier: Dossier; +export class ResizeAnnotationDialogComponent extends IqserDialogComponent< + ResizeAnnotationDialogComponent, + ResizeAnnotationData, + ResizeAnnotationResult +> { + readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId); readonly iconButtonTypes = IconButtonTypes; - dictionaries: Dictionary[] = []; - redaction: AnnotationWrapper; - readonly form = this.#getForm(); - - constructor( - activeDossiersService: ActiveDossiersService, - private readonly _dictionariesMapService: DictionariesMapService, - private readonly _formBuilder: FormBuilder, - ) { - super(); - this.#dossier = activeDossiersService.find(this.data.dossierId); - this.redaction = this.data.redaction; - } - - get displayedDictionaryLabel() { - const dictType = this.form.get('dictionary').value; - if (dictType) { - return this.dictionaries.find(d => d.type === dictType)?.label ?? null; - } - return null; - } - - ngOnInit() { - this.dictionaries = this._dictionariesMapService.get(this.#dossier.dossierTemplateId); - } + readonly dictionaries = inject(DictionariesMapService).get(this.#dossier.dossierTemplateId); + readonly entity = this.dictionaries.find(d => d.type === this.data.redaction.type); + readonly form = inject(FormBuilder).group({ + comment: [null], + }); save() { const formValue = this.form.getRawValue(); this.close({ comment: formValue.comment, - updateDictionary: this.redaction.entity.hasDictionary, - addToAllDossiers: this.redaction.entity.hasDictionary, - }); - } - - #getForm() { - return this._formBuilder.group({ - comment: [null], + updateDictionary: this.entity.hasDictionary, + addToAllDossiers: this.entity.hasDictionary, }); } } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html index 20f694aa0..403ead085 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.html @@ -26,8 +26,8 @@ {{ displayedDictionaryLabel }} - - {{ redaction.entity.label }} + + {{ redaction.typeLabel }} diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.ts index e78831197..a3f16760c 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/resize-redaction-dialog/resize-redaction-dialog.component.ts @@ -1,7 +1,6 @@ -import { Component, inject, OnInit } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { FormBuilder, FormControl, FormGroup } from '@angular/forms'; import { DetailsRadioOption, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; -import { Dictionary } from '@red/domain'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { getResizeRedactionOptions, ResizeOptions, ResizeRedactionOption } from '../../utils/dialog-options'; @@ -10,15 +9,17 @@ import { ResizeRedactionData, ResizeRedactionResult } from '../../utils/dialog-t @Component({ templateUrl: './resize-redaction-dialog.component.html', }) -export class ResizeRedactionDialogComponent - extends IqserDialogComponent - implements OnInit -{ +export class ResizeRedactionDialogComponent extends IqserDialogComponent< + ResizeRedactionDialogComponent, + ResizeRedactionData, + ResizeRedactionResult +> { readonly #applyToAllDossiers = this.data.applyToAllDossiers ?? true; readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId); readonly iconButtonTypes = IconButtonTypes; readonly options: DetailsRadioOption[]; - dictionaries: Dictionary[] = []; + readonly dictionaries = inject(DictionariesMapService).get(this.#dossier.dossierTemplateId); + readonly entity = this.dictionaries.find(d => d.type === this.data.redaction.type); readonly redaction = this.data.redaction; readonly form: FormGroup<{ comment: FormControl; @@ -26,10 +27,7 @@ export class ResizeRedactionDialogComponent option: FormControl>; }>; - constructor( - private readonly _dictionariesMapService: DictionariesMapService, - private readonly _formBuilder: FormBuilder, - ) { + constructor(private readonly _formBuilder: FormBuilder) { super(); this.options = getResizeRedactionOptions(this.redaction, this.#dossier, false, this.#applyToAllDossiers, this.data.isApprover); this.form = this.#getForm(); @@ -43,10 +41,6 @@ export class ResizeRedactionDialogComponent return null; } - ngOnInit() { - this.dictionaries = this._dictionariesMapService.get(this.#dossier.dossierTemplateId); - } - save() { const formValue = this.form.getRawValue(); const updateDictionary = formValue.option.value === ResizeOptions.IN_DOSSIER; @@ -61,7 +55,7 @@ export class ResizeRedactionDialogComponent #getForm() { return this._formBuilder.group({ comment: [null], - dictionary: new FormControl({ value: this.redaction.entity.type, disabled: true }), + dictionary: new FormControl({ value: this.redaction.typeLabel, disabled: true }), option: this.options[0], }); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts index 0fb05a0b3..0c7f3215f 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts @@ -106,7 +106,7 @@ export class AnnotationProcessingService { } const childFilter: IFilter = { id: a.filterKey, - label: a.entity.label, + label: a.typeLabel, checked: false, matches: 1, metadata: { diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index 202f26ea3..f064a2682 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -3,7 +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, IEntityLog, IEntityLogEntry, LogEntryStatuses, ViewedPage, ViewMode, ViewModes } from '@red/domain'; +import { ChangeType, ChangeTypes, EntryStates, File, IEntityLog, IEntityLogEntry, ViewedPage, ViewMode, ViewModes } from '@red/domain'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { EarmarksService } from '@services/files/earmarks.service'; import { FilesService } from '@services/files/files.service'; @@ -154,7 +154,7 @@ export class FileDataService extends EntitiesService { if (viewMode === 'STANDARD') { - return !annotation.isChangeLogRemoved; + return !annotation.isIgnored; } if (viewMode === 'DELTA') { @@ -177,13 +177,12 @@ export class FileDataService extends EntitiesService 0; + const manual = entry.manualChanges.length > 0; if (!manual && file.excludedPages.includes(pageNumber)) { continue; } - const changeLogValues = this.#getChangeLogValues(entry, file); - if (changeLogValues.hidden) { + if (entry.state === EntryStates.REMOVED) { continue; } @@ -200,14 +199,8 @@ export class FileDataService extends EntitiesService 0; if (file.numberOfAnalyses <= 1 && !file.hasUpdates && !hasManualChanges) { - return { - changeLogType: undefined, - hidden: false, - }; + return; } const viableChanges = entityLogEntry.changes?.filter(c => c.analysisNumber > 1); const lastChange = viableChanges?.sort(chronologicallyBy(x => x.dateTime)).at(-1); - const page = entityLogEntry.positions?.[0].pageNumber; + const page = entityLogEntry.positions[0].pageNumber; const viewedPage = this.#originalViewedPages.find(p => p.page === page); if (!viewedPage) { - return { - changeLogType: undefined, - hidden: lastChange ? lastChange.type === ChangeTypes.REMOVED : false, - }; + return; } // page has been seen -> let's see if it's a change @@ -249,14 +230,10 @@ export class FileDataService extends EntitiesService visibleStatuses.includes(change.annotationStatus)); + const viableManualChanges = entityLogEntry.manualChanges.filter(change => change.processed); viableManualChanges.sort(chronologicallyBy(x => x.processedDate)); const lastManualChange = viableManualChanges.at(-1); const processedTime = lastManualChange?.processedDate; @@ -264,17 +241,8 @@ export class FileDataService extends EntitiesService = { [SuperTypes.Hint]: _('annotation-type.hint'), [SuperTypes.IgnoredHint]: _('annotation-type.ignored-hint'), [SuperTypes.ManualRedaction]: _('annotation-type.manual-redaction'), + [SuperTypes.ManualHint]: _('annotation-type.manual-hint'), [SuperTypes.Recommendation]: _('annotation-type.recommendation'), [SuperTypes.Redaction]: _('annotation-type.redaction'), [SuperTypes.Skipped]: _('annotation-type.skipped'), diff --git a/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts index 2305bc13c..ac55b638b 100644 --- a/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts +++ b/apps/red-ui/src/app/utils/sorters/super-type-sorter.ts @@ -7,5 +7,6 @@ export const SuperTypeSorter: { [key in SuperType]: number } = { [SuperTypes.Skipped]: 50, [SuperTypes.Redaction]: 1, [SuperTypes.ManualRedaction]: 2, + [SuperTypes.ManualHint]: 3, [SuperTypes.Hint]: 19, }; diff --git a/libs/red-domain/src/lib/colors/annotation-color-config.ts b/libs/red-domain/src/lib/colors/annotation-color-config.ts index 449a09075..e14871c15 100644 --- a/libs/red-domain/src/lib/colors/annotation-color-config.ts +++ b/libs/red-domain/src/lib/colors/annotation-color-config.ts @@ -1,15 +1,14 @@ import { SuperType, SuperTypes } from '../files'; import { DefaultColorType } from './default-color-type'; -export type DefaultBasedColorType = SuperType | 'updated' | 'analysis'; +export type DefaultBasedColorType = Exclude | 'updated' | 'analysis'; export const annotationDefaultColorConfig: Record = { - [SuperTypes.TextHighlight]: 'redactionColor', // not actually used - [SuperTypes.IgnoredHint]: 'ignoredHintColor', [SuperTypes.Skipped]: 'skippedColor', [SuperTypes.Redaction]: 'redactionColor', [SuperTypes.ManualRedaction]: 'redactionColor', + [SuperTypes.ManualHint]: 'redactionColor', [SuperTypes.Recommendation]: 'recommendationColor', [SuperTypes.Hint]: 'hintColor', @@ -17,19 +16,15 @@ export const annotationDefaultColorConfig: Record = { +export const annotationEntityColorConfig: Record< + Exclude, + 'hexColor' | 'recommendationHexColor' | 'skippedHexColor' +> = { [SuperTypes.IgnoredHint]: 'skippedHexColor', [SuperTypes.Skipped]: 'skippedHexColor', [SuperTypes.Redaction]: 'hexColor', [SuperTypes.ManualRedaction]: 'hexColor', + [SuperTypes.ManualHint]: 'hexColor', [SuperTypes.Recommendation]: 'recommendationHexColor', [SuperTypes.Hint]: 'hexColor', } as const; diff --git a/libs/red-domain/src/lib/files/super-types.ts b/libs/red-domain/src/lib/files/super-types.ts index 29a38db2d..12091f4e9 100644 --- a/libs/red-domain/src/lib/files/super-types.ts +++ b/libs/red-domain/src/lib/files/super-types.ts @@ -1,4 +1,5 @@ import { ValuesOf } from '@iqser/common-ui/lib/utils'; +import { EntityType, EntityTypes, EntryState, EntryStates, IEntityLogEntry } from '../redaction-log'; export const SuperTypes = { TextHighlight: 'text-highlight', @@ -6,12 +7,72 @@ export const SuperTypes = { Skipped: 'skipped', Redaction: 'redaction', ManualRedaction: 'manual', + ManualHint: 'manual-hint', Recommendation: 'recommendation', Hint: 'hint', } as const; export type SuperType = ValuesOf; +function throwWrongSuperType(entry: IEntityLogEntry): never { + console.log('throwWrongSuperType', entry); + throw new Error(`A ${entry.state} ${entry.entryType} should never be mapped to a super type`); +} + +/** + * https://knecon.atlassian.net/wiki/spaces/RED/pages/102072322/EntityLog+-+Enum+combinations + */ +export const SuperTypeMapper: Record SuperType>> = { + [EntityTypes.ENTITY]: { + [EntryStates.APPLIED]: entry => (entry.manualChanges.length ? SuperTypes.ManualRedaction : SuperTypes.Redaction), + [EntryStates.SKIPPED]: () => SuperTypes.Skipped, + [EntryStates.IGNORED]: () => SuperTypes.Redaction, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.HINT]: { + [EntryStates.APPLIED]: entry => (entry.manualChanges.length ? SuperTypes.ManualHint : SuperTypes.Hint), + [EntryStates.SKIPPED]: entry => (entry.manualChanges.length ? SuperTypes.ManualHint : SuperTypes.Hint), + [EntryStates.IGNORED]: () => SuperTypes.IgnoredHint, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.FALSE_POSITIVE]: { + [EntryStates.APPLIED]: throwWrongSuperType, + [EntryStates.SKIPPED]: throwWrongSuperType, + [EntryStates.IGNORED]: throwWrongSuperType, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.RECOMMENDATION]: { + [EntryStates.APPLIED]: throwWrongSuperType, + [EntryStates.SKIPPED]: () => SuperTypes.Recommendation, + [EntryStates.IGNORED]: throwWrongSuperType, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.FALSE_RECOMMENDATION]: { + [EntryStates.APPLIED]: throwWrongSuperType, + [EntryStates.SKIPPED]: throwWrongSuperType, + [EntryStates.IGNORED]: throwWrongSuperType, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.AREA]: { + [EntryStates.APPLIED]: () => SuperTypes.Redaction, + [EntryStates.SKIPPED]: throwWrongSuperType, + [EntryStates.IGNORED]: throwWrongSuperType, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.IMAGE]: { + [EntryStates.APPLIED]: () => SuperTypes.Redaction, + [EntryStates.SKIPPED]: () => SuperTypes.Skipped, + [EntryStates.IGNORED]: throwWrongSuperType, + [EntryStates.REMOVED]: throwWrongSuperType, + }, + [EntityTypes.IMAGE_HINT]: { + [EntryStates.APPLIED]: throwWrongSuperType, + [EntryStates.SKIPPED]: () => SuperTypes.Hint, + [EntryStates.IGNORED]: throwWrongSuperType, + [EntryStates.REMOVED]: throwWrongSuperType, + }, +}; + export const LowLevelFilterTypes = { [SuperTypes.Hint]: true, [SuperTypes.Redaction]: true, diff --git a/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts b/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts index 9b47d1645..9a7db5e90 100644 --- a/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts +++ b/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts @@ -1,7 +1,7 @@ import { ITrackable } from '@iqser/common-ui'; import { IChange } from './change'; import { EntryState } from './entity-states'; -import { EntryType } from './entry-types'; +import { EntityType } from './entity-types'; import { IManualChange } from './manual-change'; import { LogEntryEngine } from './types'; @@ -12,7 +12,7 @@ export interface IEntityLogEntryPosition { export interface IEntityLogEntry extends ITrackable { type: string; - entryType: EntryType; + entryType: EntityType; state: EntryState; value: string; reason: string; diff --git a/libs/red-domain/src/lib/redaction-log/entry-types.ts b/libs/red-domain/src/lib/redaction-log/entity-types.ts similarity index 70% rename from libs/red-domain/src/lib/redaction-log/entry-types.ts rename to libs/red-domain/src/lib/redaction-log/entity-types.ts index fdc77d152..5a5bd1ea9 100644 --- a/libs/red-domain/src/lib/redaction-log/entry-types.ts +++ b/libs/red-domain/src/lib/redaction-log/entity-types.ts @@ -1,4 +1,4 @@ -export const EntryTypes = { +export const EntityTypes = { ENTITY: 'ENTITY', HINT: 'HINT', FALSE_POSITIVE: 'FALSE_POSITIVE', @@ -9,4 +9,4 @@ export const EntryTypes = { IMAGE_HINT: 'IMAGE_HINT', } as const; -export type EntryType = (typeof EntryTypes)[keyof typeof EntryTypes]; +export type EntityType = (typeof EntityTypes)[keyof typeof EntityTypes]; diff --git a/libs/red-domain/src/lib/redaction-log/index.ts b/libs/red-domain/src/lib/redaction-log/index.ts index 5ebab18b3..4091fbe7c 100644 --- a/libs/red-domain/src/lib/redaction-log/index.ts +++ b/libs/red-domain/src/lib/redaction-log/index.ts @@ -15,4 +15,4 @@ export * from './dictionary-entry-types'; export * from './entity-log'; export * from './entity-log-entry'; export * from './entity-states'; -export * from './entry-types'; +export * from './entity-types'; From 7d141c5b2307e83b1742af69f2078ee38ad3e13c Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Mon, 30 Oct 2023 15:02:20 +0200 Subject: [PATCH 07/10] RED-7619 update annotation wrapper --- .../file/annotation-permissions.utils.ts | 2 +- .../src/app/models/file/annotation.wrapper.ts | 43 +++++---------- .../services/file-data.service.ts | 55 ++++++++++++++----- .../services/annotation-draw.service.ts | 2 +- libs/red-domain/src/lib/files/super-types.ts | 51 +++++++++-------- .../src/lib/redaction-log/manual-change.ts | 3 +- .../redaction-log/manual-redaction-entry.ts | 2 - .../red-domain/src/lib/redaction-log/types.ts | 7 --- 8 files changed, 85 insertions(+), 80 deletions(-) diff --git a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts index 5d64803f6..fd1ff6d7c 100644 --- a/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts +++ b/apps/red-ui/src/app/models/file/annotation-permissions.utils.ts @@ -32,7 +32,7 @@ export const canChangeLegalBasis = (annotation: AnnotationWrapper, canAddRedacti canAddRedaction && annotation.isRedacted && !annotation.pending; export const canRecategorizeAnnotation = (annotation: AnnotationWrapper, canRecategorize: boolean) => - canRecategorize && (annotation.isImage || annotation.HINT) && !annotation.pending; + canRecategorize && (annotation.isImage || annotation.isDictBasedHint) && !annotation.pending; export const canResizeAnnotation = (annotation: AnnotationWrapper, canAddRedaction: boolean) => canAddRedaction && diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index 996bb68c8..eeaa7c420 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -186,10 +186,6 @@ export class AnnotationWrapper implements IListable { return Math.floor(this.positions[0].height); } - get previewAnnotation() { - return this.isRedacted; - } - static fromEarmark(earmark: Earmark) { const annotationWrapper = new AnnotationWrapper(); @@ -244,27 +240,30 @@ export class AnnotationWrapper implements IListable { annotationWrapper.engines = logEntry.engines ?? []; annotationWrapper.section = logEntry.section; annotationWrapper.reference = logEntry.reference || []; - annotationWrapper.hasBeenResized = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.RESIZE && c.processed, - ); + annotationWrapper.hasBeenResized = !!logEntry.manualChanges?.find(c => c.manualRedactionType === ManualRedactionTypes.RESIZE); annotationWrapper.hasBeenRecategorized = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.RECATEGORIZE && c.processed, + c => c.manualRedactionType === ManualRedactionTypes.RECATEGORIZE, ); annotationWrapper.hasLegalBasisChanged = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE && c.processed, + c => c.manualRedactionType === ManualRedactionTypes.LEGAL_BASIS_CHANGE, ); annotationWrapper.hasBeenForcedHint = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.FORCE_HINT && c.processed, + c => c.manualRedactionType === ManualRedactionTypes.FORCE_HINT, ); annotationWrapper.hasBeenForcedRedaction = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.FORCE_REDACT && c.processed, + c => c.manualRedactionType === ManualRedactionTypes.FORCE_REDACT, ); annotationWrapper.hasBeenRemovedByManualOverride = !!logEntry.manualChanges?.find( - c => c.manualRedactionType === ManualRedactionTypes.REMOVE_LOCALLY && c.processed, + c => c.manualRedactionType === ManualRedactionTypes.REMOVE_LOCALLY, ); - this.#createContent(annotationWrapper, logEntry, isDocumine, legalBasisList); - this.#setSuperType(annotationWrapper, logEntry); + const content = this.#createContent(annotationWrapper, logEntry, isDocumine); + annotationWrapper.shortContent = this.#getShortContent(annotationWrapper, legalBasisList) || content; + annotationWrapper.content = content; + + const lastRelevantManualChange = logEntry.manualChanges?.at(-1); + annotationWrapper.pending = lastRelevantManualChange && !lastRelevantManualChange.processed; + annotationWrapper.superType = SuperTypeMapper[logEntry.entryType][logEntry.state](logEntry); annotationWrapper.superTypeLabel = annotationTypesTranslations[annotationWrapper.superType]; annotationWrapper.typeLabel = dictionary.virtual ? undefined : dictionary.label; @@ -276,18 +275,7 @@ export class AnnotationWrapper implements IListable { return annotationWrapper; } - static #setSuperType(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry) { - const lastRelevantManualChange = logEntry.manualChanges?.at(-1); - annotationWrapper.pending = lastRelevantManualChange && !lastRelevantManualChange.processed; - annotationWrapper.superType = SuperTypeMapper[logEntry.entryType][logEntry.state](logEntry); - } - - static #createContent( - annotationWrapper: AnnotationWrapper, - logEntry: IEntityLogEntry, - isDocumine: boolean, - legalBasisList: ILegalBasis[], - ) { + static #createContent(annotationWrapper: AnnotationWrapper, logEntry: IEntityLogEntry, isDocumine: boolean) { let content = ''; if (logEntry.matchedRule) { content += `Rule ${logEntry.matchedRule} matched${isDocumine ? ':' : ''} \n\n`; @@ -320,8 +308,7 @@ export class AnnotationWrapper implements IListable { content += `${prefix} "${logEntry.section}"`; } - annotationWrapper.shortContent = this.#getShortContent(annotationWrapper, legalBasisList) || content; - annotationWrapper.content = content; + return content; } static #getShortContent(annotationWrapper: AnnotationWrapper, legalBasisList: ILegalBasis[]) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index f064a2682..38eadfafe 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -1,9 +1,20 @@ -import { effect, Injectable, Signal, signal } from '@angular/core'; +import { effect, inject, Injectable, Signal, signal } from '@angular/core'; 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, EntryStates, File, IEntityLog, IEntityLogEntry, ViewedPage, ViewMode, ViewModes } from '@red/domain'; +import { + ChangeType, + ChangeTypes, + EntryStates, + File, + IEntityLog, + IEntityLogEntry, + SuperTypeMapper, + ViewedPage, + ViewMode, + ViewModes, +} from '@red/domain'; import { DictionaryService } from '@services/entity-services/dictionary.service'; import { EarmarksService } from '@services/files/earmarks.service'; import { FilesService } from '@services/files/files.service'; @@ -35,6 +46,8 @@ export class FileDataService extends EntitiesService>(new Map()); #originalViewedPages: ViewedPage[] = []; readonly #isDocumine = getConfig().IS_DOCUMINE; + readonly #logger = inject(NGXLogger); + readonly #toaster = inject(Toaster); protected readonly _entityClass = AnnotationWrapper; missingTypes = new Set(); readonly earmarks: Signal>; @@ -53,8 +66,6 @@ export class FileDataService extends EntitiesService !a.isFalsePositive); @@ -131,7 +142,7 @@ export class FileDataService extends EntitiesService 0) { - this._toaster.error(_('error.missing-types'), { + this.#toaster.error(_('error.missing-types'), { disableTimeOut: true, params: { missingTypes: Array.from(this.missingTypes).join(', ') }, }); @@ -142,12 +153,12 @@ export class FileDataService extends EntitiesService dict.type === entry.type); if (!dictionary && checkDictionary) { const dictionaryRequest = this._dictionaryService.loadDictionaryDataForDossierTemplate(this._state.dossierTemplateId); diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts index a5dcead27..4ce67b20c 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/annotation-draw.service.ts @@ -163,7 +163,7 @@ export class AnnotationDrawService { (hideSkipped && annotationWrapper.isSkipped) || this._annotationManager.isHidden(annotationWrapper.id); annotation.setCustomData('redact-manager', 'true'); - annotation.setCustomData('redaction', String(annotationWrapper.previewAnnotation)); + annotation.setCustomData('redaction', String(annotationWrapper.isRedacted)); annotation.setCustomData('skipped', String(annotationWrapper.isSkipped)); annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry)); annotation.setCustomData('changeLogRemoved', String(annotationWrapper.isIgnored)); diff --git a/libs/red-domain/src/lib/files/super-types.ts b/libs/red-domain/src/lib/files/super-types.ts index 12091f4e9..9dbf33fae 100644 --- a/libs/red-domain/src/lib/files/super-types.ts +++ b/libs/red-domain/src/lib/files/super-types.ts @@ -14,62 +14,61 @@ export const SuperTypes = { export type SuperType = ValuesOf; -function throwWrongSuperType(entry: IEntityLogEntry): never { - console.log('throwWrongSuperType', entry); - throw new Error(`A ${entry.state} ${entry.entryType} should never be mapped to a super type`); +function wrongSuperTypeHandler(): never | undefined { + return undefined; } /** * https://knecon.atlassian.net/wiki/spaces/RED/pages/102072322/EntityLog+-+Enum+combinations */ -export const SuperTypeMapper: Record SuperType>> = { +export const SuperTypeMapper: Record SuperType | undefined>> = { [EntityTypes.ENTITY]: { [EntryStates.APPLIED]: entry => (entry.manualChanges.length ? SuperTypes.ManualRedaction : SuperTypes.Redaction), [EntryStates.SKIPPED]: () => SuperTypes.Skipped, [EntryStates.IGNORED]: () => SuperTypes.Redaction, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.HINT]: { - [EntryStates.APPLIED]: entry => (entry.manualChanges.length ? SuperTypes.ManualHint : SuperTypes.Hint), + [EntryStates.APPLIED]: wrongSuperTypeHandler, [EntryStates.SKIPPED]: entry => (entry.manualChanges.length ? SuperTypes.ManualHint : SuperTypes.Hint), [EntryStates.IGNORED]: () => SuperTypes.IgnoredHint, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.FALSE_POSITIVE]: { - [EntryStates.APPLIED]: throwWrongSuperType, - [EntryStates.SKIPPED]: throwWrongSuperType, - [EntryStates.IGNORED]: throwWrongSuperType, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.APPLIED]: wrongSuperTypeHandler, + [EntryStates.SKIPPED]: wrongSuperTypeHandler, + [EntryStates.IGNORED]: wrongSuperTypeHandler, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.RECOMMENDATION]: { - [EntryStates.APPLIED]: throwWrongSuperType, + [EntryStates.APPLIED]: wrongSuperTypeHandler, [EntryStates.SKIPPED]: () => SuperTypes.Recommendation, - [EntryStates.IGNORED]: throwWrongSuperType, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.IGNORED]: wrongSuperTypeHandler, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.FALSE_RECOMMENDATION]: { - [EntryStates.APPLIED]: throwWrongSuperType, - [EntryStates.SKIPPED]: throwWrongSuperType, - [EntryStates.IGNORED]: throwWrongSuperType, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.APPLIED]: wrongSuperTypeHandler, + [EntryStates.SKIPPED]: wrongSuperTypeHandler, + [EntryStates.IGNORED]: wrongSuperTypeHandler, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.AREA]: { [EntryStates.APPLIED]: () => SuperTypes.Redaction, - [EntryStates.SKIPPED]: throwWrongSuperType, - [EntryStates.IGNORED]: throwWrongSuperType, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.SKIPPED]: wrongSuperTypeHandler, + [EntryStates.IGNORED]: wrongSuperTypeHandler, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.IMAGE]: { [EntryStates.APPLIED]: () => SuperTypes.Redaction, [EntryStates.SKIPPED]: () => SuperTypes.Skipped, - [EntryStates.IGNORED]: throwWrongSuperType, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.IGNORED]: wrongSuperTypeHandler, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, [EntityTypes.IMAGE_HINT]: { - [EntryStates.APPLIED]: throwWrongSuperType, + [EntryStates.APPLIED]: wrongSuperTypeHandler, [EntryStates.SKIPPED]: () => SuperTypes.Hint, - [EntryStates.IGNORED]: throwWrongSuperType, - [EntryStates.REMOVED]: throwWrongSuperType, + [EntryStates.IGNORED]: wrongSuperTypeHandler, + [EntryStates.REMOVED]: wrongSuperTypeHandler, }, }; diff --git a/libs/red-domain/src/lib/redaction-log/manual-change.ts b/libs/red-domain/src/lib/redaction-log/manual-change.ts index 63e95fe9a..41cb75594 100644 --- a/libs/red-domain/src/lib/redaction-log/manual-change.ts +++ b/libs/red-domain/src/lib/redaction-log/manual-change.ts @@ -1,10 +1,9 @@ -import { LogEntryStatus, ManualRedactionType } from './types'; +import { ManualRedactionType } from './types'; export interface IManualChange { userId: string; processedDate: string; requestedDate: string; - annotationStatus: LogEntryStatus; manualRedactionType: ManualRedactionType; propertyChanges: { [key: string]: any }; processed: boolean; diff --git a/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts b/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts index 92712e2f7..917f08cb7 100644 --- a/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts +++ b/libs/red-domain/src/lib/redaction-log/manual-redaction-entry.ts @@ -1,5 +1,4 @@ import { IRectangle } from '../geometry'; -import { LogEntryStatus } from './types'; export interface IManualRedactionEntry { addToDictionary?: boolean; @@ -11,7 +10,6 @@ export interface IManualRedactionEntry { reason?: string; requestDate?: string; softDeletedTime?: string; - status?: LogEntryStatus; type?: string; user?: string; value?: string; diff --git a/libs/red-domain/src/lib/redaction-log/types.ts b/libs/red-domain/src/lib/redaction-log/types.ts index ff114eff4..06ce98d73 100644 --- a/libs/red-domain/src/lib/redaction-log/types.ts +++ b/libs/red-domain/src/lib/redaction-log/types.ts @@ -21,10 +21,3 @@ export const ManualRedactionTypes = { } as const; export type ManualRedactionType = ValuesOf; - -export const LogEntryStatuses = { - APPROVED: 'APPROVED', - DECLINED: 'DECLINED', -} as const; - -export type LogEntryStatus = ValuesOf; From f2e2a5ba1a14882f8c60d4607a0d3e4ad1f2adad Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Mon, 30 Oct 2023 20:56:49 +0200 Subject: [PATCH 08/10] RED-7619 I think its ready? --- .../src/app/models/file/annotation.wrapper.ts | 5 +- .../annotation-wrapper.component.html | 21 +++- .../annotation-wrapper.component.scss | 6 + .../annotation-wrapper.component.ts | 5 +- .../comments/comments.component.html | 59 ++++------ .../comments/comments.component.scss | 9 +- .../components/comments/comments.component.ts | 107 ++++++++---------- .../file-preview/file-preview-providers.ts | 32 +++--- .../services/annotation-actions.service.ts | 6 +- .../services/annotation-processing.service.ts | 2 +- .../services/commenting.service.ts | 39 ------- .../services/file-data.service.ts | 3 + .../services/manual-redaction.service.ts | 13 +-- .../src/app/services/comments-api.service.ts | 28 +++++ .../src/lib/redaction-log/entity-log-entry.ts | 1 + 15 files changed, 154 insertions(+), 182 deletions(-) delete mode 100644 apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts create mode 100644 apps/red-ui/src/app/services/comments-api.service.ts diff --git a/apps/red-ui/src/app/models/file/annotation.wrapper.ts b/apps/red-ui/src/app/models/file/annotation.wrapper.ts index eeaa7c420..26fa7ca9c 100644 --- a/apps/red-ui/src/app/models/file/annotation.wrapper.ts +++ b/apps/red-ui/src/app/models/file/annotation.wrapper.ts @@ -9,7 +9,6 @@ import { EntityTypes, EntryStates, FalsePositiveSuperTypes, - IComment, IEntityLogEntry, ILegalBasis, IPoint, @@ -31,7 +30,7 @@ export class AnnotationWrapper implements IListable { type: string; typeLabel?: string; color: string; - comments: IComment[] = []; + numberOfComments = 0; firstTopLeftPoint: IPoint; shortContent: string; content: string; @@ -233,9 +232,9 @@ export class AnnotationWrapper implements IListable { annotationWrapper.isIgnored = logEntry.state === EntryStates.IGNORED; + annotationWrapper.numberOfComments = logEntry.numberOfComments; 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; diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html index 7800d1036..498cb36c9 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.html @@ -10,26 +10,35 @@
- {{ annotation.item.comments.length }} + {{ annotation.item.numberOfComments }}
-
+
- + + + +
+
diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss index 6817bb6ea..36304a969 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.scss @@ -67,3 +67,9 @@ } } } + +.hide-comments { + margin-top: 5px; + margin-bottom: 8px; + padding-left: 26px; +} diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.ts index 3307c7b6d..3b2c9775c 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-wrapper/annotation-wrapper.component.ts @@ -13,12 +13,13 @@ import { ActionsHelpModeKeys } from '../../utils/constants'; }) export class AnnotationWrapperComponent implements OnChanges { readonly #isDocumine = getConfig().IS_DOCUMINE; - protected readonly _pdfProxyService = inject(PdfProxyService); - protected readonly _multiSelectService = inject(MultiSelectService); + protected readonly pdfProxyService = inject(PdfProxyService); + protected readonly multiSelectService = inject(MultiSelectService); @Input({ required: true }) annotation!: ListItem; @HostBinding('attr.annotation-id') annotationId: string; @HostBinding('class.active') active = false; actionsHelpModeKey?: string; + showComments = false; ngOnChanges() { this.annotationId = this.annotation.item.id; diff --git a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html index 3b7c4a0a2..833094349 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html @@ -1,39 +1,30 @@ - -
-
-
- {{ comment.user | name }} - {{ comment.date | date : 'sophisticatedDate' }} -
- -
- -
+
+
+
+ {{ comment.user | name }} + {{ comment.date | date: 'sophisticatedDate' }}
-
{{ comment.text }}
+
+ +
- +
{{ comment.text }}
+
-
- + diff --git a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.scss b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.scss index 6d438a45f..f9c8c4a3b 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.scss @@ -1,7 +1,7 @@ :host { display: flex; flex-direction: column; - padding: 8px 0 8px 16px; + padding: 8px 0 0 16px; .comment { margin-bottom: 10px; @@ -36,12 +36,7 @@ margin: 5px 0 10px 0; } - .hide-comments { - margin-top: 5px; - } - - .comment, - .hide-comments { + .comment { padding-left: 12px; } } diff --git a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts index 578020003..62e5ea6b8 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.ts @@ -1,84 +1,73 @@ -import { ChangeDetectorRef, Component, HostBinding, Input, OnInit, ViewChild } from '@angular/core'; -import type { IComment, User } from '@red/domain'; -import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { PermissionsService } from '@services/permissions.service'; +import { Component, inject, Input, OnChanges, signal, SimpleChanges, ViewChild } from '@angular/core'; import { InputWithActionComponent, LoadingService } from '@iqser/common-ui'; -import { Observable } from 'rxjs'; -import { CommentingService } from '../../services/commenting.service'; -import { tap } from 'rxjs/operators'; -import { FilePreviewStateService } from '../../services/file-preview-state.service'; -import { ManualRedactionService } from '../../services/manual-redaction.service'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; -import { ContextComponent, trackByFactory } from '@iqser/common-ui/lib/utils'; - -interface CommentsContext { - hiddenComments: boolean; -} +import { trackByFactory } from '@iqser/common-ui/lib/utils'; +import { AnnotationWrapper } from '@models/file/annotation.wrapper'; +import type { IComment, User } from '@red/domain'; +import { CommentsApiService } from '@services/comments-api.service'; +import { PermissionsService } from '@services/permissions.service'; +import { NGXLogger } from 'ngx-logger'; +import { FilePreviewStateService } from '../../services/file-preview-state.service'; @Component({ selector: 'redaction-comments', templateUrl: './comments.component.html', styleUrls: ['./comments.component.scss'], }) -export class CommentsComponent extends ContextComponent implements OnInit { - @HostBinding('class.hidden') private _hidden = true; - @ViewChild(InputWithActionComponent) private readonly _input: InputWithActionComponent; - @Input() annotation: AnnotationWrapper; - readonly trackBy = trackByFactory(); - readonly currentUser = getCurrentUser(); - hiddenComments$: Observable; +export class CommentsComponent implements OnChanges { + readonly #commentsApiService = inject(CommentsApiService); + readonly #logger = inject(NGXLogger); + @ViewChild(InputWithActionComponent) protected readonly input: InputWithActionComponent; + protected readonly trackBy = trackByFactory(); + protected readonly comments = signal([]); + protected readonly currentUser = getCurrentUser(); + @Input({ required: true }) annotation: AnnotationWrapper; constructor( readonly permissionsService: PermissionsService, - private readonly _manualRedactionService: ManualRedactionService, - private readonly _commentingService: CommentingService, private readonly _loadingService: LoadingService, - private readonly _changeRef: ChangeDetectorRef, - protected readonly _state: FilePreviewStateService, - ) { - super(); + protected readonly state: FilePreviewStateService, + ) {} + + ngOnChanges(changes: SimpleChanges) { + const currentAnnotation: AnnotationWrapper = changes.annotation?.currentValue; + const previousAnnotation: AnnotationWrapper = changes.annotation?.previousValue; + const annotationChanged = currentAnnotation?.id !== previousAnnotation?.id; + const commentsChanged = currentAnnotation?.numberOfComments !== previousAnnotation?.numberOfComments; + if (annotationChanged || commentsChanged) { + this.#logger.info(`[COMMENTS] State of annotation ${this.annotation.value} changed. Fetch comments.`); + const request = this.#commentsApiService.fetch(this.state.dossierId, this.state.fileId, this.annotation.id); + request.then(comments => this.comments.set(comments)); + } } - ngOnInit() { - this.hiddenComments$ = this._commentingService.isActive$(this.annotation.id).pipe( - tap(active => { - this._hidden = !active; - }), - ); - - super._initContext({ - hiddenComments: this.hiddenComments$, - }); - } - - async addComment(value: string): Promise { + async add(value: string): Promise { if (!value) { return; } this._loadingService.start(); - const { dossierId, fileId } = this._state; - const commentId = await this._manualRedactionService.addComment(value, this.annotation.id, dossierId, fileId); - this.annotation.comments.push({ - text: value, - id: commentId, - annotationId: this.annotation.id, - user: this.currentUser.id, - }); - this._input.reset(); - this._changeRef.markForCheck(); + const { dossierId, fileId } = this.state; + const commentId = await this.#commentsApiService.add(value, this.annotation.id, dossierId, fileId); + this.annotation.numberOfComments++; + this.comments.update(current => [ + ...current, + { + text: value, + id: commentId, + annotationId: this.annotation.id, + user: this.currentUser.id, + }, + ]); + this.input.reset(); this._loadingService.stop(); } - toggleExpandComments(): void { - this._commentingService.toggle(this.annotation.id); - } - - async deleteComment(comment: IComment): Promise { + async remove(comment: IComment): Promise { this._loadingService.start(); - const { dossierId, fileId } = this._state; - await this._manualRedactionService.deleteComment(comment.id, this.annotation.id, dossierId, fileId); - this.annotation.comments.splice(this.annotation.comments.indexOf(comment), 1); - this._changeRef.markForCheck(); + const { dossierId, fileId } = this.state; + await this.#commentsApiService.remove(comment.id, this.annotation.id, dossierId, fileId); + this.annotation.numberOfComments--; + this.comments.update(current => current.filter(c => c.id !== comment.id)); this._loadingService.stop(); } } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts index 32326378d..e809b6ab5 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-providers.ts @@ -1,22 +1,21 @@ -import { ExcludedPagesService } from './services/excluded-pages.service'; -import { ViewModeService } from './services/view-mode.service'; -import { MultiSelectService } from './services/multi-select.service'; -import { DocumentInfoService } from './services/document-info.service'; -import { CommentingService } from './services/commenting.service'; -import { SkippedService } from './services/skipped.service'; -import { AnnotationActionsService } from './services/annotation-actions.service'; -import { FilePreviewStateService } from './services/file-preview-state.service'; -import { AnnotationReferencesService } from './services/annotation-references.service'; import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui'; -import { AnnotationProcessingService } from './services/annotation-processing.service'; -import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; -import { FileDataService } from './services/file-data.service'; -import { AnnotationsListingService } from './services/annotations-listing.service'; -import { StampService } from './services/stamp.service'; -import { PdfProxyService } from './services/pdf-proxy.service'; -import { PdfAnnotationActionsService } from './services/pdf-annotation-actions.service'; import { FilterService } from '@iqser/common-ui/lib/filtering'; import { SortingService } from '@iqser/common-ui/lib/sorting'; +import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; +import { AnnotationActionsService } from './services/annotation-actions.service'; +import { AnnotationProcessingService } from './services/annotation-processing.service'; +import { AnnotationReferencesService } from './services/annotation-references.service'; +import { AnnotationsListingService } from './services/annotations-listing.service'; +import { DocumentInfoService } from './services/document-info.service'; +import { ExcludedPagesService } from './services/excluded-pages.service'; +import { FileDataService } from './services/file-data.service'; +import { FilePreviewStateService } from './services/file-preview-state.service'; +import { MultiSelectService } from './services/multi-select.service'; +import { PdfAnnotationActionsService } from './services/pdf-annotation-actions.service'; +import { PdfProxyService } from './services/pdf-proxy.service'; +import { SkippedService } from './services/skipped.service'; +import { StampService } from './services/stamp.service'; +import { ViewModeService } from './services/view-mode.service'; export const filePreviewScreenProviders = [ FilterService, @@ -24,7 +23,6 @@ export const filePreviewScreenProviders = [ ViewModeService, MultiSelectService, DocumentInfoService, - CommentingService, SkippedService, AnnotationActionsService, PdfAnnotationActionsService, diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts index 328f9ae47..9f77c276c 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-actions.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { IqserDialog } from '@common-ui/dialog/iqser-dialog.service'; import { getConfig, Toaster } from '@iqser/common-ui'; import { List, log } from '@iqser/common-ui/lib/utils'; @@ -13,6 +13,7 @@ import { IRectangle, IResizeRequest, } from '@red/domain'; +import { CommentsApiService } from '@services/comments-api.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { PermissionsService } from '@services/permissions.service'; import { firstValueFrom, Observable, zip } from 'rxjs'; @@ -46,6 +47,7 @@ import { SkippedService } from './skipped.service'; @Injectable() export class AnnotationActionsService { readonly #isDocumine = getConfig().IS_DOCUMINE; + readonly #commentsApiService = inject(CommentsApiService); constructor( private readonly _manualRedactionService: ManualRedactionService, @@ -129,7 +131,7 @@ export class AnnotationActionsService { if (result.comment) { try { for (const a of annotations) { - await this._manualRedactionService.addComment(result.comment, a.id, dossierId, fileId); + await this.#commentsApiService.add(result.comment, a.id, dossierId, fileId); } } catch (error) { this._toaster.rawError(error.error.message); diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts index 0c7f3215f..06f0e5db4 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-processing.service.ts @@ -42,7 +42,7 @@ export class AnnotationProcessingService { label: _('filter-menu.with-comments'), checked: false, topLevelFilter: true, - checker: (annotation: AnnotationWrapper) => annotation?.comments?.length > 0, + checker: (annotation: AnnotationWrapper) => annotation?.numberOfComments > 0, }, { id: 'redaction-changes', diff --git a/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts b/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts deleted file mode 100644 index 494cfb796..000000000 --- a/apps/red-ui/src/app/modules/file-preview/services/commenting.service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject, Observable } from 'rxjs'; -import { map, startWith } from 'rxjs/operators'; -import { shareDistinctLast } from '@iqser/common-ui/lib/utils'; - -@Injectable() -export class CommentingService { - private _activeAnnotations = new BehaviorSubject>(new Set()); - - /** Annotations with active comments section */ - isActive$(annotationId: string): Observable { - return this._activeAnnotations.pipe( - map(annotations => annotations.has(annotationId)), - startWith(false), - shareDistinctLast(), - ); - } - - toggle(annotationId: string): void { - if (this._activeAnnotations.value.has(annotationId)) { - this._deactivate(annotationId); - } else { - this._activate(annotationId); - } - } - - private _activate(annotationId: string): void { - const currentValue = this._activeAnnotations.value; - const newSet = new Set(currentValue).add(annotationId); - this._activeAnnotations.next(newSet); - } - - private _deactivate(annotationId: string): void { - const currentValue = this._activeAnnotations.value; - const newSet = new Set(currentValue); - newSet.delete(annotationId); - this._activeAnnotations.next(newSet); - } -} diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index 38eadfafe..1f08b8b01 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -212,6 +212,9 @@ export class FileDataService extends EntitiesService { super(); } - async addComment(comment: string, annotationId: string, dossierId: string, fileId: string) { - const url = `${this._defaultModelPath}/comment/add/${dossierId}/${fileId}/${annotationId}`; - const request = await firstValueFrom(this._post<{ commentId: string }>({ text: comment }, url)); - return request.commentId; - } - - deleteComment(commentId: string, annotationId: string, dossierId: string, fileId: string) { - const url = `${this._defaultModelPath}/comment/undo/${dossierId}/${fileId}/${annotationId}/${commentId}`; - return firstValueFrom(super.delete({}, url)); - } - addRecommendation(annotations: AnnotationWrapper[], redaction: IAddRedactionRequest, dossierId: string, fileId: string) { const recommendations: List = annotations.map(annotation => ({ addToDictionary: redaction.addToDictionary, diff --git a/apps/red-ui/src/app/services/comments-api.service.ts b/apps/red-ui/src/app/services/comments-api.service.ts new file mode 100644 index 000000000..5f78a71e9 --- /dev/null +++ b/apps/red-ui/src/app/services/comments-api.service.ts @@ -0,0 +1,28 @@ +import { Injectable, signal } from '@angular/core'; +import { GenericService } from '@common-ui/services/generic.service'; +import { IComment } from '@red/domain'; +import { firstValueFrom, map } from 'rxjs'; + +@Injectable({ + providedIn: 'root', +}) +export class CommentsApiService extends GenericService { + protected readonly _defaultModelPath = 'manualRedaction'; + readonly comments = signal>({}); + + async add(comment: string, annotationId: string, dossierId: string, fileId: string) { + const url = `${this._defaultModelPath}/comment/add/${dossierId}/${fileId}/${annotationId}`; + const request = await firstValueFrom(this._post<{ commentId: string }>({ text: comment }, url)); + return request.commentId; + } + + remove(commentId: string, annotationId: string, dossierId: string, fileId: string) { + const url = `${this._defaultModelPath}/comment/undo/${dossierId}/${fileId}/${annotationId}/${commentId}`; + return firstValueFrom(super.delete({}, url)); + } + + fetch(dossierId: string, fileId: string, annotationId: string): Promise { + const url = `${this._defaultModelPath}/comments/${dossierId}/${fileId}/${annotationId}`; + return firstValueFrom(super.getAll<{ comments: IComment[] }>(url).pipe(map(res => res.comments))); + } +} diff --git a/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts b/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts index 9a7db5e90..21d94933f 100644 --- a/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts +++ b/libs/red-domain/src/lib/redaction-log/entity-log-entry.ts @@ -37,4 +37,5 @@ export interface IEntityLogEntry extends ITrackable { engines: LogEntryEngine[]; reference: string[]; importedRedactionIntersections: string[]; + numberOfComments: number; } From 6cac3f94a22fc1f3fdb76e79ccc559cd6a20613e Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Mon, 30 Oct 2023 20:57:58 +0200 Subject: [PATCH 09/10] RED-7619 update dockerfile --- docker/red-ui/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/red-ui/Dockerfile b/docker/red-ui/Dockerfile index 5987c95ac..f48d35cb4 100644 --- a/docker/red-ui/Dockerfile +++ b/docker/red-ui/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.8-buster as builder +FROM node:20.9-buster as builder WORKDIR /ng-app @@ -31,7 +31,7 @@ CMD ["/bin/cp", "-r", "/ng-app/dist/paligo-styles", "/tmp/styles-export"] ### STAGE 2: Setup ### -FROM nginx:1.25.2-alpine +FROM nginx:1.25.3-alpine ## Copy our default nginx config COPY docker/common/nginx/nginx.conf /etc/nginx/conf.d/default.conf From 70c76ee8ae5fee3ddf63c3bae9617a10173d198f Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Mon, 30 Oct 2023 21:54:49 +0200 Subject: [PATCH 10/10] RED-7619 update translations --- apps/red-ui/src/assets/i18n/redact/de.json | 3 +-- apps/red-ui/src/assets/i18n/redact/en.json | 3 +-- apps/red-ui/src/assets/i18n/scm/de.json | 3 +-- apps/red-ui/src/assets/i18n/scm/en.json | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index c8b2efd8a..9a3c2b790 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -3,8 +3,7 @@ "header": { "add-to-dictionary": "Zum Wörterbuch hinzufügen", "request-add-to-dictionary": "Request add to dictionary" - }, - "multiple-values": "Multiple recommendations selected" + } }, "account-settings": "Kontoeinstellungen", "actions": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 675a077c9..1963a00ca 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -3,8 +3,7 @@ "header": { "add-to-dictionary": "Add to dictionary", "request-add-to-dictionary": "Request add to dictionary" - }, - "multiple-values": "Multiple recommendations selected" + } }, "account-settings": "Account Settings", "actions": { diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 374482c65..37e8fcf0c 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -3,8 +3,7 @@ "header": { "add-to-dictionary": "", "request-add-to-dictionary": "" - }, - "multiple-values": "" + } }, "account-settings": "Account Einstellungen", "actions": { diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 83af62c38..12b31119e 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -3,8 +3,7 @@ "header": { "add-to-dictionary": "Add to dictionary", "request-add-to-dictionary": "Request add to dictionary" - }, - "multiple-values": "Multiple recommendations selected" + } }, "account-settings": "Account Settings", "actions": {