Compare commits
49 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b7ad118d4 | ||
|
|
c977f95f1e | ||
|
|
1da7b41692 | ||
|
|
6100c59a87 | ||
|
|
860146cd1a | ||
|
|
0b8a0f08d2 | ||
|
|
e167e94171 | ||
|
|
315bd225af | ||
|
|
6a9f440b8a | ||
|
|
0ba173b4b9 | ||
|
|
6d74ab60cc | ||
|
|
1f36b0be04 | ||
|
|
40d6718e8e | ||
|
|
cc22fdf538 | ||
|
|
4c6bb84567 | ||
|
|
41a3dce600 | ||
|
|
53cfc669d6 | ||
|
|
540649edbd | ||
|
|
32369d7121 | ||
|
|
a9a935b90d | ||
|
|
491977cb49 | ||
|
|
b620605613 | ||
|
|
a28f5fd727 | ||
|
|
2e2eaf476d | ||
|
|
b0d38e1b0f | ||
|
|
d4991f6806 | ||
|
|
9d18113f56 | ||
|
|
d04f1b7b0b | ||
|
|
b1948622fe | ||
|
|
eb4368c3ce | ||
|
|
9772145239 | ||
|
|
183b19c9da | ||
|
|
4c9b487c78 | ||
|
|
ba311ad8e3 | ||
|
|
62d4d18eaa | ||
|
|
7f8dca3098 | ||
|
|
289ee7f61d | ||
|
|
bf1f25c0dd | ||
|
|
773f2bfe9f | ||
|
|
ac1780ade4 | ||
|
|
5f309bffe0 | ||
|
|
611f293e64 | ||
|
|
bc7919551e | ||
|
|
4e3e64f2eb | ||
|
|
1233761ac3 | ||
|
|
fd3b99a785 | ||
|
|
f9361a2e82 | ||
|
|
4acb4d4eb7 | ||
|
|
7d4d2889da |
@ -22,7 +22,7 @@
|
||||
}
|
||||
|
||||
.mat-mdc-menu-item.notification {
|
||||
padding: 8px 26px 10px 8px;
|
||||
padding: 8px 26px 10px 8px !important;
|
||||
margin: 2px 0 0 0;
|
||||
height: fit-content;
|
||||
position: relative;
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
<div class="mt-44">
|
||||
<redaction-donut-chart
|
||||
[config]="chartConfig"
|
||||
[config]="chartConfig()"
|
||||
[radius]="63"
|
||||
[strokeWidth]="15"
|
||||
[subtitles]="['user-stats.chart.users' | translate]"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, input, Input, output, Output } from '@angular/core';
|
||||
import { DonutChartConfig } from '@red/domain';
|
||||
import { CircleButtonComponent } from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@ -12,6 +12,6 @@ import { DonutChartComponent } from '@shared/components/donut-chart/donut-chart.
|
||||
imports: [CircleButtonComponent, TranslateModule, DonutChartComponent],
|
||||
})
|
||||
export class UsersStatsComponent {
|
||||
@Output() toggleCollapse = new EventEmitter();
|
||||
@Input() chartConfig: DonutChartConfig[];
|
||||
readonly chartConfig = input.required<DonutChartConfig[]>();
|
||||
readonly toggleCollapse = output();
|
||||
}
|
||||
|
||||
@ -101,11 +101,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnInit {
|
||||
this.closeDialog.emit(true);
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.status === HttpStatusCode.Conflict) {
|
||||
this._toaster.error(_('add-edit-user.error.email-already-used'));
|
||||
} else {
|
||||
this._toaster.error(_('add-edit-user.error.generic'));
|
||||
}
|
||||
this._toaster.error(null, { error });
|
||||
this._loadingService.stop();
|
||||
});
|
||||
} else {
|
||||
|
||||
@ -17,7 +17,7 @@ import { RouterHistoryService } from '@services/router-history.service';
|
||||
import { auditCategoriesTranslations } from '@translations/audit-categories-translations';
|
||||
import { Roles } from '@users/roles';
|
||||
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
|
||||
import { Dayjs } from 'dayjs';
|
||||
import dayjs, { Dayjs } from 'dayjs';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { AuditService } from '../../services/audit.service';
|
||||
@ -139,16 +139,9 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnI
|
||||
const promises = [];
|
||||
const category = this.form.get('category').value;
|
||||
const userId = this.form.get('userId').value;
|
||||
const from = this.form.get('from').value;
|
||||
let to = this.form.get('to').value;
|
||||
if (to) {
|
||||
const hoursLeft = new Date(to).getHours();
|
||||
const minutesLeft = new Date(to).getMinutes();
|
||||
to = to
|
||||
.clone()
|
||||
.add(24 - hoursLeft - 1, 'h')
|
||||
.add(60 - minutesLeft - 1);
|
||||
}
|
||||
const from = this.form.get('from').value ? dayjs(this.form.get('from').value).startOf('day').toISOString() : null;
|
||||
const to = this.form.get('to').value ? dayjs(this.form.get('to').value).endOf('day').toISOString() : null;
|
||||
|
||||
const logsRequestBody: IAuditSearchRequest = {
|
||||
pageSize: PAGE_SIZE,
|
||||
page: page,
|
||||
|
||||
@ -42,6 +42,15 @@
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div class="iqser-input-group required w-150">
|
||||
<label translate="add-edit-component-mapping.form.quote-char"></label>
|
||||
<input
|
||||
[placeholder]="'add-edit-component-mapping.form.quote-char-placeholder' | translate"
|
||||
formControlName="quoteChar"
|
||||
name="quoteChar"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group required w-150">
|
||||
<label translate="add-edit-component-mapping.form.encoding-type"></label>
|
||||
|
||||
@ -17,12 +17,14 @@ interface DialogData {
|
||||
dossierTemplateId: string;
|
||||
mapping: IComponentMapping;
|
||||
}
|
||||
|
||||
interface DialogResult {
|
||||
id: string;
|
||||
name: string;
|
||||
file: Blob;
|
||||
encoding: string;
|
||||
delimiter: string;
|
||||
quoteChar: string;
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
@ -72,14 +74,14 @@ export class AddEditComponentMappingDialogComponent
|
||||
const file = new Blob([fileContent.body as Blob], { type: 'text/csv' });
|
||||
this.form.get('file').setValue(file);
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
this.#disableEncodingAndDelimiter();
|
||||
this.#disableEncodingAndQuoteCharAndDelimiter();
|
||||
}
|
||||
}
|
||||
|
||||
changeFile(file: File) {
|
||||
this.form.get('file').setValue(file);
|
||||
this.form.get('fileName').setValue(file?.name);
|
||||
this.#enableEncodingAndDelimiter();
|
||||
this.#enableEncodingAndQuoteCharAndDelimiter();
|
||||
}
|
||||
|
||||
save() {
|
||||
@ -93,16 +95,19 @@ export class AddEditComponentMappingDialogComponent
|
||||
fileName: [this.data?.mapping?.fileName, Validators.required],
|
||||
encoding: this.encodingTypeOptions.find(e => e === this.data?.mapping?.encoding) ?? this.encodingTypeOptions[0],
|
||||
delimiter: [this.data?.mapping?.delimiter ?? ',', Validators.required],
|
||||
quoteChar: [this.data?.mapping?.quoteChar ?? '"', Validators.required],
|
||||
});
|
||||
}
|
||||
|
||||
#disableEncodingAndDelimiter() {
|
||||
#disableEncodingAndQuoteCharAndDelimiter() {
|
||||
this.form.get('encoding').disable();
|
||||
this.form.get('delimiter').disable();
|
||||
this.form.get('quoteChar').disable();
|
||||
}
|
||||
|
||||
#enableEncodingAndDelimiter() {
|
||||
#enableEncodingAndQuoteCharAndDelimiter() {
|
||||
this.form.get('encoding').enable();
|
||||
this.form.get('delimiter').enable();
|
||||
this.form.get('quoteChar').enable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,8 +99,8 @@ export default class ComponentMappingsScreenComponent extends ListingComponent<C
|
||||
const result = await dialog.result();
|
||||
if (result) {
|
||||
this._loadingService.start();
|
||||
const { id, name, encoding, delimiter, fileName } = result;
|
||||
const newMapping = { id, name, encoding, delimiter, fileName };
|
||||
const { id, name, encoding, delimiter, fileName, quoteChar } = result;
|
||||
const newMapping = { id, name, encoding, delimiter, fileName, quoteChar };
|
||||
await firstValueFrom(
|
||||
this._componentMappingService.createUpdateComponentMapping(this.#dossierTemplateId, newMapping, result.file),
|
||||
);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<div class="dialog-header">
|
||||
<div class="heading-l" translate="general-config-screen.general.title"></div>
|
||||
<div translate="general-config-screen.general.subtitle"></div>
|
||||
</div>
|
||||
<form (submit)="save()" *ngIf="form" [formGroup]="form">
|
||||
<div class="dialog-content">
|
||||
|
||||
@ -17,8 +17,17 @@
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<label translate="add-edit-entity.form.technical-name"></label>
|
||||
<div class="technical-name">{{ this.technicalName() || '-' }}</div>
|
||||
<span
|
||||
[translateParams]="{ type: data.justification ? 'edit' : 'create' }"
|
||||
[translate]="'add-edit-entity.form.technical-name-hint'"
|
||||
class="hint"
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group required w-400">
|
||||
<div class="iqser-input-group w-400">
|
||||
<label translate="add-edit-justification.form.reason"></label>
|
||||
<input
|
||||
[placeholder]="'add-edit-justification.form.reason-placeholder' | translate"
|
||||
@ -28,7 +37,7 @@
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group required w-400">
|
||||
<div class="iqser-input-group w-400">
|
||||
<label translate="add-edit-justification.form.description"></label>
|
||||
<textarea
|
||||
[placeholder]="'add-edit-justification.form.description-placeholder' | translate"
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, computed, Inject, untracked } from '@angular/core';
|
||||
import { ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Justification } from '@red/domain';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { BaseDialogComponent, CircleButtonComponent, IconButtonComponent } from '@iqser/common-ui';
|
||||
import { BaseDialogComponent, CircleButtonComponent, HasScrollbarDirective, IconButtonComponent } from '@iqser/common-ui';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { formControlToSignal } from '@utils/functions';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
|
||||
interface DialogData {
|
||||
justification?: Justification;
|
||||
@ -16,9 +18,29 @@ interface DialogData {
|
||||
templateUrl: './add-edit-justification-dialog.component.html',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [TranslateModule, ReactiveFormsModule, IconButtonComponent, CircleButtonComponent],
|
||||
imports: [TranslateModule, ReactiveFormsModule, IconButtonComponent, CircleButtonComponent, HasScrollbarDirective],
|
||||
})
|
||||
export class AddEditJustificationDialogComponent extends BaseDialogComponent {
|
||||
readonly form = this.#getForm();
|
||||
readonly name = formControlToSignal(this.form.controls['name']);
|
||||
readonly allJustifications = toSignal(this._justificationService.all$);
|
||||
readonly technicalName = computed(() => {
|
||||
if (this.data.justification) {
|
||||
return this.data.justification.technicalName;
|
||||
}
|
||||
if (!this.name()) {
|
||||
return null;
|
||||
}
|
||||
let currentTechnicalName = Justification.toTechnicalName(this.name());
|
||||
const existingTechnicalNames = untracked(this.allJustifications).map(justification => justification.technicalName);
|
||||
let suffix = 1;
|
||||
while (existingTechnicalNames.includes(currentTechnicalName)) {
|
||||
currentTechnicalName =
|
||||
currentTechnicalName === '_' ? `${currentTechnicalName}${suffix++}` : [currentTechnicalName, suffix++].join('_');
|
||||
}
|
||||
return currentTechnicalName;
|
||||
});
|
||||
|
||||
constructor(
|
||||
private readonly _justificationService: JustificationsService,
|
||||
protected readonly _dialogRef: MatDialogRef<AddEditJustificationDialogComponent>,
|
||||
@ -26,7 +48,6 @@ export class AddEditJustificationDialogComponent extends BaseDialogComponent {
|
||||
) {
|
||||
super(_dialogRef, !!data.justification);
|
||||
|
||||
this.form = this._getForm();
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
}
|
||||
|
||||
@ -34,7 +55,8 @@ export class AddEditJustificationDialogComponent extends BaseDialogComponent {
|
||||
const dossierTemplateId = this.data.dossierTemplateId;
|
||||
this._loadingService.start();
|
||||
try {
|
||||
await firstValueFrom(this._justificationService.createOrUpdate(this.form.getRawValue() as Justification, dossierTemplateId));
|
||||
const formValue = { ...this.form.getRawValue(), technicalName: this.technicalName() };
|
||||
await firstValueFrom(this._justificationService.createOrUpdate(formValue as Justification, dossierTemplateId));
|
||||
await firstValueFrom(this._justificationService.loadAll(dossierTemplateId));
|
||||
this._dialogRef.close(true);
|
||||
} catch (error) {
|
||||
@ -43,11 +65,12 @@ export class AddEditJustificationDialogComponent extends BaseDialogComponent {
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
private _getForm(): UntypedFormGroup {
|
||||
#getForm(): UntypedFormGroup {
|
||||
return this._formBuilder.group({
|
||||
name: [{ value: this.data.justification?.name, disabled: !!this.data.justification }, Validators.required],
|
||||
reason: [this.data.justification?.reason, Validators.required],
|
||||
description: [this.data.justification?.description, Validators.required],
|
||||
reason: [this.data.justification?.reason],
|
||||
description: [this.data.justification?.description],
|
||||
technicalName: [this.data.justification?.technicalName ?? null],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,9 +78,9 @@ export class LicenseRetentionCapacityComponent {
|
||||
|
||||
return [
|
||||
{
|
||||
data: monthlyData.flatMap(d => d.activeFilesUploadedBytes),
|
||||
label: this._translateService.instant('license-info-screen.retention-capacity-usage.active-documents'),
|
||||
...getLineConfig(ChartGreen, false, 'origin'),
|
||||
data: monthlyData.flatMap(d => d.trashFilesUploadedBytes),
|
||||
label: this._translateService.instant('license-info-screen.retention-capacity-usage.trash-documents'),
|
||||
...getLineConfig(ChartRed, false, 'origin'),
|
||||
stack: 'storage',
|
||||
},
|
||||
{
|
||||
@ -90,9 +90,9 @@ export class LicenseRetentionCapacityComponent {
|
||||
stack: 'storage',
|
||||
},
|
||||
{
|
||||
data: monthlyData.flatMap(d => d.trashFilesUploadedBytes),
|
||||
label: this._translateService.instant('license-info-screen.retention-capacity-usage.trash-documents'),
|
||||
...getLineConfig(ChartRed, false, '-1'),
|
||||
data: monthlyData.flatMap(d => d.activeFilesUploadedBytes),
|
||||
label: this._translateService.instant('license-info-screen.retention-capacity-usage.active-documents'),
|
||||
...getLineConfig(ChartGreen, false, 'origin'),
|
||||
stack: 'storage',
|
||||
},
|
||||
{
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<mat-icon *ngIf="!fileAttribute.editable" [matTooltip]="'readonly' | translate" svgIcon="red:read-only"></mat-icon>
|
||||
<span
|
||||
*ngIf="!isDate; else date"
|
||||
[style.max-width]="attributeValueWidth"
|
||||
[style.max-width]="attributeValueWidth()"
|
||||
[matTooltip]="fileAttributeValue"
|
||||
[ngClass]="{ hide: isInEditMode, 'clamp-3': mode !== 'workflow' }"
|
||||
>
|
||||
@ -56,13 +56,12 @@
|
||||
class="edit-input"
|
||||
iqserStopPropagation
|
||||
>
|
||||
<form [formGroup]="form">
|
||||
<form [formGroup]="form" [style.width]="inputFormWidth()">
|
||||
<iqser-dynamic-input
|
||||
(closedDatepicker)="closedDatepicker = $event"
|
||||
(keyup.enter)="form.valid && save()"
|
||||
(keydown.escape)="close()"
|
||||
[style.max-width]="editFieldWidth"
|
||||
[style.min-width]="editFieldWidth"
|
||||
[style.width]="inputFieldWidth()"
|
||||
[formControlName]="fileAttribute.id"
|
||||
[id]="fileAttribute.id"
|
||||
[ngClass]="{ 'workflow-input': mode === 'workflow' || fileNameColumn, 'file-name-input': fileNameColumn }"
|
||||
|
||||
@ -97,7 +97,7 @@
|
||||
iqser-circle-button {
|
||||
margin-left: 15px;
|
||||
|
||||
@media screen and (max-width: 1395px) {
|
||||
@media screen and (max-width: 1745px) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { AsyncPipe, NgClass, NgIf, NgTemplateOutlet } from '@angular/common';
|
||||
import { Component, computed, effect, HostListener, Input, OnDestroy } from '@angular/core';
|
||||
import { Component, computed, effect, HostListener, input, Input, OnDestroy } from '@angular/core';
|
||||
import { AbstractControl, FormBuilder, FormsModule, ReactiveFormsModule, UntypedFormGroup, ValidatorFn } from '@angular/forms';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
@ -14,7 +14,7 @@ import {
|
||||
StopPropagationDirective,
|
||||
Toaster,
|
||||
} from '@iqser/common-ui';
|
||||
import { Debounce, log } from '@iqser/common-ui/lib/utils';
|
||||
import { Debounce } from '@iqser/common-ui/lib/utils';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
@ -49,7 +49,6 @@ import { ConfigService } from '../../config.service';
|
||||
})
|
||||
export class FileAttributeComponent extends BaseFormComponent implements OnDestroy {
|
||||
readonly #subscriptions = new Subscription();
|
||||
#widthFactor = window.innerWidth >= 1800 ? 0.85 : 0.7;
|
||||
isInEditMode = false;
|
||||
closedDatepicker = true;
|
||||
@Input({ required: true }) fileAttribute!: IFileAttributeConfig;
|
||||
@ -66,7 +65,10 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
||||
@Input({ required: true }) dossier!: Dossier;
|
||||
@Input() fileNameColumn = false;
|
||||
readonlyAttrs: string[] = [];
|
||||
@Input() width?: number;
|
||||
readonly width = input<number>();
|
||||
readonly inputFormWidth = computed(() => (this.width() ? this.width() + 'px' : 'unset'));
|
||||
readonly inputFieldWidth = computed(() => (this.width() ? this.width() - 50 + 'px' : 'unset'));
|
||||
readonly attributeValueWidth = computed(() => (this.width() ? `${this.width() * 0.9}px` : 'unset'));
|
||||
|
||||
constructor(
|
||||
router: Router,
|
||||
@ -99,14 +101,6 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
||||
);
|
||||
}
|
||||
|
||||
get editFieldWidth(): string {
|
||||
return this.width ? `${this.width * this.#widthFactor}px` : 'unset';
|
||||
}
|
||||
|
||||
get attributeValueWidth(): string {
|
||||
return this.width ? `${this.width * 0.9}px` : 'unset';
|
||||
}
|
||||
|
||||
get isDate(): boolean {
|
||||
return this.fileAttribute.type === FileAttributeConfigTypes.DATE;
|
||||
}
|
||||
@ -123,15 +117,6 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
||||
return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id];
|
||||
}
|
||||
|
||||
@HostListener('window:resize')
|
||||
onResize() {
|
||||
if (window.innerWidth >= 1800) {
|
||||
this.#widthFactor = 0.85;
|
||||
} else {
|
||||
this.#widthFactor = 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
@Debounce(60)
|
||||
@HostListener('document:click', ['$event'])
|
||||
clickOutside($event: MouseEvent) {
|
||||
@ -147,6 +132,7 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
||||
|
||||
handleClick($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
$event.preventDefault();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -154,12 +140,14 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
||||
}
|
||||
|
||||
handleFieldClick($event: MouseEvent) {
|
||||
$event.preventDefault();
|
||||
if (!this.fileNameColumn) {
|
||||
this.editFileAttribute($event);
|
||||
}
|
||||
}
|
||||
|
||||
editFileAttribute($event: MouseEvent) {
|
||||
$event.preventDefault();
|
||||
if (
|
||||
!this.file.isInitialProcessing &&
|
||||
this.permissionsService.canEditFileAttributes(this.file, this.dossier) &&
|
||||
|
||||
@ -2,18 +2,33 @@
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.analysisRequired"
|
||||
[color]="analysisColor$ | async"
|
||||
label="A"
|
||||
[label]="(workloadTranslations['analysis'] | translate)[0]"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="updated"
|
||||
[color]="updatedColor$ | async"
|
||||
[label]="(workloadTranslations['updated'] | translate)[0]"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="updated" [color]="updatedColor$ | async" label="U" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.hasRedactions"
|
||||
[color]="redactionColor$ | async"
|
||||
[label]="'redaction-abbreviation' | translate"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hasImages" [color]="imageColor$ | async" label="I" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="file.hintsOnly" [color]="hintColor$ | async" label="H" type="circle"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.hasImages"
|
||||
[color]="imageColor$ | async"
|
||||
[label]="(workloadTranslations['image'] | translate)[0]"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="file.hintsOnly"
|
||||
[color]="hintColor$ | async"
|
||||
[label]="(workloadTranslations['hint'] | translate)[0]"
|
||||
type="circle"
|
||||
></redaction-annotation-icon>
|
||||
<mat-icon *ngIf="file.hasAnnotationComments" svgIcon="red:comment"></mat-icon>
|
||||
<ng-container *ngIf="noWorkloadItems"> -</ng-container>
|
||||
</div>
|
||||
|
||||
@ -10,6 +10,7 @@ import { AnnotationIconComponent } from '@shared/components/annotation-icon/anno
|
||||
import { AsyncPipe, NgIf } from '@angular/common';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { workloadTranslations } from '@translations/workload-translations';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-workload',
|
||||
@ -27,6 +28,7 @@ export class FileWorkloadComponent implements OnInit {
|
||||
analysisColor$: Observable<string>;
|
||||
hintColor$: Observable<string>;
|
||||
redactionColor$: Observable<string>;
|
||||
readonly workloadTranslations = workloadTranslations;
|
||||
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
|
||||
@ -588,4 +588,16 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
||||
this.displayedPages.every((value, index) => value === newDisplayedPages[index])
|
||||
);
|
||||
}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
clickInsideWorkloadView($event: MouseEvent) {
|
||||
$event?.stopPropagation();
|
||||
}
|
||||
|
||||
@HostListener('document: click')
|
||||
clickOutsideWorkloadView() {
|
||||
if (this.multiSelectService.active() && !this._dialog.openDialogs.length) {
|
||||
this.multiSelectService.deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
class="dialog-header heading-l"
|
||||
></div>
|
||||
|
||||
<div [class.fixed-height]="isRedacted && isImage" class="dialog-content redaction">
|
||||
<div [class.image-dialog]="isRedacted && isImage" [class.rectangle-dialog]="allRectangles" class="dialog-content redaction">
|
||||
<div *ngIf="!isImage && redactedTexts.length && !allRectangles" class="iqser-input-group">
|
||||
<redaction-selected-annotations-table
|
||||
[columns]="tableColumns"
|
||||
@ -90,7 +90,7 @@
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="allRectangles" class="iqser-input-group w-400">
|
||||
<div *ngIf="allRectangles" class="iqser-input-group w-450">
|
||||
<label [translate]="'change-legal-basis-dialog.content.classification'"></label>
|
||||
<input
|
||||
[placeholder]="'edit-redaction.dialog.content.unchanged' | translate"
|
||||
@ -107,7 +107,7 @@
|
||||
formControlName="comment"
|
||||
iqserHasScrollbar
|
||||
name="comment"
|
||||
rows="4"
|
||||
rows="3"
|
||||
type="text"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
@ -1,8 +1,16 @@
|
||||
.dialog-content {
|
||||
padding-top: 8px;
|
||||
|
||||
&.fixed-height {
|
||||
height: 386px;
|
||||
&.rectangle-dialog {
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
&.image-dialog {
|
||||
height: 346px;
|
||||
}
|
||||
|
||||
.rectangle-dialog,
|
||||
.image-dialog {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,11 +33,12 @@ import {
|
||||
LegalBasisOption,
|
||||
RectangleRedactOption,
|
||||
RectangleRedactOptions,
|
||||
RedactOrHintOptions,
|
||||
} 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';
|
||||
import { validatePageRange } from '../../utils/form-validators';
|
||||
import { parseRectanglePosition, parseSelectedPageNumbers } from '../../utils/enhance-manual-redaction-request.utils';
|
||||
import { parseRectanglePosition, parseSelectedPageNumbers, prefillPageRange } from '../../utils/enhance-manual-redaction-request.utils';
|
||||
|
||||
interface TypeSelectOptions {
|
||||
type: string;
|
||||
@ -88,7 +89,7 @@ export class EditRedactionDialogComponent
|
||||
{ label: redaction.value, bold: true },
|
||||
{ label: redaction.typeLabel },
|
||||
]);
|
||||
options = this.allRectangles ? getRectangleRedactOptions('edit') : getEditRedactionOptions();
|
||||
options = this.allRectangles ? getRectangleRedactOptions('edit') : getEditRedactionOptions(this.isHint);
|
||||
legalOptions: LegalBasisOption[] = [];
|
||||
dictionaries: Dictionary[] = [];
|
||||
typeSelectOptions: TypeSelectOptions[] = [];
|
||||
@ -103,6 +104,14 @@ export class EditRedactionDialogComponent
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
) {
|
||||
super();
|
||||
|
||||
if (this.allRectangles) {
|
||||
prefillPageRange(
|
||||
this.data.annotations[0],
|
||||
this.data.allFileAnnotations,
|
||||
this.options as DetailsRadioOption<RectangleRedactOption>[],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
get displayedDictionaryLabel() {
|
||||
@ -206,7 +215,7 @@ export class EditRedactionDialogComponent
|
||||
const initialReason: LegalBasisOption = this.initialFormValue.reason;
|
||||
const initialLegalBasis = initialReason?.legalBasis ?? '';
|
||||
const pageNumbers = parseSelectedPageNumbers(
|
||||
this.form.get('option').value.additionalInput?.value,
|
||||
this.form.get('option').value?.additionalInput?.value,
|
||||
this.data.file,
|
||||
this.data.annotations[0],
|
||||
);
|
||||
@ -218,7 +227,7 @@ export class EditRedactionDialogComponent
|
||||
comment: value.comment,
|
||||
type: value.type,
|
||||
value: this.allRectangles ? value.value : null,
|
||||
option: value.option.value,
|
||||
option: value.option?.value ?? RedactOrHintOptions.ONLY_HERE,
|
||||
position,
|
||||
pageNumbers,
|
||||
});
|
||||
@ -255,7 +264,10 @@ export class EditRedactionDialogComponent
|
||||
disabled: this.isImported,
|
||||
}),
|
||||
section: new FormControl<string>({ value: sameSection ? this.annotations[0].section : null, disabled: this.isImported }),
|
||||
option: new FormControl<DetailsRadioOption<EditRedactionOption | RectangleRedactOption>>(this.options[0], validatePageRange()),
|
||||
option: new FormControl<DetailsRadioOption<EditRedactionOption | RectangleRedactOption>>(
|
||||
this.options[0],
|
||||
validatePageRange(this.data.file.numberOfPages),
|
||||
),
|
||||
value: new FormControl<string>(this.allRectangles ? this.annotations[0].value : null),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import { Component, Inject, OnInit } from '@angular/core';
|
||||
import { ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import {
|
||||
BaseDialogComponent,
|
||||
CircleButtonComponent,
|
||||
getConfig,
|
||||
HasScrollbarDirective,
|
||||
HelpButtonComponent,
|
||||
IconButtonComponent,
|
||||
IqserDenyDirective,
|
||||
IqserDialogComponent,
|
||||
} from '@iqser/common-ui';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { Dossier, ILegalBasisChangeRequest } from '@red/domain';
|
||||
@ -21,20 +20,19 @@ import {
|
||||
ValueColumn,
|
||||
} from '../../components/selected-annotations-table/selected-annotations-table.component';
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { MatFormField } from '@angular/material/form-field';
|
||||
import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select';
|
||||
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';
|
||||
import { ForceAnnotationData, ForceAnnotationOption, ForceAnnotationResult, LegalBasisOption } from '../../utils/dialog-types';
|
||||
import { getForceAnnotationOptions } from '../../utils/dialog-options';
|
||||
import { SystemDefaults } from '../../../account/utils/dialog-defaults';
|
||||
import { MatFormField } from '@angular/material/form-field';
|
||||
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, 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';
|
||||
|
||||
const DOCUMINE_LEGAL_BASIS = 'n-a.';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-force-annotation-dialog',
|
||||
templateUrl: './force-annotation-dialog.component.html',
|
||||
styleUrls: ['./force-annotation-dialog.component.scss'],
|
||||
standalone: true,
|
||||
@ -57,12 +55,16 @@ const DOCUMINE_LEGAL_BASIS = 'n-a.';
|
||||
DetailsRadioComponent,
|
||||
],
|
||||
})
|
||||
export class ForceAnnotationDialogComponent extends BaseDialogComponent implements OnInit {
|
||||
export class ForceAnnotationDialogComponent
|
||||
extends IqserDialogComponent<ForceAnnotationDialogComponent, ForceAnnotationData, ForceAnnotationResult>
|
||||
implements OnInit
|
||||
{
|
||||
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||
readonly options: DetailsRadioOption<ForceAnnotationOption>[];
|
||||
|
||||
readonly form: FormGroup;
|
||||
readonly tableColumns: ValueColumn[] = [{ label: 'Value' }, { label: 'Type' }];
|
||||
readonly tableData: ValueColumn[][] = this._data.annotations.map(redaction => [
|
||||
readonly tableData: ValueColumn[][] = this.data.annotations.map(redaction => [
|
||||
{ label: redaction.value, bold: true },
|
||||
{ label: redaction.typeLabel },
|
||||
]);
|
||||
@ -72,21 +74,23 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
|
||||
|
||||
constructor(
|
||||
private readonly _justificationsService: JustificationsService,
|
||||
protected readonly _dialogRef: MatDialogRef<ForceAnnotationDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA)
|
||||
private readonly _data: { readonly dossier: Dossier; readonly hint: boolean; annotations: AnnotationWrapper[] },
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
) {
|
||||
super(_dialogRef);
|
||||
this.options = getForceAnnotationOptions(this.isDocumine, this.isHintDialog);
|
||||
super();
|
||||
this.options = getForceAnnotationOptions(this.isDocumine, this.isHintDialog, this.isImageDialog);
|
||||
this.form = this.#getForm();
|
||||
}
|
||||
|
||||
get isImageHint() {
|
||||
return this._data.annotations.every(annotation => annotation.IMAGE_HINT);
|
||||
return this.data.annotations.every(annotation => annotation.IMAGE_HINT);
|
||||
}
|
||||
|
||||
get isHintDialog() {
|
||||
return this._data.hint;
|
||||
return this.data.hint;
|
||||
}
|
||||
|
||||
get isImageDialog() {
|
||||
return this.data.image;
|
||||
}
|
||||
|
||||
get disabled(): boolean {
|
||||
@ -103,7 +107,7 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
|
||||
|
||||
async ngOnInit() {
|
||||
if (!this.isDocumine) {
|
||||
const data = await firstValueFrom(this._justificationsService.getForDossierTemplate(this._data.dossier.dossierTemplateId));
|
||||
const data = await firstValueFrom(this._justificationsService.getForDossierTemplate(this.data.dossier.dossierTemplateId));
|
||||
|
||||
this.legalOptions = data.map(lbm => ({
|
||||
legalBasis: lbm.reason,
|
||||
@ -114,8 +118,8 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
|
||||
this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
|
||||
|
||||
// Set pre-existing reason if it exists
|
||||
const existingReason = this.legalOptions.find(option => option.legalBasis === this._data.annotations[0].legalBasis);
|
||||
if (!this._data.hint && existingReason) {
|
||||
const existingReason = this.legalOptions.find(option => option.legalBasis === this.data.annotations[0].legalBasis);
|
||||
if (!this.data.hint && existingReason) {
|
||||
this.form.patchValue({ reason: existingReason }, { emitEvent: false });
|
||||
}
|
||||
}
|
||||
@ -123,12 +127,12 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
|
||||
}
|
||||
|
||||
save() {
|
||||
this._dialogRef.close(this.#createForceRedactionRequest());
|
||||
this.close(this.#createForceRedactionRequest());
|
||||
}
|
||||
|
||||
#getForm(): UntypedFormGroup {
|
||||
return this._formBuilder.group({
|
||||
reason: this._data.hint ? ['Forced Hint'] : [null, !this.isDocumine ? Validators.required : null],
|
||||
reason: this.data.hint ? ['Forced Hint'] : [null, !this.isDocumine ? Validators.required : null],
|
||||
comment: [null],
|
||||
option: this.options.find(o => o.value === SystemDefaults.FORCE_REDACTION_DEFAULT),
|
||||
});
|
||||
@ -140,7 +144,7 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
|
||||
request.legalBasis = !this.isDocumine ? this.form.get('reason').value.legalBasis : DOCUMINE_LEGAL_BASIS;
|
||||
request.comment = this.form.get('comment').value;
|
||||
request.reason = this.form.get('reason').value.description;
|
||||
request.option = this.form.get('option').value.value;
|
||||
request.option = this.form.get('option').value?.value;
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<form (submit)="save()" [formGroup]="form">
|
||||
<div [translate]="'manual-annotation.dialog.header.redaction'" class="dialog-header heading-l"></div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="dialog-content redaction">
|
||||
<iqser-details-radio
|
||||
[options]="options"
|
||||
(extraOptionChanged)="extraOptionChanged($event)"
|
||||
@ -43,7 +43,7 @@
|
||||
|
||||
<div class="iqser-input-group w-450">
|
||||
<label [translate]="'manual-annotation.dialog.content.comment'"></label>
|
||||
<textarea formControlName="comment" iqserHasScrollbar name="comment" rows="4" type="text"></textarea>
|
||||
<textarea formControlName="comment" iqserHasScrollbar name="comment" rows="3" type="text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
}
|
||||
|
||||
.dialog-content {
|
||||
height: 650px;
|
||||
overflow-y: auto;
|
||||
height: 600px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.apply-on-multiple-pages {
|
||||
|
||||
@ -130,7 +130,7 @@ export class RectangleAnnotationDialog
|
||||
reason: [null, Validators.required],
|
||||
comment: [null],
|
||||
classification: [NON_READABLE_CONTENT],
|
||||
option: [this.#getOption(SystemDefaults.RECTANGLE_REDACT_DEFAULT), validatePageRange()],
|
||||
option: [this.#getOption(SystemDefaults.RECTANGLE_REDACT_DEFAULT), validatePageRange(this.data.file.numberOfPages)],
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -162,7 +162,11 @@ export class RedactRecommendationDialogComponent
|
||||
}
|
||||
|
||||
#setDictionaries() {
|
||||
this.dictionaries = this._dictionaryService.getRedactTextDictionaries(this.#dossier.dossierId, !this.#applyToAllDossiers);
|
||||
this.dictionaries = this._dictionaryService.getRedactTextDictionaries(
|
||||
this.#dossier.dossierId,
|
||||
!this.#applyToAllDossiers,
|
||||
this.#dossier.dossierTemplateId,
|
||||
);
|
||||
}
|
||||
|
||||
#selectReason() {
|
||||
|
||||
@ -219,7 +219,11 @@ export class RedactTextDialogComponent
|
||||
}
|
||||
|
||||
#setDictionaries() {
|
||||
this.dictionaries = this._dictionaryService.getRedactTextDictionaries(this.#dossier.dossierId, !this.#applyToAllDossiers);
|
||||
this.dictionaries = this._dictionaryService.getRedactTextDictionaries(
|
||||
this.#dossier.dossierId,
|
||||
!this.#applyToAllDossiers,
|
||||
this.#dossier.dossierTemplateId,
|
||||
);
|
||||
}
|
||||
|
||||
#getForm(): FormGroup {
|
||||
|
||||
@ -36,7 +36,7 @@ import {
|
||||
} from '../../utils/dialog-types';
|
||||
import { isJustOne } from '@common-ui/utils';
|
||||
import { validatePageRange } from '../../utils/form-validators';
|
||||
import { parseRectanglePosition, parseSelectedPageNumbers } from '../../utils/enhance-manual-redaction-request.utils';
|
||||
import { parseRectanglePosition, parseSelectedPageNumbers, prefillPageRange } from '../../utils/enhance-manual-redaction-request.utils';
|
||||
|
||||
@Component({
|
||||
templateUrl: './remove-redaction-dialog.component.html',
|
||||
@ -112,7 +112,7 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent<
|
||||
readonly redactedTexts = this.data.redactions.map(annotation => annotation.value);
|
||||
form: UntypedFormGroup = this._formBuilder.group({
|
||||
comment: [null],
|
||||
option: [this.defaultOption, validatePageRange(true)],
|
||||
option: [this.defaultOption, validatePageRange(this.data.file.numberOfPages, true)],
|
||||
});
|
||||
|
||||
readonly selectedOption = toSignal(this.form.get('option').valueChanges.pipe(map(value => value.value)));
|
||||
@ -140,6 +140,14 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent<
|
||||
private readonly _userPreferences: UserPreferenceService,
|
||||
) {
|
||||
super();
|
||||
|
||||
if (this.#allRectangles) {
|
||||
prefillPageRange(
|
||||
this.data.redactions[0],
|
||||
this.data.allFileRedactions,
|
||||
this.options as DetailsRadioOption<RectangleRedactOption>[],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
get hasFalsePositiveOption() {
|
||||
@ -177,12 +185,9 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent<
|
||||
}
|
||||
|
||||
save(): void {
|
||||
const optionValue = this.form.controls.option.value.value;
|
||||
const pageNumbers = parseSelectedPageNumbers(
|
||||
this.form.get('option').value.additionalInput?.value,
|
||||
this.data.file,
|
||||
this.data.redactions[0],
|
||||
);
|
||||
const optionValue = this.form.controls.option?.value?.value;
|
||||
const optionInputValue = this.form.controls.option?.value?.additionalInput?.value;
|
||||
const pageNumbers = parseSelectedPageNumbers(optionInputValue, this.data.file, this.data.redactions[0]);
|
||||
const position = parseRectanglePosition(this.data.redactions[0]);
|
||||
|
||||
this.close({
|
||||
|
||||
@ -77,7 +77,7 @@ export class ResizeRedactionDialogComponent extends IqserDialogComponent<
|
||||
|
||||
save() {
|
||||
const formValue = this.form.getRawValue();
|
||||
const updateDictionary = formValue.option.value === ResizeOptions.IN_DOSSIER;
|
||||
const updateDictionary = formValue.option?.value === ResizeOptions.IN_DOSSIER;
|
||||
|
||||
super.close({
|
||||
comment: formValue.comment,
|
||||
|
||||
@ -248,11 +248,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._viewerHeaderService.enableLoadAllAnnotations(); // Reset the button state (since the viewer is reused between files)
|
||||
super.ngOnDetach();
|
||||
this.pdf.instance.UI.hotkeys.off('esc');
|
||||
this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
|
||||
this._changeRef.markForCheck();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.pdf.instance.UI.hotkeys.off('esc');
|
||||
this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
|
||||
super.ngOnDestroy();
|
||||
}
|
||||
|
||||
@ -277,6 +279,29 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
}
|
||||
|
||||
@Bind()
|
||||
handleViewerClick(event: MouseEvent) {
|
||||
this._ngZone.run(() => {
|
||||
if (event.isTrusted) {
|
||||
const clickedElement = event.target as HTMLElement;
|
||||
const editingAnnotation =
|
||||
(clickedElement as HTMLImageElement).src?.includes('edit.svg') || clickedElement.getAttribute('aria-label') === 'Edit';
|
||||
if (this._multiSelectService.active() && !editingAnnotation) {
|
||||
if (
|
||||
clickedElement.querySelector('#selectionrect') ||
|
||||
clickedElement.id === `pageWidgetContainer${this.pdf.currentPage()}`
|
||||
) {
|
||||
if (!this._annotationManager.selected.length) {
|
||||
this._multiSelectService.deactivate();
|
||||
}
|
||||
} else {
|
||||
this._multiSelectService.deactivate();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async ngOnAttach(previousRoute: ActivatedRouteSnapshot) {
|
||||
if (!this.state.file().canBeOpened) {
|
||||
return this.#navigateToDossier();
|
||||
@ -307,6 +332,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this.#restoreOldFilters();
|
||||
this.pdf.instance.UI.hotkeys.on('esc', this.handleEscInsideViewer);
|
||||
this._viewerHeaderService.resetLayers();
|
||||
this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
|
||||
this.pdf.instance.UI.iframeWindow.document.addEventListener('click', this.handleViewerClick);
|
||||
}
|
||||
|
||||
async openRectangleAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
|
||||
|
||||
@ -7,6 +7,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import {
|
||||
DictionaryEntryTypes,
|
||||
DownloadFileTypes,
|
||||
EarmarkOperation,
|
||||
type IBulkLocalRemoveRequest,
|
||||
IBulkRecategorizationRequest,
|
||||
@ -51,6 +52,7 @@ import { FilePreviewStateService } from './file-preview-state.service';
|
||||
import { ManualRedactionService } from './manual-redaction.service';
|
||||
import { SkippedService } from './skipped.service';
|
||||
import { NON_READABLE_CONTENT } from '../dialogs/rectangle-annotation-dialog/rectangle-annotation-dialog.component';
|
||||
import { ForceAnnotationDialogComponent } from '../dialogs/force-redaction-dialog/force-annotation-dialog.component';
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationActionsService {
|
||||
@ -81,41 +83,49 @@ export class AnnotationActionsService {
|
||||
this._dialogService.openDialog('highlightAction', data);
|
||||
}
|
||||
|
||||
forceAnnotation(annotations: AnnotationWrapper[], hint: boolean = false) {
|
||||
async forceAnnotation(annotations: AnnotationWrapper[], hint: boolean = false) {
|
||||
const { dossierId, fileId } = this._state;
|
||||
const data = { dossier: this._state.dossier(), annotations, hint };
|
||||
this._dialogService.openDialog('forceAnnotation', data, (request: ILegalBasisChangeRequest) => {
|
||||
let obs$: Observable<unknown>;
|
||||
if (request.option === ForceAnnotationOptions.ONLY_HERE) {
|
||||
obs$ = this._manualRedactionService.bulkForce(
|
||||
annotations.map(a => ({ ...request, annotationId: a.id })),
|
||||
dossierId,
|
||||
fileId,
|
||||
annotations[0].isIgnoredHint,
|
||||
);
|
||||
} else {
|
||||
const addAnnotationRequest = annotations.map(a => ({
|
||||
comment: { text: request.comment },
|
||||
legalBasis: request.legalBasis,
|
||||
reason: request.reason,
|
||||
positions: a.positions,
|
||||
type: a.type,
|
||||
value: a.value,
|
||||
}));
|
||||
obs$ = this._manualRedactionService.addAnnotation(addAnnotationRequest, dossierId, fileId, {
|
||||
hint,
|
||||
bulkLocal: true,
|
||||
});
|
||||
}
|
||||
this.#processObsAndEmit(obs$).then();
|
||||
});
|
||||
const image = annotations.every(a => a.isImage);
|
||||
const data = { dossier: this._state.dossier(), annotations, hint, image };
|
||||
|
||||
const dialogRef = this._iqserDialog.openDefault(ForceAnnotationDialogComponent, { data });
|
||||
const result = await dialogRef.result();
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
let obs$: Observable<unknown>;
|
||||
if (result.option === ForceAnnotationOptions.ONLY_HERE || hint || image) {
|
||||
obs$ = this._manualRedactionService.bulkForce(
|
||||
annotations.map(a => ({ ...result, annotationId: a.id })),
|
||||
dossierId,
|
||||
fileId,
|
||||
annotations[0].isIgnoredHint,
|
||||
);
|
||||
} else {
|
||||
const addAnnotationRequest = annotations.map(a => ({
|
||||
comment: result.comment,
|
||||
legalBasis: result.legalBasis,
|
||||
reason: result.reason,
|
||||
positions: a.positions,
|
||||
type: a.type,
|
||||
value: a.value,
|
||||
}));
|
||||
obs$ = this._manualRedactionService.addAnnotation(addAnnotationRequest, dossierId, fileId, {
|
||||
hint,
|
||||
bulkLocal: true,
|
||||
});
|
||||
}
|
||||
this.#processObsAndEmit(obs$).then();
|
||||
}
|
||||
|
||||
async editRedaction(annotations: AnnotationWrapper[]) {
|
||||
const { dossierId, file } = this._state;
|
||||
const includeUnprocessed = annotations.every(annotation => this.#includeUnprocessed(annotation, true));
|
||||
const allFileAnnotations = this._fileDataService.annotations();
|
||||
const data = {
|
||||
annotations,
|
||||
allFileAnnotations,
|
||||
dossierId,
|
||||
file: file(),
|
||||
};
|
||||
@ -145,15 +155,11 @@ export class AnnotationActionsService {
|
||||
return body;
|
||||
});
|
||||
} else {
|
||||
const originTypes = annotations.map(a => a.type);
|
||||
const originLegalBases = annotations.map(a => a.legalBasis);
|
||||
recategorizeBody = {
|
||||
value: annotations[0].value,
|
||||
type: result.type,
|
||||
legalBasis: result.legalBasis,
|
||||
section: result.section,
|
||||
originTypes,
|
||||
originLegalBases,
|
||||
rectangle: annotations[0].AREA,
|
||||
pageNumbers: result.pageNumbers,
|
||||
position: result.position,
|
||||
@ -168,7 +174,6 @@ export class AnnotationActionsService {
|
||||
dossierId,
|
||||
file().id,
|
||||
this.#getChangedFields(annotations, result),
|
||||
includeUnprocessed,
|
||||
result.option === RedactOrHintOptions.IN_DOCUMENT || !!result.pageNumbers.length,
|
||||
)
|
||||
.pipe(log()),
|
||||
@ -184,9 +189,11 @@ export class AnnotationActionsService {
|
||||
const dossierTemplate = this._dossierTemplatesService.find(this._state.dossierTemplateId);
|
||||
const isApprover = this._permissionsService.isApprover(this._state.dossier());
|
||||
const { file } = this._state;
|
||||
const allFileRedactions = this._fileDataService.annotations();
|
||||
|
||||
const data = {
|
||||
redactions,
|
||||
allFileRedactions,
|
||||
file: file(),
|
||||
dossier: this._state.dossier(),
|
||||
falsePositiveContext: redactions.map(r => this.#getFalsePositiveText(r)),
|
||||
@ -202,8 +209,8 @@ export class AnnotationActionsService {
|
||||
}
|
||||
|
||||
if (
|
||||
result.option.value === RemoveRedactionOptions.FALSE_POSITIVE ||
|
||||
result.option.value === RemoveRedactionOptions.DO_NOT_RECOMMEND
|
||||
result.option?.value === RemoveRedactionOptions.FALSE_POSITIVE ||
|
||||
result.option?.value === RemoveRedactionOptions.DO_NOT_RECOMMEND
|
||||
) {
|
||||
this.#setAsFalsePositive(redactions, result);
|
||||
} else {
|
||||
@ -265,7 +272,6 @@ export class AnnotationActionsService {
|
||||
|
||||
async acceptResize(annotation: AnnotationWrapper, permissions: AnnotationPermissions): Promise<void> {
|
||||
const textAndPositions = await this.#extractTextAndPositions(annotation.id);
|
||||
const includeUnprocessed = this.#includeUnprocessed(annotation);
|
||||
if (annotation.isRecommendation) {
|
||||
const recommendation = {
|
||||
...annotation,
|
||||
@ -316,16 +322,16 @@ export class AnnotationActionsService {
|
||||
await this.cancelResize(annotation);
|
||||
|
||||
const { fileId, dossierId } = this._state;
|
||||
const request = this._manualRedactionService.resize([resizeRequest], dossierId, fileId, includeUnprocessed);
|
||||
const request = this._manualRedactionService.resize([resizeRequest], dossierId, fileId);
|
||||
return this.#processObsAndEmit(request);
|
||||
}
|
||||
|
||||
async cancelResize(annotationWrapper: AnnotationWrapper) {
|
||||
this._annotationManager.resizingAnnotationId = undefined;
|
||||
this._annotationManager.annotationHasBeenResized = false;
|
||||
this._annotationManager.deselect();
|
||||
this._annotationManager.delete(annotationWrapper);
|
||||
await this._annotationDrawService.draw([annotationWrapper], this._skippedService.hideSkipped(), this._state.dossierTemplateId);
|
||||
this._annotationManager.deselect();
|
||||
}
|
||||
|
||||
#generateRectangle(annotationWrapper: AnnotationWrapper) {
|
||||
@ -472,8 +478,7 @@ export class AnnotationActionsService {
|
||||
}
|
||||
|
||||
#removeRedaction(redactions: AnnotationWrapper[], dialogResult: RemoveRedactionResult) {
|
||||
const removeFromDictionary = dialogResult.option.value === RemoveRedactionOptions.IN_DOSSIER;
|
||||
const includeUnprocessed = redactions.every(redaction => this.#includeUnprocessed(redaction, true));
|
||||
const removeFromDictionary = dialogResult.option?.value === RemoveRedactionOptions.IN_DOSSIER;
|
||||
const body = this.#getRemoveRedactionBody(redactions, dialogResult);
|
||||
// todo: might not be correct, probably shouldn't get to this point if they are not all the same
|
||||
const isHint = redactions.every(r => r.isHint);
|
||||
@ -501,7 +506,6 @@ export class AnnotationActionsService {
|
||||
fileId,
|
||||
removeFromDictionary,
|
||||
isHint,
|
||||
includeUnprocessed,
|
||||
dialogResult.bulkLocal,
|
||||
),
|
||||
),
|
||||
@ -517,7 +521,6 @@ export class AnnotationActionsService {
|
||||
fileId,
|
||||
removeFromDictionary,
|
||||
isHint,
|
||||
includeUnprocessed,
|
||||
dialogResult.bulkLocal || !!dialogResult.pageNumbers.length,
|
||||
),
|
||||
).then();
|
||||
@ -576,20 +579,6 @@ export class AnnotationActionsService {
|
||||
return { changes: changedFields.join(', ') };
|
||||
}
|
||||
|
||||
//TODO this is temporary, based on RED-8950. Should be removed when a better solution will be found
|
||||
#includeUnprocessed(annotation: AnnotationWrapper, isRemoveOrRecategorize = false) {
|
||||
const processed = annotation.entry.manualChanges.at(-1)?.processed;
|
||||
if (!processed) {
|
||||
const autoAnalysisDisabled = this._state.file().excludedFromAutomaticAnalysis;
|
||||
const addedLocallyWhileDisabled = annotation.manual;
|
||||
if (autoAnalysisDisabled) {
|
||||
return addedLocallyWhileDisabled;
|
||||
}
|
||||
return isRemoveOrRecategorize && addedLocallyWhileDisabled;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#getRemoveRedactionBody(
|
||||
redactions: AnnotationWrapper[],
|
||||
dialogResult: RemoveRedactionResult,
|
||||
@ -599,8 +588,6 @@ export class AnnotationActionsService {
|
||||
return {
|
||||
value: redaction.value,
|
||||
rectangle: redaction.value === NON_READABLE_CONTENT,
|
||||
originTypes: [redaction.entry.type],
|
||||
originLegalBases: [redaction.legalBasis],
|
||||
pageNumbers: dialogResult.pageNumbers,
|
||||
position: dialogResult.position,
|
||||
comment: dialogResult.comment,
|
||||
@ -611,8 +598,8 @@ export class AnnotationActionsService {
|
||||
annotationId: redaction.id,
|
||||
value: redaction.value,
|
||||
comment: dialogResult.comment,
|
||||
removeFromDictionary: dialogResult.option.value === RemoveRedactionOptions.IN_DOSSIER,
|
||||
removeFromAllDossiers: !!dialogResult.option.additionalCheck?.checked || !!dialogResult.applyToAllDossiers,
|
||||
removeFromDictionary: dialogResult.option?.value === RemoveRedactionOptions.IN_DOSSIER,
|
||||
removeFromAllDossiers: !!dialogResult.option?.additionalCheck?.checked || !!dialogResult.applyToAllDossiers,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,10 +3,9 @@ import { MatDialog } from '@angular/material/dialog';
|
||||
import { ConfirmationDialogComponent, DialogConfig, DialogService } from '@iqser/common-ui';
|
||||
import { ChangeLegalBasisDialogComponent } from '../dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
|
||||
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';
|
||||
|
||||
type DialogType = 'confirm' | 'documentInfo' | 'changeLegalBasis' | 'forceAnnotation' | 'highlightAction';
|
||||
type DialogType = 'confirm' | 'documentInfo' | 'changeLegalBasis' | 'highlightAction';
|
||||
|
||||
@Injectable()
|
||||
export class FilePreviewDialogService extends DialogService<DialogType> {
|
||||
@ -22,9 +21,6 @@ export class FilePreviewDialogService extends DialogService<DialogType> {
|
||||
changeLegalBasis: {
|
||||
component: ChangeLegalBasisDialogComponent,
|
||||
},
|
||||
forceAnnotation: {
|
||||
component: ForceAnnotationDialogComponent,
|
||||
},
|
||||
highlightAction: {
|
||||
component: HighlightActionDialogComponent,
|
||||
},
|
||||
|
||||
@ -75,13 +75,10 @@ export class ManualRedactionService extends GenericService<IManualAddResponse> {
|
||||
body: List<IRecategorizationRequest> | IBulkRecategorizationRequest,
|
||||
dossierId: string,
|
||||
fileId: string,
|
||||
successMessageParameters?: {
|
||||
[key: string]: string;
|
||||
},
|
||||
includeUnprocessed = false,
|
||||
successMessageParameters?: { [p: string]: string },
|
||||
bulkLocal = false,
|
||||
) {
|
||||
return this.#recategorize(body, dossierId, fileId, includeUnprocessed, bulkLocal).pipe(
|
||||
return this.#recategorize(body, dossierId, fileId, bulkLocal).pipe(
|
||||
this.#showToast('recategorize-annotation', false, successMessageParameters),
|
||||
);
|
||||
}
|
||||
@ -117,10 +114,9 @@ export class ManualRedactionService extends GenericService<IManualAddResponse> {
|
||||
fileId: string,
|
||||
removeFromDictionary = false,
|
||||
isHint = false,
|
||||
includeUnprocessed = false,
|
||||
bulkLocal = false,
|
||||
) {
|
||||
return this.#remove(body, dossierId, fileId, includeUnprocessed, bulkLocal).pipe(
|
||||
return this.#remove(body, dossierId, fileId, bulkLocal).pipe(
|
||||
this.#showToast(!isHint ? 'remove' : 'remove-hint', removeFromDictionary),
|
||||
);
|
||||
}
|
||||
@ -154,36 +150,23 @@ export class ManualRedactionService extends GenericService<IManualAddResponse> {
|
||||
return this._post(body, `${this.#bulkRedaction}/force/${dossierId}/${fileId}`).pipe(this.#log('Force redaction', body));
|
||||
}
|
||||
|
||||
resize(body: List<IResizeRequest>, dossierId: string, fileId: string, includeUnprocessed = false) {
|
||||
return this._post(body, `${this.#bulkRedaction}/resize/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`).pipe(
|
||||
this.#log('Resize', body),
|
||||
);
|
||||
resize(body: List<IResizeRequest>, dossierId: string, fileId: string) {
|
||||
return this._post(body, `${this.#bulkRedaction}/resize/${dossierId}/${fileId}`).pipe(this.#log('Resize', body));
|
||||
}
|
||||
|
||||
#recategorize(
|
||||
body: List<IRecategorizationRequest> | IBulkRecategorizationRequest,
|
||||
dossierId: string,
|
||||
fileId: string,
|
||||
includeUnprocessed = false,
|
||||
bulkLocal = false,
|
||||
) {
|
||||
const bulkPath = bulkLocal ? this.#bulkLocal : this.#bulkRedaction;
|
||||
return this._post(body, `${bulkPath}/recategorize/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`).pipe(
|
||||
this.#log('Recategorize', body),
|
||||
);
|
||||
return this._post(body, `${bulkPath}/recategorize/${dossierId}/${fileId}`).pipe(this.#log('Recategorize', body));
|
||||
}
|
||||
|
||||
#remove(
|
||||
body: List<IRemoveRedactionRequest> | IBulkLocalRemoveRequest,
|
||||
dossierId: string,
|
||||
fileId: string,
|
||||
includeUnprocessed = false,
|
||||
bulkLocal = false,
|
||||
) {
|
||||
#remove(body: List<IRemoveRedactionRequest> | IBulkLocalRemoveRequest, dossierId: string, fileId: string, bulkLocal = false) {
|
||||
const bulkPath = bulkLocal ? this.#bulkLocal : this.#bulkRedaction;
|
||||
return this._post(body, `${bulkPath}/remove/${dossierId}/${fileId}?includeUnprocessed=${includeUnprocessed}`).pipe(
|
||||
this.#log('Remove', body),
|
||||
);
|
||||
return this._post(body, `${bulkPath}/remove/${dossierId}/${fileId}`).pipe(this.#log('Remove', body));
|
||||
}
|
||||
|
||||
#log(action: string, body: unknown) {
|
||||
|
||||
@ -26,7 +26,7 @@ export class PdfAnnotationActionsService {
|
||||
get(annotations: AnnotationWrapper[], annotationChangesAllowed: boolean): IHeaderElement[] {
|
||||
const availableActions: IHeaderElement[] = [];
|
||||
const permissions = this.#getAnnotationsPermissions(annotations);
|
||||
const sameType = annotations.every(a => a.type === annotations[0].type);
|
||||
const sameType = annotations.every(a => a.superType === annotations[0].superType);
|
||||
|
||||
// you can only resize one annotation at a time
|
||||
if (permissions.canResizeAnnotation && annotationChangesAllowed) {
|
||||
|
||||
@ -30,7 +30,11 @@ const DOCUMENT_ICON = 'iqser:document';
|
||||
const FOLDER_ICON = 'red:folder';
|
||||
const REMOVE_FROM_DICT_ICON = 'red:remove-from-dict';
|
||||
|
||||
export const getEditRedactionOptions = (): DetailsRadioOption<EditRedactionOption>[] => {
|
||||
export const getEditRedactionOptions = (hint: boolean): DetailsRadioOption<EditRedactionOption>[] => {
|
||||
if (hint) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
label: editRedactionTranslations.onlyHere.label,
|
||||
@ -118,6 +122,7 @@ export const getRectangleRedactOptions = (action: 'add' | 'edit' | 'remove' = 'a
|
||||
description: translations.multiplePages.extraOptionDescription,
|
||||
placeholder: translations.multiplePages.extraOptionPlaceholder,
|
||||
value: '',
|
||||
errorCode: 'invalidRange',
|
||||
},
|
||||
},
|
||||
];
|
||||
@ -131,22 +136,21 @@ export const getResizeRedactionOptions = (
|
||||
isApprover: boolean,
|
||||
canResizeInDictionary: boolean,
|
||||
): DetailsRadioOption<ResizeRedactionOption>[] => {
|
||||
if (isRss || !canResizeInDictionary) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const translations = resizeRedactionTranslations;
|
||||
const options: DetailsRadioOption<ResizeRedactionOption>[] = [
|
||||
const dictBasedType = redaction.isModifyDictionary;
|
||||
|
||||
return [
|
||||
{
|
||||
label: translations.onlyHere.label,
|
||||
description: translations.onlyHere.description,
|
||||
icon: PIN_ICON,
|
||||
value: ResizeOptions.ONLY_HERE,
|
||||
},
|
||||
];
|
||||
|
||||
if (isRss) {
|
||||
return options;
|
||||
}
|
||||
if (canResizeInDictionary) {
|
||||
const dictBasedType = redaction.isModifyDictionary;
|
||||
options.push({
|
||||
{
|
||||
label: translations.inDossier.label,
|
||||
description: translations.inDossier.description,
|
||||
descriptionParams: { dossierName: dossier.dossierName },
|
||||
@ -159,9 +163,8 @@ export const getResizeRedactionOptions = (
|
||||
checked: applyToAllDossiers,
|
||||
hidden: !isApprover,
|
||||
},
|
||||
});
|
||||
}
|
||||
return options;
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const getRemoveRedactionOptions = (
|
||||
@ -172,9 +175,10 @@ export const getRemoveRedactionOptions = (
|
||||
const translations = isDocumine ? removeAnnotationTranslations : removeRedactionTranslations;
|
||||
const { permissions, redactions, isApprover, falsePositiveContext } = data;
|
||||
const isBulk = redactions.length > 1;
|
||||
const isImage = redactions.reduce((acc, next) => acc && next.isImage, true);
|
||||
|
||||
const options: DetailsRadioOption<RemoveRedactionOption>[] = [];
|
||||
if (permissions.canRemoveOnlyHere) {
|
||||
if (permissions.canRemoveOnlyHere && !isImage) {
|
||||
options.push({
|
||||
label: translations.ONLY_HERE.label,
|
||||
description: isBulk ? translations.ONLY_HERE.descriptionBulk : translations.ONLY_HERE.description,
|
||||
@ -187,15 +191,15 @@ export const getRemoveRedactionOptions = (
|
||||
value: RemoveRedactionOptions.ONLY_HERE,
|
||||
});
|
||||
|
||||
options.push({
|
||||
label: removeRedactionTranslations.IN_DOCUMENT.label,
|
||||
description: removeRedactionTranslations.IN_DOCUMENT.description,
|
||||
descriptionParams: {
|
||||
isImage: redactions[0].isImage ? 'image' : redactions[0].typeLabel,
|
||||
},
|
||||
icon: DOCUMENT_ICON,
|
||||
value: RemoveRedactionOptions.IN_DOCUMENT,
|
||||
});
|
||||
const isHint = redactions.reduce((acc, next) => acc && next.isHint, true);
|
||||
if (!isHint) {
|
||||
options.push({
|
||||
label: removeRedactionTranslations.IN_DOCUMENT.label,
|
||||
description: removeRedactionTranslations.IN_DOCUMENT.description,
|
||||
icon: DOCUMENT_ICON,
|
||||
value: RemoveRedactionOptions.IN_DOCUMENT,
|
||||
});
|
||||
}
|
||||
}
|
||||
if (permissions.canRemoveFromDictionary) {
|
||||
options.push({
|
||||
@ -264,8 +268,12 @@ export const getRemoveRedactionOptions = (
|
||||
return options;
|
||||
};
|
||||
|
||||
export const getForceAnnotationOptions = (isDocumine: boolean, isHint: boolean): DetailsRadioOption<ForceAnnotationOption>[] => {
|
||||
if (isDocumine || isHint) {
|
||||
export const getForceAnnotationOptions = (
|
||||
isDocumine: boolean,
|
||||
isHint: boolean,
|
||||
isImage: boolean,
|
||||
): DetailsRadioOption<ForceAnnotationOption>[] => {
|
||||
if (isDocumine || isHint || isImage) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@ -64,6 +64,7 @@ export interface RedactTextData {
|
||||
|
||||
export interface EditRedactionData {
|
||||
annotations: AnnotationWrapper[];
|
||||
allFileAnnotations?: AnnotationWrapper[];
|
||||
dossierId: string;
|
||||
file: File;
|
||||
isApprover?: boolean;
|
||||
@ -72,6 +73,21 @@ export interface EditRedactionData {
|
||||
export type AddAnnotationData = RedactTextData;
|
||||
export type AddHintData = RedactTextData;
|
||||
|
||||
export interface ForceAnnotationData {
|
||||
readonly dossier: Dossier;
|
||||
readonly annotations: AnnotationWrapper[];
|
||||
readonly hint: boolean;
|
||||
readonly image: boolean;
|
||||
}
|
||||
|
||||
export interface ForceAnnotationResult {
|
||||
readonly annotationId?: string;
|
||||
readonly comment?: string;
|
||||
readonly legalBasis?: string;
|
||||
readonly reason?: string;
|
||||
readonly option?: ForceAnnotationOption;
|
||||
}
|
||||
|
||||
export interface RedactTextResult {
|
||||
redaction: IManualRedactionEntry;
|
||||
dictionary: Dictionary;
|
||||
@ -135,6 +151,7 @@ export interface RemoveRedactionPermissions {
|
||||
|
||||
export interface RemoveRedactionData {
|
||||
redactions: AnnotationWrapper[];
|
||||
allFileRedactions?: AnnotationWrapper[];
|
||||
dossier: Dossier;
|
||||
file?: File;
|
||||
falsePositiveContext: string[];
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { Dictionary, File, IAddRedactionRequest, IEntityLogEntryPosition, SuperType } from '@red/domain';
|
||||
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||
import { LegalBasisOption } from './dialog-types';
|
||||
import { LegalBasisOption, RectangleRedactOption, RectangleRedactOptions } from './dialog-types';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';
|
||||
|
||||
export interface EnhanceRequestData {
|
||||
readonly type: SuperType | null;
|
||||
@ -79,3 +80,60 @@ export const parseRectanglePosition = (annotation: AnnotationWrapper) => {
|
||||
pageNumber: position.page,
|
||||
} as IEntityLogEntryPosition;
|
||||
};
|
||||
|
||||
export const prefillPageRange = (
|
||||
annotation: AnnotationWrapper,
|
||||
allFileAnnotations: AnnotationWrapper[],
|
||||
options: DetailsRadioOption<RectangleRedactOption>[],
|
||||
) => {
|
||||
const option = options.find(o => o.value === RectangleRedactOptions.MULTIPLE_PAGES);
|
||||
const pages = extractPages(annotation, allFileAnnotations);
|
||||
option.additionalInput.value = toRangeString(pages);
|
||||
};
|
||||
|
||||
const extractPages = (annotation: AnnotationWrapper, allFileAnnotations: AnnotationWrapper[]): number[] => {
|
||||
return allFileAnnotations.reduce((pages, a) => {
|
||||
const position = a.positions[0];
|
||||
const annotationPosition = annotation.positions[0];
|
||||
if (
|
||||
position.height === annotationPosition.height &&
|
||||
position.width === annotationPosition.width &&
|
||||
position.topLeft.x === annotationPosition.topLeft.x &&
|
||||
position.topLeft.y === annotationPosition.topLeft.y
|
||||
) {
|
||||
pages.push(position.page);
|
||||
}
|
||||
return pages;
|
||||
}, []);
|
||||
};
|
||||
|
||||
const toRangeString = (pages: number[]): string => {
|
||||
if (pages.length === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let ranges = [];
|
||||
let start = pages[0];
|
||||
let end = pages[0];
|
||||
|
||||
for (let i = 1; i < pages.length; i++) {
|
||||
if (pages[i] === end + 1) {
|
||||
end = pages[i];
|
||||
} else {
|
||||
if (start === end) {
|
||||
ranges.push(`${start}`);
|
||||
} else {
|
||||
ranges.push(`${start}-${end}`);
|
||||
}
|
||||
start = end = pages[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (start === end) {
|
||||
ranges.push(`${start}`);
|
||||
} else {
|
||||
ranges.push(`${start}-${end}`);
|
||||
}
|
||||
|
||||
return ranges.join(',');
|
||||
};
|
||||
|
||||
@ -1,12 +1,26 @@
|
||||
import { AbstractControl, ValidatorFn } from '@angular/forms';
|
||||
|
||||
export const validatePageRange = (allowEmpty = false): ValidatorFn => {
|
||||
export const validatePageRange = (numberOfPages: number, allowEmpty = false): ValidatorFn => {
|
||||
return (control: AbstractControl): { [key: string]: any } | null => {
|
||||
const option = control.value;
|
||||
if (option?.additionalInput) {
|
||||
const value = option.additionalInput.value;
|
||||
const validRange = /^(\d+(-\d+)?)(,\d+(-\d+)?)*$/.test(value);
|
||||
return validRange || (!value.length && allowEmpty) ? null : { invalidRange: true };
|
||||
|
||||
if (!validRange && !(value.length === 0 && allowEmpty)) {
|
||||
return { invalidRange: true };
|
||||
}
|
||||
|
||||
const ranges = value.split(',');
|
||||
const isWithinRange = ranges.every(range => {
|
||||
const [start, end] = range.split('-').map(Number);
|
||||
if (end) {
|
||||
return start >= 1 && end <= numberOfPages && start < end;
|
||||
}
|
||||
return start >= 1 && start <= numberOfPages;
|
||||
});
|
||||
|
||||
return isWithinRange || (value.length === 0 && allowEmpty) ? null : { invalidRange: true };
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -8,7 +8,9 @@
|
||||
>
|
||||
<redaction-annotation-icon
|
||||
[color]="dictionary.hexColor"
|
||||
[label]="dictionary.hint ? 'H' : 'R'"
|
||||
[label]="
|
||||
dictionary.hint ? (workloadTranslations['hint'] | translate)[0] : (workloadTranslations['redaction'] | translate)[0]
|
||||
"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<div class="details">
|
||||
|
||||
@ -20,6 +20,7 @@ import { AnnotationIconComponent } from '@shared/components/annotation-icon/anno
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { workloadTranslations } from '@translations/workload-translations';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-dictionary',
|
||||
@ -47,6 +48,7 @@ export class EditDossierDictionaryComponent implements OnInit {
|
||||
activeEntryType = DictionaryEntryTypes.ENTRY;
|
||||
entriesToDisplay: List = [];
|
||||
readonly entryTypes = DictionaryEntryTypes;
|
||||
protected readonly workloadTranslations = workloadTranslations;
|
||||
@ViewChild(DictionaryManagerComponent, { static: false }) private readonly _dictionaryManager: DictionaryManagerComponent;
|
||||
|
||||
constructor(
|
||||
|
||||
@ -44,11 +44,15 @@
|
||||
<div class="iqser-input-group w-300">
|
||||
<label translate="edit-dossier-dialog.general-info.form.dossier-state.label"></label>
|
||||
<mat-form-field>
|
||||
<mat-select [placeholder]="statusPlaceholder" formControlName="dossierStatusId">
|
||||
<mat-option *ngFor="let stateId of states" [value]="stateId">
|
||||
<div [matTooltip]="getStateName(stateId)" class="flex-align-items-center" matTooltipPosition="after">
|
||||
<iqser-small-chip *ngIf="!!stateId" [color]="getStateColor(stateId)"></iqser-small-chip>
|
||||
<div class="clamp-1">{{ getStateName(stateId) }}</div>
|
||||
<mat-select [placeholder]="statePlaceholder()" formControlName="dossierStatusId">
|
||||
<mat-option *ngFor="let stateId of states()" [value]="stateId">
|
||||
<div
|
||||
[matTooltip]="stateNameAndColor()[stateId]?.name"
|
||||
class="flex-align-items-center"
|
||||
matTooltipPosition="after"
|
||||
>
|
||||
<iqser-small-chip *ngIf="!!stateId" [color]="stateNameAndColor()[stateId]?.color"></iqser-small-chip>
|
||||
<div class="clamp-1">{{ stateNameAndColor()[stateId]?.name }}</div>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
@ -80,7 +84,7 @@
|
||||
<div class="dialog-actions">
|
||||
<iqser-icon-button
|
||||
(action)="deleteDossier()"
|
||||
*ngIf="permissionsService.canDeleteDossier(dossier)"
|
||||
*ngIf="permissionsService.canDeleteDossier(dossier())"
|
||||
[attr.help-mode-key]="'edit_dossier_delete_dossier_DIALOG'"
|
||||
[buttonId]="'deleteDossier'"
|
||||
[icon]="'iqser:trash'"
|
||||
@ -90,7 +94,7 @@
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="archiveDossier()"
|
||||
*ngIf="permissionsService.canArchiveDossier(dossier)"
|
||||
*ngIf="permissionsService.canArchiveDossier(dossier())"
|
||||
[attr.help-mode-key]="'edit_dossier_archive_dossier_DIALOG'"
|
||||
[icon]="'red:archive'"
|
||||
[label]="'dossier-listing.archive.action' | translate"
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { NgForOf, NgIf } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, computed, effect, input, OnInit, signal, untracked } from '@angular/core';
|
||||
import { FormGroup, ReactiveFormsModule, UntypedFormBuilder, Validators } from '@angular/forms';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { MatFormField, MatSuffix } from '@angular/material/form-field';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { MatOption, MatSelect } from '@angular/material/select';
|
||||
import { MatOption, MatSelect, MatSelectTrigger } from '@angular/material/select';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { Router } from '@angular/router';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
@ -30,12 +30,22 @@ import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
||||
import { TrashService } from '@services/entity-services/trash.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { dateWithoutTime } from '@utils/functions';
|
||||
import { dateWithoutTime, formControlToSignal } from '@utils/functions';
|
||||
import dayjs from 'dayjs';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { type EditDossierDialogComponent } from '../edit-dossier-dialog.component';
|
||||
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { AsControl, isJustOne } from '@common-ui/utils';
|
||||
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
|
||||
|
||||
interface GeneralInfoForm {
|
||||
dossierName: string;
|
||||
dossierTemplateId: string;
|
||||
dossierStatusId?: string;
|
||||
description?: string;
|
||||
dueDate?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-general-info',
|
||||
@ -59,18 +69,36 @@ import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-doss
|
||||
MatSuffix,
|
||||
IconButtonComponent,
|
||||
NgIf,
|
||||
MatSelectTrigger,
|
||||
],
|
||||
})
|
||||
export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSectionInterface {
|
||||
@Input() dossier: Dossier;
|
||||
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
|
||||
form: UntypedFormGroup;
|
||||
statusPlaceholder: string;
|
||||
readonly dossier = input<Dossier>();
|
||||
hasDueDate: boolean;
|
||||
dossierTemplates: IDossierTemplate[];
|
||||
states: string[];
|
||||
form: FormGroup<AsControl<GeneralInfoForm>> = this._formBuilder.group({
|
||||
dossierName: [null, Validators.required],
|
||||
dossierTemplateId: [null, Validators.required],
|
||||
dossierStatusId: [null],
|
||||
description: [null],
|
||||
dueDate: [null],
|
||||
});
|
||||
initialFormValue: GeneralInfoForm;
|
||||
readonly dossierStatusIdControl = formControlToSignal(this.form.controls.dossierStatusId);
|
||||
readonly dossierTemplateIdControl = formControlToSignal<GeneralInfoForm['dossierTemplateId']>(this.form.controls.dossierTemplateId);
|
||||
readonly states = signal([null]);
|
||||
readonly stateNameAndColor = computed(() => {
|
||||
const nameAndColor = {};
|
||||
this.states().forEach(stateId => {
|
||||
nameAndColor[stateId] = {
|
||||
name: this.#getStateName(stateId, untracked(this.dossierTemplateIdControl)),
|
||||
color: this.#getStateColor(stateId, untracked(this.dossierTemplateIdControl)),
|
||||
};
|
||||
});
|
||||
return nameAndColor;
|
||||
});
|
||||
readonly statePlaceholder = computed(() => this.#statePlaceholder);
|
||||
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
@ -87,18 +115,40 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
) {}
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
) {
|
||||
effect(() => {
|
||||
const shouldBeDisabled = this.#formValue.find(item => item.key === 'dossierTemplateId')?.disabled;
|
||||
if (
|
||||
(this.dossierStatusIdControl() !== this.initialFormValue.dossierStatusId && this.dossierStatusIdControl()) ||
|
||||
shouldBeDisabled
|
||||
) {
|
||||
this.form.controls.dossierTemplateId.disable();
|
||||
} else {
|
||||
this.form.controls.dossierTemplateId.enable();
|
||||
}
|
||||
});
|
||||
|
||||
effect(
|
||||
() => {
|
||||
this.states.set(this.#statesForDossierTemplate);
|
||||
this.#onDossierTemplateChange();
|
||||
},
|
||||
{ allowSignalWrites: true },
|
||||
);
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
for (const key of Object.keys(this.form.getRawValue())) {
|
||||
if (key === 'dueDate') {
|
||||
if (this.hasDueDate !== !!this.dossier.dueDate) {
|
||||
if (this.hasDueDate !== !!this.dossier().dueDate) {
|
||||
return true;
|
||||
}
|
||||
if (this.hasDueDate && !dayjs(this.dossier.dueDate).isSame(dayjs(this.form.get(key).value), 'day')) {
|
||||
if (this.hasDueDate && !dayjs(this.dossier().dueDate).isSame(dayjs(this.form.get(key).value), 'day')) {
|
||||
return true;
|
||||
}
|
||||
} else if (this.dossier[key] !== this.form.get(key).value) {
|
||||
} else if (this.dossier()[key] !== this.form.get(key).value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -114,40 +164,87 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
return this.hasDueDate && this.form.get('dueDate').value === null;
|
||||
}
|
||||
|
||||
get #statusPlaceholder(): string {
|
||||
get #statePlaceholder(): string {
|
||||
return this._translateService.instant(
|
||||
this.states.length === 1
|
||||
isJustOne(this.states())
|
||||
? 'edit-dossier-dialog.general-info.form.dossier-state.no-state-placeholder'
|
||||
: 'dossier-state.placeholder',
|
||||
) as string;
|
||||
}
|
||||
|
||||
get #statesForDossierTemplate() {
|
||||
return [
|
||||
null,
|
||||
...this._dossierStatesMapService
|
||||
.get(this.dossierTemplateIdControl() ?? untracked(this.dossier).dossierTemplateId)
|
||||
.map(s => s.id),
|
||||
];
|
||||
}
|
||||
|
||||
get #formValue(): { key: string; value: string; disabled: boolean }[] {
|
||||
const dossier = untracked(this.dossier);
|
||||
const formFieldWithArchivedCheck = value => ({ value, disabled: !dossier.isActive });
|
||||
const states = untracked(this.states);
|
||||
return [
|
||||
{
|
||||
key: 'dossierName',
|
||||
...formFieldWithArchivedCheck(dossier.dossierName),
|
||||
},
|
||||
{
|
||||
key: 'dossierTemplateId',
|
||||
value: dossier.dossierTemplateId,
|
||||
disabled: this._dossierStatsService.get(dossier.id).hasFiles || !dossier.isActive,
|
||||
},
|
||||
{
|
||||
key: 'dossierStatusId',
|
||||
value: dossier.dossierStatusId,
|
||||
disabled: isJustOne(states) || !dossier.isActive,
|
||||
},
|
||||
{
|
||||
key: 'description',
|
||||
...formFieldWithArchivedCheck(dossier.description),
|
||||
},
|
||||
{
|
||||
key: 'dueDate',
|
||||
...formFieldWithArchivedCheck(dossier.dueDate),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.states = [null, ...this._dossierStatesMapService.get(this.dossier.dossierTemplateId).map(s => s.id)];
|
||||
this.statusPlaceholder = this.#statusPlaceholder;
|
||||
this.#filterInvalidDossierTemplates();
|
||||
this.form = this.#getForm();
|
||||
if (!this.permissionsService.canEditDossier(this.dossier)) {
|
||||
if (isJustOne(this._dossierTemplatesService.all)) {
|
||||
this._loadingService.loadWhile(
|
||||
firstValueFrom(this._dossierTemplatesService.loadOnlyDossierTemplates()).then(async () => {
|
||||
await firstValueFrom(this._dossierStatesService.loadAllForAllTemplates());
|
||||
this.#filterInvalidDossierTemplates();
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
this.#filterInvalidDossierTemplates();
|
||||
}
|
||||
this.#patchFormValue();
|
||||
if (!this.permissionsService.canEditDossier(this.dossier())) {
|
||||
this.form.disable();
|
||||
}
|
||||
this.hasDueDate = !!this.dossier.dueDate;
|
||||
this.hasDueDate = !!this.dossier().dueDate;
|
||||
}
|
||||
|
||||
revert() {
|
||||
this.form.reset({
|
||||
dossierName: this.dossier.dossierName,
|
||||
dossierTemplateId: this.dossier.dossierTemplateId,
|
||||
dossierStatusId: this.dossier.dossierStatusId,
|
||||
description: this.dossier.description,
|
||||
dueDate: this.dossier.dueDate,
|
||||
dossierName: this.dossier().dossierName,
|
||||
dossierTemplateId: this.dossier().dossierTemplateId,
|
||||
dossierStatusId: this.dossier().dossierStatusId,
|
||||
description: this.dossier().description,
|
||||
dueDate: this.dossier().dueDate,
|
||||
});
|
||||
this.hasDueDate = !!this.dossier.dueDate;
|
||||
this.hasDueDate = !!this.dossier().dueDate;
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
}
|
||||
|
||||
async save(): EditDossierSaveResult {
|
||||
const dueDate = dateWithoutTime(dayjs(this.form.get('dueDate').value));
|
||||
const dossier = {
|
||||
...this.dossier,
|
||||
...this.dossier(),
|
||||
dossierName: this.form.get('dossierName').value,
|
||||
description: this.form.get('description').value,
|
||||
dueDate: dueDate.isValid() ? dueDate.toISOString() : undefined,
|
||||
@ -156,9 +253,10 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
} as IDossierRequest;
|
||||
|
||||
const updatedDossier = await firstValueFrom(this._dossiersService.createOrUpdate(dossier));
|
||||
if (updatedDossier && updatedDossier.dossierTemplateId !== this.dossier.dossierTemplateId) {
|
||||
if (updatedDossier && updatedDossier.dossierTemplateId !== this.dossier().dossierTemplateId) {
|
||||
await this._router.navigate([updatedDossier.routerLink]);
|
||||
}
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
return { success: !!updatedDossier };
|
||||
}
|
||||
|
||||
@ -171,14 +269,14 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
requireInput: true,
|
||||
denyText: _('confirmation-dialog.delete-dossier.deny-text'),
|
||||
translateParams: {
|
||||
dossierName: this.dossier.dossierName,
|
||||
dossierName: this.dossier().dossierName,
|
||||
dossiersCount: 1,
|
||||
},
|
||||
};
|
||||
|
||||
this._dialogService.openDialog('confirm', data, async () => {
|
||||
this._loadingService.start();
|
||||
const successful = await this._trashService.deleteDossier(this.dossier);
|
||||
const successful = await this._trashService.deleteDossier(this.dossier());
|
||||
if (successful) {
|
||||
await this.#closeDialogAndRedirectToDossier();
|
||||
}
|
||||
@ -194,7 +292,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
confirmationText: _('confirm-archive-dossier.archive'),
|
||||
denyText: _('confirm-archive-dossier.cancel'),
|
||||
titleColor: TitleColors.WARN,
|
||||
translateParams: { ...this.dossier },
|
||||
translateParams: { ...this.dossier() },
|
||||
checkboxes: [{ value: false, label: _('confirm-archive-dossier.checkbox.documents') }],
|
||||
toastMessage: _('confirm-archive-dossier.toast-error'),
|
||||
};
|
||||
@ -202,10 +300,10 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
this._dialogService.openDialog('confirm', data, async result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._archivedDossiersService.archive([this.dossier]));
|
||||
await firstValueFrom(this._archivedDossiersService.archive([this.dossier()]));
|
||||
this._toaster.success(_('dossier-listing.archive.archive-succeeded'), {
|
||||
params: {
|
||||
dossierName: this.dossier.dossierName,
|
||||
dossierName: this.dossier().dossierName,
|
||||
},
|
||||
});
|
||||
this._editDossierDialogRef.close();
|
||||
@ -214,15 +312,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
});
|
||||
}
|
||||
|
||||
getStateName(stateId: string): string {
|
||||
return (this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId)?.name ||
|
||||
this._translateService.instant('dossier-state.placeholder')) as string;
|
||||
}
|
||||
|
||||
getStateColor(stateId: string): string {
|
||||
return this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId).color;
|
||||
}
|
||||
|
||||
toggleDueDateField() {
|
||||
this.hasDueDate = !this.hasDueDate;
|
||||
if (!this.hasDueDate) {
|
||||
@ -230,46 +319,63 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
}
|
||||
}
|
||||
|
||||
#getStateName(stateId: string, templateId: string): string {
|
||||
return (this._dossierStatesMapService.get(templateId, stateId)?.name ||
|
||||
this._translateService.instant('dossier-state.placeholder')) as string;
|
||||
}
|
||||
|
||||
#getStateColor(stateId: string, templateId: string): string {
|
||||
return this._dossierStatesMapService.get(templateId, stateId)?.color;
|
||||
}
|
||||
|
||||
#patchFormValue() {
|
||||
this.#formValue.forEach(formValue => {
|
||||
this.form.patchValue({ [formValue.key]: formValue.value });
|
||||
if (formValue.disabled) this.form.get(formValue.key).disable();
|
||||
});
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
}
|
||||
|
||||
async #closeDialogAndRedirectToDossier() {
|
||||
this._editDossierDialogRef.close();
|
||||
await this._router.navigate([this.dossier.dossiersListRouterLink]);
|
||||
await this._router.navigate([this.dossier().dossiersListRouterLink]);
|
||||
this._toaster.success(_('edit-dossier-dialog.delete-successful'), {
|
||||
params: {
|
||||
dossierName: this.dossier.dossierName,
|
||||
dossierName: this.dossier().dossierName,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
#getForm(): UntypedFormGroup {
|
||||
const formFieldWithArchivedCheck = value => ({ value, disabled: !this.dossier.isActive });
|
||||
return this._formBuilder.group({
|
||||
dossierName: [formFieldWithArchivedCheck(this.dossier.dossierName), Validators.required],
|
||||
dossierTemplateId: [
|
||||
{
|
||||
value: this.dossier.dossierTemplateId,
|
||||
disabled: this._dossierStatsService.get(this.dossier.id).hasFiles || !this.dossier.isActive,
|
||||
},
|
||||
Validators.required,
|
||||
],
|
||||
dossierStatusId: [
|
||||
{
|
||||
value: this.dossier.dossierStatusId,
|
||||
disabled: this.states.length === 1 || !this.dossier.isActive,
|
||||
},
|
||||
],
|
||||
description: [formFieldWithArchivedCheck(this.dossier.description)],
|
||||
dueDate: [formFieldWithArchivedCheck(this.dossier.dueDate)],
|
||||
});
|
||||
}
|
||||
|
||||
#filterInvalidDossierTemplates() {
|
||||
const dossier = untracked(this.dossier);
|
||||
this.dossierTemplates = this._dossierTemplatesService.all.filter(r => {
|
||||
if (this.dossier?.dossierTemplateId === r.dossierTemplateId) {
|
||||
if (dossier.dossierTemplateId === r.dossierTemplateId) {
|
||||
return true;
|
||||
}
|
||||
const notYetValid = !!r.validFrom && dayjs(r.validFrom).isAfter(dayjs());
|
||||
const notValidAnymore = !!r.validTo && dayjs(r.validTo).add(1, 'd').isBefore(dayjs());
|
||||
this._changeDetectorRef.markForCheck();
|
||||
return !(notYetValid || notValidAnymore) && r.isActive;
|
||||
});
|
||||
}
|
||||
|
||||
#onDossierTemplateChange() {
|
||||
const dossierStateId = untracked(this.dossierStatusIdControl);
|
||||
const dossierTemplateId = untracked(this.dossierTemplateIdControl);
|
||||
if (!!dossierStateId && dossierTemplateId !== this.initialFormValue.dossierTemplateId) {
|
||||
this.form.controls.dossierStatusId.setValue(null);
|
||||
}
|
||||
const dossier = untracked(this.dossier);
|
||||
if (dossierTemplateId === this.initialFormValue.dossierTemplateId) {
|
||||
this.form.controls.dossierStatusId.setValue(dossier.dossierStatusId);
|
||||
}
|
||||
const states = untracked(this.states);
|
||||
if (isJustOne(states) || !dossier.isActive) {
|
||||
this.form.controls.dossierStatusId.disable();
|
||||
} else {
|
||||
this.form.controls.dossierStatusId.enable();
|
||||
}
|
||||
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,24 +78,6 @@
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div *ngIf="isIqserDevMode && form.get('aiCreationEnabled')" class="iqser-input-group">
|
||||
<mat-slide-toggle color="primary" formControlName="aiCreationEnabled">
|
||||
{{ 'add-edit-entity.form.ai-creation-enabled' | translate }}
|
||||
</mat-slide-toggle>
|
||||
</div>
|
||||
|
||||
<div *ngIf="isIqserDevMode && form.get('aiCreationEnabled')?.value && form.get('aiDescription')" class="iqser-input-group w-400">
|
||||
<label translate="add-edit-entity.form.ai-description"></label>
|
||||
<textarea
|
||||
[placeholder]="'add-edit-entity.form.ai-description-placeholder' | translate"
|
||||
formControlName="aiDescription"
|
||||
iqserHasScrollbar
|
||||
name="aiDescription"
|
||||
rows="4"
|
||||
type="text"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div *ngIf="form.get('hasDictionary')" class="iqser-input-group">
|
||||
<mat-slide-toggle color="primary" formControlName="hasDictionary">
|
||||
{{ 'add-edit-entity.form.has-dictionary' | translate }}
|
||||
|
||||
@ -9,7 +9,7 @@ import { MatSelect } from '@angular/material/select';
|
||||
import { MatSlideToggle } from '@angular/material/slide-toggle';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { RoundCheckboxComponent } from '@common-ui/inputs/round-checkbox/round-checkbox.component';
|
||||
import { BaseFormComponent, getConfig, isIqserDevMode, HasScrollbarDirective, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { BaseFormComponent, getConfig, HasScrollbarDirective, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { Dictionary, IDictionary } from '@red/domain';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
@ -62,7 +62,6 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
|
||||
|
||||
colors: Color[];
|
||||
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||
readonly isIqserDevMode = isIqserDevMode();
|
||||
|
||||
constructor(
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
@ -159,8 +158,6 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
|
||||
skippedHexColor: [this.entity?.skippedHexColor, [Validators.required, Validators.minLength(7)]],
|
||||
type: [this.entity?.type],
|
||||
description: [this.entity?.description],
|
||||
aiCreationEnabled: [this.entity?.aiCreationEnabled],
|
||||
aiDescription: [this.entity?.aiDescription],
|
||||
rank: [{ value: this.entity?.rank, disabled: this.#isSystemManaged }, Validators.required],
|
||||
hint: [{ value: !!this.entity?.hint, disabled: this.#isSystemManaged }],
|
||||
hasDictionary: [
|
||||
@ -253,8 +250,6 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
|
||||
dossierTemplateId: this.dossierTemplateId,
|
||||
type: this.form.get('type').value,
|
||||
description: this.form.get('description').value,
|
||||
aiCreationEnabled: this.form.get('aiCreationEnabled').value,
|
||||
aiDescription: this.form.get('aiDescription').value,
|
||||
hint: this.#isHint,
|
||||
rank: this.form.get('rank').value,
|
||||
caseInsensitive: !this.form.get('caseSensitive').value,
|
||||
|
||||
@ -99,6 +99,8 @@
|
||||
.error-message {
|
||||
margin-top: 2px;
|
||||
color: var(--iqser-primary);
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -45,6 +45,13 @@ export class DossierTemplatesService extends EntitiesService<IDossierTemplate, D
|
||||
);
|
||||
}
|
||||
|
||||
loadOnlyDossierTemplates(): Observable<DossierTemplate[]> {
|
||||
return this.getAll().pipe(
|
||||
mapEach(entity => new DossierTemplate(entity)),
|
||||
tap(templates => this.setEntities(templates)),
|
||||
);
|
||||
}
|
||||
|
||||
loadDossierTemplate(dossierTemplateId: string) {
|
||||
return this._getOne([dossierTemplateId], this._defaultModelPath).pipe(
|
||||
map(entity => new DossierTemplate(entity)),
|
||||
|
||||
@ -28,6 +28,7 @@ export class ComponentMappingsService extends EntitiesService<IComponentMapping,
|
||||
{ key: 'name', value: componentMapping.name },
|
||||
{ key: 'encoding', value: componentMapping.encoding },
|
||||
{ key: 'delimiter', value: componentMapping.delimiter },
|
||||
{ key: 'quoteChar', value: componentMapping.quoteChar },
|
||||
];
|
||||
|
||||
if (componentMapping.id) {
|
||||
|
||||
@ -152,8 +152,9 @@ export class DictionaryService extends EntitiesService<IDictionary, Dictionary>
|
||||
.filter(d => d.model['typeId'] && (d.hasDictionary || d.addToDictionaryAction));
|
||||
}
|
||||
|
||||
getRedactTextDictionaries(dossierId: string, dossierDictionaryOnly: boolean): Dictionary[] {
|
||||
return this.#extractDossierLevelTypes(dossierId)
|
||||
getRedactTextDictionaries(dossierId: string, dossierDictionaryOnly: boolean, dossierTemplateId: string): Dictionary[] {
|
||||
const types = dossierDictionaryOnly ? this.#extractDossierLevelTypes(dossierId) : this.getDictionariesOptions(dossierTemplateId);
|
||||
return types
|
||||
.filter(d => d.model['typeId'] && !d.hint && d.addToDictionaryAction && (dossierDictionaryOnly || !d.dossierDictionaryOnly))
|
||||
.sort((a, b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
@ -57,7 +57,7 @@ export class TranslateChartService {
|
||||
translateRoles(config: DonutChartConfig[]): DonutChartConfig[] {
|
||||
return config.map(val => ({
|
||||
...val,
|
||||
label: this._translateService.instant(rolesTranslations[val.label]).toLowerCase(),
|
||||
label: this._translateService.instant(rolesTranslations[val.label], { length: val.value }),
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,7 +4,6 @@ import { ProcessingFileStatus, WorkflowFileStatus } from '@red/domain';
|
||||
export const workflowFileStatusTranslations: { [key in WorkflowFileStatus]: string } = {
|
||||
APPROVED: _('file-status.approved'),
|
||||
NEW: _('file-status.new'),
|
||||
UNASSIGNED: _('file-status.unassigned'),
|
||||
UNDER_APPROVAL: _('file-status.under-approval'),
|
||||
UNDER_REVIEW: _('file-status.under-review'),
|
||||
};
|
||||
|
||||
@ -2,7 +2,7 @@ import { ITrackable } from '@iqser/common-ui';
|
||||
import type { List } from '@iqser/common-ui/lib/utils';
|
||||
import type { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { Dayjs } from 'dayjs';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { AbstractControl } from '@angular/forms';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
|
||||
export function hexToRgb(hex: string) {
|
||||
@ -146,6 +146,6 @@ export function urlFileId() {
|
||||
return fileId.split('?')[0];
|
||||
}
|
||||
|
||||
export function formControlToSignal<T>(control: FormControl<T>) {
|
||||
export function formControlToSignal<T>(control: AbstractControl<T>) {
|
||||
return toSignal(control.valueChanges, { initialValue: control.value });
|
||||
}
|
||||
|
||||
@ -108,6 +108,8 @@
|
||||
"file": "Mapping-Datei",
|
||||
"name": "Mapping-Name",
|
||||
"name-placeholder": "Mapping-Name",
|
||||
"quote-char": "Quotation marker",
|
||||
"quote-char-placeholder": "\"",
|
||||
"version": "Version"
|
||||
}
|
||||
},
|
||||
@ -135,9 +137,9 @@
|
||||
},
|
||||
"add-edit-entity": {
|
||||
"form": {
|
||||
"ai-creation-enabled": "AI Erzeugung aktivieren",
|
||||
"ai-description": "AI Beschreibung",
|
||||
"ai-description-placeholder": "AI Beschreibung eingeben",
|
||||
"ai-creation-enabled": "KI-Erstellung aktivieren",
|
||||
"ai-description": "KI-Beschreibung",
|
||||
"ai-description-placeholder": "KI-Beschreibung eingeben",
|
||||
"case-sensitive": "Groß-/Kleinschreibung beachten",
|
||||
"color": "Farbe {type, select, redaction{Schwärzung} hint{Hinweis} recommendation{Empfehlung} skipped{Ingorierte Schwärzung} ignored{Ignorierter Hinweis} other{}}",
|
||||
"color-placeholder": "#",
|
||||
@ -244,7 +246,7 @@
|
||||
},
|
||||
"type": "Typ",
|
||||
"type-placeholder": "Typ auswählen...",
|
||||
"value": ""
|
||||
"value": "Wert"
|
||||
},
|
||||
"title": "Hinweis hinzufügen"
|
||||
}
|
||||
@ -276,6 +278,9 @@
|
||||
"watermarks": "Wasserzeichen"
|
||||
},
|
||||
"analysis-disabled": "",
|
||||
"annotation": {
|
||||
"pending": "(Analyse steht aus)"
|
||||
},
|
||||
"annotation-actions": {
|
||||
"accept-recommendation": {
|
||||
"label": "Empfehlung annehmen"
|
||||
@ -331,14 +336,14 @@
|
||||
"error": "Rekategorisierung des Bilds fehlgeschlagen: {error}",
|
||||
"success": "Bild wurde einer neuen Kategorie zugeordnet."
|
||||
},
|
||||
"remove-hint": {
|
||||
"error": "Entfernen des Hinweises fehlgeschlagen: {error}",
|
||||
"success": "Hinweis wurde entfernt"
|
||||
},
|
||||
"remove": {
|
||||
"error": "Entfernen der Schwärzung fehlgeschlagen: {error}",
|
||||
"success": "Schwärzung wurde entfernt"
|
||||
},
|
||||
"remove-hint": {
|
||||
"error": "Entfernen des Hinweises fehlgeschlagen: {error}",
|
||||
"success": "Hinweis wurde entfernt"
|
||||
},
|
||||
"undo": {
|
||||
"error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}",
|
||||
"success": "Rücksetzung erfolgreich"
|
||||
@ -351,15 +356,15 @@
|
||||
"remove-highlights": {
|
||||
"label": "Ausgewählte Markierungen entfernen"
|
||||
},
|
||||
"resize": {
|
||||
"label": "Größe ändern"
|
||||
},
|
||||
"resize-accept": {
|
||||
"label": "Neue Größe speichern"
|
||||
},
|
||||
"resize-cancel": {
|
||||
"label": "Größenänderung abbrechen"
|
||||
},
|
||||
"resize": {
|
||||
"label": "Größe ändern"
|
||||
},
|
||||
"see-references": {
|
||||
"label": "Referenzen anzeigen"
|
||||
},
|
||||
@ -376,7 +381,7 @@
|
||||
"removed-manual": "Schwärzung/Hinweis wurde entfernt",
|
||||
"resized": "Schwärzungsbereich wurde geändert"
|
||||
},
|
||||
"annotation-content": "{hasRule, select, true {Regel {matchedRule} trifft zu auf{ruleSymbol}} other {}} {hasReason, select, true {{reason}} other {}} {hasLb, select, true {Rechstgrundlage: {legalBasis}} other {}} {hasOverride, select, true {Entfernt durch manuelles Überschreiben} other {}} {hasSection, select, true {{shouldLower, plural, =0 {I} other {i}}n Abschnitt{sectionSymbol} \"{section}\"} other {}}",
|
||||
"annotation-content": "{hasRule, select, true {Rule {matchedRule} trifft zu:{ruleSymbol}} other {}} {hasReason, select, true {{reason}} other {}} {hasLb, select, true {Legal basis: {legalBasis}} other {}} {hasOverride, select, true {Removed by manual override} other {}} {hasSection, select, true {{shouldLower, plural, =0 {I} other {i}}n Abschnitt{sectionSymbol} \"{section}\"} other {}}",
|
||||
"annotation-engines": {
|
||||
"dictionary": "Basiert auf Wörterbuch",
|
||||
"dossier-dictionary": "Basiert auf Dossier-Wörterbuch",
|
||||
@ -394,9 +399,6 @@
|
||||
"skipped": "Ignorierte Schwärzung",
|
||||
"text-highlight": "Markierung"
|
||||
},
|
||||
"annotation": {
|
||||
"pending": "(Analyse steht aus)"
|
||||
},
|
||||
"annotations": "Annotationen",
|
||||
"archived-dossiers-listing": {
|
||||
"no-data": {
|
||||
@ -775,7 +777,7 @@
|
||||
"revert-changes": "Zurücksetzen",
|
||||
"save-changes": "Änderungen speichern",
|
||||
"search": "Suche...",
|
||||
"select-dictionary": "Wählen Sie oben ein Wörterbuch für den Vergleich aus.",
|
||||
"select-dictionary": "Wählen Sie aus dem Drop-down oben ein Wörterbuch für den Vergleich aus.",
|
||||
"success": {
|
||||
"generic": "Wörterbuch wurde aktualisiert"
|
||||
}
|
||||
@ -1020,13 +1022,13 @@
|
||||
"recent": "Neu ({hours} h)",
|
||||
"unassigned": "Keinem Bearbeiter zugewiesen"
|
||||
},
|
||||
"reanalyse": {
|
||||
"action": "Datei analysieren"
|
||||
},
|
||||
"reanalyse-dossier": {
|
||||
"error": "Einplanung der Dateien für die Reanalyse fehlgeschlagen. Bitte versuchen Sie es noch einmal.",
|
||||
"success": "Dateien für Reanalyse vorgesehen."
|
||||
},
|
||||
"reanalyse": {
|
||||
"action": "Datei analysieren"
|
||||
},
|
||||
"report-download": "",
|
||||
"start-auto-analysis": "Auto-Analyse aktivieren",
|
||||
"stop-auto-analysis": "Auto-Analyse anhalten",
|
||||
@ -1096,6 +1098,14 @@
|
||||
"total-documents": "Dokumente",
|
||||
"total-people": "<strong>{count}</strong> {count, plural, one{Benutzer} other {Benutzer}}"
|
||||
},
|
||||
"dossier-templates": {
|
||||
"label": "Dossier-Vorlagen",
|
||||
"status": {
|
||||
"active": "Aktiv",
|
||||
"inactive": "Inaktiv",
|
||||
"incomplete": "Unvollständig"
|
||||
}
|
||||
},
|
||||
"dossier-templates-listing": {
|
||||
"action": {
|
||||
"clone": "Vorlage klonen",
|
||||
@ -1130,14 +1140,6 @@
|
||||
"title": "{length} {length, plural, one{Dossier-Vorlage} other{Dossier-Vorlagen}}"
|
||||
}
|
||||
},
|
||||
"dossier-templates": {
|
||||
"label": "Dossier-Vorlagen",
|
||||
"status": {
|
||||
"active": "Aktiv",
|
||||
"inactive": "Inaktiv",
|
||||
"incomplete": "Unvollständig"
|
||||
}
|
||||
},
|
||||
"dossier-watermark-selector": {
|
||||
"heading": "Wasserzeichen auf Dokumenten",
|
||||
"no-watermark": "Kein Wasserzeichen in der Dossier-Vorlage verfügbar:<br>Bitten Sie Ihren Admin, eines zu konfigurieren.",
|
||||
@ -1165,15 +1167,15 @@
|
||||
"queued": "Ihr Download wurde zur Warteschlange hinzugefügt.<br><br>Hier finden Sie Ihre generierten Downloads: <a href=\"{downloadHref}\">Meine Downloads<a/>."
|
||||
},
|
||||
"download-type": {
|
||||
"annotated": "Annotierte PDF",
|
||||
"annotated": "Annotiertes PDF",
|
||||
"delta-preview": "Delta-PDF",
|
||||
"flatten": "Verflachte PDF",
|
||||
"flatten": "Verflachtes PDF",
|
||||
"label": "{length} Dokumenten{length, plural, one{typ} other{typen}}",
|
||||
"optimized-preview": "Optimierte Vorschau-PDF",
|
||||
"original": "Optimierte PDF",
|
||||
"optimized-preview": "Optimiertes Vorschau-PDF",
|
||||
"original": "Optimiertes PDF",
|
||||
"preview": "Vorschau-PDF",
|
||||
"redacted": "Geschwärzte PDF",
|
||||
"redacted-only": "Geschwärzte PDF (nur freigegebene Dateien)"
|
||||
"redacted": "Geschwärztes PDF",
|
||||
"redacted-only": "Geschwärztes PDF (nur freigegebene Dateien)"
|
||||
},
|
||||
"downloads-list": {
|
||||
"actions": {
|
||||
@ -1235,10 +1237,10 @@
|
||||
"save": "Speichern",
|
||||
"title": "{label} bearbeiten"
|
||||
},
|
||||
"entries-count": "",
|
||||
"false-positives": "Falsch-Positive",
|
||||
"false-recommendations": "Falsche Empfehlungen",
|
||||
"to-redact": "Schwärzungen"
|
||||
"entries-count": "{count} {count, plural, one{Eintrag} other{Einträge}}",
|
||||
"false-positives": "Falsch-Positive ({count})",
|
||||
"false-recommendations": "Falsche Empfehlungen ({count})",
|
||||
"to-redact": "Einträge ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
@ -1250,7 +1252,7 @@
|
||||
"label": "Dossier-Status",
|
||||
"no-state-placeholder": "Für dieses Dossier ist noch kein Status festgelegt"
|
||||
},
|
||||
"due-date": "Enddatum",
|
||||
"due-date": "Termin",
|
||||
"name": {
|
||||
"label": "Dossier-Name",
|
||||
"placeholder": "Namen eingeben"
|
||||
@ -1262,7 +1264,7 @@
|
||||
"missing-owner": "Bearbeiten des Dossiers nicht möglich: Kein Besitzer zugewiesen.",
|
||||
"nav-items": {
|
||||
"choose-download": "Stellen Sie Ihr Download-Paket zusammen:",
|
||||
"dictionary": "Wörterbücher",
|
||||
"dictionary": "Dossier-Einträge",
|
||||
"dossier-attributes": "Dossier-Attribute",
|
||||
"dossier-dictionary": "Dossier-Einträge",
|
||||
"dossier-info": "Dossier-Info",
|
||||
@ -1278,15 +1280,15 @@
|
||||
"content": {
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "",
|
||||
"extraOptionDescription": "",
|
||||
"extraOptionLabel": "",
|
||||
"extraOptionPlaceholder": "",
|
||||
"label": ""
|
||||
"description": "Bearbeiten Sie die Schwärzung auf einer Reihe von Seiten",
|
||||
"extraOptionDescription": "Minus (-) für Seitenbereich und Komma (,) für Aufzählung.",
|
||||
"extraOptionLabel": "Seiten",
|
||||
"extraOptionPlaceholder": "z. B. 1-20,22,32",
|
||||
"label": "Auf mehreren Seiten ändern"
|
||||
},
|
||||
"only-this-page": {
|
||||
"description": "",
|
||||
"label": ""
|
||||
"description": "Schwärzung nur an dieser Position in diesem Dokument bearbeiten",
|
||||
"label": "Nur auf dieser Seite ändern"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1309,7 +1311,7 @@
|
||||
},
|
||||
"only-here": {
|
||||
"description": "Bearbeiten Sie die Schwärzung nur an dieser Stelle im Dokument.",
|
||||
"label": "Typ nur hier ändern"
|
||||
"label": "Nur hier ändern"
|
||||
}
|
||||
},
|
||||
"reason": "Grund",
|
||||
@ -1348,6 +1350,15 @@
|
||||
"title": "{length} {length, plural, one{Wörterbuch} other{Wörterbücher}}"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"info": {
|
||||
"actions": {
|
||||
"revert": "Zurücksetzen",
|
||||
"save": "Änderungen speichern"
|
||||
},
|
||||
"heading": "Entität bearbeiten"
|
||||
}
|
||||
},
|
||||
"entity-rules-screen": {
|
||||
"error": {
|
||||
"generic": "Fehler: Aktualisierung der Entitätsregeln fehlgeschlagen."
|
||||
@ -1361,28 +1372,19 @@
|
||||
"title": "Entitätsregeln-Editor",
|
||||
"warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} in Regeln gefunden"
|
||||
},
|
||||
"entity": {
|
||||
"info": {
|
||||
"actions": {
|
||||
"revert": "Zurücksetzen",
|
||||
"save": "Änderungen speichern"
|
||||
},
|
||||
"heading": "Entität bearbeiten"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"deleted-entity": {
|
||||
"dossier": {
|
||||
"action": "Zurück zur Übersicht",
|
||||
"label": "Dieses Dossier wurde gelöscht!"
|
||||
},
|
||||
"file-dossier": {
|
||||
"action": "Zurück zur Übersicht",
|
||||
"label": "Das Dossier dieser Datei wurde gelöscht!"
|
||||
},
|
||||
"file": {
|
||||
"action": "Zurück zum Dossier",
|
||||
"label": "Diese Datei wurde gelöscht!"
|
||||
},
|
||||
"file-dossier": {
|
||||
"action": "Zurück zur Übersicht",
|
||||
"label": "Das Dossier dieser Datei wurde gelöscht!"
|
||||
}
|
||||
},
|
||||
"file-preview": {
|
||||
@ -1400,6 +1402,12 @@
|
||||
},
|
||||
"exact-date": "{day}. {month} {year} um {hour}:{minute} Uhr",
|
||||
"file": "Datei",
|
||||
"file-attribute": {
|
||||
"update": {
|
||||
"error": "Aktualisierung des Werts für das Datei-Attribut fehlgeschlagen. Bitte versuchen Sie es noch einmal.",
|
||||
"success": "Der Wert für das Dateiattribut wurde erfolgreich aktualisiert."
|
||||
}
|
||||
},
|
||||
"file-attribute-encoding-types": {
|
||||
"ascii": "ASCII",
|
||||
"iso": "ISO-8859-1",
|
||||
@ -1410,12 +1418,6 @@
|
||||
"number": "Nummer",
|
||||
"text": "Freier Text"
|
||||
},
|
||||
"file-attribute": {
|
||||
"update": {
|
||||
"error": "Aktualisierung des Werts für das Datei-Attribut fehlgeschlagen. Bitte versuchen Sie es noch einmal.",
|
||||
"success": "Der Wert für das Dateiattribut wurde erfolgreich aktualisiert."
|
||||
}
|
||||
},
|
||||
"file-attributes-configurations": {
|
||||
"cancel": "Abbrechen",
|
||||
"form": {
|
||||
@ -1633,15 +1635,6 @@
|
||||
"csv": "Die Datei-Attribute wurden erfolgreich aus der hochgeladenen CSV-Datei importiert."
|
||||
}
|
||||
},
|
||||
"filter-menu": {
|
||||
"filter-options": "Filteroptionen",
|
||||
"filter-types": "Filter",
|
||||
"label": "Filter",
|
||||
"pages-without-annotations": "Nur Seiten ohne Annotationen",
|
||||
"redaction-changes": "Nur Annotationen mit lokalen manuellen Änderungen",
|
||||
"unseen-pages": "Nur Annotationen auf ungesehenen Seiten",
|
||||
"with-comments": "Nur Annotationen mit Kommentaren"
|
||||
},
|
||||
"filter": {
|
||||
"analysis": "Analyse erforderlich",
|
||||
"comment": "Kommentare",
|
||||
@ -1651,6 +1644,15 @@
|
||||
"redaction": "Schwärzung",
|
||||
"updated": "Aktualisiert"
|
||||
},
|
||||
"filter-menu": {
|
||||
"filter-options": "Filteroptionen",
|
||||
"filter-types": "Filter",
|
||||
"label": "Filter",
|
||||
"pages-without-annotations": "Nur Seiten ohne Annotationen",
|
||||
"redaction-changes": "Nur Annotationen mit lokalen manuellen Änderungen",
|
||||
"unseen-pages": "Nur Annotationen auf ungesehenen Seiten",
|
||||
"with-comments": "Nur Annotationen mit Kommentaren"
|
||||
},
|
||||
"filters": {
|
||||
"assigned-people": "Bearbeiter",
|
||||
"documents-status": "Dokumentenstatus",
|
||||
@ -1695,7 +1697,6 @@
|
||||
"form": {
|
||||
"forgot-password": "„Passwort vergessen?“-Link auf Login-Seite anzeigen"
|
||||
},
|
||||
"subtitle": "",
|
||||
"title": "Allgemeine Einstellungen"
|
||||
},
|
||||
"subtitle": "SMTP (Simple Mail Transfer Protocol) ermöglicht es Ihnen, Ihre E-Mails über die angegebenen Servereinstellungen zu versenden.",
|
||||
@ -1794,8 +1795,8 @@
|
||||
},
|
||||
"import-only-for-pages": "Nur für diese Seiten importieren",
|
||||
"range": {
|
||||
"label": "Minus (-) für Spanne und Komma (,) für Aufzählung.",
|
||||
"placeholder": "Beispiel: 1-20,22,32"
|
||||
"label": "Minus (-) für Seitenbereich und Komma (,) für Aufzählung.",
|
||||
"placeholder": "z. B. 1-20,22,32"
|
||||
},
|
||||
"title": "Dokument mit Schwärzungen importieren"
|
||||
},
|
||||
@ -1889,15 +1890,15 @@
|
||||
"legalBasis": "Rechtsgrundlage",
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "",
|
||||
"extraOptionDescription": "",
|
||||
"extraOptionLabel": "",
|
||||
"extraOptionPlaceholder": "",
|
||||
"label": ""
|
||||
"description": "Fügen Sie die Schwärzung auf einer Reihe von Seiten hinzu",
|
||||
"extraOptionDescription": "Minus (-) für Seitenbereich und Komma (,) für Aufzählung.",
|
||||
"extraOptionLabel": "Seiten",
|
||||
"extraOptionPlaceholder": "z. B. 1-20,22,32",
|
||||
"label": "Auf mehreren Seiten anwenden"
|
||||
},
|
||||
"only-this-page": {
|
||||
"description": "",
|
||||
"label": ""
|
||||
"description": "Schwärzung nur an dieser Position in diesem Dokument hinzufügen",
|
||||
"label": "Auf dieser Seite anwenden"
|
||||
}
|
||||
},
|
||||
"reason": "Grund",
|
||||
@ -1934,6 +1935,13 @@
|
||||
"user-promoted-to-approver": "<b>{user}</b> wurde im Dossier <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b> zum Genehmiger ernannt!",
|
||||
"user-removed-as-dossier-member": "<b>{user}</b> wurde als Mitglied von: <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b> entfernt!"
|
||||
},
|
||||
"notifications": {
|
||||
"button-text": "Benachrichtigungen",
|
||||
"deleted-dossier": "Gelöschtes Dossier",
|
||||
"label": "Benachrichtigungen",
|
||||
"mark-all-as-read": "Alle als gelesen markieren",
|
||||
"mark-as": "Als {type, select, read{gelesen} unread{ungelesen} other{}} markieren"
|
||||
},
|
||||
"notifications-screen": {
|
||||
"category": {
|
||||
"email-notifications": "E-Mail-Benachrichtigungen",
|
||||
@ -1947,7 +1955,6 @@
|
||||
"dossier": "Benachrichtigungen zu Dossiers",
|
||||
"other": "Andere Benachrichtigungen"
|
||||
},
|
||||
"options-title": "Wählen Sie aus, bei welchen Aktivitäten Sie benachrichtigt werden möchten",
|
||||
"options": {
|
||||
"ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen werde",
|
||||
"ASSIGN_REVIEWER": "Wenn ich einem Dokument als Prüfer zugewiesen werde",
|
||||
@ -1965,6 +1972,7 @@
|
||||
"USER_PROMOTED_TO_APPROVER": "Wenn ich Genehmiger in einem Dossier werde",
|
||||
"USER_REMOVED_AS_DOSSIER_MEMBER": "Wenn ich die Dossier-Mitgliedschaft verliere"
|
||||
},
|
||||
"options-title": "Wählen Sie aus, bei welchen Aktivitäten Sie benachrichtigt werden möchten",
|
||||
"schedule": {
|
||||
"daily": "Tägliche Zusammenfassung",
|
||||
"instant": "Sofort",
|
||||
@ -1972,13 +1980,6 @@
|
||||
},
|
||||
"title": "Benachrichtigungseinstellungen"
|
||||
},
|
||||
"notifications": {
|
||||
"button-text": "Benachrichtigungen",
|
||||
"deleted-dossier": "Gelöschtes Dossier",
|
||||
"label": "Benachrichtigungen",
|
||||
"mark-all-as-read": "Alle als gelesen markieren",
|
||||
"mark-as": "Als {type, select, read{gelesen} unread{ungelesen} other{}} markieren"
|
||||
},
|
||||
"ocr": {
|
||||
"confirmation-dialog": {
|
||||
"cancel": "Abbrechen",
|
||||
@ -2032,19 +2033,19 @@
|
||||
"left-panel-button": "Panel",
|
||||
"load-all-annotations": "Alle Annotationen laden",
|
||||
"no-outlines-text": "Keine Gliederung verfügbar",
|
||||
"no-signatures-text": "In diesem Dokument gibt es keine Unterschriftenfelder",
|
||||
"no-signatures-text": "Dieses Dokument enthält keine Unterschriftenfelder.",
|
||||
"outline-multi-select": "Bearbeiten",
|
||||
"outlines-panel-button": "Gliederung",
|
||||
"pan-tool-button": "Verschieben",
|
||||
"rectangle-tool-button": "Bereichsschwärzung",
|
||||
"rectangle-tool-button": "Bereich schwärzen",
|
||||
"rotate-left-button": "Seite nach links drehen",
|
||||
"rotate-right-button": "Seite nach rechts drehen",
|
||||
"select-tool-button": "Auswählen",
|
||||
"signature-panel-button": "Unterschriften",
|
||||
"thumbnails-panel-button": "Miniaturansicht",
|
||||
"toggle-layers": "Layout-Raster {active, select, true{deaktivieren} false{aktivieren} other{}}",
|
||||
"toggle-readable-redactions": "Schwärzungen {active, select, true{wie im finalen Dokument} false{in Vorschau-Farbe} other{}} anzeigen",
|
||||
"toggle-tooltips": "Tooltips zu Annotationen {active, select, true{deaktivieren} false{aktivieren} other{}}",
|
||||
"toggle-readable-redactions": "Schwärzungen {active, select, true{wie im finalen Dokument} false{in Preview-Farbe anzeigen} other{}}",
|
||||
"toggle-tooltips": "Tooltips für Annotationen {active, select, true{deaktivieren} false{aktivieren} other{}}",
|
||||
"zoom-in-button": "Vergrößern",
|
||||
"zoom-out-button": "Verkleinern"
|
||||
},
|
||||
@ -2090,16 +2091,16 @@
|
||||
"warnings-label": "Dialoge und Meldungen",
|
||||
"warnings-subtitle": "„Nicht mehr anzeigen“-Optionen"
|
||||
},
|
||||
"processing": {
|
||||
"basic": "Verarbeitung läuft",
|
||||
"ocr": "OCR"
|
||||
},
|
||||
"processing-status": {
|
||||
"ocr": "OCR",
|
||||
"pending": "Ausstehend",
|
||||
"processed": "Verarbeitet",
|
||||
"processing": "Verarbeitung läuft"
|
||||
},
|
||||
"processing": {
|
||||
"basic": "Verarbeitung läuft",
|
||||
"ocr": "OCR"
|
||||
},
|
||||
"readonly": "Lesemodus",
|
||||
"readonly-archived": "Lesemodus (archiviert)",
|
||||
"redact-text": {
|
||||
@ -2134,7 +2135,7 @@
|
||||
"type": "Typ",
|
||||
"type-placeholder": "Typ auswählen...",
|
||||
"unchanged": "Ungeändert",
|
||||
"value": ""
|
||||
"value": "Wert"
|
||||
},
|
||||
"title": "Text schwärzen"
|
||||
}
|
||||
@ -2184,15 +2185,15 @@
|
||||
"content": {
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "",
|
||||
"extraOptionDescription": "",
|
||||
"extraOptionLabel": "",
|
||||
"extraOptionPlaceholder": "",
|
||||
"label": ""
|
||||
"description": "Entfernen Sie die Schwärzung auf einer Reihe von Seiten",
|
||||
"extraOptionDescription": "Minus (-) für Seitenbereich und Komma (,) für Aufzählung.",
|
||||
"extraOptionLabel": "Seiten",
|
||||
"extraOptionPlaceholder": "z. B. 1-20,22,32",
|
||||
"label": "Auf mehreren Seiten entfernen"
|
||||
},
|
||||
"only-this-page": {
|
||||
"description": "",
|
||||
"label": ""
|
||||
"description": "Schwärzung nur an dieser Stelle in diesem Dokument entfernen",
|
||||
"label": "Nur auf dieser Seite entfernen"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2217,12 +2218,12 @@
|
||||
"false-positive": {
|
||||
"description": "Markieren Sie die Schwärzung als falsch-positiv. Der Begriff wird in diesem Dossier nicht geschwärzt, wenn er im gleichen Kontext vorkommt.",
|
||||
"description-bulk": "Markieren Sie die Schwärzungen als falsch-positiv. Die Begriffe werden in diesem Dossier nicht geschwärzt, wenn sie im gleichen Kontext vorkommen.",
|
||||
"extraOptionDescription": "Um diese Aktion rückgängig machen zu können, benötigen Sie Zugriff auf die Dossier-Vorlage. Als regulärer Benutzer können sie die Aktion nur für dieses Dossier rückgängig machen.",
|
||||
"extraOptionDescription": "Um diese Aktion rückgängig machen zu können, benötigen Sie Zugriff auf die Dossier-Vorlage. Als regulärer Benutzer können Sie die Aktion nur für dieses Dossier rückgängig machen.",
|
||||
"extraOptionLabel": "In alle aktiven und zukünftigen Dossiers übernehmen",
|
||||
"label": "In diesem Kontext aus Dossier entfernen"
|
||||
},
|
||||
"in-document": {
|
||||
"description": "{isImage, select, image{Das Bild} other{der Begriff}} wird auf keiner Seite dieses Dokuments automatisch geschwärzt.",
|
||||
"description": "{isImage, select, image{Das Bild} other{Der Begriff}} wird auf keiner Seite dieses Dokuments automatisch geschwärzt.",
|
||||
"label": "Aus Dokument entfernen"
|
||||
},
|
||||
"in-dossier": {
|
||||
@ -2367,6 +2368,12 @@
|
||||
"red-user-admin": "Benutzeradmin",
|
||||
"regular": "regulärer Benutzer"
|
||||
},
|
||||
"search": {
|
||||
"active-dossiers": "Dokumente in aktiven Dossiers",
|
||||
"all-dossiers": "Alle Dokumente",
|
||||
"placeholder": "Dokumente durchsuchen...",
|
||||
"this-dossier": "In diesem Dossier"
|
||||
},
|
||||
"search-screen": {
|
||||
"cols": {
|
||||
"assignee": "Bearbeiter",
|
||||
@ -2390,12 +2397,6 @@
|
||||
"no-match": "Der Suchbegriff wurde in keinem der Dokumente gefunden.",
|
||||
"table-header": "{length} {length, plural, one{Suchergebnis} other{Suchergebnisse}}"
|
||||
},
|
||||
"search": {
|
||||
"active-dossiers": "Dokumente in aktiven Dossiers",
|
||||
"all-dossiers": "Alle Dokumente",
|
||||
"placeholder": "Dokumente durchsuchen...",
|
||||
"this-dossier": "In diesem Dossier"
|
||||
},
|
||||
"seconds": "Sekunden",
|
||||
"size": "Größe",
|
||||
"smtp-auth-config": {
|
||||
@ -2482,7 +2483,7 @@
|
||||
"time-to-restore": "Verbleibende Zeit für Wiederherstellung"
|
||||
},
|
||||
"table-header": {
|
||||
"title": "{length} {length, plural, one{gelöschtes Dossier} other{gelöschte Dossiers}}"
|
||||
"title": "{length} {length, plural, one{gelöschtes Element} other{gelöschte Elemente}}"
|
||||
}
|
||||
},
|
||||
"type": "Typ",
|
||||
@ -2617,7 +2618,7 @@
|
||||
},
|
||||
"pagination": {
|
||||
"landscape": "Querformat",
|
||||
"portrait": "Hoch-"
|
||||
"portrait": "Hochformat"
|
||||
}
|
||||
},
|
||||
"watermarks-listing": {
|
||||
@ -2640,7 +2641,7 @@
|
||||
"table-header": {
|
||||
"title": "Wasserzeichen"
|
||||
},
|
||||
"watermark-is-used": "Dieses Wasserzeichen wird bereits verwendet. Möchten Sie es dennocht löschen?"
|
||||
"watermark-is-used": "Dieses Wasserzeichen wird bereits verwendet. Möchten Sie es dennoch löschen?"
|
||||
},
|
||||
"workflow": {
|
||||
"selection": {
|
||||
|
||||
@ -102,6 +102,8 @@
|
||||
},
|
||||
"disabled-file-options": "",
|
||||
"form": {
|
||||
"quote-char": "Quotation marker",
|
||||
"quote-char-placeholder": "\"",
|
||||
"delimiter": "",
|
||||
"delimiter-placeholder": "",
|
||||
"encoding-type": "",
|
||||
@ -112,6 +114,9 @@
|
||||
}
|
||||
},
|
||||
"add-edit-dossier-attribute": {
|
||||
"error": {
|
||||
"generic": "Failed to save attribute."
|
||||
},
|
||||
"form": {
|
||||
"label": "Attribute name",
|
||||
"label-placeholder": "Enter name",
|
||||
@ -135,9 +140,6 @@
|
||||
},
|
||||
"add-edit-entity": {
|
||||
"form": {
|
||||
"ai-creation-enabled": "Enable AI creation",
|
||||
"ai-description": "AI Description",
|
||||
"ai-description-placeholder": "Enter AI description",
|
||||
"case-sensitive": "Case-sensitive",
|
||||
"color": "{type, select, redaction{Redaction} hint{Hint} recommendation{Recommendation} skipped{Skipped redaction} ignored{Ignored hint} other{}} color",
|
||||
"color-placeholder": "#",
|
||||
@ -775,7 +777,7 @@
|
||||
"revert-changes": "Revert",
|
||||
"save-changes": "Save changes",
|
||||
"search": "Search entries...",
|
||||
"select-dictionary": "Select a dictionary for comparison above.",
|
||||
"select-dictionary": "Select a dictionary for comparison from the drop-down.",
|
||||
"success": {
|
||||
"generic": "Dictionary updated"
|
||||
}
|
||||
@ -1060,7 +1062,7 @@
|
||||
"dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}"
|
||||
},
|
||||
"error": {
|
||||
"conflict": "Dossier state with this name already exists"
|
||||
"conflict": "Dossier state with this name already exists."
|
||||
},
|
||||
"no-data": {
|
||||
"title": "There are no dossier states."
|
||||
@ -1236,9 +1238,9 @@
|
||||
"title": "Edit {label}"
|
||||
},
|
||||
"entries-count": "{count} {count, plural, one{entry} other{entries}}",
|
||||
"false-positives": "False positives",
|
||||
"false-recommendations": "False recommendations",
|
||||
"to-redact": "To redact"
|
||||
"false-positives": "False positives ({count})",
|
||||
"false-recommendations": "False recommendations ({count})",
|
||||
"to-redact": "Entries ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
@ -1262,7 +1264,7 @@
|
||||
"missing-owner": "Editing the dossier not possible: No owner assigned.",
|
||||
"nav-items": {
|
||||
"choose-download": "Select the documents for your download:",
|
||||
"dictionary": "Dictionaries",
|
||||
"dictionary": "Dossier entries",
|
||||
"dossier-attributes": "Dossier attributes",
|
||||
"dossier-dictionary": "Dossier entries",
|
||||
"dossier-info": "Dossier info",
|
||||
@ -1278,11 +1280,11 @@
|
||||
"content": {
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "Edit redaction on following range of pages",
|
||||
"description": "Edit redaction on a range of pages",
|
||||
"extraOptionDescription": "Minus(-) for range and comma(,) for enumeration",
|
||||
"extraOptionLabel": "Range",
|
||||
"extraOptionLabel": "Pages",
|
||||
"extraOptionPlaceholder": "e.g. 1-20,22,32",
|
||||
"label": "Change on all pages"
|
||||
"label": "Change on multiple pages"
|
||||
},
|
||||
"only-this-page": {
|
||||
"description": "Edit redaction only at this position in this document",
|
||||
@ -1304,12 +1306,12 @@
|
||||
"legal-basis": "Legal basis",
|
||||
"options": {
|
||||
"in-document": {
|
||||
"description": "Edit redaction of all linked occurrences of the term in this document.",
|
||||
"description": "Edit redaction of all instances of the term in this document.",
|
||||
"label": "Change in document"
|
||||
},
|
||||
"only-here": {
|
||||
"description": "Edit redaction only at this position in this document.",
|
||||
"label": "Change type only here"
|
||||
"label": "Change only here"
|
||||
}
|
||||
},
|
||||
"reason": "Reason",
|
||||
@ -1695,7 +1697,6 @@
|
||||
"form": {
|
||||
"forgot-password": "Show 'Forgot password' link on login screen"
|
||||
},
|
||||
"subtitle": " ",
|
||||
"title": "General configurations"
|
||||
},
|
||||
"subtitle": "SMTP (Simple Mail Transfer Protocol) enables you to send your e-mails through the specified server settings.",
|
||||
@ -1889,9 +1890,9 @@
|
||||
"legalBasis": "Legal basis",
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "Add redaction on following range of pages",
|
||||
"description": "Add redaction on a range of pages",
|
||||
"extraOptionDescription": "Minus(-) for range and comma(,) for enumeration",
|
||||
"extraOptionLabel": "Range",
|
||||
"extraOptionLabel": "Pages",
|
||||
"extraOptionPlaceholder": "e.g. 1-20,22,32",
|
||||
"label": "Apply on multiple pages"
|
||||
},
|
||||
@ -2115,7 +2116,7 @@
|
||||
"legal-basis": "Legal basis",
|
||||
"options": {
|
||||
"in-document": {
|
||||
"description": "Add redaction for each occurrence of the term in this document.",
|
||||
"description": "Add redaction for each instance of the term in this document.",
|
||||
"label": "Redact in document"
|
||||
},
|
||||
"in-dossier": {
|
||||
@ -2184,11 +2185,11 @@
|
||||
"content": {
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "Remove redaction on following range of pages",
|
||||
"description": "Remove redaction on a range of pages",
|
||||
"extraOptionDescription": "Minus(-) for range and comma(,) for enumeration",
|
||||
"extraOptionLabel": "Range",
|
||||
"extraOptionLabel": "Pages",
|
||||
"extraOptionPlaceholder": "e.g. 1-20,22,32",
|
||||
"label": "Remove on all pages"
|
||||
"label": "Remove on multiple pages"
|
||||
},
|
||||
"only-this-page": {
|
||||
"description": "Remove redaction only at this position in this document",
|
||||
@ -2222,7 +2223,7 @@
|
||||
"label": "Remove from dossier in this context"
|
||||
},
|
||||
"in-document": {
|
||||
"description": "Do not auto-redact the selected {isImage, select, image{image} other{term}} in any pages of this document.",
|
||||
"description": "Do not auto-redact the selected {isImage, select, image{image} other{term}} on any page of this document.",
|
||||
"label": "Remove from document"
|
||||
},
|
||||
"in-dossier": {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@
|
||||
},
|
||||
"content": {
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Add remarks or mentions...",
|
||||
"comment-placeholder": "Add remarks or notes...",
|
||||
"selected-text": "Selected text:",
|
||||
"type": "Type",
|
||||
"type-placeholder": "Select type..."
|
||||
@ -100,7 +100,7 @@
|
||||
"dialog": {
|
||||
"title": "{type, select, add{Add new} edit{Edit} other{}} component mapping"
|
||||
},
|
||||
"disabled-file-options": "Re-upload mapping file to change",
|
||||
"disabled-file-options": "Upload updated mapping file",
|
||||
"form": {
|
||||
"delimiter": "CSV delimiter",
|
||||
"delimiter-placeholder": "CSV delimiter",
|
||||
@ -112,6 +112,9 @@
|
||||
}
|
||||
},
|
||||
"add-edit-dossier-attribute": {
|
||||
"error": {
|
||||
"generic": "Failed to save attribute!"
|
||||
},
|
||||
"form": {
|
||||
"label": "Attribute name",
|
||||
"label-placeholder": "Enter name",
|
||||
@ -135,9 +138,6 @@
|
||||
},
|
||||
"add-edit-entity": {
|
||||
"form": {
|
||||
"ai-creation-enabled": "Enable AI creation",
|
||||
"ai-description": "AI Description",
|
||||
"ai-description-placeholder": "Enter AI description",
|
||||
"case-sensitive": "Case-sensitive",
|
||||
"color": "{type, select, redaction{Annotation} hint{Hint} recommendation{Recommendation} skipped{Skipped annotation} ignored{Ignored hint} other{}} Color",
|
||||
"color-placeholder": "#",
|
||||
@ -230,11 +230,11 @@
|
||||
},
|
||||
"content": {
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Add remarks or mentions...",
|
||||
"comment-placeholder": "Add remarks or notes...",
|
||||
"options": {
|
||||
"in-dossier": {
|
||||
"description": "Add hint in every document in {dossierName}.",
|
||||
"extraOptionLabel": "Apply to all dossiers",
|
||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||
"label": "Add hint in dossier"
|
||||
},
|
||||
"only-here": {
|
||||
@ -981,7 +981,7 @@
|
||||
}
|
||||
},
|
||||
"download-file": "Download",
|
||||
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
||||
"download-file-disabled": "To download, ensure you are an approver in the dossier, and the {count, plural, one{file has undergone} other{files have undergone}} initial processing.",
|
||||
"file-listing": {
|
||||
"file-entry": {
|
||||
"file-error": "Re-processing required",
|
||||
@ -1060,13 +1060,13 @@
|
||||
"dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}"
|
||||
},
|
||||
"error": {
|
||||
"conflict": "Dossier state with this name already exists!"
|
||||
"conflict": "Dossier state with this name already exists."
|
||||
},
|
||||
"no-data": {
|
||||
"title": "There are no dossier states."
|
||||
},
|
||||
"no-match": {
|
||||
"title": "No dossier states match your current filters."
|
||||
"title": "No dossier state matches the currently selected filters."
|
||||
},
|
||||
"search": "Search...",
|
||||
"table-col-names": {
|
||||
@ -1141,7 +1141,7 @@
|
||||
"dossier-watermark-selector": {
|
||||
"heading": "Watermarks on documents",
|
||||
"no-watermark": "There is no watermark defined for the dossier template.<br>Contact your app admin to define one.",
|
||||
"preview": "Watermark application on preview documents",
|
||||
"preview": "Watermark on preview documents",
|
||||
"watermark": "Watermark application on documents"
|
||||
},
|
||||
"dossiers-type-switch": {
|
||||
@ -1153,7 +1153,7 @@
|
||||
"save": "Download"
|
||||
},
|
||||
"form": {
|
||||
"redaction-preview-color": "Redaction preview color",
|
||||
"redaction-preview-color": "Preview color",
|
||||
"redaction-preview-color-placeholder": "#000000"
|
||||
},
|
||||
"header": "Download options",
|
||||
@ -1161,7 +1161,7 @@
|
||||
},
|
||||
"download-includes": "Choose what is included at download:",
|
||||
"download-status": {
|
||||
"error": "The download preparation failed, please recheck the selected files and download option settings.",
|
||||
"error": "<strong>Download generation failed</strong><br><br>Please check the selected files and download option settings.",
|
||||
"queued": "Your download has been queued, you can find all your requested downloads here: <a href=\"{downloadHref}\">My downloads<a/>."
|
||||
},
|
||||
"download-type": {
|
||||
@ -1236,9 +1236,9 @@
|
||||
"title": ""
|
||||
},
|
||||
"entries-count": "{count} {count, plural, one{entry} other{entries}}",
|
||||
"false-positives": "False positives",
|
||||
"false-recommendations": "False recommendations",
|
||||
"to-redact": "To redact"
|
||||
"false-positives": "False positives ({count})",
|
||||
"false-recommendations": "False recommendations ({count})",
|
||||
"to-redact": "To redact ({count})"
|
||||
},
|
||||
"general-info": {
|
||||
"form": {
|
||||
@ -1259,7 +1259,7 @@
|
||||
}
|
||||
},
|
||||
"header": "Edit {dossierName}",
|
||||
"missing-owner": "You cannot edit the dossier because the owner is missing!",
|
||||
"missing-owner": "Editing the dossier not possible: No owner assigned.",
|
||||
"nav-items": {
|
||||
"choose-download": "Choose what is included at download:",
|
||||
"dictionary": "Dictionary",
|
||||
@ -1300,12 +1300,12 @@
|
||||
},
|
||||
"content": {
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Add remarks or mentions...",
|
||||
"comment-placeholder": "Add remarks or notes...",
|
||||
"legal-basis": "",
|
||||
"options": {
|
||||
"in-document": {
|
||||
"description": "",
|
||||
"label": ""
|
||||
"label": "In Dokument ändern"
|
||||
},
|
||||
"only-here": {
|
||||
"description": "",
|
||||
@ -1350,13 +1350,13 @@
|
||||
},
|
||||
"entity-rules-screen": {
|
||||
"error": {
|
||||
"generic": "Something went wrong... Entity rules update failed!"
|
||||
"generic": "Error: Entity rules update failed."
|
||||
},
|
||||
"errors-found": "{errors, plural, one{An error} other{{errors} errors}} found in rules",
|
||||
"revert-changes": "Revert",
|
||||
"save-changes": "Save changes",
|
||||
"success": {
|
||||
"generic": "Entity rules updated!"
|
||||
"generic": "Entity rules updated."
|
||||
},
|
||||
"title": "Entity rule editor",
|
||||
"warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules"
|
||||
@ -1458,7 +1458,7 @@
|
||||
"none": "None"
|
||||
},
|
||||
"save": {
|
||||
"error": "Failed to create file attributes!",
|
||||
"error": "Failed to create file attributes.",
|
||||
"label": "Save attributes",
|
||||
"success": "{count} file {count, plural, one{attribute} other{attributes}} created successfully!"
|
||||
},
|
||||
@ -1551,7 +1551,7 @@
|
||||
"redacted": "Preview",
|
||||
"redacted-tooltip": "Component preview shows only annotations. Consider this a preview for the final version. This view is only available if the file has no pending changes & doesn't require a reanalysis",
|
||||
"standard": "Standard",
|
||||
"standard-tooltip": "Standard workload view shows all hints, annotations & recommendations. This view allows editing.",
|
||||
"standard-tooltip": "Standard shows all annotation types and allows for editing.",
|
||||
"tabs": {
|
||||
"annotations": {
|
||||
"hide-skipped": "",
|
||||
@ -1695,7 +1695,6 @@
|
||||
"form": {
|
||||
"forgot-password": "Show 'Forgot password' link on login screen"
|
||||
},
|
||||
"subtitle": " ",
|
||||
"title": "General configurations"
|
||||
},
|
||||
"subtitle": "SMTP (Simple Mail Transfer Protocol) enables you to send your e-mails through the specified server settings.",
|
||||
@ -1745,7 +1744,7 @@
|
||||
"label": "Convert on all pages"
|
||||
},
|
||||
"this-page": {
|
||||
"description": "The earmarks in the selected HEX color will be converted only on the current page in view.",
|
||||
"description": "The earmarks in the selected HEX color will be converted only on the currently viewed page.",
|
||||
"label": "Convert only on this page"
|
||||
}
|
||||
},
|
||||
@ -1874,8 +1873,8 @@
|
||||
}
|
||||
},
|
||||
"license-information": "License Information",
|
||||
"load-all-annotations-success": "All annotations were loaded and are now visible in the document thumbnails",
|
||||
"load-all-annotations-threshold-exceeded": "Caution, document contains more than {threshold} annotations. Drawing all annotations will affect the performance of the app and could even block it. Do you want to proceed?",
|
||||
"load-all-annotations-success": "All annotations were loaded and are now visible in the document thumbnails.",
|
||||
"load-all-annotations-threshold-exceeded": "<strong>Alert:</strong> Document contains more than {threshold} annotations. Drawing all annotations may cause the app to slow down or freeze. Do you still want to continue?",
|
||||
"load-all-annotations-threshold-exceeded-checkbox": "Do not show this warning again",
|
||||
"loading": "Loading",
|
||||
"manual-annotation": {
|
||||
@ -1889,14 +1888,14 @@
|
||||
"legalBasis": "Legal Basis",
|
||||
"options": {
|
||||
"multiple-pages": {
|
||||
"description": "Edit redaction the range of pages",
|
||||
"description": "Edit annotation the range of pages",
|
||||
"extraOptionDescription": "Minus(-) for range and comma(,) for enumeration",
|
||||
"extraOptionLabel": "Range",
|
||||
"extraOptionPlaceholder": "e.g. 1-20,22,32",
|
||||
"label": "Apply on multiple pages"
|
||||
},
|
||||
"only-this-page": {
|
||||
"description": "Edit redaction only at this position in this document",
|
||||
"description": "Edit annotation only at this position in this document",
|
||||
"label": "Apply only on this page"
|
||||
}
|
||||
},
|
||||
@ -1919,16 +1918,16 @@
|
||||
"minutes": "minutes",
|
||||
"no-active-license": "Invalid or corrupt license – Please contact your administrator",
|
||||
"notification": {
|
||||
"assign-approver": "You have been assigned to <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> in dossier: <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"assign-reviewer": "You have been assigned to <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> in dossier: <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"assign-approver": "You have been assigned as approver for a document. <br>Document: <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> <br> Dossier: <b>{dossierHref, select, null{{dossierName}} other{{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}}}</b>",
|
||||
"assign-reviewer": "You have been assigned as reviewer for a document. <br>Document: <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> <br>\nDossier: <b>{dossierHref, select, null{{dossierName}} other{{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}}}</b>",
|
||||
"document-approved": " <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> has been moved to Done!",
|
||||
"dossier-deleted": "Dossier: <b>{dossierName}</b> has been deleted!",
|
||||
"dossier-owner-deleted": "The owner of dossier: <b>{dossierName}</b> has been deleted!",
|
||||
"dossier-owner-removed": "You have been removed as dossier owner from <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"dossier-owner-set": "You are now the dossier owner of <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"dossier-owner-set": "You are now the dossier owner of <b>{dossierHref, select, null{{dossierName}} other\n{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"download-ready": "Your <b><a href=\"{downloadHref}\", target=\"_self\">download</a></b> is ready!",
|
||||
"no-data": "You currently have no notifications",
|
||||
"unassigned-from-file": "You have been unassigned from <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> in dossier: <b>{dossierHref, select, null{{dossierName}} other{{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}}}</b>!",
|
||||
"unassigned-from-file": "You have been unassigned from a document. <br>Document: <b>{fileHref, select, null{{fileName}} other{<a href=\"{fileHref}\" target=\"_blank\">{fileName}</a>}}</b> <br>Dossier: <b>{dossierHref, select, null{{dossierName}} other{{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>\n}}}}</b>",
|
||||
"user-becomes-dossier-member": "You have been added to dossier: <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"user-demoted-to-reviewer": "You have been demoted to reviewer in dossier: <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
"user-promoted-to-approver": "You have been promoted to approver in dossier: <b>{dossierHref, select, null{{dossierName}} other{<a href=\"{dossierHref}\" target=\"_blank\">{dossierName}</a>}}</b>!",
|
||||
@ -1982,12 +1981,12 @@
|
||||
"ocr": {
|
||||
"confirmation-dialog": {
|
||||
"cancel": "Cancel",
|
||||
"question": "Manual changes could get lost if OCR makes changes at those positions. Are you sure you want to proceed?",
|
||||
"question": "Manual changes may be overwritten if the OCR makes changes at the respective positions. Do you still want to proceed?",
|
||||
"title": "Warning: the file has manual adjustments!"
|
||||
}
|
||||
},
|
||||
"overwrite-files-dialog": {
|
||||
"archive-question": "Dossier is not empty, so files might overlap with the contents of the archive you are uploading. Choose how to proceed in case of duplicates:",
|
||||
"archive-question": "Dossier already contains files. Files might overlap with the contents of the folder you are uploading. Select how to handle duplicates:",
|
||||
"archive-title": "Uploading a ZIP archive",
|
||||
"file-question": "<b>{filename}</b> already exists. Choose how to proceed:",
|
||||
"file-title": "File already exists!",
|
||||
@ -1996,16 +1995,16 @@
|
||||
"cancel": "Cancel upload",
|
||||
"current-files": "Apply to current file",
|
||||
"full-overwrite": {
|
||||
"description": "Manual changes done to the existing file will be removed and you are able to start over.",
|
||||
"description": "Remove all manual changes made to the file, and start reviewing a freshly processed file.",
|
||||
"label": "Overwrite and start over"
|
||||
},
|
||||
"partial-overwrite": {
|
||||
"description": "Manual changes are kept only if the affected annotations are still at the same position in the file. Some annotations could be misplaced if the content of the file changed.",
|
||||
"description": "Keep manual changes if the affected redactions remain in their original positions. Some redactions could be misplaced if the content has changed.",
|
||||
"label": "Overwrite and keep manual changes"
|
||||
},
|
||||
"proceed": "Proceed",
|
||||
"skip": {
|
||||
"description": "The upload will be skipped and the existing file will not be replaced.",
|
||||
"description": "Skip the file upload and do not replace the existing file.",
|
||||
"label": "Keep the existing file and do not overwrite"
|
||||
}
|
||||
},
|
||||
@ -2079,14 +2078,14 @@
|
||||
},
|
||||
"form": {
|
||||
"auto-expand-filters-on-action": "Auto expand filters on my actions",
|
||||
"help-mode-dialog": "Help Mode Dialog",
|
||||
"load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview",
|
||||
"help-mode-dialog": "Help mode activation dialog",
|
||||
"load-all-annotations-warning": "Warning regarding simultaneous loading of all annotations in thumbnails",
|
||||
"overwrite-file-option": "Preferred action when re-uploading an already existing file",
|
||||
"table-extraction-type": "Table extraction type"
|
||||
},
|
||||
"label": "Preferences",
|
||||
"title": "Edit preferences",
|
||||
"warnings-description": "Selecting the 'Do not show this message again' checkbox will skip the warning dialog the next time you trigger it.",
|
||||
"warnings-description": "Selecting the 'Do not show this message again' checkbox will skip the dialog the next time you trigger it.",
|
||||
"warnings-label": "Prompts and dialogs",
|
||||
"warnings-subtitle": "Do not show again options"
|
||||
},
|
||||
@ -2110,7 +2109,7 @@
|
||||
},
|
||||
"content": {
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Add remarks or mentions...",
|
||||
"comment-placeholder": "Add remarks or notes...",
|
||||
"edit-text": "",
|
||||
"legal-basis": "Legal basis",
|
||||
"options": {
|
||||
@ -2120,7 +2119,7 @@
|
||||
},
|
||||
"in-dossier": {
|
||||
"description": "Add redaction in every document in {dossierName}.",
|
||||
"extraOptionLabel": "Apply to all dossiers",
|
||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||
"label": "Redact in dossier"
|
||||
},
|
||||
"only-here": {
|
||||
@ -2149,27 +2148,27 @@
|
||||
},
|
||||
"content": {
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Add remarks or mentions...",
|
||||
"comment-placeholder": "Add remarks or notes...",
|
||||
"list-item": "{text}",
|
||||
"list-item-false-positive": "''{text}'' in the context: ''{context}''",
|
||||
"options": {
|
||||
"false-positive": {
|
||||
"description": "''{value}'' is not a ''{type}'' in this context: ''{context}''.",
|
||||
"description-bulk": "The selected items should not be annotated in their respective contexts.",
|
||||
"label": "False positive"
|
||||
"description": "Mark this redaction as a false-positive. The term will not be redacted in this dossier if it occurs in the same context.",
|
||||
"description-bulk": "Mark this redaction as a false-positive. The term will not be redacted in this dossier if it occurs in the same context.",
|
||||
"label": "Remove from dossier in this context"
|
||||
},
|
||||
"in-document": {
|
||||
"description": "",
|
||||
"label": ""
|
||||
"label": "Aus Dokument entfernen"
|
||||
},
|
||||
"in-dossier": {
|
||||
"description": "Do not annotate ''{value}'' as ''{type}'' in any dossier.",
|
||||
"description": "Do not annotate the term in any dossier.",
|
||||
"description-bulk": "Do not annotate the selected terms as their respective types in any dossier.",
|
||||
"label": "No longer annotate as ''{type}''",
|
||||
"label-bulk": "No longer annotate in any dossier"
|
||||
"label-bulk": "Do not annotate as <i>{type}</i>"
|
||||
},
|
||||
"only-here": {
|
||||
"description": "Do not annotate ''{value}'' at this position in the current document.",
|
||||
"description": "Do not annotate the term at this position in this document.",
|
||||
"description-bulk": "Do not annotate the selected terms at this position in the current document.",
|
||||
"label": "Remove here"
|
||||
}
|
||||
@ -2206,35 +2205,35 @@
|
||||
},
|
||||
"content": {
|
||||
"comment": "Comment",
|
||||
"comment-placeholder": "Add remarks or mentions...",
|
||||
"comment-placeholder": "Add remarks or notes...",
|
||||
"options": {
|
||||
"do-not-recommend": {
|
||||
"description": "Do not recommend ''{value}'' as {type} in any document of the current dossier.",
|
||||
"description": "Do not recommend the selected term in any document of this dossier.",
|
||||
"description-bulk": "Do not recommend the selected values as their respective types in any document of the current dossier.",
|
||||
"extraOptionLabel": "Apply to all dossiers",
|
||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||
"label": "Remove from dossier"
|
||||
},
|
||||
"false-positive": {
|
||||
"description": "''{value}'' is not a {type} in this context: ''{context}''.",
|
||||
"description": "Mark this redaction as a false-positive. The term will not be redacted in this dossier if it occurs in the same context.",
|
||||
"description-bulk": "",
|
||||
"extraOptionDescription": "",
|
||||
"extraOptionLabel": "Apply to all dossiers",
|
||||
"label": "False positive"
|
||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||
"label": "Remove from dossier in this context"
|
||||
},
|
||||
"in-document": {
|
||||
"description": "",
|
||||
"label": ""
|
||||
"label": "Aus Dokument entfernen"
|
||||
},
|
||||
"in-dossier": {
|
||||
"description": "Do not {type} \"{value}\" in any document of the current dossier.",
|
||||
"description": "Do not annotate the term in this dossier.",
|
||||
"description-bulk": "",
|
||||
"extraOptionLabel": "Apply to all dossiers",
|
||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||
"label": "Remove from dossier",
|
||||
"label-bulk": ""
|
||||
},
|
||||
"only-here": {
|
||||
"description": "Do not {type} ''{value}'' at this position in the current document.",
|
||||
"description-bulk": "",
|
||||
"description": "Do not{type} '{value}'' at this position in the current document.",
|
||||
"description-bulk": "Do not{type} ''{value}'' at this position in the current document.",
|
||||
"label": "Remove here"
|
||||
}
|
||||
}
|
||||
@ -2268,7 +2267,7 @@
|
||||
"display-name": "This placeholder is replaced by the name of the entity the component is based on."
|
||||
},
|
||||
"excerpt": "This placeholder is replaced by a text snippet that contains the component.",
|
||||
"is-skipped": "The skipped redaction placeholder indicates whether a redaction is skipped or not. It can be included in a separate column of a template that also contains the '{{redaction.value'}} placeholder. The placeholder is replaced by “true” if the respective redaction is skipped, and by “false” if it is redacted (i. e., not skipped).",
|
||||
"is-skipped": "The skipped redaction placeholder indicates whether a redaction is skipped or not. It can be included in a separate column of a template that also contains the '\n{{'redaction.value'}}' placeholder. The placeholder is replaced by “true” if the respective redaction is skipped, and by “false” if it is redacted (i. e., not skipped).",
|
||||
"justification": "This placeholder is replaced by the justification of the component. It is a combination of the legal reference (justificationParagraph) and the justification text (justificationReason).",
|
||||
"justification-legal-basis": "This placeholder is replaced by the legal basis for the component.",
|
||||
"justification-paragraph": "This placeholder is replaced by the legal reference of the justification of the component.",
|
||||
@ -2331,7 +2330,7 @@
|
||||
"options": {
|
||||
"in-dossier": {
|
||||
"description": "Resize in every document in {dossierName}.",
|
||||
"extraOptionLabel": "Apply to all dossiers",
|
||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||
"label": "Resize in dossier",
|
||||
"tooltip": "Only available for dictionary-based types"
|
||||
},
|
||||
@ -2386,7 +2385,7 @@
|
||||
},
|
||||
"missing": "Missing",
|
||||
"must-contain": "Must contain",
|
||||
"no-data": "Please enter a keyword into the search bar to look for documents or document content.",
|
||||
"no-data": "Enter a keyword into the search bar<br> to look for documents or document content.",
|
||||
"no-match": "The specified search term was not found in any of the documents.",
|
||||
"table-header": "{length} search {length, plural, one{result} other{results}}"
|
||||
},
|
||||
@ -2422,7 +2421,7 @@
|
||||
"sign-in-previous-domain": "Sign in to a previously used workspace",
|
||||
"youre-logged-out": "You have successfully been logged out."
|
||||
},
|
||||
"input-placeholder": "your workspace"
|
||||
"input-placeholder": "Your workspace"
|
||||
},
|
||||
"time": {
|
||||
"days": "{days} {days, plural, one{day} other{days}}",
|
||||
@ -2515,7 +2514,7 @@
|
||||
},
|
||||
"error": {
|
||||
"file-size": "File too large. Limit is {size}MB.",
|
||||
"file-type": "This file type is not accepted.",
|
||||
"file-type": "This file type is not supported.",
|
||||
"generic": "Failed to upload file. {error}"
|
||||
}
|
||||
},
|
||||
@ -2570,7 +2569,7 @@
|
||||
},
|
||||
"title": "Edit profile",
|
||||
"update": {
|
||||
"success": "Successfully updated profile!"
|
||||
"success": "Successfully updated profile."
|
||||
}
|
||||
},
|
||||
"user-stats": {
|
||||
@ -2588,9 +2587,9 @@
|
||||
},
|
||||
"watermark-screen": {
|
||||
"action": {
|
||||
"change-success": "Watermark has been updated!",
|
||||
"created-success": "Watermark has been created!",
|
||||
"error": "Failed to update watermark",
|
||||
"change-success": "Watermark has been updated.",
|
||||
"created-success": "Watermark has been created.",
|
||||
"error": "Failed to update watermark.",
|
||||
"revert": "Revert",
|
||||
"save": "Save changes"
|
||||
},
|
||||
|
||||
BIN
apps/red-ui/src/assets/pdftron/Arimo-Bold.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/Arimo-Bold.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/Arimo-BoldItalic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/Arimo-BoldItalic.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/Arimo-Italic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/Arimo-Italic.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/Arimo-Regular.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/Arimo-Regular.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/LiberationSerif.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/LiberationSerif.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/LiberationSerifBold.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/LiberationSerifBold.ttf.lzma
Normal file
Binary file not shown.
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/LiberationSerifItalic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/LiberationSerifItalic.ttf.lzma
Normal file
Binary file not shown.
@ -14,6 +14,30 @@
|
||||
"800": "Mplus1pHeavy",
|
||||
"900": "Mplus1pBlack"
|
||||
}
|
||||
},
|
||||
{
|
||||
"coverage": "U+1-7F,U+A0-370,U+374-376,U+37A-37F,U+384-38B,U+38C,U+38E-3A2,U+3A3-3CF,U+3D0-514,U+51A-51E,U+591-5C8,U+5D0-5EB,U+5F0-5F5,U+1D00-1DCB,U+1DFE-1E9C,U+1E9E,U+1EA0-1EFA,U+1F00-1F16,U+1F18-1F1E,U+1F20-1F46,U+1F48-1F4E,U+1F50-1F58,U+1F59,U+1F5B,U+1F5D,U+1F5F-1F7E,U+1F80-1FB5,U+1FB6-1FC5,U+1FC6-1FD4,U+1FD6-1FDC,U+1FDD-1FF0,U+1FF2-1FF5,U+1FF6-1FFF,U+2000-2010,U+2012-2023,U+2026,U+202A-2031,U+2032-2035,U+2039-203B,U+203C,U+203E,U+2044,U+205E,U+206A-2070,U+2074-2076,U+2077-2079,U+207F,U+2090-2095,U+20A0-20B6,U+20F0,U+2105,U+2113,U+2116-2118,U+2122,U+2126,U+212E,U+214D-214F,U+2153-2155,U+215B-215F,U+2184,U+2190-2196,U+21A8,U+2202,U+2206,U+220F,U+2211-2213,U+2215,U+2219-221B,U+221E-2220,U+2229,U+222B,U+2248,U+2260-2262,U+2264-2266,U+2302,U+2310,U+2320-2322,U+2500,U+2502,U+250C,U+2510,U+2514,U+2518,U+251C,U+2524,U+252C,U+2534,U+253C,U+2550-256D,U+2580,U+2584,U+2588,U+258C,U+2590-2594,U+25A0-25A2,U+25AA-25AD,U+25B2,U+25BA,U+25BC,U+25C4,U+25CA-25CD,U+25CF,U+25D8-25DA,U+25E6,U+263A-263D,U+2640,U+2642,U+2660,U+2663,U+2665-2667,U+266A-266C,U+266F,U+2C60-2C6E,U+2C71-2C78,U+2E17,U+A717-A722,U+A788-A78D,U+F001-F003,U+F004-F006,U+F00A-F00F,U+FB01-FB03,U+FB1D-FB37,U+FB38-FB3D,U+FB3E,U+FB40-FB42,U+FB43-FB45,U+FB46-FB50,U+FE20-FE24,U+FEFF,U+FFFC",
|
||||
"ext": ["ttf", "ttf.lzma", "ttf.brotli"],
|
||||
"family": "Liberation Serif",
|
||||
"id": "liberationserif1",
|
||||
"variants": {
|
||||
"500": "LiberationSerif",
|
||||
"500I": "LiberationSerifItalic",
|
||||
"700": "LiberationSerifBold",
|
||||
"700I": "LiberationSerifBoldItalic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"coverage": "U+1-7F,U+A0-370,U+374-376,U+37A-37F,U+384-38B,U+38C,U+38E-3A2,U+3A3-3CF,U+3D0-514,U+51A-51E,U+591-5C8,U+5D0-5EB,U+5F0-5F5,U+1D00-1DCB,U+1DFE-1E9C,U+1E9E,U+1EA0-1EFA,U+1F00-1F16,U+1F18-1F1E,U+1F20-1F46,U+1F48-1F4E,U+1F50-1F58,U+1F59,U+1F5B,U+1F5D,U+1F5F-1F7E,U+1F80-1FB5,U+1FB6-1FC5,U+1FC6-1FD4,U+1FD6-1FDC,U+1FDD-1FF0,U+1FF2-1FF5,U+1FF6-1FFF,U+2000-2010,U+2012-2023,U+2026,U+202A-2031,U+2032-2035,U+2039-203B,U+203C,U+203E,U+2044,U+205E,U+206A-2070,U+2074-2076,U+2077-2079,U+207F,U+2090-2095,U+20A0-20B6,U+20F0,U+2105,U+2113,U+2116-2118,U+2122,U+2126,U+212E,U+214D-214F,U+2153-2155,U+215B-215F,U+2184,U+2190-2196,U+21A8,U+2202,U+2206,U+220F,U+2211-2213,U+2215,U+2219-221B,U+221E-2220,U+2229,U+222B,U+2248,U+2260-2262,U+2264-2266,U+2302,U+2310,U+2320-2322,U+2500,U+2502,U+250C,U+2510,U+2514,U+2518,U+251C,U+2524,U+252C,U+2534,U+253C,U+2550-256D,U+2580,U+2584,U+2588,U+258C,U+2590-2594,U+25A0-25A2,U+25AA-25AD,U+25B2,U+25BA,U+25BC,U+25C4,U+25CA-25CD,U+25CF,U+25D8-25DA,U+25E6,U+263A-263D,U+2640,U+2642,U+2660,U+2663,U+2665-2667,U+266A-266C,U+266F,U+2C60-2C6E,U+2C71-2C78,U+2E17,U+A717-A722,U+A788-A78D,U+F001-F003,U+F005,U+F00A-F00F,U+FB01-FB03,U+FB1D-FB37,U+FB38-FB3D,U+FB3E,U+FB40-FB42,U+FB43-FB45,U+FB46-FB50,U+FE20-FE24,U+FEFF,U+FFFC",
|
||||
"ext": ["ttf", "ttf.lzma", "ttf.brotli"],
|
||||
"family": "Arimo",
|
||||
"id": "arimo1",
|
||||
"variants": {
|
||||
"500": "Arimo-Regular",
|
||||
"500I": "Arimo-Italic",
|
||||
"700": "Arimo-Bold",
|
||||
"700I": "Arimo-BoldItalic"
|
||||
}
|
||||
}
|
||||
],
|
||||
"matchPatterns": [
|
||||
@ -21,6 +45,16 @@
|
||||
"match": "M+1p*",
|
||||
"target": "m+1p1",
|
||||
"type": "Wildcard"
|
||||
},
|
||||
{
|
||||
"match": "Liberation*Serif*",
|
||||
"target": "liberationserif1",
|
||||
"type": "Wildcard"
|
||||
},
|
||||
{
|
||||
"match": "Arimo*",
|
||||
"target": "arimo1",
|
||||
"type": "Wildcard"
|
||||
}
|
||||
],
|
||||
"versionMajor": 2,
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit e88929f0d48e54298d85ef05ea467980be11524b
|
||||
Subproject commit 074f88e66abc765b0ef8654eb56a552d88e1bbda
|
||||
@ -10,6 +10,7 @@ export interface IComponentMapping extends IListable {
|
||||
numberOfLines: number;
|
||||
encoding: string;
|
||||
delimiter: string;
|
||||
quoteChar: string;
|
||||
}
|
||||
|
||||
export class ComponentMapping implements IComponentMapping, IListable {
|
||||
@ -22,6 +23,7 @@ export class ComponentMapping implements IComponentMapping, IListable {
|
||||
readonly numberOfLines: number;
|
||||
readonly encoding: string;
|
||||
readonly delimiter: string;
|
||||
readonly quoteChar: string;
|
||||
|
||||
constructor(componentMapping: IComponentMapping) {
|
||||
this.id = componentMapping.id;
|
||||
@ -33,6 +35,7 @@ export class ComponentMapping implements IComponentMapping, IListable {
|
||||
this.numberOfLines = componentMapping.numberOfLines;
|
||||
this.encoding = componentMapping.encoding;
|
||||
this.delimiter = componentMapping.delimiter;
|
||||
this.quoteChar = componentMapping.quoteChar;
|
||||
}
|
||||
|
||||
get searchKey(): string {
|
||||
|
||||
@ -7,8 +7,6 @@ export class Dictionary extends Entity<IDictionary> implements IDictionary {
|
||||
readonly addToDictionaryAction: boolean;
|
||||
readonly caseInsensitive: boolean;
|
||||
readonly description: string;
|
||||
readonly aiCreationEnabled: boolean;
|
||||
readonly aiDescription: string;
|
||||
readonly dossierTemplateId?: string;
|
||||
readonly hexColor?: string;
|
||||
readonly recommendationHexColor?: string;
|
||||
@ -35,8 +33,6 @@ export class Dictionary extends Entity<IDictionary> implements IDictionary {
|
||||
this.addToDictionaryAction = !!entity.addToDictionaryAction;
|
||||
this.caseInsensitive = !!entity.caseInsensitive;
|
||||
this.description = entity.description ?? '';
|
||||
this.aiCreationEnabled = !!entity.aiCreationEnabled;
|
||||
this.aiDescription = entity.aiDescription ?? '';
|
||||
this.dossierTemplateId = entity.dossierTemplateId;
|
||||
this.entries = entity.entries ?? [];
|
||||
this.falsePositiveEntries = entity.falsePositiveEntries ?? [];
|
||||
|
||||
@ -16,14 +16,6 @@ export interface IDictionary {
|
||||
* The description of the dictionary type
|
||||
*/
|
||||
readonly description?: string;
|
||||
/**
|
||||
* True if the entries in this type should also be created via AI, default is false.
|
||||
*/
|
||||
readonly aiCreationEnabled?: boolean;
|
||||
/**
|
||||
* The AI description of the dictionary type
|
||||
*/
|
||||
readonly aiDescription?: string;
|
||||
/**
|
||||
* The DossierTemplate Id for this type
|
||||
*/
|
||||
|
||||
@ -5,7 +5,6 @@ export const FILE_ID = 'fileId';
|
||||
export const WorkflowFileStatuses = {
|
||||
APPROVED: 'APPROVED',
|
||||
NEW: 'NEW',
|
||||
UNASSIGNED: 'UNASSIGNED',
|
||||
UNDER_APPROVAL: 'UNDER_APPROVAL',
|
||||
UNDER_REVIEW: 'UNDER_REVIEW',
|
||||
} as const;
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
import { IListable } from '@iqser/common-ui';
|
||||
import { ILegalBasis } from './legal-basis';
|
||||
import { toSnakeCase } from '@utils/functions';
|
||||
|
||||
export class Justification implements ILegalBasis, IListable {
|
||||
readonly description?: string;
|
||||
readonly name: string;
|
||||
readonly reason?: string;
|
||||
readonly technicalName?: string;
|
||||
|
||||
constructor(justification: ILegalBasis) {
|
||||
this.description = justification.description;
|
||||
this.name = justification.name;
|
||||
this.reason = justification.reason;
|
||||
this.technicalName = justification.technicalName;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
@ -19,4 +22,13 @@ export class Justification implements ILegalBasis, IListable {
|
||||
get searchKey(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
static toTechnicalName(value: string) {
|
||||
const baseTechnicalName = toSnakeCase(value.trim());
|
||||
let technicalName = baseTechnicalName.replaceAll(/[^A-Za-z0-9_-]/g, '');
|
||||
if (!technicalName.length && baseTechnicalName.length) {
|
||||
technicalName = '_';
|
||||
}
|
||||
return technicalName;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,4 +2,5 @@ export interface ILegalBasis {
|
||||
readonly name: string;
|
||||
readonly description?: string;
|
||||
readonly reason?: string;
|
||||
readonly technicalName?: string;
|
||||
}
|
||||
|
||||
@ -14,8 +14,8 @@ export interface IBulkRecategorizationRequest {
|
||||
readonly type: string;
|
||||
readonly legalBasis: string;
|
||||
readonly section: string;
|
||||
readonly originTypes: string[];
|
||||
readonly originLegalBases: string[];
|
||||
readonly originTypes?: string[];
|
||||
readonly originLegalBases?: string[];
|
||||
readonly rectangle: boolean;
|
||||
readonly position?: IEntityLogEntryPosition;
|
||||
readonly pageNumbers?: number[];
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { WorkflowFileStatus } from '../../files/types';
|
||||
import { WorkflowFileStatus } from '../../files';
|
||||
|
||||
type StatusSorterItem = { key: WorkflowFileStatus } | WorkflowFileStatus | string;
|
||||
type Sorter = Record<WorkflowFileStatus, number> & {
|
||||
@ -7,10 +7,9 @@ type Sorter = Record<WorkflowFileStatus, number> & {
|
||||
|
||||
export const StatusSorter: Sorter = {
|
||||
NEW: 0,
|
||||
UNASSIGNED: 1,
|
||||
UNDER_REVIEW: 2,
|
||||
UNDER_APPROVAL: 3,
|
||||
APPROVED: 4,
|
||||
UNDER_REVIEW: 1,
|
||||
UNDER_APPROVAL: 2,
|
||||
APPROVED: 3,
|
||||
byStatus: (a: StatusSorterItem, b: StatusSorterItem): number => {
|
||||
if (typeof a !== typeof b) {
|
||||
throw TypeError('Used different types when calling StatusSorter.byStatus1');
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"]
|
||||
"files": ["/assets/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani|lzma)"]
|
||||
}
|
||||
}
|
||||
],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user