+
-
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/manual-redaction-dialog/manual-annotation-dialog.component.scss
index 07b46869c..a0421d753 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/manual-redaction-dialog/manual-annotation-dialog.component.scss
@@ -1,3 +1,23 @@
.full-width {
width: 100%;
}
+
+.apply-on-multiple-pages {
+ min-height: 55px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+
+ &.iqser-input-group input {
+ margin-top: 0;
+ }
+
+ mat-checkbox {
+ width: fit-content;
+ margin-right: 16px;
+ }
+}
+
+.mb-15 {
+ margin-bottom: 15px;
+}
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
index 2acec7c55..b3db1abc3 100644
--- 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
@@ -6,9 +6,10 @@ import { JustificationsService } from '@services/entity-services/justifications.
import { Dictionary, Dossier, IAddRedactionRequest } from '@red/domain';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { DictionaryService } from '@services/entity-services/dictionary.service';
-import { BaseDialogComponent, CircleButtonTypes } from '@iqser/common-ui';
+import { BaseDialogComponent, CircleButtonTypes, Toaster } from '@iqser/common-ui';
import { firstValueFrom } from 'rxjs';
import { ManualRedactionService } from '../../services/manual-redaction.service';
+import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
export interface LegalBasisOption {
label?: string;
@@ -38,8 +39,9 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _dictionaryService: DictionaryService,
protected readonly _injector: Injector,
+ protected readonly _toaster: Toaster,
protected readonly _dialogRef: MatDialogRef,
- @Inject(MAT_DIALOG_DATA) public data: { manualRedactionEntryWrapper: ManualRedactionEntryWrapper; dossierId: string },
+ @Inject(MAT_DIALOG_DATA) readonly data: { manualRedactionEntryWrapper: ManualRedactionEntryWrapper; dossierId: string },
) {
super(_injector, _dialogRef);
this._dossier = this._activeDossiersService.find(this.data.dossierId);
@@ -55,6 +57,10 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
return this._manualRedactionService.getTitle(this.data.manualRedactionEntryWrapper.type, this._dossier);
}
+ get isRectangle() {
+ return !!this.data.manualRedactionEntryWrapper.manualRedactionEntry.rectangle;
+ }
+
get displayedDictionaryLabel() {
const dictType = this.form.get('dictionary').value;
if (dictType) {
@@ -81,14 +87,43 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
}));
this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
- if (!this.data.manualRedactionEntryWrapper.manualRedactionEntry.rectangle) {
+ if (!this.isRectangle) {
this._formatSelectedTextValue();
}
}
save() {
this._enhanceManualRedaction(this.data.manualRedactionEntryWrapper.manualRedactionEntry);
- this._dialogRef.close(this.data.manualRedactionEntryWrapper);
+ try {
+ const annotations = this.isRectangle ? this.#getRectangles() : [this.data.manualRedactionEntryWrapper];
+ this._dialogRef.close(annotations);
+ } catch (e) {
+ this._toaster.error(_('manual-annotation.dialog.error'));
+ }
+ }
+
+ #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) {
+ throw new Error();
+ }
+
+ for (let page = startPage; page <= endPage; page++) {
+ const manualRedactionEntry = { ...entry, positions: [{ ...quads, page }] };
+ wrappers.push({ ...wrapper, manualRedactionEntry });
+ }
+ });
+
+ return wrappers;
}
private _formatSelectedTextValue() {
@@ -110,6 +145,7 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
: ['manual', Validators.required],
comment: [null],
classification: ['non-readable content'],
+ multiplePages: '',
});
}
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 2a0c8f2cf..dfc0a80f6 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
@@ -30,7 +30,7 @@ import { FileWorkloadComponent } from './components/file-workload/file-workload.
import { TranslateService } from '@ngx-translate/core';
import { FilesService } from '@services/entity-services/files.service';
import { FileManagementService } from '@services/entity-services/file-management.service';
-import { catchError, debounceTime, map, startWith, switchMap, tap, withLatestFrom } from 'rxjs/operators';
+import { catchError, debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators';
import { FilesMapService } from '@services/entity-services/files-map.service';
import { WatermarkService } from '@shared/services/watermark.service';
import { ExcludedPagesService } from './services/excluded-pages.service';
@@ -266,12 +266,14 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
'manualAnnotation',
null,
{ manualRedactionEntryWrapper, dossierId: this.dossierId },
- ({ manualRedactionEntry }: ManualRedactionEntryWrapper) => {
- const add$ = this._manualRedactionService.addAnnotation([manualRedactionEntry], this.dossierId, this.fileId);
- const addAndReload$ = add$.pipe(
- withLatestFrom(this.state.file$),
- switchMap(([, file]) => this._filesService.reload(this.dossierId, file)),
+ async (wrappers: ManualRedactionEntryWrapper[]) => {
+ const file = await this.state.file;
+ const add$ = this._manualRedactionService.addAnnotation(
+ wrappers.map(w => w.manualRedactionEntry).filter(e => e.positions[0].page <= file.numberOfPages),
+ this.dossierId,
+ this.fileId,
);
+ const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file)));
return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined))));
},
);
diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json
index cf9aac978..3a691f506 100644
--- a/apps/red-ui/src/assets/i18n/de.json
+++ b/apps/red-ui/src/assets/i18n/de.json
@@ -1516,6 +1516,9 @@
"save": "Speichern"
},
"content": {
+ "apply-on-multiple-pages": "",
+ "apply-on-multiple-pages-hint": "",
+ "apply-on-multiple-pages-placeholder": "",
"classification": "Wert / Klassifizierung",
"comment": "Kommentar",
"dictionary": "Wörterbuch",
@@ -1527,6 +1530,7 @@
"section": "Absatz / Ort",
"text": "Ausgewählter Text:"
},
+ "error": "",
"header": {
"dictionary": "Zum Wörterbuch hinzufügen",
"false-positive": "Als Falsch-Positiv definieren",
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index 317e7b7d8..0ceb4c396 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -1516,6 +1516,9 @@
"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",
@@ -1527,6 +1530,7 @@
"section": "Paragraph / Location",
"text": "Selected text:"
},
+ "error": "Error! Invalid page selection",
"header": {
"dictionary": "Add to dictionary",
"false-positive": "Set false positive",