Compare commits
45 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd9ae173f8 | ||
|
|
d1421420f2 | ||
|
|
2d5a6b474f | ||
|
|
eb6aa43d48 | ||
|
|
f5d63c9174 | ||
|
|
2bd524842e | ||
|
|
1dc069a091 | ||
|
|
c9bb6bc6a5 | ||
|
|
584a6b7bd0 | ||
|
|
a890e4c5bc | ||
|
|
4ec81ed0b3 | ||
|
|
489c3e4117 | ||
|
|
2de02e95c8 | ||
|
|
d883472ed3 | ||
|
|
de238c0a8e | ||
|
|
67c9e54df0 | ||
|
|
7ac3d3e5b6 | ||
|
|
44050c0373 | ||
|
|
67e50478e7 | ||
|
|
edd709df6f | ||
|
|
05b6f88d64 | ||
|
|
7027de6f6e | ||
|
|
7beddc6138 | ||
|
|
71980486a2 | ||
|
|
1081f8ad1c | ||
|
|
435b9f16a9 | ||
|
|
52f124adff | ||
|
|
1171c0d78f | ||
|
|
6cedf8afb0 | ||
|
|
1b2f14ec89 | ||
|
|
dc66b8a708 | ||
|
|
e2cd71dd24 | ||
|
|
3777c12134 | ||
|
|
3bfa4796b0 | ||
|
|
c0c6232f0a | ||
|
|
d52b8b0d87 | ||
|
|
61b869675e | ||
|
|
be743fa9d7 | ||
|
|
e5a3366ec7 | ||
|
|
4a49e68c4a | ||
|
|
15a675515d | ||
|
|
3f8a53b86c | ||
|
|
ae0510add8 | ||
|
|
ca51e31de8 | ||
|
|
02addbbc16 |
@ -258,6 +258,7 @@ export const appModuleFactory = (config: AppConfig) => {
|
|||||||
provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
|
provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
|
||||||
useValue: {
|
useValue: {
|
||||||
disableTooltipInteractivity: true,
|
disableTooltipInteractivity: true,
|
||||||
|
showDelay: 1,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
BaseDatePipe,
|
BaseDatePipe,
|
||||||
|
|||||||
@ -11,7 +11,9 @@ import { DictionaryService } from '@services/entity-services/dictionary.service'
|
|||||||
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||||
import { WatermarkService } from '@services/entity-services/watermark.service';
|
import { WatermarkService } from '@services/entity-services/watermark.service';
|
||||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||||
import { getConfig } from '@iqser/common-ui';
|
import { getConfig, Toaster } from '@iqser/common-ui';
|
||||||
|
import { RulesService } from '../modules/admin/services/rules.service';
|
||||||
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
|
|
||||||
export function templateExistsWhenEnteringAdmin(): CanActivateFn {
|
export function templateExistsWhenEnteringAdmin(): CanActivateFn {
|
||||||
return async function (route: ActivatedRouteSnapshot): Promise<boolean> {
|
return async function (route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||||
@ -21,12 +23,14 @@ export function templateExistsWhenEnteringAdmin(): CanActivateFn {
|
|||||||
const defaultColorsService = inject(DefaultColorsService);
|
const defaultColorsService = inject(DefaultColorsService);
|
||||||
const watermarksService = inject(WatermarkService);
|
const watermarksService = inject(WatermarkService);
|
||||||
const router = inject(Router);
|
const router = inject(Router);
|
||||||
|
const rulesService = inject(RulesService);
|
||||||
const isDocumine = getConfig().IS_DOCUMINE;
|
const isDocumine = getConfig().IS_DOCUMINE;
|
||||||
|
|
||||||
const dossierTemplate = inject(DossierTemplateStatsService).get(dossierTemplateId);
|
const dossierTemplate = inject(DossierTemplateStatsService).get(dossierTemplateId);
|
||||||
await firstValueFrom(fileAttributesService.loadFileAttributesConfig(dossierTemplateId));
|
await firstValueFrom(fileAttributesService.loadFileAttributesConfig(dossierTemplateId));
|
||||||
await firstValueFrom(dictionaryService.loadDictionaryDataForDossierTemplate(dossierTemplateId));
|
await firstValueFrom(dictionaryService.loadDictionaryDataForDossierTemplate(dossierTemplateId));
|
||||||
await firstValueFrom(defaultColorsService.loadForDossierTemplate(dossierTemplateId));
|
await firstValueFrom(defaultColorsService.loadForDossierTemplate(dossierTemplateId));
|
||||||
|
await firstValueFrom(rulesService.getFor(dossierTemplateId));
|
||||||
if (!isDocumine) {
|
if (!isDocumine) {
|
||||||
await firstValueFrom(watermarksService.loadForDossierTemplate(dossierTemplateId));
|
await firstValueFrom(watermarksService.loadForDossierTemplate(dossierTemplateId));
|
||||||
}
|
}
|
||||||
@ -50,6 +54,8 @@ export function templateExistsWhenEnteringDossierList(): CanActivateFn {
|
|||||||
const dictionaryService = inject(DictionaryService);
|
const dictionaryService = inject(DictionaryService);
|
||||||
const defaultColorsService = inject(DefaultColorsService);
|
const defaultColorsService = inject(DefaultColorsService);
|
||||||
const watermarksService = inject(WatermarkService);
|
const watermarksService = inject(WatermarkService);
|
||||||
|
const rulesService = inject(RulesService);
|
||||||
|
const toaster = inject(Toaster);
|
||||||
const isDocumine = getConfig().IS_DOCUMINE;
|
const isDocumine = getConfig().IS_DOCUMINE;
|
||||||
|
|
||||||
await firstValueFrom(dashboardStatsService.loadForTemplate(dossierTemplateId));
|
await firstValueFrom(dashboardStatsService.loadForTemplate(dossierTemplateId));
|
||||||
@ -64,6 +70,10 @@ export function templateExistsWhenEnteringDossierList(): CanActivateFn {
|
|||||||
await firstValueFrom(fileAttributesService.loadFileAttributesConfig(dossierTemplateId));
|
await firstValueFrom(fileAttributesService.loadFileAttributesConfig(dossierTemplateId));
|
||||||
await firstValueFrom(dictionaryService.loadDictionaryDataForDossierTemplate(dossierTemplateId));
|
await firstValueFrom(dictionaryService.loadDictionaryDataForDossierTemplate(dossierTemplateId));
|
||||||
await firstValueFrom(defaultColorsService.loadForDossierTemplate(dossierTemplateId));
|
await firstValueFrom(defaultColorsService.loadForDossierTemplate(dossierTemplateId));
|
||||||
|
const rules = await firstValueFrom(rulesService.getFor(dossierTemplateId));
|
||||||
|
if (rules.timeoutDetected) {
|
||||||
|
toaster.error(_('dossier-listing.rules.timeoutError'));
|
||||||
|
}
|
||||||
if (!isDocumine) {
|
if (!isDocumine) {
|
||||||
await firstValueFrom(watermarksService.loadForDossierTemplate(dossierTemplateId));
|
await firstValueFrom(watermarksService.loadForDossierTemplate(dossierTemplateId));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,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 {
|
||||||
@ -27,6 +27,7 @@ interface PreferencesForm {
|
|||||||
// warnings preferences
|
// warnings preferences
|
||||||
loadAllAnnotationsWarning: boolean;
|
loadAllAnnotationsWarning: boolean;
|
||||||
helpModeDialog: boolean;
|
helpModeDialog: boolean;
|
||||||
|
overwriteFileOption: boolean;
|
||||||
|
|
||||||
[k: string]: any;
|
[k: string]: any;
|
||||||
}
|
}
|
||||||
@ -57,6 +58,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;
|
||||||
@ -65,76 +72,87 @@ 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()],
|
||||||
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.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(),
|
||||||
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -50,9 +50,11 @@
|
|||||||
icon="iqser:trash"
|
icon="iqser:trash"
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
}
|
}
|
||||||
@if (selectedComponent?.id === component.id) {
|
<mat-icon
|
||||||
<mat-icon class="arrow-right" svgIcon="red:arrow-right"></mat-icon>
|
[class.not-visible]="selectedComponent?.id !== component.id"
|
||||||
}
|
class="arrow-right"
|
||||||
|
svgIcon="red:arrow-right"
|
||||||
|
></mat-icon>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -38,6 +38,10 @@
|
|||||||
|
|
||||||
.arrow-right {
|
.arrow-right {
|
||||||
transform: scale(0.7);
|
transform: scale(0.7);
|
||||||
|
|
||||||
|
&.not-visible {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -45,6 +49,8 @@
|
|||||||
.content-container {
|
.content-container {
|
||||||
background-color: var(--iqser-grey-6);
|
background-color: var(--iqser-grey-6);
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.content-header {
|
.content-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -61,6 +67,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@ -68,7 +75,8 @@
|
|||||||
.components-list {
|
.components-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
background-color: var(--iqser-white);
|
background-color: var(--iqser-white);
|
||||||
width: 100%;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|||||||
@ -103,6 +103,7 @@ export default class ComponentDefinitionsComponent extends BaseFormComponent imp
|
|||||||
this._dialogService.openDialog('confirm', null, async () => {
|
this._dialogService.openDialog('confirm', null, async () => {
|
||||||
await firstValueFrom(this._componentDefinitionsService.deleteComponentDefinitions(this.#dossierTemplateId, [componentId]));
|
await firstValueFrom(this._componentDefinitionsService.deleteComponentDefinitions(this.#dossierTemplateId, [componentId]));
|
||||||
await this.#loadData();
|
await this.#loadData();
|
||||||
|
this.selectedComponent = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@
|
|||||||
<div
|
<div
|
||||||
class="row"
|
class="row"
|
||||||
[matTooltip]="'add-edit-component-mapping.disabled-file-options' | translate"
|
[matTooltip]="'add-edit-component-mapping.disabled-file-options' | translate"
|
||||||
[matTooltipDisabled]="!disabledFileOptions"
|
[matTooltipDisabled]="!form.get('encoding')?.disabled"
|
||||||
[matTooltipPosition]="'above'"
|
[matTooltipPosition]="'above'"
|
||||||
>
|
>
|
||||||
<div class="iqser-input-group required w-150">
|
<div class="iqser-input-group required w-150">
|
||||||
@ -40,13 +40,12 @@
|
|||||||
formControlName="delimiter"
|
formControlName="delimiter"
|
||||||
name="delimiter"
|
name="delimiter"
|
||||||
type="text"
|
type="text"
|
||||||
[class.disabled-file-options]="disabledFileOptions"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="iqser-input-group required w-150">
|
<div class="iqser-input-group required w-150">
|
||||||
<label translate="add-edit-component-mapping.form.encoding-type"></label>
|
<label translate="add-edit-component-mapping.form.encoding-type"></label>
|
||||||
<mat-form-field [class.disabled-file-options]="disabledFileOptions">
|
<mat-form-field>
|
||||||
<mat-select formControlName="encoding">
|
<mat-select formControlName="encoding">
|
||||||
<mat-option *ngFor="let type of encodingTypeOptions" [value]="type">
|
<mat-option *ngFor="let type of encodingTypeOptions" [value]="type">
|
||||||
{{ translations[type] | translate }}
|
{{ translations[type] | translate }}
|
||||||
|
|||||||
@ -18,11 +18,6 @@
|
|||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled-file-options {
|
|
||||||
opacity: 0.5;
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.row:last-child {
|
.row:last-child {
|
||||||
|
|||||||
@ -52,7 +52,6 @@ export class AddEditComponentMappingDialogComponent
|
|||||||
{
|
{
|
||||||
protected readonly encodingTypeOptions = Object.keys(FileAttributeEncodingTypes);
|
protected readonly encodingTypeOptions = Object.keys(FileAttributeEncodingTypes);
|
||||||
protected readonly translations = fileAttributeEncodingTypesTranslations;
|
protected readonly translations = fileAttributeEncodingTypesTranslations;
|
||||||
#fileChanged = false;
|
|
||||||
activeFile: File;
|
activeFile: File;
|
||||||
form!: UntypedFormGroup;
|
form!: UntypedFormGroup;
|
||||||
|
|
||||||
@ -73,13 +72,14 @@ export class AddEditComponentMappingDialogComponent
|
|||||||
const file = new Blob([fileContent.body as Blob], { type: 'text/csv' });
|
const file = new Blob([fileContent.body as Blob], { type: 'text/csv' });
|
||||||
this.form.get('file').setValue(file);
|
this.form.get('file').setValue(file);
|
||||||
this.initialFormValue = this.form.getRawValue();
|
this.initialFormValue = this.form.getRawValue();
|
||||||
|
this.#disableEncodingAndDelimiter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeFile(file: File) {
|
changeFile(file: File) {
|
||||||
this.#fileChanged = true;
|
|
||||||
this.form.get('file').setValue(file);
|
this.form.get('file').setValue(file);
|
||||||
this.form.get('fileName').setValue(file?.name);
|
this.form.get('fileName').setValue(file?.name);
|
||||||
|
this.#enableEncodingAndDelimiter();
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
@ -96,7 +96,13 @@ export class AddEditComponentMappingDialogComponent
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
get disabledFileOptions() {
|
#disableEncodingAndDelimiter() {
|
||||||
return this.initialFormValue?.file && !this.#fileChanged;
|
this.form.get('encoding').disable();
|
||||||
|
this.form.get('delimiter').disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
#enableEncodingAndDelimiter() {
|
||||||
|
this.form.get('encoding').enable();
|
||||||
|
this.form.get('delimiter').enable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,6 +34,21 @@
|
|||||||
<span [innerHTML]="'dossier-template-info-screen.created-on' | translate: { date: createdOn }"></span>
|
<span [innerHTML]="'dossier-template-info-screen.created-on' | translate: { date: createdOn }"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="areRulesLocked()">
|
||||||
|
<mat-icon
|
||||||
|
(click)="resetRules()"
|
||||||
|
[matTooltip]="
|
||||||
|
currentUser.isAdmin
|
||||||
|
? ('dossier-template-info-screen.rules-reset.tooltip' | translate)
|
||||||
|
: ('dossier-template-info-screen.rules-reset.disabled-action' | translate)
|
||||||
|
"
|
||||||
|
[class.cursor-pointer]="currentUser.isAdmin"
|
||||||
|
svgIcon="iqser:alert-circle"
|
||||||
|
class="action-icon"
|
||||||
|
></mat-icon>
|
||||||
|
<span class="error">{{ 'dossier-template-info-screen.rules-reset.label' | translate }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<mat-icon svgIcon="red:entries"></mat-icon>
|
<mat-icon svgIcon="red:entries"></mat-icon>
|
||||||
{{ 'dossier-template-info-screen.entries' | translate: { count: ctx.stats.numberOfEntries } }}
|
{{ 'dossier-template-info-screen.entries' | translate: { count: ctx.stats.numberOfEntries } }}
|
||||||
|
|||||||
@ -18,3 +18,17 @@
|
|||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: var(--iqser-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-icon {
|
||||||
|
::ng-deep svg g {
|
||||||
|
fill: var(--iqser-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cursor-pointer {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, computed, Input, OnInit } from '@angular/core';
|
||||||
import { ContextComponent } from '@iqser/common-ui/lib/utils';
|
import { ContextComponent } from '@iqser/common-ui/lib/utils';
|
||||||
import { type DossierTemplate, type DossierTemplateStats } from '@red/domain';
|
import { type DossierTemplate, type DossierTemplateStats } from '@red/domain';
|
||||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||||
@ -9,6 +9,12 @@ import { MatIcon } from '@angular/material/icon';
|
|||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { InitialsAvatarComponent } from '@common-ui/users';
|
import { InitialsAvatarComponent } from '@common-ui/users';
|
||||||
import { DatePipe } from '@shared/pipes/date.pipe';
|
import { DatePipe } from '@shared/pipes/date.pipe';
|
||||||
|
import { RulesService } from '../../../services/rules.service';
|
||||||
|
import { Toaster } from '@iqser/common-ui';
|
||||||
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
|
import { getCurrentUser } from '@users/user.service';
|
||||||
|
|
||||||
interface Context {
|
interface Context {
|
||||||
readonly dossierTemplate: DossierTemplate;
|
readonly dossierTemplate: DossierTemplate;
|
||||||
@ -20,16 +26,22 @@ interface Context {
|
|||||||
templateUrl: './dossier-template-details.component.html',
|
templateUrl: './dossier-template-details.component.html',
|
||||||
styleUrls: ['./dossier-template-details.component.scss'],
|
styleUrls: ['./dossier-template-details.component.scss'],
|
||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [NgIf, AsyncPipe, MatIcon, TranslateModule, DatePipe, InitialsAvatarComponent],
|
imports: [NgIf, AsyncPipe, MatIcon, TranslateModule, DatePipe, InitialsAvatarComponent, MatTooltip],
|
||||||
})
|
})
|
||||||
export class DossierTemplateDetailsComponent extends ContextComponent<Context> implements OnInit {
|
export class DossierTemplateDetailsComponent extends ContextComponent<Context> implements OnInit {
|
||||||
readonly translations = dossierTemplateStatusTranslations;
|
readonly translations = dossierTemplateStatusTranslations;
|
||||||
|
|
||||||
@Input({ required: true }) dossierTemplateId: string;
|
@Input({ required: true }) dossierTemplateId: string;
|
||||||
|
readonly areRulesLocked = computed(() => {
|
||||||
|
return this._rulesService.currentTemplateRules().timeoutDetected;
|
||||||
|
});
|
||||||
|
readonly currentUser = getCurrentUser();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||||
private readonly _dossierTemplateStatsService: DossierTemplateStatsService,
|
private readonly _dossierTemplateStatsService: DossierTemplateStatsService,
|
||||||
|
private readonly _rulesService: RulesService,
|
||||||
|
private readonly _toaster: Toaster,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
@ -40,4 +52,11 @@ export class DossierTemplateDetailsComponent extends ContextComponent<Context> i
|
|||||||
stats: this._dossierTemplateStatsService.watch$(this.dossierTemplateId),
|
stats: this._dossierTemplateStatsService.watch$(this.dossierTemplateId),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async resetRules() {
|
||||||
|
if (!this.currentUser.isAdmin) return;
|
||||||
|
await firstValueFrom(this._rulesService.reset(this.dossierTemplateId));
|
||||||
|
this._toaster.success(_('dossier-template-info-screen.rules-reset.success'));
|
||||||
|
await firstValueFrom(this._rulesService.getFor(this.dossierTemplateId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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();
|
||||||
|
|||||||
@ -1,9 +1,25 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { GenericService } from '@iqser/common-ui';
|
import { EntitiesService, QueryParam } from '@iqser/common-ui';
|
||||||
import { IRules } from '@red/domain';
|
import { IRules, Rules } from '@red/domain';
|
||||||
|
import { map, Observable, tap } from 'rxjs';
|
||||||
|
import { List } from '@common-ui/utils';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
import { distinctUntilChanged, filter } from 'rxjs/operators';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({ providedIn: 'root' })
|
||||||
export class RulesService extends GenericService<IRules> {
|
export class RulesService extends EntitiesService<IRules, Rules> {
|
||||||
|
readonly currentTemplateRules = toSignal(
|
||||||
|
this.all$.pipe(
|
||||||
|
filter(all => !!all.length),
|
||||||
|
map(rules => rules[0]),
|
||||||
|
distinctUntilChanged(
|
||||||
|
(prev, curr) =>
|
||||||
|
prev.rules === curr.rules &&
|
||||||
|
prev.timeoutDetected === curr.timeoutDetected &&
|
||||||
|
prev.dossierTemplateId === curr.dossierTemplateId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
protected readonly _defaultModelPath = 'rules';
|
protected readonly _defaultModelPath = 'rules';
|
||||||
|
|
||||||
download(dossierTemplateId: string, ruleFileType: IRules['ruleFileType'] = 'ENTITY') {
|
download(dossierTemplateId: string, ruleFileType: IRules['ruleFileType'] = 'ENTITY') {
|
||||||
@ -13,4 +29,12 @@ export class RulesService extends GenericService<IRules> {
|
|||||||
uploadRules(body: IRules) {
|
uploadRules(body: IRules) {
|
||||||
return this._post<unknown>({ ...body, ruleFileType: body.ruleFileType ?? 'ENTITY' });
|
return this._post<unknown>({ ...body, ruleFileType: body.ruleFileType ?? 'ENTITY' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFor<R = IRules>(entityId: string, queryParams?: List<QueryParam>): Observable<R> {
|
||||||
|
return super.getFor<R>(entityId, queryParams).pipe(tap(rules => this.setEntities([rules as Rules])));
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(dossierTemplateId: string, ruleFileType: IRules['ruleFileType'] = 'ENTITY') {
|
||||||
|
return this._put(null, `${this._defaultModelPath}/${dossierTemplateId}/${ruleFileType}/reset`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
<ng-container (longPress)="forceReanalysisAction($event)" *ngIf="selectedFiles.length" redactionLongPress>
|
<ng-container (longPress)="forceReanalysisAction($event)" *ngIf="selectedFiles().length" redactionLongPress>
|
||||||
<redaction-expandable-file-actions
|
<redaction-expandable-file-actions
|
||||||
[actions]="buttons"
|
[actions]="buttons()"
|
||||||
[buttonType]="buttonType"
|
[buttonType]="buttonType()"
|
||||||
[maxWidth]="maxWidth"
|
[maxWidth]="maxWidth()"
|
||||||
[tooltipPosition]="IqserTooltipPositions.above"
|
[tooltipPosition]="IqserTooltipPositions.above"
|
||||||
>
|
>
|
||||||
</redaction-expandable-file-actions>
|
</redaction-expandable-file-actions>
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { Component, Input, OnChanges } from '@angular/core';
|
import { Component, computed, input, signal } from '@angular/core';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { CircleButtonType, CircleButtonTypes } from '@iqser/common-ui';
|
import { CircleButtonType, CircleButtonTypes, Toaster } from '@iqser/common-ui';
|
||||||
import { Action, ActionTypes, Dossier, File, ProcessingFileStatuses } from '@red/domain';
|
import { Action, ActionTypes, Dossier, File, ProcessingFileStatuses } from '@red/domain';
|
||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { LongPressDirective, LongPressEvent } from '@shared/directives/long-press.directive';
|
import { LongPressDirective, LongPressEvent } from '@shared/directives/long-press.directive';
|
||||||
@ -9,6 +9,8 @@ import { BulkActionsService } from '../../services/bulk-actions.service';
|
|||||||
import { ExpandableFileActionsComponent } from '@shared/components/expandable-file-actions/expandable-file-actions.component';
|
import { ExpandableFileActionsComponent } from '@shared/components/expandable-file-actions/expandable-file-actions.component';
|
||||||
import { IqserTooltipPositions } from '@common-ui/utils';
|
import { IqserTooltipPositions } from '@common-ui/utils';
|
||||||
import { NgIf } from '@angular/common';
|
import { NgIf } from '@angular/common';
|
||||||
|
import { RulesService } from '../../../admin/services/rules.service';
|
||||||
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-dossier-overview-bulk-actions [dossier] [selectedFiles]',
|
selector: 'redaction-dossier-overview-bulk-actions [dossier] [selectedFiles]',
|
||||||
@ -17,218 +19,211 @@ import { NgIf } from '@angular/common';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [LongPressDirective, ExpandableFileActionsComponent, NgIf],
|
imports: [LongPressDirective, ExpandableFileActionsComponent, NgIf],
|
||||||
})
|
})
|
||||||
export class DossierOverviewBulkActionsComponent implements OnChanges {
|
export class DossierOverviewBulkActionsComponent {
|
||||||
#analysisForced: boolean;
|
readonly dossier = input<Dossier>();
|
||||||
#canAssignToSelf: boolean;
|
readonly selectedFiles = input<File[]>();
|
||||||
#canAssign: boolean;
|
readonly buttonType = input<CircleButtonType>(CircleButtonTypes.default);
|
||||||
#canDelete: boolean;
|
readonly maxWidth = input<number>();
|
||||||
#canReanalyse: boolean;
|
readonly buttons = computed(() => this.#buttons);
|
||||||
#canDisableAutoAnalysis: boolean;
|
|
||||||
#canEnableAutoAnalysis: boolean;
|
|
||||||
#canOcr: boolean;
|
|
||||||
#canSetToNew: boolean;
|
|
||||||
#canSetToUnderReview: boolean;
|
|
||||||
#canSetToUnderApproval: boolean;
|
|
||||||
#isReadyForApproval: boolean;
|
|
||||||
#canApprove: boolean;
|
|
||||||
#canUndoApproval: boolean;
|
|
||||||
#canToggleAnalysis: boolean;
|
|
||||||
#assignTooltip: string;
|
|
||||||
#toggleAnalysisTooltip: string;
|
|
||||||
#allFilesAreExcluded: boolean;
|
|
||||||
#canMoveToSameState: boolean;
|
|
||||||
@Input() dossier: Dossier;
|
|
||||||
@Input() selectedFiles: File[];
|
|
||||||
@Input() buttonType: CircleButtonType = CircleButtonTypes.default;
|
|
||||||
@Input() maxWidth: number;
|
|
||||||
buttons: Action[];
|
|
||||||
readonly IqserTooltipPositions = IqserTooltipPositions;
|
readonly IqserTooltipPositions = IqserTooltipPositions;
|
||||||
|
readonly #areFilesInErrorState = computed(() => this.selectedFiles().some(file => file.isError));
|
||||||
|
readonly #areRulesLocked = computed(() => this._rulesService.currentTemplateRules().timeoutDetected);
|
||||||
|
readonly #allFilesAreUnderReviewOrUnassigned = computed(() =>
|
||||||
|
this.selectedFiles().reduce((acc, file) => acc && (file.isUnderReview || file.isNew), true),
|
||||||
|
);
|
||||||
|
readonly #allFilesAreUnderApproval = computed(() => this.selectedFiles().reduce((acc, file) => acc && file.isUnderApproval, true));
|
||||||
|
readonly #allFilesAreExcluded = computed(() => this.selectedFiles().reduce((acc, file) => acc && file.excluded, true));
|
||||||
|
readonly #allFilesAreApproved = computed(() => this.selectedFiles().reduce((acc, file) => acc && file.isApproved, true));
|
||||||
|
readonly #canMoveToSameState = computed(
|
||||||
|
() => this.#allFilesAreUnderReviewOrUnassigned() || this.#allFilesAreUnderApproval() || this.#allFilesAreApproved(),
|
||||||
|
);
|
||||||
|
readonly #canAssign = computed(
|
||||||
|
() =>
|
||||||
|
this.#canMoveToSameState() &&
|
||||||
|
(this._permissionsService.canAssignUser(this.selectedFiles(), this.dossier()) ||
|
||||||
|
this._permissionsService.canUnassignUser(this.selectedFiles(), this.dossier())),
|
||||||
|
);
|
||||||
|
readonly #canAssignToSelf = computed(
|
||||||
|
() => this.#canMoveToSameState() && this._permissionsService.canAssignToSelf(this.selectedFiles(), this.dossier()),
|
||||||
|
);
|
||||||
|
readonly #canDelete = computed(() => this._permissionsService.canSoftDeleteFile(this.selectedFiles(), this.dossier()));
|
||||||
|
readonly #canReanalyse = computed(() => this._permissionsService.canReanalyseFile(this.selectedFiles(), this.dossier()));
|
||||||
|
readonly #canDisableAutoAnalysis = computed(
|
||||||
|
() => this._permissionsService.canDisableAutoAnalysis(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canEnableAutoAnalysis = computed(
|
||||||
|
() => this._permissionsService.canEnableAutoAnalysis(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canToggleAnalysis = computed(() => this._permissionsService.canToggleAnalysis(this.selectedFiles(), this.dossier()));
|
||||||
|
readonly #canOcr = computed(
|
||||||
|
() => this._permissionsService.canOcrFile(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canSetToNew = computed(
|
||||||
|
() => this._permissionsService.canSetToNew(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canSetToUnderReview = computed(
|
||||||
|
() => this._permissionsService.canSetUnderReview(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canSetToUnderApproval = computed(
|
||||||
|
() => this._permissionsService.canSetUnderApproval(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #isReadyForApproval = computed(
|
||||||
|
() => this._permissionsService.isReadyForApproval(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canApprove = computed(
|
||||||
|
() => this._permissionsService.canBeApproved(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #canUndoApproval = computed(
|
||||||
|
() => this._permissionsService.canUndoApproval(this.selectedFiles(), this.dossier()) && !this.#areFilesInErrorState(),
|
||||||
|
);
|
||||||
|
readonly #assignTooltip = computed(() =>
|
||||||
|
this.#allFilesAreUnderApproval() ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer'),
|
||||||
|
);
|
||||||
|
readonly #toggleAnalysisTooltip = computed(() =>
|
||||||
|
this.#allFilesAreExcluded() ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable'),
|
||||||
|
);
|
||||||
|
readonly #analysisForced = signal(false);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _permissionsService: PermissionsService,
|
private readonly _permissionsService: PermissionsService,
|
||||||
private readonly _userPreferenceService: UserPreferenceService,
|
private readonly _userPreferenceService: UserPreferenceService,
|
||||||
private readonly _bulkActionsService: BulkActionsService,
|
private readonly _bulkActionsService: BulkActionsService,
|
||||||
|
private readonly _rulesService: RulesService,
|
||||||
|
private readonly _toaster: Toaster,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
private get _buttons(): Action[] {
|
get #buttons(): Action[] {
|
||||||
const actions: Action[] = [
|
const actions: Action[] = [
|
||||||
{
|
{
|
||||||
id: 'delete-files-btn',
|
id: 'delete-files-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.delete(this.selectedFiles),
|
action: () => this._bulkActionsService.delete(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.bulk.delete'),
|
tooltip: _('dossier-overview.bulk.delete'),
|
||||||
icon: 'iqser:trash',
|
icon: 'iqser:trash',
|
||||||
show: this.#canDelete,
|
show: this.#canDelete(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'assign-files-btn',
|
id: 'assign-files-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.assign(this.selectedFiles),
|
action: () => this._bulkActionsService.assign(this.selectedFiles()),
|
||||||
tooltip: this.#assignTooltip,
|
tooltip: this.#assignTooltip(),
|
||||||
icon: 'red:assign',
|
icon: 'red:assign',
|
||||||
show: this.#canAssign,
|
show: this.#canAssign(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'assign-files-to-me-btn',
|
id: 'assign-files-to-me-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.assignToMe(this.selectedFiles),
|
action: () => this._bulkActionsService.assignToMe(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.assign-me'),
|
tooltip: _('dossier-overview.assign-me'),
|
||||||
icon: 'red:assign-me',
|
icon: 'red:assign-me',
|
||||||
show: this.#canAssignToSelf,
|
show: this.#canAssignToSelf(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'to-new-btn',
|
id: 'to-new-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.setToNew(this.selectedFiles),
|
action: () => this._bulkActionsService.setToNew(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.back-to-new'),
|
tooltip: _('dossier-overview.back-to-new'),
|
||||||
icon: 'red:undo',
|
icon: 'red:undo',
|
||||||
show: this.#canSetToNew,
|
show: this.#canSetToNew(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'to-under-approval-btn',
|
id: 'to-under-approval-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles),
|
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.under-approval'),
|
tooltip: _('dossier-overview.under-approval'),
|
||||||
icon: 'red:ready-for-approval',
|
icon: 'red:ready-for-approval',
|
||||||
show: this.#canSetToUnderApproval,
|
show: this.#canSetToUnderApproval(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'to-under-review-btn',
|
id: 'to-under-review-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.backToUnderReview(this.selectedFiles),
|
action: () => this._bulkActionsService.backToUnderReview(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.under-review'),
|
tooltip: _('dossier-overview.under-review'),
|
||||||
icon: 'red:undo',
|
icon: 'red:undo',
|
||||||
show: this.#canSetToUnderReview,
|
show: this.#canSetToUnderReview(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'download-files-btn',
|
id: 'download-files-btn',
|
||||||
type: ActionTypes.downloadBtn,
|
type: ActionTypes.downloadBtn,
|
||||||
show: !this.selectedFiles.some(file => file.processingStatus === ProcessingFileStatuses.ERROR || !file.lastProcessed),
|
show: !this.selectedFiles().some(file => file.processingStatus === ProcessingFileStatuses.ERROR || !file.lastProcessed),
|
||||||
files: this.selectedFiles,
|
files: this.selectedFiles(),
|
||||||
dossier: this.dossier,
|
dossier: this.dossier(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'approve-files-btn',
|
id: 'approve-files-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.approve(this.selectedFiles),
|
action: () => this._bulkActionsService.approve(this.selectedFiles()),
|
||||||
disabled: !this.#canApprove,
|
disabled: !this.#canApprove(),
|
||||||
tooltip: this.#canApprove ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
|
tooltip: this.#canApprove() ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
|
||||||
icon: 'red:approved',
|
icon: 'red:approved',
|
||||||
show: this.#isReadyForApproval,
|
show: this.#isReadyForApproval(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'set-under-approval-btn',
|
id: 'set-under-approval-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles),
|
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.under-approval'),
|
tooltip: _('dossier-overview.under-approval'),
|
||||||
icon: 'red:undo',
|
icon: 'red:undo',
|
||||||
show: this.#canUndoApproval,
|
show: this.#canUndoApproval(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'ocr-files-btn',
|
id: 'ocr-files-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.ocr(this.selectedFiles),
|
action: () => this._bulkActionsService.ocr(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.ocr-file'),
|
tooltip: _('dossier-overview.ocr-file'),
|
||||||
icon: 'iqser:ocr',
|
icon: 'iqser:ocr',
|
||||||
show: this.#canOcr,
|
show: this.#canOcr(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'reanalyse-files-btn',
|
id: 'reanalyse-files-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.reanalyse(this.selectedFiles),
|
action: () => this.#reanalyseBulk(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.bulk.reanalyse'),
|
tooltip: this.#areRulesLocked() ? _('dossier-listing.rules.timeoutError') : _('dossier-overview.bulk.reanalyse'),
|
||||||
icon: 'iqser:refresh',
|
icon: 'iqser:refresh',
|
||||||
|
disabled: this.#areRulesLocked(),
|
||||||
show:
|
show:
|
||||||
this.#canReanalyse &&
|
this.#canReanalyse() &&
|
||||||
(this.#analysisForced || this.#canEnableAutoAnalysis || this.selectedFiles.every(file => file.isError)),
|
(this.#analysisForced() || this.#canEnableAutoAnalysis() || this.selectedFiles().every(file => file.isError)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'stop-automatic-analysis-btn',
|
id: 'stop-automatic-analysis-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
|
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.stop-auto-analysis'),
|
tooltip: _('dossier-overview.stop-auto-analysis'),
|
||||||
icon: 'red:disable-analysis',
|
icon: 'red:disable-analysis',
|
||||||
show: this.#canDisableAutoAnalysis,
|
show: this.#canDisableAutoAnalysis(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'start-automatic-analysis-btn',
|
id: 'start-automatic-analysis-btn',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
|
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles()),
|
||||||
tooltip: _('dossier-overview.start-auto-analysis'),
|
tooltip: _('dossier-overview.start-auto-analysis'),
|
||||||
icon: 'red:enable-analysis',
|
icon: 'red:enable-analysis',
|
||||||
show: this.#canEnableAutoAnalysis,
|
show: this.#canEnableAutoAnalysis(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'toggle-analysis-btn',
|
id: 'toggle-analysis-btn',
|
||||||
type: ActionTypes.toggle,
|
type: ActionTypes.toggle,
|
||||||
action: () => this._bulkActionsService.toggleAnalysis(this.selectedFiles, !this.#allFilesAreExcluded),
|
action: () => this._bulkActionsService.toggleAnalysis(this.selectedFiles(), !this.#allFilesAreExcluded()),
|
||||||
tooltip: this.#toggleAnalysisTooltip,
|
tooltip: this.#toggleAnalysisTooltip(),
|
||||||
checked: !this.#allFilesAreExcluded,
|
checked: !this.#allFilesAreExcluded(),
|
||||||
show: this.#canToggleAnalysis,
|
show: this.#canToggleAnalysis(),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return actions.filter(btn => btn.show);
|
return actions.filter(btn => btn.show);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
|
||||||
this._setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
forceReanalysisAction($event: LongPressEvent) {
|
forceReanalysisAction($event: LongPressEvent) {
|
||||||
this.#analysisForced = !$event.touchEnd && this._userPreferenceService.isIqserDevMode;
|
this.#analysisForced.set(!$event.touchEnd && this._userPreferenceService.isIqserDevMode);
|
||||||
this._setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setup() {
|
async #reanalyseBulk(selectedFiles: File[]) {
|
||||||
if (!this.selectedFiles.length) {
|
const rules = await firstValueFrom(this._rulesService.getFor(this.dossier().dossierTemplateId));
|
||||||
|
if (rules.timeoutDetected) {
|
||||||
|
this._toaster.error(_('dossier-listing.rules.timeoutError'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce(
|
await this._bulkActionsService.reanalyse(selectedFiles);
|
||||||
(acc, file) => acc && (file.isUnderReview || file.isNew),
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
|
|
||||||
const allFilesAreApproved = this.selectedFiles.reduce((acc, file) => acc && file.isApproved, true);
|
|
||||||
this.#allFilesAreExcluded = this.selectedFiles.reduce((acc, file) => acc && file.excluded, true);
|
|
||||||
this.#canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval || allFilesAreApproved;
|
|
||||||
|
|
||||||
this.#canAssign =
|
|
||||||
this.#canMoveToSameState &&
|
|
||||||
(this._permissionsService.canAssignUser(this.selectedFiles, this.dossier) ||
|
|
||||||
this._permissionsService.canUnassignUser(this.selectedFiles, this.dossier));
|
|
||||||
this.#canAssignToSelf = this.#canMoveToSameState && this._permissionsService.canAssignToSelf(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canDelete = this._permissionsService.canSoftDeleteFile(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canReanalyse = this._permissionsService.canReanalyseFile(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canOcr = this._permissionsService.canOcrFile(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canSetToNew = this._permissionsService.canSetToNew(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canSetToUnderApproval = this._permissionsService.canSetUnderApproval(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#isReadyForApproval = this._permissionsService.isReadyForApproval(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canApprove = this._permissionsService.canBeApproved(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#canUndoApproval = this._permissionsService.canUndoApproval(this.selectedFiles, this.dossier);
|
|
||||||
|
|
||||||
this.#assignTooltip = allFilesAreUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
|
|
||||||
|
|
||||||
this.#toggleAnalysisTooltip = this.#allFilesAreExcluded
|
|
||||||
? _('file-preview.toggle-analysis.enable')
|
|
||||||
: _('file-preview.toggle-analysis.disable');
|
|
||||||
|
|
||||||
this.buttons = this._buttons;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,7 +61,8 @@
|
|||||||
*ngFor="let config of statusConfig"
|
*ngFor="let config of statusConfig"
|
||||||
[attr.help-mode-key]="'dashboard_in_dossier'"
|
[attr.help-mode-key]="'dashboard_in_dossier'"
|
||||||
[config]="config"
|
[config]="config"
|
||||||
filterKey="processingTypeFilters"
|
[class.indent]="!!PendingTypes[config.id]"
|
||||||
|
[filterKey]="PendingTypes[config.id] ? 'pendingTypeFilters' : 'processingTypeFilters'"
|
||||||
></iqser-progress-bar>
|
></iqser-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -45,3 +45,7 @@
|
|||||||
iqser-progress-bar:not(:last-child) {
|
iqser-progress-bar:not(:last-child) {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.indent {
|
||||||
|
margin-left: 32px;
|
||||||
|
}
|
||||||
|
|||||||
@ -21,7 +21,9 @@ import {
|
|||||||
DossierAttributeWithValue,
|
DossierAttributeWithValue,
|
||||||
DossierStats,
|
DossierStats,
|
||||||
File,
|
File,
|
||||||
|
FileErrorCodes,
|
||||||
IDossierRequest,
|
IDossierRequest,
|
||||||
|
PendingTypes,
|
||||||
ProcessingTypes,
|
ProcessingTypes,
|
||||||
StatusSorter,
|
StatusSorter,
|
||||||
User,
|
User,
|
||||||
@ -58,7 +60,6 @@ interface DossierDetailsContext {
|
|||||||
NgIf,
|
NgIf,
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
IqserAllowDirective,
|
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
DonutChartComponent,
|
DonutChartComponent,
|
||||||
IqserLoadingModule,
|
IqserLoadingModule,
|
||||||
@ -68,12 +69,14 @@ interface DossierDetailsContext {
|
|||||||
AssignUserDropdownComponent,
|
AssignUserDropdownComponent,
|
||||||
InitialsAvatarComponent,
|
InitialsAvatarComponent,
|
||||||
TeamMembersComponent,
|
TeamMembersComponent,
|
||||||
|
IqserAllowDirective,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class DossierDetailsComponent extends ContextComponent<DossierDetailsContext> {
|
export class DossierDetailsComponent extends ContextComponent<DossierDetailsContext> {
|
||||||
#currentChartSubtitleIndex = 0;
|
#currentChartSubtitleIndex = 0;
|
||||||
readonly #dossierId = getParam(DOSSIER_ID);
|
readonly #dossierId = getParam(DOSSIER_ID);
|
||||||
protected readonly circleButtonTypes = CircleButtonTypes;
|
protected readonly circleButtonTypes = CircleButtonTypes;
|
||||||
|
protected readonly PendingTypes = PendingTypes;
|
||||||
@Input() dossierAttributes: DossierAttributeWithValue[];
|
@Input() dossierAttributes: DossierAttributeWithValue[];
|
||||||
@Output() readonly toggleCollapse = new EventEmitter();
|
@Output() readonly toggleCollapse = new EventEmitter();
|
||||||
editingOwner = false;
|
editingOwner = false;
|
||||||
@ -97,14 +100,17 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
|
|||||||
super();
|
super();
|
||||||
const dossier$ = _dossiersService.getEntityChanged$(this.#dossierId).pipe(shareLast());
|
const dossier$ = _dossiersService.getEntityChanged$(this.#dossierId).pipe(shareLast());
|
||||||
const filesChanged$ = _filesMapService.watchChanged$(this.#dossierId).pipe(shareLast());
|
const filesChanged$ = _filesMapService.watchChanged$(this.#dossierId).pipe(shareLast());
|
||||||
|
const files$ = _filesMapService.get$(this.#dossierId).pipe(shareLast());
|
||||||
const dossierStats$ = dossierStatsService.watch$(this.#dossierId).pipe(shareLast());
|
const dossierStats$ = dossierStatsService.watch$(this.#dossierId).pipe(shareLast());
|
||||||
const dossierStatsWithEffects$ = dossierStats$.pipe(
|
const dossierStatsWithEffects$ = dossierStats$.pipe(
|
||||||
combineLatestWith(filesChanged$),
|
combineLatestWith(filesChanged$),
|
||||||
tap(([stats]) => this.#calculateChartConfig(stats)),
|
tap(([stats]) => this.#calculateChartConfig(stats)),
|
||||||
map(([stats]) => stats),
|
map(([stats]) => stats),
|
||||||
);
|
);
|
||||||
const statusConfig$ = dossierStats$.pipe(map(stats => this.#calculateStatusConfig(stats)));
|
const statusConfig$ = dossierStats$.pipe(
|
||||||
|
combineLatestWith(files$),
|
||||||
|
map(([stats, files]) => this.#calculateStatusConfig(stats, files)),
|
||||||
|
);
|
||||||
super._initContext({
|
super._initContext({
|
||||||
needsWorkFilters: filterService.getFilterModels$('needsWorkFilters'),
|
needsWorkFilters: filterService.getFilterModels$('needsWorkFilters'),
|
||||||
dossier: dossier$,
|
dossier: dossier$,
|
||||||
@ -152,7 +158,8 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
|
|||||||
.reduce((sum: number, file: File) => sum + file.numberOfPages, 0);
|
.reduce((sum: number, file: File) => sum + file.numberOfPages, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#calculateStatusConfig(stats: DossierStats): ProgressBarConfigModel[] {
|
#calculateStatusConfig(stats: DossierStats, files: File[]): ProgressBarConfigModel[] {
|
||||||
|
const numberOfTimeoutFiles = files.filter(file => file.errorCode === FileErrorCodes.RULES_EXECUTION_TIMEOUT).length;
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: ProcessingTypes.pending,
|
id: ProcessingTypes.pending,
|
||||||
@ -161,6 +168,13 @@ export class DossierDetailsComponent extends ContextComponent<DossierDetailsCont
|
|||||||
count: stats.processingStats.pending,
|
count: stats.processingStats.pending,
|
||||||
icon: 'red:reanalyse',
|
icon: 'red:reanalyse',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: PendingTypes.timeout,
|
||||||
|
label: _('processing-status.pending-timeout'),
|
||||||
|
total: stats.numberOfFiles,
|
||||||
|
count: numberOfTimeoutFiles,
|
||||||
|
icon: 'red:reanalyse',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: ProcessingTypes.ocr,
|
id: ProcessingTypes.ocr,
|
||||||
label: _('processing-status.ocr'),
|
label: _('processing-status.ocr'),
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<iqser-page-header
|
<iqser-page-header
|
||||||
(closeAction)="router.navigate([dossier.dossiersListRouterLink])"
|
(closeAction)="router.navigate([dossier().dossiersListRouterLink])"
|
||||||
[actionConfigs]="actionConfigs"
|
[actionConfigs]="actionConfigs()"
|
||||||
[helpModeKey]="'document'"
|
[helpModeKey]="'document'"
|
||||||
[showCloseButton]="true"
|
[showCloseButton]="true"
|
||||||
[viewModeSelection]="viewModeSelection"
|
[viewModeSelection]="viewModeSelection"
|
||||||
@ -10,36 +10,44 @@
|
|||||||
[attr.help-mode-key]="isDocumine ? 'dossier_download_dossier' : 'download_dossier_in_dossier'"
|
[attr.help-mode-key]="isDocumine ? 'dossier_download_dossier' : 'download_dossier_in_dossier'"
|
||||||
[buttonId]="'download-files-btn'"
|
[buttonId]="'download-files-btn'"
|
||||||
[disabled]="downloadFilesDisabled$ | async"
|
[disabled]="downloadFilesDisabled$ | async"
|
||||||
[dossier]="dossier"
|
[dossier]="dossier()"
|
||||||
[files]="entitiesService.all$ | async"
|
[files]="entitiesService.all$ | async"
|
||||||
|
[iqserDisableStopPropagation]="shouldDisableStopPropagation()"
|
||||||
|
[stopMenuImmediatePropagation]="shouldDisableStopPropagation()"
|
||||||
dossierDownload
|
dossierDownload
|
||||||
></redaction-file-download-btn>
|
></redaction-file-download-btn>
|
||||||
|
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="downloadDossierAsCSV()"
|
(action)="downloadDossierAsCSV()"
|
||||||
*ngIf="permissionsService.canDownloadCsvReport(dossier)"
|
*ngIf="permissionsService.canDownloadCsvReport(dossier())"
|
||||||
[attr.help-mode-key]="'download_csv'"
|
[attr.help-mode-key]="'download_csv'"
|
||||||
[disabled]="listingService.areSomeSelected$ | async"
|
[disabled]="listingService.areSomeSelected$ | async"
|
||||||
[icon]="'iqser:csv'"
|
[icon]="'iqser:csv'"
|
||||||
|
[iqserDisableStopPropagation]="shouldDisableStopPropagation()"
|
||||||
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
|
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
|
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="reanalyseDossier()"
|
(action)="reanalyseDossier()"
|
||||||
*ngIf="permissionsService.displayReanalyseBtn(dossier)"
|
*ngIf="permissionsService.displayReanalyseBtn(dossier())"
|
||||||
[disabled]="listingService.areSomeSelected$ | async"
|
[disabled]="(listingService.areSomeSelected$ | async) || areRulesLocked()"
|
||||||
[icon]="'iqser:refresh'"
|
[icon]="'iqser:refresh'"
|
||||||
|
[iqserDisableStopPropagation]="shouldDisableStopPropagation()"
|
||||||
[tooltipClass]="'small warn'"
|
[tooltipClass]="'small warn'"
|
||||||
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
|
[tooltip]="
|
||||||
|
(areRulesLocked() ? 'dossier-listing.rules.timeoutError' : 'dossier-overview.new-rule.toast.actions.reanalyse-all')
|
||||||
|
| translate
|
||||||
|
"
|
||||||
[type]="circleButtonTypes.warn"
|
[type]="circleButtonTypes.warn"
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
|
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="upload.emit()"
|
(action)="upload.emit()"
|
||||||
*ngIf="permissionsService.canUploadFiles(dossier)"
|
*ngIf="permissionsService.canUploadFiles(dossier())"
|
||||||
[attr.help-mode-key]="'upload_document'"
|
[attr.help-mode-key]="'upload_document'"
|
||||||
[buttonId]="'upload-document-btn'"
|
[buttonId]="'upload-document-btn'"
|
||||||
[icon]="'iqser:upload'"
|
[icon]="'iqser:upload'"
|
||||||
|
[iqserDisableStopPropagation]="shouldDisableStopPropagation()"
|
||||||
[tooltip]="'dossier-overview.header-actions.upload-document' | translate"
|
[tooltip]="'dossier-overview.header-actions.upload-document' | translate"
|
||||||
[type]="circleButtonTypes.primary"
|
[type]="circleButtonTypes.primary"
|
||||||
class="ml-14"
|
class="ml-14"
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, computed, EventEmitter, input, OnInit, Output } from '@angular/core';
|
||||||
import {
|
import {
|
||||||
ActionConfig,
|
|
||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
CircleButtonTypes,
|
CircleButtonTypes,
|
||||||
DisableStopPropagationDirective,
|
DisableStopPropagationDirective,
|
||||||
@ -24,13 +23,14 @@ import { PrimaryFileAttributeService } from '@services/primary-file-attribute.se
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { Roles } from '@users/roles';
|
import { Roles } from '@users/roles';
|
||||||
import { SortingService } from '@iqser/common-ui/lib/sorting';
|
import { SortingService } from '@iqser/common-ui/lib/sorting';
|
||||||
import { List, some } from '@iqser/common-ui/lib/utils';
|
import { some } from '@iqser/common-ui/lib/utils';
|
||||||
import { ComponentLogService } from '@services/files/component-log.service';
|
|
||||||
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
|
|
||||||
import { AsyncPipe, NgIf } from '@angular/common';
|
import { AsyncPipe, NgIf } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { FileDownloadBtnComponent } from '@shared/components/buttons/file-download-btn/file-download-btn.component';
|
import { FileDownloadBtnComponent } from '@shared/components/buttons/file-download-btn/file-download-btn.component';
|
||||||
import { ViewModeSelectionComponent } from '../view-mode-selection/view-mode-selection.component';
|
import { ViewModeSelectionComponent } from '../view-mode-selection/view-mode-selection.component';
|
||||||
|
import { toSignal } from '@angular/core/rxjs-interop';
|
||||||
|
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||||
|
import { RulesService } from '../../../admin/services/rules.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-dossier-overview-screen-header [dossier] [upload]',
|
selector: 'redaction-dossier-overview-screen-header [dossier] [upload]',
|
||||||
@ -39,27 +39,30 @@ import { ViewModeSelectionComponent } from '../view-mode-selection/view-mode-sel
|
|||||||
imports: [
|
imports: [
|
||||||
IqserListingModule,
|
IqserListingModule,
|
||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
MatMenuTrigger,
|
|
||||||
IqserAllowDirective,
|
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
FileDownloadBtnComponent,
|
FileDownloadBtnComponent,
|
||||||
NgIf,
|
NgIf,
|
||||||
ViewModeSelectionComponent,
|
ViewModeSelectionComponent,
|
||||||
DisableStopPropagationDirective,
|
DisableStopPropagationDirective,
|
||||||
MatMenu,
|
IqserAllowDirective,
|
||||||
MatMenuItem,
|
|
||||||
],
|
],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class DossierOverviewScreenHeaderComponent implements OnInit {
|
export class DossierOverviewScreenHeaderComponent {
|
||||||
@Input() dossier: Dossier;
|
readonly dossier = input<Dossier>();
|
||||||
@Output() readonly upload = new EventEmitter<void>();
|
@Output() readonly upload = new EventEmitter<void>();
|
||||||
readonly circleButtonTypes = CircleButtonTypes;
|
readonly circleButtonTypes = CircleButtonTypes;
|
||||||
readonly roles = Roles;
|
readonly roles = Roles;
|
||||||
actionConfigs: List<ActionConfig>;
|
|
||||||
readonly downloadFilesDisabled$: Observable<boolean>;
|
readonly downloadFilesDisabled$: Observable<boolean>;
|
||||||
readonly downloadComponentLogsDisabled$: Observable<boolean>;
|
readonly downloadComponentLogsDisabled$: Observable<boolean>;
|
||||||
readonly isDocumine = getConfig().IS_DOCUMINE;
|
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||||
|
readonly areRulesLocked = computed(() => {
|
||||||
|
return this._rulesService.currentTemplateRules().timeoutDetected;
|
||||||
|
});
|
||||||
|
readonly areSomeSelected = toSignal(this.listingService.areSomeSelected$);
|
||||||
|
readonly actionConfigs = computed(() => this.configService.actionConfig(this.dossier().id, this.areSomeSelected()));
|
||||||
|
readonly shouldDisableStopPropagation = computed(() => this._fileAttributesService.isEditingFileAttribute());
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _toaster: Toaster,
|
private readonly _toaster: Toaster,
|
||||||
@ -73,6 +76,8 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
|
|||||||
private readonly _reanalysisService: ReanalysisService,
|
private readonly _reanalysisService: ReanalysisService,
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _primaryFileAttributeService: PrimaryFileAttributeService,
|
private readonly _primaryFileAttributeService: PrimaryFileAttributeService,
|
||||||
|
private readonly _rulesService: RulesService,
|
||||||
|
private readonly _fileAttributesService: FileAttributesService,
|
||||||
) {
|
) {
|
||||||
const someNotProcessed$ = this.entitiesService.all$.pipe(some(file => !file.lastProcessed));
|
const someNotProcessed$ = this.entitiesService.all$.pipe(some(file => !file.lastProcessed));
|
||||||
this.downloadFilesDisabled$ = combineLatest([this.listingService.areSomeSelected$, someNotProcessed$]).pipe(
|
this.downloadFilesDisabled$ = combineLatest([this.listingService.areSomeSelected$, someNotProcessed$]).pipe(
|
||||||
@ -83,14 +88,16 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.actionConfigs = this.configService.actionConfig(this.dossier.id, this.listingService.areSomeSelected$);
|
|
||||||
}
|
|
||||||
|
|
||||||
async reanalyseDossier() {
|
async reanalyseDossier() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
|
const rules = await firstValueFrom(this._rulesService.getFor(this.dossier().dossierTemplateId));
|
||||||
|
if (rules.timeoutDetected) {
|
||||||
|
this._toaster.error(_('dossier-listing.rules.timeoutError'));
|
||||||
|
this._loadingService.stop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await this._reanalysisService.reanalyzeDossier(this.dossier, true);
|
await this._reanalysisService.reanalyzeDossier(this.dossier(), true);
|
||||||
this._toaster.success(_('dossier-overview.reanalyse-dossier.success'));
|
this._toaster.success(_('dossier-overview.reanalyse-dossier.success'));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this._toaster.error(_('dossier-overview.reanalyse-dossier.error'));
|
this._toaster.error(_('dossier-overview.reanalyse-dossier.error'));
|
||||||
@ -101,12 +108,12 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
|
|||||||
async downloadDossierAsCSV() {
|
async downloadDossierAsCSV() {
|
||||||
const displayedEntities = await firstValueFrom(this.listingService.displayed$);
|
const displayedEntities = await firstValueFrom(this.listingService.displayed$);
|
||||||
const entities = this.sortingService.defaultSort(displayedEntities);
|
const entities = this.sortingService.defaultSort(displayedEntities);
|
||||||
const fileName = this.dossier.dossierName + '.export.csv';
|
const fileName = this.dossier().dossierName + '.export.csv';
|
||||||
const mapper = (file?: File) => ({
|
const mapper = (file?: File) => ({
|
||||||
...file,
|
...file,
|
||||||
hasAnnotations: file.hasRedactions,
|
hasAnnotations: file.hasRedactions,
|
||||||
assignee: this._userService.getName(file.assignee) || '-',
|
assignee: this._userService.getName(file.assignee) || '-',
|
||||||
primaryAttribute: this._primaryFileAttributeService.getPrimaryFileAttributeValue(file, this.dossier.dossierTemplateId),
|
primaryAttribute: this._primaryFileAttributeService.getPrimaryFileAttributeValue(file, this.dossier().dossierTemplateId),
|
||||||
});
|
});
|
||||||
const documineOnlyFields = ['hasAnnotations'];
|
const documineOnlyFields = ['hasAnnotations'];
|
||||||
const redactionOnlyFields = ['hasHints', 'hasImages', 'hasUpdates', 'hasRedactions'];
|
const redactionOnlyFields = ['hasHints', 'hasImages', 'hasUpdates', 'hasRedactions'];
|
||||||
|
|||||||
@ -23,11 +23,13 @@
|
|||||||
<div class="cell" *ngIf="!isDocumine">
|
<div class="cell" *ngIf="!isDocumine">
|
||||||
<redaction-file-workload *ngIf="!file.excluded" [file]="file"></redaction-file-workload>
|
<redaction-file-workload *ngIf="!file.excluded" [file]="file"></redaction-file-workload>
|
||||||
</div>
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<div class="user-column cell">
|
<div class="user-column cell">
|
||||||
<iqser-initials-avatar [user]="file.assignee" [withName]="true"></iqser-initials-avatar>
|
<iqser-initials-avatar [user]="file.assignee" [withName]="true"></iqser-initials-avatar>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!file.isError">
|
||||||
<div class="cell">
|
<div class="cell">
|
||||||
<div class="small-label stats-subtitle">
|
<div class="small-label stats-subtitle">
|
||||||
<div>
|
<div>
|
||||||
@ -39,7 +41,12 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div [class.extend-cols]="file.isError" class="status-container cell">
|
<div [class.extend-cols]="file.isError" class="status-container cell">
|
||||||
<div *ngIf="file.isError" class="small-label error" translate="dossier-overview.file-listing.file-entry.file-error"></div>
|
<div
|
||||||
|
*ngIf="file.isError"
|
||||||
|
class="small-label error"
|
||||||
|
translate="dossier-overview.file-listing.file-entry.file-error"
|
||||||
|
[translateParams]="{ errorCode: file.errorCode }"
|
||||||
|
></div>
|
||||||
|
|
||||||
<div *ngIf="file.isUnprocessed" class="small-label" translate="dossier-overview.file-listing.file-entry.file-pending"></div>
|
<div *ngIf="file.isUnprocessed" class="small-label" translate="dossier-overview.file-listing.file-entry.file-pending"></div>
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.extend-cols {
|
.extend-cols {
|
||||||
grid-column-end: span 3;
|
grid-column-end: span 2;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,9 @@
|
|||||||
<redaction-file-attribute [dossier]="dossier" [fileAttribute]="config" [file]="file"></redaction-file-attribute>
|
<redaction-file-attribute [dossier]="dossier" [fileAttribute]="config" [file]="file"></redaction-file-attribute>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<redaction-file-workload [file]="file"></redaction-file-workload>
|
@if (!isDocumine) {
|
||||||
|
<redaction-file-workload [file]="file"></redaction-file-workload>
|
||||||
|
}
|
||||||
|
|
||||||
<div class="file-actions overflow-visible">
|
<div class="file-actions overflow-visible">
|
||||||
<redaction-processing-indicator [file]="file" class="mr-8"></redaction-processing-indicator>
|
<redaction-processing-indicator [file]="file" class="mr-8"></redaction-processing-indicator>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ChangeDetectorRef, Component, computed, ElementRef, Input, OnInit, Optional, ViewChild } from '@angular/core';
|
import { ChangeDetectorRef, Component, ElementRef, Input, OnInit, Optional, ViewChild } from '@angular/core';
|
||||||
import { DisableStopPropagationDirective, HelpModeService } from '@iqser/common-ui';
|
import { DisableStopPropagationDirective, getConfig, HelpModeService } from '@iqser/common-ui';
|
||||||
import { Debounce, trackByFactory } from '@iqser/common-ui/lib/utils';
|
import { Debounce, trackByFactory } from '@iqser/common-ui/lib/utils';
|
||||||
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
|
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
|
||||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||||
@ -37,6 +37,7 @@ import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
|
|||||||
export class WorkflowItemComponent implements OnInit {
|
export class WorkflowItemComponent implements OnInit {
|
||||||
@ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef;
|
@ViewChild('actionsWrapper', { static: true }) private _actionsWrapper: ElementRef;
|
||||||
width: number;
|
width: number;
|
||||||
|
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||||
readonly trackBy = trackByFactory();
|
readonly trackBy = trackByFactory();
|
||||||
@Input({ required: true }) file: File;
|
@Input({ required: true }) file: File;
|
||||||
@Input({ required: true }) dossier: Dossier;
|
@Input({ required: true }) dossier: Dossier;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ import {
|
|||||||
FileAttributeConfigType,
|
FileAttributeConfigType,
|
||||||
FileAttributeConfigTypes,
|
FileAttributeConfigTypes,
|
||||||
IFileAttributeConfig,
|
IFileAttributeConfig,
|
||||||
|
PendingType,
|
||||||
ProcessingType,
|
ProcessingType,
|
||||||
StatusSorter,
|
StatusSorter,
|
||||||
User,
|
User,
|
||||||
@ -46,6 +47,7 @@ import { annotationFilterChecker, RedactionFilterSorter, sortArray, sortByName }
|
|||||||
import { EditDossierDialogComponent } from '../shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
import { EditDossierDialogComponent } from '../shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
||||||
import { DossiersDialogService } from '../shared-dossiers/services/dossiers-dialog.service';
|
import { DossiersDialogService } from '../shared-dossiers/services/dossiers-dialog.service';
|
||||||
import { BulkActionsService } from './services/bulk-actions.service';
|
import { BulkActionsService } from './services/bulk-actions.service';
|
||||||
|
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ConfigService {
|
export class ConfigService {
|
||||||
@ -67,6 +69,7 @@ export class ConfigService {
|
|||||||
private readonly _userPreferenceService: UserPreferenceService,
|
private readonly _userPreferenceService: UserPreferenceService,
|
||||||
private readonly _dossiersService: DossiersService,
|
private readonly _dossiersService: DossiersService,
|
||||||
private readonly _iqserPermissionsService: IqserPermissionsService,
|
private readonly _iqserPermissionsService: IqserPermissionsService,
|
||||||
|
private readonly _fileAttributesService: FileAttributesService,
|
||||||
) {
|
) {
|
||||||
const previousListingMode = this._userPreferenceService.getFilesListingMode();
|
const previousListingMode = this._userPreferenceService.getFilesListingMode();
|
||||||
const listingMode = previousListingMode ? previousListingMode : ListingModes.table;
|
const listingMode = previousListingMode ? previousListingMode : ListingModes.table;
|
||||||
@ -112,7 +115,7 @@ export class ConfigService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
actionConfig(dossierId: string, disabled$: Observable<boolean>): List<ActionConfig> {
|
actionConfig(dossierId: string, disabled: boolean): List<ActionConfig> {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
id: 'editDossier',
|
id: 'editDossier',
|
||||||
@ -121,7 +124,8 @@ export class ConfigService {
|
|||||||
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),
|
||||||
helpModeKey: 'edit_dossier',
|
helpModeKey: 'edit_dossier',
|
||||||
disabled$,
|
disableStopPropagation: this._fileAttributesService.isEditingFileAttribute(),
|
||||||
|
disabled,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -184,6 +188,7 @@ export class ConfigService {
|
|||||||
const allDistinctPeople = new Set<string>();
|
const allDistinctPeople = new Set<string>();
|
||||||
const allDistinctNeedsWork = new Set<string>();
|
const allDistinctNeedsWork = new Set<string>();
|
||||||
const allDistinctProcessingTypes = new Set<ProcessingType>();
|
const allDistinctProcessingTypes = new Set<ProcessingType>();
|
||||||
|
const allDistinctPendingTypes = new Set<PendingType>();
|
||||||
|
|
||||||
const dynamicFilters = new Map<string, { type: FileAttributeConfigType; filterValue: Set<string> }>();
|
const dynamicFilters = new Map<string, { type: FileAttributeConfigType; filterValue: Set<string> }>();
|
||||||
|
|
||||||
@ -216,6 +221,7 @@ export class ConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
allDistinctProcessingTypes.add(file.processingType);
|
allDistinctProcessingTypes.add(file.processingType);
|
||||||
|
allDistinctPendingTypes.add(file.pendingType);
|
||||||
|
|
||||||
// extract values for dynamic filters
|
// extract values for dynamic filters
|
||||||
fileAttributeConfigs.forEach(config => {
|
fileAttributeConfigs.forEach(config => {
|
||||||
@ -317,6 +323,14 @@ export class ConfigService {
|
|||||||
hide: true,
|
hide: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const pendingTypesFilters = [...allDistinctPendingTypes].map(item => new NestedFilter({ id: item, label: item }));
|
||||||
|
filterGroups.push({
|
||||||
|
slug: 'pendingTypeFilters',
|
||||||
|
filters: pendingTypesFilters,
|
||||||
|
checker: (file: File, filter: INestedFilter) => file.pendingType === filter.id,
|
||||||
|
hide: true,
|
||||||
|
});
|
||||||
|
|
||||||
dynamicFilters.forEach((value: { filterValue: Set<string>; type: FileAttributeConfigType }, filterKey: string) => {
|
dynamicFilters.forEach((value: { filterValue: Set<string>; type: FileAttributeConfigType }, filterKey: string) => {
|
||||||
const id = filterKey.split(':')[0];
|
const id = filterKey.split(':')[0];
|
||||||
const key = filterKey.split(':')[1];
|
const key = filterKey.split(':')[1];
|
||||||
|
|||||||
@ -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]))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 6px;
|
top: 6px;
|
||||||
right: 19px;
|
right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover {
|
.popover {
|
||||||
|
|||||||
@ -96,7 +96,7 @@ export class AnnotationDetailsComponent implements OnChanges {
|
|||||||
icon: 'red:rule',
|
icon: 'red:rule',
|
||||||
description: _('annotation-engines.rule'),
|
description: _('annotation-engines.rule'),
|
||||||
show: isBasedOn(annotation, LogEntryEngines.RULE),
|
show: isBasedOn(annotation, LogEntryEngines.RULE),
|
||||||
translateParams: { rule: annotation.legalBasisValue || '' },
|
translateParams: { rule: annotation.legalBasisValue === 'n-a' ? '' : annotation.legalBasisValue || '' },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
icon: 'red:import_redactions',
|
icon: 'red:import_redactions',
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import { Component, computed, ElementRef, EventEmitter, Input, Output } from '@angular/core';
|
import { Component, computed, ElementRef, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { getConfig, HasScrollbarDirective } from '@iqser/common-ui';
|
import { getConfig, HasScrollbarDirective } from '@iqser/common-ui';
|
||||||
import { FilterService } from '@iqser/common-ui/lib/filtering';
|
import { FilterService } from '@iqser/common-ui/lib/filtering';
|
||||||
import { IqserEventTarget } from '@iqser/common-ui/lib/utils';
|
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { ListItem } from '@models/file/list-item';
|
import { ListItem } from '@models/file/list-item';
|
||||||
import { EarmarkGroup } from '@red/domain';
|
import { EarmarkGroup } from '@red/domain';
|
||||||
@ -15,6 +14,7 @@ import { NgForOf, NgIf } from '@angular/common';
|
|||||||
import { HighlightsSeparatorComponent } from '../highlights-separator/highlights-separator.component';
|
import { HighlightsSeparatorComponent } from '../highlights-separator/highlights-separator.component';
|
||||||
import { AnnotationWrapperComponent } from '../annotation-wrapper/annotation-wrapper.component';
|
import { AnnotationWrapperComponent } from '../annotation-wrapper/annotation-wrapper.component';
|
||||||
import { AnnotationReferencesListComponent } from '../annotation-references-list/annotation-references-list.component';
|
import { AnnotationReferencesListComponent } from '../annotation-references-list/annotation-references-list.component';
|
||||||
|
import { isTargetInput } from '@utils/functions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-annotations-list',
|
selector: 'redaction-annotations-list',
|
||||||
@ -52,7 +52,7 @@ export class AnnotationsListComponent extends HasScrollbarDirective {
|
|||||||
console.log('Selected Annotation:', annotation);
|
console.log('Selected Annotation:', annotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (($event?.target as IqserEventTarget)?.localName === 'input') {
|
if (isTargetInput($event)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,13 +18,10 @@
|
|||||||
|
|
||||||
.right-content {
|
.right-content {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
height: calc(100% - 71px);
|
||||||
|
|
||||||
@include common-mixins.scroll-bar;
|
@include common-mixins.scroll-bar;
|
||||||
overflow: hidden;
|
overflow-y: auto;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.has-scrollbar .section {
|
&.has-scrollbar .section {
|
||||||
padding-right: 13px;
|
padding-right: 13px;
|
||||||
|
|||||||
@ -3,12 +3,16 @@
|
|||||||
@if (!editing) {
|
@if (!editing) {
|
||||||
<div class="value">
|
<div class="value">
|
||||||
<div class="text">
|
<div class="text">
|
||||||
@for (componentValue of entry.componentValues; track componentValue) {
|
@for (componentValue of currentEntry().componentValues; track componentValue) {
|
||||||
<span [innerHTML]="transformNewLines(componentValue.value ?? componentValue.originalValue)"></span>
|
<span
|
||||||
|
[innerHTML]="transformNewLines(componentValue.value ?? componentValue.originalValue) | replaceNbsp"
|
||||||
|
[matTooltip]="componentValue.valueDescription"
|
||||||
|
[matTooltipPositionAtOrigin]="true"
|
||||||
|
></span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
@if (canEdit) {
|
@if (canEdit()) {
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="edit()"
|
(action)="edit()"
|
||||||
[tooltip]="'component-management.actions.edit' | translate"
|
[tooltip]="'component-management.actions.edit' | translate"
|
||||||
@ -16,7 +20,7 @@
|
|||||||
[class.help-mode]="helpModeService.isHelpModeActive()"
|
[class.help-mode]="helpModeService.isHelpModeActive()"
|
||||||
icon="iqser:edit"
|
icon="iqser:edit"
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
@if (hasUpdatedValues) {
|
@if (hasUpdatedValues()) {
|
||||||
<div class="changes-dot"></div>
|
<div class="changes-dot"></div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,23 +28,23 @@
|
|||||||
</div>
|
</div>
|
||||||
} @else {
|
} @else {
|
||||||
<div (cdkDropListDropped)="drop($event)" cdkDropList>
|
<div (cdkDropListDropped)="drop($event)" cdkDropList>
|
||||||
@for (value of entry.componentValues; track value) {
|
@for (value of currentEntry().componentValues; track value) {
|
||||||
<div cdkDrag class="editing-value">
|
<div cdkDrag class="editing-value">
|
||||||
<mat-icon
|
<mat-icon
|
||||||
[class.hidden-button]="entry.componentValues.length === 1"
|
[class.hidden-button]="currentEntry().componentValues.length === 1"
|
||||||
[attr.help-mode-key]="'change_component_order'"
|
[attr.help-mode-key]="currentEntry().componentValues.length > 1 ? 'change_component_order' : null"
|
||||||
cdkDragHandle
|
cdkDragHandle
|
||||||
class="draggable"
|
class="draggable"
|
||||||
svgIcon="red:draggable-dots"
|
svgIcon="red:draggable-dots"
|
||||||
></mat-icon>
|
></mat-icon>
|
||||||
<div [attr.help-mode-key]="'edit_component'" class="iqser-input-group w-full">
|
<div [attr.help-mode-key]="'editor_edit_component'" class="iqser-input-group w-full">
|
||||||
<textarea [id]="'value-input-' + $index" [(ngModel)]="value.value" rows="1" type="text"></textarea>
|
<textarea [id]="'value-input-' + $index" [(ngModel)]="value.value" rows="1" type="text"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="removeValue($index)"
|
(action)="removeValue($index)"
|
||||||
[tooltip]="'component-management.actions.delete' | translate"
|
[tooltip]="'component-management.actions.delete' | translate"
|
||||||
[class.hidden-button]="entry.componentValues.length === 1"
|
[class.hidden-button]="currentEntry().componentValues.length === 1"
|
||||||
[attr.help-mode-key]="'remove_component_value'"
|
[attr.help-mode-key]="currentEntry().componentValues.length > 1 ? 'remove_component_value' : null"
|
||||||
class="remove-value"
|
class="remove-value"
|
||||||
icon="iqser:trash"
|
icon="iqser:trash"
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
@ -54,9 +58,9 @@
|
|||||||
[label]="'component-management.actions.save' | translate"
|
[label]="'component-management.actions.save' | translate"
|
||||||
[type]="iconButtonTypes.primary"
|
[type]="iconButtonTypes.primary"
|
||||||
></iqser-icon-button>
|
></iqser-icon-button>
|
||||||
<div (click)="deselect($event)" class="all-caps-label cancel" translate="component-management.actions.cancel"></div>
|
<div (click)="cancel($event)" class="all-caps-label cancel" translate="component-management.actions.cancel"></div>
|
||||||
<div class="flex right">
|
<div class="flex right">
|
||||||
@if (hasUpdatedValues && canEdit) {
|
@if (hasUpdatedValues() && canEdit()) {
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="undo()"
|
(action)="undo()"
|
||||||
[tooltip]="'component-management.actions.undo' | translate"
|
[tooltip]="'component-management.actions.undo' | translate"
|
||||||
|
|||||||
@ -2,12 +2,13 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
padding: 10px 0 10px 0;
|
padding: 10px 0 10px 0;
|
||||||
margin-left: 26px;
|
margin-left: 14px;
|
||||||
margin-right: 26px;
|
margin-right: 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
.component {
|
.component {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
@ -72,13 +73,13 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
margin-right: 26px;
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.component {
|
.component {
|
||||||
margin-left: 26px;
|
margin-left: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
@ -94,7 +95,7 @@
|
|||||||
border-left: 4px solid var(--iqser-primary);
|
border-left: 4px solid var(--iqser-primary);
|
||||||
|
|
||||||
.component {
|
.component {
|
||||||
margin-left: 22px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow-right {
|
.arrow-right {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
import { AsyncPipe, KeyValuePipe, NgClass, NgForOf, NgIf } from '@angular/common';
|
import { AsyncPipe, KeyValuePipe, NgClass, NgForOf, NgIf } from '@angular/common';
|
||||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
import { Component, computed, input, OnInit, output, signal, WritableSignal } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { MatIcon } from '@angular/material/icon';
|
import { MatIcon } from '@angular/material/icon';
|
||||||
import { CircleButtonComponent, HelpModeService, IconButtonComponent, IconButtonTypes, IqserDialog } from '@iqser/common-ui';
|
import { CircleButtonComponent, HelpModeService, IconButtonComponent, IconButtonTypes, IqserDialog } from '@iqser/common-ui';
|
||||||
@ -8,6 +8,9 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
import { IComponentLogEntry, IComponentValue } from '@red/domain';
|
import { IComponentLogEntry, IComponentValue } from '@red/domain';
|
||||||
import { RevertValueDialogComponent } from '../../dialogs/docu-mine/revert-value-dialog/revert-value-dialog.component';
|
import { RevertValueDialogComponent } from '../../dialogs/docu-mine/revert-value-dialog/revert-value-dialog.component';
|
||||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||||
|
import { escapeHtml } from '@common-ui/utils';
|
||||||
|
import { ReplaceNbspPipe } from '@common-ui/pipes/replace-nbsp.pipe';
|
||||||
|
import { MatTooltip } from '@angular/material/tooltip';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-editable-structured-component-value [entry] [canEdit]',
|
selector: 'redaction-editable-structured-component-value [entry] [canEdit]',
|
||||||
@ -28,20 +31,24 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi
|
|||||||
CdkDragHandle,
|
CdkDragHandle,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
AsyncPipe,
|
AsyncPipe,
|
||||||
|
ReplaceNbspPipe,
|
||||||
|
MatTooltip,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class EditableStructuredComponentValueComponent implements OnInit {
|
export class EditableStructuredComponentValueComponent implements OnInit {
|
||||||
|
readonly entry = input<IComponentLogEntry>();
|
||||||
|
currentEntry: WritableSignal<IComponentLogEntry>;
|
||||||
|
readonly canEdit = input<boolean>();
|
||||||
|
readonly deselectLast = output();
|
||||||
|
readonly overrideValue = output<IComponentLogEntry>();
|
||||||
|
readonly revertOverride = output<string>();
|
||||||
|
hasUpdatedValues = computed(() => this.currentEntry().overridden);
|
||||||
|
selected = false;
|
||||||
|
valueBeforeCurrentEdit: IComponentValue[];
|
||||||
protected entryLabel: string;
|
protected entryLabel: string;
|
||||||
protected editing = false;
|
protected editing = false;
|
||||||
protected hasUpdatedValues = false;
|
|
||||||
protected initialEntry: IComponentLogEntry;
|
protected initialEntry: IComponentLogEntry;
|
||||||
protected readonly iconButtonTypes = IconButtonTypes;
|
protected readonly iconButtonTypes = IconButtonTypes;
|
||||||
@Input() entry: IComponentLogEntry;
|
|
||||||
@Input() canEdit: boolean;
|
|
||||||
@Output() readonly deselectLast = new EventEmitter();
|
|
||||||
@Output() readonly overrideValue = new EventEmitter<IComponentLogEntry>();
|
|
||||||
@Output() readonly revertOverride = new EventEmitter<string>();
|
|
||||||
selected = false;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
readonly helpModeService: HelpModeService,
|
readonly helpModeService: HelpModeService,
|
||||||
@ -50,38 +57,26 @@ export class EditableStructuredComponentValueComponent implements OnInit {
|
|||||||
) {}
|
) {}
|
||||||
|
|
||||||
get disabled() {
|
get disabled() {
|
||||||
for (let i = 0; i < this.entry.componentValues.length; i++) {
|
for (let i = 0; i < this.currentEntry().componentValues.length; i++) {
|
||||||
if (this.entry.componentValues[i].value !== this.initialEntry.componentValues[i]?.value) {
|
if (this.currentEntry().componentValues[i].value !== this.initialEntry.componentValues[i]?.value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.entry.componentValues.length === this.initialEntry.componentValues.length;
|
return this.currentEntry().componentValues.length === this.initialEntry.componentValues.length;
|
||||||
}
|
|
||||||
|
|
||||||
get #hasUpdatedValues() {
|
|
||||||
for (const value of this.entry.componentValues) {
|
|
||||||
if (value.originalValue === null && value.value === '') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (value.originalValue !== value.value) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get #initialEntry() {
|
get #initialEntry() {
|
||||||
return JSON.parse(JSON.stringify(this.entry));
|
return JSON.parse(JSON.stringify(this.entry()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.currentEntry = signal(this.entry());
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
reset() {
|
reset() {
|
||||||
this.initialEntry = this.#initialEntry;
|
this.initialEntry = this.#initialEntry;
|
||||||
this.hasUpdatedValues = this.#hasUpdatedValues;
|
this.entryLabel = this.parseName(this.currentEntry().name);
|
||||||
this.entryLabel = this.parseName(this.entry.name);
|
|
||||||
this.deselect();
|
this.deselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,11 +88,12 @@ export class EditableStructuredComponentValueComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
this.deselectLast.emit();
|
this.deselectLast.emit();
|
||||||
this.selected = true;
|
this.selected = true;
|
||||||
this._state.componentReferenceIds = this.#getUniqueReferencesIds(this.entry.componentValues);
|
this._state.componentReferenceIds = this.#getUniqueReferencesIds(this.currentEntry().componentValues);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
edit() {
|
edit() {
|
||||||
|
this.valueBeforeCurrentEdit = JSON.parse(JSON.stringify([...this.currentEntry().componentValues]));
|
||||||
this.deselectLast.emit();
|
this.deselectLast.emit();
|
||||||
this.selected = true;
|
this.selected = true;
|
||||||
this.editing = true;
|
this.editing = true;
|
||||||
@ -111,37 +107,48 @@ export class EditableStructuredComponentValueComponent implements OnInit {
|
|||||||
this._state.componentReferenceIds = null;
|
this._state.componentReferenceIds = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancel($event?: MouseEvent) {
|
||||||
|
this.currentEntry.update(value => ({ ...value, componentValues: this.valueBeforeCurrentEdit }));
|
||||||
|
this.deselect($event);
|
||||||
|
}
|
||||||
|
|
||||||
removeValue(index: number) {
|
removeValue(index: number) {
|
||||||
this.entry.componentValues.splice(index, 1);
|
this.currentEntry.update(value => ({ ...value, componentValues: value.componentValues.filter((_, i) => i !== index) }));
|
||||||
}
|
}
|
||||||
|
|
||||||
save() {
|
save() {
|
||||||
this.entry.overridden = true;
|
this.currentEntry.update(value => ({ ...value, overridden: true }));
|
||||||
this.overrideValue.emit(this.entry);
|
this.overrideValue.emit(this.currentEntry());
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
async undo() {
|
async undo() {
|
||||||
const dialog = this._iqserDialog.openDefault(RevertValueDialogComponent, { data: { entry: this.entry }, width: '800px' });
|
const dialog = this._iqserDialog.openDefault(RevertValueDialogComponent, { data: { entry: this.currentEntry() }, width: '800px' });
|
||||||
const result = await dialog.result();
|
const result = await dialog.result();
|
||||||
if (result) {
|
if (result) {
|
||||||
this.revertOverride.emit(this.entry.name);
|
this.revertOverride.emit(this.currentEntry().name);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add() {
|
add() {
|
||||||
this.entry.componentValues.push({
|
this.currentEntry.update(value => ({
|
||||||
componentRuleId: null,
|
...value,
|
||||||
entityReferences: [],
|
componentValues: [
|
||||||
originalValue: null,
|
...value.componentValues,
|
||||||
value: '',
|
{
|
||||||
valueDescription: '',
|
componentRuleId: null,
|
||||||
});
|
entityReferences: [],
|
||||||
|
originalValue: null,
|
||||||
|
value: '',
|
||||||
|
valueDescription: '',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
drop(event: CdkDragDrop<string>) {
|
drop(event: CdkDragDrop<string>) {
|
||||||
moveItemInArray(this.entry.componentValues, event.previousIndex, event.currentIndex);
|
moveItemInArray(this.currentEntry().componentValues, event.previousIndex, event.currentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseName(name: string) {
|
parseName(name: string) {
|
||||||
@ -149,7 +156,7 @@ export class EditableStructuredComponentValueComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
transformNewLines(value: string) {
|
transformNewLines(value: string) {
|
||||||
return value.replace(/\n/g, '<br>');
|
return escapeHtml(value).replace(/\n/g, '<br>');
|
||||||
}
|
}
|
||||||
|
|
||||||
#getUniqueReferencesIds(values: IComponentValue[]) {
|
#getUniqueReferencesIds(values: IComponentValue[]) {
|
||||||
@ -164,7 +171,7 @@ export class EditableStructuredComponentValueComponent implements OnInit {
|
|||||||
|
|
||||||
#updateTextAreaHeight() {
|
#updateTextAreaHeight() {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
for (let i = 0; i < this.entry.componentValues.length; i++) {
|
for (let i = 0; i < this.currentEntry().componentValues.length; i++) {
|
||||||
const textArea = document.getElementById(`value-input-${i}`);
|
const textArea = document.getElementById(`value-input-${i}`);
|
||||||
textArea.style.height = 'auto';
|
textArea.style.height = 'auto';
|
||||||
textArea.style.height = `${textArea.scrollHeight}px`;
|
textArea.style.height = `${textArea.scrollHeight}px`;
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import {
|
|||||||
Component,
|
Component,
|
||||||
computed,
|
computed,
|
||||||
ElementRef,
|
ElementRef,
|
||||||
HostListener,
|
|
||||||
Input,
|
Input,
|
||||||
NgZone,
|
NgZone,
|
||||||
OnDestroy,
|
OnDestroy,
|
||||||
@ -19,7 +18,6 @@ import {
|
|||||||
getConfig,
|
getConfig,
|
||||||
HelpModeService,
|
HelpModeService,
|
||||||
IqserAllowDirective,
|
IqserAllowDirective,
|
||||||
IqserDialog,
|
|
||||||
IqserPermissionsService,
|
IqserPermissionsService,
|
||||||
isIqserDevMode,
|
isIqserDevMode,
|
||||||
LoadingService,
|
LoadingService,
|
||||||
@ -51,6 +49,7 @@ import { ALL_HOTKEYS } from '../../utils/constants';
|
|||||||
import { AnnotationDrawService } from '../../../pdf-viewer/services/annotation-draw.service';
|
import { AnnotationDrawService } from '../../../pdf-viewer/services/annotation-draw.service';
|
||||||
import { FileManagementService } from '@services/files/file-management.service';
|
import { FileManagementService } from '@services/files/file-management.service';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { isTargetInput, isTargetTextArea } from '@utils/functions';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-file-header',
|
selector: 'redaction-file-header',
|
||||||
@ -105,6 +104,7 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD
|
|||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
document.documentElement.addEventListener('fullscreenchange', this.fullscreenListener);
|
document.documentElement.addEventListener('fullscreenchange', this.fullscreenListener);
|
||||||
|
this._pdf.instance.UI.iframeWindow.addEventListener('keyup', this.handleKeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
@ -116,10 +116,12 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD
|
|||||||
|
|
||||||
ngOnDetach() {
|
ngOnDetach() {
|
||||||
document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener);
|
document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener);
|
||||||
|
this._pdf.instance.UI.iframeWindow.removeEventListener('keyup', this.handleKeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener);
|
document.documentElement.removeEventListener('fullscreenchange', this.fullscreenListener);
|
||||||
|
this._pdf.instance.UI.iframeWindow.removeEventListener('keyup', this.handleKeyEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
async downloadOriginalFile({ cacheIdentifier, dossierId, fileId, filename }: File) {
|
async downloadOriginalFile({ cacheIdentifier, dossierId, fileId, filename }: File) {
|
||||||
@ -177,7 +179,7 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('document:keyup', ['$event'])
|
@Bind()
|
||||||
handleKeyEvent($event: KeyboardEvent) {
|
handleKeyEvent($event: KeyboardEvent) {
|
||||||
if (this._router.url.indexOf('/file/') < 0) {
|
if (this._router.url.indexOf('/file/') < 0) {
|
||||||
return;
|
return;
|
||||||
@ -208,19 +210,20 @@ export class FileHeaderComponent implements OnInit, AfterViewInit, OnDetach, OnD
|
|||||||
this._changeRef.markForCheck();
|
this._changeRef.markForCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($event.key === 'F5') {
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isTargetInput($event) || isTargetTextArea($event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!$event.ctrlKey && !$event.metaKey && ['f', 'F'].includes($event.key)) {
|
if (!$event.ctrlKey && !$event.metaKey && ['f', 'F'].includes($event.key)) {
|
||||||
// if you type in an input, don't toggle full-screen
|
|
||||||
if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.toggleFullScreen();
|
this.toggleFullScreen();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (['h', 'H'].includes($event.key)) {
|
if (['h', 'H'].includes($event.key)) {
|
||||||
if ($event.target instanceof HTMLInputElement || $event.target instanceof HTMLTextAreaElement) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this._ngZone.run(() => {
|
this._ngZone.run(() => {
|
||||||
window.focus();
|
window.focus();
|
||||||
this._helpModeService.activateHelpMode(false);
|
this._helpModeService.activateHelpMode(false);
|
||||||
|
|||||||
@ -43,7 +43,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
&.documine-width {
|
&.documine-width {
|
||||||
width: calc(var(--documine-workload-content-width));
|
width: calc(var(--documine-workload-content-width) - 55px);
|
||||||
border-right: 1px solid var(--iqser-separator);
|
border-right: 1px solid var(--iqser-separator);
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
@ -79,7 +79,7 @@
|
|||||||
.quick-navigation {
|
.quick-navigation {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
border-right: 1px solid var(--iqser-separator);
|
border-right: 1px solid var(--iqser-separator);
|
||||||
min-width: var(--qiuck-navigation-width);
|
min-width: var(--quick-navigation-width);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
@ -27,7 +27,7 @@ import {
|
|||||||
PreventDefaultDirective,
|
PreventDefaultDirective,
|
||||||
} from '@iqser/common-ui';
|
} from '@iqser/common-ui';
|
||||||
import { FilterService, INestedFilter, PopupFilterComponent } from '@iqser/common-ui/lib/filtering';
|
import { FilterService, INestedFilter, PopupFilterComponent } from '@iqser/common-ui/lib/filtering';
|
||||||
import { AutoUnsubscribe, Debounce, IqserEventTarget } from '@iqser/common-ui/lib/utils';
|
import { AutoUnsubscribe, Debounce } from '@iqser/common-ui/lib/utils';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { ListItem } from '@models/file/list-item';
|
import { ListItem } from '@models/file/list-item';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
@ -36,7 +36,7 @@ import { workloadTranslations } from '@translations/workload-translations';
|
|||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
import { getLocalStorageDataByFileId } from '@utils/local-storage';
|
import { getLocalStorageDataByFileId } from '@utils/local-storage';
|
||||||
import { combineLatest, delay, Observable } from 'rxjs';
|
import { combineLatest, delay, Observable } from 'rxjs';
|
||||||
import { map, tap } from 'rxjs/operators';
|
import { filter, map, tap } from 'rxjs/operators';
|
||||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||||
import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service';
|
import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service';
|
||||||
import { REDDocumentViewer } from '../../../pdf-viewer/services/document-viewer.service';
|
import { REDDocumentViewer } from '../../../pdf-viewer/services/document-viewer.service';
|
||||||
@ -57,6 +57,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 { isTargetInput } 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'];
|
||||||
@ -89,10 +90,7 @@ const ALL_HOTKEY_ARRAY = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
|||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, OnDestroy {
|
export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, OnDestroy {
|
||||||
private readonly _annotationsElement = viewChild<ElementRef>('annotationsElement');
|
|
||||||
private readonly _quickNavigationElement = viewChild<ElementRef>('quickNavigation');
|
|
||||||
readonly multiSelectTemplate = viewChild<TemplateRef<any>>('multiSelect');
|
readonly multiSelectTemplate = viewChild<TemplateRef<any>>('multiSelect');
|
||||||
readonly #isIqserDevMode = this._userPreferenceService.isIqserDevMode;
|
|
||||||
protected readonly iconButtonTypes = IconButtonTypes;
|
protected readonly iconButtonTypes = IconButtonTypes;
|
||||||
protected readonly circleButtonTypes = CircleButtonTypes;
|
protected readonly circleButtonTypes = CircleButtonTypes;
|
||||||
protected readonly displayedAnnotations$: Observable<Map<number, ListItem<AnnotationWrapper>[]>>;
|
protected readonly displayedAnnotations$: Observable<Map<number, ListItem<AnnotationWrapper>[]>>;
|
||||||
@ -106,6 +104,9 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
protected displayedPages: number[] = [];
|
protected displayedPages: number[] = [];
|
||||||
protected pagesPanelActive = true;
|
protected pagesPanelActive = true;
|
||||||
protected enabledFilters = [];
|
protected enabledFilters = [];
|
||||||
|
private readonly _annotationsElement = viewChild<ElementRef>('annotationsElement');
|
||||||
|
private readonly _quickNavigationElement = viewChild<ElementRef>('quickNavigation');
|
||||||
|
readonly #isIqserDevMode = this._userPreferenceService.isIqserDevMode;
|
||||||
#displayedPagesChanged = false;
|
#displayedPagesChanged = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -187,6 +188,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
const secondary$ = this.filterService.getFilterModels$('secondaryFilters');
|
const secondary$ = this.filterService.getFilterModels$('secondaryFilters');
|
||||||
|
|
||||||
return combineLatest([
|
return combineLatest([
|
||||||
|
this._documentViewer.loaded$,
|
||||||
this.fileDataService.all$,
|
this.fileDataService.all$,
|
||||||
primary$,
|
primary$,
|
||||||
secondary$,
|
secondary$,
|
||||||
@ -195,7 +197,8 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
this._pageRotationService.rotations$,
|
this._pageRotationService.rotations$,
|
||||||
]).pipe(
|
]).pipe(
|
||||||
delay(0),
|
delay(0),
|
||||||
map(([annotations, primary, secondary, componentReferenceIds]) =>
|
filter(([loaded]) => loaded),
|
||||||
|
map(([, annotations, primary, secondary, componentReferenceIds]) =>
|
||||||
this.#filterAnnotations(annotations, primary, secondary, componentReferenceIds),
|
this.#filterAnnotations(annotations, primary, secondary, componentReferenceIds),
|
||||||
),
|
),
|
||||||
map(annotations => this.#mapListItemsFromAnnotationWrapperArray(annotations)),
|
map(annotations => this.#mapListItemsFromAnnotationWrapperArray(annotations)),
|
||||||
@ -243,11 +246,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
|
|
||||||
@HostListener('window:keyup', ['$event'])
|
@HostListener('window:keyup', ['$event'])
|
||||||
handleKeyEvent($event: KeyboardEvent): void {
|
handleKeyEvent($event: KeyboardEvent): void {
|
||||||
if (
|
if (!ALL_HOTKEY_ARRAY.includes($event.key) || this._dialog.openDialogs.length || isTargetInput($event)) {
|
||||||
!ALL_HOTKEY_ARRAY.includes($event.key) ||
|
|
||||||
this._dialog.openDialogs.length ||
|
|
||||||
($event.target as IqserEventTarget).localName === 'input'
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,7 +328,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
|||||||
}
|
}
|
||||||
|
|
||||||
preventKeyDefault($event: KeyboardEvent): void {
|
preventKeyDefault($event: KeyboardEvent): void {
|
||||||
if (COMMAND_KEY_ARRAY.includes($event.key) && !(($event.target as any).localName === 'input')) {
|
if (COMMAND_KEY_ARRAY.includes($event.key) && !isTargetInput($event)) {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
@use 'common-mixins';
|
||||||
|
|
||||||
.components-header {
|
.components-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -24,18 +26,19 @@ mat-icon {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
overflow: scroll;
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
height: calc(100% - 40px);
|
height: calc(100% - 40px);
|
||||||
|
@include common-mixins.scroll-bar;
|
||||||
|
|
||||||
.component-row {
|
.component-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-left: 13px;
|
margin-left: 13px;
|
||||||
margin-right: 13px;
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 10px 26px;
|
padding: 10px 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
|
||||||
:first-child {
|
:first-child {
|
||||||
@ -47,9 +50,9 @@ 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-right: 13px;
|
||||||
margin-right: 26px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit, signal, ViewChildren } from '@angular/core';
|
import { Component, effect, Input, OnInit, signal, ViewChildren } from '@angular/core';
|
||||||
import { List } from '@common-ui/utils';
|
import { List } from '@common-ui/utils';
|
||||||
import { IconButtonTypes, LoadingService } from '@iqser/common-ui';
|
import { IconButtonTypes, LoadingService } from '@iqser/common-ui';
|
||||||
import { ComponentLogEntry, Dictionary, File, IComponentLogEntry, WorkflowFileStatuses } from '@red/domain';
|
import { ComponentLogEntry, Dictionary, File, IComponentLogEntry, WorkflowFileStatuses } from '@red/domain';
|
||||||
@ -11,6 +11,7 @@ import { map } from 'rxjs/operators';
|
|||||||
import { toObservable } from '@angular/core/rxjs-interop';
|
import { toObservable } from '@angular/core/rxjs-interop';
|
||||||
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
|
import { AsyncPipe, NgForOf, NgIf } from '@angular/common';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-structured-component-management',
|
selector: 'redaction-structured-component-management',
|
||||||
@ -33,7 +34,13 @@ export class StructuredComponentManagementComponent implements OnInit {
|
|||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _componentLogFilterService: ComponentLogFilterService,
|
private readonly _componentLogFilterService: ComponentLogFilterService,
|
||||||
private readonly _filterService: FilterService,
|
private readonly _filterService: FilterService,
|
||||||
) {}
|
private readonly _state: FilePreviewStateService,
|
||||||
|
) {
|
||||||
|
effect(async () => {
|
||||||
|
this._state.file();
|
||||||
|
await this.#loadData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get canEdit() {
|
get canEdit() {
|
||||||
return this.file.workflowStatus !== WorkflowFileStatuses.APPROVED;
|
return this.file.workflowStatus !== WorkflowFileStatuses.APPROVED;
|
||||||
@ -75,7 +82,6 @@ export class StructuredComponentManagementComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async #loadData(): Promise<void> {
|
async #loadData(): Promise<void> {
|
||||||
this._loadingService.start();
|
|
||||||
const componentLogData = await firstValueFrom(
|
const componentLogData = await firstValueFrom(
|
||||||
this._componentLogService.getComponentLogData(
|
this._componentLogService.getComponentLogData(
|
||||||
this.file.dossierTemplateId,
|
this.file.dossierTemplateId,
|
||||||
|
|||||||
@ -52,6 +52,7 @@
|
|||||||
</iqser-icon-button>
|
</iqser-icon-button>
|
||||||
|
|
||||||
<div [translate]="'edit-redaction.dialog.actions.cancel'" class="all-caps-label cancel" mat-dialog-close></div>
|
<div [translate]="'edit-redaction.dialog.actions.cancel'" class="all-caps-label cancel" mat-dialog-close></div>
|
||||||
|
<iqser-help-button></iqser-help-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,13 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
|
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup } from '@angular/forms';
|
||||||
import { CircleButtonComponent, HasScrollbarDirective, IconButtonComponent, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui';
|
import {
|
||||||
|
CircleButtonComponent,
|
||||||
|
HasScrollbarDirective,
|
||||||
|
HelpButtonComponent,
|
||||||
|
IconButtonComponent,
|
||||||
|
IconButtonTypes,
|
||||||
|
IqserDialogComponent,
|
||||||
|
} from '@iqser/common-ui';
|
||||||
import { Dictionary, Dossier, SuperTypes } from '@red/domain';
|
import { Dictionary, Dossier, SuperTypes } from '@red/domain';
|
||||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||||
@ -33,6 +40,7 @@ import { MatDialogClose } from '@angular/material/dialog';
|
|||||||
IconButtonComponent,
|
IconButtonComponent,
|
||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
MatDialogClose,
|
MatDialogClose,
|
||||||
|
HelpButtonComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class EditAnnotationDialogComponent
|
export class EditAnnotationDialogComponent
|
||||||
|
|||||||
@ -60,6 +60,7 @@
|
|||||||
</iqser-icon-button>
|
</iqser-icon-button>
|
||||||
|
|
||||||
<div [translate]="'remove-annotation.dialog.actions.cancel'" class="all-caps-label cancel" mat-dialog-close></div>
|
<div [translate]="'remove-annotation.dialog.actions.cancel'" class="all-caps-label cancel" mat-dialog-close></div>
|
||||||
|
<iqser-help-button></iqser-help-button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,14 @@ import { MatDialogClose } from '@angular/material/dialog';
|
|||||||
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';
|
import { DetailsRadioOption } from '@common-ui/inputs/details-radio/details-radio-option';
|
||||||
import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component';
|
import { DetailsRadioComponent } from '@common-ui/inputs/details-radio/details-radio.component';
|
||||||
import { ReplaceNbspPipe } from '@common-ui/pipes/replace-nbsp.pipe';
|
import { ReplaceNbspPipe } from '@common-ui/pipes/replace-nbsp.pipe';
|
||||||
import { CircleButtonComponent, HasScrollbarDirective, IconButtonComponent, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui';
|
import {
|
||||||
|
CircleButtonComponent,
|
||||||
|
HasScrollbarDirective,
|
||||||
|
HelpButtonComponent,
|
||||||
|
IconButtonComponent,
|
||||||
|
IconButtonTypes,
|
||||||
|
IqserDialogComponent,
|
||||||
|
} from '@iqser/common-ui';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { getRemoveRedactionOptions } from '../../../utils/dialog-options';
|
import { getRemoveRedactionOptions } from '../../../utils/dialog-options';
|
||||||
import { RemoveAnnotationData, RemoveAnnotationOption, RemoveAnnotationOptions, RemoveAnnotationResult } from '../../../utils/dialog-types';
|
import { RemoveAnnotationData, RemoveAnnotationOption, RemoveAnnotationOptions, RemoveAnnotationResult } from '../../../utils/dialog-types';
|
||||||
@ -28,6 +35,7 @@ import { RemoveAnnotationData, RemoveAnnotationOption, RemoveAnnotationOptions,
|
|||||||
CircleButtonComponent,
|
CircleButtonComponent,
|
||||||
MatDialogClose,
|
MatDialogClose,
|
||||||
NgIf,
|
NgIf,
|
||||||
|
HelpButtonComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class RemoveAnnotationDialogComponent extends IqserDialogComponent<
|
export class RemoveAnnotationDialogComponent extends IqserDialogComponent<
|
||||||
|
|||||||
@ -39,7 +39,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.documine-container {
|
&.documine-container {
|
||||||
width: 60%;
|
width: calc(100% - var(--structured-component-management-width));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
import { ActivatedRouteSnapshot, NavigationExtras, Router, RouterLink } from '@angular/router';
|
import { ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
|
||||||
import { ChangeDetectorRef, Component, effect, NgZone, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
import { ChangeDetectorRef, Component, effect, NgZone, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
import { ComponentCanDeactivate } from '@guards/can-deactivate.guard';
|
import { ComponentCanDeactivate } from '@guards/can-deactivate.guard';
|
||||||
import {
|
import {
|
||||||
CircleButtonComponent,
|
|
||||||
CircleButtonTypes,
|
CircleButtonTypes,
|
||||||
ConfirmOption,
|
ConfirmOption,
|
||||||
ConfirmOptions,
|
ConfirmOptions,
|
||||||
@ -12,13 +11,12 @@ import {
|
|||||||
ErrorService,
|
ErrorService,
|
||||||
getConfig,
|
getConfig,
|
||||||
IConfirmationDialogData,
|
IConfirmationDialogData,
|
||||||
IqserAllowDirective,
|
|
||||||
IqserDialog,
|
IqserDialog,
|
||||||
LoadingService,
|
LoadingService,
|
||||||
Toaster,
|
Toaster,
|
||||||
} from '@iqser/common-ui';
|
} from '@iqser/common-ui';
|
||||||
import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilters } from '@iqser/common-ui/lib/filtering';
|
import { copyLocalStorageFiltersValues, FilterService, NestedFilter, processFilters } from '@iqser/common-ui/lib/filtering';
|
||||||
import { AutoUnsubscribe, Bind, bool, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils';
|
import { AutoUnsubscribe, bool, List, OnAttach, OnDetach } from '@iqser/common-ui/lib/utils';
|
||||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { ManualRedactionEntryTypes, ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
import { ManualRedactionEntryTypes, ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
|
||||||
import { Dictionary, File, ViewModes } from '@red/domain';
|
import { Dictionary, File, ViewModes } from '@red/domain';
|
||||||
@ -60,12 +58,7 @@ import { ViewModeService } from './services/view-mode.service';
|
|||||||
import { RedactTextData } from './utils/dialog-types';
|
import { RedactTextData } from './utils/dialog-types';
|
||||||
import { MultiSelectService } from './services/multi-select.service';
|
import { MultiSelectService } from './services/multi-select.service';
|
||||||
import { NgIf } from '@angular/common';
|
import { NgIf } from '@angular/common';
|
||||||
import { ViewSwitchComponent } from './components/view-switch/view-switch.component';
|
|
||||||
import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component';
|
|
||||||
import { UserManagementComponent } from './components/user-management/user-management.component';
|
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { InitialsAvatarComponent } from '@common-ui/users';
|
|
||||||
import { FileActionsComponent } from '../shared-dossiers/components/file-actions/file-actions.component';
|
|
||||||
import { FilePreviewRightContainerComponent } from './components/right-container/file-preview-right-container.component';
|
import { FilePreviewRightContainerComponent } from './components/right-container/file-preview-right-container.component';
|
||||||
import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.component';
|
import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.component';
|
||||||
import { FileHeaderComponent } from './components/file-header/file-header.component';
|
import { FileHeaderComponent } from './components/file-header/file-header.component';
|
||||||
@ -79,16 +72,8 @@ import { DocumentInfoService } from './services/document-info.service';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [
|
imports: [
|
||||||
NgIf,
|
NgIf,
|
||||||
ViewSwitchComponent,
|
|
||||||
ProcessingIndicatorComponent,
|
|
||||||
UserManagementComponent,
|
|
||||||
TranslateModule,
|
TranslateModule,
|
||||||
InitialsAvatarComponent,
|
|
||||||
CircleButtonComponent,
|
|
||||||
IqserAllowDirective,
|
|
||||||
FileActionsComponent,
|
|
||||||
DisableStopPropagationDirective,
|
DisableStopPropagationDirective,
|
||||||
RouterLink,
|
|
||||||
FilePreviewRightContainerComponent,
|
FilePreviewRightContainerComponent,
|
||||||
TypeFilterComponent,
|
TypeFilterComponent,
|
||||||
FileHeaderComponent,
|
FileHeaderComponent,
|
||||||
@ -303,7 +288,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
super.ngOnDestroy();
|
super.ngOnDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bind()
|
|
||||||
handleEscInsideViewer($event: KeyboardEvent) {
|
handleEscInsideViewer($event: KeyboardEvent) {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
if (!!this._annotationManager.selected[0]) {
|
if (!!this._annotationManager.selected[0]) {
|
||||||
@ -356,7 +340,13 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
|||||||
|
|
||||||
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', {
|
||||||
|
keydown: (e: KeyboardEvent) => this.pdf.escKeyHandler.keydown(e),
|
||||||
|
keyup: (e: KeyboardEvent) => {
|
||||||
|
this.pdf.escKeyHandler.keyup(e);
|
||||||
|
this.handleEscInsideViewer(e);
|
||||||
|
},
|
||||||
|
});
|
||||||
this._viewerHeaderService.resetLayers();
|
this._viewerHeaderService.resetLayers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,10 @@ export class DocumentInfoService {
|
|||||||
},
|
},
|
||||||
{ allowSignalWrites: true },
|
{ allowSignalWrites: true },
|
||||||
);
|
);
|
||||||
|
|
||||||
|
effect(() => {
|
||||||
|
document.body.style.setProperty('--quick-navigation-width', this.shown() ? '350px' : '61px');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fileAttributes$(fileId: string, dossierId: string, dossierTemplateId: string) {
|
fileAttributes$(fileId: string, dossierId: string, dossierTemplateId: string) {
|
||||||
|
|||||||
@ -270,7 +270,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
|||||||
const viewTime = timestampOf(viewedPage.viewedTime) - DELTA_VIEW_TIME;
|
const viewTime = timestampOf(viewedPage.viewedTime) - DELTA_VIEW_TIME;
|
||||||
let changeOccurredAfterPageIsViewed = lastChange && timestampOf(lastChange.dateTime) > viewTime;
|
let changeOccurredAfterPageIsViewed = lastChange && timestampOf(lastChange.dateTime) > viewTime;
|
||||||
|
|
||||||
if (changeOccurredAfterPageIsViewed) {
|
if (changeOccurredAfterPageIsViewed !== undefined) {
|
||||||
this.#markPageAsUnseenIfNeeded(viewedPage, lastChange.dateTime);
|
this.#markPageAsUnseenIfNeeded(viewedPage, lastChange.dateTime);
|
||||||
return lastChange?.type;
|
return lastChange?.type;
|
||||||
}
|
}
|
||||||
@ -281,7 +281,7 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
|||||||
const processedTime = lastManualChange?.processedDate;
|
const processedTime = lastManualChange?.processedDate;
|
||||||
changeOccurredAfterPageIsViewed = processedTime && timestampOf(processedTime) > viewTime;
|
changeOccurredAfterPageIsViewed = processedTime && timestampOf(processedTime) > viewTime;
|
||||||
|
|
||||||
if (changeOccurredAfterPageIsViewed) {
|
if (changeOccurredAfterPageIsViewed !== undefined) {
|
||||||
this.#markPageAsUnseenIfNeeded(viewedPage, processedTime);
|
this.#markPageAsUnseenIfNeeded(viewedPage, processedTime);
|
||||||
return ChangeTypes.CHANGED;
|
return ChangeTypes.CHANGED;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -128,7 +128,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),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,7 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
&.documine-pagination {
|
&.documine-pagination {
|
||||||
left: calc(100% - (var(--documine-viewer-width) / 2) - var(--qiuck-navigation-width));
|
left: calc(100% - (var(--documine-viewer-width) / 2) - var(--quick-navigation-width));
|
||||||
}
|
}
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
|
|||||||
@ -14,6 +14,7 @@ import { PdfViewer } from './pdf-viewer.service';
|
|||||||
import Color = Core.Annotations.Color;
|
import Color = Core.Annotations.Color;
|
||||||
import DocumentViewer = Core.DocumentViewer;
|
import DocumentViewer = Core.DocumentViewer;
|
||||||
import Quad = Core.Math.Quad;
|
import Quad = Core.Math.Quad;
|
||||||
|
import { isTargetInput } from '@utils/functions';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class REDDocumentViewer {
|
export class REDDocumentViewer {
|
||||||
@ -71,12 +72,12 @@ export class REDDocumentViewer {
|
|||||||
return fromEvent<KeyboardEvent>(this.#document, 'keyUp').pipe(
|
return fromEvent<KeyboardEvent>(this.#document, 'keyUp').pipe(
|
||||||
tap(stopAndPreventIfNotAllowed),
|
tap(stopAndPreventIfNotAllowed),
|
||||||
filter($event => {
|
filter($event => {
|
||||||
if (($event.target as HTMLElement)?.tagName?.toLowerCase() === 'input') {
|
if (isTargetInput($event)) {
|
||||||
if ($event.key === 'Escape') {
|
if ($event.key === 'Escape') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ($event.target as HTMLElement)?.tagName?.toLowerCase() !== 'input';
|
return isTargetInput($event);
|
||||||
}),
|
}),
|
||||||
filter($event => $event.key.startsWith('Arrow') || ['f', 'h', 'H', 'Escape'].includes($event.key)),
|
filter($event => $event.key.startsWith('Arrow') || ['f', 'h', 'H', 'Escape'].includes($event.key)),
|
||||||
tap<KeyboardEvent>(stopAndPrevent),
|
tap<KeyboardEvent>(stopAndPrevent),
|
||||||
|
|||||||
@ -65,6 +65,21 @@ export class PdfViewer {
|
|||||||
};
|
};
|
||||||
selectedText = '';
|
selectedText = '';
|
||||||
|
|
||||||
|
readonly escKeyHandler = {
|
||||||
|
keydown: (e: KeyboardEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
this.#clickSelectToolButton();
|
||||||
|
},
|
||||||
|
keyup: (e: KeyboardEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (this.#isElementActive('searchPanel') && !this._annotationManager.resizingAnnotationId) {
|
||||||
|
this.#focusViewer();
|
||||||
|
this.deactivateSearch();
|
||||||
|
}
|
||||||
|
this.#clickSelectToolButton();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _logger: NGXLogger,
|
private readonly _logger: NGXLogger,
|
||||||
private readonly _errorService: ErrorService,
|
private readonly _errorService: ErrorService,
|
||||||
@ -147,7 +162,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 () => {
|
||||||
@ -163,7 +178,6 @@ export class PdfViewer {
|
|||||||
this.#disableHotkeys();
|
this.#disableHotkeys();
|
||||||
this.#getSelectedText();
|
this.#getSelectedText();
|
||||||
this.#listenForCommandF();
|
this.#listenForCommandF();
|
||||||
this.#listenForEsc();
|
|
||||||
this.#clearSearchResultsWhenVisibilityChanged();
|
this.#clearSearchResultsWhenVisibilityChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -270,23 +284,6 @@ export class PdfViewer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#listenForEsc() {
|
|
||||||
this.#instance.UI.hotkeys.on('esc', {
|
|
||||||
keydown: e => {
|
|
||||||
e.preventDefault();
|
|
||||||
this.#clickSelectToolButton();
|
|
||||||
},
|
|
||||||
keyup: e => {
|
|
||||||
e.preventDefault();
|
|
||||||
if (this.#isElementActive('searchPanel') && !this._annotationManager.resizingAnnotationId) {
|
|
||||||
this.#focusViewer();
|
|
||||||
this.deactivateSearch();
|
|
||||||
}
|
|
||||||
this.#clickSelectToolButton();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
<div *ngIf="isDossierOverviewList && fileAttributesService.isEditingFileAttribute() === false" class="action-buttons">
|
<div *ngIf="isDossierOverviewList() && fileAttributesService.isEditingFileAttribute() === false" class="action-buttons">
|
||||||
<ng-container *ngTemplateOutlet="actions"></ng-container>
|
<ng-container *ngTemplateOutlet="actions"></ng-container>
|
||||||
|
|
||||||
<redaction-processing-indicator *ngIf="showStatusBar" [file]="file"></redaction-processing-indicator>
|
<redaction-processing-indicator *ngIf="showStatusBar()" [file]="file()"></redaction-processing-indicator>
|
||||||
|
|
||||||
<iqser-status-bar *ngIf="showStatusBar" [configs]="[{ color: file.workflowStatus, length: 1 }]"></iqser-status-bar>
|
<iqser-status-bar *ngIf="showStatusBar()" [configs]="[{ color: file().workflowStatus, length: 1 }]"></iqser-status-bar>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="isFilePreview || isDossierOverviewWorkflow">
|
<ng-container *ngIf="isFilePreview() || isDossierOverviewWorkflow()">
|
||||||
<ng-container *ngTemplateOutlet="actions"></ng-container>
|
<ng-container *ngTemplateOutlet="actions"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-template #actions (longPress)="forceReanalysisAction($event)" redactionLongPress>
|
<ng-template #actions (longPress)="forceReanalysisAction($event)" redactionLongPress>
|
||||||
<div class="file-actions">
|
<div class="file-actions">
|
||||||
<redaction-expandable-file-actions
|
<redaction-expandable-file-actions
|
||||||
[actions]="buttons"
|
[actions]="buttons()"
|
||||||
[id]="'actions-for-' + file.fileId"
|
[id]="'actions-for-' + file().fileId"
|
||||||
[maxWidth]="maxWidth"
|
[maxWidth]="maxWidth()"
|
||||||
[minWidth]="minWidth"
|
[minWidth]="minWidth()"
|
||||||
[tooltipPosition]="tooltipPosition"
|
[tooltipPosition]="tooltipPosition"
|
||||||
[helpModeKeyPrefix]="helpModeKeyPrefix"
|
[helpModeKeyPrefix]="helpModeKeyPrefix()"
|
||||||
[isDossierOverviewWorkflow]="isDossierOverviewWorkflow"
|
[isDossierOverviewWorkflow]="isDossierOverviewWorkflow()"
|
||||||
[singleEntityAction]="singleEntityAction"
|
[singleEntityAction]="singleEntityAction()"
|
||||||
></redaction-expandable-file-actions>
|
></redaction-expandable-file-actions>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ChangeDetectorRef, Component, HostBinding, Injector, Input, OnChanges, Optional, ViewChild } from '@angular/core';
|
import { Component, computed, HostBinding, Injector, input, Optional, signal, ViewChild } from '@angular/core';
|
||||||
import { toObservable } from '@angular/core/rxjs-interop';
|
import { toObservable } from '@angular/core/rxjs-interop';
|
||||||
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';
|
||||||
@ -36,6 +36,7 @@ import { FileAssignService } from '../../services/file-assign.service';
|
|||||||
import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component';
|
import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component';
|
||||||
import { StatusBarComponent } from '@common-ui/shared';
|
import { StatusBarComponent } from '@common-ui/shared';
|
||||||
import { NgIf, NgTemplateOutlet } from '@angular/common';
|
import { NgIf, NgTemplateOutlet } from '@angular/common';
|
||||||
|
import { RulesService } from '../../../admin/services/rules.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-file-actions',
|
selector: 'redaction-file-actions',
|
||||||
@ -44,52 +45,113 @@ import { NgIf, NgTemplateOutlet } from '@angular/common';
|
|||||||
standalone: true,
|
standalone: true,
|
||||||
imports: [ProcessingIndicatorComponent, StatusBarComponent, LongPressDirective, ExpandableFileActionsComponent, NgTemplateOutlet, NgIf],
|
imports: [ProcessingIndicatorComponent, StatusBarComponent, LongPressDirective, ExpandableFileActionsComponent, NgTemplateOutlet, NgIf],
|
||||||
})
|
})
|
||||||
export class FileActionsComponent implements OnChanges {
|
export class FileActionsComponent {
|
||||||
@Input({ required: true }) file: File;
|
|
||||||
@Input({ required: true }) dossier: Dossier;
|
|
||||||
@Input({ required: true }) type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
|
|
||||||
@Input() maxWidth: number;
|
|
||||||
@Input() minWidth: number;
|
|
||||||
@Input() helpModeKeyPrefix: 'dossier' | 'editor' = 'dossier';
|
|
||||||
@Input() singleEntityAction = false;
|
|
||||||
readonly currentUser = getCurrentUser<User>();
|
|
||||||
toggleTooltip?: string;
|
|
||||||
assignTooltip?: string;
|
|
||||||
showDownload = false;
|
|
||||||
showSetToNew = false;
|
|
||||||
showUndoApproval = false;
|
|
||||||
showAssignToSelf = false;
|
|
||||||
showImportRedactions = false;
|
|
||||||
showAssign = false;
|
|
||||||
showDelete = false;
|
|
||||||
showOCR = false;
|
|
||||||
canReanalyse = false;
|
|
||||||
canDisableAutoAnalysis = false;
|
|
||||||
canEnableAutoAnalysis = false;
|
|
||||||
showUnderReview = false;
|
|
||||||
showUnderApproval = false;
|
|
||||||
showApprove = false;
|
|
||||||
canToggleAnalysis = false;
|
|
||||||
showToggleAnalysis = false;
|
|
||||||
showStatusBar = false;
|
|
||||||
showReanalyseFilePreview = false;
|
|
||||||
showReanalyseDossierOverview = false;
|
|
||||||
analysisForced = false;
|
|
||||||
isDossierOverview = false;
|
|
||||||
isDossierOverviewList = false;
|
|
||||||
isDossierOverviewWorkflow = false;
|
|
||||||
isFilePreview = false;
|
|
||||||
isDossierMember = false;
|
|
||||||
tooltipPosition = IqserTooltipPositions.above;
|
|
||||||
buttons: Action[];
|
|
||||||
@ViewChild(ExpandableFileActionsComponent)
|
@ViewChild(ExpandableFileActionsComponent)
|
||||||
private readonly _expandableActionsComponent: ExpandableFileActionsComponent;
|
private readonly _expandableActionsComponent: ExpandableFileActionsComponent;
|
||||||
|
readonly file = input.required<File>();
|
||||||
|
readonly dossier = input.required<Dossier>();
|
||||||
|
readonly type = input.required<'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow'>();
|
||||||
|
readonly maxWidth = input<number>();
|
||||||
|
readonly minWidth = input<number>();
|
||||||
|
readonly helpModeKeyPrefix = input<'dossier' | 'editor'>('dossier');
|
||||||
|
readonly singleEntityAction = input(false);
|
||||||
|
readonly currentUser = getCurrentUser<User>();
|
||||||
|
readonly tooltipPosition = IqserTooltipPositions.above;
|
||||||
|
|
||||||
|
readonly isDossierOverview = computed(() => this.type().startsWith('dossier-overview'));
|
||||||
|
readonly isDossierOverviewList = computed(() => this.type() === 'dossier-overview-list');
|
||||||
|
readonly isDossierOverviewWorkflow = computed(() => this.type() === 'dossier-overview-workflow');
|
||||||
|
readonly isFilePreview = computed(() => this.type() === 'file-preview');
|
||||||
|
readonly buttons = computed(() => this.#buttons);
|
||||||
|
readonly showStatusBar = computed(() => !this.file().isError && !this.file().isUnprocessed && this.isDossierOverviewList());
|
||||||
|
readonly #assignTooltip? = computed(() =>
|
||||||
|
this.file().isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer'),
|
||||||
|
);
|
||||||
|
readonly #showSetToNew = computed(
|
||||||
|
() =>
|
||||||
|
this._permissionsService.canSetToNew(this.file(), this.dossier()) && !this.isDossierOverviewWorkflow() && !this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #showUndoApproval = computed(
|
||||||
|
() =>
|
||||||
|
this._permissionsService.canUndoApproval(this.file(), this.dossier()) &&
|
||||||
|
!this.isDossierOverviewWorkflow() &&
|
||||||
|
!this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #showAssignToSelf = computed(
|
||||||
|
() => this._permissionsService.canAssignToSelf(this.file(), this.dossier()) && this.isDossierOverview(),
|
||||||
|
);
|
||||||
|
readonly #showImportRedactions = computed(
|
||||||
|
() => this._permissionsService.canImportRedactions(this.file(), this.dossier()) && !this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #showAssign = computed(
|
||||||
|
() =>
|
||||||
|
(this._permissionsService.canAssignUser(this.file(), this.dossier()) ||
|
||||||
|
this._permissionsService.canUnassignUser(this.file(), this.dossier())) &&
|
||||||
|
this.isDossierOverview(),
|
||||||
|
);
|
||||||
|
readonly #showDelete = computed(() => this._permissionsService.canSoftDeleteFile(this.file(), this.dossier()));
|
||||||
|
readonly #showOCR = computed(() => this._permissionsService.canOcrFile(this.file(), this.dossier()) && !this.file().isError);
|
||||||
|
readonly #canReanalyse = computed(() => this._permissionsService.canReanalyseFile(this.file(), this.dossier()));
|
||||||
|
readonly #canEnableAutoAnalysis = computed(
|
||||||
|
() => this._permissionsService.canEnableAutoAnalysis([this.file()], this.dossier()) && !this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #showUnderReview = computed(
|
||||||
|
() =>
|
||||||
|
this._permissionsService.canSetUnderReview(this.file(), this.dossier()) &&
|
||||||
|
!this.isDossierOverviewWorkflow() &&
|
||||||
|
!this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #showUnderApproval = computed(
|
||||||
|
() =>
|
||||||
|
this._permissionsService.canSetUnderApproval(this.file(), this.dossier()) &&
|
||||||
|
!this.isDossierOverviewWorkflow() &&
|
||||||
|
!this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #showApprove = computed(
|
||||||
|
() =>
|
||||||
|
this._permissionsService.isReadyForApproval(this.file(), this.dossier()) &&
|
||||||
|
!this.isDossierOverviewWorkflow() &&
|
||||||
|
!this.file().isError,
|
||||||
|
);
|
||||||
|
readonly #canToggleAnalysis = computed(() => this._permissionsService.canToggleAnalysis(this.file(), this.dossier()));
|
||||||
|
readonly #toggleTooltip? = computed(() => {
|
||||||
|
if (!this.#canToggleAnalysis()) {
|
||||||
|
return _('file-preview.toggle-analysis.only-managers');
|
||||||
|
}
|
||||||
|
return this.file()?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
|
||||||
|
});
|
||||||
|
readonly #showToggleAnalysis = computed(
|
||||||
|
() => !!this.file().lastProcessed && this._permissionsService.showToggleAnalysis(this.dossier()),
|
||||||
|
);
|
||||||
|
readonly #analysisForced = signal(false);
|
||||||
|
readonly #showReanalyse = computed(
|
||||||
|
() => (this.#canReanalyse() || this.file().excludedFromAutomaticAnalysis || this.#analysisForced()) && !this.file().dossierArchived,
|
||||||
|
);
|
||||||
|
readonly #isDossierMember = computed(() => this._permissionsService.isDossierMember(this.dossier()));
|
||||||
|
readonly #showDownload = computed(
|
||||||
|
() =>
|
||||||
|
this._permissionsService.canDownloadRedactedFile() &&
|
||||||
|
!!this.file().lastProcessed &&
|
||||||
|
!this.file().isError &&
|
||||||
|
this.#isDossierMember(),
|
||||||
|
);
|
||||||
|
readonly #showReanalyseFilePreview = computed(
|
||||||
|
() => this.#showReanalyse() && this.isFilePreview() && !this.file().isApproved && this.#isDossierMember(),
|
||||||
|
);
|
||||||
|
readonly #showReanalyseDossierOverview = computed(
|
||||||
|
() => this.#showReanalyse() && this.isDossierOverview() && !this.file().isApproved && this.#isDossierMember(),
|
||||||
|
);
|
||||||
|
readonly #ariaExpanded$ = toObservable(this._documentInfoService?.shown);
|
||||||
|
readonly #areRulesLocked = computed(() => this._rulesService.currentTemplateRules().timeoutDetected);
|
||||||
|
|
||||||
readonly #isDocumine = getConfig().IS_DOCUMINE;
|
readonly #isDocumine = getConfig().IS_DOCUMINE;
|
||||||
|
readonly #canDisableAutoAnalysis = computed(
|
||||||
|
() => !this.#isDocumine && this._permissionsService.canDisableAutoAnalysis([this.file()], this.dossier()),
|
||||||
|
);
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly _injector: Injector,
|
private readonly _injector: Injector,
|
||||||
private readonly _filesService: FilesService,
|
private readonly _filesService: FilesService,
|
||||||
private readonly _changeRef: ChangeDetectorRef,
|
|
||||||
private readonly _loadingService: LoadingService,
|
private readonly _loadingService: LoadingService,
|
||||||
private readonly _dialogService: DossiersDialogService,
|
private readonly _dialogService: DossiersDialogService,
|
||||||
private readonly _iqserDialog: IqserDialog,
|
private readonly _iqserDialog: IqserDialog,
|
||||||
@ -100,6 +162,8 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
private readonly _activeDossiersService: ActiveDossiersService,
|
private readonly _activeDossiersService: ActiveDossiersService,
|
||||||
private readonly _fileManagementService: FileManagementService,
|
private readonly _fileManagementService: FileManagementService,
|
||||||
private readonly _userPreferenceService: UserPreferenceService,
|
private readonly _userPreferenceService: UserPreferenceService,
|
||||||
|
private readonly _rulesService: RulesService,
|
||||||
|
private readonly _toasterService: Toaster,
|
||||||
readonly fileAttributesService: FileAttributesService,
|
readonly fileAttributesService: FileAttributesService,
|
||||||
@Optional() private readonly _documentInfoService: DocumentInfoService,
|
@Optional() private readonly _documentInfoService: DocumentInfoService,
|
||||||
@Optional() private readonly _excludedPagesService: ExcludedPagesService,
|
@Optional() private readonly _excludedPagesService: ExcludedPagesService,
|
||||||
@ -110,24 +174,15 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
return !!this._expandableActionsComponent?.expanded;
|
return !!this._expandableActionsComponent?.expanded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private get _toggleTooltip(): string {
|
get #buttons() {
|
||||||
if (!this.canToggleAnalysis) {
|
|
||||||
return _('file-preview.toggle-analysis.only-managers');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.file?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
|
|
||||||
}
|
|
||||||
|
|
||||||
private get _buttons(): Action[] {
|
|
||||||
const actions: Action[] = [
|
const actions: Action[] = [
|
||||||
{
|
{
|
||||||
id: 'btn-download_file',
|
id: 'btn-download_file',
|
||||||
type: ActionTypes.downloadBtn,
|
type: ActionTypes.downloadBtn,
|
||||||
files: [this.file],
|
files: [this.file()],
|
||||||
dossier: this.dossier,
|
dossier: this.dossier(),
|
||||||
tooltipClass: 'small',
|
tooltipClass: 'small',
|
||||||
show: this.showDownload,
|
show: this.#showDownload(),
|
||||||
disabled: this.file.processingStatus === ProcessingFileStatuses.ERROR,
|
|
||||||
helpModeKey: this.#isDocumine ? 'download_document' : 'download',
|
helpModeKey: this.#isDocumine ? 'download_document' : 'download',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -136,16 +191,16 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#openDeleteFileDialog(),
|
action: () => this.#openDeleteFileDialog(),
|
||||||
tooltip: _('dossier-overview.delete.action'),
|
tooltip: _('dossier-overview.delete.action'),
|
||||||
icon: 'iqser:trash',
|
icon: 'iqser:trash',
|
||||||
show: this.showDelete,
|
show: this.#showDelete(),
|
||||||
helpModeKey: 'delete_file',
|
helpModeKey: 'delete_file',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'btn-assign',
|
id: 'btn-assign',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.#assign(),
|
action: () => this.#assign(),
|
||||||
tooltip: this.assignTooltip,
|
tooltip: this.#assignTooltip(),
|
||||||
icon: 'red:assign',
|
icon: 'red:assign',
|
||||||
show: this.showAssign,
|
show: this.#showAssign(),
|
||||||
helpModeKey: 'assign_user',
|
helpModeKey: 'assign_user',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -154,7 +209,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#assignToMe(),
|
action: () => this.#assignToMe(),
|
||||||
tooltip: _('dossier-overview.assign-me'),
|
tooltip: _('dossier-overview.assign-me'),
|
||||||
icon: 'red:assign-me',
|
icon: 'red:assign-me',
|
||||||
show: this.showAssignToSelf,
|
show: this.#showAssignToSelf(),
|
||||||
helpModeKey: 'assign_user',
|
helpModeKey: 'assign_user',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -163,7 +218,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#openImportRedactionsDialog(),
|
action: () => this.#openImportRedactionsDialog(),
|
||||||
tooltip: _('dossier-overview.import-redactions'),
|
tooltip: _('dossier-overview.import-redactions'),
|
||||||
icon: 'red:import_redactions',
|
icon: 'red:import_redactions',
|
||||||
show: this.showImportRedactions && !this._iqserPermissionsService.has(Roles.getRss),
|
show: this.#showImportRedactions() && !this._iqserPermissionsService.has(Roles.getRss),
|
||||||
helpModeKey: 'import_redactions',
|
helpModeKey: 'import_redactions',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -171,7 +226,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.#toggleDocumentInfo(),
|
action: () => this.#toggleDocumentInfo(),
|
||||||
tooltip: _('file-preview.document-info'),
|
tooltip: _('file-preview.document-info'),
|
||||||
ariaExpanded: toObservable(this._documentInfoService?.shown, { injector: this._injector }),
|
ariaExpanded: this.#ariaExpanded$,
|
||||||
icon: 'red:status-info',
|
icon: 'red:status-info',
|
||||||
show: !!this._documentInfoService,
|
show: !!this._documentInfoService,
|
||||||
helpModeKey: 'document_info',
|
helpModeKey: 'document_info',
|
||||||
@ -181,10 +236,10 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.#toggleExcludePages(),
|
action: () => this.#toggleExcludePages(),
|
||||||
tooltip: _('file-preview.exclude-pages'),
|
tooltip: _('file-preview.exclude-pages'),
|
||||||
ariaExpanded: toObservable(this._excludedPagesService?.shown, { injector: this._injector }),
|
ariaExpanded: this.#ariaExpanded$,
|
||||||
showDot: !!this.file.excludedPages?.length,
|
showDot: !!this.file().excludedPages?.length,
|
||||||
icon: 'red:exclude-pages',
|
icon: 'red:exclude-pages',
|
||||||
show: !!this._excludedPagesService && this._permissionsService.canExcludePages(this.file, this.dossier),
|
show: !!this._excludedPagesService && this._permissionsService.canExcludePages(this.file(), this.dossier()),
|
||||||
helpModeKey: 'exclude_pages',
|
helpModeKey: 'exclude_pages',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -193,7 +248,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#setToNew(),
|
action: () => this.#setToNew(),
|
||||||
tooltip: _('dossier-overview.back-to-new'),
|
tooltip: _('dossier-overview.back-to-new'),
|
||||||
icon: 'red:undo',
|
icon: 'red:undo',
|
||||||
show: this.showSetToNew,
|
show: this.#showSetToNew(),
|
||||||
helpModeKey: 'change_status',
|
helpModeKey: 'change_status',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -202,7 +257,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#setFileUnderApproval(),
|
action: () => this.#setFileUnderApproval(),
|
||||||
tooltip: _('dossier-overview.under-approval'),
|
tooltip: _('dossier-overview.under-approval'),
|
||||||
icon: 'red:ready-for-approval',
|
icon: 'red:ready-for-approval',
|
||||||
show: this.showUnderApproval,
|
show: this.#showUnderApproval(),
|
||||||
helpModeKey: 'change_status',
|
helpModeKey: 'change_status',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -211,17 +266,17 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#setFileUnderReview(),
|
action: () => this.#setFileUnderReview(),
|
||||||
tooltip: _('dossier-overview.under-review'),
|
tooltip: _('dossier-overview.under-review'),
|
||||||
icon: 'red:undo',
|
icon: 'red:undo',
|
||||||
show: this.showUnderReview,
|
show: this.#showUnderReview(),
|
||||||
helpModeKey: 'change_status',
|
helpModeKey: 'change_status',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'btn-set_file_approved',
|
id: 'btn-set_file_approved',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.setFileApproved(),
|
action: () => this.setFileApproved(),
|
||||||
tooltip: this.file.canBeApproved ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
|
tooltip: this.file().canBeApproved ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
|
||||||
icon: 'red:approved',
|
icon: 'red:approved',
|
||||||
disabled: !this.file.canBeApproved,
|
disabled: !this.file().canBeApproved,
|
||||||
show: this.showApprove,
|
show: this.#showApprove(),
|
||||||
helpModeKey: 'change_status',
|
helpModeKey: 'change_status',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -230,28 +285,27 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#toggleAutomaticAnalysis(),
|
action: () => this.#toggleAutomaticAnalysis(),
|
||||||
tooltip: _('dossier-overview.stop-auto-analysis'),
|
tooltip: _('dossier-overview.stop-auto-analysis'),
|
||||||
icon: 'red:disable-analysis',
|
icon: 'red:disable-analysis',
|
||||||
show: this.canDisableAutoAnalysis,
|
show: this.#canDisableAutoAnalysis(),
|
||||||
helpModeKey: 'stop_analysis',
|
helpModeKey: 'stop_analysis',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'btn-reanalyse_file_preview',
|
id: 'btn-reanalyse_file_preview',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.#reanalyseFile(),
|
action: () => this.#reanalyseFile(),
|
||||||
tooltip: _('file-preview.reanalyse-notification'),
|
tooltip: this.#areRulesLocked() ? _('dossier-listing.rules.timeoutError') : _('file-preview.reanalyse-notification'),
|
||||||
tooltipClass: 'small',
|
|
||||||
icon: 'iqser:refresh',
|
icon: 'iqser:refresh',
|
||||||
show: this.showReanalyseFilePreview,
|
show: this.#showReanalyseFilePreview(),
|
||||||
disabled: this.file.isProcessing,
|
disabled: this.file().isProcessing || this.#areRulesLocked(),
|
||||||
helpModeKey: 'stop_analysis',
|
helpModeKey: this.#isDocumine ? 'analyze_file' : 'stop_analysis',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'btn-toggle_automatic_analysis',
|
id: 'btn-toggle_automatic_analysis',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.#toggleAutomaticAnalysis(),
|
action: () => this.#toggleAutomaticAnalysis(),
|
||||||
tooltip: _('dossier-overview.start-auto-analysis'),
|
tooltip: _('dossier-overview.start-auto-analysis'),
|
||||||
buttonType: this.isFilePreview ? CircleButtonTypes.warn : CircleButtonTypes.default,
|
buttonType: this.isFilePreview() ? CircleButtonTypes.warn : CircleButtonTypes.default,
|
||||||
icon: 'red:enable-analysis',
|
icon: 'red:enable-analysis',
|
||||||
show: this.canEnableAutoAnalysis,
|
show: this.#canEnableAutoAnalysis(),
|
||||||
helpModeKey: 'stop_analysis',
|
helpModeKey: 'stop_analysis',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -260,7 +314,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#setFileUnderApproval(),
|
action: () => this.#setFileUnderApproval(),
|
||||||
tooltip: _('dossier-overview.under-approval'),
|
tooltip: _('dossier-overview.under-approval'),
|
||||||
icon: 'red:undo',
|
icon: 'red:undo',
|
||||||
show: this.showUndoApproval,
|
show: this.#showUndoApproval(),
|
||||||
helpModeKey: 'change_status',
|
helpModeKey: 'change_status',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -269,27 +323,28 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
action: () => this.#ocrFile(),
|
action: () => this.#ocrFile(),
|
||||||
tooltip: _('dossier-overview.ocr-file'),
|
tooltip: _('dossier-overview.ocr-file'),
|
||||||
icon: 'iqser:ocr',
|
icon: 'iqser:ocr',
|
||||||
show: this.showOCR,
|
show: this.#showOCR(),
|
||||||
helpModeKey: 'automatic_text_recognition',
|
helpModeKey: 'automatic_text_recognition',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'btn-reanalyse_file',
|
id: 'btn-reanalyse_file',
|
||||||
type: ActionTypes.circleBtn,
|
type: ActionTypes.circleBtn,
|
||||||
action: () => this.#reanalyseFile(),
|
action: () => this.#reanalyseFile(),
|
||||||
tooltip: _('dossier-overview.reanalyse.action'),
|
tooltip: this.#areRulesLocked() ? _('dossier-listing.rules.timeoutError') : _('dossier-overview.reanalyse.action'),
|
||||||
icon: 'iqser:refresh',
|
icon: 'iqser:refresh',
|
||||||
show: this.showReanalyseDossierOverview,
|
show: this.#showReanalyseDossierOverview(),
|
||||||
helpModeKey: 'stop_analysis',
|
disabled: this.#areRulesLocked(),
|
||||||
|
helpModeKey: this.#isDocumine ? 'analyze_file' : 'stop_analysis',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'btn-toggle_analysis',
|
id: 'btn-toggle_analysis',
|
||||||
type: ActionTypes.toggle,
|
type: ActionTypes.toggle,
|
||||||
action: () => this.#toggleAnalysis(),
|
action: () => this.#toggleAnalysis(),
|
||||||
disabled: !this.canToggleAnalysis,
|
disabled: !this.#canToggleAnalysis(),
|
||||||
tooltip: this.toggleTooltip,
|
tooltip: this.#toggleTooltip(),
|
||||||
class: { 'mr-24': this.isDossierOverviewList },
|
class: { 'mr-24': this.isDossierOverviewList() },
|
||||||
checked: !this.file.excluded,
|
checked: !this.file().excluded,
|
||||||
show: this.showToggleAnalysis && this.isDossierMember,
|
show: this.#showToggleAnalysis() && this.#isDossierMember(),
|
||||||
helpModeKey: 'disable_extraction',
|
helpModeKey: 'disable_extraction',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -297,33 +352,28 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
return actions.filter(btn => btn.show);
|
return actions.filter(btn => btn.show);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
|
||||||
this.#setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
async setFileApproved() {
|
async setFileApproved() {
|
||||||
if (!this.file.analysisRequired && !this.file.hasUpdates) {
|
if (!this.file().analysisRequired && !this.file().hasUpdates) {
|
||||||
await this.#setFileApproved();
|
await this.#setFileApproved();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data: IConfirmationDialogData = {
|
const data: IConfirmationDialogData = {
|
||||||
title: this.file.analysisRequired
|
title: this.file().analysisRequired
|
||||||
? _('confirmation-dialog.approve-file-without-analysis.title')
|
? _('confirmation-dialog.approve-file-without-analysis.title')
|
||||||
: _('confirmation-dialog.approve-file.title'),
|
: _('confirmation-dialog.approve-file.title'),
|
||||||
question: this.file.analysisRequired
|
question: this.file().analysisRequired
|
||||||
? _('confirmation-dialog.approve-file-without-analysis.question')
|
? _('confirmation-dialog.approve-file-without-analysis.question')
|
||||||
: _('confirmation-dialog.approve-file.question'),
|
: _('confirmation-dialog.approve-file.question'),
|
||||||
confirmationText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.confirmationText') : null,
|
confirmationText: this.file().analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.confirmationText') : null,
|
||||||
denyText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.denyText') : null,
|
denyText: this.file().analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.denyText') : null,
|
||||||
};
|
};
|
||||||
|
|
||||||
this._dialogService.openDialog('confirm', data, () => this.#setFileApproved());
|
this._dialogService.openDialog('confirm', data, () => this.#setFileApproved());
|
||||||
}
|
}
|
||||||
|
|
||||||
forceReanalysisAction($event: LongPressEvent) {
|
forceReanalysisAction($event: LongPressEvent) {
|
||||||
this.analysisForced = !$event.touchEnd && this._userPreferenceService.isIqserDevMode;
|
this.#analysisForced.set(!$event.touchEnd && this._userPreferenceService.isIqserDevMode);
|
||||||
this.#setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#showOCRConfirmationDialog(): Observable<boolean> {
|
#showOCRConfirmationDialog(): Observable<boolean> {
|
||||||
@ -338,7 +388,7 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#openImportRedactionsDialog() {
|
#openImportRedactionsDialog() {
|
||||||
this._dialogService.openDialog('importRedactions', { dossierId: this.file.dossierId, fileId: this.file.fileId });
|
this._dialogService.openDialog('importRedactions', { dossierId: this.file().dossierId, fileId: this.file().fileId });
|
||||||
}
|
}
|
||||||
|
|
||||||
#openDeleteFileDialog() {
|
#openDeleteFileDialog() {
|
||||||
@ -351,8 +401,8 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
async () => {
|
async () => {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
try {
|
try {
|
||||||
const dossier = this._activeDossiersService.find(this.file.dossierId);
|
const dossier = this._activeDossiersService.find(this.file().dossierId);
|
||||||
await firstValueFrom(this._fileManagementService.delete([this.file], this.file.dossierId));
|
await firstValueFrom(this._fileManagementService.delete([this.file()], this.file().dossierId));
|
||||||
await this._injector.get(Router).navigate([dossier.routerLink]);
|
await this._injector.get(Router).navigate([dossier.routerLink]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this._injector.get(Toaster).error(_('error.http.generic'), { params: error });
|
this._injector.get(Toaster).error(_('error.http.generic'), { params: error });
|
||||||
@ -363,8 +413,8 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#assign() {
|
#assign() {
|
||||||
const files = [this.file];
|
const files = [this.file()];
|
||||||
const targetStatus = this.file.workflowStatus;
|
const targetStatus = this.file().workflowStatus;
|
||||||
const withCurrentUserAsDefault = true;
|
const withCurrentUserAsDefault = true;
|
||||||
const withUnassignedOption = true;
|
const withUnassignedOption = true;
|
||||||
this._iqserDialog.openDefault(AssignReviewerApproverDialogComponent, {
|
this._iqserDialog.openDefault(AssignReviewerApproverDialogComponent, {
|
||||||
@ -378,29 +428,34 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async #assignToMe() {
|
async #assignToMe() {
|
||||||
await this._fileAssignService.assignToMe([this.file]);
|
await this._fileAssignService.assignToMe([this.file()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #reanalyseFile() {
|
async #reanalyseFile() {
|
||||||
|
const rules = await firstValueFrom(this._rulesService.getFor(this.dossier().dossierTemplateId));
|
||||||
|
if (rules.timeoutDetected) {
|
||||||
|
this._toasterService.error(_('dossier-listing.rules.timeoutError'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const params: ReanalyzeQueryParams = {
|
const params: ReanalyzeQueryParams = {
|
||||||
force: true,
|
force: true,
|
||||||
triggeredByUser: true,
|
triggeredByUser: true,
|
||||||
};
|
};
|
||||||
await this._reanalysisService.reanalyzeFilesForDossier([this.file], this.file.dossierId, params);
|
await this._reanalysisService.reanalyzeFilesForDossier([this.file()], this.file().dossierId, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #toggleAutomaticAnalysis() {
|
async #toggleAutomaticAnalysis() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
await firstValueFrom(this._reanalysisService.toggleAutomaticAnalysis(this.file.dossierId, [this.file]));
|
await firstValueFrom(this._reanalysisService.toggleAutomaticAnalysis(this.file().dossierId, [this.file()]));
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
async #setFileUnderApproval() {
|
async #setFileUnderApproval() {
|
||||||
await this._fileAssignService.assignApprover(this.file, true);
|
await this._fileAssignService.assignApprover(this.file(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #ocrFile() {
|
async #ocrFile() {
|
||||||
if (this.file.lastManualChangeDate) {
|
if (this.file().lastManualChangeDate) {
|
||||||
const confirm = await firstValueFrom(this.#showOCRConfirmationDialog());
|
const confirm = await firstValueFrom(this.#showOCRConfirmationDialog());
|
||||||
if (!confirm) {
|
if (!confirm) {
|
||||||
return;
|
return;
|
||||||
@ -413,93 +468,47 @@ export class FileActionsComponent implements OnChanges {
|
|||||||
viewerHeaderService.disableRotationButtons();
|
viewerHeaderService.disableRotationButtons();
|
||||||
|
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
await this._reanalysisService.ocrFiles([this.file], this.file.dossierId);
|
await this._reanalysisService.ocrFiles([this.file()], this.file().dossierId);
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
async #setFileUnderReview() {
|
async #setFileUnderReview() {
|
||||||
await this._fileAssignService.assignReviewer(this.file, true);
|
await this._fileAssignService.assignReviewer(this.file(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
async #toggleAnalysis() {
|
async #toggleAnalysis() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
await this._reanalysisService.toggleAnalysis(this.file.dossierId, [this.file], !this.file.excluded);
|
await this._reanalysisService.toggleAnalysis(this.file().dossierId, [this.file()], !this.file().excluded);
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup() {
|
|
||||||
this.isDossierOverviewList = this.type === 'dossier-overview-list';
|
|
||||||
this.isDossierOverviewWorkflow = this.type === 'dossier-overview-workflow';
|
|
||||||
this.isDossierOverview = this.type.startsWith('dossier-overview');
|
|
||||||
this.isFilePreview = this.type === 'file-preview';
|
|
||||||
|
|
||||||
this.assignTooltip = this.file.isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
|
|
||||||
this.showAssign =
|
|
||||||
(this._permissionsService.canAssignUser(this.file, this.dossier) ||
|
|
||||||
this._permissionsService.canUnassignUser(this.file, this.dossier)) &&
|
|
||||||
this.isDossierOverview;
|
|
||||||
|
|
||||||
this.showAssignToSelf = this._permissionsService.canAssignToSelf(this.file, this.dossier) && this.isDossierOverview;
|
|
||||||
this.showImportRedactions = this._permissionsService.canImportRedactions(this.file, this.dossier);
|
|
||||||
|
|
||||||
this.showSetToNew = this._permissionsService.canSetToNew(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
|
||||||
this.showUndoApproval = this._permissionsService.canUndoApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
|
||||||
this.showUnderReview = this._permissionsService.canSetUnderReview(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
|
||||||
this.showUnderApproval = this._permissionsService.canSetUnderApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
|
||||||
this.showApprove = this._permissionsService.isReadyForApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
|
|
||||||
|
|
||||||
this.canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.file, this.dossier);
|
|
||||||
this.showToggleAnalysis = !!this.file.lastProcessed && this._permissionsService.showToggleAnalysis(this.dossier);
|
|
||||||
this.toggleTooltip = this._toggleTooltip;
|
|
||||||
this.isDossierMember = this._permissionsService.isDossierMember(this.dossier);
|
|
||||||
|
|
||||||
this.showDelete = this._permissionsService.canSoftDeleteFile(this.file, this.dossier);
|
|
||||||
this.showOCR = this._permissionsService.canOcrFile(this.file, this.dossier);
|
|
||||||
this.canReanalyse = this._permissionsService.canReanalyseFile(this.file, this.dossier);
|
|
||||||
this.canDisableAutoAnalysis = !this.#isDocumine && this._permissionsService.canDisableAutoAnalysis([this.file], this.dossier);
|
|
||||||
this.canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis([this.file], this.dossier);
|
|
||||||
|
|
||||||
this.showStatusBar = !this.file.isError && !this.file.isUnprocessed && this.isDossierOverviewList;
|
|
||||||
|
|
||||||
const showReanalyse =
|
|
||||||
(this.canReanalyse || this.file.excludedFromAutomaticAnalysis || this.analysisForced) && !this.file.dossierArchived;
|
|
||||||
|
|
||||||
this.showReanalyseFilePreview = showReanalyse && this.isFilePreview && !this.file.isApproved && this.isDossierMember;
|
|
||||||
this.showReanalyseDossierOverview = showReanalyse && this.isDossierOverview && !this.file.isApproved && this.isDossierMember;
|
|
||||||
|
|
||||||
this.showDownload = this._permissionsService.canDownloadRedactedFile() && !!this.file.lastProcessed && this.isDossierMember;
|
|
||||||
this.buttons = this._buttons;
|
|
||||||
|
|
||||||
this._changeRef.markForCheck();
|
|
||||||
}
|
|
||||||
|
|
||||||
async #setFileApproved() {
|
async #setFileApproved() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
await this._filesService.setApproved(this.file);
|
await this._filesService.setApproved(this.file());
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
async #setToNew() {
|
async #setToNew() {
|
||||||
this._loadingService.start();
|
this._loadingService.start();
|
||||||
await this._filesService.setToNew(this.file);
|
await this._filesService.setToNew(this.file());
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
#toggleExcludePages() {
|
#toggleExcludePages() {
|
||||||
this._excludedPagesService.toggle();
|
this._excludedPagesService.toggle();
|
||||||
const shown = this._excludedPagesService.shown();
|
const shown = this._excludedPagesService.shown();
|
||||||
setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', shown);
|
setLocalStorageDataByFileId(this.file().id, 'show-exclude-pages', shown);
|
||||||
if (shown) {
|
if (shown) {
|
||||||
setLocalStorageDataByFileId(this.file.id, 'show-document-info', false);
|
setLocalStorageDataByFileId(this.file().id, 'show-document-info', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#toggleDocumentInfo() {
|
#toggleDocumentInfo() {
|
||||||
this._documentInfoService.toggle();
|
this._documentInfoService.toggle();
|
||||||
const shown = this._documentInfoService.shown();
|
const shown = this._documentInfoService.shown();
|
||||||
setLocalStorageDataByFileId(this.file.id, 'show-document-info', shown);
|
setLocalStorageDataByFileId(this.file().id, 'show-document-info', shown);
|
||||||
if (shown) {
|
if (shown) {
|
||||||
setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', false);
|
setLocalStorageDataByFileId(this.file().id, 'show-exclude-pages', false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,6 +1,6 @@
|
|||||||
@if (dropdownButton()) {
|
@if (dropdownButton()) {
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(click)="$event.stopImmediatePropagation()"
|
(click)="stopImmediatePropagation($event)"
|
||||||
[matMenuTriggerFor]="downloadMenu"
|
[matMenuTriggerFor]="downloadMenu"
|
||||||
[tooltipClass]="tooltipClass()"
|
[tooltipClass]="tooltipClass()"
|
||||||
[tooltipPosition]="tooltipPosition()"
|
[tooltipPosition]="tooltipPosition()"
|
||||||
|
|||||||
@ -28,6 +28,7 @@ export class FileDownloadBtnComponent implements OnChanges {
|
|||||||
readonly singleFileDownload = input<boolean>(false);
|
readonly singleFileDownload = input<boolean>(false);
|
||||||
readonly dossierDownload = input(false, { transform: booleanAttribute });
|
readonly dossierDownload = input(false, { transform: booleanAttribute });
|
||||||
readonly dropdownButton = computed(() => this.isDocumine && (this.dossierDownload() || this.singleFileDownload()));
|
readonly dropdownButton = computed(() => this.isDocumine && (this.dossierDownload() || this.singleFileDownload()));
|
||||||
|
readonly stopMenuImmediatePropagation = input(false);
|
||||||
tooltip: string;
|
tooltip: string;
|
||||||
canDownloadFiles: boolean;
|
canDownloadFiles: boolean;
|
||||||
invalidDownload = false;
|
invalidDownload = false;
|
||||||
@ -96,4 +97,10 @@ export class FileDownloadBtnComponent implements OnChanges {
|
|||||||
const fileToDownload = !this.dossierDownload() ? this.files()[0] : null;
|
const fileToDownload = !this.dossierDownload() ? this.files()[0] : null;
|
||||||
return firstValueFrom(this._componentLogService.exportXML(this.dossier().dossierTemplateId, this.dossier().id, fileToDownload));
|
return firstValueFrom(this._componentLogService.exportXML(this.dossier().dossierTemplateId, this.dossier().id, fileToDownload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stopImmediatePropagation($event: MouseEvent) {
|
||||||
|
if (!this.stopMenuImmediatePropagation()) {
|
||||||
|
$event.stopImmediatePropagation();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,17 +1,16 @@
|
|||||||
import { GenericService, LAST_CHECKED_OFFSET, QueryParam, ROOT_CHANGES_KEY } from '@iqser/common-ui';
|
import { GenericService, ROOT_CHANGES_KEY } from '@iqser/common-ui';
|
||||||
import { Dossier, DossierStats, IDossierChanges } from '@red/domain';
|
import { Dossier, IChangesDetails, IDossierChanges } 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 {
|
||||||
@ -19,40 +18,40 @@ export class DossiersChangesService extends GenericService<Dossier> implements O
|
|||||||
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';
|
protected readonly _defaultModelPath = 'dossier';
|
||||||
|
|
||||||
loadOnlyChanged(): Observable<IDossierChanges> {
|
loadOnlyChanged(): Observable<IChangesDetails> {
|
||||||
const removeIfNotFound = (id: string) =>
|
const load = (changes: IChangesDetails) => this.#load(this.#mapDossierChanges(changes.dossierChanges));
|
||||||
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));
|
||||||
|
const dossierIds = this.#filterDossierIds(Array.from(dossierStatsToLoad));
|
||||||
|
return this.#dossierStatsService.getFor(dossierIds);
|
||||||
|
};
|
||||||
|
|
||||||
return this.hasChangesDetails$().pipe(
|
return this.hasChangesDetails$().pipe(
|
||||||
tap(changes => this.#logger.info('[DOSSIERS_CHANGES] Found changes', changes)),
|
tap(changes => console.log('[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().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,18 +74,37 @@ 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;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#filterDossierIds(ids: string[]) {
|
||||||
|
return ids.filter(id => this.#dashboardStatsService.all.find(stats => stats.dossiersInTemplate.includes(id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#mapDossierChanges(dossierChanges: IDossierChanges | string[]): string[] {
|
||||||
|
const dossierIds = dossierChanges.map(change => change.dossierId);
|
||||||
|
return this.#filterDossierIds(dossierIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import { inject, Injectable } from '@angular/core';
|
import { inject, Injectable } from '@angular/core';
|
||||||
import { StatsService } from '@iqser/common-ui';
|
import { StatsService } from '@iqser/common-ui';
|
||||||
import { DOSSIER_ID, DossierStats, IDossierStats } from '@red/domain';
|
import { DashboardStats, DOSSIER_ID, DossierStats, IDossierStats } from '@red/domain';
|
||||||
import { Observable, of } from 'rxjs';
|
import { Observable, of } from 'rxjs';
|
||||||
import { UserService } from '@users/user.service';
|
import { UserService } from '@users/user.service';
|
||||||
import { NGXLogger } from 'ngx-logger';
|
import { NGXLogger } from 'ngx-logger';
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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,6 +27,32 @@ 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) {
|
||||||
const files$ = this.getFor(dossierId).pipe(
|
const files$ = this.getFor(dossierId).pipe(
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { inject, Injectable, OnDestroy } from '@angular/core';
|
import { inject, Injectable, OnDestroy } from '@angular/core';
|
||||||
import { EntitiesService, getConfig, QueryParam } from '@iqser/common-ui';
|
import { EntitiesService, getConfig, QueryParam } from '@iqser/common-ui';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { EMPTY, firstValueFrom, iif, merge, Observable, of, Subscription, timer } from 'rxjs';
|
import { EMPTY, firstValueFrom, merge, Observable, of, Subscription, timer } from 'rxjs';
|
||||||
import { AppConfig, Dossier, INotification, Notification, NotificationTypes } from '@red/domain';
|
import { AppConfig, Dossier, INotification, Notification, NotificationTypes } from '@red/domain';
|
||||||
import { map, switchMap, tap } from 'rxjs/operators';
|
import { map, switchMap, tap } from 'rxjs/operators';
|
||||||
import { notificationsTranslations } from '@translations/notifications-translations';
|
import { notificationsTranslations } from '@translations/notifications-translations';
|
||||||
@ -141,6 +141,14 @@ export class NotificationsService extends EntitiesService<INotification, Notific
|
|||||||
}
|
}
|
||||||
|
|
||||||
#loadNotificationsIfChanged(): Observable<Notification[]> {
|
#loadNotificationsIfChanged(): Observable<Notification[]> {
|
||||||
return this.hasChanges$().pipe(switchMap(changed => iif(() => changed, this.loadAll(), EMPTY)));
|
return this.hasChanges$().pipe(
|
||||||
|
switchMap(changed => {
|
||||||
|
if (changed) {
|
||||||
|
return this.loadAll();
|
||||||
|
} else {
|
||||||
|
return EMPTY;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -473,7 +473,7 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#canAssignToSelf(file: File, dossier: Dossier): boolean {
|
#canAssignToSelf(file: File, dossier: Dossier): boolean {
|
||||||
const precondition = this.#fileIsOk(file, dossier) && !this.isFileAssignee(file);
|
const precondition = (this.#fileIsOk(file, dossier) || file.isError) && !this.isFileAssignee(file);
|
||||||
return precondition && (this.isApprover(dossier) || (this.isDossierMember(dossier) && (file.isNew || file.isUnderReview)));
|
return precondition && (this.isApprover(dossier) || (this.isDossierMember(dossier) && (file.isNew || file.isUnderReview)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +500,7 @@ export class PermissionsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#canAssignReviewer(file: File, dossier: Dossier) {
|
#canAssignReviewer(file: File, dossier: Dossier) {
|
||||||
const fileStatesForReviewer = file.isNew || file.isUnderReview || file.isUnderApproval;
|
const fileStatesForReviewer = file.isNew || file.isUnderReview || file.isUnderApproval || file.isApproved;
|
||||||
return fileStatesForReviewer && this.isDossierMember(dossier);
|
return fileStatesForReviewer && this.isDossierMember(dossier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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',
|
||||||
@ -21,6 +22,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({
|
||||||
@ -169,4 +171,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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { ITrackable } from '@iqser/common-ui';
|
import { ITrackable } from '@iqser/common-ui';
|
||||||
import type { List } from '@iqser/common-ui/lib/utils';
|
import type { IqserEventTarget, List } from '@iqser/common-ui/lib/utils';
|
||||||
import type { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
import type { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||||
import { Dayjs } from 'dayjs';
|
import { Dayjs } from 'dayjs';
|
||||||
|
|
||||||
@ -143,3 +143,11 @@ export function urlFileId() {
|
|||||||
const fileId = splitUrl[splitUrl.length - 1];
|
const fileId = splitUrl[splitUrl.length - 1];
|
||||||
return fileId.split('?')[0];
|
return fileId.split('?')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isTargetInput(event: Event) {
|
||||||
|
return (event?.target as IqserEventTarget)?.localName === 'input';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isTargetTextArea(event: Event) {
|
||||||
|
return (event?.target as IqserEventTarget)?.localName === 'textarea';
|
||||||
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"ADMIN_CONTACT_NAME": null,
|
"ADMIN_CONTACT_NAME": null,
|
||||||
"ADMIN_CONTACT_URL": null,
|
"ADMIN_CONTACT_URL": null,
|
||||||
"API_URL": "https://dan2.iqser.cloud",
|
"API_URL": "https://frontend2.iqser.cloud",
|
||||||
"APP_NAME": "RedactManager",
|
"APP_NAME": "RedactManager",
|
||||||
"IS_DOCUMINE": false,
|
"IS_DOCUMINE": true,
|
||||||
"RULE_EDITOR_DEV_ONLY": false,
|
"RULE_EDITOR_DEV_ONLY": false,
|
||||||
"AUTO_READ_TIME": 3,
|
"AUTO_READ_TIME": 3,
|
||||||
"BACKEND_APP_VERSION": "4.4.40",
|
"BACKEND_APP_VERSION": "4.4.40",
|
||||||
@ -13,13 +13,13 @@
|
|||||||
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
"MAX_RETRIES_ON_SERVER_ERROR": 3,
|
||||||
"OAUTH_CLIENT_ID": "redaction",
|
"OAUTH_CLIENT_ID": "redaction",
|
||||||
"OAUTH_IDP_HINT": null,
|
"OAUTH_IDP_HINT": null,
|
||||||
"OAUTH_URL": "https://dan2.iqser.cloud/auth",
|
"OAUTH_URL": "https://frontend2.iqser.cloud/auth",
|
||||||
"RECENT_PERIOD_IN_HOURS": 24,
|
"RECENT_PERIOD_IN_HOURS": 24,
|
||||||
"SELECTION_MODE": "structural",
|
"SELECTION_MODE": "structural",
|
||||||
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
|
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview",
|
||||||
"ANNOTATIONS_THRESHOLD": 1000,
|
"ANNOTATIONS_THRESHOLD": 1000,
|
||||||
"THEME": "redact",
|
"THEME": "scm",
|
||||||
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/redact/",
|
"BASE_TRANSLATIONS_DIRECTORY": "/assets/i18n/scm/",
|
||||||
"AVAILABLE_NOTIFICATIONS_DAYS": 30,
|
"AVAILABLE_NOTIFICATIONS_DAYS": 30,
|
||||||
"AVAILABLE_OLD_NOTIFICATIONS_MINUTES": 60,
|
"AVAILABLE_OLD_NOTIFICATIONS_MINUTES": 60,
|
||||||
"NOTIFICATIONS_THRESHOLD": 1000,
|
"NOTIFICATIONS_THRESHOLD": 1000,
|
||||||
|
|||||||
@ -520,6 +520,11 @@
|
|||||||
"documentKey": "dossier_stop_analysis",
|
"documentKey": "dossier_stop_analysis",
|
||||||
"scrollableParentView": "VIRTUAL_SCROLL"
|
"scrollableParentView": "VIRTUAL_SCROLL"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"elementKey": "dossier_analyze_file",
|
||||||
|
"documentKey": "analyze_file",
|
||||||
|
"scrollableParentView": "VIRTUAL_SCROLL"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"elementKey": "dossier_automatic_text_recognition",
|
"elementKey": "dossier_automatic_text_recognition",
|
||||||
"documentKey": "dossier_automatic_text_recognition",
|
"documentKey": "dossier_automatic_text_recognition",
|
||||||
@ -569,7 +574,6 @@
|
|||||||
"elementKey": "workload_page_list",
|
"elementKey": "workload_page_list",
|
||||||
"documentKey": "workload_page_list"
|
"documentKey": "workload_page_list"
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
"elementKey": "editor_delete_file",
|
"elementKey": "editor_delete_file",
|
||||||
"documentKey": "editor_delete_file"
|
"documentKey": "editor_delete_file"
|
||||||
@ -735,10 +739,6 @@
|
|||||||
"elementKey": "components_table",
|
"elementKey": "components_table",
|
||||||
"documentKey": "components_table"
|
"documentKey": "components_table"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"elementKey": "components_table",
|
|
||||||
"documentKey": "components_table"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"elementKey": "remove_annotation_DIALOG",
|
"elementKey": "remove_annotation_DIALOG",
|
||||||
"documentKey": "remove_annotation"
|
"documentKey": "remove_annotation"
|
||||||
|
|||||||
@ -273,9 +273,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"
|
||||||
@ -331,14 +328,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"
|
||||||
@ -351,15 +348,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"
|
||||||
},
|
},
|
||||||
@ -393,6 +390,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": {
|
||||||
@ -587,8 +587,7 @@
|
|||||||
"success": {
|
"success": {
|
||||||
"generic": ""
|
"generic": ""
|
||||||
},
|
},
|
||||||
"title": "",
|
"title": ""
|
||||||
"warning-text": ""
|
|
||||||
},
|
},
|
||||||
"configurations": "Konfiguration",
|
"configurations": "Konfiguration",
|
||||||
"confirm-archive-dossier": {
|
"confirm-archive-dossier": {
|
||||||
@ -637,18 +636,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": {
|
||||||
@ -657,6 +652,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?",
|
||||||
@ -934,6 +933,9 @@
|
|||||||
"reanalyse": {
|
"reanalyse": {
|
||||||
"action": "Ganzes Dossier analysieren"
|
"action": "Ganzes Dossier analysieren"
|
||||||
},
|
},
|
||||||
|
"rules": {
|
||||||
|
"timeoutError": "Regeln für Dossier-Vorlagen gesperrt!"
|
||||||
|
},
|
||||||
"stats": {
|
"stats": {
|
||||||
"analyzed-pages": "{count, plural, one{Seite} other{Seiten}}",
|
"analyzed-pages": "{count, plural, one{Seite} other{Seiten}}",
|
||||||
"total-people": "Benutzer"
|
"total-people": "Benutzer"
|
||||||
@ -990,7 +992,7 @@
|
|||||||
"download-file-disabled": "Download: Sie müssen Genehmiger im Dossier sein und die initiale Verarbeitung {count, plural, one{der Datei} other{der Dateien}} muss abgeschlossen sein.",
|
"download-file-disabled": "Download: Sie müssen Genehmiger im Dossier sein und die initiale Verarbeitung {count, plural, one{der Datei} other{der Dateien}} muss abgeschlossen sein.",
|
||||||
"file-listing": {
|
"file-listing": {
|
||||||
"file-entry": {
|
"file-entry": {
|
||||||
"file-error": "Reanalyse erforderlich",
|
"file-error": "Reanalyse erforderlich {errorCode, select, RULES_EXECUTION_TIMEOUT{(Zeitlimit für Regeln)} other{}}",
|
||||||
"file-pending": "Ausstehend ..."
|
"file-pending": "Ausstehend ..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1026,13 +1028,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"
|
||||||
|
},
|
||||||
"report-download": "",
|
"report-download": "",
|
||||||
"start-auto-analysis": "Auto-Analyse aktivieren",
|
"start-auto-analysis": "Auto-Analyse aktivieren",
|
||||||
"stop-auto-analysis": "Auto-Analyse anhalten",
|
"stop-auto-analysis": "Auto-Analyse anhalten",
|
||||||
@ -1066,8 +1068,7 @@
|
|||||||
"dossier-states": "{count, plural, one{Dossier-Status} other{Dossier-Status}}"
|
"dossier-states": "{count, plural, one{Dossier-Status} other{Dossier-Status}}"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"conflict": "Es gibt bereits einen Dossier-Status mit diesem Namen.",
|
"conflict": "Es gibt bereits einen Dossier-Status mit diesem Namen."
|
||||||
"generic": "Speichern des Dossier-Status fehlgeschlagen."
|
|
||||||
},
|
},
|
||||||
"no-data": {
|
"no-data": {
|
||||||
"title": "Es wurde noch kein Dossier-Status angelegt."
|
"title": "Es wurde noch kein Dossier-Status angelegt."
|
||||||
@ -1091,6 +1092,12 @@
|
|||||||
"entities": "{count} {count, plural, one{Entität} other{Entitäten}}",
|
"entities": "{count} {count, plural, one{Entität} other{Entitäten}}",
|
||||||
"entries": "{count} {count, plural, one{Eintrag} other{Einträge}}",
|
"entries": "{count} {count, plural, one{Eintrag} other{Einträge}}",
|
||||||
"modified-on": "Geändert am: {date}",
|
"modified-on": "Geändert am: {date}",
|
||||||
|
"rules-reset": {
|
||||||
|
"disabled-action": "Bitte wenden Sie sich an Ihren Administrator, um die Regeln freizuschalten.",
|
||||||
|
"label": "Regeln gesperrt",
|
||||||
|
"success": "Die Regeln der Dossier-Vorlage wurden erfolgreich zurückgesetzt.",
|
||||||
|
"tooltip": "Klicken Sie hier, um die Regeln zurückzusetzen"
|
||||||
|
},
|
||||||
"title": "Dossier-Vorlage bearbeiten",
|
"title": "Dossier-Vorlage bearbeiten",
|
||||||
"valid-from": "Gültig ab: {date}",
|
"valid-from": "Gültig ab: {date}",
|
||||||
"valid-to": "Gültig bis: {Datum}"
|
"valid-to": "Gültig bis: {Datum}"
|
||||||
@ -1103,14 +1110,6 @@
|
|||||||
"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",
|
||||||
@ -1145,6 +1144,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.",
|
||||||
@ -1340,15 +1347,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."
|
||||||
@ -1360,22 +1358,30 @@
|
|||||||
"generic": "Die Entitätsregeln wurden aktualisiert."
|
"generic": "Die Entitätsregeln wurden aktualisiert."
|
||||||
},
|
},
|
||||||
"title": "Entitätsregeln-Editor",
|
"title": "Entitätsregeln-Editor",
|
||||||
"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": {
|
||||||
@ -1393,12 +1399,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",
|
||||||
@ -1409,6 +1409,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": {
|
||||||
@ -1453,7 +1459,7 @@
|
|||||||
"save": {
|
"save": {
|
||||||
"error": "Erstellung der Datei-Attribute fehlgeschlagen.",
|
"error": "Erstellung der Datei-Attribute fehlgeschlagen.",
|
||||||
"label": "Attribute speichern",
|
"label": "Attribute speichern",
|
||||||
"success": "{count} Datei-{count, plural, one{Attribut} other{Attribute}} erfolgreich erstellt!"
|
"success": "{count} Datei-{count, plural, one{Attribut} other{Attribute}} erfolgreich erstellt."
|
||||||
},
|
},
|
||||||
"search": {
|
"search": {
|
||||||
"placeholder": "Nach Spaltennamen suchen..."
|
"placeholder": "Nach Spaltennamen suchen..."
|
||||||
@ -1626,15 +1632,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",
|
||||||
@ -1644,6 +1641,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",
|
||||||
@ -1922,13 +1928,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",
|
||||||
@ -1942,6 +1941,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",
|
||||||
@ -1959,7 +1959,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",
|
||||||
@ -1967,6 +1966,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",
|
||||||
@ -2049,7 +2055,7 @@
|
|||||||
"auto-expand-filters-on-action": "Filter ausgehend von meinen Aktionen automatisch anpassen",
|
"auto-expand-filters-on-action": "Filter ausgehend von meinen Aktionen automatisch anpassen",
|
||||||
"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",
|
"overwrite-file-option": "",
|
||||||
"table-extraction-type": "Art der Tabellenextraktion"
|
"table-extraction-type": "Art der Tabellenextraktion"
|
||||||
},
|
},
|
||||||
"label": "Präferenzen",
|
"label": "Präferenzen",
|
||||||
@ -2058,16 +2064,17 @@
|
|||||||
"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",
|
||||||
|
"pending-timeout": "Ausstehend (Zeitlimit für Regeln)",
|
||||||
"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": {
|
||||||
@ -2297,18 +2304,12 @@
|
|||||||
"inactive": "Inaktiv",
|
"inactive": "Inaktiv",
|
||||||
"manager-admin": "Manager & Admin",
|
"manager-admin": "Manager & Admin",
|
||||||
"no-role": "Keine Rolle definiert",
|
"no-role": "Keine Rolle definiert",
|
||||||
"red-admin": "Anwendungsadmin",
|
"red-admin": "{count, plural, one{Anwendungsadmin} other{Anwendungsadmins}}",
|
||||||
"red-manager": "Manager",
|
"red-manager": "{count, plural, one{Manager} other{Manager}}",
|
||||||
"red-user": "Benutzer",
|
"red-user": "Benutzer",
|
||||||
"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",
|
||||||
@ -2332,6 +2333,12 @@
|
|||||||
"no-match": "Der Suchbegriff wurde in keinem der Dokumente gefunden.",
|
"no-match": "Der 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": {
|
||||||
@ -2587,4 +2594,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Gestern"
|
"yesterday": "Gestern"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -933,6 +933,9 @@
|
|||||||
"reanalyse": {
|
"reanalyse": {
|
||||||
"action": "Analyze entire dossier"
|
"action": "Analyze entire dossier"
|
||||||
},
|
},
|
||||||
|
"rules": {
|
||||||
|
"timeoutError": "Dossier template rules locked!"
|
||||||
|
},
|
||||||
"stats": {
|
"stats": {
|
||||||
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
||||||
"total-people": "Total users"
|
"total-people": "Total users"
|
||||||
@ -989,7 +992,7 @@
|
|||||||
"download-file-disabled": "To download, ensure you are an approver in the dossier, and the {count, plural, one{file has undergone} other{files have undergone}} initial processing.",
|
"download-file-disabled": "To download, ensure you are an approver in the dossier, and the {count, plural, one{file has undergone} other{files have undergone}} initial processing.",
|
||||||
"file-listing": {
|
"file-listing": {
|
||||||
"file-entry": {
|
"file-entry": {
|
||||||
"file-error": "Re-processing required",
|
"file-error": "Re-processing required {errorCode, select, RULES_EXECUTION_TIMEOUT{(Rules timeout)} other{}}",
|
||||||
"file-pending": "Pending..."
|
"file-pending": "Pending..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1089,6 +1092,12 @@
|
|||||||
"entities": "{count} {count, plural, one{entity} other{entities}}",
|
"entities": "{count} {count, plural, one{entity} other{entities}}",
|
||||||
"entries": "{count} {count, plural, one{entry} other{entries}}",
|
"entries": "{count} {count, plural, one{entry} other{entries}}",
|
||||||
"modified-on": "Modified on: {date}",
|
"modified-on": "Modified on: {date}",
|
||||||
|
"rules-reset": {
|
||||||
|
"disabled-action": "Please contact your administrator to unlock the rules.",
|
||||||
|
"label": "Rules locked",
|
||||||
|
"success": "Dossier template rules successfully reset.",
|
||||||
|
"tooltip": "Click to reset rules"
|
||||||
|
},
|
||||||
"title": "Edit dossier template",
|
"title": "Edit dossier template",
|
||||||
"valid-from": "Valid from: {date}",
|
"valid-from": "Valid from: {date}",
|
||||||
"valid-to": "Valid to: {date}"
|
"valid-to": "Valid to: {date}"
|
||||||
@ -2046,6 +2055,7 @@
|
|||||||
"auto-expand-filters-on-action": "Auto-expand filters on my actions",
|
"auto-expand-filters-on-action": "Auto-expand filters on my actions",
|
||||||
"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",
|
||||||
|
"overwrite-file-option": "Preferred action when re-uploading an already existing file",
|
||||||
"table-extraction-type": "Table extraction type"
|
"table-extraction-type": "Table extraction type"
|
||||||
},
|
},
|
||||||
"label": "Preferences",
|
"label": "Preferences",
|
||||||
@ -2057,6 +2067,7 @@
|
|||||||
"processing-status": {
|
"processing-status": {
|
||||||
"ocr": "OCR",
|
"ocr": "OCR",
|
||||||
"pending": "Pending",
|
"pending": "Pending",
|
||||||
|
"pending-timeout": "Pending (Rules timeout)",
|
||||||
"processed": "Processed",
|
"processed": "Processed",
|
||||||
"processing": "Processing"
|
"processing": "Processing"
|
||||||
},
|
},
|
||||||
@ -2583,4 +2594,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Yesterday"
|
"yesterday": "Yesterday"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -273,9 +273,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"
|
||||||
@ -324,21 +321,21 @@
|
|||||||
"success": "Schwärzung eingefügt!"
|
"success": "Schwärzung eingefügt!"
|
||||||
},
|
},
|
||||||
"recategorize-annotation": {
|
"recategorize-annotation": {
|
||||||
"error": "",
|
"error": "Bearbeiten des Typs fehlgeschlagen: {error}",
|
||||||
"success": ""
|
"success": "Annotation wurde bearbeitet: {changes} geändert."
|
||||||
},
|
},
|
||||||
"recategorize-image": {
|
"recategorize-image": {
|
||||||
"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"
|
||||||
@ -351,15 +348,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"
|
||||||
},
|
},
|
||||||
@ -393,6 +390,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": {
|
||||||
@ -587,8 +587,7 @@
|
|||||||
"success": {
|
"success": {
|
||||||
"generic": "Component rules updated!"
|
"generic": "Component rules updated!"
|
||||||
},
|
},
|
||||||
"title": "Component rule editor",
|
"title": "Component rule editor"
|
||||||
"warning-text": "Warning: experimental feature!"
|
|
||||||
},
|
},
|
||||||
"configurations": "Einstellungen",
|
"configurations": "Einstellungen",
|
||||||
"confirm-archive-dossier": {
|
"confirm-archive-dossier": {
|
||||||
@ -637,18 +636,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": {
|
||||||
@ -657,6 +652,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?",
|
||||||
@ -934,6 +933,9 @@
|
|||||||
"reanalyse": {
|
"reanalyse": {
|
||||||
"action": "Gesamtes Dossier analysieren"
|
"action": "Gesamtes Dossier analysieren"
|
||||||
},
|
},
|
||||||
|
"rules": {
|
||||||
|
"timeoutError": "Regeln für Dossier-Vorlagen gesperrt!"
|
||||||
|
},
|
||||||
"stats": {
|
"stats": {
|
||||||
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
||||||
"total-people": "Anzahl der Benutzer"
|
"total-people": "Anzahl der Benutzer"
|
||||||
@ -990,7 +992,7 @@
|
|||||||
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
||||||
"file-listing": {
|
"file-listing": {
|
||||||
"file-entry": {
|
"file-entry": {
|
||||||
"file-error": "Reanalyse erforderlich",
|
"file-error": "Reanalyse erforderlich {errorCode, select, RULES_EXECUTION_TIMEOUT{(Zeitlimit für Regeln)} other{}}",
|
||||||
"file-pending": "Ausstehend ..."
|
"file-pending": "Ausstehend ..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1026,13 +1028,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"
|
||||||
|
},
|
||||||
"report-download": "Report download",
|
"report-download": "Report download",
|
||||||
"start-auto-analysis": "Enable auto-analysis",
|
"start-auto-analysis": "Enable auto-analysis",
|
||||||
"stop-auto-analysis": "Stop auto-analysis",
|
"stop-auto-analysis": "Stop auto-analysis",
|
||||||
@ -1066,8 +1068,7 @@
|
|||||||
"dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}"
|
"dossier-states": "{count, plural, one{Dossier state} other{Dossier states}}"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"conflict": "Dossier state with this name already exists!",
|
"conflict": "Dossier state with this name already exists!"
|
||||||
"generic": "Failed to save dossier state!"
|
|
||||||
},
|
},
|
||||||
"no-data": {
|
"no-data": {
|
||||||
"title": "There are no dossier states."
|
"title": "There are no dossier states."
|
||||||
@ -1091,6 +1092,12 @@
|
|||||||
"entities": "{count} {count, plural, one{entity} other{entities}}",
|
"entities": "{count} {count, plural, one{entity} other{entities}}",
|
||||||
"entries": "{count} {count, plural, one{entry} other{entries}}",
|
"entries": "{count} {count, plural, one{entry} other{entries}}",
|
||||||
"modified-on": "Modified on: {date}",
|
"modified-on": "Modified on: {date}",
|
||||||
|
"rules-reset": {
|
||||||
|
"disabled-action": "Bitte wenden Sie sich an Ihren Administrator, um die Regeln freizuschalten.",
|
||||||
|
"label": "Regeln gesperrt",
|
||||||
|
"success": "Die Regeln der Dossier-Vorlage wurden erfolgreich zurückgesetzt.",
|
||||||
|
"tooltip": "Klicken Sie hier, um die Regeln zurückzusetzen"
|
||||||
|
},
|
||||||
"title": "Edit dossier template",
|
"title": "Edit dossier template",
|
||||||
"valid-from": "Valid from: {date}",
|
"valid-from": "Valid from: {date}",
|
||||||
"valid-to": "Valid to: {date}"
|
"valid-to": "Valid to: {date}"
|
||||||
@ -1103,14 +1110,6 @@
|
|||||||
"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",
|
||||||
@ -1145,6 +1144,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.",
|
||||||
@ -1340,15 +1347,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!"
|
||||||
@ -1360,22 +1358,30 @@
|
|||||||
"generic": "Entity rules updated!"
|
"generic": "Entity rules updated!"
|
||||||
},
|
},
|
||||||
"title": "Entity rule editor",
|
"title": "Entity rule editor",
|
||||||
"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": {
|
||||||
@ -1393,12 +1399,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",
|
||||||
@ -1409,6 +1409,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": {
|
||||||
@ -1626,15 +1632,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",
|
||||||
@ -1644,6 +1641,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",
|
||||||
@ -1922,13 +1928,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",
|
||||||
@ -1942,6 +1941,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",
|
||||||
@ -1959,7 +1959,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",
|
||||||
@ -1967,6 +1966,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",
|
||||||
@ -2049,7 +2055,7 @@
|
|||||||
"auto-expand-filters-on-action": "Auto expand filters on my actions",
|
"auto-expand-filters-on-action": "Auto expand filters on my actions",
|
||||||
"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",
|
"overwrite-file-option": "",
|
||||||
"table-extraction-type": "Table extraction type"
|
"table-extraction-type": "Table extraction type"
|
||||||
},
|
},
|
||||||
"label": "Preferences",
|
"label": "Preferences",
|
||||||
@ -2058,16 +2064,17 @@
|
|||||||
"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-status": {
|
||||||
|
"ocr": "OCR",
|
||||||
|
"pending": "Ausstehend",
|
||||||
|
"pending-timeout": "Ausstehend (Zeitlimit für Regeln)",
|
||||||
|
"processed": "Verarbeitet",
|
||||||
|
"processing": "Verarbeitung läuft"
|
||||||
|
},
|
||||||
"processing": {
|
"processing": {
|
||||||
"basic": "Processing",
|
"basic": "Processing",
|
||||||
"ocr": "OCR"
|
"ocr": "OCR"
|
||||||
},
|
},
|
||||||
"processing-status": {
|
|
||||||
"ocr": "OCR",
|
|
||||||
"pending": "Pending",
|
|
||||||
"processed": "Processed",
|
|
||||||
"processing": "Processing"
|
|
||||||
},
|
|
||||||
"readonly": "Lesemodus",
|
"readonly": "Lesemodus",
|
||||||
"readonly-archived": "Read only (archived)",
|
"readonly-archived": "Read only (archived)",
|
||||||
"redact-text": {
|
"redact-text": {
|
||||||
@ -2220,7 +2227,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"invalid-upload": "Ungültiges Upload-Format ausgewählt! Unterstützt werden Dokumente im .xlsx- und im .docx-Format",
|
"invalid-upload": "Ungültiges Upload-Format ausgewählt. Unterstützte Formate: .xlsx- und .docx",
|
||||||
"multi-file-report": "(Mehrere Dateien)",
|
"multi-file-report": "(Mehrere Dateien)",
|
||||||
"report-documents": "Dokumente für den Bericht",
|
"report-documents": "Dokumente für den Bericht",
|
||||||
"setup": "Click the upload button on the right to upload your component report templates.",
|
"setup": "Click the upload button on the right to upload your component report templates.",
|
||||||
@ -2303,12 +2310,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",
|
||||||
@ -2332,6 +2333,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": {
|
||||||
@ -2587,4 +2594,4 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"yesterday": "Gestern"
|
"yesterday": "Gestern"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -321,8 +321,8 @@
|
|||||||
"success": "Annotation added!"
|
"success": "Annotation added!"
|
||||||
},
|
},
|
||||||
"recategorize-annotation": {
|
"recategorize-annotation": {
|
||||||
"error": "",
|
"error": "Failed to edit type: {error}",
|
||||||
"success": ""
|
"success": "Annotation was edited: Changed {changes}."
|
||||||
},
|
},
|
||||||
"recategorize-image": {
|
"recategorize-image": {
|
||||||
"error": "Failed to recategorize image: {error}",
|
"error": "Failed to recategorize image: {error}",
|
||||||
@ -933,6 +933,9 @@
|
|||||||
"reanalyse": {
|
"reanalyse": {
|
||||||
"action": "Analyze entire dossier"
|
"action": "Analyze entire dossier"
|
||||||
},
|
},
|
||||||
|
"rules": {
|
||||||
|
"timeoutError": "Dossier template rules locked!"
|
||||||
|
},
|
||||||
"stats": {
|
"stats": {
|
||||||
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
||||||
"total-people": "Total users"
|
"total-people": "Total users"
|
||||||
@ -989,7 +992,7 @@
|
|||||||
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
||||||
"file-listing": {
|
"file-listing": {
|
||||||
"file-entry": {
|
"file-entry": {
|
||||||
"file-error": "Re-processing required",
|
"file-error": "Re-processing required {errorCode, select, RULES_EXECUTION_TIMEOUT{(Rules timeout)} other{}}",
|
||||||
"file-pending": "Pending..."
|
"file-pending": "Pending..."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1089,6 +1092,12 @@
|
|||||||
"entities": "{count} {count, plural, one{entity} other{entities}}",
|
"entities": "{count} {count, plural, one{entity} other{entities}}",
|
||||||
"entries": "{count} {count, plural, one{entry} other{entries}}",
|
"entries": "{count} {count, plural, one{entry} other{entries}}",
|
||||||
"modified-on": "Modified on: {date}",
|
"modified-on": "Modified on: {date}",
|
||||||
|
"rules-reset": {
|
||||||
|
"disabled-action": "Please contact your administrator to unlock the rules.",
|
||||||
|
"label": "Rules locked",
|
||||||
|
"success": "Dossier template rules successfully reset.",
|
||||||
|
"tooltip": "Click to reset rules"
|
||||||
|
},
|
||||||
"title": "Edit dossier template",
|
"title": "Edit dossier template",
|
||||||
"valid-from": "Valid from: {date}",
|
"valid-from": "Valid from: {date}",
|
||||||
"valid-to": "Valid to: {date}"
|
"valid-to": "Valid to: {date}"
|
||||||
@ -1531,7 +1540,7 @@
|
|||||||
},
|
},
|
||||||
"last-assignee": "Last assignee",
|
"last-assignee": "Last assignee",
|
||||||
"no-data": {
|
"no-data": {
|
||||||
"title": "There are no annotations on this page."
|
"title": "This page does not contain annotations for the selected component or filter."
|
||||||
},
|
},
|
||||||
"quick-nav": {
|
"quick-nav": {
|
||||||
"jump-first": "Jump to first page",
|
"jump-first": "Jump to first page",
|
||||||
@ -1548,7 +1557,7 @@
|
|||||||
"jump-to-next": "Jump to next",
|
"jump-to-next": "Jump to next",
|
||||||
"jump-to-previous": "Jump to previous",
|
"jump-to-previous": "Jump to previous",
|
||||||
"label": "Workload",
|
"label": "Workload",
|
||||||
"no-annotations": "There are no annotations on the selected page or for the selected component.",
|
"no-annotations": "There are no annotations for the selected component.",
|
||||||
"page-is": "This page is",
|
"page-is": "This page is",
|
||||||
"reset": "reset",
|
"reset": "reset",
|
||||||
"select": "Select",
|
"select": "Select",
|
||||||
@ -1556,7 +1565,7 @@
|
|||||||
"select-none": "None",
|
"select-none": "None",
|
||||||
"show-skipped": "Show skipped in document",
|
"show-skipped": "Show skipped in document",
|
||||||
"the-filters": "the filters",
|
"the-filters": "the filters",
|
||||||
"wrong-filters": "The selected filter combination is not possible. Please adjust or"
|
"wrong-filters": "No annotations for the selected filter combination. Please adjust or"
|
||||||
},
|
},
|
||||||
"document-info": {
|
"document-info": {
|
||||||
"close": "Close document info",
|
"close": "Close document info",
|
||||||
@ -2046,6 +2055,7 @@
|
|||||||
"auto-expand-filters-on-action": "Auto expand filters on my actions",
|
"auto-expand-filters-on-action": "Auto expand filters on my actions",
|
||||||
"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",
|
||||||
|
"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",
|
||||||
@ -2057,6 +2067,7 @@
|
|||||||
"processing-status": {
|
"processing-status": {
|
||||||
"ocr": "OCR",
|
"ocr": "OCR",
|
||||||
"pending": "Pending",
|
"pending": "Pending",
|
||||||
|
"pending-timeout": "Pending (Rules timeout)",
|
||||||
"processed": "Processed",
|
"processed": "Processed",
|
||||||
"processing": "Processing"
|
"processing": "Processing"
|
||||||
},
|
},
|
||||||
@ -2583,4 +2594,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.
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