diff --git a/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.html b/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.html index a6e907c1b..e3f5c58a5 100644 --- a/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.html +++ b/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.html @@ -26,6 +26,7 @@ *allow="roles.reportTemplates.upload; if: currentUser.isAdmin" [tooltip]="'reports-screen.upload-document' | translate" [attr.help-mode-key]="'upload_report'" + [buttonId]="'upload_report'" icon="iqser:upload" > @@ -46,6 +47,7 @@ { - const foundAnalysisRequiredFile = files.find(file => file.analysisRequired); - const foundUpdatedFile = files.find(file => file.hasUpdates); - if (foundAnalysisRequiredFile || foundUpdatedFile) { - this._dialogService.openDialog( - 'confirm', - { - title: foundAnalysisRequiredFile - ? _('confirmation-dialog.approve-multiple-files-without-analysis.title') - : _('confirmation-dialog.approve-multiple-files.title'), - question: foundAnalysisRequiredFile - ? _('confirmation-dialog.approve-multiple-files-without-analysis.question') - : _('confirmation-dialog.approve-multiple-files.question'), - confirmationText: foundAnalysisRequiredFile - ? _('confirmation-dialog.approve-multiple-files-without-analysis.confirmationText') - : null, - denyText: foundAnalysisRequiredFile ? _('confirmation-dialog.approve-multiple-files-without-analysis.denyText') : null, - } as IConfirmationDialogData, - async () => { - this._loadingService.start(); - await this._filesService.setApproved(files); - this._loadingService.stop(); - }, - ); - } else { - this._loadingService.start(); - await this._filesService.setApproved(files); - this._loadingService.stop(); + this._loadingService.start(); + const approvalResponse: ApproveResponse[] = await this._filesService.getApproveWarnings(files); + this._loadingService.stop(); + const hasWarnings = approvalResponse.some(response => response.hasWarnings); + if (!hasWarnings) { + return; } + + const fileWarnings = approvalResponse.map(response => ({ fileId: response.fileId, fileWarnings: response.fileWarnings })); + this._dialogService.openDialog( + 'confirm', + { + title: _('confirmation-dialog.approve-file.title'), + question: _('confirmation-dialog.approve-file.question'), + translateParams: { questionLength: files.length }, + confirmationText: _('confirmation-dialog.approve-file.confirmationText'), + denyText: _('confirmation-dialog.approve-file.denyText'), + component: ApproveWarningDetailsComponent, + componentInputs: { data: signal(fileWarnings), files: signal(files) }, + cancelButtonPrimary: true, + } as IConfirmationDialogData, + async () => { + this._loadingService.start(); + await this._filesService.setApproved(files); + this._loadingService.stop(); + }, + ); } assign(files: File[]): void { diff --git a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html index b12b528d5..725693fd3 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/editable-structured-component-value/editable-structured-component-value.component.html @@ -32,7 +32,7 @@
diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts index a6e0675a4..6ccf8e4c7 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts @@ -36,7 +36,7 @@ import { workloadTranslations } from '@translations/workload-translations'; import { UserPreferenceService } from '@users/user-preference.service'; import { getLocalStorageDataByFileId } from '@utils/local-storage'; import { combineLatest, delay, Observable } from 'rxjs'; -import { map, tap } from 'rxjs/operators'; +import { filter, map, tap } from 'rxjs/operators'; import scrollIntoView from 'scroll-into-view-if-needed'; import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service'; import { REDDocumentViewer } from '../../../pdf-viewer/services/document-viewer.service'; @@ -187,6 +187,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On const secondary$ = this.filterService.getFilterModels$('secondaryFilters'); return combineLatest([ + this._documentViewer.loaded$, this.fileDataService.all$, primary$, secondary$, @@ -195,7 +196,8 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On this._pageRotationService.rotations$, ]).pipe( delay(0), - map(([annotations, primary, secondary, componentReferenceIds]) => + filter(([loaded]) => loaded), + map(([, annotations, primary, secondary, componentReferenceIds]) => this.#filterAnnotations(annotations, primary, secondary, componentReferenceIds), ), map(annotations => this.#mapListItemsFromAnnotationWrapperArray(annotations)), diff --git a/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.html b/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.html index f8bbf10d5..a47798615 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.html @@ -1,14 +1,17 @@ - - - - + + diff --git a/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.scss b/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.scss index 6812c9358..ebcb45852 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.scss +++ b/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.scss @@ -27,7 +27,7 @@ table { th, td { - &:not(.w-50) { + &:first-child:not(.w-50) { width: 25%; } max-width: 0; diff --git a/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.ts b/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.ts index 3601d4b77..bc8018123 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/selected-annotations-table/selected-annotations-table.component.ts @@ -1,9 +1,9 @@ -import { Component, Input } from '@angular/core'; +import { Component, computed, input } from '@angular/core'; import { NgClass, NgForOf, NgStyle } from '@angular/common'; export interface ValueColumn { label: string; - show: boolean; + hide?: boolean; bold?: boolean; } @@ -18,11 +18,12 @@ const MAX_ITEMS_DISPLAY = 10; styleUrl: './selected-annotations-table.component.scss', }) export class SelectedAnnotationsTableComponent { - @Input({ required: true }) columns: ValueColumn[]; - @Input({ required: true }) data: ValueColumn[][]; - @Input() staticColumns = false; + readonly columns = input.required(); + readonly data = input.required(); + readonly staticColumns = input(false); - get redactedTextsAreaHeight() { - return this.data.length <= MAX_ITEMS_DISPLAY ? TABLE_ROW_SIZE * this.data.length : TABLE_ROW_SIZE * MAX_ITEMS_DISPLAY; - } + readonly redactedTextsAreaHeight = computed(() => + this.data().length <= MAX_ITEMS_DISPLAY ? TABLE_ROW_SIZE * this.data().length : TABLE_ROW_SIZE * MAX_ITEMS_DISPLAY, + ); + readonly shouldApplyHalfWidth = computed(() => this.columns().filter(column => !column.hide).length === 2); } 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 4a0e68714..44aa3110c 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 @@ -77,19 +77,10 @@ export class EditRedactionDialogComponent readonly isRedacted = this.annotations.every(annotation => annotation.isRedacted); readonly isImported: boolean = this.annotations.every(annotation => annotation.imported); readonly allRectangles = this.annotations.reduce((acc, a) => acc && a.AREA, true); - readonly tableColumns = [ - { - label: 'Value', - show: true, - }, - { - label: 'Type', - show: true, - }, - ]; + readonly tableColumns: ValueColumn[] = [{ label: 'Value' }, { label: 'Type' }]; readonly tableData: ValueColumn[][] = this.data.annotations.map(redaction => [ - { label: redaction.value, show: true, bold: true }, - { label: redaction.typeLabel, show: true }, + { label: redaction.value, bold: true }, + { label: redaction.typeLabel }, ]); options: DetailsRadioOption[] | undefined; legalOptions: LegalBasisOption[] = []; 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 2bf000c19..1f41643c1 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 @@ -67,19 +67,10 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen readonly isDocumine = getConfig().IS_DOCUMINE; readonly options: DetailsRadioOption[]; - readonly tableColumns = [ - { - label: 'Value', - show: true, - }, - { - label: 'Type', - show: true, - }, - ]; + readonly tableColumns: ValueColumn[] = [{ label: 'Value' }, { label: 'Type' }]; readonly tableData: ValueColumn[][] = this._data.annotations.map(redaction => [ - { label: redaction.value, show: true, bold: true }, - { label: redaction.typeLabel, show: true }, + { label: redaction.value, bold: true }, + { label: redaction.typeLabel }, ]); legalOptions: LegalBasisOption[] = []; 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 ef4ce7d20..85a109583 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 @@ -75,19 +75,10 @@ export class RedactRecommendationDialogComponent reason: [null], }); - readonly tableColumns = [ - { - label: 'Value', - show: true, - }, - { - label: 'Type', - show: true, - }, - ]; + readonly tableColumns: ValueColumn[] = [{ label: 'Value' }, { label: 'Type' }]; readonly tableData: ValueColumn[][] = this.data.annotations.map(redaction => [ - { label: redaction.value, show: true, bold: true }, - { label: redaction.typeLabel, show: true }, + { label: redaction.value, bold: true }, + { label: redaction.typeLabel }, ]); constructor( diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts index 48e4d99d2..547c4f9ca 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/remove-redaction-dialog/remove-redaction-dialog.component.ts @@ -111,25 +111,19 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent< readonly selectedOption = toSignal(this.form.get('option').valueChanges.pipe(map(value => value.value))); readonly isFalsePositive = computed(() => this.selectedOption() === RemoveRedactionOptions.FALSE_POSITIVE); readonly tableColumns = computed(() => [ - { - label: 'Value', - show: true, - }, - { - label: 'Type', - show: true, - }, + { label: 'Value' }, + { label: 'Type' }, { label: 'Context', - show: this.isFalsePositive(), + hide: !this.isFalsePositive(), }, ]); readonly tableData = computed(() => this.data.redactions.map((redaction, index) => [ - { label: redaction.value, show: true, bold: true }, - { label: redaction.typeLabel, show: true }, - { label: this.data.falsePositiveContext[index], show: this.isFalsePositive() }, + { label: redaction.value, bold: true }, + { label: redaction.typeLabel }, + { label: this.data.falsePositiveContext[index], hide: !this.isFalsePositive() }, ]), ); diff --git a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts index 19a721f98..760c59c66 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, HostBinding, Injector, Input, OnChanges, Optional, ViewChild } from '@angular/core'; +import { ChangeDetectorRef, Component, HostBinding, Injector, Input, OnChanges, Optional, signal, ViewChild } from '@angular/core'; import { toObservable } from '@angular/core/rxjs-interop'; import { Router } from '@angular/router'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -13,7 +13,7 @@ import { } from '@iqser/common-ui'; import { getCurrentUser } from '@iqser/common-ui/lib/users'; import { IqserTooltipPositions } from '@iqser/common-ui/lib/utils'; -import { Action, ActionTypes, Dossier, File, ProcessingFileStatuses, User } from '@red/domain'; +import { Action, ActionTypes, ApproveResponse, Dossier, File, ProcessingFileStatuses, User } from '@red/domain'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { FileManagementService } from '@services/files/file-management.service'; @@ -36,6 +36,7 @@ import { FileAssignService } from '../../services/file-assign.service'; import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component'; import { StatusBarComponent } from '@common-ui/shared'; import { NgIf, NgTemplateOutlet } from '@angular/common'; +import { ApproveWarningDetailsComponent } from '@shared/components/approve-warning-details/approve-warning-details.component'; @Component({ selector: 'redaction-file-actions', @@ -302,20 +303,22 @@ export class FileActionsComponent implements OnChanges { } async setFileApproved() { - if (!this.file.analysisRequired && !this.file.hasUpdates) { - await this.#setFileApproved(); + this._loadingService.start(); + const approvalResponse: ApproveResponse = (await this._filesService.getApproveWarnings([this.file]))[0]; + this._loadingService.stop(); + if (!approvalResponse.hasWarnings) { return; } const data: IConfirmationDialogData = { - title: this.file.analysisRequired - ? _('confirmation-dialog.approve-file-without-analysis.title') - : _('confirmation-dialog.approve-file.title'), - question: this.file.analysisRequired - ? _('confirmation-dialog.approve-file-without-analysis.question') - : _('confirmation-dialog.approve-file.question'), - confirmationText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.confirmationText') : null, - denyText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.denyText') : null, + title: _('confirmation-dialog.approve-file.title'), + question: _('confirmation-dialog.approve-file.question'), + translateParams: { questionLength: 1 }, + confirmationText: _('confirmation-dialog.approve-file.confirmationText'), + denyText: _('confirmation-dialog.approve-file.denyText'), + component: ApproveWarningDetailsComponent, + componentInputs: { data: signal([approvalResponse]), files: signal([this.file]) }, + cancelButtonPrimary: true, }; this._dialogService.openDialog('confirm', data, () => this.#setFileApproved()); diff --git a/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.html b/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.html new file mode 100644 index 000000000..c618edd96 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.html @@ -0,0 +1,9 @@ +
+ @for (file of data(); track file) { + + } +
diff --git a/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.scss b/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.scss new file mode 100644 index 000000000..668a18134 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.scss @@ -0,0 +1,10 @@ +@use 'common-mixins'; + +.scrollable { + overflow-y: auto; + max-height: calc(5 * 50px); + @include common-mixins.scroll-bar; + + padding-left: 2px; + padding-right: 11px; +} diff --git a/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.ts b/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.ts new file mode 100644 index 000000000..91d350058 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/components/approve-warning-details/approve-warning-details.component.ts @@ -0,0 +1,31 @@ +import { Component, computed, input } from '@angular/core'; +import { ApproveResponse, File } from '@red/domain'; +import { SelectedAnnotationsTableComponent } from '../../../file-preview/components/selected-annotations-table/selected-annotations-table.component'; +import { MatExpansionPanel, MatExpansionPanelHeader } from '@angular/material/expansion'; +import { KeyValuePipe, NgStyle } from '@angular/common'; +import { WarningDetailsPanelComponent } from '@shared/components/warning-details-panel/warning-details-panel.component'; +import { CdkFixedSizeVirtualScroll, CdkVirtualScrollViewport } from '@angular/cdk/scrolling'; + +@Component({ + selector: 'redaction-approve-warning-details', + standalone: true, + imports: [ + SelectedAnnotationsTableComponent, + MatExpansionPanel, + MatExpansionPanelHeader, + KeyValuePipe, + WarningDetailsPanelComponent, + CdkVirtualScrollViewport, + CdkFixedSizeVirtualScroll, + NgStyle, + ], + templateUrl: './approve-warning-details.component.html', + styleUrl: './approve-warning-details.component.scss', +}) +export class ApproveWarningDetailsComponent { + readonly data = input.required(); + readonly files = input.required(); + + readonly fileNamesByIds = computed(() => this.files().reduce((acc, file) => ({ ...acc, [file.id]: file.filename }), {})); + readonly shouldPanelOpenDefault = computed(() => this.files().length === 1); +} diff --git a/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.html b/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.html new file mode 100644 index 000000000..bae0d9986 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.html @@ -0,0 +1,8 @@ + + {{ filename() }} + + diff --git a/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.scss b/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.scss new file mode 100644 index 000000000..1be3d10c7 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.scss @@ -0,0 +1,4 @@ +mat-expansion-panel { + margin-bottom: 8px; + max-width: 100%; +} diff --git a/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.ts b/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.ts new file mode 100644 index 000000000..9726e2900 --- /dev/null +++ b/apps/red-ui/src/app/modules/shared/components/warning-details-panel/warning-details-panel.component.ts @@ -0,0 +1,37 @@ +import { Component, computed, inject, input } from '@angular/core'; +import { + SelectedAnnotationsTableComponent, + ValueColumn, +} from '../../../file-preview/components/selected-annotations-table/selected-annotations-table.component'; +import { WarningModel } from '@red/domain'; +import { MatExpansionPanel, MatExpansionPanelHeader } from '@angular/material/expansion'; +import { approvalWarningReasonTranslations } from '@translations/approval-warning-reason-translations'; +import { TranslateService } from '@ngx-translate/core'; + +@Component({ + selector: 'redaction-warning-details-panel', + standalone: true, + imports: [MatExpansionPanel, MatExpansionPanelHeader, SelectedAnnotationsTableComponent], + templateUrl: './warning-details-panel.component.html', + styleUrl: './warning-details-panel.component.scss', +}) +export class WarningDetailsPanelComponent { + readonly #translateService = inject(TranslateService); + readonly warnings = input(); + readonly filename = input(); + readonly openByDefault = input(); + readonly tableColumns = computed(() => [ + { label: 'Value' }, + { label: 'Type' }, + { label: 'Page' }, + { label: 'Warning Reason' }, + ]); + readonly tableData = computed(() => + this.warnings().map(warning => [ + { label: warning.value, bold: true }, + { label: warning.type }, + { label: warning.pages.join(',') }, + { label: this.#translateService.instant(approvalWarningReasonTranslations[warning.warningType]) }, + ]), + ); +} diff --git a/apps/red-ui/src/app/services/files/files.service.ts b/apps/red-ui/src/app/services/files/files.service.ts index ae2857d51..59db98b39 100644 --- a/apps/red-ui/src/app/services/files/files.service.ts +++ b/apps/red-ui/src/app/services/files/files.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { EntitiesService, isArray, QueryParam } from '@iqser/common-ui'; import { List, mapEach } from '@iqser/common-ui/lib/utils'; -import { File, IFile } from '@red/domain'; +import { ApproveResponse, File, IFile } from '@red/domain'; import { UserService } from '@users/user.service'; import { NGXLogger } from 'ngx-logger'; import { firstValueFrom } from 'rxjs'; @@ -70,7 +70,13 @@ export class FilesService extends EntitiesService { async setApproved(files: File | List) { const _files = asList(files); - return this.#makePost(_files, `${this._defaultModelPath}/approved/${_files[0].dossierId}/bulk`); + return this.#makePost(_files, `${this._defaultModelPath}/approved/${_files[0].dossierId}/bulk`, [{ key: 'force', value: true }]); + } + + async getApproveWarnings(files: File[]) { + const filesIds = files.map(file => file.id); + const url = `${this._defaultModelPath}/approved/${files[0].dossierId}/bulk`; + return await firstValueFrom(this._post(filesIds, url)); } async setUnderReview(files: File | List) { diff --git a/apps/red-ui/src/app/translations/approval-warning-reason-translations.ts b/apps/red-ui/src/app/translations/approval-warning-reason-translations.ts new file mode 100644 index 000000000..8a7265dcf --- /dev/null +++ b/apps/red-ui/src/app/translations/approval-warning-reason-translations.ts @@ -0,0 +1,8 @@ +import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; +import { WarningType } from '@red/domain'; + +export const approvalWarningReasonTranslations: Record = { + [WarningType.PENDING_CHANGE]: _('confirmation-dialog.approve-file.warning-reason.pending-changes'), + [WarningType.LEGAL_BASIS_MISSING]: _('confirmation-dialog.approve-file.warning-reason.legal-basis-missing'), + [WarningType.UNMAPPED_JUSTIFICATION]: _('confirmation-dialog.approve-file.warning-reason.unmapped-justification'), +}; diff --git a/apps/red-ui/src/assets/i18n/redact/de.json b/apps/red-ui/src/assets/i18n/redact/de.json index ea6e33f05..daf9660b7 100644 --- a/apps/red-ui/src/assets/i18n/redact/de.json +++ b/apps/red-ui/src/assets/i18n/redact/de.json @@ -638,25 +638,16 @@ "warning": "Warnung: Wiederherstellung des Benutzers nicht möglich." }, "confirmation-dialog": { - "approve-file-without-analysis": { - "confirmationText": "Ohne Analyse freigeben", - "denyText": "Abbrechen", - "question": "Analyse zur Erkennung neuer Schwärzungen erforderlich.", - "title": "Warnung!" - }, "approve-file": { - "question": "Dieses Dokument enthält ungesehene Änderungen, die sich durch die Reanalyse ergeben haben.

Möchten Sie es trotzdem freigeben?", - "title": "Warnung!" - }, - "approve-multiple-files-without-analysis": { - "confirmationText": "Ohne Analyse freigeben", - "denyText": "Abbrechen", - "question": "Für mindestens eine Datei ist ein Analyselauf zur Erkennung neuer Schwärzungen erforderlich.", - "title": "Warnung" - }, - "approve-multiple-files": { - "question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen, die im Zuge einer Reanalyse hinzugefügt wurden.

Möchen Sie die Dateien wirklich freigeben?", - "title": "Warnung!" + "confirmationText": "Approve anyway", + "denyText": "No, cancel", + "question": "Do you still want to approve the {questionLength, plural, one{document} other{documents}}?", + "title": "Approval warning", + "warning-reason": { + "legal-basis-missing": "Legal basis missing", + "pending-changes": "Pending Changes", + "unmapped-justification": "Unmapped justification" + } }, "assign-file-to-me": { "question": { diff --git a/apps/red-ui/src/assets/i18n/redact/en.json b/apps/red-ui/src/assets/i18n/redact/en.json index 1208b8d24..206af55b0 100644 --- a/apps/red-ui/src/assets/i18n/redact/en.json +++ b/apps/red-ui/src/assets/i18n/redact/en.json @@ -638,25 +638,16 @@ "warning": "Warning: This action cannot be undone!" }, "confirmation-dialog": { - "approve-file-without-analysis": { - "confirmationText": "Approve without analysis", - "denyText": "Cancel", - "question": "Analysis required to detect new redactions.", - "title": "Warning!" - }, "approve-file": { - "question": "This document contains unseen changes that have been added during the reanalysis.

Do you still want to approve it?", - "title": "Warning!" - }, - "approve-multiple-files-without-analysis": { - "confirmationText": "Approve without analysis", - "denyText": "Cancel", - "question": "Analysis required to detect new redactions for at least one file.", - "title": "Warning" - }, - "approve-multiple-files": { - "question": "At least one of the selected files contains unseen changes that have been added during the reanalysis.

Do you still want to approve them?", - "title": "Warning!" + "confirmationText": "Approve anyway", + "denyText": "No, cancel", + "question": "Do you still want to approve the {questionLength, plural, one{document} other{documents}}?", + "title": "Approval warning", + "warning-reason": { + "legal-basis-missing": "Legal basis missing", + "pending-changes": "Pending Changes", + "unmapped-justification": "Unmapped justification" + } }, "assign-file-to-me": { "question": { diff --git a/apps/red-ui/src/assets/i18n/scm/de.json b/apps/red-ui/src/assets/i18n/scm/de.json index ab563171b..701683e42 100644 --- a/apps/red-ui/src/assets/i18n/scm/de.json +++ b/apps/red-ui/src/assets/i18n/scm/de.json @@ -638,25 +638,16 @@ "warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!" }, "confirmation-dialog": { - "approve-file-without-analysis": { - "confirmationText": "Approve without analysis", - "denyText": "Cancel", - "question": "Analysis required to detect new components.", - "title": "Warning!" - }, "approve-file": { - "question": "Dieses Dokument enthält ungesehene Änderungen. Möchten Sie es trotzdem genehmigen?", - "title": "Warnung!" - }, - "approve-multiple-files-without-analysis": { - "confirmationText": "Approve without analysis", - "denyText": "Cancel", - "question": "Analysis required to detect new components for at least one file.", - "title": "Warning" - }, - "approve-multiple-files": { - "question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen. Möchten Sie sie trotzdem genehmigen?", - "title": "Warnung!" + "confirmationText": "Approve anyway", + "denyText": "No, cancel", + "question": "Do you still want to approve the {questionLength, plural, one{document} other{documents}}?", + "title": "Approval warning", + "warning-reason": { + "legal-basis-missing": "Legal basis missing", + "pending-changes": "Pending Changes", + "unmapped-justification": "Unmapped justification" + } }, "assign-file-to-me": { "question": { diff --git a/apps/red-ui/src/assets/i18n/scm/en.json b/apps/red-ui/src/assets/i18n/scm/en.json index 89fcbd78c..a8d077d68 100644 --- a/apps/red-ui/src/assets/i18n/scm/en.json +++ b/apps/red-ui/src/assets/i18n/scm/en.json @@ -638,25 +638,16 @@ "warning": "Warning: this cannot be undone!" }, "confirmation-dialog": { - "approve-file-without-analysis": { - "confirmationText": "Approve without analysis", - "denyText": "Cancel", - "question": "Analysis required to detect new components.", - "title": "Warning!" - }, "approve-file": { - "question": "This document has unseen changes, do you wish to approve it anyway?", - "title": "Warning!" - }, - "approve-multiple-files-without-analysis": { - "confirmationText": "Approve without analysis", - "denyText": "Cancel", - "question": "Analysis required to detect new components for at least one file.", - "title": "Warning" - }, - "approve-multiple-files": { - "question": "At least one of the files you selected has unseen changes, do you wish to approve them anyway?", - "title": "Warning!" + "confirmationText": "Approve anyway", + "denyText": "No, cancel", + "question": "Do you still want to approve the {questionLength, plural, one{document} other{documents}}?", + "title": "Approval warning", + "warning-reason": { + "legal-basis-missing": "Legal basis missing", + "pending-changes": "Pending Changes", + "unmapped-justification": "Unmapped justification" + } }, "assign-file-to-me": { "question": { diff --git a/libs/red-domain/src/lib/files/approve-file-types.ts b/libs/red-domain/src/lib/files/approve-file-types.ts new file mode 100644 index 000000000..60da462d6 --- /dev/null +++ b/libs/red-domain/src/lib/files/approve-file-types.ts @@ -0,0 +1,19 @@ +export interface ApproveResponse { + readonly fileId: string; + readonly hasWarnings?: boolean; + readonly fileWarnings: WarningModel[]; +} + +export interface WarningModel { + id: string; + value: string; + pages: number[]; + type: string; + warningType: WarningType; +} + +export enum WarningType { + PENDING_CHANGE = 'PENDING_CHANGE', + LEGAL_BASIS_MISSING = 'LEGAL_BASIS_MISSING', + UNMAPPED_JUSTIFICATION = 'UNMAPPED_JUSTIFICATION', +} diff --git a/libs/red-domain/src/lib/files/index.ts b/libs/red-domain/src/lib/files/index.ts index c238e8dff..a821aefd0 100644 --- a/libs/red-domain/src/lib/files/index.ts +++ b/libs/red-domain/src/lib/files/index.ts @@ -4,3 +4,4 @@ export * from './types'; export * from './file-upload-result'; export * from './overwrite-file-options'; export * from './super-types'; +export * from './approve-file-types';
+
+
{{ cell.label }}