From 6f94b1198ac7120b3304c4d8ea7b38f75ead9244 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 15 Sep 2023 13:42:09 +0300 Subject: [PATCH 01/12] fix text formatting for multiline redactions --- .../redact-text-dialog.component.html | 10 ++- .../redact-text-dialog.component.scss | 4 ++ .../redact-text-dialog.component.ts | 66 ++++++++----------- .../services/pdf-proxy.service.ts | 2 +- 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html index e900cddfb..71f903cf8 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html @@ -6,14 +6,16 @@
+
- {{ form.get('selectedText').value }} + + + + - +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss index f3381afc3..f1487499b 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.scss @@ -43,3 +43,7 @@ textarea { margin-top: 0; } + +.use-n-as-line-break { + white-space: pre-line !important; +} 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 3a11a87a2..c63635e4e 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 @@ -1,18 +1,18 @@ import { Component, inject, OnInit } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { FormBuilder, UntypedFormGroup } from '@angular/forms'; +import { FormBuilder } from '@angular/forms'; import { DetailsRadioOption, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; import { Dictionary, 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 { calcTextWidthInPixels } from '@utils/functions'; import { firstValueFrom } from 'rxjs'; import { tap } from 'rxjs/operators'; import { getRedactOrHintOptions, RedactOrHintOption, RedactOrHintOptions } from '../../utils/dialog-options'; import { RedactTextData, RedactTextResult } from '../../utils/dialog-types'; import { LegalBasisOption } from '../manual-redaction-dialog/manual-annotation-dialog.component'; -import { calcTextWidthInPixels } from '@utils/functions'; const MAXIMUM_SELECTED_TEXT_WIDTH = 421; @@ -24,19 +24,19 @@ export class RedactTextDialogComponent extends IqserDialogComponent implements OnInit { - readonly #manualRedactionTypeExists: boolean; readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId); + readonly #manualRedactionTypeExists = inject(DictionaryService).hasManualType(this.#dossier.dossierTemplateId); #applyToAllDossiers = this.data.applyToAllDossiers ?? true; readonly roles = Roles; readonly iconButtonTypes = IconButtonTypes; - readonly options: DetailsRadioOption[]; - readonly form: UntypedFormGroup; - readonly initialText: string; + readonly options = getRedactOrHintOptions(this.#dossier, this.#applyToAllDossiers, this.data.isApprover); + readonly initialText = this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value; + readonly form = this.#getForm(); dictionaryRequest = false; legalOptions: LegalBasisOption[] = []; dictionaries: Dictionary[] = []; isEditingSelectedText = false; - modifiedText: string; + modifiedText = this.initialText; selectedTextRows = 1; constructor( @@ -45,16 +45,8 @@ export class RedactTextDialogComponent private readonly _formBuilder: FormBuilder, ) { super(); - this.#manualRedactionTypeExists = this._dictionaryService.hasManualType(this.#dossier.dossierTemplateId); - this.options = getRedactOrHintOptions(this.#dossier, this.#applyToAllDossiers, this.data.isApprover); - - this.form = this.#getForm(); - this.initialText = this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value; - this.modifiedText = this.initialText; - - this.form - .get('option') - .valueChanges.pipe( + this.form.controls.option.valueChanges + .pipe( tap((option: DetailsRadioOption) => { this.dictionaryRequest = option.value === RedactOrHintOptions.IN_DOSSIER; if (this.dictionaryRequest) { @@ -62,7 +54,7 @@ export class RedactTextDialogComponent this.form.patchValue({ selectedText: this.modifiedText }); } else { this.isEditingSelectedText = false; - this.modifiedText = this.form.get('selectedText').value; + this.modifiedText = this.form.controls.selectedText.value; this.form.patchValue({ selectedText: this.initialText }); } this.#resetValues(); @@ -73,7 +65,7 @@ export class RedactTextDialogComponent } get displayedDictionaryLabel() { - const dictType = this.form.get('dictionary').value; + const dictType = this.form.controls.dictionary.value; if (dictType) { return this.dictionaries.find(d => d.type === dictType)?.label ?? null; } @@ -82,9 +74,9 @@ export class RedactTextDialogComponent get disabled() { if (this.dictionaryRequest) { - return !this.form.get('dictionary').value; + return !this.form.controls.dictionary.value; } - return !this.form.get('reason').value; + return !this.form.controls.dictionary.value; } async ngOnInit(): Promise { @@ -108,18 +100,18 @@ export class RedactTextDialogComponent this.#applyToAllDossiers = option.extraOption.checked; this.#setDictionaries(); - if (this.#applyToAllDossiers && this.form.get('dictionary').value) { - const selectedDictionaryLabel = this.form.get('dictionary').value; + if (this.#applyToAllDossiers && this.form.controls.dictionary.value) { + const selectedDictionaryLabel = this.form.controls.dictionary.value; const selectedDictionary = this.dictionaries.find(d => d.type === selectedDictionaryLabel); if (!selectedDictionary) { - this.form.get('dictionary').setValue(null); + this.form.controls.dictionary.setValue(null); } } } typeChanged() { if (!this.#applyToAllDossiers) { - const selectedDictionaryType = this.form.get('dictionary').value; + const selectedDictionaryType = this.form.controls.dictionary.value; const selectedDictionary = this.dictionaries.find(d => d.type === selectedDictionaryType); this.options[1].extraOption.disabled = selectedDictionary.dossierDictionaryOnly; } @@ -130,14 +122,14 @@ export class RedactTextDialogComponent const redaction = this.data.manualRedactionEntryWrapper.manualRedactionEntry; this.close({ redaction, - dictionary: this.dictionaries.find(d => d.type === this.form.get('dictionary').value), + dictionary: this.dictionaries.find(d => d.type === this.form.controls.dictionary.value), }); } toggleEditingSelectedText() { this.isEditingSelectedText = !this.isEditingSelectedText; if (this.isEditingSelectedText) { - const width = calcTextWidthInPixels(this.form.get('selectedText').value); + const width = calcTextWidthInPixels(this.form.controls.selectedText.value); this.selectedTextRows = Math.ceil(width / MAXIMUM_SELECTED_TEXT_WIDTH); } } @@ -149,25 +141,25 @@ export class RedactTextDialogComponent #getForm() { return this._formBuilder.group({ selectedText: this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value, - reason: [null], + reason: null as LegalBasisOption, comment: [null], dictionary: [this.#manualRedactionTypeExists ? SuperTypes.ManualRedaction : null], - option: [this.options[0]], + option: this.options[0], }); } #selectReason() { if (this.legalOptions.length === 1) { - this.form.get('reason').setValue(this.legalOptions[0]); + this.form.controls.reason.setValue(this.legalOptions[0]); } } #enhanceManualRedaction(addRedactionRequest: IAddRedactionRequest) { - addRedactionRequest.type = this.form.get('dictionary').value; + addRedactionRequest.type = this.form.controls.dictionary.value; addRedactionRequest.section = null; - addRedactionRequest.value = this.form.get('selectedText').value; + addRedactionRequest.value = this.form.controls.selectedText.value; - const legalOption: LegalBasisOption = this.form.get('reason').value; + const legalOption: LegalBasisOption = this.form.controls.reason.value; if (legalOption) { addRedactionRequest.reason = legalOption.description; addRedactionRequest.legalBasis = legalOption.legalBasis; @@ -184,7 +176,7 @@ export class RedactTextDialogComponent if (!addRedactionRequest.reason) { addRedactionRequest.reason = 'Dictionary Request'; } - const commentValue = this.form.get('comment').value; + const commentValue = this.form.controls.comment.value; addRedactionRequest.comment = commentValue ? { text: commentValue } : null; addRedactionRequest.addToAllDossiers = this.data.isApprover && this.dictionaryRequest && this.#applyToAllDossiers; } @@ -193,10 +185,10 @@ export class RedactTextDialogComponent this.#applyToAllDossiers = this.data.applyToAllDossiers ?? true; this.options[1].extraOption.checked = this.#applyToAllDossiers; if (this.dictionaryRequest) { - this.form.get('reason').setValue(null); - this.form.get('dictionary').setValue(null); + this.form.controls.reason.setValue(null); + this.form.controls.dictionary.setValue(null); return; } - this.form.get('dictionary').setValue(this.#manualRedactionTypeExists ? SuperTypes.ManualRedaction : null); + this.form.controls.dictionary.setValue(this.#manualRedactionTypeExists ? SuperTypes.ManualRedaction : null); } } diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index ce5b804d2..a63e2d645 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -274,7 +274,7 @@ export class PdfProxyService { #formatSelectedText(text: string): string { return text?.replace( // eslint-disable-next-line no-control-regex,max-len - /([^\s\d-]{2,})[-\u00AD]\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]/gi, + /([^\s\d-]{2,})[-\u00AD]\u000D|[\u000B\u000C\u000D\u0085\u2028\u2029]/gi, '$1', ); } From 33e0ba3d574159f9e3820a0a5c799c7b2e98163a Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 15 Sep 2023 13:43:13 +0300 Subject: [PATCH 02/12] update node version --- docker/red-ui/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/red-ui/Dockerfile b/docker/red-ui/Dockerfile index e73829193..2aea4ec1e 100644 --- a/docker/red-ui/Dockerfile +++ b/docker/red-ui/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20.5-buster as builder +FROM node:20.6-buster as builder WORKDIR /ng-app From 258a304b94bc5bdc63f9ae3e780756e9a9d40fde Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 15 Sep 2023 13:53:31 +0300 Subject: [PATCH 03/12] use \n as line break --- .../add-annotation-dialog.component.html | 2 +- .../add-annotation-dialog.component.ts | 21 ++++++++++--------- .../redact-text-dialog.component.html | 6 +++++- .../redact-text-dialog.component.scss | 4 ---- libs/common-ui | 2 +- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.html index 4993b949f..97a163b1a 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.html @@ -5,7 +5,7 @@
- {{ form.get('selectedText').value }} +
diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.ts index f58b626b4..f2e596777 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/docu-mine/add-annotation-dialog/add-annotation-dialog.component.ts @@ -1,10 +1,9 @@ import { Component, inject, OnInit } from '@angular/core'; import { FormBuilder } from '@angular/forms'; -import { IconButtonTypes, IqserDialogComponent, IqserPermissionsService } from '@iqser/common-ui'; +import { IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui'; import { Dictionary, IAddRedactionRequest } from '@red/domain'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { DictionaryService } from '@services/entity-services/dictionary.service'; -import { Roles } from '@users/roles'; import { AddAnnotationData, AddAnnotationResult } from '../../../utils/dialog-types'; @Component({ @@ -15,17 +14,19 @@ export class AddAnnotationDialogComponent implements OnInit { readonly #dossier = inject(ActiveDossiersService).find(this.data.dossierId); - readonly #isRss = inject(IqserPermissionsService).has(Roles.getRss); readonly iconButtonTypes = IconButtonTypes; dictionaries: Dictionary[] = []; readonly form = this.#getForm(); - constructor(private readonly _dictionaryService: DictionaryService, private readonly _formBuilder: FormBuilder) { + constructor( + private readonly _dictionaryService: DictionaryService, + private readonly _formBuilder: FormBuilder, + ) { super(); } get displayedDictionaryLabel() { - const dictType = this.form.get('dictionary').value; + const dictType = this.form.controls.dictionary.value; if (dictType) { return this.dictionaries.find(d => d.type === dictType)?.label ?? null; } @@ -33,7 +34,7 @@ export class AddAnnotationDialogComponent } get disabled() { - return !this.#isRss || !this.form.get('dictionary').value; + return !this.form.controls.dictionary.value; } ngOnInit() { @@ -45,7 +46,7 @@ export class AddAnnotationDialogComponent const redaction = this.data.manualRedactionEntryWrapper.manualRedactionEntry; this.close({ redaction, - dictionary: this.dictionaries.find(d => d.type === this.form.get('dictionary').value), + dictionary: this.dictionaries.find(d => d.type === this.form.controls.dictionary.value), }); } @@ -58,16 +59,16 @@ export class AddAnnotationDialogComponent } #enhanceManualRedaction(addRedactionRequest: IAddRedactionRequest) { - addRedactionRequest.type = this.form.get('dictionary').value; + addRedactionRequest.type = this.form.controls.dictionary.value; const selectedType = this.dictionaries.find(d => d.type === addRedactionRequest.type); addRedactionRequest.addToDictionary = !!selectedType?.hasDictionary; addRedactionRequest.reason ??= 'Dictionary Request'; - const commentValue = this.form.get('comment').value; + const commentValue = this.form.controls.comment.value; addRedactionRequest.comment = commentValue ? { text: commentValue } : null; addRedactionRequest.section = null; - addRedactionRequest.value = this.form.get('selectedText').value; + addRedactionRequest.value = this.form.controls.selectedText.value; addRedactionRequest.addToAllDossiers = addRedactionRequest.addToDictionary || !!this.data.applyToAllDossiers; } } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html index 71f903cf8..150c83ee9 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/redact-text-dialog/redact-text-dialog.component.html @@ -14,7 +14,11 @@ >
- +