Compare commits
40 Commits
master
...
RED-10148-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2aa20085b0 | ||
|
|
bd66f39474 | ||
|
|
969e375986 | ||
|
|
d59a4c02a0 | ||
|
|
53e9725243 | ||
|
|
a3b2382bad | ||
|
|
327620d5f6 | ||
|
|
471d111d69 | ||
|
|
46b48de214 | ||
|
|
ae1c137b61 | ||
|
|
84aa3f1c00 | ||
|
|
c8c632a2c1 | ||
|
|
26e8d9fff9 | ||
|
|
1fcc95b138 | ||
|
|
aa171f992b | ||
|
|
33bacfd967 | ||
|
|
ce262a5f3a | ||
|
|
c6ec428bc4 | ||
|
|
edf9e61132 | ||
|
|
e57d54a755 | ||
|
|
036bfa2878 | ||
|
|
bf9e6816f8 | ||
|
|
0bff02a3e7 | ||
|
|
9016ff91b3 | ||
|
|
afa399baf1 | ||
|
|
41b8407862 | ||
|
|
303aa0a1a4 | ||
|
|
262e30e2c0 | ||
|
|
901ba934af | ||
|
|
ca0fe4cf13 | ||
|
|
5d3eb3751c | ||
|
|
1db68cbb7a | ||
|
|
c9b25e2af4 | ||
|
|
9881c3e321 | ||
|
|
e4cb33978c | ||
|
|
1376e1a486 | ||
|
|
1894a378b5 | ||
|
|
701a69db95 | ||
|
|
77f94a7983 | ||
|
|
108a3315da |
@ -9,7 +9,7 @@
|
|||||||
<redaction-breadcrumbs></redaction-breadcrumbs>
|
<redaction-breadcrumbs></redaction-breadcrumbs>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a [matTooltip]="'top-bar.navigation-items.back-to-dashboard' | translate" [routerLink]="['/']" class="logo">
|
<a [matTooltip]="'top-bar.navigation-items.back-to-dashboard' | translate" [routerLink]="['/main']" class="logo">
|
||||||
<div [attr.help-mode-key]="'home'" class="actions">
|
<div [attr.help-mode-key]="'home'" class="actions">
|
||||||
<iqser-logo (iqserHiddenAction)="userPreferenceService.toggleDevFeatures()" icon="iqser:logo"></iqser-logo>
|
<iqser-logo (iqserHiddenAction)="userPreferenceService.toggleDevFeatures()" icon="iqser:logo"></iqser-logo>
|
||||||
<div class="app-name">{{ titleService.getTitle() }}</div>
|
<div class="app-name">{{ titleService.getTitle() }}</div>
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.mat-mdc-menu-item.notification {
|
.mat-mdc-menu-item.notification {
|
||||||
padding: 8px 26px 10px 8px;
|
padding: 8px 26px 10px 8px !important;
|
||||||
margin: 2px 0 0 0;
|
margin: 2px 0 0 0;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
import { AnnotationPermissions } from '@models/file/annotation.permissions';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Dictionary, LogEntryEngines, SuperTypes } from '@red/domain';
|
import { Dictionary, SuperTypes } from '@red/domain';
|
||||||
|
|
||||||
export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) => !isApprover && annotation.pending;
|
export const canUndo = (annotation: AnnotationWrapper, isApprover: boolean) => !isApprover && annotation.pending;
|
||||||
|
|
||||||
@ -17,8 +17,9 @@ export const canAcceptRecommendation = (annotation: AnnotationWrapper) => annota
|
|||||||
|
|
||||||
export const canMarkAsFalsePositive = (annotation: AnnotationWrapper, annotationEntity: Dictionary) =>
|
export const canMarkAsFalsePositive = (annotation: AnnotationWrapper, annotationEntity: Dictionary) =>
|
||||||
annotation.canBeMarkedAsFalsePositive &&
|
annotation.canBeMarkedAsFalsePositive &&
|
||||||
!annotation.hasBeenForcedRedaction &&
|
|
||||||
!annotation.hasBeenResizedLocally &&
|
!annotation.hasBeenResizedLocally &&
|
||||||
|
!annotation.isRemovedLocally &&
|
||||||
|
!annotation.hasBeenForcedRedaction &&
|
||||||
annotationEntity?.hasDictionary;
|
annotationEntity?.hasDictionary;
|
||||||
|
|
||||||
export const canRemoveOnlyHere = (annotation: AnnotationWrapper, canAddRedaction: boolean, autoAnalysisDisabled: boolean) =>
|
export const canRemoveOnlyHere = (annotation: AnnotationWrapper, canAddRedaction: boolean, autoAnalysisDisabled: boolean) =>
|
||||||
@ -30,7 +31,7 @@ export const canRemoveFromDictionary = (annotation: AnnotationWrapper, autoAnaly
|
|||||||
annotation.isModifyDictionary &&
|
annotation.isModifyDictionary &&
|
||||||
(annotation.isRedacted || annotation.isSkipped || annotation.isHint || (annotation.isIgnoredHint && !annotation.isRuleBased)) &&
|
(annotation.isRedacted || annotation.isSkipped || annotation.isHint || (annotation.isIgnoredHint && !annotation.isRuleBased)) &&
|
||||||
(autoAnalysisDisabled || !annotation.pending) &&
|
(autoAnalysisDisabled || !annotation.pending) &&
|
||||||
[LogEntryEngines.DICTIONARY, LogEntryEngines.DOSSIER_DICTIONARY].some(engine => annotation.engines.includes(engine));
|
annotation.isDictBased;
|
||||||
|
|
||||||
export const canRemoveRedaction = (annotation: AnnotationWrapper, permissions: AnnotationPermissions) =>
|
export const canRemoveRedaction = (annotation: AnnotationWrapper, permissions: AnnotationPermissions) =>
|
||||||
(!annotation.isIgnoredHint || !annotation.isRuleBased) &&
|
(!annotation.isIgnoredHint || !annotation.isRuleBased) &&
|
||||||
|
|||||||
@ -74,7 +74,7 @@ export class AnnotationWrapper implements IListable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get isDictBased() {
|
get isDictBased() {
|
||||||
return this.engines.includes(LogEntryEngines.DICTIONARY);
|
return [LogEntryEngines.DICTIONARY, LogEntryEngines.DOSSIER_DICTIONARY].some(engine => this.engines.includes(engine));
|
||||||
}
|
}
|
||||||
|
|
||||||
get isRedactedImageHint() {
|
get isRedactedImageHint() {
|
||||||
|
|||||||
@ -37,6 +37,11 @@
|
|||||||
{{ 'preferences-screen.form.help-mode-dialog' | translate }}
|
{{ 'preferences-screen.form.help-mode-dialog' | translate }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<mat-checkbox color="primary" formControlName="overwriteFileOption">
|
||||||
|
{{ 'preferences-screen.form.overwrite-file-option' | translate }}
|
||||||
|
</mat-checkbox>
|
||||||
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
|
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, inject, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
import {
|
import {
|
||||||
@ -28,6 +28,7 @@ interface PreferencesForm {
|
|||||||
// warnings preferences
|
// warnings preferences
|
||||||
loadAllAnnotationsWarning: boolean;
|
loadAllAnnotationsWarning: boolean;
|
||||||
helpModeDialog: boolean;
|
helpModeDialog: boolean;
|
||||||
|
overwriteFileOption: boolean;
|
||||||
|
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
}
|
}
|
||||||
@ -58,6 +59,12 @@ const Screens = {
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PreferencesComponent extends BaseFormComponent implements OnInit {
|
export class PreferencesComponent extends BaseFormComponent implements OnInit {
|
||||||
|
readonly #formBuilder = inject(FormBuilder);
|
||||||
|
readonly #permissionsService = inject(IqserPermissionsService);
|
||||||
|
readonly #changeRef = inject(ChangeDetectorRef);
|
||||||
|
readonly #loadingService = inject(LoadingService);
|
||||||
|
readonly #userPreferenceService = inject(UserPreferenceService);
|
||||||
|
|
||||||
readonly form: FormGroup<AsControl<PreferencesForm>>;
|
readonly form: FormGroup<AsControl<PreferencesForm>>;
|
||||||
readonly currentScreen: Screen;
|
readonly currentScreen: Screen;
|
||||||
readonly screens = Screens;
|
readonly screens = Screens;
|
||||||
@ -66,81 +73,92 @@ export class PreferencesComponent extends BaseFormComponent implements OnInit {
|
|||||||
readonly config = getConfig();
|
readonly config = getConfig();
|
||||||
readonly isIqserDevMode = isIqserDevMode();
|
readonly isIqserDevMode = isIqserDevMode();
|
||||||
|
|
||||||
constructor(
|
get #isOverwriteFileOptionActive() {
|
||||||
route: ActivatedRoute,
|
return !(this.#userPreferenceService.getOverwriteFileOption() === 'undefined');
|
||||||
readonly userPreferenceService: UserPreferenceService,
|
}
|
||||||
private readonly _formBuilder: FormBuilder,
|
|
||||||
private readonly _permissionsService: IqserPermissionsService,
|
constructor(route: ActivatedRoute) {
|
||||||
private readonly _changeRef: ChangeDetectorRef,
|
|
||||||
private readonly _loadingService: LoadingService,
|
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
this.form = this._formBuilder.group({
|
this.form = this.#formBuilder.group({
|
||||||
// preferences
|
// preferences
|
||||||
autoExpandFiltersOnActions: [this.userPreferenceService.getAutoExpandFiltersOnActions()],
|
autoExpandFiltersOnActions: [this.#userPreferenceService.getAutoExpandFiltersOnActions()],
|
||||||
openScmDialogByDefault: [this.userPreferenceService.getOpenScmDialogByDefault()],
|
openScmDialogByDefault: [this.#userPreferenceService.getOpenScmDialogByDefault()],
|
||||||
tableExtractionType: [this.userPreferenceService.getTableExtractionType()],
|
tableExtractionType: [this.#userPreferenceService.getTableExtractionType()],
|
||||||
// warnings preferences
|
// warnings preferences
|
||||||
loadAllAnnotationsWarning: [this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)],
|
loadAllAnnotationsWarning: [this.#userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)],
|
||||||
helpModeDialog: [this.userPreferenceService.getBool(KEYS.helpModeDialog)],
|
helpModeDialog: [this.#userPreferenceService.getBool(KEYS.helpModeDialog)],
|
||||||
|
overwriteFileOption: [this.#isOverwriteFileOptionActive],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!this._permissionsService.has(Roles.managePreferences)) {
|
if (!this.#permissionsService.has(Roles.managePreferences)) {
|
||||||
this.form.disable();
|
this.form.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._permissionsService.has(Roles.getTables)) {
|
if (!this.#permissionsService.has(Roles.getTables)) {
|
||||||
this.form.controls.tableExtractionType.disable();
|
this.form.controls.tableExtractionType.disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.#isOverwriteFileOptionActive) {
|
||||||
|
this.form.controls.overwriteFileOption.disable();
|
||||||
|
}
|
||||||
|
|
||||||
this.initialFormValue = this.form.getRawValue();
|
this.initialFormValue = this.form.getRawValue();
|
||||||
this.currentScreen = route.snapshot.data.screen;
|
this.currentScreen = route.snapshot.data.screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this._loadingService.stop();
|
this.#loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
async save(): Promise<any> {
|
async save(): Promise<any> {
|
||||||
if (this.form.controls.autoExpandFiltersOnActions.value !== this.userPreferenceService.getAutoExpandFiltersOnActions()) {
|
if (this.form.controls.autoExpandFiltersOnActions.value !== this.#userPreferenceService.getAutoExpandFiltersOnActions()) {
|
||||||
await this.userPreferenceService.toggleAutoExpandFiltersOnActions();
|
await this.#userPreferenceService.toggleAutoExpandFiltersOnActions();
|
||||||
}
|
}
|
||||||
if (this.form.controls.openScmDialogByDefault.value !== this.userPreferenceService.getOpenScmDialogByDefault()) {
|
if (this.form.controls.openScmDialogByDefault.value !== this.#userPreferenceService.getOpenScmDialogByDefault()) {
|
||||||
await this.userPreferenceService.toggleOpenScmDialogByDefault();
|
await this.#userPreferenceService.toggleOpenScmDialogByDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.form.controls.tableExtractionType.value !== this.userPreferenceService.getTableExtractionType()) {
|
if (this.form.controls.tableExtractionType.value !== this.#userPreferenceService.getTableExtractionType()) {
|
||||||
await this.userPreferenceService.save(PreferencesKeys.tableExtractionType, this.form.controls.tableExtractionType.value);
|
await this.#userPreferenceService.save(PreferencesKeys.tableExtractionType, this.form.controls.tableExtractionType.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.form.controls.loadAllAnnotationsWarning.value !==
|
this.form.controls.loadAllAnnotationsWarning.value !==
|
||||||
this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)
|
this.#userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)
|
||||||
) {
|
) {
|
||||||
await this.userPreferenceService.save(
|
await this.#userPreferenceService.save(
|
||||||
PreferencesKeys.loadAllAnnotationsWarning,
|
PreferencesKeys.loadAllAnnotationsWarning,
|
||||||
String(this.form.controls.loadAllAnnotationsWarning.value),
|
String(this.form.controls.loadAllAnnotationsWarning.value),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.form.controls.helpModeDialog.value !== this.userPreferenceService.getBool(KEYS.helpModeDialog)) {
|
if (this.form.controls.helpModeDialog.value !== this.#userPreferenceService.getBool(KEYS.helpModeDialog)) {
|
||||||
await this.userPreferenceService.save(KEYS.helpModeDialog, String(this.form.controls.helpModeDialog.value));
|
await this.#userPreferenceService.save(KEYS.helpModeDialog, String(this.form.controls.helpModeDialog.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.userPreferenceService.reload();
|
if (this.form.controls.overwriteFileOption.enabled && !this.form.controls.overwriteFileOption.value) {
|
||||||
|
await this.#userPreferenceService.saveOverwriteFileOption('undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.#userPreferenceService.reload();
|
||||||
this.#patchValues();
|
this.#patchValues();
|
||||||
|
|
||||||
this.initialFormValue = this.form.getRawValue();
|
this.initialFormValue = this.form.getRawValue();
|
||||||
this._changeRef.markForCheck();
|
this.#changeRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
#patchValues() {
|
#patchValues() {
|
||||||
this.form.patchValue({
|
this.form.patchValue({
|
||||||
autoExpandFiltersOnActions: this.userPreferenceService.getAutoExpandFiltersOnActions(),
|
autoExpandFiltersOnActions: this.#userPreferenceService.getAutoExpandFiltersOnActions(),
|
||||||
openScmDialogByDefault: this.userPreferenceService.getOpenScmDialogByDefault(),
|
openScmDialogByDefault: this.#userPreferenceService.getOpenScmDialogByDefault(),
|
||||||
tableExtractionType: this.userPreferenceService.getTableExtractionType(),
|
tableExtractionType: this.#userPreferenceService.getTableExtractionType(),
|
||||||
loadAllAnnotationsWarning: this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning),
|
loadAllAnnotationsWarning: this.#userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning),
|
||||||
helpModeDialog: this.userPreferenceService.getBool(KEYS.helpModeDialog),
|
helpModeDialog: this.#userPreferenceService.getBool(KEYS.helpModeDialog),
|
||||||
|
overwriteFileOption: this.#isOverwriteFileOptionActive,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!this.#isOverwriteFileOptionActive) {
|
||||||
|
this.form.controls.overwriteFileOption.disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<div
|
<div
|
||||||
[translateParams]="{
|
[translateParams]="{
|
||||||
type: user ? 'edit' : 'create'
|
type: !!user() ? 'edit' : 'create',
|
||||||
}"
|
}"
|
||||||
[translate]="'add-edit-user.title'"
|
[translate]="'add-edit-user.title'"
|
||||||
class="dialog-header heading-l"
|
class="dialog-header heading-l"
|
||||||
@ -37,9 +37,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@if (!user()) {
|
||||||
|
<div class="iqser-input-group">
|
||||||
|
<label [translate]="'add-edit-user.form.account-setup'"></label>
|
||||||
|
<mat-checkbox formControlName="sendSetPasswordMail">{{ 'add-edit-user.form.send-email' | translate }}</mat-checkbox>
|
||||||
|
<span [translate]="'add-edit-user.form.send-email-explanation'" class="hint"></span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
(click)="toggleResetPassword.emit()"
|
(click)="toggleResetPassword.emit()"
|
||||||
*ngIf="!!user"
|
*ngIf="!!user()"
|
||||||
[translate]="'add-edit-user.form.reset-password'"
|
[translate]="'add-edit-user.form.reset-password'"
|
||||||
class="mt-24 fit-content link-action"
|
class="mt-24 fit-content link-action"
|
||||||
></div>
|
></div>
|
||||||
@ -48,14 +56,14 @@
|
|||||||
<div class="dialog-actions">
|
<div class="dialog-actions">
|
||||||
<iqser-icon-button
|
<iqser-icon-button
|
||||||
[disabled]="form.invalid || !changed"
|
[disabled]="form.invalid || !changed"
|
||||||
[label]="(user ? 'add-edit-user.actions.save-changes' : 'add-edit-user.actions.save') | translate"
|
[label]="(user() ? 'add-edit-user.actions.save-changes' : 'add-edit-user.actions.save') | translate"
|
||||||
[submit]="true"
|
[submit]="true"
|
||||||
[type]="iconButtonTypes.primary"
|
[type]="iconButtonTypes.primary"
|
||||||
></iqser-icon-button>
|
></iqser-icon-button>
|
||||||
|
|
||||||
<iqser-icon-button
|
<iqser-icon-button
|
||||||
(action)="delete()"
|
(action)="delete()"
|
||||||
*ngIf="user && !disabledDelete(user)"
|
*ngIf="user() && !disabledDelete(user())"
|
||||||
[label]="'add-edit-user.actions.delete' | translate"
|
[label]="'add-edit-user.actions.delete' | translate"
|
||||||
[type]="iconButtonTypes.dark"
|
[type]="iconButtonTypes.dark"
|
||||||
icon="iqser:trash"
|
icon="iqser:trash"
|
||||||
|
|||||||
@ -5,3 +5,7 @@
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hint {
|
||||||
|
margin-left: 23px;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
|
import { Component, input, OnInit, output } from '@angular/core';
|
||||||
import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
import { ReactiveFormsModule, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
|
||||||
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||||
import { BaseFormComponent, IconButtonComponent, LoadingService, Toaster } from '@iqser/common-ui';
|
import { BaseFormComponent, IconButtonComponent, LoadingService, Toaster } from '@iqser/common-ui';
|
||||||
@ -20,15 +20,15 @@ import { NgForOf, NgIf } from '@angular/common';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [TranslateModule, ReactiveFormsModule, MatCheckbox, NgForOf, IconButtonComponent, NgIf],
|
imports: [TranslateModule, ReactiveFormsModule, MatCheckbox, NgForOf, IconButtonComponent, NgIf],
|
||||||
})
|
})
|
||||||
export class UserDetailsComponent extends BaseFormComponent implements OnChanges {
|
export class UserDetailsComponent extends BaseFormComponent implements OnInit {
|
||||||
/** e.g. a RED_ADMIN is automatically a RED_USER_ADMIN => can't disable RED_USER_ADMIN as long as RED_ADMIN is checked */
|
user = input<User>();
|
||||||
private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
readonly toggleResetPassword = output();
|
||||||
@Input() user: User;
|
readonly closeDialog = output<boolean>();
|
||||||
@Output() readonly toggleResetPassword = new EventEmitter();
|
readonly cancel = output();
|
||||||
@Output() readonly closeDialog = new EventEmitter();
|
|
||||||
@Output() readonly cancel = new EventEmitter();
|
|
||||||
readonly ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
|
readonly ROLES = ['RED_USER', 'RED_MANAGER', 'RED_USER_ADMIN', 'RED_ADMIN'];
|
||||||
readonly translations = rolesTranslations;
|
readonly translations = rolesTranslations;
|
||||||
|
/** e.g. a RED_ADMIN is automatically a RED_USER_ADMIN => can't disable RED_USER_ADMIN as long as RED_ADMIN is checked */
|
||||||
|
readonly #ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _formBuilder: UntypedFormBuilder,
|
private readonly _formBuilder: UntypedFormBuilder,
|
||||||
@ -49,13 +49,17 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
|||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _rolesControls(): any {
|
get sendSetPasswordMail() {
|
||||||
|
return !this.form.controls.sendSetPasswordMail.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get #rolesControls() {
|
||||||
return this.ROLES.reduce(
|
return this.ROLES.reduce(
|
||||||
(prev, role) => ({
|
(prev, role) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[role]: [
|
[role]: [
|
||||||
{
|
{
|
||||||
value: this.user && this.user.has(role),
|
value: this.user() && this.user().has(role),
|
||||||
disabled: this.shouldBeDisabled(role),
|
disabled: this.shouldBeDisabled(role),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@ -64,20 +68,20 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnInit() {
|
||||||
this.form = this._getForm();
|
this.form = this.#getForm();
|
||||||
this.initialFormValue = this.form.getRawValue();
|
this.initialFormValue = this.form.getRawValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldBeDisabled(role: string): boolean {
|
shouldBeDisabled(role: string): boolean {
|
||||||
const isCurrentAdminUser = this.user && this.user.isAdmin && this.user.id === this._userService.currentUser.id;
|
const isCurrentAdminUser = this.user() && this.user().isAdmin && this.user().id === this._userService.currentUser.id;
|
||||||
return (
|
return (
|
||||||
// RED_ADMIN can't remove own RED_ADMIN role
|
// RED_ADMIN can't remove own RED_ADMIN role
|
||||||
(role === 'RED_ADMIN' && isCurrentAdminUser) ||
|
(role === 'RED_ADMIN' && isCurrentAdminUser) ||
|
||||||
// only RED_ADMINs can edit RED_ADMIN roles
|
// only RED_ADMINs can edit RED_ADMIN roles
|
||||||
(role === 'RED_ADMIN' && !this._userService.currentUser.isAdmin) ||
|
(role === 'RED_ADMIN' && !this._userService.currentUser.isAdmin) ||
|
||||||
Object.keys(this._ROLE_REQUIREMENTS).reduce(
|
Object.keys(this.#ROLE_REQUIREMENTS).reduce(
|
||||||
(value, key) => value || (role === this._ROLE_REQUIREMENTS[key] && this.user?.roles.includes(key)),
|
(value, key) => value || (role === this.#ROLE_REQUIREMENTS[key] && this.user()?.roles.includes(key)),
|
||||||
false,
|
false,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -85,9 +89,13 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
|||||||
|
|
||||||
async save() {
|
async save() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
const userData: IProfileUpdateRequest = { ...this.form.getRawValue(), roles: this.activeRoles };
|
const userData: IProfileUpdateRequest = {
|
||||||
|
...this.form.getRawValue(),
|
||||||
|
roles: this.activeRoles,
|
||||||
|
sendSetPasswordMail: this.sendSetPasswordMail,
|
||||||
|
};
|
||||||
|
|
||||||
if (!this.user) {
|
if (!this.user()) {
|
||||||
await firstValueFrom(this._userService.create(userData))
|
await firstValueFrom(this._userService.create(userData))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.closeDialog.emit(true);
|
this.closeDialog.emit(true);
|
||||||
@ -101,22 +109,22 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
|||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
await firstValueFrom(this._userService.updateProfile(userData, this.user.id));
|
await firstValueFrom(this._userService.updateProfile(userData, this.user().id));
|
||||||
this.closeDialog.emit(true);
|
this.closeDialog.emit(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete() {
|
delete() {
|
||||||
this._dialogService.deleteUsers([this.user.id], () => this.closeDialog.emit(true));
|
this._dialogService.deleteUsers([this.user().id], () => this.closeDialog.emit(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
setRolesRequirements(checked: boolean, role: string): void {
|
setRolesRequirements(checked: boolean, role: string): void {
|
||||||
if (Object.keys(this._ROLE_REQUIREMENTS).includes(role)) {
|
if (Object.keys(this.#ROLE_REQUIREMENTS).includes(role)) {
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.form.patchValue({ [this._ROLE_REQUIREMENTS[role]]: true });
|
this.form.patchValue({ [this.#ROLE_REQUIREMENTS[role]]: true });
|
||||||
this.form.controls[this._ROLE_REQUIREMENTS[role]].disable();
|
this.form.controls[this.#ROLE_REQUIREMENTS[role]].disable();
|
||||||
} else {
|
} else {
|
||||||
this.form.controls[this._ROLE_REQUIREMENTS[role]].enable();
|
this.form.controls[this.#ROLE_REQUIREMENTS[role]].enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,18 +135,19 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
|||||||
return user.id === this._userService.currentUser.id || (userAdmin && !currentUserAdmin);
|
return user.id === this._userService.currentUser.id || (userAdmin && !currentUserAdmin);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getForm(): UntypedFormGroup {
|
#getForm(): UntypedFormGroup {
|
||||||
return this._formBuilder.group({
|
return this._formBuilder.group({
|
||||||
firstName: [this.user?.firstName, Validators.required],
|
firstName: [this.user()?.firstName, Validators.required],
|
||||||
lastName: [this.user?.lastName, Validators.required],
|
lastName: [this.user()?.lastName, Validators.required],
|
||||||
email: [
|
email: [
|
||||||
{
|
{
|
||||||
value: this.user?.email,
|
value: this.user()?.email,
|
||||||
disabled: !!this.user?.email,
|
disabled: !!this.user()?.email,
|
||||||
},
|
},
|
||||||
[Validators.required, Validators.email],
|
[Validators.required, Validators.email],
|
||||||
],
|
],
|
||||||
...this._rolesControls,
|
...this.#rolesControls,
|
||||||
|
sendSetPasswordMail: [false],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<div class="content-container" iqserHasScrollbar>
|
<div class="content-container" iqserHasScrollbar>
|
||||||
<div class="dialog">
|
<div class="dialog">
|
||||||
<div class="dialog-header">
|
<div class="dialog-header">
|
||||||
<div [translate]="'entity.info.heading'" [attr.help-mode-key]="'entity_info'" class="heading-l"></div>
|
<div [translate]="'entity.info.heading'" [attr.help-mode-key]="'entity_info'" class="heading-l w-full"></div>
|
||||||
|
|
||||||
<div *ngIf="!permissionsService.canEditEntities()" class="read-only-indicator all-caps-label primary">
|
<div *ngIf="!permissionsService.canEditEntities()" class="read-only-indicator all-caps-label primary">
|
||||||
<mat-icon class="mr-8" svgIcon="red:read-only"></mat-icon>
|
<mat-icon class="mr-8" svgIcon="red:read-only"></mat-icon>
|
||||||
@ -26,8 +26,6 @@
|
|||||||
></iqser-icon-button>
|
></iqser-icon-button>
|
||||||
|
|
||||||
<div (click)="revert()" [translate]="'entity.info.actions.revert'" class="all-caps-label cancel"></div>
|
<div (click)="revert()" [translate]="'entity.info.actions.revert'" class="all-caps-label cancel"></div>
|
||||||
|
|
||||||
<iqser-help-button *ngIf="!config.IS_DOCUMINE"></iqser-help-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -26,3 +26,7 @@
|
|||||||
min-height: unset;
|
min-height: unset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import { MatDatepickerModule } from '@angular/material/datepicker';
|
|||||||
import { MatIcon } from '@angular/material/icon';
|
import { MatIcon } from '@angular/material/icon';
|
||||||
import { SelectComponent } from '@shared/components/select/select.component';
|
import { SelectComponent } from '@shared/components/select/select.component';
|
||||||
|
|
||||||
const downloadTypes = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(type => ({
|
const downloadTypes = ['ORIGINAL', 'PREVIEW', 'OPTIMIZED_PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(type => ({
|
||||||
key: type,
|
key: type,
|
||||||
label: downloadTypesTranslations[type],
|
label: downloadTypesTranslations[type],
|
||||||
}));
|
}));
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { LicenseService } from '@services/license.service';
|
|||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ChartDataset } from 'chart.js';
|
import { ChartDataset } from 'chart.js';
|
||||||
import { ChartBlue, ChartGreen, ChartRed } from '../../utils/constants';
|
import { ChartBlue, ChartGreen, ChartRed } from '../../utils/constants';
|
||||||
import { getDataUntilCurrentMonth, getLabelsFromLicense, getLineConfig, isCurrentMonthAndYear } from '../../utils/functions';
|
import { getDataUntilCurrentMonth, getLabelsFromLicense, getLineConfig, isCurrentMonth } from '../../utils/functions';
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { size } from '@iqser/common-ui/lib/utils';
|
import { size } from '@iqser/common-ui/lib/utils';
|
||||||
@ -43,7 +43,7 @@ export class LicenseAnalysisCapacityUsageComponent {
|
|||||||
#getCapacityDatasets(): ChartDataset[] {
|
#getCapacityDatasets(): ChartDataset[] {
|
||||||
const monthlyData = [...this.licenseService.selectedLicenseReport.monthlyData];
|
const monthlyData = [...this.licenseService.selectedLicenseReport.monthlyData];
|
||||||
const dataUntilCurrentMonth = getDataUntilCurrentMonth(monthlyData);
|
const dataUntilCurrentMonth = getDataUntilCurrentMonth(monthlyData);
|
||||||
if (monthlyData.length === 1 || isCurrentMonthAndYear(monthlyData[0].startDate)) {
|
if (monthlyData.length === 1 || isCurrentMonth(monthlyData[0].startDate)) {
|
||||||
const empty = { analysedFilesBytes: null } as ILicenseData;
|
const empty = { analysedFilesBytes: null } as ILicenseData;
|
||||||
dataUntilCurrentMonth.splice(0, 0, empty);
|
dataUntilCurrentMonth.splice(0, 0, empty);
|
||||||
monthlyData.splice(0, 0, empty);
|
monthlyData.splice(0, 0, empty);
|
||||||
@ -60,11 +60,8 @@ export class LicenseAnalysisCapacityUsageComponent {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
data: dataUntilCurrentMonth.map((month, monthIndex) =>
|
data: dataUntilCurrentMonth.map((_, monthIndex) =>
|
||||||
month.analysedFilesBytes
|
monthlyData.slice(0, monthIndex + 1).reduce((acc, curr) => acc + (curr.analysedFilesBytes ?? 0), 0),
|
||||||
? month.analysedFilesBytes +
|
|
||||||
monthlyData.slice(0, monthIndex).reduce((acc, curr) => acc + (curr.analysedFilesBytes ?? 0), 0)
|
|
||||||
: 0,
|
|
||||||
),
|
),
|
||||||
label: this._translateService.instant('license-info-screen.analysis-capacity-usage.analyzed-cumulative'),
|
label: this._translateService.instant('license-info-screen.analysis-capacity-usage.analyzed-cumulative'),
|
||||||
yAxisID: 'y1',
|
yAxisID: 'y1',
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { LicenseService } from '@services/license.service';
|
|||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { ChartDataset } from 'chart.js';
|
import { ChartDataset } from 'chart.js';
|
||||||
import { ChartBlue, ChartGreen, ChartRed } from '../../utils/constants';
|
import { ChartBlue, ChartGreen, ChartRed } from '../../utils/constants';
|
||||||
import { getDataUntilCurrentMonth, getLabelsFromLicense, getLineConfig, isCurrentMonthAndYear } from '../../utils/functions';
|
import { getDataUntilCurrentMonth, getLabelsFromLicense, getLineConfig, isCurrentMonth } from '../../utils/functions';
|
||||||
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { ILicenseData } from '@red/domain';
|
import { ILicenseData } from '@red/domain';
|
||||||
@ -40,7 +40,7 @@ export class LicensePageUsageComponent {
|
|||||||
#getPagesDatasets(): ChartDataset[] {
|
#getPagesDatasets(): ChartDataset[] {
|
||||||
const monthlyData = [...this.licenseService.selectedLicenseReport.monthlyData];
|
const monthlyData = [...this.licenseService.selectedLicenseReport.monthlyData];
|
||||||
const dataUntilCurrentMonth = getDataUntilCurrentMonth(monthlyData);
|
const dataUntilCurrentMonth = getDataUntilCurrentMonth(monthlyData);
|
||||||
if (monthlyData.length === 1 || isCurrentMonthAndYear(monthlyData[0].startDate)) {
|
if (monthlyData.length === 1 || isCurrentMonth(monthlyData[0].startDate)) {
|
||||||
const empty = { numberOfAnalyzedPages: null } as ILicenseData;
|
const empty = { numberOfAnalyzedPages: null } as ILicenseData;
|
||||||
dataUntilCurrentMonth.splice(0, 0, empty);
|
dataUntilCurrentMonth.splice(0, 0, empty);
|
||||||
monthlyData.splice(0, 0, empty);
|
monthlyData.splice(0, 0, empty);
|
||||||
@ -63,11 +63,8 @@ export class LicensePageUsageComponent {
|
|||||||
order: 1,
|
order: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
data: dataUntilCurrentMonth.map((month, monthIndex) =>
|
data: dataUntilCurrentMonth.map((_, monthIndex) =>
|
||||||
month.numberOfAnalyzedPages
|
monthlyData.slice(0, monthIndex + 1).reduce((acc, curr) => acc + (curr.numberOfAnalyzedPages ?? 0), 0),
|
||||||
? month.numberOfAnalyzedPages +
|
|
||||||
monthlyData.slice(0, monthIndex).reduce((acc, curr) => acc + (curr.numberOfAnalyzedPages ?? 0), 0)
|
|
||||||
: 0,
|
|
||||||
),
|
),
|
||||||
label: this._translateService.instant('license-info-screen.page-usage.cumulative-pages'),
|
label: this._translateService.instant('license-info-screen.page-usage.cumulative-pages'),
|
||||||
yAxisID: 'y1',
|
yAxisID: 'y1',
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import { ComplexFillTarget } from 'chart.js/dist/types';
|
|||||||
|
|
||||||
const monthNames = dayjs.monthsShort();
|
const monthNames = dayjs.monthsShort();
|
||||||
const currentMonth = dayjs(Date.now()).month();
|
const currentMonth = dayjs(Date.now()).month();
|
||||||
const currentYear = dayjs(Date.now()).year();
|
|
||||||
|
|
||||||
export const verboseDate = (date: Dayjs) => `${monthNames[date.month()]} ${date.year()}`;
|
export const verboseDate = (date: Dayjs) => `${monthNames[date.month()]} ${date.year()}`;
|
||||||
|
|
||||||
@ -45,7 +44,7 @@ export const getLabelsFromLicense = (license: ILicenseReport) => {
|
|||||||
monthIterator = monthIterator.add(1, 'month');
|
monthIterator = monthIterator.add(1, 'month');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startMonth.month() === endMonth.month() || startMonth.month() === currentMonth) {
|
if (startMonth.isSame(endMonth, 'month') || isCurrentMonth(startMonth.toDate())) {
|
||||||
result.splice(0, 0, '');
|
result.splice(0, 0, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -53,9 +52,9 @@ export const getLabelsFromLicense = (license: ILicenseReport) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getDataUntilCurrentMonth = (monthlyData: ILicenseData[]) => {
|
export const getDataUntilCurrentMonth = (monthlyData: ILicenseData[]) => {
|
||||||
return monthlyData.filter(data => dayjs(data.startDate).month() <= currentMonth && dayjs(data.startDate).year() <= currentYear);
|
return monthlyData.filter(data => dayjs(data.startDate).isSameOrBefore(dayjs(Date.now()), 'month'));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isCurrentMonthAndYear = (date: Date | string) => {
|
export const isCurrentMonth = (date: Date | string) => {
|
||||||
return dayjs(date).month() === currentMonth && dayjs(date).year() === currentYear;
|
return dayjs(date).isSame(dayjs(Date.now()), 'month');
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { ChangeDetectorRef, Component, ElementRef, inject, OnInit, ViewChild } f
|
|||||||
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
import { MatIcon } from '@angular/material/icon';
|
||||||
import { MatSlider, MatSliderThumb } from '@angular/material/slider';
|
import { MatSlider, MatSliderThumb } from '@angular/material/slider';
|
||||||
import { MatTooltip } from '@angular/material/tooltip';
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { environment } from '@environments/environment';
|
import { environment } from '@environments/environment';
|
||||||
@ -46,6 +45,7 @@ import { ColorPickerModule } from 'ngx-color-picker';
|
|||||||
import { BehaviorSubject, firstValueFrom, Observable, of } from 'rxjs';
|
import { BehaviorSubject, firstValueFrom, Observable, of } from 'rxjs';
|
||||||
import { tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import { PaginatorComponent } from '../paginator/paginator.component';
|
import { PaginatorComponent } from '../paginator/paginator.component';
|
||||||
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
|
|
||||||
export const DEFAULT_WATERMARK: Partial<IWatermark> = {
|
export const DEFAULT_WATERMARK: Partial<IWatermark> = {
|
||||||
text: 'Watermark',
|
text: 'Watermark',
|
||||||
@ -85,11 +85,11 @@ interface WatermarkForm {
|
|||||||
HasScrollbarDirective,
|
HasScrollbarDirective,
|
||||||
NgForOf,
|
NgForOf,
|
||||||
NgClass,
|
NgClass,
|
||||||
MatTooltip,
|
|
||||||
MatIcon,
|
MatIcon,
|
||||||
MatSlider,
|
MatSlider,
|
||||||
ColorPickerModule,
|
ColorPickerModule,
|
||||||
MatSliderThumb,
|
MatSliderThumb,
|
||||||
|
MatTooltip,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class WatermarkScreenComponent implements OnInit {
|
export class WatermarkScreenComponent implements OnInit {
|
||||||
@ -269,7 +269,7 @@ export class WatermarkScreenComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
this.instance.Core.setCustomFontURL('https://' + window.location.host + this.#convertPath('/assets/pdftron'));
|
this.instance.Core.setCustomFontURL(window.location.origin + this.#convertPath('/assets/pdftron/fonts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#disableElements();
|
this.#disableElements();
|
||||||
|
|||||||
@ -158,6 +158,7 @@ export class AdminSideNavComponent implements OnInit {
|
|||||||
{
|
{
|
||||||
screen: 'info',
|
screen: 'info',
|
||||||
label: _('admin-side-nav.entity-info'),
|
label: _('admin-side-nav.entity-info'),
|
||||||
|
helpModeKey: 'entity_info',
|
||||||
show: true,
|
show: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
|||||||
export const digitalSignatureDialogTranslations = {
|
export const digitalSignatureDialogTranslations = {
|
||||||
title: {
|
title: {
|
||||||
beforeConfiguration: _('digital-signature-dialog.title.before-configuration'),
|
beforeConfiguration: _('digital-signature-dialog.title.before-configuration'),
|
||||||
pkcs: _('digital-signature-dialog.title.pkcs'),
|
PKCS: _('digital-signature-dialog.title.pkcs'),
|
||||||
kms: _('digital-signature-dialog.title.kms'),
|
KMS: _('digital-signature-dialog.title.kms'),
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@ -116,7 +116,7 @@ export class ConfigService {
|
|||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 'editDossier',
|
id: 'editDossier',
|
||||||
label: this._translateService.instant('dossier-overview.header-actions.edit'),
|
label: _('dossier-overview.header-actions.edit'),
|
||||||
action: () => this.#openEditDossierDialog(dossierId),
|
action: () => this.#openEditDossierDialog(dossierId),
|
||||||
icon: 'iqser:edit',
|
icon: 'iqser:edit',
|
||||||
hide: !this.#currentUser.isManager && !this._iqserPermissionsService.has(Roles.dossiers.edit),
|
hide: !this.#currentUser.isManager && !this._iqserPermissionsService.has(Roles.dossiers.edit),
|
||||||
|
|||||||
@ -56,7 +56,7 @@
|
|||||||
</iqser-workflow>
|
</iqser-workflow>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="dossierAttributes$ | async" [class.collapsed]="collapsedDetails" class="right-container" iqserHasScrollbar>
|
<div *ngIf="dossierAttributes$ | async" [class.collapsed]="collapsedDetails" class="right-container">
|
||||||
<redaction-dossier-details
|
<redaction-dossier-details
|
||||||
(toggleCollapse)="collapsedDetails = !collapsedDetails"
|
(toggleCollapse)="collapsedDetails = !collapsedDetails"
|
||||||
[dossierAttributes]="dossierAttributes"
|
[dossierAttributes]="dossierAttributes"
|
||||||
|
|||||||
@ -25,10 +25,7 @@
|
|||||||
width: 375px;
|
width: 375px;
|
||||||
min-width: 375px;
|
min-width: 375px;
|
||||||
padding: 16px 24px 16px 24px;
|
padding: 16px 24px 16px 24px;
|
||||||
|
overflow-y: auto;
|
||||||
&.has-scrollbar:hover {
|
|
||||||
padding-right: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
redaction-dossier-details {
|
redaction-dossier-details {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|||||||
@ -41,7 +41,7 @@ import { Roles } from '@users/roles';
|
|||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
import { convertFiles, Files, handleFileDrop } from '@utils/index';
|
import { convertFiles, Files, handleFileDrop } from '@utils/index';
|
||||||
import { merge, Observable } from 'rxjs';
|
import { merge, Observable } from 'rxjs';
|
||||||
import { filter, skip, switchMap, tap } from 'rxjs/operators';
|
import { filter, map, skip, switchMap, tap } from 'rxjs/operators';
|
||||||
import { ConfigService } from '../config.service';
|
import { ConfigService } from '../config.service';
|
||||||
import { BulkActionsService } from '../services/bulk-actions.service';
|
import { BulkActionsService } from '../services/bulk-actions.service';
|
||||||
import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service';
|
import { DossiersCacheService } from '@services/dossiers/dossiers-cache.service';
|
||||||
@ -145,8 +145,9 @@ export default class DossierOverviewScreenComponent extends ListingComponent<Fil
|
|||||||
|
|
||||||
get #dossierFilesChange$() {
|
get #dossierFilesChange$() {
|
||||||
return this._dossiersService.dossierFileChanges$.pipe(
|
return this._dossiersService.dossierFileChanges$.pipe(
|
||||||
filter(dossierId => dossierId === this.dossierId && !!this._dossiersCacheService.get(dossierId)),
|
map(changes => changes[this.dossierId]),
|
||||||
switchMap(dossierId => this._filesService.loadAll(dossierId)),
|
filter(changes => !!changes && !!this._dossiersCacheService.get(this.dossierId)),
|
||||||
|
switchMap(changes => this._filesService.loadByIds({ [this.dossierId]: changes }).pipe(map(files => files[this.dossierId]))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -147,13 +147,13 @@ export class AnnotationActionsComponent implements OnChanges {
|
|||||||
hideAnnotation() {
|
hideAnnotation() {
|
||||||
this._annotationManager.hide(this.viewerAnnotations);
|
this._annotationManager.hide(this.viewerAnnotations);
|
||||||
this._annotationManager.deselect();
|
this._annotationManager.deselect();
|
||||||
this._annotationManager.addToHidden(this.viewerAnnotations[0].Id);
|
this.viewerAnnotations.forEach(a => this._annotationManager.addToHidden(a.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
showAnnotation() {
|
showAnnotation() {
|
||||||
this._annotationManager.show(this.viewerAnnotations);
|
this._annotationManager.show(this.viewerAnnotations);
|
||||||
this._annotationManager.deselect();
|
this._annotationManager.deselect();
|
||||||
this._annotationManager.removeFromHidden(this.viewerAnnotations[0].Id);
|
this.viewerAnnotations.forEach(a => this._annotationManager.removeFromHidden(a.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
resize() {
|
resize() {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
right: 19px;
|
right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
|
|||||||
@ -3,21 +3,13 @@
|
|||||||
:host {
|
:host {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
|
@include common-mixins.scroll-bar;
|
||||||
&:hover {
|
|
||||||
overflow-y: auto;
|
|
||||||
@include common-mixins.scroll-bar;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.has-scrollbar:hover redaction-annotation-wrapper::ng-deep,
|
&.has-scrollbar:hover redaction-annotation-wrapper::ng-deep,
|
||||||
&::ng-deep.documine-wrapper {
|
&::ng-deep.documine-wrapper {
|
||||||
.annotation {
|
.annotation {
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
redaction-annotation-details {
|
|
||||||
right: 8px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -69,6 +69,7 @@ export class AnnotationsListComponent extends HasScrollbarDirective {
|
|||||||
this._multiSelectService.activate();
|
this._multiSelectService.activate();
|
||||||
}
|
}
|
||||||
this._listingService.selectAnnotations(annotation);
|
this._listingService.selectAnnotations(annotation);
|
||||||
|
this._annotationManager.setSelectedFromWorkload();
|
||||||
}
|
}
|
||||||
|
|
||||||
referenceClicked(annotation: AnnotationWrapper): void {
|
referenceClicked(annotation: AnnotationWrapper): void {
|
||||||
|
|||||||
@ -129,7 +129,7 @@
|
|||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
[translateParams]="{ page: pdf.currentPage(), count: activeAnnotations.length }"
|
[translateParams]="{ page: pdf.currentPage(), count: activeAnnotations().length }"
|
||||||
[translate]="'page'"
|
[translate]="'page'"
|
||||||
class="all-caps-label"
|
class="all-caps-label"
|
||||||
></span>
|
></span>
|
||||||
@ -160,7 +160,7 @@
|
|||||||
id="annotations-list"
|
id="annotations-list"
|
||||||
tabindex="1"
|
tabindex="1"
|
||||||
>
|
>
|
||||||
<ng-container *ngIf="pdf.currentPage() && !displayedAnnotations.get(pdf.currentPage())?.length">
|
<ng-container *ngIf="pdf.currentPage() && !displayedAnnotations().get(pdf.currentPage())?.length">
|
||||||
<iqser-empty-state
|
<iqser-empty-state
|
||||||
[horizontalPadding]="24"
|
[horizontalPadding]="24"
|
||||||
[text]="'file-preview.no-data.title' | translate"
|
[text]="'file-preview.no-data.title' | translate"
|
||||||
|
|||||||
@ -1,5 +1,17 @@
|
|||||||
import { AsyncPipe, NgIf, NgTemplateOutlet } from '@angular/common';
|
import { AsyncPipe, NgIf, NgTemplateOutlet } from '@angular/common';
|
||||||
import { ChangeDetectorRef, Component, computed, effect, ElementRef, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
computed,
|
||||||
|
effect,
|
||||||
|
ElementRef,
|
||||||
|
HostListener,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
signal,
|
||||||
|
untracked,
|
||||||
|
ViewChild,
|
||||||
|
} from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
import { MatIcon } from '@angular/material/icon';
|
||||||
import { MatTooltip } from '@angular/material/tooltip';
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
@ -46,6 +58,7 @@ import { PageExclusionComponent } from '../page-exclusion/page-exclusion.compone
|
|||||||
import { PagesComponent } from '../pages/pages.component';
|
import { PagesComponent } from '../pages/pages.component';
|
||||||
import { ReadonlyBannerComponent } from '../readonly-banner/readonly-banner.component';
|
import { ReadonlyBannerComponent } from '../readonly-banner/readonly-banner.component';
|
||||||
import { DocumentInfoComponent } from '../document-info/document-info.component';
|
import { DocumentInfoComponent } from '../document-info/document-info.component';
|
||||||
|
import { getLast } from '@utils/functions';
|
||||||
|
|
||||||
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
const COMMAND_KEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Escape'];
|
||||||
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
||||||
@ -90,7 +103,8 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
protected readonly currentPageIsExcluded = computed(() => this.state.file().excludedPages.includes(this.pdf.currentPage()));
|
protected readonly currentPageIsExcluded = computed(() => this.state.file().excludedPages.includes(this.pdf.currentPage()));
|
||||||
protected readonly translations = workloadTranslations;
|
protected readonly translations = workloadTranslations;
|
||||||
protected readonly isDocumine = getConfig().IS_DOCUMINE;
|
protected readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||||
displayedAnnotations = new Map<number, AnnotationWrapper[]>();
|
displayedAnnotations = signal(new Map<number, AnnotationWrapper[]>());
|
||||||
|
readonly activeAnnotations = computed(() => this.displayedAnnotations().get(this.pdf.currentPage()) || []);
|
||||||
displayedPages: number[] = [];
|
displayedPages: number[] = [];
|
||||||
pagesPanelActive = true;
|
pagesPanelActive = true;
|
||||||
|
|
||||||
@ -155,10 +169,6 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
get activeAnnotations(): AnnotationWrapper[] {
|
|
||||||
return this.displayedAnnotations.get(this.pdf.currentPage()) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
get showAnalysisDisabledBanner() {
|
get showAnalysisDisabledBanner() {
|
||||||
const file = this.state.file();
|
const file = this.state.file();
|
||||||
return this.isDocumine && file.excludedFromAutomaticAnalysis && file.workflowStatus !== WorkflowFileStatuses.APPROVED;
|
return this.isDocumine && file.excludedFromAutomaticAnalysis && file.workflowStatus !== WorkflowFileStatuses.APPROVED;
|
||||||
@ -215,12 +225,14 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectAllOnActivePage() {
|
selectAllOnActivePage() {
|
||||||
this.listingService.selectAnnotations(this.activeAnnotations);
|
const activeAnnotations = untracked(this.activeAnnotations);
|
||||||
|
this.listingService.selectAnnotations(activeAnnotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
deselectAllOnActivePage(): void {
|
deselectAllOnActivePage(): void {
|
||||||
this.listingService.deselect(this.activeAnnotations);
|
const activeAnnotations = untracked(this.activeAnnotations);
|
||||||
this.annotationManager.deselect(this.activeAnnotations);
|
this.listingService.deselect(activeAnnotations);
|
||||||
|
this.annotationManager.deselect(activeAnnotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('window:keyup', ['$event'])
|
@HostListener('window:keyup', ['$event'])
|
||||||
@ -322,31 +334,33 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
this.pdf.navigateTo(this.#nextPageWithAnnotations());
|
this.pdf.navigateTo(this.#nextPageWithAnnotations());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Debounce(15)
|
||||||
navigateAnnotations($event: KeyboardEvent) {
|
navigateAnnotations($event: KeyboardEvent) {
|
||||||
const currentPage = this.pdf.currentPage();
|
const currentPage = this.pdf.currentPage();
|
||||||
|
const activeAnnotations = untracked(this.activeAnnotations);
|
||||||
if (!this._firstSelectedAnnotation || currentPage !== this._firstSelectedAnnotation.pageNumber) {
|
if (!this._firstSelectedAnnotation || currentPage !== this._firstSelectedAnnotation.pageNumber) {
|
||||||
if (this.displayedPages.indexOf(currentPage) !== -1) {
|
if (this.displayedPages.indexOf(currentPage) !== -1) {
|
||||||
// Displayed page has annotations
|
// Displayed page has annotations
|
||||||
return this.listingService.selectAnnotations(this.activeAnnotations ? this.activeAnnotations[0] : null);
|
return this.listingService.selectAnnotations(activeAnnotations ? activeAnnotations[0] : null);
|
||||||
}
|
}
|
||||||
// Displayed page doesn't have annotations
|
// Displayed page doesn't have annotations
|
||||||
if ($event.key === 'ArrowDown') {
|
if ($event.key === 'ArrowDown') {
|
||||||
const nextPage = this.#nextPageWithAnnotations();
|
const nextPage = this.#nextPageWithAnnotations();
|
||||||
|
|
||||||
return this.listingService.selectAnnotations(this.displayedAnnotations.get(nextPage)[0]);
|
return this.listingService.selectAnnotations(this.displayedAnnotations().get(nextPage)[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const prevPage = this.#prevPageWithAnnotations();
|
const prevPage = this.#prevPageWithAnnotations();
|
||||||
const prevPageAnnotations = this.displayedAnnotations.get(prevPage);
|
const prevPageAnnotations = this.displayedAnnotations().get(prevPage);
|
||||||
|
|
||||||
return this.listingService.selectAnnotations(prevPageAnnotations[prevPageAnnotations.length - 1]);
|
return this.listingService.selectAnnotations(getLast(prevPageAnnotations));
|
||||||
}
|
}
|
||||||
|
|
||||||
const page = this._firstSelectedAnnotation.pageNumber;
|
const page = this._firstSelectedAnnotation.pageNumber;
|
||||||
const pageIdx = this.displayedPages.indexOf(page);
|
const pageIdx = this.displayedPages.indexOf(page);
|
||||||
const nextPageIdx = pageIdx + 1;
|
const nextPageIdx = pageIdx + 1;
|
||||||
const previousPageIdx = pageIdx - 1;
|
const previousPageIdx = pageIdx - 1;
|
||||||
const annotationsOnPage = this.displayedAnnotations.get(page);
|
const annotationsOnPage = this.displayedAnnotations().get(page);
|
||||||
const idx = annotationsOnPage.findIndex(a => a.id === this._firstSelectedAnnotation.id);
|
const idx = annotationsOnPage.findIndex(a => a.id === this._firstSelectedAnnotation.id);
|
||||||
|
|
||||||
if ($event.key === 'ArrowDown') {
|
if ($event.key === 'ArrowDown') {
|
||||||
@ -356,7 +370,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
} else if (nextPageIdx < this.displayedPages.length) {
|
} else if (nextPageIdx < this.displayedPages.length) {
|
||||||
// If not last page
|
// If not last page
|
||||||
for (let i = nextPageIdx; i < this.displayedPages.length; i++) {
|
for (let i = nextPageIdx; i < this.displayedPages.length; i++) {
|
||||||
const nextPageAnnotations = this.displayedAnnotations.get(this.displayedPages[i]);
|
const nextPageAnnotations = this.displayedAnnotations().get(this.displayedPages[i]);
|
||||||
if (nextPageAnnotations) {
|
if (nextPageAnnotations) {
|
||||||
this.listingService.selectAnnotations(nextPageAnnotations[0]);
|
this.listingService.selectAnnotations(nextPageAnnotations[0]);
|
||||||
break;
|
break;
|
||||||
@ -374,9 +388,9 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
if (pageIdx) {
|
if (pageIdx) {
|
||||||
// If not first page
|
// If not first page
|
||||||
for (let i = previousPageIdx; i >= 0; i--) {
|
for (let i = previousPageIdx; i >= 0; i--) {
|
||||||
const prevPageAnnotations = this.displayedAnnotations.get(this.displayedPages[i]);
|
const prevPageAnnotations = this.displayedAnnotations().get(this.displayedPages[i]);
|
||||||
if (prevPageAnnotations) {
|
if (prevPageAnnotations) {
|
||||||
this.listingService.selectAnnotations(prevPageAnnotations[prevPageAnnotations.length - 1]);
|
this.listingService.selectAnnotations(getLast(prevPageAnnotations));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,8 +427,8 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
annotations = annotations.filter(a => !a.isOCR);
|
annotations = annotations.filter(a => !a.isOCR);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.displayedAnnotations = this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary);
|
this.displayedAnnotations.set(this._annotationProcessingService.filterAndGroupAnnotations(annotations, primary, secondary));
|
||||||
const pagesThatDisplayAnnotations = [...this.displayedAnnotations.keys()];
|
const pagesThatDisplayAnnotations = [...this.displayedAnnotations().keys()];
|
||||||
const enabledFilters = this.filterService.enabledFlatFilters;
|
const enabledFilters = this.filterService.enabledFlatFilters;
|
||||||
if (enabledFilters.some(f => f.id === 'pages-without-annotations')) {
|
if (enabledFilters.some(f => f.id === 'pages-without-annotations')) {
|
||||||
if (enabledFilters.length === 1 && !onlyPageWithAnnotations) {
|
if (enabledFilters.length === 1 && !onlyPageWithAnnotations) {
|
||||||
@ -422,7 +436,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
} else {
|
} else {
|
||||||
this.displayedPages = [];
|
this.displayedPages = [];
|
||||||
}
|
}
|
||||||
this.displayedAnnotations.clear();
|
this.displayedAnnotations().clear();
|
||||||
} else if (enabledFilters.length || onlyPageWithAnnotations) {
|
} else if (enabledFilters.length || onlyPageWithAnnotations) {
|
||||||
this.displayedPages = pagesThatDisplayAnnotations;
|
this.displayedPages = pagesThatDisplayAnnotations;
|
||||||
} else {
|
} else {
|
||||||
@ -430,17 +444,18 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
}
|
}
|
||||||
this.displayedPages.sort((a, b) => a - b);
|
this.displayedPages.sort((a, b) => a - b);
|
||||||
|
|
||||||
return this.displayedAnnotations;
|
return this.displayedAnnotations();
|
||||||
}
|
}
|
||||||
|
|
||||||
#selectFirstAnnotationOnCurrentPageIfNecessary() {
|
#selectFirstAnnotationOnCurrentPageIfNecessary() {
|
||||||
const currentPage = this.pdf.currentPage();
|
const currentPage = this.pdf.currentPage();
|
||||||
|
const activeAnnotations = untracked(this.activeAnnotations);
|
||||||
if (
|
if (
|
||||||
(!this._firstSelectedAnnotation || currentPage !== this._firstSelectedAnnotation.pageNumber) &&
|
(!this._firstSelectedAnnotation || currentPage !== this._firstSelectedAnnotation.pageNumber) &&
|
||||||
this.displayedPages.indexOf(currentPage) >= 0 &&
|
this.displayedPages.indexOf(currentPage) >= 0 &&
|
||||||
this.activeAnnotations.length > 0
|
activeAnnotations.length > 0
|
||||||
) {
|
) {
|
||||||
this.listingService.selectAnnotations(this.activeAnnotations[0]);
|
this.listingService.selectAnnotations(activeAnnotations[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -479,7 +494,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
#nextPageWithAnnotations() {
|
#nextPageWithAnnotations() {
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
for (const page of this.displayedPages) {
|
for (const page of this.displayedPages) {
|
||||||
if (page > this.pdf.currentPage() && this.displayedAnnotations.get(page)) {
|
if (page > this.pdf.currentPage() && this.displayedAnnotations().get(page)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
++idx;
|
++idx;
|
||||||
@ -491,7 +506,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
let idx = this.displayedPages.length - 1;
|
let idx = this.displayedPages.length - 1;
|
||||||
const reverseDisplayedPages = [...this.displayedPages].reverse();
|
const reverseDisplayedPages = [...this.displayedPages].reverse();
|
||||||
for (const page of reverseDisplayedPages) {
|
for (const page of reverseDisplayedPages) {
|
||||||
if (page < this.pdf.currentPage() && this.displayedAnnotations.get(page)) {
|
if (page < this.pdf.currentPage() && this.displayedAnnotations().get(page)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
--idx;
|
--idx;
|
||||||
@ -520,4 +535,16 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
});
|
});
|
||||||
return listItemsMap;
|
return listItemsMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HostListener('click', ['$event'])
|
||||||
|
clickInsideWorkloadView($event: MouseEvent) {
|
||||||
|
$event?.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('document: click')
|
||||||
|
clickOutsideWorkloadView() {
|
||||||
|
if (this.multiSelectService.active() && !this._dialog.openDialogs.length) {
|
||||||
|
this.multiSelectService.deactivate();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
@use 'common-mixins';
|
||||||
|
|
||||||
.components-header {
|
.components-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -26,6 +28,7 @@ mat-icon {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
|
@include common-mixins.scroll-bar;
|
||||||
|
|
||||||
.component-row {
|
.component-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -47,6 +50,7 @@ mat-icon {
|
|||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
border-bottom: 1px solid var(--iqser-separator);
|
border-bottom: 1px solid var(--iqser-separator);
|
||||||
}
|
}
|
||||||
|
|
||||||
border-bottom: 1px solid var(--iqser-separator);
|
border-bottom: 1px solid var(--iqser-separator);
|
||||||
margin-left: 26px;
|
margin-left: 26px;
|
||||||
margin-right: 26px;
|
margin-right: 26px;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export class ViewSwitchComponent {
|
|||||||
});
|
});
|
||||||
protected readonly canSwitchToRedactedView = computed(() => {
|
protected readonly canSwitchToRedactedView = computed(() => {
|
||||||
const file = this._state.file();
|
const file = this._state.file();
|
||||||
return !file.analysisRequired && !file.excluded && !file.isError;
|
return !file.excluded && !file.isError;
|
||||||
});
|
});
|
||||||
protected readonly canSwitchToEarmarksView = computed(() => {
|
protected readonly canSwitchToEarmarksView = computed(() => {
|
||||||
const file = this._state.file();
|
const file = this._state.file();
|
||||||
|
|||||||
@ -3,9 +3,56 @@
|
|||||||
<div [translate]="'add-hint.dialog.title'" class="dialog-header heading-l"></div>
|
<div [translate]="'add-hint.dialog.title'" class="dialog-header heading-l"></div>
|
||||||
|
|
||||||
<div class="dialog-content redaction">
|
<div class="dialog-content redaction">
|
||||||
<div class="iqser-input-group w-450">
|
<div class="iqser-input-group w-full selected-text-group">
|
||||||
<label class="selected-text" [translate]="'add-hint.dialog.content.selected-text'"></label>
|
<div
|
||||||
{{ form.get('selectedText').value }}
|
[class.fixed-height-36]="dictionaryRequest"
|
||||||
|
[ngClass]="isEditingSelectedText ? 'flex relative' : 'flex-align-items-center'"
|
||||||
|
>
|
||||||
|
<div class="table">
|
||||||
|
<label>Value</label>
|
||||||
|
<div class="row">
|
||||||
|
<span
|
||||||
|
*ngIf="!isEditingSelectedText"
|
||||||
|
[innerHTML]="form.controls.selectedText.value"
|
||||||
|
[ngStyle]="{
|
||||||
|
'min-width': textWidth > maximumSelectedTextWidth ? '95%' : 'unset',
|
||||||
|
'max-width': textWidth > maximumSelectedTextWidth ? 0 : 'unset',
|
||||||
|
}"
|
||||||
|
></span>
|
||||||
|
<textarea
|
||||||
|
*ngIf="isEditingSelectedText"
|
||||||
|
[rows]="selectedTextRows"
|
||||||
|
[ngStyle]="{ width: maximumTextAreaWidth + 'px' }"
|
||||||
|
formControlName="selectedText"
|
||||||
|
iqserHasScrollbar
|
||||||
|
name="value"
|
||||||
|
type="text"
|
||||||
|
></textarea>
|
||||||
|
|
||||||
|
<iqser-circle-button
|
||||||
|
(action)="toggleEditingSelectedText()"
|
||||||
|
*ngIf="dictionaryRequest && !isEditingSelectedText"
|
||||||
|
[tooltip]="'redact-text.dialog.content.edit-text' | translate"
|
||||||
|
[size]="20"
|
||||||
|
[iconSize]="13"
|
||||||
|
icon="iqser:edit"
|
||||||
|
tooltipPosition="below"
|
||||||
|
></iqser-circle-button>
|
||||||
|
|
||||||
|
<iqser-circle-button
|
||||||
|
(action)="undoTextChange(); toggleEditingSelectedText()"
|
||||||
|
*ngIf="isEditingSelectedText"
|
||||||
|
[showDot]="initialText !== form.get('selectedText').value"
|
||||||
|
[tooltip]="'redact-text.dialog.content.revert-text' | translate"
|
||||||
|
[size]="20"
|
||||||
|
[iconSize]="13"
|
||||||
|
class="undo-button"
|
||||||
|
icon="red:undo"
|
||||||
|
tooltipPosition="below"
|
||||||
|
></iqser-circle-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<iqser-details-radio
|
<iqser-details-radio
|
||||||
|
|||||||
@ -1,3 +1,67 @@
|
|||||||
.dialog-content {
|
.dialog-content {
|
||||||
height: 400px;
|
height: 493px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selected-text-group > div {
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
span {
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iqser-circle-button {
|
||||||
|
padding-left: 10px;
|
||||||
|
|
||||||
|
&.undo-button {
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep mat-icon {
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.w-full {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-height-36 {
|
||||||
|
min-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea[name='value'] {
|
||||||
|
margin-top: 0;
|
||||||
|
min-height: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-width: calc(100% - 26px);
|
||||||
|
padding: 0 13px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
opacity: 0.7;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
background-color: var(--iqser-alt-background);
|
||||||
|
min-width: 100%;
|
||||||
|
|
||||||
|
span {
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
list-style-position: inside;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { NgForOf, NgIf } from '@angular/common';
|
import { NgClass, NgForOf, NgIf, NgStyle } from '@angular/common';
|
||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||||
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
|
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
|
||||||
@ -23,12 +23,14 @@ import { ActiveDossiersService } from '@services/dossiers/active-dossiers.servic
|
|||||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||||
import { Roles } from '@users/roles';
|
import { Roles } from '@users/roles';
|
||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
import { stringToBoolean } from '@utils/functions';
|
import { calcTextWidthInPixels, stringToBoolean } from '@utils/functions';
|
||||||
import { tap } from 'rxjs/operators';
|
import { tap } from 'rxjs/operators';
|
||||||
import { SystemDefaultOption, SystemDefaults } from '../../../account/utils/dialog-defaults';
|
import { SystemDefaultOption, SystemDefaults } from '../../../account/utils/dialog-defaults';
|
||||||
import { getRedactOrHintOptions } from '../../utils/dialog-options';
|
import { getRedactOrHintOptions } from '../../utils/dialog-options';
|
||||||
import { AddHintData, AddHintResult, RedactOrHintOption, RedactOrHintOptions } from '../../utils/dialog-types';
|
import { AddHintData, AddHintResult, RedactOrHintOption, RedactOrHintOptions } from '../../utils/dialog-types';
|
||||||
|
|
||||||
|
const MAXIMUM_TEXT_AREA_WIDTH = 421;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './add-hint-dialog.component.html',
|
templateUrl: './add-hint-dialog.component.html',
|
||||||
styleUrls: ['./add-hint-dialog.component.scss'],
|
styleUrls: ['./add-hint-dialog.component.scss'],
|
||||||
@ -49,6 +51,8 @@ import { AddHintData, AddHintResult, RedactOrHintOption, RedactOrHintOptions } f
|
|||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
MatDialogClose,
|
MatDialogClose,
|
||||||
NgForOf,
|
NgForOf,
|
||||||
|
NgClass,
|
||||||
|
NgStyle,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AddHintDialogComponent extends IqserDialogComponent<AddHintDialogComponent, AddHintData, AddHintResult> implements OnInit {
|
export class AddHintDialogComponent extends IqserDialogComponent<AddHintDialogComponent, AddHintData, AddHintResult> implements OnInit {
|
||||||
@ -58,9 +62,15 @@ export class AddHintDialogComponent extends IqserDialogComponent<AddHintDialogCo
|
|||||||
readonly roles = Roles;
|
readonly roles = Roles;
|
||||||
readonly iconButtonTypes = IconButtonTypes;
|
readonly iconButtonTypes = IconButtonTypes;
|
||||||
readonly options: DetailsRadioOption<RedactOrHintOption>[];
|
readonly options: DetailsRadioOption<RedactOrHintOption>[];
|
||||||
|
readonly initialText = this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value;
|
||||||
|
readonly maximumTextAreaWidth = MAXIMUM_TEXT_AREA_WIDTH;
|
||||||
|
readonly maximumSelectedTextWidth = 567;
|
||||||
dictionaryRequest = false;
|
dictionaryRequest = false;
|
||||||
dictionaries: Dictionary[] = [];
|
dictionaries: Dictionary[] = [];
|
||||||
form!: UntypedFormGroup;
|
form!: UntypedFormGroup;
|
||||||
|
isEditingSelectedText = false;
|
||||||
|
selectedTextRows = 1;
|
||||||
|
textWidth: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _activeDossiersService: ActiveDossiersService,
|
private readonly _activeDossiersService: ActiveDossiersService,
|
||||||
@ -83,6 +93,7 @@ export class AddHintDialogComponent extends IqserDialogComponent<AddHintDialogCo
|
|||||||
);
|
);
|
||||||
|
|
||||||
this.form = this.#getForm();
|
this.form = this.#getForm();
|
||||||
|
this.textWidth = calcTextWidthInPixels(this.form.controls.selectedText.value);
|
||||||
|
|
||||||
this.form
|
this.form
|
||||||
.get('option')
|
.get('option')
|
||||||
@ -97,6 +108,18 @@ export class AddHintDialogComponent extends IqserDialogComponent<AddHintDialogCo
|
|||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleEditingSelectedText() {
|
||||||
|
this.isEditingSelectedText = !this.isEditingSelectedText;
|
||||||
|
if (this.isEditingSelectedText) {
|
||||||
|
const width = calcTextWidthInPixels(this.form.controls.selectedText.value);
|
||||||
|
this.selectedTextRows = Math.ceil(width / MAXIMUM_TEXT_AREA_WIDTH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
undoTextChange() {
|
||||||
|
this.form.patchValue({ selectedText: this.initialText });
|
||||||
|
}
|
||||||
|
|
||||||
get displayedDictionaryLabel() {
|
get displayedDictionaryLabel() {
|
||||||
const dictType = this.form.get('dictionary').value;
|
const dictType = this.form.get('dictionary').value;
|
||||||
if (dictType) {
|
if (dictType) {
|
||||||
|
|||||||
@ -160,7 +160,11 @@ export class RedactRecommendationDialogComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
#setDictionaries() {
|
#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() {
|
#selectReason() {
|
||||||
|
|||||||
@ -203,7 +203,11 @@ export class RedactTextDialogComponent
|
|||||||
}
|
}
|
||||||
|
|
||||||
#setDictionaries() {
|
#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 {
|
#getForm(): FormGroup {
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<mat-select formControlName="dictionary">
|
<mat-select formControlName="dictionary">
|
||||||
<mat-select-trigger>{{ displayedDictionaryLabel }}</mat-select-trigger>
|
<mat-select-trigger>{{ displayedDictionaryLabel }}</mat-select-trigger>
|
||||||
<mat-option [value]="entity.type">
|
<mat-option [value]="entity?.type">
|
||||||
<span> {{ redaction.typeLabel }} </span>
|
<span> {{ redaction.typeLabel }} </span>
|
||||||
</mat-option>
|
</mat-option>
|
||||||
</mat-select>
|
</mat-select>
|
||||||
|
|||||||
@ -71,6 +71,7 @@ import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.
|
|||||||
import { FileHeaderComponent } from './components/file-header/file-header.component';
|
import { FileHeaderComponent } from './components/file-header/file-header.component';
|
||||||
import { StructuredComponentManagementComponent } from './components/structured-component-management/structured-component-management.component';
|
import { StructuredComponentManagementComponent } from './components/structured-component-management/structured-component-management.component';
|
||||||
import { DocumentInfoService } from './services/document-info.service';
|
import { DocumentInfoService } from './services/document-info.service';
|
||||||
|
import { ANNOTATION_ACTION_ICONS, ANNOTATION_ACTIONS } from './utils/constants';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: './file-preview-screen.component.html',
|
templateUrl: './file-preview-screen.component.html',
|
||||||
@ -152,6 +153,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
this._fileDataService.loadAnnotations(file).then();
|
this._fileDataService.loadAnnotations(file).then();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
const file = this.state.file();
|
||||||
|
if (file.analysisRequired && !file.excludedFromAutomaticAnalysis) {
|
||||||
|
this._reanalysisService.reanalyzeFilesForDossier([file], file.dossierId, { force: true }).then();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
effect(
|
effect(
|
||||||
() => {
|
() => {
|
||||||
if (this._documentViewer.loaded()) {
|
if (this._documentViewer.loaded()) {
|
||||||
@ -295,11 +303,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
this._viewerHeaderService.enableLoadAllAnnotations(); // Reset the button state (since the viewer is reused between files)
|
this._viewerHeaderService.enableLoadAllAnnotations(); // Reset the button state (since the viewer is reused between files)
|
||||||
super.ngOnDetach();
|
super.ngOnDetach();
|
||||||
this.pdf.instance.UI.hotkeys.off('esc');
|
this.pdf.instance.UI.hotkeys.off('esc');
|
||||||
|
this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
|
||||||
this._changeRef.markForCheck();
|
this._changeRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.pdf.instance.UI.hotkeys.off('esc');
|
this.pdf.instance.UI.hotkeys.off('esc');
|
||||||
|
this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
|
||||||
super.ngOnDestroy();
|
super.ngOnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,6 +334,31 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bind()
|
||||||
|
handleViewerClick(event: MouseEvent) {
|
||||||
|
this._ngZone.run(() => {
|
||||||
|
if (event.isTrusted) {
|
||||||
|
const clickedElement = event.target as HTMLElement;
|
||||||
|
const actionIconClicked = ANNOTATION_ACTION_ICONS.some(action =>
|
||||||
|
(clickedElement as HTMLImageElement).src?.includes(action),
|
||||||
|
);
|
||||||
|
const actionClicked = ANNOTATION_ACTIONS.some(action => clickedElement.getAttribute('aria-label')?.includes(action));
|
||||||
|
if (this._multiSelectService.active() && !actionIconClicked && !actionClicked) {
|
||||||
|
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) {
|
async ngOnAttach(previousRoute: ActivatedRouteSnapshot) {
|
||||||
if (!this.state.file().canBeOpened) {
|
if (!this.state.file().canBeOpened) {
|
||||||
return this.#navigateToDossier();
|
return this.#navigateToDossier();
|
||||||
@ -350,14 +385,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
this.userPreferenceService.saveLastOpenedFileForDossier(this.dossierId, this.fileId).then();
|
this.userPreferenceService.saveLastOpenedFileForDossier(this.dossierId, this.fileId).then();
|
||||||
this.#subscribeToFileUpdates();
|
this.#subscribeToFileUpdates();
|
||||||
|
|
||||||
if (file?.analysisRequired && !file.excludedFromAutomaticAnalysis) {
|
|
||||||
await this._reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pdfProxyService.configureElements();
|
this.pdfProxyService.configureElements();
|
||||||
this.#restoreOldFilters();
|
this.#restoreOldFilters();
|
||||||
this.pdf.instance.UI.hotkeys.on('esc', this.handleEscInsideViewer);
|
this.pdf.instance.UI.hotkeys.on('esc', this.handleEscInsideViewer);
|
||||||
this._viewerHeaderService.resetLayers();
|
this._viewerHeaderService.resetLayers();
|
||||||
|
this.pdf.instance.UI.iframeWindow.document.removeEventListener('click', this.handleViewerClick);
|
||||||
|
this.pdf.instance.UI.iframeWindow.document.addEventListener('click', this.handleViewerClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
|
openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) {
|
||||||
|
|||||||
@ -1,17 +1,16 @@
|
|||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Injectable, OnDestroy } from '@angular/core';
|
import { effect, Injectable, untracked } from '@angular/core';
|
||||||
import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui';
|
import { EntitiesService, ListingService, SearchService } from '@iqser/common-ui';
|
||||||
import { filter, tap } from 'rxjs/operators';
|
|
||||||
import { MultiSelectService } from './multi-select.service';
|
import { MultiSelectService } from './multi-select.service';
|
||||||
import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service';
|
import { PdfViewer } from '../../pdf-viewer/services/pdf-viewer.service';
|
||||||
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
||||||
import { Subscription } from 'rxjs';
|
|
||||||
import { FilterService } from '@iqser/common-ui/lib/filtering';
|
import { FilterService } from '@iqser/common-ui/lib/filtering';
|
||||||
import { SortingService } from '@iqser/common-ui/lib/sorting';
|
import { SortingService } from '@iqser/common-ui/lib/sorting';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AnnotationsListingService extends ListingService<AnnotationWrapper> implements OnDestroy {
|
export class AnnotationsListingService extends ListingService<AnnotationWrapper> {
|
||||||
readonly #subscriptions: Subscription;
|
readonly selectedLength = toSignal(this.selectedLength$);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected readonly _filterService: FilterService,
|
protected readonly _filterService: FilterService,
|
||||||
@ -24,23 +23,22 @@ export class AnnotationsListingService extends ListingService<AnnotationWrapper>
|
|||||||
) {
|
) {
|
||||||
super(_filterService, _searchService, _entitiesService, _sortingService);
|
super(_filterService, _searchService, _entitiesService, _sortingService);
|
||||||
|
|
||||||
this.#subscriptions = this.selectedLength$
|
effect(
|
||||||
.pipe(
|
() => {
|
||||||
filter(length => length > 1),
|
if (this.selectedLength() > 1) {
|
||||||
tap(() => this._multiSelectService.activate()),
|
this._multiSelectService.activate();
|
||||||
)
|
}
|
||||||
.subscribe();
|
},
|
||||||
}
|
{ allowSignalWrites: true },
|
||||||
|
);
|
||||||
ngOnDestroy() {
|
|
||||||
this.#subscriptions.unsubscribe();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectAnnotations(annotations: AnnotationWrapper[] | AnnotationWrapper) {
|
selectAnnotations(annotations: AnnotationWrapper[] | AnnotationWrapper) {
|
||||||
annotations = Array.isArray(annotations) ? annotations : [annotations];
|
annotations = Array.isArray(annotations) ? annotations : [annotations];
|
||||||
const pageNumber = annotations[annotations.length - 1].pageNumber;
|
const pageNumber = annotations[annotations.length - 1].pageNumber;
|
||||||
|
|
||||||
const annotationsToSelect = this._multiSelectService.active() ? [...this.selected, ...annotations] : annotations;
|
const multiSelectActive = untracked(this._multiSelectService.active);
|
||||||
|
const annotationsToSelect = multiSelectActive ? [...this.selected, ...annotations] : annotations;
|
||||||
this.#selectAnnotations(annotationsToSelect, pageNumber);
|
this.#selectAnnotations(annotationsToSelect, pageNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,16 +47,18 @@ export class AnnotationsListingService extends ListingService<AnnotationWrapper>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._multiSelectService.inactive()) {
|
const multiSelectInactive = untracked(this._multiSelectService.inactive);
|
||||||
|
if (multiSelectInactive) {
|
||||||
this._annotationManager.deselect();
|
this._annotationManager.deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pageNumber === this._pdf.currentPage()) {
|
const currentPage = untracked(this._pdf.currentPage);
|
||||||
|
if (pageNumber === currentPage) {
|
||||||
return this._annotationManager.jumpAndSelect(annotations);
|
return this._annotationManager.jumpAndSelect(annotations);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._pdf.navigateTo(pageNumber);
|
this._pdf.navigateTo(pageNumber);
|
||||||
// wait for page to be loaded and to draw annotations
|
// wait for page to be loaded and to draw annotations
|
||||||
setTimeout(() => this._annotationManager.jumpAndSelect(annotations), 300);
|
setTimeout(() => this._annotationManager.jumpAndSelect(annotations), 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,7 +137,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
|||||||
|
|
||||||
this.#logger.info('[REDACTION_LOG] Redaction log loaded', redactionLog);
|
this.#logger.info('[REDACTION_LOG] Redaction log loaded', redactionLog);
|
||||||
let annotations = await this.#convertData(redactionLog);
|
let annotations = await this.#convertData(redactionLog);
|
||||||
this.#checkMissingTypes();
|
if (!this.#annotations().length && annotations.length !== this.missingTypes.size) this.#checkMissingTypes();
|
||||||
annotations = this.#isIqserDevMode ? annotations : annotations.filter(a => !a.isFalsePositive);
|
annotations = this.#isIqserDevMode ? annotations : annotations.filter(a => !a.isFalsePositive);
|
||||||
this.#annotations.set(annotations);
|
this.#annotations.set(annotations);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -121,7 +121,8 @@ export class FilePreviewStateService {
|
|||||||
|
|
||||||
get #dossierFilesChange$() {
|
get #dossierFilesChange$() {
|
||||||
return this._dossiersService.dossierFileChanges$.pipe(
|
return this._dossiersService.dossierFileChanges$.pipe(
|
||||||
filter(dossierId => dossierId === this.dossierId),
|
map(changes => changes[this.dossierId]),
|
||||||
|
filter(fileIds => fileIds && fileIds.length > 0),
|
||||||
map(() => true),
|
map(() => true),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { computed, Injectable, Signal, signal } from '@angular/core';
|
import { computed, Injectable, Signal, signal, untracked } from '@angular/core';
|
||||||
import { ViewModeService } from './view-mode.service';
|
import { ViewModeService } from './view-mode.service';
|
||||||
import { FilePreviewStateService } from './file-preview-state.service';
|
import { FilePreviewStateService } from './file-preview-state.service';
|
||||||
import { ViewMode, ViewModes } from '@red/domain';
|
import { ViewMode, ViewModes } from '@red/domain';
|
||||||
@ -13,13 +13,17 @@ export class MultiSelectService {
|
|||||||
|
|
||||||
readonly #active = signal(false);
|
readonly #active = signal(false);
|
||||||
|
|
||||||
constructor(protected readonly _viewModeService: ViewModeService, protected readonly _state: FilePreviewStateService) {
|
constructor(
|
||||||
|
protected readonly _viewModeService: ViewModeService,
|
||||||
|
protected readonly _state: FilePreviewStateService,
|
||||||
|
) {
|
||||||
this.active = this.#active.asReadonly();
|
this.active = this.#active.asReadonly();
|
||||||
this.inactive = computed(() => !this.#active());
|
this.inactive = computed(() => !this.#active());
|
||||||
}
|
}
|
||||||
|
|
||||||
activate() {
|
activate() {
|
||||||
if (this.enabled()) {
|
const enabled = untracked(this.enabled);
|
||||||
|
if (enabled) {
|
||||||
this.#active.set(true);
|
this.#active.set(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { computed, effect, inject, Injectable, NgZone } from '@angular/core';
|
import { computed, effect, inject, Injectable, NgZone, untracked } from '@angular/core';
|
||||||
import { getConfig, IqserPermissionsService } from '@iqser/common-ui';
|
import { getConfig, IqserPermissionsService } from '@iqser/common-ui';
|
||||||
import { getCurrentUser } from '@iqser/common-ui/lib/users';
|
import { getCurrentUser } from '@iqser/common-ui/lib/users';
|
||||||
import { isJustOne, shareDistinctLast, UI_ROOT_PATH_FN } from '@iqser/common-ui/lib/utils';
|
import { isJustOne, shareDistinctLast, UI_ROOT_PATH_FN } from '@iqser/common-ui/lib/utils';
|
||||||
@ -387,10 +387,10 @@ export class PdfProxyService {
|
|||||||
this._ngZone.run(() => {
|
this._ngZone.run(() => {
|
||||||
if (allAreVisible) {
|
if (allAreVisible) {
|
||||||
this._annotationManager.hide(viewerAnnotations);
|
this._annotationManager.hide(viewerAnnotations);
|
||||||
this._annotationManager.addToHidden(viewerAnnotations[0].Id);
|
viewerAnnotations.forEach(a => this._annotationManager.addToHidden(a.Id));
|
||||||
} else {
|
} else {
|
||||||
this._annotationManager.show(viewerAnnotations);
|
this._annotationManager.show(viewerAnnotations);
|
||||||
this._annotationManager.removeFromHidden(viewerAnnotations[0].Id);
|
viewerAnnotations.forEach(a => this._annotationManager.removeFromHidden(a.Id));
|
||||||
}
|
}
|
||||||
this._annotationManager.deselect();
|
this._annotationManager.deselect();
|
||||||
});
|
});
|
||||||
@ -402,11 +402,14 @@ export class PdfProxyService {
|
|||||||
|
|
||||||
const annotationChangesAllowed = !this.#isDocumine || !this._state.file().excludedFromAutomaticAnalysis;
|
const annotationChangesAllowed = !this.#isDocumine || !this._state.file().excludedFromAutomaticAnalysis;
|
||||||
const somePending = annotationWrappers.some(a => a.pending);
|
const somePending = annotationWrappers.some(a => a.pending);
|
||||||
|
const selectedFromWorkload = untracked(this._annotationManager.selectedFromWorkload);
|
||||||
|
|
||||||
actions =
|
actions =
|
||||||
this._multiSelectService.inactive() && !this._documentViewer.selectedText.length && !somePending
|
(this._multiSelectService.inactive() || !selectedFromWorkload) && !this._documentViewer.selectedText.length && !somePending
|
||||||
? [...actions, ...this._pdfAnnotationActionsService.get(annotationWrappers, annotationChangesAllowed)]
|
? [...actions, ...this._pdfAnnotationActionsService.get(annotationWrappers, annotationChangesAllowed)]
|
||||||
: [];
|
: [];
|
||||||
this._pdf.instance.UI.annotationPopup.update(actions);
|
this._pdf.instance.UI.annotationPopup.update(actions);
|
||||||
|
this._annotationManager.resetSelectedFromWorkload();
|
||||||
}
|
}
|
||||||
|
|
||||||
#getTitle(type: ManualRedactionEntryType) {
|
#getTitle(type: ManualRedactionEntryType) {
|
||||||
|
|||||||
@ -55,3 +55,31 @@ export const TextPopups = {
|
|||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const HIDE_SKIPPED = 'hide-skipped';
|
export const HIDE_SKIPPED = 'hide-skipped';
|
||||||
|
|
||||||
|
export const ANNOTATION_ACTION_ICONS = [
|
||||||
|
'resize',
|
||||||
|
'edit',
|
||||||
|
'trash',
|
||||||
|
'check',
|
||||||
|
'thumb-up',
|
||||||
|
'pdftron-action-add-redaction',
|
||||||
|
'visibility-off',
|
||||||
|
] as const;
|
||||||
|
export const ANNOTATION_ACTIONS = [
|
||||||
|
'Resize',
|
||||||
|
'Größe ändern',
|
||||||
|
'Edit',
|
||||||
|
'Bearbeiten',
|
||||||
|
'Remove',
|
||||||
|
'Entfernen',
|
||||||
|
'Accept recommendation',
|
||||||
|
'Empfehlung annehmen',
|
||||||
|
'Force redaction',
|
||||||
|
'Schwärzung erzwingen',
|
||||||
|
'Force hint',
|
||||||
|
'Hinweis erzwingen',
|
||||||
|
'Redact',
|
||||||
|
'Schwärzen',
|
||||||
|
'Hide',
|
||||||
|
'Ausblenden',
|
||||||
|
] as const;
|
||||||
|
|||||||
@ -152,6 +152,7 @@ export const getRemoveRedactionOptions = (
|
|||||||
descriptionParams: {
|
descriptionParams: {
|
||||||
value: redactions[0].value,
|
value: redactions[0].value,
|
||||||
type: redactions[0].HINT ? 'hint' : redactions[0].typeLabel,
|
type: redactions[0].HINT ? 'hint' : redactions[0].typeLabel,
|
||||||
|
isImage: redactions[0].isImage ? 'image' : redactions[0].typeLabel,
|
||||||
},
|
},
|
||||||
icon: PIN_ICON,
|
icon: PIN_ICON,
|
||||||
value: RemoveRedactionOptions.ONLY_HERE,
|
value: RemoveRedactionOptions.ONLY_HERE,
|
||||||
@ -161,7 +162,11 @@ export const getRemoveRedactionOptions = (
|
|||||||
options.push({
|
options.push({
|
||||||
label: isBulk ? translations.IN_DOSSIER.labelBulk : translations.IN_DOSSIER.label,
|
label: isBulk ? translations.IN_DOSSIER.labelBulk : translations.IN_DOSSIER.label,
|
||||||
description: isBulk ? translations.IN_DOSSIER.descriptionBulk : translations.IN_DOSSIER.description,
|
description: isBulk ? translations.IN_DOSSIER.descriptionBulk : translations.IN_DOSSIER.description,
|
||||||
descriptionParams: { value: redactions[0].value, type: redactions[0].HINT ? 'hint' : redactions[0].typeLabel },
|
descriptionParams: {
|
||||||
|
value: redactions[0].value,
|
||||||
|
type: redactions[0].HINT ? 'hint' : redactions[0].typeLabel,
|
||||||
|
isImage: redactions[0].isImage ? 'image' : redactions[0].typeLabel,
|
||||||
|
},
|
||||||
icon: FOLDER_ICON,
|
icon: FOLDER_ICON,
|
||||||
value: RemoveRedactionOptions.IN_DOSSIER,
|
value: RemoveRedactionOptions.IN_DOSSIER,
|
||||||
extraOption: !isDocumine
|
extraOption: !isDocumine
|
||||||
@ -182,6 +187,7 @@ export const getRemoveRedactionOptions = (
|
|||||||
value: redactions[0].value,
|
value: redactions[0].value,
|
||||||
type: redactions[0].typeLabel,
|
type: redactions[0].typeLabel,
|
||||||
context: falsePositiveContext[0],
|
context: falsePositiveContext[0],
|
||||||
|
isImage: redactions[0].isImage ? 'image' : redactions[0].typeLabel,
|
||||||
},
|
},
|
||||||
icon: FOLDER_ICON,
|
icon: FOLDER_ICON,
|
||||||
value: RemoveRedactionOptions.DO_NOT_RECOMMEND,
|
value: RemoveRedactionOptions.DO_NOT_RECOMMEND,
|
||||||
@ -201,6 +207,7 @@ export const getRemoveRedactionOptions = (
|
|||||||
value: redactions[0].value,
|
value: redactions[0].value,
|
||||||
type: redactions[0].typeLabel,
|
type: redactions[0].typeLabel,
|
||||||
context: falsePositiveContext[0],
|
context: falsePositiveContext[0],
|
||||||
|
isImage: redactions[0].isImage ? 'image' : redactions[0].typeLabel,
|
||||||
},
|
},
|
||||||
icon: REMOVE_FROM_DICT_ICON,
|
icon: REMOVE_FROM_DICT_ICON,
|
||||||
value: RemoveRedactionOptions.FALSE_POSITIVE,
|
value: RemoveRedactionOptions.FALSE_POSITIVE,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { inject, Injectable, signal } from '@angular/core';
|
import { inject, Injectable, signal } from '@angular/core';
|
||||||
import { bool, List } from '@iqser/common-ui/lib/utils';
|
import { bool, Debounce, List } from '@iqser/common-ui/lib/utils';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Core } from '@pdftron/webviewer';
|
import { Core } from '@pdftron/webviewer';
|
||||||
import { getLast, urlFileId } from '@utils/functions';
|
import { getLast, urlFileId } from '@utils/functions';
|
||||||
@ -20,6 +20,7 @@ const MOVE_OPTION = 'move';
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class REDAnnotationManager {
|
export class REDAnnotationManager {
|
||||||
readonly #hidden = signal(new Set<string>());
|
readonly #hidden = signal(new Set<string>());
|
||||||
|
readonly #selectedFromWorkload = signal(false);
|
||||||
#manager: AnnotationManager;
|
#manager: AnnotationManager;
|
||||||
readonly #logger = inject(NGXLogger);
|
readonly #logger = inject(NGXLogger);
|
||||||
readonly #annotationSelected$ = new Subject<[Annotation[], string]>();
|
readonly #annotationSelected$ = new Subject<[Annotation[], string]>();
|
||||||
@ -27,6 +28,7 @@ export class REDAnnotationManager {
|
|||||||
resizingAnnotationId?: string = undefined;
|
resizingAnnotationId?: string = undefined;
|
||||||
annotationHasBeenResized?: boolean = false;
|
annotationHasBeenResized?: boolean = false;
|
||||||
readonly hidden = this.#hidden.asReadonly();
|
readonly hidden = this.#hidden.asReadonly();
|
||||||
|
readonly selectedFromWorkload = this.#selectedFromWorkload.asReadonly();
|
||||||
|
|
||||||
get selected() {
|
get selected() {
|
||||||
return this.#manager.getSelectedAnnotations();
|
return this.#manager.getSelectedAnnotations();
|
||||||
@ -161,6 +163,15 @@ export class REDAnnotationManager {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setSelectedFromWorkload() {
|
||||||
|
this.#selectedFromWorkload.set(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Debounce()
|
||||||
|
resetSelectedFromWorkload() {
|
||||||
|
this.#selectedFromWorkload.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
#getById(annotation: AnnotationWrapper | string) {
|
#getById(annotation: AnnotationWrapper | string) {
|
||||||
return this.#manager.getAnnotationById(getId(annotation));
|
return this.#manager.getAnnotationById(getId(annotation));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -147,7 +147,7 @@ export class PdfViewer {
|
|||||||
this.#instance = await this.#getInstance(htmlElement);
|
this.#instance = await this.#getInstance(htmlElement);
|
||||||
|
|
||||||
if (environment.production) {
|
if (environment.production) {
|
||||||
this.#instance.Core.setCustomFontURL('https://' + window.location.host + this.#convertPath('/assets/pdftron'));
|
this.#instance.Core.setCustomFontURL(window.location.origin + this.#convertPath('/assets/pdftron/fonts'));
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.runWithCleanup(async () => {
|
await this.runWithCleanup(async () => {
|
||||||
@ -158,13 +158,14 @@ export class PdfViewer {
|
|||||||
|
|
||||||
this.pageChanged$ = this.#pageChanged$.pipe(shareDistinctLast());
|
this.pageChanged$ = this.#pageChanged$.pipe(shareDistinctLast());
|
||||||
this.#totalPages$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(pages => this.#totalPages.set(pages));
|
this.#totalPages$.pipe(takeUntilDestroyed(this.#destroyRef)).subscribe(pages => this.#totalPages.set(pages));
|
||||||
this.#setSelectionMode();
|
this.#setSelectionMode(this.#config.SELECTION_MODE);
|
||||||
this.#configureElements();
|
this.#configureElements();
|
||||||
this.#disableHotkeys();
|
this.#disableHotkeys();
|
||||||
this.#getSelectedText();
|
this.#getSelectedText();
|
||||||
this.#listenForCommandF();
|
this.#listenForCommandF();
|
||||||
this.#listenForEsc();
|
this.#listenForEsc();
|
||||||
this.#clearSearchResultsWhenVisibilityChanged();
|
this.#clearSearchResultsWhenVisibilityChanged();
|
||||||
|
this.#listenForSpace();
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.#instance;
|
return this.#instance;
|
||||||
@ -287,6 +288,19 @@ export class PdfViewer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#listenForSpace() {
|
||||||
|
this.#instance.UI.hotkeys.on('space', {
|
||||||
|
keydown: e => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.#setSelectionMode('rectangular');
|
||||||
|
},
|
||||||
|
keyup: e => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.#setSelectionMode('structural');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#getSearchOption(optionId: string): boolean {
|
#getSearchOption(optionId: string): boolean {
|
||||||
const iframeWindow = this.#instance.UI.iframeWindow;
|
const iframeWindow = this.#instance.UI.iframeWindow;
|
||||||
const checkbox = iframeWindow.document.getElementById(optionId) as HTMLInputElement;
|
const checkbox = iframeWindow.document.getElementById(optionId) as HTMLInputElement;
|
||||||
@ -348,9 +362,9 @@ export class PdfViewer {
|
|||||||
this.#instance.UI.disableElements(USELESS_ELEMENTS);
|
this.#instance.UI.disableElements(USELESS_ELEMENTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
#setSelectionMode(): void {
|
#setSelectionMode(mode: string): void {
|
||||||
const textTool = this.#instance.Core.Tools.TextTool as unknown as TextTool;
|
const textTool = this.#instance.Core.Tools.TextTool as unknown as TextTool;
|
||||||
textTool.SELECTION_MODE = this.#config.SELECTION_MODE;
|
textTool.SELECTION_MODE = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
#getInstance(htmlElement: HTMLElement) {
|
#getInstance(htmlElement: HTMLElement) {
|
||||||
|
|||||||
@ -42,12 +42,16 @@ export class EditDossierDownloadPackageComponent
|
|||||||
{
|
{
|
||||||
#existsWatermarks$: Observable<boolean>;
|
#existsWatermarks$: Observable<boolean>;
|
||||||
form: FormGroup;
|
form: FormGroup;
|
||||||
downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(
|
downloadTypes: { key: DownloadFileType; label: string }[] = [
|
||||||
(type: DownloadFileType) => ({
|
'ORIGINAL',
|
||||||
key: type,
|
'PREVIEW',
|
||||||
label: downloadTypesTranslations[type],
|
'OPTIMIZED_PREVIEW',
|
||||||
}),
|
'DELTA_PREVIEW',
|
||||||
);
|
'REDACTED',
|
||||||
|
].map((type: DownloadFileType) => ({
|
||||||
|
key: type,
|
||||||
|
label: downloadTypesTranslations[type],
|
||||||
|
}));
|
||||||
availableReportTypes: IReportTemplate[] = [];
|
availableReportTypes: IReportTemplate[] = [];
|
||||||
readonly roles = Roles;
|
readonly roles = Roles;
|
||||||
@Input() dossier: Dossier;
|
@Input() dossier: Dossier;
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import utc from 'dayjs/plugin/utc';
|
|||||||
import localeData from 'dayjs/plugin/localeData';
|
import localeData from 'dayjs/plugin/localeData';
|
||||||
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||||
|
import isSameOrBefore from 'dayjs/plugin/isSameOrBefore';
|
||||||
|
|
||||||
export interface DayJsDateAdapterOptions {
|
export interface DayJsDateAdapterOptions {
|
||||||
/**
|
/**
|
||||||
@ -232,6 +233,7 @@ export class CustomDateAdapter extends DateAdapter<Dayjs> {
|
|||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
dayjs.extend(customParseFormat);
|
dayjs.extend(customParseFormat);
|
||||||
dayjs.extend(localeData);
|
dayjs.extend(localeData);
|
||||||
|
dayjs.extend(isSameOrBefore);
|
||||||
|
|
||||||
this.setLocale(dateLocale);
|
this.setLocale(dateLocale);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
<ng-container *ngIf="!filter.icon">
|
<ng-container *ngIf="!filter.icon">
|
||||||
<div *ngIf="filter.id === 'comment'">
|
<mat-icon *ngIf="filter.id === 'comment'" svgIcon="red:comment"></mat-icon>
|
||||||
<mat-icon svgIcon="red:comment"></mat-icon>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<redaction-annotation-icon
|
<redaction-annotation-icon
|
||||||
*ngIf="filter.id !== 'comment'"
|
*ngIf="filter.id !== 'comment'"
|
||||||
|
|||||||
@ -12,6 +12,6 @@
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
opacity: 50%;
|
opacity: 50%;
|
||||||
line-height: 16px;
|
line-height: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -71,12 +71,16 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On
|
|||||||
readonly roles = Roles;
|
readonly roles = Roles;
|
||||||
readonly iconButtonTypes = IconButtonTypes;
|
readonly iconButtonTypes = IconButtonTypes;
|
||||||
hasDueDate = false;
|
hasDueDate = false;
|
||||||
readonly downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(
|
readonly downloadTypes: { key: DownloadFileType; label: string }[] = [
|
||||||
(type: DownloadFileType) => ({
|
'ORIGINAL',
|
||||||
key: type,
|
'PREVIEW',
|
||||||
label: downloadTypesTranslations[type],
|
'OPTIMIZED_PREVIEW',
|
||||||
}),
|
'DELTA_PREVIEW',
|
||||||
);
|
'REDACTED',
|
||||||
|
].map((type: DownloadFileType) => ({
|
||||||
|
key: type,
|
||||||
|
label: downloadTypesTranslations[type],
|
||||||
|
}));
|
||||||
dossierTemplates: IDossierTemplate[];
|
dossierTemplates: IDossierTemplate[];
|
||||||
availableReportTypes: IReportTemplate[] = [];
|
availableReportTypes: IReportTemplate[] = [];
|
||||||
dossierTemplateId: string;
|
dossierTemplateId: string;
|
||||||
|
|||||||
@ -90,7 +90,7 @@ export class DownloadDialogComponent extends IqserDialogComponent<DownloadDialog
|
|||||||
}
|
}
|
||||||
|
|
||||||
get #formDownloadTypes() {
|
get #formDownloadTypes() {
|
||||||
return ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED']
|
return ['ORIGINAL', 'PREVIEW', 'OPTIMIZED_PREVIEW', 'DELTA_PREVIEW', 'REDACTED']
|
||||||
.map((type: DownloadFileType) => ({
|
.map((type: DownloadFileType) => ({
|
||||||
key: type,
|
key: type,
|
||||||
label: downloadTypesForDownloadTranslations[type],
|
label: downloadTypesForDownloadTranslations[type],
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
|||||||
import { HeadersConfiguration } from '@iqser/common-ui/lib/utils';
|
import { HeadersConfiguration } from '@iqser/common-ui/lib/utils';
|
||||||
import { LicenseService } from '@services/license.service';
|
import { LicenseService } from '@services/license.service';
|
||||||
import { LicenseFeatures } from '../../admin/screens/license/utils/constants';
|
import { LicenseFeatures } from '../../admin/screens/license/utils/constants';
|
||||||
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
|
|
||||||
export interface ActiveUpload {
|
export interface ActiveUpload {
|
||||||
subscription: Subscription;
|
subscription: Subscription;
|
||||||
@ -43,6 +44,7 @@ export class FileUploadService extends GenericService<IFileUploadResult> impleme
|
|||||||
private readonly _errorMessageService: ErrorMessageService,
|
private readonly _errorMessageService: ErrorMessageService,
|
||||||
private readonly _licenseService: LicenseService,
|
private readonly _licenseService: LicenseService,
|
||||||
private readonly _toaster: Toaster,
|
private readonly _toaster: Toaster,
|
||||||
|
private readonly _userPreferenceService: UserPreferenceService,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
const fileFetch$ = this.#fetchFiles$.pipe(
|
const fileFetch$ = this.#fetchFiles$.pipe(
|
||||||
@ -76,7 +78,7 @@ export class FileUploadService extends GenericService<IFileUploadResult> impleme
|
|||||||
const maxSizeBytes = maxSizeMB * 1024 * 1024;
|
const maxSizeBytes = maxSizeMB * 1024 * 1024;
|
||||||
const dossierFiles = this._filesMapService.get(dossierId);
|
const dossierFiles = this._filesMapService.get(dossierId);
|
||||||
const supportMsOfficeFormats = this._licenseService.getFeature(LicenseFeatures.SUPPORT_MS_OFFICE_FORMATS)?.value as boolean;
|
const supportMsOfficeFormats = this._licenseService.getFeature(LicenseFeatures.SUPPORT_MS_OFFICE_FORMATS)?.value as boolean;
|
||||||
let option: OverwriteFileOption = localStorage.getItem('overwriteFileOption') as OverwriteFileOption;
|
let option: OverwriteFileOption | 'undefined' = this._userPreferenceService.getOverwriteFileOption();
|
||||||
for (let idx = 0; idx < files.length; ++idx) {
|
for (let idx = 0; idx < files.length; ++idx) {
|
||||||
const file = files[idx];
|
const file = files[idx];
|
||||||
let currentOption = option;
|
let currentOption = option;
|
||||||
@ -95,14 +97,14 @@ export class FileUploadService extends GenericService<IFileUploadResult> impleme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (dossierFiles.find(pf => pf.filename === file.file.name)) {
|
} else if (dossierFiles.find(pf => pf.filename === file.file.name)) {
|
||||||
if (!option) {
|
if (option === 'undefined') {
|
||||||
const res = await this._dialogService.openOverwriteFileDialog(file.file.name);
|
const res = await this._dialogService.openOverwriteFileDialog(file.file.name);
|
||||||
if (res.cancel) {
|
if (res.cancel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res.rememberChoice) {
|
if (res.rememberChoice) {
|
||||||
localStorage.setItem('overwriteFileOption', res.option);
|
await this._userPreferenceService.saveOverwriteFileOption(res.option);
|
||||||
}
|
}
|
||||||
|
|
||||||
currentOption = res.option;
|
currentOption = res.option;
|
||||||
|
|||||||
@ -1,58 +1,56 @@
|
|||||||
import { GenericService, LAST_CHECKED_OFFSET, QueryParam, ROOT_CHANGES_KEY } from '@iqser/common-ui';
|
import { GenericService, LAST_CHECKED_OFFSET, ROOT_CHANGES_KEY } from '@iqser/common-ui';
|
||||||
import { Dossier, DossierStats, IDossierChanges } from '@red/domain';
|
import { Dossier, IChangesDetails } from '@red/domain';
|
||||||
import { forkJoin, Observable, of, Subscription, throwError, timer } from 'rxjs';
|
import { forkJoin, Observable, Subscription, timer } from 'rxjs';
|
||||||
import { catchError, filter, map, switchMap, take, tap } from 'rxjs/operators';
|
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
|
||||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { ActiveDossiersService } from './active-dossiers.service';
|
import { ActiveDossiersService } from './active-dossiers.service';
|
||||||
import { ArchivedDossiersService } from './archived-dossiers.service';
|
import { ArchivedDossiersService } from './archived-dossiers.service';
|
||||||
import { inject, Injectable, OnDestroy } from '@angular/core';
|
import { inject, Injectable, OnDestroy } from '@angular/core';
|
||||||
import { DashboardStatsService } from '../dossier-templates/dashboard-stats.service';
|
import { DashboardStatsService } from '../dossier-templates/dashboard-stats.service';
|
||||||
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
|
||||||
import { List } from '@iqser/common-ui/lib/utils';
|
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { filterEventsOnPages } from '@utils/operators';
|
import { filterEventsOnPages } from '@utils/operators';
|
||||||
|
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({ providedIn: 'root' })
|
||||||
export class DossiersChangesService extends GenericService<Dossier> implements OnDestroy {
|
export class DossiersChangesService extends GenericService<Dossier> implements OnDestroy {
|
||||||
|
protected readonly _defaultModelPath = 'dossier';
|
||||||
readonly #subscription = new Subscription();
|
readonly #subscription = new Subscription();
|
||||||
readonly #activeDossiersService = inject(ActiveDossiersService);
|
readonly #activeDossiersService = inject(ActiveDossiersService);
|
||||||
readonly #archivedDossiersService = inject(ArchivedDossiersService);
|
readonly #archivedDossiersService = inject(ArchivedDossiersService);
|
||||||
readonly #dashboardStatsService = inject(DashboardStatsService);
|
readonly #dashboardStatsService = inject(DashboardStatsService);
|
||||||
|
readonly #dossierStatsService = inject(DossierStatsService);
|
||||||
readonly #logger = inject(NGXLogger);
|
readonly #logger = inject(NGXLogger);
|
||||||
readonly #router = inject(Router);
|
readonly #router = inject(Router);
|
||||||
protected readonly _defaultModelPath = 'dossier';
|
|
||||||
|
|
||||||
loadOnlyChanged(): Observable<IDossierChanges> {
|
loadOnlyChanged(): Observable<IChangesDetails> {
|
||||||
const removeIfNotFound = (id: string) =>
|
const load = (changes: IChangesDetails) => this.#load(changes.dossierChanges.map(d => d.dossierId));
|
||||||
catchError((error: unknown) => {
|
|
||||||
if (error instanceof HttpErrorResponse && error.status === HttpStatusCode.NotFound) {
|
|
||||||
this.#activeDossiersService.remove(id);
|
|
||||||
this.#archivedDossiersService.remove(id);
|
|
||||||
return of([]);
|
|
||||||
}
|
|
||||||
return throwError(() => error);
|
|
||||||
});
|
|
||||||
|
|
||||||
const load = (changes: IDossierChanges) =>
|
const loadStats = (change: IChangesDetails) => {
|
||||||
changes.map(change => this.#load(change.dossierId).pipe(removeIfNotFound(change.dossierId)));
|
const dossierStatsToLoad = new Set<string>();
|
||||||
|
change.dossierChanges.forEach(dossierChange => dossierStatsToLoad.add(dossierChange.dossierId));
|
||||||
|
change.fileChanges.forEach(fileChange => dossierStatsToLoad.add(fileChange.dossierId));
|
||||||
|
return this.#dossierStatsService.getFor(Array.from(dossierStatsToLoad));
|
||||||
|
};
|
||||||
|
|
||||||
return this.hasChangesDetails$().pipe(
|
return this.hasChangesDetails$().pipe(
|
||||||
tap(changes => this.#logger.info('[DOSSIERS_CHANGES] Found changes', changes)),
|
tap(changes => this.#logger.info('[DOSSIERS_CHANGES] Found changes', changes)),
|
||||||
switchMap(dossierChanges =>
|
switchMap(dossierChanges =>
|
||||||
forkJoin([...load(dossierChanges), this.#dashboardStatsService.loadAll().pipe(take(1))]).pipe(map(() => dossierChanges)),
|
forkJoin([load(dossierChanges), loadStats(dossierChanges), this.#dashboardStatsService.loadAll().pipe(take(1))]).pipe(
|
||||||
|
map(() => dossierChanges),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasChangesDetails$(): Observable<IDossierChanges> {
|
hasChangesDetails$(): Observable<IChangesDetails> {
|
||||||
const body = { value: this._lastCheckedForChanges.get(ROOT_CHANGES_KEY) };
|
const body = { value: this._lastCheckedForChanges.get(ROOT_CHANGES_KEY) };
|
||||||
const dateBeforeRequest = new Date(Date.now() - LAST_CHECKED_OFFSET).toISOString();
|
const dateBeforeRequest = new Date(Date.now() - LAST_CHECKED_OFFSET).toISOString();
|
||||||
|
|
||||||
this.#logger.info('[DOSSIERS_CHANGES] Check with Last Checked Date', body.value);
|
this.#logger.info('[DOSSIERS_CHANGES] Check with Last Checked Date', body.value);
|
||||||
|
|
||||||
return this._post<IDossierChanges>(body, `${this._defaultModelPath}/changes/details`).pipe(
|
return this._post<IChangesDetails>(body, `${this._defaultModelPath}/changes/details/v2`).pipe(
|
||||||
filter(changes => changes.length > 0),
|
filter(changes => changes.dossierChanges.length > 0 || changes.fileChanges.length > 0),
|
||||||
tap(() => this._lastCheckedForChanges.set(ROOT_CHANGES_KEY, dateBeforeRequest)),
|
tap(() => this._lastCheckedForChanges.set(ROOT_CHANGES_KEY, dateBeforeRequest)),
|
||||||
tap(() => this.#logger.info('[DOSSIERS_CHANGES] Save Last Checked Date value', dateBeforeRequest)),
|
tap(() => this.#logger.info('[DOSSIERS_CHANGES] Save Last Checked Date value', dateBeforeRequest)),
|
||||||
);
|
);
|
||||||
@ -75,17 +73,27 @@ export class DossiersChangesService extends GenericService<Dossier> implements O
|
|||||||
this.#subscription.unsubscribe();
|
this.#subscription.unsubscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
#load(id: string): Observable<DossierStats[]> {
|
getByIds(ids: string[]) {
|
||||||
const queryParams: List<QueryParam> = [{ key: 'includeArchived', value: true }];
|
return super._post<Record<string, Dossier>>({ value: ids }, `${this._defaultModelPath}/by-id`);
|
||||||
return super._getOne([id], this._defaultModelPath, queryParams).pipe(
|
}
|
||||||
map(entity => new Dossier(entity)),
|
|
||||||
switchMap((dossier: Dossier) => {
|
#load(ids: string[]): Observable<Dossier[]> {
|
||||||
if (dossier.isArchived) {
|
return this.getByIds(ids).pipe(
|
||||||
this.#activeDossiersService.remove(dossier.id);
|
map(entity => {
|
||||||
return this.#archivedDossiersService.updateDossier(dossier);
|
return Object.values(entity).map(dossier => new Dossier(dossier));
|
||||||
}
|
}),
|
||||||
this.#archivedDossiersService.remove(dossier.id);
|
map((dossiers: Dossier[]) => {
|
||||||
return this.#activeDossiersService.updateDossier(dossier);
|
const archivedDossiers = dossiers.filter(dossier => dossier.isArchived);
|
||||||
|
const deletedDossiers = dossiers.filter(dossier => dossier.isSoftDeleted);
|
||||||
|
const activeDossiers = dossiers.filter(dossier => !dossier.isArchived && !dossier.isSoftDeleted);
|
||||||
|
|
||||||
|
archivedDossiers.forEach(dossier => this.#activeDossiersService.remove(dossier.id));
|
||||||
|
activeDossiers.forEach(dossier => this.#archivedDossiersService.remove(dossier.id));
|
||||||
|
deletedDossiers.forEach(dossier => this.#activeDossiersService.remove(dossier.id));
|
||||||
|
|
||||||
|
this.#activeDossiersService.updateDossiers(activeDossiers);
|
||||||
|
this.#archivedDossiersService.updateDossiers(archivedDossiers);
|
||||||
|
return dossiers;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { EntitiesService, Toaster } from '@iqser/common-ui';
|
import { EntitiesService, Toaster } from '@iqser/common-ui';
|
||||||
import { Dossier, DossierStats, IDossier, IDossierChanges, IDossierRequest } from '@red/domain';
|
import { Dossier, DossierFileChanges, DossierStats, IChangesDetails, IDossier, IDossierRequest } from '@red/domain';
|
||||||
import { Observable, of, Subject } from 'rxjs';
|
import { Observable, of, Subject } from 'rxjs';
|
||||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { inject } from '@angular/core';
|
import { inject } from '@angular/core';
|
||||||
@ -17,7 +17,7 @@ export abstract class DossiersService extends EntitiesService<IDossier, Dossier>
|
|||||||
protected readonly _toaster = inject(Toaster);
|
protected readonly _toaster = inject(Toaster);
|
||||||
protected readonly _entityClass = Dossier;
|
protected readonly _entityClass = Dossier;
|
||||||
protected abstract readonly _defaultModelPath: string;
|
protected abstract readonly _defaultModelPath: string;
|
||||||
readonly dossierFileChanges$ = new Subject<string>();
|
readonly dossierFileChanges$ = new Subject<DossierFileChanges>();
|
||||||
abstract readonly routerPath: string;
|
abstract readonly routerPath: string;
|
||||||
|
|
||||||
createOrUpdate(dossier: IDossierRequest): Observable<Dossier> {
|
createOrUpdate(dossier: IDossierRequest): Observable<Dossier> {
|
||||||
@ -52,7 +52,18 @@ export abstract class DossiersService extends EntitiesService<IDossier, Dossier>
|
|||||||
return this._dossierStatsService.getFor([dossier.id]);
|
return this._dossierStatsService.getFor([dossier.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
emitFileChanges(dossierChanges: IDossierChanges): void {
|
updateDossiers(dossier: Dossier[]): void {
|
||||||
dossierChanges.filter(change => change.fileChanges).forEach(change => this.dossierFileChanges$.next(change.dossierId));
|
dossier.forEach(d => this.replace(d));
|
||||||
|
}
|
||||||
|
|
||||||
|
emitFileChanges(changes: IChangesDetails): void {
|
||||||
|
const changeModel: DossierFileChanges = {};
|
||||||
|
changes.fileChanges.forEach(change => {
|
||||||
|
if (!changeModel[change.dossierId]) {
|
||||||
|
changeModel[change.dossierId] = [];
|
||||||
|
}
|
||||||
|
changeModel[change.dossierId].push(change.fileId);
|
||||||
|
});
|
||||||
|
this.dossierFileChanges$.next(changeModel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -157,8 +157,9 @@ export class DictionaryService extends EntitiesService<IDictionary, Dictionary>
|
|||||||
.filter(d => d.model['typeId'] && (d.hasDictionary || d.addToDictionaryAction));
|
.filter(d => d.model['typeId'] && (d.hasDictionary || d.addToDictionaryAction));
|
||||||
}
|
}
|
||||||
|
|
||||||
getRedactTextDictionaries(dossierId: string, dossierDictionaryOnly: boolean): Dictionary[] {
|
getRedactTextDictionaries(dossierId: string, dossierDictionaryOnly: boolean, dossierTemplateId: string): Dictionary[] {
|
||||||
return this.#extractDossierLevelTypes(dossierId)
|
const types = dossierDictionaryOnly ? this.#extractDossierLevelTypes(dossierId) : this.getDictionariesOptions(dossierTemplateId);
|
||||||
|
return types
|
||||||
.filter(d => d.model['typeId'] && !d.hint && d.addToDictionaryAction && (dossierDictionaryOnly || !d.dossierDictionaryOnly))
|
.filter(d => d.model['typeId'] && !d.hint && d.addToDictionaryAction && (dossierDictionaryOnly || !d.dossierDictionaryOnly))
|
||||||
.sort((a, b) => a.label.localeCompare(b.label));
|
.sort((a, b) => a.label.localeCompare(b.label));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { EntitiesService, isArray, QueryParam } from '@iqser/common-ui';
|
import { EntitiesService, isArray, QueryParam } from '@iqser/common-ui';
|
||||||
import { List, mapEach } from '@iqser/common-ui/lib/utils';
|
import { List, mapEach } from '@iqser/common-ui/lib/utils';
|
||||||
import { File, IFile } from '@red/domain';
|
import { DossierFileChanges, File, IFile } from '@red/domain';
|
||||||
import { UserService } from '@users/user.service';
|
import { UserService } from '@users/user.service';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
@ -27,8 +27,35 @@ export class FilesService extends EntitiesService<IFile, File> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadByIds(dossierFileChanges: DossierFileChanges) {
|
||||||
|
const filesByDossier$ = super
|
||||||
|
._post<{ value: Record<string, IFile[]> }>({ value: dossierFileChanges }, `${this._defaultModelPath}/by-id`)
|
||||||
|
.pipe(
|
||||||
|
map(response => {
|
||||||
|
const filesByDossier = response.value;
|
||||||
|
const result: Record<string, File[]> = {};
|
||||||
|
for (const key of Object.keys(filesByDossier)) {
|
||||||
|
result[key] = filesByDossier[key].map(file => new File(file, this._userService.getName(file.assignee)));
|
||||||
|
result[key].forEach(file => this._logger.info('[FILE] Loaded', file));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
return filesByDossier$.pipe(
|
||||||
|
tap(files => {
|
||||||
|
for (const key of Object.keys(files)) {
|
||||||
|
const notDeletedFiles = files[key].filter(file => !file.deleted);
|
||||||
|
const deletedFiles = files[key].filter(file => file.deleted);
|
||||||
|
this._filesMapService.replace(key, notDeletedFiles);
|
||||||
|
deletedFiles.map(file => file.id).forEach(id => this._filesMapService.delete(key, id));
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/** Reload dossier files + stats. */
|
/** Reload dossier files + stats. */
|
||||||
loadAll(dossierId: string) {
|
loadAll(dossierId: string) {
|
||||||
|
console.log('loadAll');
|
||||||
const files$ = this.getFor(dossierId).pipe(
|
const files$ = this.getFor(dossierId).pipe(
|
||||||
mapEach(file => new File(file, this._userService.getName(file.assignee))),
|
mapEach(file => new File(file, this._userService.getName(file.assignee))),
|
||||||
tap(file => this._logger.info('[FILE] Loaded', file)),
|
tap(file => this._logger.info('[FILE] Loaded', file)),
|
||||||
|
|||||||
@ -95,7 +95,7 @@ export class NotificationsService extends EntitiesService<INotification, Notific
|
|||||||
}
|
}
|
||||||
|
|
||||||
#getDossierHref(dossier: Dossier): string {
|
#getDossierHref(dossier: Dossier): string {
|
||||||
return dossier ? `${dossier.routerLink}` : null;
|
return dossier ? `${this.#appBaseHref}${dossier.routerLink}` : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
#getUsername(userId: string | undefined) {
|
#getUsername(userId: string | undefined) {
|
||||||
|
|||||||
@ -409,11 +409,7 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#canReanalyseFile(file: File, dossier: Dossier): boolean {
|
#canReanalyseFile(file: File, dossier: Dossier): boolean {
|
||||||
return (
|
return dossier.isActive && ((this.isAssigneeOrApprover(file, dossier) && file.analysisRequired) || file.isError);
|
||||||
dossier.isActive &&
|
|
||||||
((this.isAssigneeOrApprover(file, dossier) && file.analysisRequired) ||
|
|
||||||
(file.isError && (this.isOwner(dossier) || this.isFileAssignee(file))))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
|
#canEnableAutoAnalysis(file: File, dossier: Dossier): boolean {
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { DownloadFileType } from '@red/domain';
|
|||||||
export const downloadTypesTranslations: { [key in DownloadFileType]: string } = {
|
export const downloadTypesTranslations: { [key in DownloadFileType]: string } = {
|
||||||
ORIGINAL: _('download-type.original'),
|
ORIGINAL: _('download-type.original'),
|
||||||
PREVIEW: _('download-type.preview'),
|
PREVIEW: _('download-type.preview'),
|
||||||
|
OPTIMIZED_PREVIEW: _('download-type.optimized-preview'),
|
||||||
REDACTED: _('download-type.redacted'),
|
REDACTED: _('download-type.redacted'),
|
||||||
ANNOTATED: _('download-type.annotated'),
|
ANNOTATED: _('download-type.annotated'),
|
||||||
FLATTEN: _('download-type.flatten'),
|
FLATTEN: _('download-type.flatten'),
|
||||||
@ -13,6 +14,7 @@ export const downloadTypesTranslations: { [key in DownloadFileType]: string } =
|
|||||||
export const downloadTypesForDownloadTranslations: { [key in DownloadFileType]: string } = {
|
export const downloadTypesForDownloadTranslations: { [key in DownloadFileType]: string } = {
|
||||||
ORIGINAL: _('download-type.original'),
|
ORIGINAL: _('download-type.original'),
|
||||||
PREVIEW: _('download-type.preview'),
|
PREVIEW: _('download-type.preview'),
|
||||||
|
OPTIMIZED_PREVIEW: _('download-type.optimized-preview'),
|
||||||
REDACTED: _('download-type.redacted-only'),
|
REDACTED: _('download-type.redacted-only'),
|
||||||
ANNOTATED: _('download-type.annotated'),
|
ANNOTATED: _('download-type.annotated'),
|
||||||
FLATTEN: _('download-type.flatten'),
|
FLATTEN: _('download-type.flatten'),
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import { ProcessingFileStatus, WorkflowFileStatus } from '@red/domain';
|
|||||||
export const workflowFileStatusTranslations: { [key in WorkflowFileStatus]: string } = {
|
export const workflowFileStatusTranslations: { [key in WorkflowFileStatus]: string } = {
|
||||||
APPROVED: _('file-status.approved'),
|
APPROVED: _('file-status.approved'),
|
||||||
NEW: _('file-status.new'),
|
NEW: _('file-status.new'),
|
||||||
UNASSIGNED: _('file-status.unassigned'),
|
|
||||||
UNDER_APPROVAL: _('file-status.under-approval'),
|
UNDER_APPROVAL: _('file-status.under-approval'),
|
||||||
UNDER_REVIEW: _('file-status.under-review'),
|
UNDER_REVIEW: _('file-status.under-review'),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { IqserUserPreferenceService, ListingMode } from '@iqser/common-ui';
|
import { IqserUserPreferenceService, ListingMode } from '@iqser/common-ui';
|
||||||
import { SystemDefaultOption, SystemDefaultType } from '../modules/account/utils/dialog-defaults';
|
import { SystemDefaultOption, SystemDefaultType } from '../modules/account/utils/dialog-defaults';
|
||||||
import { RedactOrHintOption, RemoveRedactionOption } from '../modules/file-preview/utils/dialog-types';
|
import { RedactOrHintOption, RemoveRedactionOption } from '../modules/file-preview/utils/dialog-types';
|
||||||
|
import { OverwriteFileOption } from '@red/domain';
|
||||||
|
|
||||||
export const PreferencesKeys = {
|
export const PreferencesKeys = {
|
||||||
dossierRecent: 'Dossier-Recent',
|
dossierRecent: 'Dossier-Recent',
|
||||||
@ -22,6 +23,7 @@ export const PreferencesKeys = {
|
|||||||
removeRedactionDefaultExtraOption: 'Remove-Redaction-Default-Extra',
|
removeRedactionDefaultExtraOption: 'Remove-Redaction-Default-Extra',
|
||||||
removeRecommendationDefaultExtraOption: 'Remove-Recommendation-Default-Extra',
|
removeRecommendationDefaultExtraOption: 'Remove-Recommendation-Default-Extra',
|
||||||
removeHintDefaultExtraOption: 'Remove-Hint-Default-Extra',
|
removeHintDefaultExtraOption: 'Remove-Hint-Default-Extra',
|
||||||
|
rememberOverwriteFileOption: 'Remember-Overwrite-File',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
@ -179,4 +181,12 @@ export class UserPreferenceService extends IqserUserPreferenceService {
|
|||||||
async saveRemoveRecommendationDefaultExtraOption(defaultOption: boolean | string): Promise<void> {
|
async saveRemoveRecommendationDefaultExtraOption(defaultOption: boolean | string): Promise<void> {
|
||||||
await this.save(PreferencesKeys.removeRecommendationDefaultExtraOption, defaultOption.toString());
|
await this.save(PreferencesKeys.removeRecommendationDefaultExtraOption, defaultOption.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getOverwriteFileOption(): OverwriteFileOption | 'undefined' {
|
||||||
|
return this._getAttribute(PreferencesKeys.rememberOverwriteFileOption, 'undefined') as OverwriteFileOption | 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveOverwriteFileOption(preference: OverwriteFileOption | 'undefined') {
|
||||||
|
await this.save(PreferencesKeys.rememberOverwriteFileOption, preference);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -206,11 +206,14 @@
|
|||||||
"generic": "Speichern des Benutzers fehlgeschlagen."
|
"generic": "Speichern des Benutzers fehlgeschlagen."
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
|
"account-setup": "User account setup",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"first-name": "Vorname",
|
"first-name": "Vorname",
|
||||||
"last-name": "Nachname",
|
"last-name": "Nachname",
|
||||||
"reset-password": "Passwort zurücksetzen",
|
"reset-password": "Passwort zurücksetzen",
|
||||||
"role": "Rolle"
|
"role": "Rolle",
|
||||||
|
"send-email": "Do not send email requesting the user to set a password",
|
||||||
|
"send-email-explanation": "Select this option if you use SSO. Please note that you will need to inform the user directly."
|
||||||
},
|
},
|
||||||
"title": "{type, select, edit{Benutzer bearbeiten} create{Neuen Benutzer erstellen} other{}}"
|
"title": "{type, select, edit{Benutzer bearbeiten} create{Neuen Benutzer erstellen} other{}}"
|
||||||
},
|
},
|
||||||
@ -271,9 +274,6 @@
|
|||||||
"watermarks": "Wasserzeichen"
|
"watermarks": "Wasserzeichen"
|
||||||
},
|
},
|
||||||
"analysis-disabled": "",
|
"analysis-disabled": "",
|
||||||
"annotation": {
|
|
||||||
"pending": "(Analyse steht aus)"
|
|
||||||
},
|
|
||||||
"annotation-actions": {
|
"annotation-actions": {
|
||||||
"accept-recommendation": {
|
"accept-recommendation": {
|
||||||
"label": "Empfehlung annehmen"
|
"label": "Empfehlung annehmen"
|
||||||
@ -329,14 +329,14 @@
|
|||||||
"error": "Rekategorisierung des Bilds fehlgeschlagen: {error}",
|
"error": "Rekategorisierung des Bilds fehlgeschlagen: {error}",
|
||||||
"success": "Bild wurde einer neuen Kategorie zugeordnet."
|
"success": "Bild wurde einer neuen Kategorie zugeordnet."
|
||||||
},
|
},
|
||||||
"remove": {
|
|
||||||
"error": "Entfernen der Schwärzung fehlgeschlagen: {error}",
|
|
||||||
"success": "Schwärzung wurde entfernt"
|
|
||||||
},
|
|
||||||
"remove-hint": {
|
"remove-hint": {
|
||||||
"error": "Entfernen des Hinweises fehlgeschlagen: {error}",
|
"error": "Entfernen des Hinweises fehlgeschlagen: {error}",
|
||||||
"success": "Hinweis wurde entfernt"
|
"success": "Hinweis wurde entfernt"
|
||||||
},
|
},
|
||||||
|
"remove": {
|
||||||
|
"error": "Entfernen der Schwärzung fehlgeschlagen: {error}",
|
||||||
|
"success": "Schwärzung wurde entfernt"
|
||||||
|
},
|
||||||
"undo": {
|
"undo": {
|
||||||
"error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}",
|
"error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}",
|
||||||
"success": "Rücksetzung erfolgreich"
|
"success": "Rücksetzung erfolgreich"
|
||||||
@ -349,15 +349,15 @@
|
|||||||
"remove-highlights": {
|
"remove-highlights": {
|
||||||
"label": "Ausgewählte Markierungen entfernen"
|
"label": "Ausgewählte Markierungen entfernen"
|
||||||
},
|
},
|
||||||
"resize": {
|
|
||||||
"label": "Größe ändern"
|
|
||||||
},
|
|
||||||
"resize-accept": {
|
"resize-accept": {
|
||||||
"label": "Neue Größe speichern"
|
"label": "Neue Größe speichern"
|
||||||
},
|
},
|
||||||
"resize-cancel": {
|
"resize-cancel": {
|
||||||
"label": "Größenänderung abbrechen"
|
"label": "Größenänderung abbrechen"
|
||||||
},
|
},
|
||||||
|
"resize": {
|
||||||
|
"label": "Größe ändern"
|
||||||
|
},
|
||||||
"see-references": {
|
"see-references": {
|
||||||
"label": "Referenzen anzeigen"
|
"label": "Referenzen anzeigen"
|
||||||
},
|
},
|
||||||
@ -391,6 +391,9 @@
|
|||||||
"skipped": "Ignorierte Schwärzung",
|
"skipped": "Ignorierte Schwärzung",
|
||||||
"text-highlight": "Markierung"
|
"text-highlight": "Markierung"
|
||||||
},
|
},
|
||||||
|
"annotation": {
|
||||||
|
"pending": "(Analyse steht aus)"
|
||||||
|
},
|
||||||
"annotations": "Annotationen",
|
"annotations": "Annotationen",
|
||||||
"archived-dossiers-listing": {
|
"archived-dossiers-listing": {
|
||||||
"no-data": {
|
"no-data": {
|
||||||
@ -613,18 +616,14 @@
|
|||||||
"warning": "Warnung: Wiederherstellung des Benutzers nicht möglich."
|
"warning": "Warnung: Wiederherstellung des Benutzers nicht möglich."
|
||||||
},
|
},
|
||||||
"confirmation-dialog": {
|
"confirmation-dialog": {
|
||||||
"approve-file": {
|
|
||||||
"question": "Dieses Dokument enthält ungesehene Änderungen, die sich durch die Reanalyse ergeben haben. <br><br>Möchten Sie es trotzdem freigeben?",
|
|
||||||
"title": "Warnung!"
|
|
||||||
},
|
|
||||||
"approve-file-without-analysis": {
|
"approve-file-without-analysis": {
|
||||||
"confirmationText": "Ohne Analyse freigeben",
|
"confirmationText": "Ohne Analyse freigeben",
|
||||||
"denyText": "Abbrechen",
|
"denyText": "Abbrechen",
|
||||||
"question": "Analyse zur Erkennung neuer Schwärzungen erforderlich.",
|
"question": "Analyse zur Erkennung neuer Schwärzungen erforderlich.",
|
||||||
"title": "Warnung!"
|
"title": "Warnung!"
|
||||||
},
|
},
|
||||||
"approve-multiple-files": {
|
"approve-file": {
|
||||||
"question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen, die im Zuge einer Reanalyse hinzugefügt wurden.<br><br>Möchen Sie die Dateien wirklich freigeben?",
|
"question": "Dieses Dokument enthält ungesehene Änderungen, die sich durch die Reanalyse ergeben haben. <br><br>Möchten Sie es trotzdem freigeben?",
|
||||||
"title": "Warnung!"
|
"title": "Warnung!"
|
||||||
},
|
},
|
||||||
"approve-multiple-files-without-analysis": {
|
"approve-multiple-files-without-analysis": {
|
||||||
@ -633,6 +632,10 @@
|
|||||||
"question": "Für mindestens eine Datei ist ein Analyselauf zur Erkennung neuer Schwärzungen erforderlich.",
|
"question": "Für mindestens eine Datei ist ein Analyselauf zur Erkennung neuer Schwärzungen erforderlich.",
|
||||||
"title": "Warnung"
|
"title": "Warnung"
|
||||||
},
|
},
|
||||||
|
"approve-multiple-files": {
|
||||||
|
"question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen, die im Zuge einer Reanalyse hinzugefügt wurden.<br><br>Möchen Sie die Dateien wirklich freigeben?",
|
||||||
|
"title": "Warnung!"
|
||||||
|
},
|
||||||
"assign-file-to-me": {
|
"assign-file-to-me": {
|
||||||
"question": {
|
"question": {
|
||||||
"multiple": "Dieses Dokument wird gerade von einer anderen Person geprüft.<br><br>Möchten Sie sich die Datei dennoch zuweisen?",
|
"multiple": "Dieses Dokument wird gerade von einer anderen Person geprüft.<br><br>Möchten Sie sich die Datei dennoch zuweisen?",
|
||||||
@ -1002,13 +1005,13 @@
|
|||||||
"recent": "Neu ({hours} h)",
|
"recent": "Neu ({hours} h)",
|
||||||
"unassigned": "Keinem Bearbeiter zugewiesen"
|
"unassigned": "Keinem Bearbeiter zugewiesen"
|
||||||
},
|
},
|
||||||
"reanalyse": {
|
|
||||||
"action": "Datei analysieren"
|
|
||||||
},
|
|
||||||
"reanalyse-dossier": {
|
"reanalyse-dossier": {
|
||||||
"error": "Einplanung der Dateien für die Reanalyse fehlgeschlagen. Bitte versuchen Sie es noch einmal.",
|
"error": "Einplanung der Dateien für die Reanalyse fehlgeschlagen. Bitte versuchen Sie es noch einmal.",
|
||||||
"success": "Dateien für Reanalyse vorgesehen."
|
"success": "Dateien für Reanalyse vorgesehen."
|
||||||
},
|
},
|
||||||
|
"reanalyse": {
|
||||||
|
"action": "Datei analysieren"
|
||||||
|
},
|
||||||
"start-auto-analysis": "Auto-Analyse aktivieren",
|
"start-auto-analysis": "Auto-Analyse aktivieren",
|
||||||
"stop-auto-analysis": "Auto-Analyse anhalten",
|
"stop-auto-analysis": "Auto-Analyse anhalten",
|
||||||
"table-col-names": {
|
"table-col-names": {
|
||||||
@ -1078,19 +1081,10 @@
|
|||||||
"total-documents": "Dokumente",
|
"total-documents": "Dokumente",
|
||||||
"total-people": "<strong>{count}</strong> {count, plural, one{Benutzer} other {Benutzer}}"
|
"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": {
|
"dossier-templates-listing": {
|
||||||
"action": {
|
"action": {
|
||||||
"clone": "Vorlage klonen",
|
"clone": "Vorlage klonen",
|
||||||
"delete": "Vorlage löschen",
|
"delete": "Vorlage löschen"
|
||||||
"edit": "Vorlage bearbeiten"
|
|
||||||
},
|
},
|
||||||
"add-new": "Neue Dossier-Vorlage",
|
"add-new": "Neue Dossier-Vorlage",
|
||||||
"bulk": {
|
"bulk": {
|
||||||
@ -1121,6 +1115,14 @@
|
|||||||
"title": "{length} {length, plural, one{Dossier-Vorlage} other{Dossier-Vorlagen}}"
|
"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": {
|
"dossier-watermark-selector": {
|
||||||
"heading": "Wasserzeichen auf Dokumenten",
|
"heading": "Wasserzeichen auf Dokumenten",
|
||||||
"no-watermark": "Kein Wasserzeichen in der Dossier-Vorlage verfügbar:<br>Bitten Sie Ihren Admin, eines zu konfigurieren.",
|
"no-watermark": "Kein Wasserzeichen in der Dossier-Vorlage verfügbar:<br>Bitten Sie Ihren Admin, eines zu konfigurieren.",
|
||||||
@ -1152,6 +1154,7 @@
|
|||||||
"delta-preview": "Delta-PDF",
|
"delta-preview": "Delta-PDF",
|
||||||
"flatten": "Verflachte PDF",
|
"flatten": "Verflachte PDF",
|
||||||
"label": "{length} Dokumenten{length, plural, one{typ} other{typen}}",
|
"label": "{length} Dokumenten{length, plural, one{typ} other{typen}}",
|
||||||
|
"optimized-preview": "Optimized Preview PDF",
|
||||||
"original": "Optimierte PDF",
|
"original": "Optimierte PDF",
|
||||||
"preview": "Vorschau-PDF",
|
"preview": "Vorschau-PDF",
|
||||||
"redacted": "Geschwärzte PDF",
|
"redacted": "Geschwärzte PDF",
|
||||||
@ -1316,15 +1319,6 @@
|
|||||||
"title": "{length} {length, plural, one{Wörterbuch} other{Wörterbücher}}"
|
"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": {
|
"entity-rules-screen": {
|
||||||
"error": {
|
"error": {
|
||||||
"generic": "Fehler: Aktualisierung der Entitätsregeln fehlgeschlagen."
|
"generic": "Fehler: Aktualisierung der Entitätsregeln fehlgeschlagen."
|
||||||
@ -1339,19 +1333,28 @@
|
|||||||
"warning-text": "Warnung: experimentelle Funktion!",
|
"warning-text": "Warnung: experimentelle Funktion!",
|
||||||
"warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} in Regeln gefunden"
|
"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": {
|
"error": {
|
||||||
"deleted-entity": {
|
"deleted-entity": {
|
||||||
"dossier": {
|
"dossier": {
|
||||||
"action": "Zurück zur Übersicht",
|
"action": "Zurück zur Übersicht",
|
||||||
"label": "Dieses Dossier wurde gelöscht!"
|
"label": "Dieses Dossier wurde gelöscht!"
|
||||||
},
|
},
|
||||||
"file": {
|
|
||||||
"action": "Zurück zum Dossier",
|
|
||||||
"label": "Diese Datei wurde gelöscht!"
|
|
||||||
},
|
|
||||||
"file-dossier": {
|
"file-dossier": {
|
||||||
"action": "Zurück zur Übersicht",
|
"action": "Zurück zur Übersicht",
|
||||||
"label": "Das Dossier dieser Datei wurde gelöscht!"
|
"label": "Das Dossier dieser Datei wurde gelöscht!"
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"action": "Zurück zum Dossier",
|
||||||
|
"label": "Diese Datei wurde gelöscht!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"file-preview": {
|
"file-preview": {
|
||||||
@ -1369,12 +1372,6 @@
|
|||||||
},
|
},
|
||||||
"exact-date": "{day}. {month} {year} um {hour}:{minute} Uhr",
|
"exact-date": "{day}. {month} {year} um {hour}:{minute} Uhr",
|
||||||
"file": "Datei",
|
"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": {
|
"file-attribute-encoding-types": {
|
||||||
"ascii": "ASCII",
|
"ascii": "ASCII",
|
||||||
"iso": "ISO-8859-1",
|
"iso": "ISO-8859-1",
|
||||||
@ -1385,6 +1382,12 @@
|
|||||||
"number": "Nummer",
|
"number": "Nummer",
|
||||||
"text": "Freier Text"
|
"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": {
|
"file-attributes-configurations": {
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
"form": {
|
"form": {
|
||||||
@ -1602,15 +1605,6 @@
|
|||||||
"csv": "Die Datei-Attribute wurden erfolgreich aus der hochgeladenen CSV-Datei importiert."
|
"csv": "Die Datei-Attribute wurden erfolgreich aus der hochgeladenen CSV-Datei importiert."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"filter": {
|
|
||||||
"analysis": "Analyse erforderlich",
|
|
||||||
"comment": "Kommentare",
|
|
||||||
"hint": "Nur Hinweise",
|
|
||||||
"image": "Bilder",
|
|
||||||
"none": "Keine Annotationen",
|
|
||||||
"redaction": "Schwärzungen",
|
|
||||||
"updated": "Aktualisiert"
|
|
||||||
},
|
|
||||||
"filter-menu": {
|
"filter-menu": {
|
||||||
"filter-options": "Filteroptionen",
|
"filter-options": "Filteroptionen",
|
||||||
"filter-types": "Filter",
|
"filter-types": "Filter",
|
||||||
@ -1620,6 +1614,15 @@
|
|||||||
"unseen-pages": "Nur Annotationen auf ungesehenen Seiten",
|
"unseen-pages": "Nur Annotationen auf ungesehenen Seiten",
|
||||||
"with-comments": "Nur Annotationen mit Kommentaren"
|
"with-comments": "Nur Annotationen mit Kommentaren"
|
||||||
},
|
},
|
||||||
|
"filter": {
|
||||||
|
"analysis": "Analyse erforderlich",
|
||||||
|
"comment": "Kommentare",
|
||||||
|
"hint": "Nur Hinweise",
|
||||||
|
"image": "Bilder",
|
||||||
|
"none": "Keine Annotationen",
|
||||||
|
"redaction": "Schwärzungen",
|
||||||
|
"updated": "Aktualisiert"
|
||||||
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"assigned-people": "Bearbeiter",
|
"assigned-people": "Bearbeiter",
|
||||||
"documents-status": "Dokumentenstatus",
|
"documents-status": "Dokumentenstatus",
|
||||||
@ -1898,13 +1901,6 @@
|
|||||||
"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-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!"
|
"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": {
|
"notifications-screen": {
|
||||||
"category": {
|
"category": {
|
||||||
"email-notifications": "E-Mail-Benachrichtigungen",
|
"email-notifications": "E-Mail-Benachrichtigungen",
|
||||||
@ -1918,6 +1914,7 @@
|
|||||||
"dossier": "Benachrichtigungen zu Dossiers",
|
"dossier": "Benachrichtigungen zu Dossiers",
|
||||||
"other": "Andere Benachrichtigungen"
|
"other": "Andere Benachrichtigungen"
|
||||||
},
|
},
|
||||||
|
"options-title": "Wählen Sie aus, bei welchen Aktivitäten Sie benachrichtigt werden möchten",
|
||||||
"options": {
|
"options": {
|
||||||
"ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen werde",
|
"ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen werde",
|
||||||
"ASSIGN_REVIEWER": "Wenn ich einem Dokument als Prüfer zugewiesen werde",
|
"ASSIGN_REVIEWER": "Wenn ich einem Dokument als Prüfer zugewiesen werde",
|
||||||
@ -1935,7 +1932,6 @@
|
|||||||
"USER_PROMOTED_TO_APPROVER": "Wenn ich Genehmiger in einem Dossier werde",
|
"USER_PROMOTED_TO_APPROVER": "Wenn ich Genehmiger in einem Dossier werde",
|
||||||
"USER_REMOVED_AS_DOSSIER_MEMBER": "Wenn ich die Dossier-Mitgliedschaft verliere"
|
"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": {
|
"schedule": {
|
||||||
"daily": "Tägliche Zusammenfassung",
|
"daily": "Tägliche Zusammenfassung",
|
||||||
"instant": "Sofort",
|
"instant": "Sofort",
|
||||||
@ -1943,6 +1939,13 @@
|
|||||||
},
|
},
|
||||||
"title": "Benachrichtigungseinstellungen"
|
"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": {
|
"ocr": {
|
||||||
"confirmation-dialog": {
|
"confirmation-dialog": {
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
@ -2026,6 +2029,7 @@
|
|||||||
"help-mode-dialog": "Dialog zur Aktivierung des Hilfemodus",
|
"help-mode-dialog": "Dialog zur Aktivierung des Hilfemodus",
|
||||||
"load-all-annotations-warning": "Warnung bei gleichzeitigem Laden aller Annotationen in der Miniaturansicht",
|
"load-all-annotations-warning": "Warnung bei gleichzeitigem Laden aller Annotationen in der Miniaturansicht",
|
||||||
"open-structured-view-by-default": "Strukturierte Komponentenansicht standardmäßig anzeigen",
|
"open-structured-view-by-default": "Strukturierte Komponentenansicht standardmäßig anzeigen",
|
||||||
|
"overwrite-file-option": "",
|
||||||
"table-extraction-type": "Art der Tabellenextraktion"
|
"table-extraction-type": "Art der Tabellenextraktion"
|
||||||
},
|
},
|
||||||
"label": "Präferenzen",
|
"label": "Präferenzen",
|
||||||
@ -2034,16 +2038,16 @@
|
|||||||
"warnings-label": "Dialoge und Meldungen",
|
"warnings-label": "Dialoge und Meldungen",
|
||||||
"warnings-subtitle": "„Nicht mehr anzeigen“-Optionen"
|
"warnings-subtitle": "„Nicht mehr anzeigen“-Optionen"
|
||||||
},
|
},
|
||||||
"processing": {
|
|
||||||
"basic": "Verarbeitung läuft",
|
|
||||||
"ocr": "OCR"
|
|
||||||
},
|
|
||||||
"processing-status": {
|
"processing-status": {
|
||||||
"ocr": "OCR",
|
"ocr": "OCR",
|
||||||
"pending": "Ausstehend",
|
"pending": "Ausstehend",
|
||||||
"processed": "verarbeitet",
|
"processed": "verarbeitet",
|
||||||
"processing": "Verarbeitung läuft"
|
"processing": "Verarbeitung läuft"
|
||||||
},
|
},
|
||||||
|
"processing": {
|
||||||
|
"basic": "Verarbeitung läuft",
|
||||||
|
"ocr": "OCR"
|
||||||
|
},
|
||||||
"readonly": "Lesemodus",
|
"readonly": "Lesemodus",
|
||||||
"readonly-archived": "Lesemodus (archiviert)",
|
"readonly-archived": "Lesemodus (archiviert)",
|
||||||
"redact-text": {
|
"redact-text": {
|
||||||
@ -2279,12 +2283,6 @@
|
|||||||
"red-user-admin": "Benutzeradmin",
|
"red-user-admin": "Benutzeradmin",
|
||||||
"regular": "regulärer Benutzer"
|
"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": {
|
"search-screen": {
|
||||||
"cols": {
|
"cols": {
|
||||||
"assignee": "Bearbeiter",
|
"assignee": "Bearbeiter",
|
||||||
@ -2308,6 +2306,12 @@
|
|||||||
"no-match": "Suchbegriff wurde in keinem der Dokumente gefunden.",
|
"no-match": "Suchbegriff wurde in keinem der Dokumente gefunden.",
|
||||||
"table-header": "{length} {length, plural, one{Suchergebnis} other{Suchergebnisse}}"
|
"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",
|
"seconds": "Sekunden",
|
||||||
"size": "Größe",
|
"size": "Größe",
|
||||||
"smtp-auth-config": {
|
"smtp-auth-config": {
|
||||||
@ -2563,4 +2567,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Gestern"
|
"yesterday": "Gestern"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -206,11 +206,14 @@
|
|||||||
"generic": "Failed to save user."
|
"generic": "Failed to save user."
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
|
"account-setup": "User account setup",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"first-name": "First name",
|
"first-name": "First name",
|
||||||
"last-name": "Last name",
|
"last-name": "Last name",
|
||||||
"reset-password": "Reset password",
|
"reset-password": "Reset password",
|
||||||
"role": "Role"
|
"role": "Role",
|
||||||
|
"send-email": "Do not send email requesting the user to set a password",
|
||||||
|
"send-email-explanation": "Select this option if you use SSO. Please note that you will need to inform the user directly."
|
||||||
},
|
},
|
||||||
"title": "{type, select, edit{Edit} create{Add new} other{}} user"
|
"title": "{type, select, edit{Edit} create{Add new} other{}} user"
|
||||||
},
|
},
|
||||||
@ -1081,8 +1084,7 @@
|
|||||||
"dossier-templates-listing": {
|
"dossier-templates-listing": {
|
||||||
"action": {
|
"action": {
|
||||||
"clone": "Clone template",
|
"clone": "Clone template",
|
||||||
"delete": "Delete template",
|
"delete": "Delete template"
|
||||||
"edit": "Edit template"
|
|
||||||
},
|
},
|
||||||
"add-new": "New dossier template",
|
"add-new": "New dossier template",
|
||||||
"bulk": {
|
"bulk": {
|
||||||
@ -1152,6 +1154,7 @@
|
|||||||
"delta-preview": "Delta PDF",
|
"delta-preview": "Delta PDF",
|
||||||
"flatten": "Flatten PDF",
|
"flatten": "Flatten PDF",
|
||||||
"label": "{length} document {length, plural, one{version} other{versions}}",
|
"label": "{length} document {length, plural, one{version} other{versions}}",
|
||||||
|
"optimized-preview": "Optimized Preview PDF",
|
||||||
"original": "Optimized PDF",
|
"original": "Optimized PDF",
|
||||||
"preview": "Preview PDF",
|
"preview": "Preview PDF",
|
||||||
"redacted": "Redacted PDF",
|
"redacted": "Redacted PDF",
|
||||||
@ -1518,7 +1521,7 @@
|
|||||||
},
|
},
|
||||||
"reanalyse-notification": "Start reanalysis",
|
"reanalyse-notification": "Start reanalysis",
|
||||||
"redacted": "Preview",
|
"redacted": "Preview",
|
||||||
"redacted-tooltip": "Redaction preview shows only redactions. Consider this a preview for the final redacted version. This view is only available if the file has no pending changes & doesn't require a reanalysis",
|
"redacted-tooltip": "The preview shows only the redactions. It is a preview of the final redacted version.",
|
||||||
"standard": "Standard",
|
"standard": "Standard",
|
||||||
"standard-tooltip": "Standard shows all annotation types and allows for editing.",
|
"standard-tooltip": "Standard shows all annotation types and allows for editing.",
|
||||||
"tabs": {
|
"tabs": {
|
||||||
@ -2026,6 +2029,7 @@
|
|||||||
"help-mode-dialog": "Help mode activation dialog",
|
"help-mode-dialog": "Help mode activation dialog",
|
||||||
"load-all-annotations-warning": "Warning regarding simultaneous loading of all annotations in thumbnails",
|
"load-all-annotations-warning": "Warning regarding simultaneous loading of all annotations in thumbnails",
|
||||||
"open-structured-view-by-default": "Display structured component management modal by default",
|
"open-structured-view-by-default": "Display structured component management modal by default",
|
||||||
|
"overwrite-file-option": "Preferred action when re-uploading of an already existing file",
|
||||||
"table-extraction-type": "Table extraction type"
|
"table-extraction-type": "Table extraction type"
|
||||||
},
|
},
|
||||||
"label": "Preferences",
|
"label": "Preferences",
|
||||||
@ -2125,28 +2129,28 @@
|
|||||||
"comment-placeholder": "Add remarks or notes...",
|
"comment-placeholder": "Add remarks or notes...",
|
||||||
"options": {
|
"options": {
|
||||||
"do-not-recommend": {
|
"do-not-recommend": {
|
||||||
"description": "Do not recommend the selected term in any document of this dossier.",
|
"description": "Do not recommend the selected {isImage, select, image{image} other{term}} in any document of this dossier.",
|
||||||
"description-bulk": "Do not recommend the selected terms in any document of this dossier.",
|
"description-bulk": "Do not recommend the selected {isImage, select, image{images} other{terms}} in any document of this dossier.",
|
||||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||||
"label": "Remove from dossier"
|
"label": "Remove from dossier"
|
||||||
},
|
},
|
||||||
"false-positive": {
|
"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": "Mark this redaction as a false-positive. The {isImage, select, image{image} other{term}} will not be redacted in this dossier if it occurs in the same context.",
|
||||||
"description-bulk": "Mark these redactions as false-positives. The terms will not be redacted in this dossier if they occur in the same context.",
|
"description-bulk": "Mark these redactions as false-positives. The {isImage, select, image{images} other{terms}} will not be redacted in this dossier if they occur in the same context.",
|
||||||
"extraOptionDescription": "Dossier template access is required to reverse this action. As a regular user you can only reverse it for this dossier.",
|
"extraOptionDescription": "Dossier template access is required to reverse this action. As a regular user you can only reverse it for this dossier.",
|
||||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||||
"label": "Remove from dossier in this context"
|
"label": "Remove from dossier in this context"
|
||||||
},
|
},
|
||||||
"in-dossier": {
|
"in-dossier": {
|
||||||
"description": "Do not {type, select, hint{annotate} other{auto-redact}} the selected term in any document of this dossier.",
|
"description": "Do not {type, select, hint{annotate} other{auto-redact}} the selected {isImage, select, image{image} other{term}} in any document of this dossier.",
|
||||||
"description-bulk": "Do not {type, select, hint{annotate} other{auto-redact}} the selected terms in this dossier.",
|
"description-bulk": "Do not {type, select, hint{annotate} other{auto-redact}} the selected {isImage, select, image{images} other{terms}} in this dossier.",
|
||||||
"extraOptionLabel": "Apply to all active and future dossiers",
|
"extraOptionLabel": "Apply to all active and future dossiers",
|
||||||
"label": "Remove from dossier",
|
"label": "Remove from dossier",
|
||||||
"label-bulk": "Remove from dossier"
|
"label-bulk": "Remove from dossier"
|
||||||
},
|
},
|
||||||
"only-here": {
|
"only-here": {
|
||||||
"description": "Do not {type, select, hint{annotate} other{redact}} the term at this position in the current document.",
|
"description": "Do not {type, select, hint{annotate} other{redact}} the {isImage, select, image{image} other{term}} at this position in the current document.",
|
||||||
"description-bulk": "Do not {type, select, hint{annotate} other{redact}} the selected terms at this position in the current document.",
|
"description-bulk": "Do not {type, select, hint{annotate} other{redact}} the selected {isImage, select, image{images} other{terms}} at this position in the current document.",
|
||||||
"label": "Remove here"
|
"label": "Remove here"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2563,4 +2567,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Yesterday"
|
"yesterday": "Yesterday"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -206,11 +206,14 @@
|
|||||||
"generic": "Benutzer konnte nicht gespeichert werden!"
|
"generic": "Benutzer konnte nicht gespeichert werden!"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
|
"account-setup": "User account setup",
|
||||||
"email": "E-Mail",
|
"email": "E-Mail",
|
||||||
"first-name": "Vorname",
|
"first-name": "Vorname",
|
||||||
"last-name": "Nachname",
|
"last-name": "Nachname",
|
||||||
"reset-password": "Passwort zurücksetzen",
|
"reset-password": "Passwort zurücksetzen",
|
||||||
"role": "Rolle"
|
"role": "Rolle",
|
||||||
|
"send-email": "Do not send email requesting the user to set a password",
|
||||||
|
"send-email-explanation": "Select this option if you use SSO. Please note that you will need to inform the user directly."
|
||||||
},
|
},
|
||||||
"title": "{type, select, edit{Benutzer bearbeiten} create{Neuen Benutzer hinzufügen} other{}}"
|
"title": "{type, select, edit{Benutzer bearbeiten} create{Neuen Benutzer hinzufügen} other{}}"
|
||||||
},
|
},
|
||||||
@ -271,9 +274,6 @@
|
|||||||
"watermarks": "Watermarks"
|
"watermarks": "Watermarks"
|
||||||
},
|
},
|
||||||
"analysis-disabled": "Analysis disabled",
|
"analysis-disabled": "Analysis disabled",
|
||||||
"annotation": {
|
|
||||||
"pending": "(Pending analysis)"
|
|
||||||
},
|
|
||||||
"annotation-actions": {
|
"annotation-actions": {
|
||||||
"accept-recommendation": {
|
"accept-recommendation": {
|
||||||
"label": "Empfehlung annehmen"
|
"label": "Empfehlung annehmen"
|
||||||
@ -329,14 +329,14 @@
|
|||||||
"error": "Rekategorisierung des Bildes gescheitert: {error}",
|
"error": "Rekategorisierung des Bildes gescheitert: {error}",
|
||||||
"success": "Bild wurde einer neuen Kategorie zugeordnet."
|
"success": "Bild wurde einer neuen Kategorie zugeordnet."
|
||||||
},
|
},
|
||||||
"remove": {
|
|
||||||
"error": "Fehler beim Entfernen der Schwärzung: {error}",
|
|
||||||
"success": "Schwärzung entfernt!"
|
|
||||||
},
|
|
||||||
"remove-hint": {
|
"remove-hint": {
|
||||||
"error": "Failed to remove hint: {error}",
|
"error": "Failed to remove hint: {error}",
|
||||||
"success": "Hint removed!"
|
"success": "Hint removed!"
|
||||||
},
|
},
|
||||||
|
"remove": {
|
||||||
|
"error": "Fehler beim Entfernen der Schwärzung: {error}",
|
||||||
|
"success": "Schwärzung entfernt!"
|
||||||
|
},
|
||||||
"undo": {
|
"undo": {
|
||||||
"error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}",
|
"error": "Die Aktion konnte nicht rückgängig gemacht werden. Fehler: {error}",
|
||||||
"success": "erfolgreich Rückgängig gemacht"
|
"success": "erfolgreich Rückgängig gemacht"
|
||||||
@ -349,15 +349,15 @@
|
|||||||
"remove-highlights": {
|
"remove-highlights": {
|
||||||
"label": "Remove selected earmarks"
|
"label": "Remove selected earmarks"
|
||||||
},
|
},
|
||||||
"resize": {
|
|
||||||
"label": "Größe ändern"
|
|
||||||
},
|
|
||||||
"resize-accept": {
|
"resize-accept": {
|
||||||
"label": "Größe speichern"
|
"label": "Größe speichern"
|
||||||
},
|
},
|
||||||
"resize-cancel": {
|
"resize-cancel": {
|
||||||
"label": "Größenänderung abbrechen"
|
"label": "Größenänderung abbrechen"
|
||||||
},
|
},
|
||||||
|
"resize": {
|
||||||
|
"label": "Größe ändern"
|
||||||
|
},
|
||||||
"see-references": {
|
"see-references": {
|
||||||
"label": "See references"
|
"label": "See references"
|
||||||
},
|
},
|
||||||
@ -391,6 +391,9 @@
|
|||||||
"skipped": "Übersprungen",
|
"skipped": "Übersprungen",
|
||||||
"text-highlight": "Earmark"
|
"text-highlight": "Earmark"
|
||||||
},
|
},
|
||||||
|
"annotation": {
|
||||||
|
"pending": "(Pending analysis)"
|
||||||
|
},
|
||||||
"annotations": "Annotations",
|
"annotations": "Annotations",
|
||||||
"archived-dossiers-listing": {
|
"archived-dossiers-listing": {
|
||||||
"no-data": {
|
"no-data": {
|
||||||
@ -613,18 +616,14 @@
|
|||||||
"warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!"
|
"warning": "Achtung: Diese Aktion kann nicht rückgängig gemacht werden!"
|
||||||
},
|
},
|
||||||
"confirmation-dialog": {
|
"confirmation-dialog": {
|
||||||
"approve-file": {
|
|
||||||
"question": "Dieses Dokument enthält ungesehene Änderungen. Möchten Sie es trotzdem genehmigen?",
|
|
||||||
"title": "Warnung!"
|
|
||||||
},
|
|
||||||
"approve-file-without-analysis": {
|
"approve-file-without-analysis": {
|
||||||
"confirmationText": "Approve without analysis",
|
"confirmationText": "Approve without analysis",
|
||||||
"denyText": "Cancel",
|
"denyText": "Cancel",
|
||||||
"question": "Analysis required to detect new components.",
|
"question": "Analysis required to detect new components.",
|
||||||
"title": "Warning!"
|
"title": "Warning!"
|
||||||
},
|
},
|
||||||
"approve-multiple-files": {
|
"approve-file": {
|
||||||
"question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen. Möchten Sie sie trotzdem genehmigen?",
|
"question": "Dieses Dokument enthält ungesehene Änderungen. Möchten Sie es trotzdem genehmigen?",
|
||||||
"title": "Warnung!"
|
"title": "Warnung!"
|
||||||
},
|
},
|
||||||
"approve-multiple-files-without-analysis": {
|
"approve-multiple-files-without-analysis": {
|
||||||
@ -633,6 +632,10 @@
|
|||||||
"question": "Analysis required to detect new components for at least one file.",
|
"question": "Analysis required to detect new components for at least one file.",
|
||||||
"title": "Warning"
|
"title": "Warning"
|
||||||
},
|
},
|
||||||
|
"approve-multiple-files": {
|
||||||
|
"question": "Mindestens eine der ausgewählten Dateien enthält ungesehene Änderungen. Möchten Sie sie trotzdem genehmigen?",
|
||||||
|
"title": "Warnung!"
|
||||||
|
},
|
||||||
"assign-file-to-me": {
|
"assign-file-to-me": {
|
||||||
"question": {
|
"question": {
|
||||||
"multiple": "Dieses Dokument wird gerade von einer anderen Person geprüft. Möchten Sie Reviewer werden und sich selbst dem Dokument zuweisen?",
|
"multiple": "Dieses Dokument wird gerade von einer anderen Person geprüft. Möchten Sie Reviewer werden und sich selbst dem Dokument zuweisen?",
|
||||||
@ -1002,13 +1005,13 @@
|
|||||||
"recent": "Neu ({hours} h)",
|
"recent": "Neu ({hours} h)",
|
||||||
"unassigned": "Niemandem zugewiesen"
|
"unassigned": "Niemandem zugewiesen"
|
||||||
},
|
},
|
||||||
"reanalyse": {
|
|
||||||
"action": "Datei analysieren"
|
|
||||||
},
|
|
||||||
"reanalyse-dossier": {
|
"reanalyse-dossier": {
|
||||||
"error": "Die Dateien konnten nicht für eine Reanalyse eingeplant werden. Bitte versuchen Sie es erneut.",
|
"error": "Die Dateien konnten nicht für eine Reanalyse eingeplant werden. Bitte versuchen Sie es erneut.",
|
||||||
"success": "Dateien für Reanalyse vorgesehen."
|
"success": "Dateien für Reanalyse vorgesehen."
|
||||||
},
|
},
|
||||||
|
"reanalyse": {
|
||||||
|
"action": "Datei analysieren"
|
||||||
|
},
|
||||||
"start-auto-analysis": "Enable auto-analysis",
|
"start-auto-analysis": "Enable auto-analysis",
|
||||||
"stop-auto-analysis": "Stop auto-analysis",
|
"stop-auto-analysis": "Stop auto-analysis",
|
||||||
"table-col-names": {
|
"table-col-names": {
|
||||||
@ -1078,19 +1081,10 @@
|
|||||||
"total-documents": "Anzahl der Dokumente",
|
"total-documents": "Anzahl der Dokumente",
|
||||||
"total-people": "<strong>{count}</strong> {count, plural, one{user} other {users}}"
|
"total-people": "<strong>{count}</strong> {count, plural, one{user} other {users}}"
|
||||||
},
|
},
|
||||||
"dossier-templates": {
|
|
||||||
"label": "Dossier-Vorlagen",
|
|
||||||
"status": {
|
|
||||||
"active": "Active",
|
|
||||||
"inactive": "Inactive",
|
|
||||||
"incomplete": "Incomplete"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dossier-templates-listing": {
|
"dossier-templates-listing": {
|
||||||
"action": {
|
"action": {
|
||||||
"clone": "Clone template",
|
"clone": "Clone template",
|
||||||
"delete": "Dossier-Vorlage",
|
"delete": "Dossier-Vorlage"
|
||||||
"edit": "Vorlage bearbeiten"
|
|
||||||
},
|
},
|
||||||
"add-new": "Neue Dossier-Vorlage",
|
"add-new": "Neue Dossier-Vorlage",
|
||||||
"bulk": {
|
"bulk": {
|
||||||
@ -1121,6 +1115,14 @@
|
|||||||
"title": "{length} dossier {length, plural, one{template} other{templates}}"
|
"title": "{length} dossier {length, plural, one{template} other{templates}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dossier-templates": {
|
||||||
|
"label": "Dossier-Vorlagen",
|
||||||
|
"status": {
|
||||||
|
"active": "Active",
|
||||||
|
"inactive": "Inactive",
|
||||||
|
"incomplete": "Incomplete"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dossier-watermark-selector": {
|
"dossier-watermark-selector": {
|
||||||
"heading": "Watermarks on documents",
|
"heading": "Watermarks on documents",
|
||||||
"no-watermark": "There is no watermark defined for the dossier template.<br>Contact your app admin to define one.",
|
"no-watermark": "There is no watermark defined for the dossier template.<br>Contact your app admin to define one.",
|
||||||
@ -1152,6 +1154,7 @@
|
|||||||
"delta-preview": "Delta PDF",
|
"delta-preview": "Delta PDF",
|
||||||
"flatten": "PDF verflachen",
|
"flatten": "PDF verflachen",
|
||||||
"label": "{length} document {length, plural, one{version} other{versions}}",
|
"label": "{length} document {length, plural, one{version} other{versions}}",
|
||||||
|
"optimized-preview": "Optimized Preview PDF",
|
||||||
"original": "Optimiertes PDF",
|
"original": "Optimiertes PDF",
|
||||||
"preview": "PDF-Vorschau",
|
"preview": "PDF-Vorschau",
|
||||||
"redacted": "geschwärztes PDF",
|
"redacted": "geschwärztes PDF",
|
||||||
@ -1316,15 +1319,6 @@
|
|||||||
"title": "{length} {length, plural, one{entity} other{entities}}"
|
"title": "{length} {length, plural, one{entity} other{entities}}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"entity": {
|
|
||||||
"info": {
|
|
||||||
"actions": {
|
|
||||||
"revert": "Revert",
|
|
||||||
"save": "Save changes"
|
|
||||||
},
|
|
||||||
"heading": "Edit entity"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"entity-rules-screen": {
|
"entity-rules-screen": {
|
||||||
"error": {
|
"error": {
|
||||||
"generic": "Something went wrong... Entity rules update failed!"
|
"generic": "Something went wrong... Entity rules update failed!"
|
||||||
@ -1339,19 +1333,28 @@
|
|||||||
"warning-text": "Warning: experimental feature!",
|
"warning-text": "Warning: experimental feature!",
|
||||||
"warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules"
|
"warnings-found": "{warnings, plural, one{A warning} other{{warnings} warnings}} found in rules"
|
||||||
},
|
},
|
||||||
|
"entity": {
|
||||||
|
"info": {
|
||||||
|
"actions": {
|
||||||
|
"revert": "Revert",
|
||||||
|
"save": "Save changes"
|
||||||
|
},
|
||||||
|
"heading": "Edit entity"
|
||||||
|
}
|
||||||
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"deleted-entity": {
|
"deleted-entity": {
|
||||||
"dossier": {
|
"dossier": {
|
||||||
"action": "Zurück zur Übersicht",
|
"action": "Zurück zur Übersicht",
|
||||||
"label": "Dieses Dossier wurde gelöscht!"
|
"label": "Dieses Dossier wurde gelöscht!"
|
||||||
},
|
},
|
||||||
"file": {
|
|
||||||
"action": "Zurück zum Dossier",
|
|
||||||
"label": "Diese Datei wurde gelöscht!"
|
|
||||||
},
|
|
||||||
"file-dossier": {
|
"file-dossier": {
|
||||||
"action": "Zurück zur Übersicht",
|
"action": "Zurück zur Übersicht",
|
||||||
"label": "Das Dossier dieser Datei wurde gelöscht!"
|
"label": "Das Dossier dieser Datei wurde gelöscht!"
|
||||||
|
},
|
||||||
|
"file": {
|
||||||
|
"action": "Zurück zum Dossier",
|
||||||
|
"label": "Diese Datei wurde gelöscht!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"file-preview": {
|
"file-preview": {
|
||||||
@ -1369,12 +1372,6 @@
|
|||||||
},
|
},
|
||||||
"exact-date": "{day} {month} {year} um {hour}:{minute} Uhr",
|
"exact-date": "{day} {month} {year} um {hour}:{minute} Uhr",
|
||||||
"file": "Datei",
|
"file": "Datei",
|
||||||
"file-attribute": {
|
|
||||||
"update": {
|
|
||||||
"error": "Failed to update file attribute value!",
|
|
||||||
"success": "File attribute value has been updated successfully!"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"file-attribute-encoding-types": {
|
"file-attribute-encoding-types": {
|
||||||
"ascii": "ASCII",
|
"ascii": "ASCII",
|
||||||
"iso": "ISO-8859-1",
|
"iso": "ISO-8859-1",
|
||||||
@ -1385,6 +1382,12 @@
|
|||||||
"number": "Nummer",
|
"number": "Nummer",
|
||||||
"text": "Freier Text"
|
"text": "Freier Text"
|
||||||
},
|
},
|
||||||
|
"file-attribute": {
|
||||||
|
"update": {
|
||||||
|
"error": "Failed to update file attribute value!",
|
||||||
|
"success": "File attribute value has been updated successfully!"
|
||||||
|
}
|
||||||
|
},
|
||||||
"file-attributes-configurations": {
|
"file-attributes-configurations": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
"form": {
|
"form": {
|
||||||
@ -1602,15 +1605,6 @@
|
|||||||
"csv": "File attributes were imported successfully from uploaded CSV file."
|
"csv": "File attributes were imported successfully from uploaded CSV file."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"filter": {
|
|
||||||
"analysis": "Analyse erforderlich",
|
|
||||||
"comment": "Kommentare",
|
|
||||||
"hint": "Nut Hinweise",
|
|
||||||
"image": "Bilder",
|
|
||||||
"none": "Keine Anmerkungen",
|
|
||||||
"redaction": "Geschwärzt",
|
|
||||||
"updated": "Aktualisiert"
|
|
||||||
},
|
|
||||||
"filter-menu": {
|
"filter-menu": {
|
||||||
"filter-options": "Filteroptionen",
|
"filter-options": "Filteroptionen",
|
||||||
"filter-types": "Filter",
|
"filter-types": "Filter",
|
||||||
@ -1620,6 +1614,15 @@
|
|||||||
"unseen-pages": "Nur Anmerkungen auf unsichtbaren Seiten",
|
"unseen-pages": "Nur Anmerkungen auf unsichtbaren Seiten",
|
||||||
"with-comments": "Nur Anmerkungen mit Kommentaren"
|
"with-comments": "Nur Anmerkungen mit Kommentaren"
|
||||||
},
|
},
|
||||||
|
"filter": {
|
||||||
|
"analysis": "Analyse erforderlich",
|
||||||
|
"comment": "Kommentare",
|
||||||
|
"hint": "Nut Hinweise",
|
||||||
|
"image": "Bilder",
|
||||||
|
"none": "Keine Anmerkungen",
|
||||||
|
"redaction": "Geschwärzt",
|
||||||
|
"updated": "Aktualisiert"
|
||||||
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"assigned-people": "Beauftragt",
|
"assigned-people": "Beauftragt",
|
||||||
"documents-status": "Documents state",
|
"documents-status": "Documents state",
|
||||||
@ -1898,13 +1901,6 @@
|
|||||||
"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-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!"
|
"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": "Notifications",
|
|
||||||
"deleted-dossier": "Deleted dossier",
|
|
||||||
"label": "Benachrichtigungen",
|
|
||||||
"mark-all-as-read": "Alle als gelesen markieren",
|
|
||||||
"mark-as": "Mark as {type, select, read{read} unread{unread} other{}}"
|
|
||||||
},
|
|
||||||
"notifications-screen": {
|
"notifications-screen": {
|
||||||
"category": {
|
"category": {
|
||||||
"email-notifications": "E-Mail Benachrichtigungen",
|
"email-notifications": "E-Mail Benachrichtigungen",
|
||||||
@ -1918,6 +1914,7 @@
|
|||||||
"dossier": "Dossierbezogene Benachrichtigungen",
|
"dossier": "Dossierbezogene Benachrichtigungen",
|
||||||
"other": "Andere Benachrichtigungen"
|
"other": "Andere Benachrichtigungen"
|
||||||
},
|
},
|
||||||
|
"options-title": "Wählen Sie aus, in welcher Kategorie Sie benachrichtigt werden möchten",
|
||||||
"options": {
|
"options": {
|
||||||
"ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen bin",
|
"ASSIGN_APPROVER": "Wenn ich einem Dokument als Genehmiger zugewiesen bin",
|
||||||
"ASSIGN_REVIEWER": "Wenn ich einem Dokument als Überprüfer zugewiesen bin",
|
"ASSIGN_REVIEWER": "Wenn ich einem Dokument als Überprüfer zugewiesen bin",
|
||||||
@ -1935,7 +1932,6 @@
|
|||||||
"USER_PROMOTED_TO_APPROVER": "Wenn ich Genehmiger in einem Dossier werde",
|
"USER_PROMOTED_TO_APPROVER": "Wenn ich Genehmiger in einem Dossier werde",
|
||||||
"USER_REMOVED_AS_DOSSIER_MEMBER": "Wenn ich die Dossier-Mitgliedschaft verliere"
|
"USER_REMOVED_AS_DOSSIER_MEMBER": "Wenn ich die Dossier-Mitgliedschaft verliere"
|
||||||
},
|
},
|
||||||
"options-title": "Wählen Sie aus, in welcher Kategorie Sie benachrichtigt werden möchten",
|
|
||||||
"schedule": {
|
"schedule": {
|
||||||
"daily": "Tägliche Zusammenfassung",
|
"daily": "Tägliche Zusammenfassung",
|
||||||
"instant": "Sofortig",
|
"instant": "Sofortig",
|
||||||
@ -1943,6 +1939,13 @@
|
|||||||
},
|
},
|
||||||
"title": "Benachrichtigungseinstellungen"
|
"title": "Benachrichtigungseinstellungen"
|
||||||
},
|
},
|
||||||
|
"notifications": {
|
||||||
|
"button-text": "Notifications",
|
||||||
|
"deleted-dossier": "Deleted dossier",
|
||||||
|
"label": "Benachrichtigungen",
|
||||||
|
"mark-all-as-read": "Alle als gelesen markieren",
|
||||||
|
"mark-as": "Mark as {type, select, read{read} unread{unread} other{}}"
|
||||||
|
},
|
||||||
"ocr": {
|
"ocr": {
|
||||||
"confirmation-dialog": {
|
"confirmation-dialog": {
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
@ -2026,6 +2029,7 @@
|
|||||||
"help-mode-dialog": "Help Mode Dialog",
|
"help-mode-dialog": "Help Mode Dialog",
|
||||||
"load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview",
|
"load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview",
|
||||||
"open-structured-view-by-default": "Display Component View by default when opening a document",
|
"open-structured-view-by-default": "Display Component View by default when opening a document",
|
||||||
|
"overwrite-file-option": "",
|
||||||
"table-extraction-type": "Table extraction type"
|
"table-extraction-type": "Table extraction type"
|
||||||
},
|
},
|
||||||
"label": "Preferences",
|
"label": "Preferences",
|
||||||
@ -2034,16 +2038,16 @@
|
|||||||
"warnings-label": "Prompts and dialogs",
|
"warnings-label": "Prompts and dialogs",
|
||||||
"warnings-subtitle": "Do not show again options"
|
"warnings-subtitle": "Do not show again options"
|
||||||
},
|
},
|
||||||
"processing": {
|
|
||||||
"basic": "Processing",
|
|
||||||
"ocr": "OCR"
|
|
||||||
},
|
|
||||||
"processing-status": {
|
"processing-status": {
|
||||||
"ocr": "OCR",
|
"ocr": "OCR",
|
||||||
"pending": "Pending",
|
"pending": "Pending",
|
||||||
"processed": "Processed",
|
"processed": "Processed",
|
||||||
"processing": "Processing"
|
"processing": "Processing"
|
||||||
},
|
},
|
||||||
|
"processing": {
|
||||||
|
"basic": "Processing",
|
||||||
|
"ocr": "OCR"
|
||||||
|
},
|
||||||
"readonly": "Lesemodus",
|
"readonly": "Lesemodus",
|
||||||
"readonly-archived": "Read only (archived)",
|
"readonly-archived": "Read only (archived)",
|
||||||
"redact-text": {
|
"redact-text": {
|
||||||
@ -2279,12 +2283,6 @@
|
|||||||
"red-user-admin": "Benutzer-Admin",
|
"red-user-admin": "Benutzer-Admin",
|
||||||
"regular": "Regulär"
|
"regular": "Regulär"
|
||||||
},
|
},
|
||||||
"search": {
|
|
||||||
"active-dossiers": "ganze Plattform",
|
|
||||||
"all-dossiers": "all documents",
|
|
||||||
"placeholder": "Nach Dokumenten oder Dokumenteninhalt suchen",
|
|
||||||
"this-dossier": "in diesem Dossier"
|
|
||||||
},
|
|
||||||
"search-screen": {
|
"search-screen": {
|
||||||
"cols": {
|
"cols": {
|
||||||
"assignee": "Bevollmächtigter",
|
"assignee": "Bevollmächtigter",
|
||||||
@ -2308,6 +2306,12 @@
|
|||||||
"no-match": "Keine Dokumente entsprechen Ihren aktuellen Filtern.",
|
"no-match": "Keine Dokumente entsprechen Ihren aktuellen Filtern.",
|
||||||
"table-header": "{length} search {length, plural, one{result} other{results}}"
|
"table-header": "{length} search {length, plural, one{result} other{results}}"
|
||||||
},
|
},
|
||||||
|
"search": {
|
||||||
|
"active-dossiers": "ganze Plattform",
|
||||||
|
"all-dossiers": "all documents",
|
||||||
|
"placeholder": "Nach Dokumenten oder Dokumenteninhalt suchen",
|
||||||
|
"this-dossier": "in diesem Dossier"
|
||||||
|
},
|
||||||
"seconds": "seconds",
|
"seconds": "seconds",
|
||||||
"size": "Size",
|
"size": "Size",
|
||||||
"smtp-auth-config": {
|
"smtp-auth-config": {
|
||||||
@ -2563,4 +2567,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Gestern"
|
"yesterday": "Gestern"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -206,11 +206,14 @@
|
|||||||
"generic": "Failed to save user!"
|
"generic": "Failed to save user!"
|
||||||
},
|
},
|
||||||
"form": {
|
"form": {
|
||||||
|
"account-setup": "User account setup",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"first-name": "First name",
|
"first-name": "First name",
|
||||||
"last-name": "Last name",
|
"last-name": "Last name",
|
||||||
"reset-password": "Reset password",
|
"reset-password": "Reset password",
|
||||||
"role": "Role"
|
"role": "Role",
|
||||||
|
"send-email": "Do not send email requesting the user to set a password",
|
||||||
|
"send-email-explanation": "Select this option if you use SSO. Please note that you will need to inform the user directly."
|
||||||
},
|
},
|
||||||
"title": "{type, select, edit{Edit} create{Add New} other{}} user"
|
"title": "{type, select, edit{Edit} create{Add New} other{}} user"
|
||||||
},
|
},
|
||||||
@ -1081,8 +1084,7 @@
|
|||||||
"dossier-templates-listing": {
|
"dossier-templates-listing": {
|
||||||
"action": {
|
"action": {
|
||||||
"clone": "Clone template",
|
"clone": "Clone template",
|
||||||
"delete": "Delete template",
|
"delete": "Delete template"
|
||||||
"edit": "Edit template"
|
|
||||||
},
|
},
|
||||||
"add-new": "New dossier template",
|
"add-new": "New dossier template",
|
||||||
"bulk": {
|
"bulk": {
|
||||||
@ -1152,6 +1154,7 @@
|
|||||||
"delta-preview": "Delta PDF",
|
"delta-preview": "Delta PDF",
|
||||||
"flatten": "Flatten PDF",
|
"flatten": "Flatten PDF",
|
||||||
"label": "{length} document {length, plural, one{version} other{versions}}",
|
"label": "{length} document {length, plural, one{version} other{versions}}",
|
||||||
|
"optimized-preview": "Optimized Preview PDF",
|
||||||
"original": "Optimized PDF",
|
"original": "Optimized PDF",
|
||||||
"preview": "Preview PDF",
|
"preview": "Preview PDF",
|
||||||
"redacted": "Redacted PDF",
|
"redacted": "Redacted PDF",
|
||||||
@ -2026,6 +2029,7 @@
|
|||||||
"help-mode-dialog": "Help Mode Dialog",
|
"help-mode-dialog": "Help Mode Dialog",
|
||||||
"load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview",
|
"load-all-annotations-warning": "Warning regarding loading all annotations at once in file preview",
|
||||||
"open-structured-view-by-default": "Display Component View by default when opening a document",
|
"open-structured-view-by-default": "Display Component View by default when opening a document",
|
||||||
|
"overwrite-file-option": "Preferred action when re-uploading of an already existing file",
|
||||||
"table-extraction-type": "Table extraction type"
|
"table-extraction-type": "Table extraction type"
|
||||||
},
|
},
|
||||||
"label": "Preferences",
|
"label": "Preferences",
|
||||||
@ -2563,4 +2567,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Yesterday"
|
"yesterday": "Yesterday"
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
205
apps/red-ui/src/assets/pdftron/fonts/Apache License.txt
Normal file
205
apps/red-ui/src/assets/pdftron/fonts/Apache License.txt
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.-------------------------------------------------------------------
|
||||||
|
------------[ Log Start: 2019-Oct-10 19:32:29.143159]--------------
|
||||||
|
System: (Windows, AMD64), PDFNetVersion: 7.1.0.71627
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
[ INFO 19:32:29.143159, fontapp, WebFontCreator.cpp(679)]: logging enabled
|
||||||
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Bold.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Bold.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Bold.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Bold.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Bold.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Bold.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-BoldItalic.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-BoldItalic.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-BoldItalic.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-BoldItalic.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-BoldItalic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-BoldItalic.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Italic.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Italic.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Italic.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Italic.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Italic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Italic.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Regular.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Regular.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Regular.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Regular.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Regular.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Arimo-Regular.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/ArivoBlack.otf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/ArivoBlack.otf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/ArivoBlack.otf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/ArivoBlack.otf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/ArivoBlack.otf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/ArivoBlack.otf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Bold.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Bold.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Bold.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Bold.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Bold.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Bold.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-BoldItalic.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-BoldItalic.ttf
Normal file
Binary file not shown.
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-BoldItalic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-BoldItalic.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Italic.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Italic.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Italic.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Italic.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Italic.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Italic.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Regular.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Regular.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Regular.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Regular.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Regular.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Caladea-Regular.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-Bold.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-Bold.ttf
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-Bold.ttf.brotli
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-Bold.ttf.brotli
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-Bold.ttf.lzma
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-Bold.ttf.lzma
Normal file
Binary file not shown.
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-BoldItalic.ttf
Normal file
BIN
apps/red-ui/src/assets/pdftron/fonts/Carlito-BoldItalic.ttf
Normal file
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user