From 7a1e968a52bc4cd8c864768ab3406963ab201666 Mon Sep 17 00:00:00 2001 From: Valentin Mihai Date: Sat, 5 Oct 2024 20:50:40 +0300 Subject: [PATCH] RED-7340 - converted ManualAnnotationDialog into RectangleAnnotationDialog --- .../change-legal-basis-dialog.component.ts | 7 +- .../edit-redaction-dialog.component.ts | 3 +- .../force-annotation-dialog.component.ts | 10 +- ...ectangle-annotation-dialog.component.html} | 38 +----- ...ectangle-annotation-dialog.component.scss} | 5 + .../rectangle-annotation-dialog.component.ts} | 123 ++++++------------ .../redact-recommendation-dialog.component.ts | 2 +- .../redact-text-dialog.component.ts | 10 +- .../file-preview-screen.component.ts | 41 +++--- .../services/annotation-actions.service.ts | 2 +- .../services/file-preview-dialog.service.ts | 7 +- .../services/manual-redaction.service.ts | 2 + .../file-preview/utils/dialog-options.ts | 2 +- .../file-preview/utils/dialog-types.ts | 6 + .../enhance-manual-redaction-request.utils.ts | 39 +++++- apps/red-ui/src/assets/config/config.json | 4 +- libs/common-ui | 2 +- .../redaction-log/add-redaction.request.ts | 2 + 18 files changed, 139 insertions(+), 166 deletions(-) rename apps/red-ui/src/app/modules/file-preview/dialogs/{manual-redaction-dialog/manual-annotation-dialog.component.html => rectangle-annotation-dialog/rectangle-annotation-dialog.component.html} (71%) rename apps/red-ui/src/app/modules/file-preview/dialogs/{manual-redaction-dialog/manual-annotation-dialog.component.scss => rectangle-annotation-dialog/rectangle-annotation-dialog.component.scss} (84%) rename apps/red-ui/src/app/modules/file-preview/dialogs/{manual-redaction-dialog/manual-annotation-dialog.component.ts => rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts} (63%) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts index dccb2181d..457bd752c 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component.ts @@ -11,12 +11,7 @@ import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select import { NgForOf, NgIf } from '@angular/common'; import { MatTooltip } from '@angular/material/tooltip'; import { TranslateModule } from '@ngx-translate/core'; - -export interface LegalBasisOption { - label?: string; - legalBasis?: string; - description?: string; -} +import { LegalBasisOption } from '../../utils/dialog-types'; @Component({ templateUrl: './change-legal-basis-dialog.component.html', 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..8f3a13cb2 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 @@ -26,8 +26,7 @@ import { 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 { EditRedactionData, EditRedactionOption, EditRedactResult, LegalBasisOption } 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'; 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/rectangle-annotation-dialog/rectangle-annotation-dialog.component.html similarity index 71% rename from apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.html rename to apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.html index ea503b117..57cb3dbf3 100644 --- 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/rectangle-annotation-dialog/rectangle-annotation-dialog.component.html @@ -3,35 +3,11 @@
- - - -
- -
- {{ form.get('selectedText').value }} - -
- - -
- -
- -
+
-
+
-
+
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/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts similarity index 63% rename from apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts rename to apps/red-ui/src/app/modules/file-preview/dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts index 4755981ef..7aaf1072c 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/rectangle-annotation-dialog/rectangle-annotation-dialog.component.ts @@ -1,24 +1,23 @@ -import { Component, Inject, OnChanges, OnInit, SimpleChanges } from '@angular/core'; -import { ReactiveFormsModule, Validators } from '@angular/forms'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { - BaseDialogComponent, CircleButtonComponent, HasScrollbarDirective, IconButtonComponent, IqserDenyDirective, + IqserDialogComponent, IqserPermissionsService, + Toaster, } from '@iqser/common-ui'; import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; -import { Dictionary, Dossier, File, IAddRedactionRequest, SuperTypes } from '@red/domain'; +import { Dictionary, Dossier, File, IAddRedactionRequest, IManualRedactionEntry, 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'; @@ -26,23 +25,28 @@ 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 { RectangleRedactOption, RectangleRedactOptions, RedactOrHintOption } from '../../utils/dialog-types'; +import { LegalBasisOption, 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'; +import { getMultiplePagesRectangle } from '../../utils/enhance-manual-redaction-request.utils'; -export interface LegalBasisOption { - label?: string; - legalBasis?: string; - description?: string; +interface RectangleDialogData { + dossierId: string; + manualRedactionEntryWrapper: ManualRedactionEntryWrapper; + file: File; +} +export interface RectangleDialogResult { + annotation: IManualRedactionEntry; + dictionary: Dictionary; } export const NON_READABLE_CONTENT = 'non-readable content'; @Component({ - templateUrl: './manual-annotation-dialog.component.html', - styleUrls: ['./manual-annotation-dialog.component.scss'], + templateUrl: './rectangle-annotation-dialog.component.html', + styleUrls: ['./rectangle-annotation-dialog.component.scss'], standalone: true, imports: [ ReactiveFormsModule, @@ -63,29 +67,30 @@ export const NON_READABLE_CONTENT = 'non-readable content'; ], providers: [ManualRedactionService], }) -export class ManualAnnotationDialogComponent extends BaseDialogComponent implements OnInit { +export class RectangleAnnotationDialog + extends IqserDialogComponent + implements OnInit +{ readonly #dossier: Dossier; protected readonly roles = Roles; protected readonly options: DetailsRadioOption[]; protected isDictionaryRequest: boolean; protected isFalsePositiveRequest: boolean; - protected isEditingSelectedText = false; - protected applyOnMultiplePages = false; protected manualRedactionTypeExists = true; protected possibleDictionaries: Dictionary[] = []; protected legalOptions: LegalBasisOption[] = []; + readonly form: UntypedFormGroup; constructor( - readonly iqserPermissionsService: IqserPermissionsService, + private readonly iqserPermissionsService: IqserPermissionsService, private readonly _justificationsService: JustificationsService, private readonly _manualRedactionService: ManualRedactionService, - activeDossiersService: ActiveDossiersService, + private readonly 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 }, + private readonly _formBuilder: FormBuilder, + private readonly _toaster: Toaster, ) { - super(_dialogRef); + super(); this.#dossier = activeDossiersService.find(this.data.dossierId); this.isFalsePositiveRequest = this.data.manualRedactionEntryWrapper.type === 'FALSE_POSITIVE'; @@ -111,10 +116,6 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme 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) { @@ -124,7 +125,7 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme } get disabled() { - return this.form.invalid || (this.applyOnMultiplePages && !this.form.get('multiplePages')?.value); + return this.form.invalid; } async ngOnInit() { @@ -142,21 +143,17 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme 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, + const annotation = + this.form.get('option').value.value === RectangleRedactOptions.MULTIPLE_PAGES + ? getMultiplePagesRectangle(this.#multiplePagesRectangleData).manualRedactionEntry + : this.data.manualRedactionEntryWrapper; + super.close({ + annotation, dictionary: this.possibleDictionaries.find(d => d.type === this.form.get('dictionary').value), }); } catch (e) { @@ -164,47 +161,12 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme } } - 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', - ); + get #multiplePagesRectangleData() { + return { + manualRedactionEntryWrapper: this.data.manualRedactionEntryWrapper, + pages: this.form.get('option').value.additionalInput.value, + file: this.data.file, + }; } #getForm() { @@ -217,7 +179,6 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme : [this.manualRedactionTypeExists ? SuperTypes.ManualRedaction : null, Validators.required], comment: [null], classification: [NON_READABLE_CONTENT], - multiplePages: '', option: [this.#getOption(SystemDefaults.RECTANGLE_REDACT_DEFAULT), validatePageRange()], }); } @@ -243,9 +204,7 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme 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; + addRedactionRequest.value = this.form.get('classification').value; } #getOption(option: RectangleRedactOption): DetailsRadioOption { 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 163b8363c..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', 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 6a9d46536..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; 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 7701d687c..e6d6227e8 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', @@ -363,29 +364,27 @@ 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, { + dictionaryLabel: result.dictionary?.label, + }); + + const addAndReload$ = add$.pipe(switchMap(() => this._filesService.reload(this.dossierId, file))); + return firstValueFrom(addAndReload$.pipe(catchError(() => of(undefined)))); } async viewerReady(pageNumber?: string) { @@ -622,7 +621,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 bd89af035..aed308032 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 @@ -48,7 +48,7 @@ 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'; @Injectable() export class AnnotationActionsService { 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..675ad5407 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 @@ -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 8f5830e0f..19f6b7b79 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 @@ -148,7 +148,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, 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 94aff4a00..2b8a44dc4 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 @@ -47,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; 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..701028276 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,6 @@ -import { Dictionary, IAddRedactionRequest, SuperType } from '@red/domain'; -import { LegalBasisOption } from '../dialogs/manual-redaction-dialog/manual-annotation-dialog.component'; +import { Dictionary, File, IAddRedactionRequest, SuperType } from '@red/domain'; +import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper'; +import { LegalBasisOption } from './dialog-types'; export interface EnhanceRequestData { readonly type: SuperType | null; @@ -12,6 +13,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 +45,31 @@ export const enhanceManualRedactionRequest = (addRedactionRequest: IAddRedaction addRedactionRequest.comment = commentValue ? { text: commentValue } : null; addRedactionRequest.addToAllDossiers = data.isApprover && data.dictionaryRequest && data.applyToAllDossiers; }; + +export const getMultiplePagesRectangle = (data: MultiplePagesRectangleData) => { + const value: string = data.pages.replace(/[^0-9-,]/g, ''); + const entry = { ...data.manualRedactionEntryWrapper.manualRedactionEntry, pageNumbers: [] }; + const wrapper = { + ...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 > data.file.numberOfPages || endPage > 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; +}; 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/libs/common-ui b/libs/common-ui index 34387d49d..3c89b8f7e 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 34387d49d29ba6449c1311cc1c5434b540398660 +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; }