Merge branch 'master' into VM/RED-7345

This commit is contained in:
Valentin Mihai 2024-09-23 11:12:25 +03:00
commit 1b9128a68f
27 changed files with 258 additions and 181 deletions

View File

@ -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"
></iqser-circle-button>
</div>
@ -46,6 +47,7 @@
<iqser-circle-button
(action)="download(template)"
*allow="roles.reportTemplates.download"
[buttonId]="(template.fileName | snakeCase) + '-download-button'"
[iconSize]="12"
[size]="18"
icon="iqser:download"
@ -54,6 +56,7 @@
<iqser-circle-button
(action)="deleteTemplate(template)"
*allow="roles.reportTemplates.delete; if: currentUser.isAdmin"
[buttonId]="(template.fileName | snakeCase) + '-delete-button'"
[iconSize]="12"
[size]="18"
icon="iqser:trash"

View File

@ -25,6 +25,7 @@ import { getCurrentUser } from '@iqser/common-ui/lib/users';
import { getParam } from '@iqser/common-ui/lib/utils';
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { SnakeCasePipe } from '@common-ui/pipes/snake-case.pipe';
interface Placeholder {
placeholder: string;
@ -41,7 +42,7 @@ const placeholderTypes: PlaceholderType[] = ['generalPlaceholders', 'fileAttribu
styleUrls: ['./reports-screen.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [HasScrollbarDirective, NgIf, NgForOf, AsyncPipe, TranslateModule, CircleButtonComponent, IqserAllowDirective],
imports: [HasScrollbarDirective, NgIf, NgForOf, AsyncPipe, TranslateModule, CircleButtonComponent, IqserAllowDirective, SnakeCasePipe],
})
export default class ReportsScreenComponent implements OnInit {
@ViewChild('fileInput') private readonly _fileInput: ElementRef;

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { Injectable, signal } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { IConfirmationDialogData, IqserDialog, LoadingService } from '@iqser/common-ui';
import { Dossier, File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
import { ApproveResponse, Dossier, File, User, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { FileManagementService } from '@services/files/file-management.service';
import { FilesService } from '@services/files/files.service';
@ -11,6 +11,7 @@ import { AssignReviewerApproverDialogComponent } from '../../shared-dossiers/dia
import { DossiersDialogService } from '../../shared-dossiers/services/dossiers-dialog.service';
import { FileAssignService } from '../../shared-dossiers/services/file-assign.service';
import { getCurrentUser } from '@common-ui/users';
import { ApproveWarningDetailsComponent } from '@shared/components/approve-warning-details/approve-warning-details.component';
@Injectable()
export class BulkActionsService {
@ -110,34 +111,33 @@ export class BulkActionsService {
}
async approve(files: File[]): Promise<void> {
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 {

View File

@ -32,7 +32,7 @@
<div cdkDrag class="editing-value">
<mat-icon
[class.hidden-button]="currentEntry().componentValues.length === 1"
[attr.help-mode-key]="'change_component_order'"
[attr.help-mode-key]="currentEntry().componentValues.length > 1 ? 'change_component_order' : null"
cdkDragHandle
class="draggable"
svgIcon="red:draggable-dots"
@ -44,7 +44,7 @@
(action)="removeValue($index)"
[tooltip]="'component-management.actions.delete' | translate"
[class.hidden-button]="currentEntry().componentValues.length === 1"
[attr.help-mode-key]="'remove_component_value'"
[attr.help-mode-key]="currentEntry().componentValues.length > 1 ? 'remove_component_value' : null"
class="remove-value"
icon="iqser:trash"
></iqser-circle-button>

View File

@ -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)),

View File

@ -1,14 +1,17 @@
<table>
<thead>
<tr>
<th *ngFor="let column of columns" [ngClass]="{ hide: !column.show, 'w-50': staticColumns }">
<th *ngFor="let column of columns()" [ngClass]="{ hide: !!column.hide, 'w-50': staticColumns() && shouldApplyHalfWidth() }">
<label>{{ column.label }}</label>
</th>
</tr>
</thead>
<tbody [ngStyle]="{ height: redactedTextsAreaHeight + 'px' }">
<tr *ngFor="let row of data">
<td *ngFor="let cell of row" [ngClass]="{ hide: !cell.show, bold: cell.bold, 'w-50': staticColumns }">
<tbody [ngStyle]="{ height: redactedTextsAreaHeight() + 'px' }">
<tr *ngFor="let row of data()">
<td
*ngFor="let cell of row"
[ngClass]="{ hide: !!cell.hide, bold: cell.bold, 'w-50': staticColumns() && shouldApplyHalfWidth() }"
>
{{ cell.label }}
</td>
</tr>

View File

@ -27,7 +27,7 @@ table {
th,
td {
&:not(.w-50) {
&:first-child:not(.w-50) {
width: 25%;
}
max-width: 0;

View File

@ -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<ValueColumn[]>();
readonly data = input.required<ValueColumn[][]>();
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);
}

View File

@ -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<RedactOrHintOption>[] | undefined;
legalOptions: LegalBasisOption[] = [];

View File

@ -67,19 +67,10 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
readonly isDocumine = getConfig().IS_DOCUMINE;
readonly options: DetailsRadioOption<ForceAnnotationOption>[];
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[] = [];

View File

@ -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(

View File

@ -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<ValueColumn[]>(() => [
{
label: 'Value',
show: true,
},
{
label: 'Type',
show: true,
},
{ label: 'Value' },
{ label: 'Type' },
{
label: 'Context',
show: this.isFalsePositive(),
hide: !this.isFalsePositive(),
},
]);
readonly tableData = computed<ValueColumn[][]>(() =>
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() },
]),
);

View File

@ -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());

View File

@ -0,0 +1,9 @@
<div class="scrollable">
@for (file of data(); track file) {
<redaction-warning-details-panel
[warnings]="file.fileWarnings"
[filename]="fileNamesByIds()[file.fileId]"
[openByDefault]="shouldPanelOpenDefault()"
></redaction-warning-details-panel>
}
</div>

View File

@ -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;
}

View File

@ -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<ApproveResponse[]>();
readonly files = input.required<File[]>();
readonly fileNamesByIds = computed(() => this.files().reduce((acc, file) => ({ ...acc, [file.id]: file.filename }), {}));
readonly shouldPanelOpenDefault = computed(() => this.files().length === 1);
}

View File

@ -0,0 +1,8 @@
<mat-expansion-panel [expanded]="openByDefault()" togglePosition="before">
<mat-expansion-panel-header>{{ filename() }}</mat-expansion-panel-header>
<redaction-selected-annotations-table
[columns]="tableColumns()"
[data]="tableData()"
[staticColumns]="true"
></redaction-selected-annotations-table>
</mat-expansion-panel>

View File

@ -0,0 +1,4 @@
mat-expansion-panel {
margin-bottom: 8px;
max-width: 100%;
}

View File

@ -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<WarningModel[]>();
readonly filename = input<string>();
readonly openByDefault = input<boolean>();
readonly tableColumns = computed<ValueColumn[]>(() => [
{ label: 'Value' },
{ label: 'Type' },
{ label: 'Page' },
{ label: 'Warning Reason' },
]);
readonly tableData = computed<ValueColumn[][]>(() =>
this.warnings().map(warning => [
{ label: warning.value, bold: true },
{ label: warning.type },
{ label: warning.pages.join(',') },
{ label: this.#translateService.instant(approvalWarningReasonTranslations[warning.warningType]) },
]),
);
}

View File

@ -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<IFile, File> {
async setApproved(files: File | List<File>) {
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<ApproveResponse[]>(this._post(filesIds, url));
}
async setUnderReview(files: File | List<File>) {

View File

@ -0,0 +1,8 @@
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { WarningType } from '@red/domain';
export const approvalWarningReasonTranslations: Record<string, string> = {
[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'),
};

View File

@ -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.<br><br>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.<br><br>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": {

View File

@ -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.<br><br>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.<br><br>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": {

View File

@ -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": {

View File

@ -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": {

View File

@ -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',
}

View File

@ -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';