diff --git a/apps/red-ui/src/app/modules/account/utils/dialog-defaults.ts b/apps/red-ui/src/app/modules/account/utils/dialog-defaults.ts index b5090ec0d..1ce97d73e 100644 --- a/apps/red-ui/src/app/modules/account/utils/dialog-defaults.ts +++ b/apps/red-ui/src/app/modules/account/utils/dialog-defaults.ts @@ -2,9 +2,15 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { addHintTranslations } from '@translations/add-hint-translations'; import { redactTextTranslations } from '@translations/redact-text-translations'; import { removeRedactionTranslations } from '@translations/remove-redaction-translations'; -import { ForceAnnotationOptions, RedactOrHintOptions, RemoveRedactionOptions } from '../../file-preview/utils/dialog-types'; +import { + ForceAnnotationOptions, + RectangleRedactOptions, + RedactOrHintOptions, + RemoveRedactionOptions, +} from '../../file-preview/utils/dialog-types'; export const SystemDefaults = { + RECTANGLE_REDACT_DEFAULT: RectangleRedactOptions.ONLY_THIS_PAGE, ADD_REDACTION_DEFAULT: RedactOrHintOptions.IN_DOSSIER, ADD_HINT_DEFAULT: RedactOrHintOptions.IN_DOSSIER, FORCE_REDACTION_DEFAULT: ForceAnnotationOptions.ONLY_HERE, diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/add-hint-dialog/add-hint-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/add-hint-dialog/add-hint-dialog.component.ts index 92258751a..2826b01a4 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/add-hint-dialog/add-hint-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/add-hint-dialog/add-hint-dialog.component.ts @@ -160,7 +160,7 @@ export class AddHintDialogComponent extends IqserDialogComponent): void { - this.#applyToAllDossiers = option.extraOption.checked; + this.#applyToAllDossiers = option.additionalCheck.checked; this.#setDictionaries(); if (this.#applyToAllDossiers && this.form.get('dictionary').value) { @@ -176,7 +176,7 @@ export class AddHintDialogComponent extends IqserDialogComponent d.type === selectedDictionaryType); - this.options[1].extraOption.disabled = selectedDictionary.dossierDictionaryOnly; + this.options[1].additionalCheck.disabled = selectedDictionary.dossierDictionaryOnly; } } @@ -223,7 +223,7 @@ export class AddHintDialogComponent extends IqserDialogComponent 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 2191aff10..1a4e8384e 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 @@ -25,11 +25,19 @@ import { SelectedAnnotationsTableComponent, ValueColumn, } from '../../components/selected-annotations-table/selected-annotations-table.component'; -import { getEditRedactionOptions } from '../../utils/dialog-options'; -import { EditRedactionData, EditRedactionOption, EditRedactResult } from '../../utils/dialog-types'; -import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component'; +import { getEditRedactionOptions, getRectangleRedactOptions } from '../../utils/dialog-options'; +import { + EditRedactionData, + EditRedactionOption, + EditRedactResult, + LegalBasisOption, + RectangleRedactOption, + RectangleRedactOptions, +} from '../../utils/dialog-types'; import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component'; import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option'; +import { validatePageRange } from '../../utils/form-validators'; +import { parseRectanglePosition, parseSelectedPageNumbers } from '../../utils/enhance-manual-redaction-request.utils'; interface TypeSelectOptions { type: string; @@ -80,7 +88,7 @@ export class EditRedactionDialogComponent { label: redaction.value, bold: true }, { label: redaction.typeLabel }, ]); - options = getEditRedactionOptions(); + options = this.allRectangles ? getRectangleRedactOptions('edit') : getEditRedactionOptions(); legalOptions: LegalBasisOption[] = []; dictionaries: Dictionary[] = []; typeSelectOptions: TypeSelectOptions[] = []; @@ -97,6 +105,14 @@ export class EditRedactionDialogComponent super(); } + extraOptionChanged(option: DetailsRadioOption): void { + if (option.value === RectangleRedactOptions.MULTIPLE_PAGES) { + setTimeout(() => { + this.form.get('option')?.updateValueAndValidity(); + }, 0); + } + } + get displayedDictionaryLabel() { const selectedDictionaryType = this.form.controls.type.value; if (selectedDictionaryType) { @@ -189,6 +205,13 @@ export class EditRedactionDialogComponent const value = this.form.value; const initialReason: LegalBasisOption = this.initialFormValue.reason; const initialLegalBasis = initialReason?.legalBasis ?? ''; + const pageNumbers = parseSelectedPageNumbers( + this.form.get('option').value.additionalInput?.value, + this.data.file, + this.data.annotations[0], + ); + const position = parseRectanglePosition(this.annotations[0]); + this.close({ legalBasis: value.reason?.legalBasis ?? (this.isImage ? initialLegalBasis : ''), section: value.section, @@ -196,6 +219,8 @@ export class EditRedactionDialogComponent type: value.type, value: this.allRectangles ? value.value : null, option: value.option.value, + position, + pageNumbers, }); } @@ -230,7 +255,7 @@ export class EditRedactionDialogComponent disabled: this.isImported, }), section: new FormControl({ value: sameSection ? this.annotations[0].section : null, disabled: this.isImported }), - option: new FormControl>(this.options[0]), + option: new FormControl>(this.options[0], validatePageRange()), value: new FormControl(this.allRectangles ? this.annotations[0].value : null), }); } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts index df634df2e..243f88bef 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts @@ -26,17 +26,11 @@ import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select import { MatTooltip } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option'; -import { ForceAnnotationOption, RedactOrHintOption } from '../../utils/dialog-types'; -import { getForceAnnotationOptions, getRedactOrHintOptions } from '../../utils/dialog-options'; +import { ForceAnnotationOption, LegalBasisOption } from '../../utils/dialog-types'; +import { getForceAnnotationOptions } from '../../utils/dialog-options'; import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component'; import { SystemDefaults } from '../../../account/utils/dialog-defaults'; -export interface LegalBasisOption { - label?: string; - legalBasis?: string; - description?: string; -} - const DOCUMINE_LEGAL_BASIS = 'n-a.'; @Component({ diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html deleted file mode 100644 index e5c522316..000000000 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html +++ /dev/null @@ -1,129 +0,0 @@ -
-
-
- -
-
- -
- {{ form.get('selectedText').value }} - -
- - -
- -
- -
- -
- - - - - - {{ displayedDictionaryLabel }} - - {{ dictionary.label }} - - - -
- -
- - - - - {{ option.label }} - - - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - {{ 'manual-annotation.dialog.content.apply-on-multiple-pages' | translate }} - - -
- - - {{ 'manual-annotation.dialog.content.apply-on-multiple-pages-hint' | translate }} -
-
-
- -
- - -
-
- - -
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts deleted file mode 100644 index c4630f766..000000000 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { Component, Inject, OnInit } from '@angular/core'; -import { ReactiveFormsModule, Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { - BaseDialogComponent, - CircleButtonComponent, - HasScrollbarDirective, - IconButtonComponent, - IqserDenyDirective, - IqserPermissionsService, -} from '@iqser/common-ui'; -import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; -import { Dictionary, Dossier, File, IAddRedactionRequest, SuperTypes } from '@red/domain'; -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 { firstValueFrom } from 'rxjs'; -import { ManualRedactionService } from '../../services/manual-redaction.service'; -import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service'; -import { NgForOf, NgIf } from '@angular/common'; -import { TranslateModule } from '@ngx-translate/core'; -import { MatFormField } from '@angular/material/form-field'; -import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select'; -import { MatTooltip } from '@angular/material/tooltip'; -import { MatCheckbox } from '@angular/material/checkbox'; - -export interface LegalBasisOption { - label?: string; - legalBasis?: string; - description?: string; -} - -export const NON_READABLE_CONTENT = 'non-readable content'; - -@Component({ - templateUrl: './manual-annotation-dialog.component.html', - styleUrls: ['./manual-annotation-dialog.component.scss'], - standalone: true, - imports: [ - ReactiveFormsModule, - NgIf, - CircleButtonComponent, - TranslateModule, - HasScrollbarDirective, - MatFormField, - MatSelectTrigger, - MatSelect, - MatOption, - NgForOf, - MatTooltip, - IqserDenyDirective, - MatCheckbox, - IconButtonComponent, - ], - providers: [ManualRedactionService], -}) -export class ManualAnnotationDialogComponent extends BaseDialogComponent implements OnInit { - readonly #dossier: Dossier; - readonly roles = Roles; - isDictionaryRequest: boolean; - isFalsePositiveRequest: boolean; - isEditingSelectedText = false; - applyOnMultiplePages = false; - manualRedactionTypeExists = true; - possibleDictionaries: Dictionary[] = []; - legalOptions: LegalBasisOption[] = []; - - constructor( - readonly iqserPermissionsService: IqserPermissionsService, - private readonly _justificationsService: JustificationsService, - private readonly _manualRedactionService: ManualRedactionService, - activeDossiersService: ActiveDossiersService, - private readonly _dictionaryService: DictionaryService, - protected readonly _dialogRef: MatDialogRef, - private readonly _annotationManager: REDAnnotationManager, - @Inject(MAT_DIALOG_DATA) readonly data: { manualRedactionEntryWrapper: ManualRedactionEntryWrapper; dossierId: string; file: File }, - ) { - super(_dialogRef); - this.#dossier = activeDossiersService.find(this.data.dossierId); - - this.isFalsePositiveRequest = this.data.manualRedactionEntryWrapper.type === 'FALSE_POSITIVE'; - this.isDictionaryRequest = this.data.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest; - - this.manualRedactionTypeExists = this._dictionaryService.hasManualType(this.#dossier.dossierTemplateId); - - this.form = this.#getForm(); - this.initialFormValue = this.form.getRawValue(); - } - - get title() { - return this._manualRedactionService.getTitle(this.data.manualRedactionEntryWrapper.type); - } - - get isRectangle() { - return !!this.data.manualRedactionEntryWrapper.manualRedactionEntry.rectangle; - } - - get displayedDictionaryLabel() { - const dictType = this.form.get('dictionary').value; - if (dictType) { - return this.possibleDictionaries.find(d => d.type === dictType).label; - } - return null; - } - - get disabled() { - return this.form.invalid || (this.applyOnMultiplePages && !this.form.get('multiplePages')?.value); - } - - async ngOnInit() { - this.possibleDictionaries = this.isDictionaryRequest - ? this._dictionaryService.getDictionariesOptions(this.#dossier.dossierTemplateId) - : this._dictionaryService.getRedactionTypes(this.#dossier.dossierTemplateId); - - const data = await firstValueFrom(this._justificationsService.getForDossierTemplate(this.#dossier.dossierTemplateId)); - this.legalOptions = data.map(lbm => ({ - legalBasis: lbm.reason, - description: lbm.description, - label: lbm.name, - })); - - this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); - - this.#selectReason(); - - if (!this.isRectangle) { - this.#formatSelectedTextValue(); - } - } - - save() { - this.#enhanceManualRedaction(this.data.manualRedactionEntryWrapper.manualRedactionEntry); - try { - const annotations = - this.isRectangle && !!this.form.get('multiplePages').value - ? this.#getRectangles() - : [this.data.manualRedactionEntryWrapper]; - this._dialogRef.close({ - annotations, - dictionary: this.possibleDictionaries.find(d => d.type === this.form.get('dictionary').value), - }); - } catch (e) { - this._toaster.error(_('manual-annotation.dialog.error')); - } - } - - close() { - super.close(); - if (this.isRectangle) { - this._annotationManager.delete(this._annotationManager.selected[0].Id); - } - } - - #getRectangles() { - const quads = this.data.manualRedactionEntryWrapper.manualRedactionEntry.positions.find(a => !!a); - const value: string = this.form.get('multiplePages').value.replace(/[^0-9-,]/g, ''); - const entry = { ...this.data.manualRedactionEntryWrapper.manualRedactionEntry }; - const wrapper = { ...this.data.manualRedactionEntryWrapper }; - const wrappers: ManualRedactionEntryWrapper[] = [wrapper]; - - value.split(',').forEach(range => { - const splitted = range.split('-'); - const startPage = parseInt(splitted[0], 10); - const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage; - if (!startPage || !endPage || startPage > this.data.file.numberOfPages || endPage > this.data.file.numberOfPages) { - throw new Error(); - } - - for (let page = startPage; page <= endPage; page++) { - if (page === wrapper.manualRedactionEntry.positions[0].page) { - continue; - } - const manualRedactionEntry = { ...entry, positions: [{ ...quads, page }] }; - wrappers.push({ ...wrapper, manualRedactionEntry }); - } - }); - - return wrappers; - } - - #formatSelectedTextValue() { - this.data.manualRedactionEntryWrapper.manualRedactionEntry.value = - this.data.manualRedactionEntryWrapper.manualRedactionEntry.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', - ); - } - - #getForm() { - return this._formBuilder.group({ - selectedText: this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value, - section: [null], - reason: this.isDictionaryRequest ? [null] : [null, Validators.required], - dictionary: this.isDictionaryRequest - ? [this.isFalsePositiveRequest ? 'false_positive' : null, Validators.required] - : [this.manualRedactionTypeExists ? SuperTypes.ManualRedaction : null, Validators.required], - comment: [null], - classification: [NON_READABLE_CONTENT], - multiplePages: '', - }); - } - - #enhanceManualRedaction(addRedactionRequest: IAddRedactionRequest) { - const legalOption: LegalBasisOption = this.form.get('reason').value; - addRedactionRequest.type = this.form.get('dictionary').value; - if (legalOption) { - addRedactionRequest.reason = legalOption.description; - addRedactionRequest.legalBasis = legalOption.legalBasis; - } - - if (this.iqserPermissionsService.has(Roles.getRss)) { - const selectedType = this.possibleDictionaries.find(d => d.type === addRedactionRequest.type); - addRedactionRequest.addToDictionary = selectedType.hasDictionary; - } else { - addRedactionRequest.addToDictionary = this.isDictionaryRequest && addRedactionRequest.type !== 'dossier_redaction'; - } - - if (!addRedactionRequest.reason) { - addRedactionRequest.reason = 'Dictionary Request'; - } - const commentValue = this.form.get('comment').value; - addRedactionRequest.comment = commentValue ? { text: commentValue } : null; - addRedactionRequest.section = this.form.get('section').value; - addRedactionRequest.value = addRedactionRequest.rectangle - ? this.form.get('classification').value - : this.form.get('selectedText').value; - } - - #selectReason() { - if (this.legalOptions.length === 1) { - this.form.get('reason').setValue(this.legalOptions[0]); - } - } -} diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.html new file mode 100644 index 000000000..deeeb9113 --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.html @@ -0,0 +1,62 @@ +
+
+
+ +
+ + +
+ + + + @for (option of legalOptions; track option) { + + {{ option.label }} + + } + + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ + +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.scss b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.scss similarity index 84% rename from apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.scss rename to apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.scss index a0421d753..a60ee0967 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.scss @@ -2,6 +2,11 @@ width: 100%; } +.dialog-content { + height: 650px; + overflow-y: auto; +} + .apply-on-multiple-pages { min-height: 55px; display: flex; diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts new file mode 100644 index 000000000..7bbe89cdb --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts @@ -0,0 +1,188 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { + CircleButtonComponent, + HasScrollbarDirective, + IconButtonComponent, + IqserDenyDirective, + IqserDialogComponent, + Toaster, +} from '@iqser/common-ui'; +import { Dossier, IAddRedactionRequest, SuperTypes } from '@red/domain'; +import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; +import { JustificationsService } from '@services/entity-services/justifications.service'; +import { Roles } from '@users/roles'; +import { firstValueFrom } from 'rxjs'; +import { ManualRedactionService } from '../../services/manual-redaction.service'; +import { NgForOf, NgIf } from '@angular/common'; +import { TranslateModule } from '@ngx-translate/core'; +import { MatFormField } from '@angular/material/form-field'; +import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select'; +import { MatTooltip } from '@angular/material/tooltip'; +import { MatCheckbox } from '@angular/material/checkbox'; +import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option'; +import { + LegalBasisOption, + RectangleDialogData, + RectangleDialogResult, + RectangleRedactOption, + RectangleRedactOptions, +} from '../../utils/dialog-types'; +import { getRectangleRedactOptions } from '../../utils/dialog-options'; +import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component'; +import { SystemDefaults } from '../../../account/utils/dialog-defaults'; +import { validatePageRange } from '../../utils/form-validators'; + +export const NON_READABLE_CONTENT = 'non-readable content'; + +@Component({ + templateUrl: './rectangle-annotation-dialog.component.html', + styleUrls: ['./rectangle-annotation-dialog.component.scss'], + standalone: true, + imports: [ + ReactiveFormsModule, + NgIf, + CircleButtonComponent, + TranslateModule, + HasScrollbarDirective, + MatFormField, + MatSelectTrigger, + MatSelect, + MatOption, + NgForOf, + MatTooltip, + IqserDenyDirective, + MatCheckbox, + IconButtonComponent, + DetailsRadioComponent, + ], + providers: [ManualRedactionService], +}) +export class RectangleAnnotationDialog + extends IqserDialogComponent + implements OnInit +{ + readonly #dossier: Dossier; + protected readonly roles = Roles; + protected readonly options: DetailsRadioOption[]; + protected legalOptions: LegalBasisOption[] = []; + + readonly form: UntypedFormGroup; + + constructor( + private readonly activeDossiersService: ActiveDossiersService, + private readonly _justificationsService: JustificationsService, + private readonly _formBuilder: FormBuilder, + private readonly _toaster: Toaster, + ) { + super(); + this.#dossier = activeDossiersService.find(this.data.dossierId); + + this.options = getRectangleRedactOptions(); + + this.form = this.#getForm(); + this.initialFormValue = this.form.getRawValue(); + } + + extraOptionChanged(option: DetailsRadioOption): void { + if (option.value === RectangleRedactOptions.MULTIPLE_PAGES) { + setTimeout(() => { + this.form.get('option')?.updateValueAndValidity(); + }, 0); + } + } + + async ngOnInit() { + const data = await firstValueFrom(this._justificationsService.getForDossierTemplate(this.#dossier.dossierTemplateId)); + this.legalOptions = data.map(lbm => ({ + legalBasis: lbm.reason, + description: lbm.description, + label: lbm.name, + })); + + this.legalOptions.sort((a, b) => a.label.localeCompare(b.label)); + + this.#selectReason(); + } + + save() { + this.#enhanceManualRedaction(this.data.manualRedactionEntryWrapper.manualRedactionEntry); + try { + const annotation = ( + this.form.get('option').value.value === RectangleRedactOptions.MULTIPLE_PAGES + ? this.#multiplePagesRectangle + : this.data.manualRedactionEntryWrapper + ).manualRedactionEntry; + super.close({ + annotation, + }); + } catch (e) { + this._toaster.error(_('manual-annotation.dialog.error')); + } + } + + #getForm() { + return this._formBuilder.group({ + selectedText: this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value, + section: [null], + reason: [null, Validators.required], + comment: [null], + classification: [NON_READABLE_CONTENT], + option: [this.#getOption(SystemDefaults.RECTANGLE_REDACT_DEFAULT), validatePageRange()], + }); + } + + #enhanceManualRedaction(addRedactionRequest: IAddRedactionRequest) { + const legalOption: LegalBasisOption = this.form.get('reason').value; + addRedactionRequest.type = SuperTypes.ManualRedaction; + if (legalOption) { + addRedactionRequest.reason = legalOption.description; + addRedactionRequest.legalBasis = legalOption.legalBasis; + } + + addRedactionRequest.addToDictionary = false; + const commentValue = this.form.get('comment').value; + addRedactionRequest.comment = commentValue ? { text: commentValue } : null; + addRedactionRequest.section = this.form.get('section').value; + addRedactionRequest.value = this.form.get('classification').value; + } + + #getOption(option: RectangleRedactOption): DetailsRadioOption { + return this.options.find(o => o.value === option); + } + + get #multiplePagesRectangle() { + const value: string = this.form.get('option').value.additionalInput.value.replace(/[^0-9-,]/g, ''); + const entry = { ...this.data.manualRedactionEntryWrapper.manualRedactionEntry, pageNumbers: [] }; + const wrapper = { + ...this.data.manualRedactionEntryWrapper, + manualRedactionEntry: entry, + }; + + value.split(',').forEach(range => { + const splitted = range.split('-'); + const startPage = parseInt(splitted[0], 10); + const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage; + if (!startPage || !endPage || startPage > this.data.file.numberOfPages || endPage > this.data.file.numberOfPages) { + throw new Error(); + } + + for (let page = startPage; page <= endPage; page++) { + if (page === wrapper.manualRedactionEntry.positions[0].page) { + continue; + } + + wrapper.manualRedactionEntry.pageNumbers.push(page); + } + }); + + return wrapper; + } + + #selectReason() { + if (this.legalOptions.length === 1) { + this.form.get('reason').setValue(this.legalOptions[0]); + } + } +} diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-recommendation-dialog/redact-recommendation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-recommendation-dialog/redact-recommendation-dialog.component.ts index 85a109583..1bca4ff37 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-recommendation-dialog/redact-recommendation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-recommendation-dialog/redact-recommendation-dialog.component.ts @@ -23,13 +23,13 @@ import { } from '../../components/selected-annotations-table/selected-annotations-table.component'; import { getRedactOrHintOptions } from '../../utils/dialog-options'; import { + LegalBasisOption, RedactOrHintOption, RedactOrHintOptions, RedactRecommendationData, RedactRecommendationResult, ResizeOptions, } from '../../utils/dialog-types'; -import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component'; @Component({ templateUrl: './redact-recommendation-dialog.component.html', @@ -128,7 +128,7 @@ export class RedactRecommendationDialogComponent } extraOptionChanged(option: DetailsRadioOption): void { - this.#applyToAllDossiers = option.extraOption.checked; + this.#applyToAllDossiers = option.additionalCheck.checked; this.#setDictionaries(); if (this.#applyToAllDossiers && this.form.controls.dictionary.value) { @@ -144,7 +144,7 @@ export class RedactRecommendationDialogComponent if (!this.#applyToAllDossiers) { const selectedDictionaryType = this.form.controls.dictionary.value; const selectedDictionary = this.dictionaries.find(d => d.type === selectedDictionaryType); - this.options[0].extraOption.disabled = selectedDictionary.dossierDictionaryOnly; + this.options[0].additionalCheck.disabled = selectedDictionary.dossierDictionaryOnly; } } 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 63332bb0a..21c95b325 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 @@ -21,8 +21,14 @@ import { firstValueFrom, Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { SystemDefaultOption, SystemDefaults } from '../../../account/utils/dialog-defaults'; import { getRedactOrHintOptions } from '../../utils/dialog-options'; -import { RedactOrHintOption, RedactOrHintOptions, RedactTextData, RedactTextResult, ResizeOptions } from '../../utils/dialog-types'; -import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component'; +import { + LegalBasisOption, + RedactOrHintOption, + RedactOrHintOptions, + RedactTextData, + RedactTextResult, + ResizeOptions, +} from '../../utils/dialog-types'; import { enhanceManualRedactionRequest, EnhanceRequestData } from '../../utils/enhance-manual-redaction-request.utils'; const MAXIMUM_TEXT_AREA_WIDTH = 421; @@ -150,7 +156,7 @@ export class RedactTextDialogComponent } extraOptionChanged(option: DetailsRadioOption): void { - this.#applyToAllDossiers = option.extraOption.checked; + this.#applyToAllDossiers = option.additionalCheck.checked; this.#setDictionaries(); if (this.#applyToAllDossiers && this.form.controls.dictionary.value) { @@ -166,7 +172,7 @@ export class RedactTextDialogComponent if (!this.#applyToAllDossiers) { const selectedDictionaryType = this.form.controls.dictionary.value; const selectedDictionary = this.dictionaries.find(d => d.type === selectedDictionaryType); - this.options[2].extraOption.disabled = selectedDictionary.dossierDictionaryOnly; + this.options[2].additionalCheck.disabled = selectedDictionary.dossierDictionaryOnly; } } @@ -230,7 +236,7 @@ export class RedactTextDialogComponent #resetValues() { this.#applyToAllDossiers = this.applyToAll; - this.options[2].extraOption.checked = this.#applyToAllDossiers; + this.options[2].additionalCheck.checked = this.#applyToAllDossiers; if (this.dictionaryRequest) { this.form.controls.reason.setValue(null); this.form.controls.dictionary.setValue(null); diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.html index 67b718ed6..af6631396 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.html @@ -14,7 +14,11 @@ > - +
@@ -31,6 +35,7 @@
acc && a.AREA, true); readonly #applyToAllDossiers = this.systemDefaultByType[this.annotationsType].extra; readonly isSystemDefault = this.optionByType[this.annotationsType].main === SystemDefaultOption.SYSTEM_DEFAULT; readonly isExtraOptionSystemDefault = this.optionByType[this.annotationsType].extra === 'undefined'; @@ -96,15 +102,17 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< ? this.systemDefaultByType[this.annotationsType].main : this.optionByType[this.annotationsType].main; readonly extraOptionPreference = stringToBoolean(this.optionByType[this.annotationsType].extra); - readonly options: DetailsRadioOption[] = getRemoveRedactionOptions( - this.data, - this.isSystemDefault || this.isExtraOptionSystemDefault ? this.#applyToAllDossiers : this.extraOptionPreference, - ); + readonly options: DetailsRadioOption[] = this.#allRectangles + ? getRectangleRedactOptions('remove') + : getRemoveRedactionOptions( + this.data, + this.isSystemDefault || this.isExtraOptionSystemDefault ? this.#applyToAllDossiers : this.extraOptionPreference, + ); readonly skipped = this.data.redactions.some(annotation => annotation.isSkipped); readonly redactedTexts = this.data.redactions.map(annotation => annotation.value); form: UntypedFormGroup = this._formBuilder.group({ comment: [null], - option: [this.defaultOption], + option: [this.defaultOption, validatePageRange()], }); readonly selectedOption = toSignal(this.form.get('option').valueChanges.pipe(map(value => value.value))); @@ -160,14 +168,31 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< return this.options.length * 75 + 230; } + extraOptionChanged(option: DetailsRadioOption): void { + if (option.value === RectangleRedactOptions.MULTIPLE_PAGES) { + setTimeout(() => { + this.form.get('option')?.updateValueAndValidity(); + }, 0); + } + } + save(): void { + const pageNumbers = parseSelectedPageNumbers( + this.form.get('option').value.additionalInput?.value, + this.data.file, + this.data.redactions[0], + ); + const position = parseRectanglePosition(this.data.redactions[0]); + this.close({ ...this.form.getRawValue(), bulkLocal: this.form.controls.option.value.value === ResizeOptions.IN_DOCUMENT, + pageNumbers, + position, }); } - #getOption(option: RemoveRedactionOption): DetailsRadioOption { + #getOption(option: RemoveRedactionOption): DetailsRadioOption { return this.options.find(o => o.value === option); } } 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 c51877fb3..a5b174c13 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 @@ -82,7 +82,7 @@ export class ResizeRedactionDialogComponent extends IqserDialogComponent< super.close({ comment: formValue.comment, updateDictionary, - addToAllDossiers: !!formValue.option?.extraOption?.checked, + addToAllDossiers: !!formValue.option?.additionalCheck?.checked, }); } diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 7aab6a810..512f783bd 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -21,7 +21,7 @@ import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilt import { AutoUnsubscribe, Bind, bool, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ManualRedactionEntryTypes, ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; -import { Dictionary, File, ViewModes } from '@red/domain'; +import { File, ViewModes } from '@red/domain'; import { ConfigService } from '@services/config.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; @@ -71,6 +71,7 @@ import { TypeFilterComponent } from '@shared/components/type-filter/type-filter. import { FileHeaderComponent } from './components/file-header/file-header.component'; import { StructuredComponentManagementComponent } from './components/structured-component-management/structured-component-management.component'; import { DocumentInfoService } from './services/document-info.service'; +import { RectangleAnnotationDialog } from './dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component'; @Component({ templateUrl: './file-preview-screen.component.html', @@ -308,29 +309,25 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni this._viewerHeaderService.resetLayers(); } - openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) { + async openRectangleAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) { const file = this.state.file(); - this._dialogService.openDialog( - 'manualAnnotation', - { manualRedactionEntryWrapper, dossierId: this.dossierId, file }, - (result: { annotations: ManualRedactionEntryWrapper[]; dictionary?: Dictionary }) => { - const selectedAnnotations = this._annotationManager.selected; - if (selectedAnnotations.length > 0) { - this._annotationManager.delete([selectedAnnotations[0].Id]); - } + const data = { manualRedactionEntryWrapper, file, dossierId: this.dossierId }; + const result = await this._iqserDialog.openDefault(RectangleAnnotationDialog, { data }).result(); - const add$ = this._manualRedactionService.addAnnotation( - result.annotations.map(w => w.manualRedactionEntry).filter(e => e.positions[0].page <= file.numberOfPages), - this.dossierId, - this.fileId, - { dictionaryLabel: result.dictionary?.label }, - ); + if (!result) { + return; + } - const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file))); - return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined)))); - }, - ); + const selectedAnnotations = this._annotationManager.selected; + if (selectedAnnotations.length > 0) { + this._annotationManager.delete([selectedAnnotations[0].Id]); + } + + const add$ = this._manualRedactionService.addAnnotation([result.annotation], this.dossierId, this.fileId); + + const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file))); + return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined)))); } async viewerReady(pageNumber?: string) { @@ -629,7 +626,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni .subscribe(); this.addActiveScreenSubscription = this.pdfProxyService.manualAnnotationRequested$.subscribe($event => { - this.openManualAnnotationDialog($event); + this.openRectangleAnnotationDialog($event).then(); }); this.addActiveScreenSubscription = this.pdfProxyService.redactTextRequested$.subscribe($event => { 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 341bd7c8b..ecf5b5300 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 @@ -35,7 +35,9 @@ import { EditRedactionData, EditRedactResult, ForceAnnotationOptions, + RectangleRedactOptions, RedactOrHintOptions, + RedactRecommendationData, RemoveRedactionData, RemoveRedactionOptions, RemoveRedactionPermissions, @@ -48,7 +50,8 @@ import { FilePreviewDialogService } from './file-preview-dialog.service'; import { FilePreviewStateService } from './file-preview-state.service'; import { ManualRedactionService } from './manual-redaction.service'; import { SkippedService } from './skipped.service'; -import { NON_READABLE_CONTENT } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; +import { NON_READABLE_CONTENT } from '../dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component'; +import { result } from 'lodash-es'; @Injectable() export class AnnotationActionsService { @@ -110,11 +113,12 @@ export class AnnotationActionsService { } async editRedaction(annotations: AnnotationWrapper[]) { - const { dossierId, fileId } = this._state; + const { dossierId, file } = this._state; const includeUnprocessed = annotations.every(annotation => this.#includeUnprocessed(annotation, true)); const data = { annotations, dossierId, + file: file(), }; const result = await this.#getEditRedactionDialog(data).result(); @@ -124,7 +128,7 @@ export class AnnotationActionsService { let recategorizeBody: List | IBulkRecategorizationRequest; - if (result.option === RedactOrHintOptions.ONLY_HERE) { + if (result.option === RedactOrHintOptions.ONLY_HERE || result.option === RectangleRedactOptions.ONLY_THIS_PAGE) { recategorizeBody = annotations.map(annotation => { const body: IRecategorizationRequest = { annotationId: annotation.id, @@ -151,7 +155,9 @@ export class AnnotationActionsService { section: result.section, originTypes, originLegalBases, - rectangle: false, + rectangle: annotations[0].AREA, + pageNumbers: result.pageNumbers, + position: result.position, }; } @@ -160,10 +166,10 @@ export class AnnotationActionsService { .recategorizeRedactions( recategorizeBody, dossierId, - fileId, + file().id, this.#getChangedFields(annotations, result), includeUnprocessed, - result.option === RedactOrHintOptions.IN_DOCUMENT, + result.option === RedactOrHintOptions.IN_DOCUMENT || !!result.pageNumbers.length, ) .pipe(log()), ); @@ -177,9 +183,11 @@ export class AnnotationActionsService { }; const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId); const isApprover = this._permissionsService.isApprover(this._state.dossier()); + const { file } = this._state; const data = { redactions, + file: file(), dossier: this._state.dossier(), falsePositiveContext: redactions.map(r => this.#getFalsePositiveText(r)), permissions: removePermissions, @@ -217,7 +225,7 @@ export class AnnotationActionsService { async convertRecommendationToAnnotation(recommendations: AnnotationWrapper[]) { const { dossierId, fileId } = this._state; - const data = this.#getRedactRecommendationDialogData(recommendations); + const data = this.#getRedactRecommendationDialogData(recommendations) as RedactRecommendationData; const dialog = this._iqserDialog.openDefault(RedactRecommendationDialogComponent, { data }); const result = await dialog.result(); if (!result) { @@ -451,7 +459,7 @@ export class AnnotationActionsService { type: redaction.type, positions: redaction.positions, addToDictionary: true, - addToAllDossiers: !!dialogResult.option.extraOption?.checked || !!dialogResult.applyToAllDossiers, + addToAllDossiers: !!dialogResult.option.additionalCheck?.checked || !!dialogResult.applyToAllDossiers, reason: 'False Positive', dictionaryEntryType: redaction.isRecommendation ? DictionaryEntryTypes.FALSE_RECOMMENDATION @@ -508,7 +516,7 @@ export class AnnotationActionsService { removeFromDictionary, isHint, includeUnprocessed, - dialogResult.bulkLocal, + dialogResult.bulkLocal || !!dialogResult.pageNumbers.length, ), ).then(); } @@ -584,15 +592,15 @@ export class AnnotationActionsService { redactions: AnnotationWrapper[], dialogResult: RemoveRedactionResult, ): List | IBulkLocalRemoveRequest { - if (dialogResult.bulkLocal) { + if (dialogResult.bulkLocal || !!dialogResult.pageNumbers.length) { const redaction = redactions[0]; if (redaction.value === NON_READABLE_CONTENT) { return { value: redaction.value, rectangle: true, - position: redaction.entry.positions[0], originTypes: [redaction.entry.type], - pageNumbers: [redaction.pageNumber], + pageNumbers: dialogResult.pageNumbers, + position: dialogResult.position, }; } @@ -607,7 +615,7 @@ export class AnnotationActionsService { value: redaction.value, comment: dialogResult.comment, removeFromDictionary: dialogResult.option.value === RemoveRedactionOptions.IN_DOSSIER, - removeFromAllDossiers: !!dialogResult.option.extraOption?.checked || !!dialogResult.applyToAllDossiers, + removeFromAllDossiers: !!dialogResult.option.additionalCheck?.checked || !!dialogResult.applyToAllDossiers, })); } } 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 59af5fef2..4028b154a 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 @@ -5,9 +5,8 @@ import { ChangeLegalBasisDialogComponent } from '../dialogs/change-legal-basis-d import { DocumentInfoDialogComponent } from '../dialogs/document-info-dialog/document-info-dialog.component'; import { ForceAnnotationDialogComponent } from '../dialogs/force-redaction-dialog/force-annotation-dialog.component'; import { HighlightActionDialogComponent } from '../dialogs/highlight-action-dialog/highlight-action-dialog.component'; -import { ManualAnnotationDialogComponent } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; -type DialogType = 'confirm' | 'documentInfo' | 'changeLegalBasis' | 'forceAnnotation' | 'manualAnnotation' | 'highlightAction'; +type DialogType = 'confirm' | 'documentInfo' | 'changeLegalBasis' | 'forceAnnotation' | 'highlightAction'; @Injectable() export class FilePreviewDialogService extends DialogService { @@ -26,10 +25,6 @@ export class FilePreviewDialogService extends DialogService { forceAnnotation: { component: ForceAnnotationDialogComponent, }, - manualAnnotation: { - component: ManualAnnotationDialogComponent, - dialogConfig: { autoFocus: true }, - }, highlightAction: { component: HighlightActionDialogComponent, }, 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 0ed5aa351..e8017d6df 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 @@ -97,7 +97,7 @@ export class ManualRedactionService extends GenericService { : this.#showToast(options?.hint ? 'force-hint' : 'add'); const canAddRedaction = this._iqserPermissionsService.has(Roles.redactions.write); if (canAddRedaction) { - return this.add(requests, dossierId, fileId, options.bulkLocal).pipe(toast); + return this.add(requests, dossierId, fileId, options?.bulkLocal).pipe(toast); } return of(undefined); @@ -139,7 +139,9 @@ export class ManualRedactionService extends GenericService { } add(body: List, dossierId: string, fileId: string, bulkLocal = false) { + bulkLocal = bulkLocal || !!body[0].pageNumbers?.length; const bulkPath = bulkLocal ? this.#bulkLocal : this.#bulkRedaction; + return this._post(bulkLocal ? body[0] : body, `${bulkPath}/add/${dossierId}/${fileId}`).pipe(this.#log('Add', body)); } 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 35cf0740c..5b4288ccd 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 @@ -9,6 +9,8 @@ import { resizeRedactionTranslations } from '@translations/resize-redaction-tran import { EditRedactionOption, ForceAnnotationOption, + RectangleRedactOption, + RectangleRedactOptions, RedactOrHintOption, RedactOrHintOptions, RemoveRedactionData, @@ -17,6 +19,11 @@ import { ResizeOptions, ResizeRedactionOption, } from './dialog-types'; +import { + editRectangleTranslations, + rectangleRedactTranslations, + removeRectangleTranslations, +} from '@translations/rectangle-redact-translations'; const PIN_ICON = 'red:push-pin'; const DOCUMENT_ICON = 'iqser:document'; @@ -81,7 +88,7 @@ export const getRedactOrHintOptions = ( icon: FOLDER_ICON, value: RedactOrHintOptions.IN_DOSSIER, disabled: isPageExcluded, - extraOption: { + additionalCheck: { label: translations.inDossier.extraOptionLabel, checked: applyToAllDossiers, hidden: !isApprover, @@ -91,6 +98,31 @@ export const getRedactOrHintOptions = ( return options; }; +export const getRectangleRedactOptions = (action: 'add' | 'edit' | 'remove' = 'add'): DetailsRadioOption[] => { + const translations = + action === 'add' ? rectangleRedactTranslations : action === 'edit' ? editRectangleTranslations : removeRectangleTranslations; + return [ + { + label: translations.onlyThisPage.label, + description: translations.onlyThisPage.description, + icon: PIN_ICON, + value: RectangleRedactOptions.ONLY_THIS_PAGE, + }, + { + label: translations.multiplePages.label, + description: translations.multiplePages.description, + icon: DOCUMENT_ICON, + value: RectangleRedactOptions.MULTIPLE_PAGES, + additionalInput: { + label: translations.multiplePages.extraOptionLabel, + description: translations.multiplePages.extraOptionDescription, + placeholder: translations.multiplePages.extraOptionPlaceholder, + value: '', + }, + }, + ]; +}; + export const getResizeRedactionOptions = ( redaction: AnnotationWrapper, dossier: Dossier, @@ -122,7 +154,7 @@ export const getResizeRedactionOptions = ( tooltip: !dictBasedType ? translations.inDossier.tooltip : null, icon: FOLDER_ICON, value: ResizeOptions.IN_DOSSIER, - extraOption: { + additionalCheck: { label: translations.inDossier.extraOptionLabel, checked: applyToAllDossiers, hidden: !isApprover, @@ -176,7 +208,7 @@ export const getRemoveRedactionOptions = ( }, icon: FOLDER_ICON, value: RemoveRedactionOptions.IN_DOSSIER, - extraOption: !isDocumine + additionalCheck: !isDocumine ? { label: translations.IN_DOSSIER.extraOptionLabel, checked: applyToAllDossiers, @@ -198,7 +230,7 @@ export const getRemoveRedactionOptions = ( }, icon: FOLDER_ICON, value: RemoveRedactionOptions.DO_NOT_RECOMMEND, - extraOption: !isDocumine + additionalCheck: !isDocumine ? { label: translations.DO_NOT_RECOMMEND.extraOptionLabel, checked: applyToAllDossiers, @@ -218,7 +250,7 @@ export const getRemoveRedactionOptions = ( }, icon: REMOVE_FROM_DICT_ICON, value: RemoveRedactionOptions.FALSE_POSITIVE, - extraOption: !isDocumine + additionalCheck: !isDocumine ? { label: translations.FALSE_POSITIVE.extraOptionLabel, checked: applyToAllDossiers, diff --git a/apps/red-ui/src/app/modules/file-preview/utils/dialog-types.ts b/apps/red-ui/src/app/modules/file-preview/utils/dialog-types.ts index 7595f3f69..00131bcda 100644 --- a/apps/red-ui/src/app/modules/file-preview/utils/dialog-types.ts +++ b/apps/red-ui/src/app/modules/file-preview/utils/dialog-types.ts @@ -1,7 +1,7 @@ import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; -import { Dictionary, Dossier, File, IAddRedactionRequest, IManualRedactionEntry } from '@red/domain'; +import { Dictionary, Dossier, File, IAddRedactionRequest, IEntityLogEntryPosition, IManualRedactionEntry } from '@red/domain'; export const EditRedactionOptions = { ONLY_HERE: 'ONLY_HERE', @@ -18,6 +18,13 @@ export const RedactOrHintOptions = { export type RedactOrHintOption = keyof typeof RedactOrHintOptions; +export const RectangleRedactOptions = { + ONLY_THIS_PAGE: 'ONLY_THIS_PAGE', + MULTIPLE_PAGES: 'MULTIPLE_PAGES', +} as const; + +export type RectangleRedactOption = keyof typeof RectangleRedactOptions; + export const ForceAnnotationOptions = { ONLY_HERE: 'ONLY_HERE', IN_DOCUMENT: 'IN_DOCUMENT', @@ -40,6 +47,12 @@ export const RemoveAnnotationOptions = RemoveRedactionOptions; export type RemoveRedactionOption = keyof typeof RemoveRedactionOptions; export type RemoveAnnotationOption = RemoveRedactionOption; +export interface LegalBasisOption { + label?: string; + legalBasis?: string; + description?: string; +} + export interface RedactTextData { manualRedactionEntryWrapper: ManualRedactionEntryWrapper; dossierId: string; @@ -52,6 +65,7 @@ export interface RedactTextData { export interface EditRedactionData { annotations: AnnotationWrapper[]; dossierId: string; + file: File; isApprover?: boolean; } @@ -80,7 +94,9 @@ export interface EditRedactResult { comment: string; type: string; value: string; - option: EditRedactionOption; + option: EditRedactionOption | RectangleRedactOption; + position: IEntityLogEntryPosition; + pageNumbers?: number[]; } export type AddHintResult = RedactTextResult; @@ -120,6 +136,7 @@ export interface RemoveRedactionPermissions { export interface RemoveRedactionData { redactions: AnnotationWrapper[]; dossier: Dossier; + file?: File; falsePositiveContext: string[]; permissions: RemoveRedactionPermissions; applyToAllDossiers: boolean; @@ -133,6 +150,17 @@ export interface RemoveRedactionResult { option: DetailsRadioOption; applyToAllDossiers?: boolean; bulkLocal?: boolean; + pageNumbers?: number[]; + position: IEntityLogEntryPosition; } export type RemoveAnnotationResult = RemoveRedactionResult; + +export interface RectangleDialogData { + dossierId: string; + manualRedactionEntryWrapper: ManualRedactionEntryWrapper; + file: File; +} +export interface RectangleDialogResult { + annotation: IManualRedactionEntry; +} diff --git a/apps/red-ui/src/app/modules/file-preview/utils/enhance-manual-redaction-request.utils.ts b/apps/red-ui/src/app/modules/file-preview/utils/enhance-manual-redaction-request.utils.ts index 25291fd22..635549d37 100644 --- a/apps/red-ui/src/app/modules/file-preview/utils/enhance-manual-redaction-request.utils.ts +++ b/apps/red-ui/src/app/modules/file-preview/utils/enhance-manual-redaction-request.utils.ts @@ -1,5 +1,7 @@ -import { Dictionary, IAddRedactionRequest, SuperType } from '@red/domain'; -import { LegalBasisOption } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; +import { Dictionary, File, IAddRedactionRequest, IEntityLogEntryPosition, SuperType } from '@red/domain'; +import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; +import { LegalBasisOption } from './dialog-types'; +import { AnnotationWrapper } from '@models/file/annotation.wrapper'; export interface EnhanceRequestData { readonly type: SuperType | null; @@ -12,6 +14,12 @@ export interface EnhanceRequestData { readonly applyToAllDossiers: boolean; } +interface MultiplePagesRectangleData { + manualRedactionEntryWrapper: ManualRedactionEntryWrapper; + pages: string; + file: File; +} + export const enhanceManualRedactionRequest = (addRedactionRequest: IAddRedactionRequest, data: EnhanceRequestData) => { addRedactionRequest.type = data.type; addRedactionRequest.section = null; @@ -38,3 +46,42 @@ export const enhanceManualRedactionRequest = (addRedactionRequest: IAddRedaction addRedactionRequest.comment = commentValue ? { text: commentValue } : null; addRedactionRequest.addToAllDossiers = data.isApprover && data.dictionaryRequest && data.applyToAllDossiers; }; + +export const parseSelectedPageNumbers = (inputValue: string, file: File, annotation: AnnotationWrapper) => { + if (!inputValue) { + return []; + } + + inputValue = inputValue.replace(/[^0-9-,]/g, ''); + const pageNumbers = []; + + inputValue.split(',').forEach(range => { + const splitted = range.split('-'); + const startPage = parseInt(splitted[0], 10); + const endPage = splitted.length > 1 ? parseInt(splitted[1], 10) : startPage; + if (!startPage || !endPage || startPage > file.numberOfPages || endPage > file.numberOfPages) { + throw new Error(); + } + + for (let page = startPage; page <= endPage; page++) { + if (page === annotation.positions[0].page) { + continue; + } + + pageNumbers.push(page); + } + }); + + return pageNumbers; +}; + +export const parseRectanglePosition = (annotation: AnnotationWrapper) => { + if (annotation.AREA) { + const position = annotation.positions[0]; + return { + rectangle: [position.topLeft.x, position.topLeft.y, position.width, position.height], + pageNumber: position.page, + } as IEntityLogEntryPosition; + } + return null; +}; diff --git a/apps/red-ui/src/app/modules/file-preview/utils/form-validators.ts b/apps/red-ui/src/app/modules/file-preview/utils/form-validators.ts new file mode 100644 index 000000000..233aed553 --- /dev/null +++ b/apps/red-ui/src/app/modules/file-preview/utils/form-validators.ts @@ -0,0 +1,12 @@ +import { AbstractControl, ValidatorFn } from '@angular/forms'; + +export const validatePageRange = (): ValidatorFn => { + return (control: AbstractControl): { [key: string]: any } | null => { + const option = control.value; + if (option?.additionalInput) { + const validRange = /^(\d+(-\d+)?)(,\d+(-\d+)?)*$/.test(option.additionalInput.value); + return validRange ? null : { invalidRange: true }; + } + return null; + }; +}; diff --git a/apps/red-ui/src/app/translations/rectangle-redact-translations.ts b/apps/red-ui/src/app/translations/rectangle-redact-translations.ts new file mode 100644 index 000000000..65359c754 --- /dev/null +++ b/apps/red-ui/src/app/translations/rectangle-redact-translations.ts @@ -0,0 +1,44 @@ +import { DialogOption } from '@translations/redact-text-translations'; +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; + +export const rectangleRedactTranslations: Record<'onlyThisPage' | 'multiplePages', DialogOption> = { + onlyThisPage: { + label: _('manual-annotation.dialog.content.options.only-this-page.label'), + description: _('manual-annotation.dialog.content.options.only-this-page.description'), + }, + multiplePages: { + label: _('manual-annotation.dialog.content.options.multiple-pages.label'), + description: _('manual-annotation.dialog.content.options.multiple-pages.description'), + extraOptionLabel: _('manual-annotation.dialog.content.options.multiple-pages.extraOptionLabel'), + extraOptionDescription: _('manual-annotation.dialog.content.options.multiple-pages.extraOptionDescription'), + extraOptionPlaceholder: _('manual-annotation.dialog.content.options.multiple-pages.extraOptionPlaceholder'), + }, +} as const; + +export const editRectangleTranslations: Record<'onlyThisPage' | 'multiplePages', DialogOption> = { + onlyThisPage: { + label: _('edit-rectangle.dialog.content.options.only-this-page.label'), + description: _('edit-rectangle.dialog.content.options.only-this-page.description'), + }, + multiplePages: { + label: _('edit-rectangle.dialog.content.options.multiple-pages.label'), + description: _('edit-rectangle.dialog.content.options.multiple-pages.description'), + extraOptionLabel: _('edit-rectangle.dialog.content.options.multiple-pages.extraOptionLabel'), + extraOptionDescription: _('edit-rectangle.dialog.content.options.multiple-pages.extraOptionDescription'), + extraOptionPlaceholder: _('edit-rectangle.dialog.content.options.multiple-pages.extraOptionPlaceholder'), + }, +} as const; + +export const removeRectangleTranslations: Record<'onlyThisPage' | 'multiplePages', DialogOption> = { + onlyThisPage: { + label: _('remove-rectangle.dialog.content.options.only-this-page.label'), + description: _('remove-rectangle.dialog.content.options.only-this-page.description'), + }, + multiplePages: { + label: _('remove-rectangle.dialog.content.options.multiple-pages.label'), + description: _('remove-rectangle.dialog.content.options.multiple-pages.description'), + extraOptionLabel: _('remove-rectangle.dialog.content.options.multiple-pages.extraOptionLabel'), + extraOptionDescription: _('remove-rectangle.dialog.content.options.multiple-pages.extraOptionDescription'), + extraOptionPlaceholder: _('remove-rectangle.dialog.content.options.multiple-pages.extraOptionPlaceholder'), + }, +} as const; diff --git a/apps/red-ui/src/app/translations/redact-text-translations.ts b/apps/red-ui/src/app/translations/redact-text-translations.ts index 0cf5b8f26..69c774c54 100644 --- a/apps/red-ui/src/app/translations/redact-text-translations.ts +++ b/apps/red-ui/src/app/translations/redact-text-translations.ts @@ -7,6 +7,7 @@ export interface DialogOption { descriptionBulk?: string; extraOptionLabel?: string; extraOptionDescription?: string; + extraOptionPlaceholder?: string; } export const redactTextTranslations: Record<'onlyHere' | 'inDocument' | 'inDossier', DialogOption> = { diff --git a/apps/red-ui/src/assets/config/config.json b/apps/red-ui/src/assets/config/config.json index deb14e6da..5f6c0ce6e 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://dan1.iqser.cloud", + "API_URL": "https://dan2.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://dan1.iqser.cloud/auth", + "OAUTH_URL": "https://dan2.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 142adad86..430e48213 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -243,7 +243,8 @@ } }, "type": "Typ", - "type-placeholder": "Typ auswählen..." + "type-placeholder": "Typ auswählen...", + "value": "" }, "title": "Hinweis hinzufügen" } @@ -275,9 +276,6 @@ "watermarks": "Wasserzeichen" }, "analysis-disabled": "", - "annotation": { - "pending": "(Analyse steht aus)" - }, "annotation-actions": { "accept-recommendation": { "label": "Empfehlung annehmen" @@ -333,14 +331,14 @@ "error": "Rekategorisierung des Bilds fehlgeschlagen: {error}", "success": "Bild wurde einer neuen Kategorie zugeordnet." }, - "remove": { - "error": "Entfernen der Schwärzung fehlgeschlagen: {error}", - "success": "Schwärzung wurde entfernt" - }, "remove-hint": { "error": "Entfernen des Hinweises fehlgeschlagen: {error}", "success": "Hinweis wurde entfernt" }, + "remove": { + "error": "Entfernen der Schwärzung fehlgeschlagen: {error}", + "success": "Schwärzung wurde entfernt" + }, "undo": { "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", "success": "Rücksetzung erfolgreich" @@ -353,15 +351,15 @@ "remove-highlights": { "label": "Ausgewählte Markierungen entfernen" }, - "resize": { - "label": "Größe ändern" - }, "resize-accept": { "label": "Neue Größe speichern" }, "resize-cancel": { "label": "Größenänderung abbrechen" }, + "resize": { + "label": "Größe ändern" + }, "see-references": { "label": "Referenzen anzeigen" }, @@ -378,6 +376,7 @@ "removed-manual": "Schwärzung/Hinweis wurde entfernt", "resized": "Schwärzungsbereich wurde geändert" }, + "annotation-content": "", "annotation-engines": { "dictionary": "Basiert auf Wörterbuch", "dossier-dictionary": "Basiert auf Dossier-Wörterbuch", @@ -395,6 +394,9 @@ "skipped": "Ignorierte Schwärzung", "text-highlight": "Markierung" }, + "annotation": { + "pending": "(Analyse steht aus)" + }, "annotations": "Annotationen", "archived-dossiers-listing": { "no-data": { @@ -1018,13 +1020,13 @@ "recent": "Neu ({hours} h)", "unassigned": "Keinem Bearbeiter zugewiesen" }, - "reanalyse": { - "action": "Datei analysieren" - }, "reanalyse-dossier": { "error": "Einplanung der Dateien für die Reanalyse fehlgeschlagen. Bitte versuchen Sie es noch einmal.", "success": "Dateien für Reanalyse vorgesehen." }, + "reanalyse": { + "action": "Datei analysieren" + }, "report-download": "", "start-auto-analysis": "Auto-Analyse aktivieren", "stop-auto-analysis": "Auto-Analyse anhalten", @@ -1094,14 +1096,6 @@ "total-documents": "Dokumente", "total-people": "{count} {count, plural, one{Benutzer} other {Benutzer}}" }, - "dossier-templates": { - "label": "Dossier-Vorlagen", - "status": { - "active": "Aktiv", - "inactive": "Inaktiv", - "incomplete": "Unvollständig" - } - }, "dossier-templates-listing": { "action": { "clone": "Vorlage klonen", @@ -1136,6 +1130,14 @@ "title": "{length} {length, plural, one{Dossier-Vorlage} other{Dossier-Vorlagen}}" } }, + "dossier-templates": { + "label": "Dossier-Vorlagen", + "status": { + "active": "Aktiv", + "inactive": "Inaktiv", + "incomplete": "Unvollständig" + } + }, "dossier-watermark-selector": { "heading": "Wasserzeichen auf Dokumenten", "no-watermark": "Kein Wasserzeichen in der Dossier-Vorlage verfügbar:
Bitten Sie Ihren Admin, eines zu konfigurieren.", @@ -1233,10 +1235,8 @@ "save": "Speichern", "title": "{label} bearbeiten" }, - "entries": "{length} {length, plural, one{Eintrag} other{Einträge}}", - "false-positive-entries": "{length} {length, plural, one{Falsch-Positiver} other{Falsch-Positive}}", + "entries-count": "", "false-positives": "Falsch-Positive", - "false-recommendation-entries": "{length} {length, plural, one{falsche Empfehlung} other{falsche Empfehlungen}}", "false-recommendations": "Falsche Empfehlungen", "to-redact": "Schwärzungen" }, @@ -1273,6 +1273,25 @@ }, "side-nav-title": "Konfiguration" }, + "edit-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + } + } + } + }, "edit-redaction": { "dialog": { "actions": { @@ -1282,14 +1301,11 @@ "content": { "comment": "Kommentar", "comment-placeholder": "Bemerkungen oder Notizen hinzufügen...", - "custom-rectangle": "Bereichsschwärzung", - "imported": "Importierte Schwärzung", "legal-basis": "Rechtsgrundlage", "options": { - "in-dossier": { - "description": "Schwärzung in jedem Dokument in {dossierName} bearbeiten.", - "extraOptionLabel": "In alle aktiven und zukünftigen Dossiers übernehmen", - "label": "Typ in Dossier ändern" + "in-document": { + "description": "", + "label": "" }, "only-here": { "description": "Bearbeiten Sie die Schwärzung nur an dieser Stelle im Dokument.", @@ -1332,15 +1348,6 @@ "title": "{length} {length, plural, one{Wörterbuch} other{Wörterbücher}}" } }, - "entity": { - "info": { - "actions": { - "revert": "Zurücksetzen", - "save": "Änderungen speichern" - }, - "heading": "Entität bearbeiten" - } - }, "entity-rules-screen": { "error": { "generic": "Fehler: Aktualisierung der Entitätsregeln fehlgeschlagen." @@ -1354,19 +1361,28 @@ "title": "Entitätsregeln-Editor", "warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} in Regeln gefunden" }, + "entity": { + "info": { + "actions": { + "revert": "Zurücksetzen", + "save": "Änderungen speichern" + }, + "heading": "Entität bearbeiten" + } + }, "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": { @@ -1384,12 +1400,6 @@ }, "exact-date": "{day}. {month} {year} um {hour}:{minute} Uhr", "file": "Datei", - "file-attribute": { - "update": { - "error": "Aktualisierung des Werts für das Datei-Attribut fehlgeschlagen. Bitte versuchen Sie es noch einmal.", - "success": "Der Wert für das Dateiattribut wurde erfolgreich aktualisiert." - } - }, "file-attribute-encoding-types": { "ascii": "ASCII", "iso": "ISO-8859-1", @@ -1400,6 +1410,12 @@ "number": "Nummer", "text": "Freier Text" }, + "file-attribute": { + "update": { + "error": "Aktualisierung des Werts für das Datei-Attribut fehlgeschlagen. Bitte versuchen Sie es noch einmal.", + "success": "Der Wert für das Dateiattribut wurde erfolgreich aktualisiert." + } + }, "file-attributes-configurations": { "cancel": "Abbrechen", "form": { @@ -1617,15 +1633,6 @@ "csv": "Die Datei-Attribute wurden erfolgreich aus der hochgeladenen CSV-Datei importiert." } }, - "filter": { - "analysis": "Analyse erforderlich", - "comment": "Kommentare", - "hint": "Nur Hinweise", - "image": "Bilder", - "none": "Keine Annotationen", - "redaction": "Schwärzung", - "updated": "Aktualisiert" - }, "filter-menu": { "filter-options": "Filteroptionen", "filter-types": "Filter", @@ -1635,6 +1642,15 @@ "unseen-pages": "Nur Annotationen auf ungesehenen Seiten", "with-comments": "Nur Annotationen mit Kommentaren" }, + "filter": { + "analysis": "Analyse erforderlich", + "comment": "Kommentare", + "hint": "Nur Hinweise", + "image": "Bilder", + "none": "Keine Annotationen", + "redaction": "Schwärzung", + "updated": "Aktualisiert" + }, "filters": { "assigned-people": "Bearbeiter", "documents-status": "Dokumentenstatus", @@ -1868,20 +1884,25 @@ "save": "Speichern" }, "content": { - "apply-on-multiple-pages": "Auf mehreren Seiten anwenden", - "apply-on-multiple-pages-hint": "Minus (-) für Bereich und Komma (,) für Aufzählung.", - "apply-on-multiple-pages-placeholder": "z. B. 1-20,22,32", "classification": "Wert / Klassifizierung", "comment": "Kommentar", - "dictionary": "Wörterbuch", - "edit-selected-text": "Ausgewählten Text bearbeiten", "legalBasis": "Rechtsgrundlage", + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + }, "reason": "Grund", "reason-placeholder": "Grund auswählen...", - "rectangle": "Bereichsschwärzung", - "section": "Absatz / Textstelle", - "text": "Ausgewählter Text:", - "type": "Entität" + "section": "Absatz / Textstelle" }, "error": "Fehler: Ungültige Seitenauswahl", "header": { @@ -1913,13 +1934,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": "Benachrichtigungen", - "deleted-dossier": "Gelöschtes Dossier", - "label": "Benachrichtigungen", - "mark-all-as-read": "Alle als gelesen markieren", - "mark-as": "Als {type, select, read{gelesen} unread{ungelesen} other{}} markieren" - }, "notifications-screen": { "category": { "email-notifications": "E-Mail-Benachrichtigungen", @@ -1933,6 +1947,7 @@ "dossier": "Benachrichtigungen zu Dossiers", "other": "Andere Benachrichtigungen" }, + "options-title": "Wählen Sie aus, bei welchen Aktivitäten Sie benachrichtigt werden möchten", "options": { "ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen werde", "ASSIGN_REVIEWER": "Wenn ich einem Dokument als Prüfer zugewiesen werde", @@ -1950,7 +1965,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, bei welchen Aktivitäten Sie benachrichtigt werden möchten", "schedule": { "daily": "Tägliche Zusammenfassung", "instant": "Sofort", @@ -1958,6 +1972,13 @@ }, "title": "Benachrichtigungseinstellungen" }, + "notifications": { + "button-text": "Benachrichtigungen", + "deleted-dossier": "Gelöschtes Dossier", + "label": "Benachrichtigungen", + "mark-all-as-read": "Alle als gelesen markieren", + "mark-as": "Als {type, select, read{gelesen} unread{ungelesen} other{}} markieren" + }, "ocr": { "confirmation-dialog": { "cancel": "Abbrechen", @@ -2004,14 +2025,34 @@ "previous": "Vorherige" }, "pdf-viewer": { + "header": { + "all-annotations-loaded": "", + "compare-button": "", + "layers-panel-button": "", + "left-panel-button": "", + "load-all-annotations": "", + "no-outlines-text": "", + "no-signatures-text": "", + "outline-multi-select": "", + "outlines-panel-button": "", + "pan-tool-button": "", + "rectangle-tool-button": "", + "rotate-left-button": "", + "rotate-right-button": "", + "select-tool-button": "", + "signature-panel-button": "", + "thumbnails-panel-button": "", + "toggle-layers": "", + "toggle-readable-redactions": "", + "toggle-tooltips": "", + "zoom-in-button": "", + "zoom-out-button": "" + }, "text-popup": { "actions": { "search": "Ausgewählten Text suchen" } - }, - "toggle-layers": "Layout-Raster {active, select, true{deaktivieren} false{aktivieren} other{}}", - "toggle-readable-redactions": "Schwärzungen {active, select, true{wie im finalen Dokument} false{in Vorschau-Farbe} other{}} anzeigen", - "toggle-tooltips": "Tooltips zu Annotationen {active, select, true{deaktivieren} false{aktivieren} other{}}" + } }, "permissions-screen": { "dossier": { @@ -2049,16 +2090,16 @@ "warnings-label": "Dialoge und Meldungen", "warnings-subtitle": "„Nicht mehr anzeigen“-Optionen" }, - "processing": { - "basic": "Verarbeitung läuft", - "ocr": "OCR" - }, "processing-status": { "ocr": "OCR", "pending": "Ausstehend", "processed": "Verarbeitet", "processing": "Verarbeitung läuft" }, + "processing": { + "basic": "Verarbeitung läuft", + "ocr": "OCR" + }, "readonly": "Lesemodus", "readonly-archived": "Lesemodus (archiviert)", "redact-text": { @@ -2073,6 +2114,10 @@ "edit-text": "Text bearbeiten", "legal-basis": "Rechtsgrundlage", "options": { + "in-document": { + "description": "", + "label": "" + }, "in-dossier": { "description": "Fügen Sie die Schwärzung zu jedem Dokument in {dossierName} hinzu.", "extraOptionLabel": "In alle aktiven und zukünftigen Dossiers übernehmen", @@ -2088,7 +2133,8 @@ "revert-text": "Zurück zu ursprünglicher Auswahl", "type": "Typ", "type-placeholder": "Typ auswählen...", - "unchanged": "Ungeändert" + "unchanged": "Ungeändert", + "value": "" }, "title": "Text schwärzen" } @@ -2112,6 +2158,10 @@ "description-bulk": "", "label": "In diesem Kontext aus dem Dossier entfernen" }, + "in-document": { + "description": "", + "label": "" + }, "in-dossier": { "description": "Annotieren Sie den Begriff in diesem Dossier nicht.", "description-bulk": "", @@ -2129,6 +2179,25 @@ "title": "{count, plural, one{Annotation} other {Annotationen}} entfernen" } }, + "remove-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + } + } + } + }, "remove-redaction": { "dialog": { "actions": { @@ -2152,6 +2221,10 @@ "extraOptionLabel": "In alle aktiven und zukünftigen Dossiers übernehmen", "label": "In diesem Kontext aus Dossier entfernen" }, + "in-document": { + "description": "", + "label": "" + }, "in-dossier": { "description": "Der Begriff wird in keinem Dokument dieses Dossiers {type, select, hint{annotiert} other{automatisch geschwärzt}}.", "description-bulk": "Die ausgewählten Begriffe werden in diesem Dossier nicht {type, select, hint{annotiert} other{automatisch geschwärzt}}.", @@ -2294,12 +2367,6 @@ "red-user-admin": "Benutzeradmin", "regular": "regulärer Benutzer" }, - "search": { - "active-dossiers": "Dokumente in aktiven Dossiers", - "all-dossiers": "Alle Dokumente", - "placeholder": "Dokumente durchsuchen...", - "this-dossier": "In diesem Dossier" - }, "search-screen": { "cols": { "assignee": "Bearbeiter", @@ -2323,6 +2390,12 @@ "no-match": "Der Suchbegriff wurde in keinem der Dokumente gefunden.", "table-header": "{length} {length, plural, one{Suchergebnis} other{Suchergebnisse}}" }, + "search": { + "active-dossiers": "Dokumente in aktiven Dossiers", + "all-dossiers": "Alle Dokumente", + "placeholder": "Dokumente durchsuchen...", + "this-dossier": "In diesem Dossier" + }, "seconds": "Sekunden", "size": "Größe", "smtp-auth-config": { @@ -2513,10 +2586,6 @@ "view-as": "Ansicht:", "workflow": "Workflow-Spalten" }, - "viewer-header": { - "all-annotations-loaded": "Alle Annotationen geladen", - "load-all-annotations": "Alle Annotationen laden" - }, "watermark-screen": { "action": { "change-success": "Wasserzeichen wurde aktualisiert.", @@ -2545,6 +2614,10 @@ "orientation": "Textrichtung", "text-label": "Text für Wasserzeichen", "text-placeholder": "Text eingeben" + }, + "pagination": { + "landscape": "", + "portrait": "" } }, "watermarks-listing": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 76cd7ed59..b4b07efe4 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -1273,6 +1273,25 @@ }, "side-nav-title": "Configurations" }, + "edit-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "Edit redaction the range of pages", + "extraOptionDescription": "Minus(-) for range and comma(,) for enumeration", + "extraOptionLabel": "Range", + "extraOptionPlaceholder": "e.g. 1-20,22,32", + "label": "Change on all pages" + }, + "only-this-page": { + "description": "Edit redaction only at this position in this document", + "label": "Change only on this page" + } + } + } + } + }, "edit-redaction": { "dialog": { "actions": { @@ -1865,20 +1884,25 @@ "save": "Save" }, "content": { - "apply-on-multiple-pages": "Apply on multiple pages", - "apply-on-multiple-pages-hint": "Minus(-) for range and comma(,) for enumeration.", - "apply-on-multiple-pages-placeholder": "e.g. 1-20,22,32", "classification": "Value / classification", "comment": "Comment", - "dictionary": "Dictionary", - "edit-selected-text": "Edit selected text", "legalBasis": "Legal basis", + "options": { + "multiple-pages": { + "description": "Edit redaction the range of pages", + "extraOptionDescription": "Minus(-) for range and comma(,) for enumeration", + "extraOptionLabel": "Range", + "extraOptionPlaceholder": "e.g. 1-20,22,32", + "label": "Apply on multiple pages" + }, + "only-this-page": { + "description": "Edit redaction only at this position in this document", + "label": "Apply only on this page" + } + }, "reason": "Reason", "reason-placeholder": "Select a reason...", - "rectangle": "Custom rectangle", - "section": "Paragraph / location", - "text": "Selected text:", - "type": "Entity" + "section": "Paragraph / location" }, "error": "Error! Invalid page selection", "header": { @@ -2155,6 +2179,25 @@ "title": "Remove {count, plural, one{annotation} other {annotations}}" } }, + "remove-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "Edit redaction the range of pages", + "extraOptionDescription": "Minus(-) for range and comma(,) for enumeration", + "extraOptionLabel": "Range", + "extraOptionPlaceholder": "e.g. 1-20,22,32", + "label": "Remove on all pages" + }, + "only-this-page": { + "description": "Edit redaction only at this position in this document", + "label": "Remove only on this page" + } + } + } + } + }, "remove-redaction": { "dialog": { "actions": { diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index 448859eef..d90f55996 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -243,7 +243,8 @@ } }, "type": "Typ", - "type-placeholder": "Typ auswählen..." + "type-placeholder": "Typ auswählen...", + "value": "" }, "title": "Hinweis hinzufügen" } @@ -275,9 +276,6 @@ "watermarks": "Wasserzeichen" }, "analysis-disabled": "Analyse deaktiviert", - "annotation": { - "pending": "(Analyse steht aus)" - }, "annotation-actions": { "accept-recommendation": { "label": "Empfehlung annehmen" @@ -333,14 +331,14 @@ "error": "Rekategorisierung des Bilds fehlgeschlagen: {error}", "success": "Bild wurde einer neuen Kategorie zugeordnet." }, - "remove": { - "error": "Entfernen der Annotation fehlgeschlagen: {error}", - "success": "Annotation wurde entfernt" - }, "remove-hint": { "error": "Entfernen des Hinweises fehlgeschlagen: {error}", "success": "Hinweis wurde entfernt" }, + "remove": { + "error": "Entfernen der Annotation fehlgeschlagen: {error}", + "success": "Annotation wurde entfernt" + }, "undo": { "error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}", "success": "erfolgreich Rückgängig gemacht" @@ -353,15 +351,15 @@ "remove-highlights": { "label": "Ausgewählte Markierungen entfernen" }, - "resize": { - "label": "Größe ändern" - }, "resize-accept": { "label": "Neue Größe speichern" }, "resize-cancel": { "label": "Größenänderung abbrechen" }, + "resize": { + "label": "Größe ändern" + }, "see-references": { "label": "See references" }, @@ -378,6 +376,7 @@ "removed-manual": "Schwärzung/Hinweis entfernt", "resized": "Schwärzungsbereich wurde geändert" }, + "annotation-content": "", "annotation-engines": { "dictionary": "{isHint, select, true{Hinweis} other{Schwärzung}} basiert auf Wörterbuch", "dossier-dictionary": "Annotation basiert auf Dossier-Wörterbuch", @@ -395,6 +394,9 @@ "skipped": "Übersprungen", "text-highlight": "Markierung" }, + "annotation": { + "pending": "(Analyse steht aus)" + }, "annotations": "Annotationen", "archived-dossiers-listing": { "no-data": { @@ -1018,13 +1020,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" + }, "report-download": "Report download", "start-auto-analysis": "Enable auto-analysis", "stop-auto-analysis": "Stop auto-analysis", @@ -1094,14 +1096,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", @@ -1136,6 +1130,14 @@ "title": "{length} dossier {length, plural, one{template} other{templates}}" } }, + "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.", @@ -1233,10 +1235,8 @@ "save": "", "title": "" }, - "entries": "{length} {length, plural, one{entry} other{entries}} to {hint, select, true{annotate} other{redact}}", - "false-positive-entries": "{length} false positive {length, plural, one{entry} other{entries}}", + "entries-count": "", "false-positives": "False positives", - "false-recommendation-entries": "{length} false recommendation {length, plural, one{entry} other{entries}}", "false-recommendations": "False recommendations", "to-redact": "To redact" }, @@ -1273,6 +1273,25 @@ }, "side-nav-title": "Konfiguration" }, + "edit-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + } + } + } + }, "edit-redaction": { "dialog": { "actions": { @@ -1282,13 +1301,10 @@ "content": { "comment": "Comment", "comment-placeholder": "Add remarks or mentions...", - "custom-rectangle": "", - "imported": "", "legal-basis": "", "options": { - "in-dossier": { + "in-document": { "description": "", - "extraOptionLabel": "", "label": "" }, "only-here": { @@ -1332,15 +1348,6 @@ "title": "{length} {length, plural, one{entity} other{entities}}" } }, - "entity": { - "info": { - "actions": { - "revert": "Revert", - "save": "Save changes" - }, - "heading": "Edit entity" - } - }, "entity-rules-screen": { "error": { "generic": "Something went wrong... Entity rules update failed!" @@ -1354,19 +1361,28 @@ "title": "Entity rule editor", "warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules" }, + "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": { @@ -1384,12 +1400,6 @@ }, "exact-date": "{day} {month} {year} um {hour}:{minute} Uhr", "file": "Datei", - "file-attribute": { - "update": { - "error": "Aktualisierung des Werts für das Datei-Attribut fehlgeschlagen. Bitte versuchen Sie es noch einmal.", - "success": "Der Wert für das Dateiattribut wurde erfolgreich aktualisiert." - } - }, "file-attribute-encoding-types": { "ascii": "ASCII", "iso": "ISO-8859-1", @@ -1400,6 +1410,12 @@ "number": "Nummer", "text": "Freier Text" }, + "file-attribute": { + "update": { + "error": "Aktualisierung des Werts für das Datei-Attribut fehlgeschlagen. Bitte versuchen Sie es noch einmal.", + "success": "Der Wert für das Dateiattribut wurde erfolgreich aktualisiert." + } + }, "file-attributes-configurations": { "cancel": "Abbrechen", "form": { @@ -1617,15 +1633,6 @@ "csv": "Die Datei-Attribute wurden erfolgreich aus der hochgeladenen CSV-Datei importiert." } }, - "filter": { - "analysis": "Analyse erforderlich", - "comment": "Kommentare", - "hint": "Nur Hinweise", - "image": "Bilder", - "none": "Keine Annotationen", - "redaction": "Annotationen", - "updated": "Aktualisiert" - }, "filter-menu": { "filter-options": "Filteroptionen", "filter-types": "Filter", @@ -1635,6 +1642,15 @@ "unseen-pages": "Nur Anmerkungen auf ungesehenen Seiten", "with-comments": "Nur Anmerkungen mit Kommentaren" }, + "filter": { + "analysis": "Analyse erforderlich", + "comment": "Kommentare", + "hint": "Nur Hinweise", + "image": "Bilder", + "none": "Keine Annotationen", + "redaction": "Annotationen", + "updated": "Aktualisiert" + }, "filters": { "assigned-people": "Bearbeiter", "documents-status": "Dokumentenstatus", @@ -1868,20 +1884,25 @@ "save": "Speichern" }, "content": { - "apply-on-multiple-pages": "Apply on multiple pages", - "apply-on-multiple-pages-hint": "Minus(-) for range and comma(,) for enumeration.", - "apply-on-multiple-pages-placeholder": "e.g. 1-20,22,32", "classification": "Wert / Klassifizierung", "comment": "Kommentar", - "dictionary": "Wörterbuch", - "edit-selected-text": "Edit selected text", "legalBasis": "Rechtsgrundlage", + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + }, "reason": "Begründung", "reason-placeholder": "Wählen Sie eine Begründung aus ...", - "rectangle": "Benutzerdefinierter Bereich", - "section": "Absatz / Ort", - "text": "Ausgewählter Text:", - "type": "Entity" + "section": "Absatz / Ort" }, "error": "Error! Invalid page selection", "header": { @@ -1913,13 +1934,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", @@ -1933,6 +1947,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", @@ -1950,7 +1965,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", @@ -1958,6 +1972,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", @@ -2004,14 +2025,34 @@ "previous": "Vorherige" }, "pdf-viewer": { + "header": { + "all-annotations-loaded": "", + "compare-button": "", + "layers-panel-button": "", + "left-panel-button": "", + "load-all-annotations": "", + "no-outlines-text": "", + "no-signatures-text": "", + "outline-multi-select": "", + "outlines-panel-button": "", + "pan-tool-button": "", + "rectangle-tool-button": "", + "rotate-left-button": "", + "rotate-right-button": "", + "select-tool-button": "", + "signature-panel-button": "", + "thumbnails-panel-button": "", + "toggle-layers": "", + "toggle-readable-redactions": "", + "toggle-tooltips": "", + "zoom-in-button": "", + "zoom-out-button": "" + }, "text-popup": { "actions": { "search": "Search for selected text" } - }, - "toggle-layers": "{active, select, true{Disable} false{Enable} other{}} layout grid", - "toggle-readable-redactions": "Show components {active, select, true{as in final document} false{in preview color} other{}}", - "toggle-tooltips": "{active, select, true{Disable} false{Enable} other{}} Kurzinfos für Anmerkungen" + } }, "permissions-screen": { "dossier": { @@ -2049,16 +2090,16 @@ "warnings-label": "Prompts and dialogs", "warnings-subtitle": "Do not show again options" }, - "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": { @@ -2073,6 +2114,10 @@ "edit-text": "", "legal-basis": "Legal basis", "options": { + "in-document": { + "description": "", + "label": "" + }, "in-dossier": { "description": "Add redaction in every document in {dossierName}.", "extraOptionLabel": "Apply to all dossiers", @@ -2088,7 +2133,8 @@ "revert-text": "", "type": "Type", "type-placeholder": "Select type...", - "unchanged": "" + "unchanged": "", + "value": "" }, "title": "Redact text" } @@ -2112,6 +2158,10 @@ "description-bulk": "The selected items should not be annotated in their respective contexts.", "label": "False positive" }, + "in-document": { + "description": "", + "label": "" + }, "in-dossier": { "description": "Do not annotate ''{value}'' as ''{type}'' in any dossier.", "description-bulk": "Do not annotate the selected terms as their respective types in any dossier.", @@ -2129,6 +2179,25 @@ "title": "Remove {count, plural, one{annotation} other {annotations}}" } }, + "remove-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + } + } + } + }, "remove-redaction": { "dialog": { "actions": { @@ -2152,6 +2221,10 @@ "extraOptionLabel": "Apply to all dossiers", "label": "False positive" }, + "in-document": { + "description": "", + "label": "" + }, "in-dossier": { "description": "Do not {type} \"{value}\" in any document of the current dossier.", "description-bulk": "", @@ -2294,12 +2367,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", @@ -2323,6 +2390,12 @@ "no-match": "Keine Dokumente entsprechen Ihren aktuellen Filtern.", "table-header": "{length} search {length, plural, one{result} other{results}}" }, + "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": { @@ -2513,10 +2586,6 @@ "view-as": "Ansicht als:", "workflow": "Arbeitsablauf" }, - "viewer-header": { - "all-annotations-loaded": "All annotations loaded", - "load-all-annotations": "Load all annotations" - }, "watermark-screen": { "action": { "change-success": "Das Wasserzeichen wurde aktualisiert!", @@ -2545,6 +2614,10 @@ "orientation": "Ausrichtung", "text-label": "Watermark text", "text-placeholder": "Text eingeben" + }, + "pagination": { + "landscape": "", + "portrait": "" } }, "watermarks-listing": { diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 974651f57..5b74c260d 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -1273,6 +1273,25 @@ }, "side-nav-title": "Configurations" }, + "edit-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + } + } + } + }, "edit-redaction": { "dialog": { "actions": { @@ -1865,20 +1884,25 @@ "save": "Save" }, "content": { - "apply-on-multiple-pages": "Apply on multiple pages", - "apply-on-multiple-pages-hint": "Minus(-) for range and comma(,) for enumeration.", - "apply-on-multiple-pages-placeholder": "e.g. 1-20,22,32", "classification": "Value / classification", "comment": "Comment", - "dictionary": "Dictionary", - "edit-selected-text": "Edit selected text", "legalBasis": "Legal Basis", + "options": { + "multiple-pages": { + "description": "Edit redaction the range of pages", + "extraOptionDescription": "Minus(-) for range and comma(,) for enumeration", + "extraOptionLabel": "Range", + "extraOptionPlaceholder": "e.g. 1-20,22,32", + "label": "Apply on multiple pages" + }, + "only-this-page": { + "description": "Edit redaction only at this position in this document", + "label": "Apply only on this page" + } + }, "reason": "Reason", "reason-placeholder": "Select a reason ...", - "rectangle": "Custom Rectangle", - "section": "Paragraph / Location", - "text": "Selected text:", - "type": "Entity" + "section": "Paragraph / Location" }, "error": "Error! Invalid page selection", "header": { @@ -2155,6 +2179,25 @@ "title": "Remove {count, plural, one{annotation} other {annotations}}" } }, + "remove-rectangle": { + "dialog": { + "content": { + "options": { + "multiple-pages": { + "description": "", + "extraOptionDescription": "", + "extraOptionLabel": "", + "extraOptionPlaceholder": "", + "label": "" + }, + "only-this-page": { + "description": "", + "label": "" + } + } + } + } + }, "remove-redaction": { "dialog": { "actions": { diff --git a/libs/common-ui b/libs/common-ui index 304657d25..3c89b8f7e 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 304657d2599f2f076b50c9c98b438a34fb4d081f +Subproject commit 3c89b8f7e71eb9253aa40f40c1598eac2c400c71 diff --git a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts index 189d16a88..2665fa420 100644 --- a/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts +++ b/libs/red-domain/src/lib/redaction-log/add-redaction.request.ts @@ -14,4 +14,6 @@ export interface IAddRedactionRequest { section?: string; rectangle?: boolean; addToAllDossiers?: boolean; + pageNumbers?: []; + caseSensitive?: boolean; } diff --git a/libs/red-domain/src/lib/redaction-log/recategorization.request.ts b/libs/red-domain/src/lib/redaction-log/recategorization.request.ts index 815d28acf..edf967fc8 100644 --- a/libs/red-domain/src/lib/redaction-log/recategorization.request.ts +++ b/libs/red-domain/src/lib/redaction-log/recategorization.request.ts @@ -1,3 +1,5 @@ +import { IEntityLogEntryPosition } from './entity-log-entry'; + export interface IRecategorizationRequest { readonly annotationId?: string; readonly comment?: string; @@ -15,9 +17,6 @@ export interface IBulkRecategorizationRequest { readonly originTypes: string[]; readonly originLegalBases: string[]; readonly rectangle: boolean; - readonly position?: { - readonly rectangle: number[]; - readonly pageNumber: number; - }; + readonly position?: IEntityLogEntryPosition; readonly pageNumbers?: number[]; }