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 a00e57441..d19b067c3 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 @@ -15,29 +15,36 @@ export const canAcceptRecommendation = (annotation: AnnotationWrapper) => annota export const canMarkAsFalsePositive = (annotation: AnnotationWrapper, annotationEntity: Dictionary) => annotation.canBeMarkedAsFalsePositive && annotationEntity?.hasDictionary; -export const canRemoveOnlyHere = (annotation: AnnotationWrapper, canAddRedaction: boolean) => - canAddRedaction && !annotation.pending && (annotation.isRedacted || (annotation.isHint && !annotation.isImage)); +export const canRemoveOnlyHere = (annotation: AnnotationWrapper, canAddRedaction: boolean, autoAnalysisDisabled: boolean) => + canAddRedaction && + (autoAnalysisDisabled || !annotation.pending) && + (annotation.isRedacted || (annotation.isHint && !annotation.isImage)); -export const canRemoveFromDictionary = (annotation: AnnotationWrapper) => +export const canRemoveFromDictionary = (annotation: AnnotationWrapper, autoAnalysisDisabled: boolean) => annotation.isModifyDictionary && (annotation.isRedacted || annotation.isSkipped || annotation.isHint) && - !annotation.pending && + (autoAnalysisDisabled || !annotation.pending) && !annotation.hasBeenResized; export const canRemoveRedaction = (annotation: AnnotationWrapper, permissions: AnnotationPermissions) => !annotation.isIgnoredHint && (permissions.canRemoveOnlyHere || permissions.canRemoveFromDictionary || permissions.canMarkAsFalsePositive); -export const canChangeLegalBasis = (annotation: AnnotationWrapper, canAddRedaction: boolean) => - canAddRedaction && annotation.isRedacted && !annotation.pending; +export const canChangeLegalBasis = (annotation: AnnotationWrapper, canAddRedaction: boolean, autoAnalysisDisabled: boolean) => + canAddRedaction && annotation.isRedacted && (autoAnalysisDisabled || !annotation.pending); -export const canRecategorizeAnnotation = (annotation: AnnotationWrapper, canRecategorize: boolean) => - canRecategorize && (annotation.isImage || annotation.isDictBasedHint) && !annotation.pending; +export const canRecategorizeAnnotation = (annotation: AnnotationWrapper, canRecategorize: boolean, autoAnalysisDisabled: boolean) => + canRecategorize && (annotation.isImage || annotation.isDictBasedHint) && (autoAnalysisDisabled || !annotation.pending); -export const canResizeAnnotation = (annotation: AnnotationWrapper, canAddRedaction: boolean, hasDictionary = false) => +export const canResizeAnnotation = ( + annotation: AnnotationWrapper, + canAddRedaction: boolean, + autoAnalysisDisabled: boolean, + hasDictionary = false, +) => canAddRedaction && !annotation.isSkipped && - !annotation.pending && + (autoAnalysisDisabled || !annotation.pending) && (annotation.isRedacted || annotation.isImage || annotation.isDictBasedHint || 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 e99e52326..bdb75e87d 100644 --- a/apps/red-ui/src/app/models/file/annotation.permissions.ts +++ b/apps/red-ui/src/app/models/file/annotation.permissions.ts @@ -41,6 +41,7 @@ export class AnnotationPermissions { annotations: AnnotationWrapper | AnnotationWrapper[], entities: Dictionary[], permissionsService: IqserPermissionsService, + autoAnalysisDisabled: boolean, ) { if (!isArray(annotations)) { annotations = [annotations]; @@ -57,12 +58,17 @@ export class AnnotationPermissions { permissions.canForceRedaction = canForceRedaction(annotation, canAddRedaction); permissions.canAcceptRecommendation = canAcceptRecommendation(annotation); permissions.canMarkAsFalsePositive = canMarkAsFalsePositive(annotation, annotationEntity); - permissions.canRemoveOnlyHere = canRemoveOnlyHere(annotation, canAddRedaction); - permissions.canRemoveFromDictionary = canRemoveFromDictionary(annotation); + permissions.canRemoveOnlyHere = canRemoveOnlyHere(annotation, canAddRedaction, autoAnalysisDisabled); + permissions.canRemoveFromDictionary = canRemoveFromDictionary(annotation, autoAnalysisDisabled); permissions.canRemoveRedaction = canRemoveRedaction(annotation, permissions); - permissions.canChangeLegalBasis = canChangeLegalBasis(annotation, canAddRedaction); - permissions.canRecategorizeAnnotation = canRecategorizeAnnotation(annotation, canAddRedaction); - permissions.canResizeAnnotation = canResizeAnnotation(annotation, canAddRedaction, annotationEntity?.hasDictionary); + permissions.canChangeLegalBasis = canChangeLegalBasis(annotation, canAddRedaction, autoAnalysisDisabled); + permissions.canRecategorizeAnnotation = canRecategorizeAnnotation(annotation, canAddRedaction, autoAnalysisDisabled); + permissions.canResizeAnnotation = canResizeAnnotation( + annotation, + canAddRedaction, + autoAnalysisDisabled, + annotationEntity?.hasDictionary, + ); permissions.canEditAnnotations = canEditAnnotation(annotation); permissions.canEditHints = canEditHint(annotation); permissions.canEditImages = canEditImage(annotation); 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 2611dc36a..219ad821b 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 @@ -165,6 +165,7 @@ export class AnnotationActionsComponent implements OnChanges { this.#annotations, this._state.dictionaries, this._iqserPermissionsService, + this._state.file().excludedFromAutomaticAnalysis, ); } 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 9f77c276c..d1f546119 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 @@ -91,7 +91,8 @@ export class AnnotationActionsService { } async editRedaction(annotations: AnnotationWrapper[]) { - const { dossierId, dossierTemplateId, fileId } = this._state; + const { dossierId, dossierTemplateId, fileId, file } = this._state; + const isUnprocessed = annotations.every(annotation => annotation.pending); const dossierTemplate = this._dossierTemplatesService.find(dossierTemplateId); const data = { annotations, @@ -118,14 +119,28 @@ export class AnnotationActionsService { section: result.section ?? annotation.section, value: result.value ?? annotation.value, })); - requests.push(this._manualRedactionService.changeLegalBasis(changeLegalBasisBody, dossierId, fileId)); + requests.push( + this._manualRedactionService.changeLegalBasis( + changeLegalBasisBody, + dossierId, + fileId, + file().excludedFromAutomaticAnalysis && isUnprocessed, + ), + ); } if (result.type && !annotations.every(annotation => annotation.type === result.type)) { const recategorizeBody: List = annotations.map(annotation => ({ annotationId: annotation.id, type: result.type ?? annotation.type, })); - requests.push(this._manualRedactionService.recategorizeRedactions(recategorizeBody, dossierId, fileId)); + requests.push( + this._manualRedactionService.recategorizeRedactions( + recategorizeBody, + dossierId, + fileId, + file().excludedFromAutomaticAnalysis && isUnprocessed, + ), + ); } if (result.comment) { @@ -152,6 +167,7 @@ export class AnnotationActionsService { }; const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); const isApprover = this._permissionsService.isApprover(this._state.dossier()); + const isUnprocessed = redactions.every(annotation => annotation.pending); const data = { redactions, @@ -174,7 +190,7 @@ export class AnnotationActionsService { ) { this.#setAsFalsePositive(redactions, result); } else { - this.#removeRedaction(redactions, result); + this.#removeRedaction(redactions, result, this._state.file().excludedFromAutomaticAnalysis && isUnprocessed); } } @@ -241,6 +257,7 @@ export class AnnotationActionsService { const text = annotation.AREA ? annotation.value : isImageText; const isApprover = this._permissionsService.isApprover(dossier); const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); + const isUnprocessed = annotation.pending; const data = { redaction: annotation, @@ -267,8 +284,13 @@ export class AnnotationActionsService { await this.cancelResize(annotation); - const { fileId, dossierId } = this._state; - const request = this._manualRedactionService.resize([resizeRequest], dossierId, fileId); + const { fileId, dossierId, file } = this._state; + const request = this._manualRedactionService.resize( + [resizeRequest], + dossierId, + fileId, + isUnprocessed && file().excludedFromAutomaticAnalysis, + ); return this.#processObsAndEmit(request); } @@ -423,7 +445,7 @@ export class AnnotationActionsService { this.#processObsAndEmit(this._manualRedactionService.addAnnotation(requests, dossierId, fileId)).then(); } - #removeRedaction(redactions: AnnotationWrapper[], dialogResult: RemoveRedactionResult) { + #removeRedaction(redactions: AnnotationWrapper[], dialogResult: RemoveRedactionResult, includeUnprocessed = false) { const removeFromDictionary = dialogResult.option.value === RemoveRedactionOptions.IN_DOSSIER; const body = redactions.map(redaction => ({ annotationId: redaction.id, @@ -434,7 +456,9 @@ export class AnnotationActionsService { // todo: might not be correct, probably shouldn't get to this point if they are not all the same const isHint = redactions.every(r => r.isHint); const { dossierId, fileId } = this._state; - this.#processObsAndEmit(this._manualRedactionService.removeRedaction(body, dossierId, fileId, removeFromDictionary, isHint)).then(); + this.#processObsAndEmit( + this._manualRedactionService.removeRedaction(body, dossierId, fileId, removeFromDictionary, isHint, includeUnprocessed), + ).then(); } #getRemoveRedactionDialog(data: RemoveRedactionData) { 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 2864bdc5f..e8c7799b1 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 @@ -62,12 +62,12 @@ export class ManualRedactionService extends GenericService { return this.addAnnotation(recommendations, dossierId, fileId); } - changeLegalBasis(body: List, dossierId: string, fileId: string) { - return this.legalBasisChange(body, dossierId, fileId).pipe(this.#showToast('change-legal-basis')); + changeLegalBasis(body: List, dossierId: string, fileId: string, includeUnprocessed = false) { + return this.legalBasisChange(body, dossierId, fileId, includeUnprocessed).pipe(this.#showToast('change-legal-basis')); } - recategorizeRedactions(body: List, dossierId: string, fileId: string) { - return this.recategorize(body, dossierId, fileId).pipe(this.#showToast('change-type')); + recategorizeRedactions(body: List, dossierId: string, fileId: string, includeUnprocessed = false) { + return this.recategorize(body, dossierId, fileId, includeUnprocessed).pipe(this.#showToast('change-type')); } addAnnotation( @@ -95,8 +95,17 @@ export class ManualRedactionService extends GenericService { 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)); + removeRedaction( + body: List, + dossierId: string, + fileId: string, + removeFromDictionary = false, + isHint = false, + includeUnprocessed = false, + ) { + return this.remove(body, dossierId, fileId, includeUnprocessed).pipe( + this.#showToast(!isHint ? 'remove' : 'remove-hint', removeFromDictionary), + ); } getTitle(type: ManualRedactionEntryType) { @@ -116,14 +125,17 @@ export class ManualRedactionService extends GenericService { return this._post(body, `${this.#bulkRedaction}/add/${dossierId}/${fileId}`).pipe(this.#log('Add', body)); } - recategorize(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRedaction}/recategorize/${dossierId}/${fileId}`).pipe(this.#log('Recategorize', body)); + recategorize(body: List, dossierId: string, fileId: string, includeUnprocessed = false) { + return this._post(body, `${this.#bulkRedaction}/recategorize/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`).pipe( + this.#log('Recategorize', body), + ); } - legalBasisChange(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRedaction}/legalBasisChange/${dossierId}/${fileId}`).pipe( - this.#log('Legal basis change', body), - ); + legalBasisChange(body: List, dossierId: string, fileId: string, includeUnprocessed = false) { + return this._post( + body, + `${this.#bulkRedaction}/legalBasisChange/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`, + ).pipe(this.#log('Legal basis change', body)); } undo(annotationIds: List, dossierId: string, fileId: string) { @@ -131,16 +143,20 @@ export class ManualRedactionService extends GenericService { return super.delete(annotationIds, url).pipe(this.#log('Undo', annotationIds)); } - remove(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRedaction}/remove/${dossierId}/${fileId}`).pipe(this.#log('Remove', body)); + remove(body: List, dossierId: string, fileId: string, includeUnprocessed = false) { + return this._post(body, `${this.#bulkRedaction}/remove/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`).pipe( + this.#log('Remove', body), + ); } forceRedaction(body: List, dossierId: string, fileId: string) { return this._post(body, `${this.#bulkRedaction}/force/${dossierId}/${fileId}`).pipe(this.#log('Force redaction', body)); } - resize(body: List, dossierId: string, fileId: string) { - return this._post(body, `${this.#bulkRedaction}/resize/${dossierId}/${fileId}`).pipe(this.#log('Resize', body)); + resize(body: List, dossierId: string, fileId: string, includeUnprocessed = false) { + return this._post(body, `${this.#bulkRedaction}/resize/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`).pipe( + this.#log('Resize', body), + ); } #log(action: string, body: unknown) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts index f967c3f73..a80b12d3f 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts @@ -133,7 +133,10 @@ export class PdfAnnotationActionsService { const dossier = this.#state.dossier(); const isApprover = this.#permissionsService.isApprover(dossier); const dictionaries = this.#state.dictionaries; - const permissions = annotations.map(a => AnnotationPermissions.forUser(isApprover, a, dictionaries, this.#iqserPermissionsService)); + const autoAnalysisDisabled = this.#state.file().excludedFromAutomaticAnalysis; + const permissions = annotations.map(a => + AnnotationPermissions.forUser(isApprover, a, dictionaries, this.#iqserPermissionsService, autoAnalysisDisabled), + ); return AnnotationPermissions.reduce(permissions); } }