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 06ef6596b..cf088d9bf 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 @@ -176,5 +176,14 @@ [type]="buttonType" icon="iqser:trash" > + + 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 7162ba49a..395c17f01 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 @@ -78,6 +78,10 @@ export class AnnotationActionsComponent implements OnChanges { this.annotationActionsService.removeOrSuggestRemoveAnnotation(this.annotations, removeFromDict); } + removeOrSuggestRemoveRedaction() { + this.annotationActionsService.removeOrSuggestRemoveRedaction(this.annotations); + } + markAsFalsePositive() { this.annotationActionsService.markAsFalsePositive(this.annotations); } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html index 92af9cacc..9b9426339 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html @@ -10,7 +10,7 @@ - +
@@ -37,7 +37,7 @@
- +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss index 84db58094..0bc0b2eb8 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss @@ -2,3 +2,7 @@ label { font-weight: bold; padding-bottom: 8px; } + +iqser-details-radio { + padding-top: 20px; +} diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts index 83e36d099..e7db28d0d 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.ts @@ -13,6 +13,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ManualRedactionEntryType, ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; import { redactTextTranslations } from '@translations/redact-text-translations'; import { RedactTextOption, RedactTextOptions } from './redact-text-options'; +import { tap } from 'rxjs/operators'; const PIN_ICON = 'red:push-pin'; const FOLDER_ICON = 'red:folder'; @@ -24,13 +25,13 @@ const FOLDER_ICON = 'red:folder'; export class RedactTextDialogComponent extends BaseDialogComponent implements OnInit { readonly roles = Roles; readonly options: DetailsRadioOption[]; + readonly type: ManualRedactionEntryType; dictionaryRequest = false; legalOptions: LegalBasisOption[] = []; dictionaries: Dictionary[] = []; readonly #translations = redactTextTranslations; readonly #dossier: Dossier; - readonly #type: ManualRedactionEntryType; constructor( private _justificationsService: JustificationsService, @@ -43,7 +44,7 @@ export class RedactTextDialogComponent extends BaseDialogComponent implements On super(_dialogRef); this.#dossier = _activeDossiersService.find(this.data.dossierId); - this.#type = this.data.manualRedactionEntryWrapper.type; + this.type = this.data.manualRedactionEntryWrapper.type; this.options = this.#options(); this.form = this.#getForm(); @@ -62,6 +63,17 @@ export class RedactTextDialogComponent extends BaseDialogComponent implements On this.#selectReason(); this.#formatSelectedTextValue(); + + this._subscriptions.add( + this.form + .get('option') + .valueChanges.pipe( + tap((option: DetailsRadioOption) => { + this.dictionaryRequest = option.value === RedactTextOptions.IN_DOSSIER; + }), + ) + .subscribe(), + ); } get displayedDictionaryLabel() { @@ -85,11 +97,6 @@ export class RedactTextDialogComponent extends BaseDialogComponent implements On } } - // toggleType() { - // console.log('test'); - // this.dictionaryRequest = this.form.get('option').value === RedactTextOptions.IN_DOSSIER; - // } - #getForm(): UntypedFormGroup { return this._formBuilder.group({ selectedText: this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value, @@ -98,7 +105,7 @@ export class RedactTextDialogComponent extends BaseDialogComponent implements On dictionary: [null, Validators.required], classification: '', multiplePages: '', - option: [this.options[0], Validators.required], + option: [this.options[0]], }); } @@ -147,14 +154,14 @@ export class RedactTextDialogComponent extends BaseDialogComponent implements On #options() { return [ { - label: this.#translations[this.#type].onlyHere.label, - description: this.#translations[this.#type].onlyHere.description, + label: this.#translations[this.type].onlyHere.label, + description: this.#translations[this.type].onlyHere.description, icon: PIN_ICON, value: RedactTextOptions.ONLY_HERE, }, { - label: this.#translations[this.#type].inDossier.label, - description: this.#translations[this.#type].inDossier.description, + label: this.#translations[this.type].inDossier.label, + description: this.#translations[this.type].inDossier.description, icon: FOLDER_ICON, value: RedactTextOptions.IN_DOSSIER, }, diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.scss b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.scss new file mode 100644 index 000000000..e69de29bb 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 new file mode 100644 index 000000000..942bb7d78 --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts @@ -0,0 +1,65 @@ +import { Component, Inject } from '@angular/core'; +import { BaseDialogComponent, DetailsRadioOption } from '@iqser/common-ui'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { RemoveRedactionOption, RemoveRedactionOptions } from './remove-redaction-options'; +import { UntypedFormGroup } from '@angular/forms'; +import { removeRedactionTranslations } from '@translations/remove-redaction-translations'; + +const PIN_ICON = 'red:push-pin'; +const FOLDER_ICON = 'red:folder'; +const REMOVE_FROM_DICT_ICON = 'red:remove-from-dict'; + +@Component({ + templateUrl: './remove-redaction-dialog.html', + styleUrls: ['./remove-redaction-dialog.component.scss'], +}) +export class RemoveRedactionDialogComponent extends BaseDialogComponent { + readonly options: DetailsRadioOption[]; + + readonly #translations = removeRedactionTranslations; + + constructor( + protected readonly _dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) readonly data: NonNullable, + ) { + super(_dialogRef); + + this.options = this.#options(); + this.form = this.#getForm(); + this.initialFormValue = this.form.getRawValue(); + } + + save(): void { + console.log('test'); + } + + #getForm(): UntypedFormGroup { + return this._formBuilder.group({ + comment: [null], + option: [this.options[0]], + }); + } + + #options() { + return [ + { + label: this.#translations.ONLY_HERE.label, + description: this.#translations.ONLY_HERE.description, + icon: PIN_ICON, + value: RemoveRedactionOptions.ONLY_HERE, + }, + { + label: this.#translations.IN_DOSSIER.label, + description: this.#translations.IN_DOSSIER.description, + icon: FOLDER_ICON, + value: RemoveRedactionOptions.IN_DOSSIER, + }, + { + label: this.#translations.FALSE_POSITIVE.label, + description: this.#translations.FALSE_POSITIVE.description, + icon: REMOVE_FROM_DICT_ICON, + value: RemoveRedactionOptions.FALSE_POSITIVE, + }, + ]; + } +} diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.html b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.html new file mode 100644 index 000000000..9ef3350bd --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.html @@ -0,0 +1,35 @@ +
+
+
+ +
+ + +
+ + +
+
+ +
+ + + +
+
+
+ + +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-options.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-options.ts new file mode 100644 index 000000000..56a0bde4e --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-options.ts @@ -0,0 +1,7 @@ +export const RemoveRedactionOptions = { + ONLY_HERE: 'ONLY_HERE', + IN_DOSSIER: 'IN_DOSSIER', + FALSE_POSITIVE: 'FALSE_POSITIVE', +} as const; + +export type RemoveRedactionOption = keyof typeof RemoveRedactionOptions; 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 32efb144e..1dbaf9ceb 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 @@ -66,6 +66,7 @@ import { SharedModule } from '@shared/shared.module'; import { SharedDossiersModule } from '../shared-dossiers/shared-dossiers.module'; import { FalsePositiveDialogComponent } from './dialogs/false-positive-dialog/false-positive-dialog.component'; import { RedactTextDialogComponent } from './dialogs/redact-text-dialog/redact-text-dialog.component'; +import { RemoveRedactionDialogComponent } from './dialogs/remove-redaction-dialog/remove-redaction-dialog.component'; const routes: IqserRoutes = [ { @@ -91,6 +92,7 @@ const dialogs = [ RssDialogComponent, FalsePositiveDialogComponent, RedactTextDialogComponent, + RemoveRedactionDialogComponent, ]; const components = [ 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 6163a1650..7955420a9 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 @@ -129,6 +129,24 @@ export class AnnotationActionsService { }); } + removeOrSuggestRemoveRedaction(annotations: AnnotationWrapper[]) { + const data = { + annotationsToRemove: annotations, + dossier: this._state.dossier(), + hint: annotations[0].hintDictionary, + }; + const { dossierId, fileId } = this._state; + this._dialogService.openDialog('removeRedaction', data, (result: { comment: string }) => { + const body = annotations.map(annotation => ({ + annotationId: annotation.id, + comment: result.comment, + })); + this.#processObsAndEmit( + this._manualRedactionService.removeOrSuggestRemove(body, dossierId, fileId, true, annotations[0].isHint), + ).then(); + }); + } + recategorizeImages(annotations: AnnotationWrapper[]) { const data = { annotations, dossier: this._state.dossier() }; const { dossierId, fileId } = this._state; diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts index b848da12c..e3f995715 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-dialog.service.ts @@ -12,6 +12,7 @@ import { HighlightActionDialogComponent } from '../dialogs/highlight-action-dial import { RssDialogComponent } from '../dialogs/rss-dialog/rss-dialog.component'; import { FalsePositiveDialogComponent } from '../dialogs/false-positive-dialog/false-positive-dialog.component'; import { RedactTextDialogComponent } from '../dialogs/redact-text-dialog/redact-text-dialog.component'; +import { RemoveRedactionDialogComponent } from '../dialogs/remove-redaction-dialog/remove-redaction-dialog.component'; type DialogType = | 'confirm' @@ -25,7 +26,8 @@ type DialogType = | 'manualAnnotation' | 'highlightAction' | 'falsePositive' - | 'redactText'; + | 'redactText' + | 'removeRedaction'; @Injectable() export class FilePreviewDialogService extends DialogService { @@ -70,6 +72,9 @@ export class FilePreviewDialogService extends DialogService { redactText: { component: RedactTextDialogComponent, }, + removeRedaction: { + component: RemoveRedactionDialogComponent, + }, }; constructor(protected readonly _dialog: MatDialog) { 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 0fe12e20f..d63300232 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 @@ -129,6 +129,13 @@ export class PdfAnnotationActionsService { availableActions.push(removeOrSuggestToRemoveOnlyHereButton); } + if (permissions.canRemoveOrSuggestToRemoveOnlyHere) { + const removeOrSuggestToRemoveButton = this.#getButton('trash', _('annotation-actions.remove-annotation.remove-redaction'), () => + this.#annotationActionsService.removeOrSuggestRemoveRedaction(annotations), + ); + availableActions.push(removeOrSuggestToRemoveButton); + } + return availableActions; } diff --git a/apps/red-ui/src/app/translations/remove-redaction-translations.ts b/apps/red-ui/src/app/translations/remove-redaction-translations.ts new file mode 100644 index 000000000..d90195846 --- /dev/null +++ b/apps/red-ui/src/app/translations/remove-redaction-translations.ts @@ -0,0 +1,22 @@ +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { RemoveRedactionOption } from '../modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-options'; + +interface Option { + label: string; + description: string; +} + +export const removeRedactionTranslations: { [key in RemoveRedactionOption]: Option } = { + ONLY_HERE: { + label: _('remove-redaction.dialog.content.options.only-here.label'), + description: _('remove-redaction.dialog.content.options.only-here.description'), + }, + IN_DOSSIER: { + label: _('remove-redaction.dialog.content.options.in-dossier.label'), + description: _('remove-redaction.dialog.content.options.in-dossier.description'), + }, + FALSE_POSITIVE: { + label: _('remove-redaction.dialog.content.options.false-positive.label'), + description: _('remove-redaction.dialog.content.options.false-positive.description'), + }, +}; diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index 2d621be68..9f00d6961 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -328,7 +328,8 @@ "remove-annotation": { "false-positive": "Falsch positiv", "only-here": "nur hier entfernen", - "remove-from-dict": "Aus dem Wörterbuch entfernen" + "remove-from-dict": "Aus dem Wörterbuch entfernen", + "remove-redaction": "" }, "remove-highlights": { "label": "" @@ -1958,6 +1959,33 @@ }, "value": "Wert" }, + "remove-redaction": { + "dialog": { + "actions": { + "cancel": "", + "save": "" + }, + "content": { + "comment": "", + "comment-placeholder": "", + "options": { + "false-positive": { + "description": "", + "label": "" + }, + "in-dossier": { + "description": "", + "label": "" + }, + "only-here": { + "description": "", + "label": "" + } + } + }, + "title": "" + } + }, "report-type": { "label": "{length} {length, plural, one{Berichtstyp} other{Berichtstypen}}" }, diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 0446bd7a9..1712bdf73 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -328,7 +328,8 @@ "remove-annotation": { "false-positive": "False Positive", "only-here": "Remove only here", - "remove-from-dict": "Remove from dictionary" + "remove-from-dict": "Remove from dictionary", + "remove-redaction": "Remove" }, "remove-highlights": { "label": "Remove Selected Earmarks" @@ -1958,6 +1959,33 @@ }, "value": "Value" }, + "remove-redaction": { + "dialog": { + "actions": { + "cancel": "Cancel", + "save": "Save" + }, + "content": { + "comment": "Comment", + "comment-placeholder": "Add remarks or mentions ...", + "options": { + "false-positive": { + "description": "\"White\" is not a CBI Author in this context: \"White rabbits are\".", + "label": "False positive" + }, + "in-dossier": { + "description": "Do not redact \"White\" in any document of the current dossier.", + "label": "Remove in dossier" + }, + "only-here": { + "description": "Do not redact \"White\" at this position in the current document.", + "label": "Remove here" + } + } + }, + "title": "Remove redaction" + } + }, "report-type": { "label": "{length} report {length, plural, one{type} other{types}}" }, diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 6cdc7d44e..a086a88cc 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -328,7 +328,8 @@ "remove-annotation": { "false-positive": "Falsch positiv", "only-here": "nur hier entfernen", - "remove-from-dict": "Aus dem Wörterbuch entfernen" + "remove-from-dict": "Aus dem Wörterbuch entfernen", + "remove-redaction": "" }, "remove-highlights": { "label": "" @@ -1958,6 +1959,33 @@ }, "value": "Wert" }, + "remove-redaction": { + "dialog": { + "actions": { + "cancel": "", + "save": "" + }, + "content": { + "comment": "", + "comment-placeholder": "", + "options": { + "false-positive": { + "description": "", + "label": "" + }, + "in-dossier": { + "description": "", + "label": "" + }, + "only-here": { + "description": "", + "label": "" + } + } + }, + "title": "" + } + }, "report-type": { "label": "{length} {length, plural, one{Berichtstyp} other{Berichtstypen}}" }, diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 349592572..2eaf5bbd8 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -328,7 +328,8 @@ "remove-annotation": { "false-positive": "False Positive", "only-here": "Remove only here", - "remove-from-dict": "Remove from dictionary" + "remove-from-dict": "Remove from dictionary", + "remove-redaction": "Remove" }, "remove-highlights": { "label": "Remove Selected Earmarks" @@ -1958,6 +1959,33 @@ }, "value": "Value" }, + "remove-redaction": { + "dialog": { + "actions": { + "cancel": "Cancel", + "save": "Save" + }, + "content": { + "comment": "Comment", + "comment-placeholder": "Add remarks or mentions ...", + "options": { + "false-positive": { + "description": "\"White\" is not a CBI Author in this context: \"White rabbits are\".", + "label": "False positive" + }, + "in-dossier": { + "description": "Do not redact \"White\" in any document of the current dossier.", + "label": "Remove in dossier" + }, + "only-here": { + "description": "Do not redact \"White\" at this position in the current document.", + "label": "Remove here" + } + } + }, + "title": "Remove redaction" + } + }, "report-type": { "label": "{length} report {length, plural, one{type} other{types}}" }, diff --git a/libs/common-ui b/libs/common-ui index e23f355ae..5a027f7e1 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit e23f355aefa0d723783eff1860fa549e56d7cf71 +Subproject commit 5a027f7e1cb7aa1b093fc2f664bf6c1d3b919a8f