Merge branch 'master' into VM/RED-4169

This commit is contained in:
Valentin Mihai 2022-06-16 16:46:03 +03:00
commit bfa71e821a
72 changed files with 2807 additions and 2430 deletions

View File

@ -2,6 +2,7 @@
"version": 1,
"projects": {
"common-ui": {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/common-ui",
"sourceRoot": "libs/common-ui/src",
@ -26,6 +27,7 @@
"tags": []
},
"red-cache": {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/red-cache",
"sourceRoot": "libs/red-cache/src",
@ -55,6 +57,7 @@
"tags": []
},
"red-domain": {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"root": "libs/red-domain",
"sourceRoot": "libs/red-domain/src",
@ -78,6 +81,7 @@
}
},
"red-ui": {
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"projectType": "application",
"schematics": {
"@schematics/angular:component": {

View File

@ -1,11 +1,11 @@
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { RouterModule, Routes } from '@angular/router';
import { CompositeRouteGuard } from '@iqser/common-ui';
import { AuthGuard } from '../auth/auth.guard';
import { RedRoleGuard } from '../auth/red-role.guard';
import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component';
const routes = [
const routes: Routes = [
{ path: '', redirectTo: 'user-profile', pathMatch: 'full' },
{
path: 'user-profile',

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { NotificationPreferencesService } from '../../../services/notification-preferences.service';
import { BaseFormComponent, LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -26,7 +26,7 @@ export class NotificationsScreenComponent extends BaseFormComponent implements O
constructor(
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _notificationPreferencesService: NotificationPreferencesService,
private readonly _changeRef: ChangeDetectorRef,
@ -77,7 +77,7 @@ export class NotificationsScreenComponent extends BaseFormComponent implements O
this._loadingService.stop();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
inAppNotificationsEnabled: [undefined],
emailNotificationsEnabled: [undefined],

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
import { TranslateService } from '@ngx-translate/core';
import { BaseFormComponent, LoadingService } from '@iqser/common-ui';
@ -25,7 +25,7 @@ export class UserProfileScreenComponent extends BaseFormComponent implements OnI
constructor(
readonly permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _userService: UserService,
private readonly _configService: ConfigService,
private readonly _languageService: LanguageService,
@ -89,7 +89,7 @@ export class UserProfileScreenComponent extends BaseFormComponent implements OnI
this._initializeForm();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
email: [undefined, [Validators.required, Validators.email]],
firstName: [undefined],

View File

@ -1,13 +1,18 @@
import { Injectable, Injector } from '@angular/core';
import { GenericService } from '@iqser/common-ui';
import { Observable, of } from 'rxjs';
import { Observable, of, switchMap } from 'rxjs';
import { UserService } from '@services/user.service';
import { EmailNotificationScheduleTypes, INotificationPreferences } from '@red/domain';
import { EmailNotificationScheduleTypes, INotificationPreferences, Notification } from '@red/domain';
import { catchError } from 'rxjs/operators';
import { NotificationsService } from '@services/notifications.service';
@Injectable()
export class NotificationPreferencesService extends GenericService<INotificationPreferences> {
constructor(protected readonly _injector: Injector, private readonly _userService: UserService) {
constructor(
protected readonly _injector: Injector,
private readonly _userService: UserService,
private readonly _notificationsService: NotificationsService,
) {
super(_injector, 'notification-preferences');
}
@ -25,7 +30,7 @@ export class NotificationPreferencesService extends GenericService<INotification
return super.get<INotificationPreferences>().pipe(catchError(() => of(this._defaultPreferences)));
}
update(notificationPreferences: INotificationPreferences): Observable<void> {
return super._post(notificationPreferences);
update(notificationPreferences: INotificationPreferences): Observable<Notification[]> {
return super._post(notificationPreferences).pipe(switchMap(() => this._notificationsService.loadAll()));
}
}

View File

@ -22,7 +22,7 @@ import { DossierStatesListingScreenComponent } from './screens/dossier-states-li
import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component';
import { PermissionsGuard } from '../../guards/permissions-guard';
const dossierTemplateIdRoutes = [
const dossierTemplateIdRoutes: Routes = [
{
path: 'info',
canActivate: [CompositeRouteGuard],

View File

@ -1,5 +1,5 @@
import { Component, HostListener, Inject, Injector, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { DossierAttributeConfigTypes, FileAttributeConfigTypes, IDossierAttributeConfig } from '@red/domain';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { BaseDialogComponent, IqserEventTarget, LoadingService, Toaster } from '@iqser/common-ui';
@ -18,7 +18,7 @@ export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent
readonly typeOptions = Object.keys(DossierAttributeConfigTypes);
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _dossierAttributesService: DossierAttributesService,
private readonly _toaster: Toaster,
@ -74,7 +74,7 @@ export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent
}
}
private _getForm(dossierAttribute: IDossierAttributeConfig): FormGroup {
private _getForm(dossierAttribute: IDossierAttributeConfig): UntypedFormGroup {
return this._formBuilder.group({
label: [dossierAttribute?.label, Validators.required],
...(!!dossierAttribute && {

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { BaseDialogComponent, LoadingService, Toaster } from '@iqser/common-ui';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { IDossierState } from '@red/domain';
import { firstValueFrom } from 'rxjs';
@ -20,7 +20,7 @@ interface DialogData {
})
export class AddEditDossierStateDialogComponent extends BaseDialogComponent {
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _toaster: Toaster,
private readonly _dossierStatesService: DossierStatesService,
@ -52,7 +52,7 @@ export class AddEditDossierStateDialogComponent extends BaseDialogComponent {
this._loadingService.stop();
}
#getForm(): FormGroup {
#getForm(): UntypedFormGroup {
return this._formBuilder.group({
name: [this.data.dossierState?.name, Validators.required],
color: [this.data.dossierState?.color, Validators.required],

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import { downloadTypesTranslations } from '@translations/download-types-translations';
@ -39,7 +39,7 @@ export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogCompon
private readonly _toaster: Toaster,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _dictionaryService: DictionaryService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddEditCloneDossierTemplateDialogComponent>,
private readonly _loadingService: LoadingService,
@ -102,7 +102,7 @@ export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogCompon
this._loadingService.stop();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
name: [this._getCloneName(), Validators.required],
description: [this.dossierTemplate?.description],

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { fileAttributeTypesTranslations } from '@translations/file-attribute-types-translations';
@ -22,7 +22,7 @@ export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
readonly canSetFilterable!: boolean;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _fileAttributesService: FileAttributesService,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddEditFileAttributeDialogComponent>,
@ -50,7 +50,7 @@ export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
this._dialogRef.close(fileAttribute);
}
private _getForm(fileAttribute: IFileAttributeConfig): FormGroup {
private _getForm(fileAttribute: IFileAttributeConfig): UntypedFormGroup {
return this._formBuilder.group({
label: [fileAttribute?.label, Validators.required],
csvColumnHeader: [fileAttribute?.csvColumnHeader],

View File

@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { UserService } from '@services/user.service';
import { LoadingService, Toaster } from '@iqser/common-ui';
import { User } from '@red/domain';
@ -17,7 +17,7 @@ export class ResetPasswordComponent {
@Output() readonly toggleResetPassword = new EventEmitter();
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _userService: UserService,
private readonly _loadingService: LoadingService,
private readonly _toaster: Toaster,
@ -42,7 +42,7 @@ export class ResetPasswordComponent {
this._loadingService.stop();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
temporaryPassword: [null, Validators.required],
});

View File

@ -1,5 +1,5 @@
import { Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { AdminDialogService } from '../../../services/admin-dialog.service';
import { BaseFormComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { rolesTranslations } from '@translations/roles-translations';
@ -27,7 +27,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
private readonly _ROLE_REQUIREMENTS = { RED_MANAGER: 'RED_USER', RED_ADMIN: 'RED_USER_ADMIN' };
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _toaster: Toaster,
private readonly _dialogService: AdminDialogService,
private readonly _loadingService: LoadingService,
@ -108,7 +108,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
this._dialogService.deleteUsers([this.user.id], null, () => this.closeDialog.emit(true));
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
firstName: [this.user?.firstName, Validators.required],
lastName: [this.user?.lastName, Validators.required],

View File

@ -7,7 +7,7 @@ import { KmsSignatureConfigurationComponent } from './form/kms-signature-configu
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { HttpStatusCode } from '@angular/common/http';
import { DigitalSignatureOption, DigitalSignatureOptions } from '@red/domain';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, FormGroup, Validators } from '@angular/forms';
const DEFAULT_DIALOG_WIDTH = '662px';
const KMS_SIGNATURE_DIALOG_WIDTH = '810px';
@ -40,7 +40,7 @@ export class ConfigureCertificateDialogComponent extends BaseDialogComponent {
constructor(
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ConfigureCertificateDialogComponent>,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _toaster: Toaster,
private readonly _changeDetectorRef: ChangeDetectorRef,

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { BaseSignatureConfigurationComponent } from '../base-signature-configuration-component';
import { IKmsDigitalSignature, IKmsDigitalSignatureRequest, DigitalSignatureOptions } from '@red/domain';
import { firstValueFrom } from 'rxjs';
@ -14,7 +14,7 @@ import { DigitalSignatureService } from '../../../../services/digital-signature.
export class KmsSignatureConfigurationComponent extends BaseSignatureConfigurationComponent implements OnInit {
@Input() digitalSignature!: IKmsDigitalSignatureRequest;
constructor(protected readonly _digitalSignatureService: DigitalSignatureService, private readonly _formBuilder: FormBuilder) {
constructor(protected readonly _digitalSignatureService: DigitalSignatureService, private readonly _formBuilder: UntypedFormBuilder) {
super(_digitalSignatureService, DigitalSignatureOptions.KMS);
}

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { BaseSignatureConfigurationComponent } from '../base-signature-configuration-component';
import { IPkcsDigitalSignature, IPkcsDigitalSignatureRequest, DigitalSignatureOptions } from '@red/domain';
import { firstValueFrom } from 'rxjs';
@ -15,7 +15,7 @@ import { lastIndexOfEnd } from '../../../../../../utils';
export class PkcsSignatureConfigurationComponent extends BaseSignatureConfigurationComponent implements OnInit {
@Input() digitalSignature!: IPkcsDigitalSignatureRequest;
constructor(protected readonly _digitalSignatureService: DigitalSignatureService, private readonly _formBuilder: FormBuilder) {
constructor(protected readonly _digitalSignatureService: DigitalSignatureService, private readonly _formBuilder: UntypedFormBuilder) {
super(_digitalSignatureService, DigitalSignatureOptions.PKCS);
}

View File

@ -6,26 +6,25 @@
<div class="dialog-content">
<div class="heading">{{ 'confirm-delete-dossier-state.warning' | translate: translateArgs }}</div>
<ng-container *ngIf="data.dossierCount !== 0">
<div class="replacement-suggestion">{{ 'confirm-delete-dossier-state.suggestion' | translate }}</div>
<form *ngIf="data.dossierCount !== 0 && data.otherStates.length > 0" [formGroup]="form" class="mt-16">
<div class="iqser-input-group">
<mat-checkbox color="primary" formControlName="replace">
{{ 'confirm-delete-dossier-state.question' | translate: { count: data.dossierCount } }}
</mat-checkbox>
</div>
<form [formGroup]="form">
<div class="flex">
<div class="iqser-input-group w-300">
<label translate="confirm-delete-dossier-state.form.state"></label>
<mat-select
[placeholder]="'confirm-delete-dossier-state.form.state-placeholder' | translate"
formControlName="replaceDossierStatusId"
>
<mat-option>{{ 'confirm-delete-dossier-state.form.state-placeholder' | translate }}</mat-option>
<mat-option *ngFor="let state of data.otherStates" [value]="state.dossierStatusId">
{{ state.name }}
</mat-option>
</mat-select>
</div>
</div>
</form>
</ng-container>
<div *ngIf="form.get('replace').value" class="iqser-input-group w-300 min-h-55">
<label translate="confirm-delete-dossier-state.form.state"></label>
<mat-select
[placeholder]="'confirm-delete-dossier-state.form.state-placeholder' | translate"
formControlName="replaceDossierStatusId"
>
<mat-option *ngFor="let state of data.otherStates" [value]="state.dossierStatusId">
{{ state.name }}
</mat-option>
</mat-select>
</div>
</form>
</div>
<div class="dialog-actions">

View File

@ -1,14 +1,7 @@
.replacement-suggestion {
font-size: 13px;
line-height: 18px;
color: var(--iqser-grey-1);
margin-bottom: 24px;
}
.dialog-header {
color: var(--iqser-primary);
}
.heading {
margin-bottom: 8px;
.min-h-55 {
min-height: 55px;
}

View File

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { DossierState } from '@red/domain';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { firstValueFrom, forkJoin } from 'rxjs';
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
@ -23,10 +23,10 @@ interface DialogData {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ConfirmDeleteDossierStateDialogComponent {
readonly form: FormGroup;
readonly form: UntypedFormGroup;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _toaster: Toaster,
private readonly _dossierStatesService: DossierStatesService,
@ -45,17 +45,17 @@ export class ConfirmDeleteDossierStateDialogComponent {
};
}
get replaceDossierStatusId(): string {
return this.form.get('replaceDossierStatusId').value;
get label(): string {
return this.#replaceDossierStatusId ? _('confirm-delete-dossier-state.delete-replace') : _('confirm-delete-dossier-state.delete');
}
get label(): string {
return this.replaceDossierStatusId ? _('confirm-delete-dossier-state.delete-replace') : _('confirm-delete-dossier-state.delete');
get #replaceDossierStatusId(): string {
return this.form.get('replace').value ? this.form.get('replaceDossierStatusId').value : undefined;
}
async save(): Promise<void> {
this._loadingService.start();
await firstValueFrom(this._dossierStatesService.deleteState(this.data.toBeDeletedState, this.replaceDossierStatusId));
await firstValueFrom(this._dossierStatesService.deleteState(this.data.toBeDeletedState, this.#replaceDossierStatusId));
await firstValueFrom(
forkJoin([this._activeDossiersService.loadAll().pipe(take(1)), this._archivedDossiersService.loadAll().pipe(take(1))]),
);
@ -64,8 +64,9 @@ export class ConfirmDeleteDossierStateDialogComponent {
this._loadingService.stop();
}
#getForm(): FormGroup {
#getForm(): UntypedFormGroup {
return this._formBuilder.group({
replace: [false],
replaceDossierStatusId: [null],
});
}

View File

@ -2,7 +2,7 @@ import { Component, Inject, Injector } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DefaultColorType, IColors } from '@red/domain';
import { BaseDialogComponent, Toaster } from '@iqser/common-ui';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { TranslateService } from '@ngx-translate/core';
import { defaultColorsTranslations } from '@translations/default-colors-translations';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -24,7 +24,7 @@ export class EditColorDialogComponent extends BaseDialogComponent {
private readonly _dossierTemplateId: string;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _dictionaryService: DictionaryService,
private readonly _toaster: Toaster,
private readonly _translateService: TranslateService,
@ -56,7 +56,7 @@ export class EditColorDialogComponent extends BaseDialogComponent {
}
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
color: [this.data.colors[this.data.colorKey], [Validators.required, Validators.minLength(7)]],
});

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { FileAttributeEncodingTypes, IFileAttributesConfig } from '@red/domain';
import { fileAttributeEncodingTypesTranslations } from '@translations/file-attribute-encoding-types-translations';
import { BaseDialogComponent, Toaster } from '@iqser/common-ui';
@ -20,7 +20,7 @@ export class FileAttributesConfigurationsDialogComponent extends BaseDialogCompo
private readonly _configuration: IFileAttributesConfig = this._data.config;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _fileAttributesService: FileAttributesService,
private readonly _toaster: Toaster,
@ -58,7 +58,7 @@ export class FileAttributesConfigurationsDialogComponent extends BaseDialogCompo
this._dialogRef.close();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
supportCsvMapping: [!!this._configuration.filenameMappingColumnHeaderName],
keyColumn: [this._configuration.keyColumn || '', [Validators.required]],

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { AbstractControl, FormBuilder, FormGroup, ValidatorFn, Validators } from '@angular/forms';
import { AbstractControl, UntypedFormBuilder, UntypedFormGroup, ValidatorFn, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import * as Papa from 'papaparse';
import { firstValueFrom, Observable } from 'rxjs';
@ -26,7 +26,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
parseResult: { data: any[]; errors: any[]; meta: any; fields: IField[] };
hoveredColumn: string;
activeFields: IField[] = [];
readonly form: FormGroup;
readonly form: UntypedFormGroup;
isSearchOpen = false;
previewExpanded = true;
filteredKeyOptions: Observable<string[]>;
@ -39,7 +39,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
constructor(
private readonly _toaster: Toaster,
protected readonly _injector: Injector,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
readonly dialogRef: MatDialogRef<FileAttributesCsvImportDialogComponent>,
private readonly _fileAttributesService: FileAttributesService,
@Inject(MAT_DIALOG_DATA) readonly data: IFileAttributesCSVImportData,
@ -199,7 +199,7 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent<IFi
}, 0);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
filenameMappingColumnHeaderName: ['', [Validators.required, this._autocompleteStringValidator()]],
delimiter: [undefined, Validators.required],

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UserService } from '@services/user.service';
import { ISmtpConfiguration } from '@red/domain';
@ -12,7 +12,7 @@ import { BaseDialogComponent } from '@iqser/common-ui';
})
export class SmtpAuthDialogComponent extends BaseDialogComponent {
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _userService: UserService,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<SmtpAuthDialogComponent>,
@ -23,7 +23,7 @@ export class SmtpAuthDialogComponent extends BaseDialogComponent {
this.initialFormValue = this.form.getRawValue();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
user: [this.data?.user || this._userService.currentUser.email, [Validators.required]],
password: [this.data?.password, Validators.required],

View File

@ -1,5 +1,5 @@
import { Component, forwardRef, Injector, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
import { DefaultListingServices, ListingComponent, LoadingService, TableColumnConfig } from '@iqser/common-ui';
import { auditCategoriesTranslations } from '@translations/audit-categories-translations';
@ -23,7 +23,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnD
readonly ALL_USERS = _('audit-screen.all-users');
readonly translations = auditCategoriesTranslations;
readonly currentUser = this._userService.currentUser;
readonly form: FormGroup = this._getForm();
readonly form: UntypedFormGroup = this._getForm();
categories: string[] = [];
userIds: Set<string>;
logs: IAuditResponse;
@ -40,7 +40,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnD
constructor(
private readonly _userService: UserService,
protected readonly _injector: Injector,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _loadingService: LoadingService,
private readonly _auditService: AuditService,
) {
@ -68,7 +68,7 @@ export class AuditScreenComponent extends ListingComponent<Audit> implements OnD
await this._fetchData();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
category: [this.ALL_CATEGORIES],
userId: [this.ALL_USERS],

View File

@ -53,7 +53,7 @@
<iqser-icon-button
(action)="openAddEditStateDialog($event)"
*ngIf="permissionsService.canPerformDossierStatesActions"
*ngIf="permissionsService.canPerformDossierStatesActions()"
[label]="'dossier-states-listing.add-new' | translate"
[type]="iconButtonTypes.primary"
icon="iqser:plus"
@ -79,7 +79,7 @@
</div>
<div class="cell">
<div *ngIf="permissionsService.canPerformDossierStatesActions" class="action-buttons">
<div *ngIf="permissionsService.canPerformDossierStatesActions()" class="action-buttons">
<iqser-circle-button
(action)="openAddEditStateDialog($event, state)"
[tooltip]="'dossier-states-listing.action.edit' | translate"

View File

@ -1,6 +1,6 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { RouterModule, Routes } from '@angular/router';
import { SharedModule } from '@shared/shared.module';
import { DictionaryScreenComponent } from './screens/dictionary/dictionary-screen.component';
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
@ -8,7 +8,7 @@ import { InfoComponent } from './screens/info/info.component';
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
import { SharedAdminModule } from '../../shared/shared-admin.module';
const routes = [
const routes: Routes = [
{ path: '', redirectTo: 'info', pathMatch: 'full' },
{
path: 'info',

View File

@ -3,7 +3,7 @@ import { BaseFormComponent, LoadingService } from '@iqser/common-ui';
import { GeneralSettingsService } from '@services/general-settings.service';
import { IGeneralConfiguration } from '@red/domain';
import { ConfigService } from '@services/config.service';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { firstValueFrom } from 'rxjs';
@Component({
@ -18,7 +18,7 @@ export class GeneralConfigFormComponent extends BaseFormComponent implements OnI
private readonly _loadingService: LoadingService,
private readonly _generalSettingsService: GeneralSettingsService,
private readonly _configService: ConfigService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
) {
super();
this.form = this._getForm();
@ -40,7 +40,7 @@ export class GeneralConfigFormComponent extends BaseFormComponent implements OnI
await this._loadData();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
forgotPasswordFunctionEnabled: [false],
auxiliaryName: [undefined],

View File

@ -1,5 +1,5 @@
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { ISmtpConfiguration } from '@red/domain';
import { BaseFormComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { AdminDialogService } from '../../../services/admin-dialog.service';
@ -17,7 +17,7 @@ export class SmtpFormComponent extends BaseFormComponent implements OnInit, OnDe
private _initialConfiguration: ISmtpConfiguration;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _dialogService: AdminDialogService,
private readonly _smtpConfigService: SmtpConfigService,
private readonly _loadingService: LoadingService,
@ -66,7 +66,7 @@ export class SmtpFormComponent extends BaseFormComponent implements OnInit, OnDe
}
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
host: [undefined, Validators.required],
port: [25],

View File

@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { SystemPreferences } from '@red/domain';
import { BaseFormComponent, KeysOf, LoadingService } from '@iqser/common-ui';
import { firstValueFrom } from 'rxjs';
@ -25,7 +25,7 @@ export class SystemPreferencesFormComponent extends BaseFormComponent {
constructor(
private readonly _loadingService: LoadingService,
private readonly _systemPreferencesService: SystemPreferencesService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
) {
super();
this.form = this._getForm();
@ -39,7 +39,7 @@ export class SystemPreferencesFormComponent extends BaseFormComponent {
this._loadingService.stop();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
const controlsConfig = {};
this.keys.forEach(key => (controlsConfig[key.name] = [this._systemPreferencesService.values[key.name], Validators.required]));
return this._formBuilder.group(controlsConfig);

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Justification } from '@red/domain';
import { JustificationsService } from '@services/entity-services/justifications.service';
@ -15,7 +15,7 @@ import { firstValueFrom } from 'rxjs';
})
export class AddEditJustificationDialogComponent extends BaseDialogComponent {
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _justificationService: JustificationsService,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _loadingService: LoadingService,
@ -39,7 +39,7 @@ export class AddEditJustificationDialogComponent extends BaseDialogComponent {
this._dialogRef.close(true);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
name: [{ value: this.data.justification?.name, disabled: !!this.data.justification }, Validators.required],
reason: [this.data.justification?.reason, Validators.required],

View File

@ -2,7 +2,7 @@ import { ChangeDetectorRef, Component, ElementRef, Inject, OnInit, ViewChild } f
import { PermissionsService } from '@services/permissions.service';
import WebViewer, { WebViewerInstance } from '@pdftron/webviewer';
import { HttpClient } from '@angular/common/http';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Debounce, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { DOSSIER_TEMPLATE_ID, IWatermark, WatermarkOrientation, WatermarkOrientations } from '@red/domain';
import { BASE_HREF_FN, BaseHrefFn } from '../../../../../tokens';
@ -30,7 +30,7 @@ export const DEFAULT_WATERMARK: IWatermark = {
})
export class WatermarkScreenComponent implements OnInit {
readonly iconButtonTypes = IconButtonTypes;
readonly form: FormGroup = this._getForm();
readonly form: UntypedFormGroup = this._getForm();
readonly #dossierTemplateId: string;
private _instance: WebViewerInstance;
private _watermark: IWatermark = {};
@ -41,7 +41,7 @@ export class WatermarkScreenComponent implements OnInit {
route: ActivatedRoute,
private readonly _http: HttpClient,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
readonly permissionsService: PermissionsService,
private readonly _loadingService: LoadingService,
private readonly _licenseService: LicenseService,
@ -187,7 +187,7 @@ export class WatermarkScreenComponent implements OnInit {
this._changeDetectorRef.detectChanges();
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
const defaultValue = {
value: null,
disabled: !this.permissionsService.isAdmin(),

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
import { Dictionary, IDictionary } from '@red/domain';
import { FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { map, startWith } from 'rxjs/operators';
import { firstValueFrom, Observable } from 'rxjs';
import { toSnakeCase } from '@utils/functions';
@ -32,7 +32,7 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
private readonly _dictionaryService: DictionaryService,
private readonly _toaster: Toaster,
private readonly _loadingService: LoadingService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _changeRef: ChangeDetectorRef,
) {
super();
@ -111,17 +111,17 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
if (isHint) {
REDACTION_FIELDS.forEach(field => form.removeControl(field));
} else {
form.addControl('defaultReason', new FormControl({ value: null, disabled: true }));
form.addControl('defaultReason', new UntypedFormControl({ value: null, disabled: true }));
if (form.get('hasDictionary').value) {
form.addControl('addToDictionaryAction', new FormControl(this.#addToDictionaryActionControl));
form.addControl('addToDictionaryAction', new UntypedFormControl(this.#addToDictionaryActionControl));
}
}
});
form.get('hasDictionary').valueChanges.subscribe(hasDictionary => {
if (hasDictionary && !form.get('hint').value) {
form.addControl('addToDictionaryAction', new FormControl(this.#addToDictionaryActionControl));
form.addControl('addToDictionaryAction', new UntypedFormControl(this.#addToDictionaryActionControl));
} else {
form.removeControl('addToDictionaryAction');
}
@ -153,7 +153,7 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
return technicalName;
}
private _colorEmpty$(form: FormGroup, field: string) {
private _colorEmpty$(form: UntypedFormGroup, field: string) {
return form.get(field).valueChanges.pipe(
startWith(form.get(field).value),
map((value: string) => !value || value?.length === 0),

View File

@ -10,8 +10,8 @@
<redaction-date-column [date]="file.redactionModificationDate" [isError]="file.isError"></redaction-date-column>
</div>
<div *ngFor="let config of displayedAttributes" class="cell">
{{ file.fileAttributes.attributeIdToValue[config.id] || '-' }}
<div *ngFor="let config of displayedAttributes" [matTooltip]="file.fileAttributes.attributeIdToValue[config.id]" class="cell">
<span class="clamp-3"> {{ file.fileAttributes.attributeIdToValue[config.id] || '-' }}</span>
</div>
<!-- always show A for error-->

View File

@ -108,7 +108,7 @@
></iqser-circle-button>
<iqser-circle-button
(action)="annotationReferencesService.show(annotations[0])"
(action)="$event.stopPropagation(); annotationReferencesService.show(annotations[0])"
*ngIf="!multiSelectService.isActive && annotations[0].reference.length"
[tooltipPosition]="tooltipPosition"
[tooltip]="'annotation-actions.see-references.label' | translate"

View File

@ -9,6 +9,7 @@
max-height: 380px;
right: 370px;
top: 165px;
z-index: 1;
.references-header {
padding: 8px 8px 8px 13px;

View File

@ -3,6 +3,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { AnnotationReferencesService } from '../../services/annotation-references.service';
import { Observable, switchMap } from 'rxjs';
import { AnnotationsListingService } from '../../services/annotations-listing.service';
import { filter } from 'rxjs/operators';
@Component({
selector: 'redaction-annotation-references-list',
@ -19,6 +20,7 @@ export class AnnotationReferencesListComponent {
readonly annotationReferencesService: AnnotationReferencesService,
) {
this.isSelected$ = this.annotationReferencesService.annotation$.pipe(
filter(annotation => !!annotation),
switchMap(annotation => this._listingService.isSelected$(annotation)),
);
}

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { PermissionsService } from '@services/permissions.service';
import { Dictionary, Dossier } from '@red/domain';
@ -29,7 +29,7 @@ export class AcceptRecommendationDialogComponent extends BaseDialogComponent imp
private readonly _dossier: Dossier;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _permissionsService: PermissionsService,
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _dictionaryService: DictionaryService,
@ -77,7 +77,7 @@ export class AcceptRecommendationDialogComponent extends BaseDialogComponent imp
);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
dictionary: [Validators.required],
comment: [null],

View File

@ -1,7 +1,7 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { PermissionsService } from '@services/permissions.service';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { JustificationsService } from '@services/entity-services/justifications.service';
@ -25,7 +25,7 @@ export class ChangeLegalBasisDialogComponent extends BaseDialogComponent impleme
private readonly _justificationsService: JustificationsService,
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ChangeLegalBasisDialogComponent>,
@Inject(MAT_DIALOG_DATA) private readonly _data: { annotations: AnnotationWrapper[]; dossier: Dossier },
@ -65,7 +65,7 @@ export class ChangeLegalBasisDialogComponent extends BaseDialogComponent impleme
});
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
reason: [null, Validators.required],
comment: [null],

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
@ -13,14 +13,14 @@ import { firstValueFrom } from 'rxjs';
styleUrls: ['./document-info-dialog.component.scss'],
})
export class DocumentInfoDialogComponent extends BaseDialogComponent implements OnInit {
form: FormGroup;
form: UntypedFormGroup;
attributes: IFileAttributeConfig[];
private readonly _dossier: Dossier;
constructor(
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _fileAttributesService: FileAttributesService,
private readonly _filesService: FilesService,
protected readonly _injector: Injector,
@ -50,7 +50,7 @@ export class DocumentInfoDialogComponent extends BaseDialogComponent implements
this._dialogRef.close(true);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group(
this.attributes.reduce(
(acc, attr) => ({

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { BaseDialogComponent } from '@iqser/common-ui';
import { JustificationsService } from '@services/entity-services/justifications.service';
@ -22,7 +22,7 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
legalOptions: LegalBasisOption[] = [];
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _justificationsService: JustificationsService,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ForceAnnotationDialogComponent>,
@ -66,7 +66,7 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
this._dialogRef.close(this._createForceRedactionRequest());
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
reason: this._data.hint ? ['Forced Hint'] : [null, Validators.required],
comment: [null],

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { TextHighlightOperation, TextHighlightOperationPages } from '@red/domain';
import { BaseDialogComponent, LoadingService } from '@iqser/common-ui';
@ -26,7 +26,7 @@ export class HighlightActionDialogComponent extends BaseDialogComponent {
options = [TextHighlightOperationPages.THIS_PAGE, TextHighlightOperationPages.ALL_PAGES];
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<HighlightActionDialogComponent>,
private readonly _textHighlightService: TextHighlightService,
@ -57,7 +57,7 @@ export class HighlightActionDialogComponent extends BaseDialogComponent {
this._dialogRef.close(true);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
if (this.data.color) {
return this._formBuilder.group({
color: [{ value: this.data.color, disabled: true }, Validators.required],

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { ManualRedactionEntryWrapper } from '@models/file/manual-redaction-entry.wrapper';
import { JustificationsService } from '@services/entity-services/justifications.service';
@ -34,7 +34,7 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
private readonly _dossier: Dossier;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _justificationsService: JustificationsService,
private readonly _manualRedactionService: ManualRedactionService,
private readonly _activeDossiersService: ActiveDossiersService,
@ -139,7 +139,7 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
selectedText: this.data?.manualRedactionEntryWrapper?.manualRedactionEntry?.value,
section: [null],

View File

@ -1,5 +1,5 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { UntypedFormBuilder, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { imageCategoriesTranslations } from '@translations/image-categories-translations';
@ -14,7 +14,7 @@ export class RecategorizeImageDialogComponent extends BaseDialogComponent implem
translations = imageCategoriesTranslations;
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<RecategorizeImageDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { annotations: AnnotationWrapper[]; dossier: Dossier },

View File

@ -2,7 +2,7 @@ import { Component, Inject, Injector } from '@angular/core';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { TranslateService } from '@ngx-translate/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder } from '@angular/forms';
import { UntypedFormBuilder } from '@angular/forms';
import { BaseDialogComponent, humanize } from '@iqser/common-ui';
import { Dossier } from '@red/domain';
@ -20,7 +20,7 @@ export interface RemoveAnnotationsDialogInput {
export class RemoveAnnotationsDialogComponent extends BaseDialogComponent {
constructor(
private readonly _translateService: TranslateService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<RemoveAnnotationsDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: RemoveAnnotationsDialogInput,

View File

@ -1,6 +1,6 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder } from '@angular/forms';
import { UntypedFormBuilder } from '@angular/forms';
import { BaseDialogComponent } from '@iqser/common-ui';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
@ -9,7 +9,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper';
})
export class ResizeAnnotationDialogComponent extends BaseDialogComponent implements OnInit {
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ResizeAnnotationDialogComponent>,
@Inject(MAT_DIALOG_DATA) private readonly _data: { annotation: AnnotationWrapper; text?: string },

View File

@ -12,8 +12,13 @@
<ng-container *ngIf="permissionsService.isApprover(dossier) && !!file.lastReviewer">
<div class="vertical-line"></div>
<div class="all-caps-label mr-16 ml-8" translate="file-preview.last-reviewer"></div>
<redaction-initials-avatar [user]="file.lastReviewer" [withName]="true"></redaction-initials-avatar>
<div class="all-caps-label mr-16 ml-8">
{{ 'file-preview.last-assignee' | translate: { status: file.workflowStatus } }}
</div>
<redaction-initials-avatar
[user]="file.isApproved ? file.lastApprover : file.lastReviewer"
[withName]="true"
></redaction-initials-avatar>
</ng-container>
<div class="vertical-line"></div>

View File

@ -89,3 +89,5 @@
</div>
</div>
</ng-template>
<ng-container *ngIf="dossierTemplates$ | async"></ng-container>

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnDestroy } from '@angular/core';
import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnDestroy, OnInit } from '@angular/core';
import {
DefaultListingServices,
IFilterGroup,
@ -10,18 +10,29 @@ import {
SortingOrders,
TableColumnConfig,
} from '@iqser/common-ui';
import { combineLatest, Observable, of } from 'rxjs';
import { combineLatest, firstValueFrom, Observable, of } from 'rxjs';
import { debounceTime, map, startWith, switchMap, tap } from 'rxjs/operators';
import { ActivatedRoute, Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { workflowFileStatusTranslations } from '@translations/file-status-translations';
import { TranslateService } from '@ngx-translate/core';
import { RouterHistoryService } from '@services/router-history.service';
import { Dossier, DOSSIERS_ARCHIVE, IMatchedDocument, ISearchListItem, ISearchResponse } from '@red/domain';
import {
Dossier,
DOSSIERS_ARCHIVE,
DossierTemplate,
IMatchedDocument,
ISearchListItem,
ISearchResponse,
WorkflowFileStatus,
WorkflowFileStatuses,
} from '@red/domain';
import { FilesMapService } from '@services/files/files-map.service';
import { PlatformSearchService } from '@services/entity-services/platform-search.service';
import { FeaturesService } from '@services/features.service';
import { DossiersCacheService } from '../../../services/dossiers/dossiers-cache.service';
import { DossierTemplatesService } from '../../../services/dossier-templates/dossier-templates.service';
import { UserService } from '../../../services/user.service';
@Component({
templateUrl: './search-screen.component.html',
@ -44,11 +55,16 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
readonly searchResults$ = combineLatest([this._queryChanged, this._filtersChanged$]).pipe(
tap(() => this._loadingService.start()),
tap(([query, [dossierIds, onlyActive]]) => this._updateNavigation(query, dossierIds, onlyActive)),
switchMap(([query, [dossierIds, onlyActive]]) =>
tap(([query, [dossierIds, workflowStatus, assignee, dossierTemplateIds, onlyActive]]) =>
this._updateNavigation(query, dossierIds, workflowStatus, assignee, dossierTemplateIds, onlyActive),
),
switchMap(([query, [dossierIds, workflowStatus, assignee, dossierTemplateIds, onlyActive]]) =>
this._platformSearchService.search({
query,
dossierIds,
dossierTemplateIds,
workflowStatus,
assignee,
includeDeletedDossiers: false,
includeArchivedDossiers: !onlyActive,
}),
@ -59,6 +75,8 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
tap(() => this._loadingService.stop()),
);
readonly dossierTemplates$ = this._dossierTemplateService.loadAll().pipe(tap(templates => this._addTemplateFilter(templates)));
constructor(
private readonly _router: Router,
protected readonly _injector: Injector,
@ -70,11 +88,16 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
private readonly _filesMapService: FilesMapService,
private readonly _platformSearchService: PlatformSearchService,
private readonly _featuresService: FeaturesService,
private readonly _dossierTemplateService: DossierTemplatesService,
private readonly _userService: UserService,
) {
super(_injector);
this.searchService.skip = true;
this.sortingService.setSortingOption({ column: 'searchKey', order: SortingOrders.desc });
this._initFilters();
}
private _initFilters() {
const dossierIds = this._routeDossierIds;
const dossierToFilter = ({ dossierName, id }: Dossier) => {
const checked = dossierIds.includes(id);
@ -88,17 +111,86 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
filters: this._dossiersCacheService.all.map(dossierToFilter),
checker: keyChecker('dossierId'),
};
this.filterService.addFilterGroups([dossierNameFilter]);
const status = this._routeStatus;
const statusToFilter = (workflowStatus: WorkflowFileStatus) => {
const checked = status === workflowStatus;
return new NestedFilter({
id: workflowStatus,
label: this._translateService.instant(workflowFileStatusTranslations[workflowStatus]),
checked,
});
};
const workflowStatusFilter: IFilterGroup = {
slug: 'status',
label: this._translateService.instant('search-screen.filters.status'),
icon: 'red:status',
filters: Object.values(WorkflowFileStatuses).map(statusToFilter),
singleSelect: true,
checker: keyChecker('status'),
};
const assignee = this._routeAssignee;
const assigneeToFilter = (userId: string) => {
const checked = assignee === userId;
return new NestedFilter({ id: userId, label: this._userService.getNameForId(userId), checked });
};
const assigneeFilter: IFilterGroup = {
slug: 'assignee',
label: this._translateService.instant('search-screen.filters.assignee'),
icon: 'red:user',
filters: this._userService.all.map(user => user.id).map(assigneeToFilter),
singleSelect: true,
checker: keyChecker('assignee'),
};
assigneeFilter.filters.push(
new NestedFilter({
id: null,
label: this._translateService.instant('initials-avatar.unassigned'),
}),
);
this.filterService.addFilterGroups([dossierNameFilter, workflowStatusFilter, assigneeFilter]);
const onlyActiveLabel = this._translateService.instant('search-screen.filters.only-active');
if (this.#enabledArchive) {
this.filterService.addSingleFilter({ id: 'onlyActiveDossiers', label: onlyActiveLabel, checked: this._routeOnlyActive });
}
}
private _addTemplateFilter(templates: DossierTemplate[]) {
const templatesIds = this._routeDossierTemplateIds;
const templateToFilter = ({ name, id }: DossierTemplate) => {
const checked = templatesIds?.includes(id);
return new NestedFilter({ id, label: name, checked });
};
const templateNameFilter: IFilterGroup = {
slug: 'templates',
label: this._translateService.instant('search-screen.filters.by-template'),
filterceptionPlaceholder: this._translateService.instant('search-screen.filters.search-by-template-placeholder'),
icon: 'red:template',
filters: templates.map(templateToFilter),
checker: keyChecker('dossierTemplateId'),
};
this.filterService.addFilterGroups([templateNameFilter]);
}
private get _routeDossierIds(): string[] {
return this._activatedRoute.snapshot.queryParamMap.get('dossierIds').split(',');
}
private get _routeDossierTemplateIds(): string[] {
return this._activatedRoute.snapshot.queryParamMap.get('dossierTemplateIds')?.split(',');
}
private get _routeStatus(): WorkflowFileStatus {
return this._activatedRoute.snapshot.queryParamMap.get('status') as WorkflowFileStatus;
}
private get _routeAssignee(): string {
return this._activatedRoute.snapshot.queryParamMap.get('assignee');
}
private get _routeOnlyActive(): boolean {
return this._activatedRoute.snapshot.queryParamMap.get('onlyActive') === 'true';
}
@ -119,7 +211,7 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
return this._featuresService.isEnabled(DOSSIERS_ARCHIVE);
}
private get _filtersChanged$(): Observable<[string[], boolean]> {
private get _filtersChanged$(): Observable<[string[], WorkflowFileStatus, string, string[], boolean]> {
const onlyActiveDossiers$ = this.#enabledArchive
? this.filterService.getSingleFilter('onlyActiveDossiers').pipe(map(f => !!f.checked))
: of(true);
@ -127,9 +219,18 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
return combineLatest([filterGroups$, onlyActiveDossiers$]).pipe(
map(([groups, onlyActive]) => {
const dossierIds: string[] = groups[0].filters.filter(v => v.checked).map(v => v.id);
return [dossierIds, onlyActive];
const workflowStatus: WorkflowFileStatus = groups[1].filters.filter(v => v.checked).map(v => v.id)[0] as WorkflowFileStatus;
const assignee: string = groups[2].filters.filter(v => v.checked).map(v => v.id)[0];
const dossierTemplateIds: string[] = groups[3]?.filters.filter(v => v.checked).map(v => v.id);
return [dossierIds, workflowStatus, assignee, dossierTemplateIds, onlyActive];
}),
startWith<[string[], boolean]>([this._routeDossierIds, this._routeOnlyActive]),
startWith<[string[], WorkflowFileStatus, string, string[], boolean]>([
this._routeDossierIds,
this._routeStatus,
this._routeAssignee,
this._routeDossierTemplateIds,
this._routeOnlyActive,
]),
);
}
@ -138,8 +239,22 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
this.searchService.searchValue = newQuery ?? '';
}
private _updateNavigation(query?: string, dossierIds?: string[], onlyActive?: boolean): Promise<boolean> {
const queryParams = { query, dossierIds: dossierIds.join(','), onlyActive };
private _updateNavigation(
query?: string,
dossierIds?: string[],
workflowStatus?: WorkflowFileStatus,
assignee?: string,
dossierTemplateIds?: string[],
onlyActive?: boolean,
): Promise<boolean> {
const queryParams = {
query,
dossierIds: dossierIds.join(','),
dossierTemplateIds: dossierTemplateIds?.join(','),
workflowStatus,
assignee,
onlyActive,
};
return this._router.navigate([], { queryParams, replaceUrl: true });
}
@ -171,6 +286,7 @@ export class SearchScreenComponent extends ListingComponent<ISearchListItem> imp
return {
id: fileId,
dossierId,
dossierTemplateId: file.dossierTemplateId,
deleted: dossierDeleted,
archived: dossierArchived,
unmatched: unmatchedTerms || null,

View File

@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { UserService } from '@services/user.service';
import { LoadingService, Toaster } from '@iqser/common-ui';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Dossier, File, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FilesService } from '@services/files/files.service';
@ -23,14 +23,14 @@ class DialogData {
styleUrls: ['./assign-reviewer-approver-dialog.component.scss'],
})
export class AssignReviewerApproverDialogComponent {
readonly form: FormGroup;
readonly form: UntypedFormGroup;
readonly mode: 'reviewer' | 'approver';
dossier: Dossier;
constructor(
readonly userService: UserService,
private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _filesService: FilesService,
private readonly _loadingService: LoadingService,
@ -118,7 +118,7 @@ export class AssignReviewerApproverDialogComponent {
this._dialogRef.close(true);
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
// Allow a null reviewer if a previous reviewer exists (= it's not the first assignment) & current user is allowed to unassign
user: [this._user, this._canUnassignFiles && !this._user ? Validators.required : null],

View File

@ -3,7 +3,7 @@ import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-doss
import { Dossier, DossierAttributeConfigType, DossierAttributeConfigTypes, DossierAttributeWithValue } from '@red/domain';
import { PermissionsService } from '@services/permissions.service';
import { CircleButtonTypes, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { DossierAttributesService } from '@services/entity-services/dossier-attributes.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { firstValueFrom } from 'rxjs';
@ -24,14 +24,14 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
imageAttributes: DossierAttributeWithValue[] = [];
attributes: DossierAttributeWithValue[] = [];
form: FormGroup;
form: UntypedFormGroup;
@ViewChildren('fileInput') private _fileInputs: QueryList<ElementRef>;
constructor(
private readonly _permissionsService: PermissionsService,
private readonly _dossierAttributesService: DossierAttributesService,
private readonly _loadingService: LoadingService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _toaster: Toaster,
) {}
@ -135,7 +135,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
this.imageAttributes = this.attributes.filter(attr => this.isSpecificType(attr, this.dossierAttributeConfigTypes.IMAGE));
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
const controlsConfig = {};
for (const attribute of this.attributes) {
controlsConfig[attribute.id] = [{ value: attribute.value, disabled: this.disabled }];

View File

@ -6,7 +6,7 @@ import { DictionaryManagerComponent } from '@shared/components/dictionary-manage
import { DictionaryService } from '@services/entity-services/dictionary.service';
import { CircleButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { firstValueFrom } from 'rxjs';
import { DossiersService } from '@services/dossiers/dossiers.service';
@ -18,7 +18,7 @@ import { DossiersService } from '@services/dossiers/dossiers.service';
export class EditDossierDictionaryComponent implements EditDossierSectionInterface, OnInit {
@Input() dossier: Dossier;
form: FormGroup;
form: UntypedFormGroup;
canEdit = false;
canEditDisplayName = false;
dossierDictionary: Dictionary;
@ -31,7 +31,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
private readonly _dictionaryService: DictionaryService,
private readonly _permissionsService: PermissionsService,
private readonly _loadingService: LoadingService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _toaster: Toaster,
) {}
@ -117,7 +117,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
});
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group({
addToDictionaryAction: [
{

View File

@ -1,6 +1,6 @@
import { Component, Input, OnInit } from '@angular/core';
import { Dossier, DownloadFileType, IReportTemplate } from '@red/domain';
import { FormBuilder, FormGroup } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { downloadTypesTranslations } from '@translations/download-types-translations';
import { ReportTemplateService } from '@services/report-template.service';
@ -14,7 +14,7 @@ import { DossiersService } from '@services/dossiers/dossiers.service';
styleUrls: ['./edit-dossier-download-package.component.scss'],
})
export class EditDossierDownloadPackageComponent implements OnInit, EditDossierSectionInterface {
form: FormGroup;
form: UntypedFormGroup;
downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(
(type: DownloadFileType) => ({
key: type,
@ -28,7 +28,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
constructor(
private readonly _dossiersService: DossiersService,
private readonly _reportTemplateController: ReportTemplateService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _permissionsService: PermissionsService,
) {}
@ -111,7 +111,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
});
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group(
{
reportTemplateIds: [this.dossier.reportTemplateIds],

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core';
import { UserService } from '@services/user.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Dossier, IDossierRequest } from '@red/domain';
import { AutoUnsubscribe } from '@iqser/common-ui';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
@ -16,7 +16,7 @@ import { compareLists } from '@utils/functions';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class EditDossierTeamComponent extends AutoUnsubscribe implements EditDossierSectionInterface, OnInit, OnDestroy {
form: FormGroup;
form: UntypedFormGroup;
searchQuery = '';
@Input() dossier: Dossier;
@ -28,7 +28,7 @@ export class EditDossierTeamComponent extends AutoUnsubscribe implements EditDos
constructor(
readonly userService: UserService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _dossiersService: DossiersService,
private readonly _permissionsService: PermissionsService,
) {

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { Dossier, DOSSIER_TEMPLATE_ID, IDossierRequest, IDossierTemplate } from '@red/domain';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
@ -30,7 +30,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
@Input() dossier: Dossier;
form: FormGroup;
form: UntypedFormGroup;
statusPlaceholder: string;
hasDueDate: boolean;
dossierTemplates: IDossierTemplate[];
@ -43,7 +43,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
private readonly _dossiersService: DossiersService,
private readonly _trashService: TrashService,
private readonly _dossierStatsService: DossierStatsService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _dialogService: DossiersDialogService,
private readonly _router: Router,
private readonly _editDossierDialogRef: MatDialogRef<EditDossierDialogComponent>,
@ -108,11 +108,15 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
}
async save(): EditDossierSaveResult {
let dueDate;
if (this.hasDueDate) {
dueDate = dayjs(this.form.get('dueDate').value).set('h', 0).set('m', 0).set('s', 0);
}
const dossier = {
...this.dossier,
dossierName: this.form.get('dossierName').value,
description: this.form.get('description').value,
dueDate: this.hasDueDate ? this.form.get('dueDate').value : undefined,
dueDate: dueDate,
dossierTemplateId: this.form.get(DOSSIER_TEMPLATE_ID).value,
dossierStatusId: this.form.get('dossierStatusId').value,
} as IDossierRequest;
@ -179,7 +183,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
return this._dossierStatesMapService.get(this.dossier.dossierTemplateId, stateId).color;
}
#getForm(): FormGroup {
#getForm(): UntypedFormGroup {
const formFieldWithArchivedCheck = value => ({ value, disabled: !this.dossier.isActive });
return this._formBuilder.group({
dossierName: [formFieldWithArchivedCheck(this.dossier.dossierName), Validators.required],

View File

@ -36,7 +36,7 @@ export class DossierNameColumnComponent {
}
private get _dueDateDaysDiff(): number {
return dayjs(this.dossier.dueDate).diff(dayjs().startOf('day'), 'days');
return dayjs(this.dossier.dueDate).get('date') - dayjs().get('date');
}
getDossierTemplateNameFor(dossierTemplateId: string): string {

View File

@ -1,7 +1,7 @@
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DOSSIER_TEMPLATE_ID, DownloadFileType, IDossierRequest, IDossierTemplate, IReportTemplate } from '@red/domain';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { downloadTypesTranslations } from '@translations/download-types-translations';
import { BaseDialogComponent, IconButtonTypes, LoadingService, SaveOptions } from '@iqser/common-ui';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
@ -36,7 +36,7 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On
constructor(
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
private readonly _reportTemplateController: ReportTemplateService,
private readonly _router: Router,
private readonly _dialogService: DossiersDialogService,
@ -116,7 +116,7 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On
}
}
private _getForm(): FormGroup {
private _getForm(): UntypedFormGroup {
return this._formBuilder.group(
{
dossierName: [null, Validators.required],

View File

@ -2,7 +2,7 @@ import { Component, Inject } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DetailsRadioOption, IconButtonTypes } from '@iqser/common-ui';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { OverwriteFileOption, OverwriteFileOptions } from '@red/domain';
@ -13,7 +13,7 @@ import { OverwriteFileOption, OverwriteFileOptions } from '@red/domain';
})
export class OverwriteFilesDialogComponent {
readonly iconButtonTypes = IconButtonTypes;
readonly form: FormGroup;
readonly form: UntypedFormGroup;
readonly options: DetailsRadioOption<OverwriteFileOption>[] = [
{
label: _('overwrite-files-dialog.options.full-overwrite.label'),
@ -34,7 +34,7 @@ export class OverwriteFilesDialogComponent {
constructor(
private readonly _translateService: TranslateService,
private readonly _formBuilder: FormBuilder,
private readonly _formBuilder: UntypedFormBuilder,
public dialogRef: MatDialogRef<OverwriteFilesDialogComponent>,
@Inject(MAT_DIALOG_DATA) public filename: string,
) {

View File

@ -161,7 +161,13 @@ export class DictionaryService extends EntitiesService<Dictionary, IDictionary>
this._toaster.success(_('dictionary-overview.success.generic'));
}
},
() => this._toaster.error(_('dictionary-overview.error.generic')),
error => {
if (error.status === 400) {
this._toaster.error(_('dictionary-overview.error.400'));
} else {
this._toaster.error(_('dictionary-overview.error.generic'));
}
},
),
);
} else {

View File

@ -18,7 +18,15 @@ export class PlatformSearchService extends GenericService<ISearchResponse> {
super(_injector, 'search-v2');
}
search({ dossierIds, query, includeDeletedDossiers, includeArchivedDossiers }: ISearchInput): Observable<ISearchResponse> {
search({
dossierIds,
dossierTemplateIds,
workflowStatus,
assignee,
query,
includeDeletedDossiers,
includeArchivedDossiers,
}: ISearchInput): Observable<ISearchResponse> {
if (!query) {
return of({
matchedDocuments: [],
@ -28,6 +36,9 @@ export class PlatformSearchService extends GenericService<ISearchResponse> {
const body: ISearchRequest = {
dossierIds,
dossierTemplateIds,
workflowStatus,
assignee,
queryString: query ?? '',
page: 0,
returnSections: false,

View File

@ -47,10 +47,10 @@ export class NotificationsService extends EntitiesService<Notification, INotific
queryParam = { key: 'setRead', value: setRead };
}
return this._post(body, `${this._defaultModelPath}/toggle-read`, [queryParam]).pipe(switchMap(() => this.#loadAll()));
return this._post(body, `${this._defaultModelPath}/toggle-read`, [queryParam]).pipe(switchMap(() => this.loadAll()));
}
#loadAll(includeSeen = INCLUDE_SEEN): Observable<Notification[]> {
loadAll(includeSeen = INCLUDE_SEEN): Observable<Notification[]> {
const queryParam: QueryParam = { key: 'includeSeen', value: includeSeen };
return this.getAll<{ notifications: Notification[] }>(this._defaultModelPath, [queryParam]).pipe(
@ -61,7 +61,7 @@ export class NotificationsService extends EntitiesService<Notification, INotific
}
#loadNotificationsIfChanged(): Observable<Notification[]> {
return this.hasChanges$().pipe(switchMap(changed => iif(() => changed, this.#loadAll(), EMPTY)));
return this.hasChanges$().pipe(switchMap(changed => iif(() => changed, this.loadAll(), EMPTY)));
}
private _new(notification: INotification) {

View File

@ -20,10 +20,11 @@ export class RouterHistoryService {
}
navigateToLastDossiersScreen(): void {
if (this._router.url === this._lastDossiersScreen) {
if (this._router.url === decodeURI(this._lastDossiersScreen)) {
this._router.navigate(['/']);
} else {
this._router.navigate([this._lastDossiersScreen]);
const url = decodeURI(this._lastDossiersScreen).split('?')[0];
this._router.navigate([url]);
}
}
}

View File

@ -1,11 +1,11 @@
import { FormGroup } from '@angular/forms';
import { UntypedFormGroup } from '@angular/forms';
import { Dayjs } from 'dayjs';
export function applyIntervalConstraints(
value,
previousFrom: Dayjs,
previousTo: Dayjs,
form: FormGroup,
form: UntypedFormGroup,
fromKey: string,
toKey: string,
): boolean {

View File

@ -502,8 +502,8 @@
"state": "",
"state-placeholder": ""
},
"question": "",
"success": "",
"suggestion": "",
"title": "",
"warning": ""
},
@ -631,6 +631,7 @@
},
"download": "",
"error": {
"400": "",
"entries-too-short": "Einige Einträge im Wörterbuch unterschreiten die Mindestlänge von 2 Zeichen. Diese sind rot markiert.",
"generic": "Es ist ein Fehler aufgetreten ... Das Wörterbuch konnte nicht aktualisiert werden!"
},
@ -1305,7 +1306,7 @@
"convert": "",
"remove": ""
},
"last-reviewer": "Zuletzt überprüft von:",
"last-assignee": "Zuletzt überprüft von:",
"no-data": {
"title": "Auf dieser Seite gibt es keine Anmerkungen."
},
@ -1459,13 +1460,11 @@
"labels": {
"download-cleanup-download-files-hours": "",
"download-cleanup-not-download-files-hours": "",
"remove-digital-signature-on-upload": "",
"soft-delete-cleanup-time": ""
},
"placeholders": {
"download-cleanup-download-files-hours": "",
"download-cleanup-not-download-files-hours": "",
"remove-digital-signature-on-upload": "",
"soft-delete-cleanup-time": ""
},
"title": ""
@ -1890,9 +1889,13 @@
"status": "Status"
},
"filters": {
"assignee": "",
"by-dossier": "Nach Dossier filtern",
"by-template": "",
"only-active": "",
"search-placeholder": "Dossiername..."
"search-by-template-placeholder": "",
"search-placeholder": "Dossiername...",
"status": ""
},
"missing": "Fehlt",
"must-contain": "Muss enthalten",

View File

@ -502,8 +502,8 @@
"state": "Replace State",
"state-placeholder": "Choose another state"
},
"question": "Replace the {count, plural, one{dossier's} other{dossiers'}} state with another state",
"success": "Successfully deleted state!",
"suggestion": "Would you like to replace the dossiers' states with another state?",
"title": "Delete Dossier State",
"warning": "The {name} state is assigned to {count} {count, plural, one{dossier} other{dossiers}}."
},
@ -631,6 +631,7 @@
},
"download": "Download current entries",
"error": {
"400": "Cannot update dictionary because at least one of the newly added words where recognized as a general term that appear too often in texts.",
"entries-too-short": "Some entries of the dictionary are below the minimum length of 2. These are highlighted with red!",
"generic": "Something went wrong... Dictionary update failed!"
},
@ -1305,7 +1306,7 @@
"convert": "Convert highlights",
"remove": "Remove highlights"
},
"last-reviewer": "Last Reviewed by:",
"last-assignee": "{status, select, APPROVED{Approved} UNDER_APPROVAL{Reviewed} other{Last reviewed}} by:",
"no-data": {
"title": "There have been no changes to this page."
},
@ -1459,13 +1460,11 @@
"labels": {
"download-cleanup-download-files-hours": "Deletion time (hours) for download packages that have been generated and downloaded",
"download-cleanup-not-download-files-hours": "Deletion time (hours) for download packages that have been generated but not yet downloaded",
"remove-digital-signature-on-upload": "Remove digital signature on upload",
"soft-delete-cleanup-time": "Deletion time (hours) for deleted files in Trash"
},
"placeholders": {
"download-cleanup-download-files-hours": "(hours)",
"download-cleanup-not-download-files-hours": "(hours)",
"remove-digital-signature-on-upload": "True / False",
"soft-delete-cleanup-time": "(hours)"
},
"title": "System Preferences"
@ -1890,9 +1889,13 @@
"status": "Status"
},
"filters": {
"by-dossier": "Filter by Dossier",
"assignee": "Assignee",
"by-dossier": "Dossier",
"by-template": "Dossier Template",
"only-active": "Active dossiers only",
"search-placeholder": "Dossier name..."
"search-by-template-placeholder": "Dossier Template name...",
"search-placeholder": "Dossier name...",
"status": "Status"
},
"missing": "Missing",
"must-contain": "Must contain",

View File

@ -9,5 +9,8 @@
{
"path": "./tsconfig.spec.json"
}
]
],
"compilerOptions": {
"target": "es2020"
}
}

View File

@ -9,5 +9,8 @@
{
"path": "./tsconfig.spec.json"
}
]
],
"compilerOptions": {
"target": "es2020"
}
}

View File

@ -1,8 +1,12 @@
import { List } from '@iqser/common-ui';
import { WorkflowFileStatus } from '../files';
export interface ISearchInput {
readonly query: string;
readonly dossierIds?: List;
readonly dossierTemplateIds?: List;
readonly workflowStatus?: WorkflowFileStatus;
readonly assignee?: string;
readonly includeDeletedDossiers: boolean;
readonly includeArchivedDossiers: boolean;
}

View File

@ -2,6 +2,7 @@ import { IListable, List } from '@iqser/common-ui';
export interface ISearchListItem extends IListable {
readonly dossierId: string;
readonly dossierTemplateId: string;
readonly filename: string;
readonly assignee: string;
readonly unmatched: List | null;

View File

@ -1,4 +1,5 @@
import { List } from '@iqser/common-ui';
import { WorkflowFileStatus } from '../files';
export interface ISearchRequest {
readonly dossierIds?: List;
@ -10,4 +11,6 @@ export interface ISearchRequest {
readonly pageSize?: number;
readonly queryString?: string;
readonly returnSections?: boolean;
readonly workflowStatus?: WorkflowFileStatus;
readonly assignee?: string;
}

View File

@ -31,7 +31,6 @@
]
},
"cli": {
"defaultCollection": "@nrwl/angular",
"analytics": false,
"packageManager": "yarn"
},
@ -46,5 +45,6 @@
"unitTestRunner": "jest"
},
"@nrwl/angular:component": {}
}
},
"$schema": "./node_modules/nx/schemas/nx-schema.json"
}

View File

@ -1,6 +1,6 @@
{
"name": "redaction",
"version": "3.523.0",
"version": "3.537.0",
"private": true,
"license": "MIT",
"scripts": {
@ -8,7 +8,7 @@
"build-lint-all": "ng build --project=red-ui --configuration production --base-href /ui/",
"build-paligo-styles": "mkdir -p dist/paligo-styles && sass --load-path=. paligo-styles/style.scss > dist/paligo-styles/redacto-theme.css",
"i18n:extract": "ngx-translate-extract --input ./apps/red-ui/src ./libs/common-ui/src --output apps/red-ui/src/assets/i18n/{en,de}.json --clean --sort --format namespaced-json && prettier apps/red-ui/src/assets/i18n/*.json --write",
"postinstall": "ngcc --properties es2015 browser module main",
"postinstall": "ngcc --properties es2020 browser module main",
"lint": "ng lint --project=red-domain --fix && ng lint --project=red-ui --fix && ng lint --project=common-ui --fix",
"nx": "nx",
"start": "nx serve",
@ -24,27 +24,27 @@
}
},
"dependencies": {
"@angular/animations": "13.3.9",
"@angular/cdk": "13.3.7",
"@angular/common": "13.3.9",
"@angular/compiler": "13.3.9",
"@angular/core": "13.3.9",
"@angular/forms": "13.3.9",
"@angular/material": "13.3.7",
"@angular/platform-browser": "13.3.9",
"@angular/platform-browser-dynamic": "13.3.9",
"@angular/router": "13.3.9",
"@angular/service-worker": "13.3.9",
"@angular/animations": "14.0.1",
"@angular/cdk": "14.0.1",
"@angular/common": "14.0.1",
"@angular/compiler": "14.0.1",
"@angular/core": "14.0.1",
"@angular/forms": "14.0.1",
"@angular/material": "14.0.1",
"@angular/platform-browser": "14.0.1",
"@angular/platform-browser-dynamic": "14.0.1",
"@angular/router": "14.0.1",
"@angular/service-worker": "14.0.1",
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
"@materia-ui/ngx-monaco-editor": "^6.0.0",
"@ngneat/until-destroy": "^9.2.0",
"@ngx-translate/core": "^14.0.0",
"@ngx-translate/http-loader": "^7.0.0",
"@nrwl/angular": "14.1.9",
"@pdftron/webviewer": "8.5.0",
"@nrwl/angular": "14.3.2",
"@pdftron/webviewer": "8.6.0",
"@tabuckner/material-dayjs-adapter": "2.0.0",
"angular-google-charts": "^2.2.2",
"dayjs": "^1.11.2",
"dayjs": "^1.11.3",
"file-saver": "^2.0.5",
"jwt-decode": "^3.1.2",
"keycloak-angular": "10.0.0",
@ -59,36 +59,36 @@
"object-hash": "^3.0.0",
"papaparse": "^5.3.2",
"rxjs": "~7.5.2",
"sass": "^1.52.1",
"sass": "^1.52.3",
"scroll-into-view-if-needed": "^2.2.28",
"streamsaver": "^2.0.5",
"tslib": "^2.4.0",
"zone.js": "0.11.5"
},
"devDependencies": {
"@angular-devkit/build-angular": "13.3.6",
"@angular-eslint/eslint-plugin": "13.2.1",
"@angular-eslint/eslint-plugin-template": "13.2.1",
"@angular-eslint/template-parser": "13.2.1",
"@angular/cli": "13.3.6",
"@angular/compiler-cli": "13.3.9",
"@angular/language-service": "13.3.9",
"@angular-devkit/build-angular": "14.0.1",
"@angular-eslint/eslint-plugin": "13.5.0",
"@angular-eslint/eslint-plugin-template": "13.5.0",
"@angular-eslint/template-parser": "13.5.0",
"@angular/cli": "~14.0.0",
"@angular/compiler-cli": "14.0.1",
"@angular/language-service": "14.0.1",
"@bartholomej/ngx-translate-extract": "^8.0.2",
"@nrwl/cli": "14.1.9",
"@nrwl/eslint-plugin-nx": "14.1.9",
"@nrwl/jest": "14.1.9",
"@nrwl/linter": "14.1.9",
"@nrwl/workspace": "14.1.9",
"@nrwl/cli": "14.3.2",
"@nrwl/eslint-plugin-nx": "14.3.2",
"@nrwl/jest": "14.3.2",
"@nrwl/linter": "14.3.2",
"@nrwl/workspace": "14.3.2",
"@types/google.visualization": "^0.0.68",
"@types/jest": "27.5.1",
"@types/jest": "28.1.1",
"@types/lodash-es": "^4.17.6",
"@types/node": "17.0.35",
"@types/node": "17.0.42",
"@types/puppeteer": "^5.4.6",
"@typescript-eslint/eslint-plugin": "5.26.0",
"@typescript-eslint/parser": "5.26.0",
"@typescript-eslint/eslint-plugin": "5.24.0",
"@typescript-eslint/parser": "5.24.0",
"axios": "^0.27.2",
"dotenv": "16.0.1",
"eslint": "8.16.0",
"eslint": "8.17.0",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.0.0",
"eslint-config-prettier": "8.5.0",
@ -96,23 +96,23 @@
"eslint-plugin-prettier": "^4.0.0",
"google-translate-api-browser": "^1.1.71",
"husky": "4.3.8",
"jest": "28.1.0",
"jest-preset-angular": "12.0.1",
"ng-packagr": "13.3.1",
"nx": "14.1.9",
"jest": "28.1.1",
"jest-preset-angular": "12.1.0",
"ng-packagr": "14.0.2",
"nx": "14.3.2",
"postcss": "^8.4.14",
"postcss-import": "14.1.0",
"postcss-preset-env": "~7.6.0",
"postcss-preset-env": "~7.7.1",
"postcss-url": "10.1.3",
"prettier": "2.6.2",
"prettier": "2.7.0",
"pretty-quick": "^3.1.3",
"sonarqube-scanner": "^2.8.1",
"superagent": "^7.1.3",
"superagent": "^7.1.6",
"superagent-promise": "^1.1.0",
"ts-jest": "28.0.3",
"ts-node": "10.8.0",
"typescript": "4.6.4",
"webpack": "^5.72.1",
"ts-jest": "28.0.5",
"ts-node": "10.8.1",
"typescript": "4.7.3",
"webpack": "^5.73.0",
"webpack-bundle-analyzer": "^4.5.0",
"xliff": "^6.0.0"
}

Binary file not shown.

4549
yarn.lock

File diff suppressed because it is too large Load Diff