Merge remote-tracking branch 'origin/master' into refactor-fp/state

This commit is contained in:
Adina Țeudan 2022-01-19 20:59:59 +02:00
commit 057c883b75
40 changed files with 273 additions and 282 deletions

View File

@ -95,11 +95,11 @@
</div>
<div class="dialog-actions">
<button (click)="save()" [disabled]="!valid || !changed" color="primary" mat-flat-button>
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button>
{{ 'add-edit-dictionary.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Observable } from 'rxjs';
@ -6,7 +6,7 @@ import { BaseDialogComponent, shareDistinctLast, Toaster } from '@iqser/common-u
import { TranslateService } from '@ngx-translate/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { AppStateService } from '@state/app-state.service';
import { toKebabCase } from '@utils/functions';
import { toSnakeCase } from '@utils/functions';
import { DictionaryService } from '@shared/services/dictionary.service';
import { Dictionary, IDictionary } from '@red/domain';
import { UserService } from '@services/user.service';
@ -21,7 +21,6 @@ import { HttpStatusCode } from '@angular/common/http';
})
export class AddEditDictionaryDialogComponent extends BaseDialogComponent {
readonly dictionary = this._data.dictionary;
readonly form: FormGroup = this._getForm(this.dictionary);
readonly canEditLabel$ = this._canEditLabel$;
readonly technicalName$: Observable<string>;
readonly dialogHeader = this._translateService.instant('add-edit-dictionary.title', {
@ -29,7 +28,6 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent {
name: this._data.dictionary?.label,
});
readonly hasColor$: Observable<boolean>;
readonly disabled = false;
private readonly _dossierTemplateId = this._data.dossierTemplateId;
constructor(
@ -39,37 +37,18 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent {
private readonly _appStateService: AppStateService,
private readonly _translateService: TranslateService,
private readonly _dictionaryService: DictionaryService,
private readonly _dialogRef: MatDialogRef<AddEditDictionaryDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddEditDictionaryDialogComponent>,
@Inject(MAT_DIALOG_DATA)
private readonly _data: { readonly dictionary: Dictionary; readonly dossierTemplateId: string },
) {
super();
super(_injector, _dialogRef);
this.form = this._getForm(this.dictionary);
this.initialFormValue = this.form.getRawValue();
this.hasColor$ = this._colorEmpty$;
this.technicalName$ = this.form.get('label').valueChanges.pipe(map(value => this._toTechnicalName(value)));
}
get valid(): boolean {
return this.form.valid;
}
get changed(): boolean {
if (!this.dictionary) {
return true;
}
for (const key of Object.keys(this.form.getRawValue())) {
if (key === 'caseSensitive') {
if (this.getDictCaseSensitive(this.dictionary) !== this.form.get(key).value) {
return true;
}
} else if (this.dictionary[key] !== this.form.get(key).value) {
return true;
}
}
return false;
}
private get _canEditLabel$() {
return this.userService.currentUser$.pipe(
map(user => user.isAdmin || !this._data.dictionary),
@ -126,7 +105,7 @@ export class AddEditDictionaryDialogComponent extends BaseDialogComponent {
private _toTechnicalName(value: string) {
const existingTechnicalNames = Object.keys(this._appStateService.dictionaryData[this._dossierTemplateId]);
const baseTechnicalName = toKebabCase(value.trim());
const baseTechnicalName = toSnakeCase(value.trim());
let technicalName = baseTechnicalName;
let suffix = 1;
while (existingTechnicalNames.includes(technicalName)) {

View File

@ -35,11 +35,11 @@
</div>
</div>
<div class="dialog-actions">
<button (click)="save()" [disabled]="form.invalid || !changed" color="primary" mat-flat-button>
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button>
{{ 'add-edit-dossier-attribute.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,8 +1,8 @@
import { Component, HostListener, Inject, OnDestroy } from '@angular/core';
import { Component, HostListener, Inject, Injector, OnDestroy } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { DossierAttributeConfigTypes, FileAttributeConfigTypes, IDossierAttributeConfig } from '@red/domain';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AutoUnsubscribe, IqserEventTarget, LoadingService, Toaster } from '@iqser/common-ui';
import { BaseDialogComponent, IqserEventTarget, LoadingService, Toaster } from '@iqser/common-ui';
import { HttpErrorResponse } from '@angular/common/http';
import { DossierAttributesService } from '@shared/services/controller-wrappers/dossier-attributes.service';
import { dossierAttributeTypesTranslations } from '../../translations/dossier-attribute-types-translations';
@ -12,9 +12,8 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
templateUrl: './add-edit-dossier-attribute-dialog.component.html',
styleUrls: ['./add-edit-dossier-attribute-dialog.component.scss'],
})
export class AddEditDossierAttributeDialogComponent extends AutoUnsubscribe implements OnDestroy {
export class AddEditDossierAttributeDialogComponent extends BaseDialogComponent implements OnDestroy {
dossierAttribute: IDossierAttributeConfig = this.data.dossierAttribute;
readonly form: FormGroup = this._getForm(this.dossierAttribute);
readonly translations = dossierAttributeTypesTranslations;
readonly typeOptions = Object.keys(DossierAttributeConfigTypes);
@ -23,11 +22,14 @@ export class AddEditDossierAttributeDialogComponent extends AutoUnsubscribe impl
private readonly _loadingService: LoadingService,
private readonly _dossierAttributesService: DossierAttributesService,
private readonly _toaster: Toaster,
readonly dialogRef: MatDialogRef<AddEditDossierAttributeDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddEditDossierAttributeDialogComponent>,
@Inject(MAT_DIALOG_DATA)
readonly data: { readonly dossierAttribute: IDossierAttributeConfig },
) {
super();
super(_injector, _dialogRef);
this.form = this._getForm(this.dossierAttribute);
this.initialFormValue = this.form.getRawValue();
}
get changed(): boolean {
@ -55,7 +57,7 @@ export class AddEditDossierAttributeDialogComponent extends AutoUnsubscribe impl
this._dossierAttributesService.createOrUpdate(attribute).subscribe(
() => {
this.dialogRef.close(true);
this._dialogRef.close(true);
},
(error: HttpErrorResponse) => {
this._loadingService.stop();

View File

@ -33,16 +33,11 @@
<div class="validity">
<div>
<mat-checkbox
(change)="hasValidFrom = !hasValidFrom"
[checked]="hasValidFrom"
class="filter-menu-checkbox"
color="primary"
>
<mat-checkbox (change)="toggleHasValid('from')" [checked]="hasValidFrom" class="filter-menu-checkbox" color="primary">
{{ 'add-edit-dossier-template.form.valid-from' | translate }}
</mat-checkbox>
<mat-checkbox (change)="hasValidTo = !hasValidTo" [checked]="hasValidTo" class="filter-menu-checkbox" color="primary">
<mat-checkbox (change)="toggleHasValid('to')" [checked]="hasValidTo" class="filter-menu-checkbox" color="primary">
{{ 'add-edit-dossier-template.form.valid-to' | translate }}
</mat-checkbox>
</div>
@ -87,11 +82,11 @@
</div>
<div class="dialog-actions">
<button (click)="save()" [disabled]="!valid || !changed" color="primary" mat-flat-button>
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button>
{{ 'add-edit-dossier-template.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,4 +1,4 @@
import { Component, Inject } from '@angular/core';
import { Component, Inject, Injector } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@ -17,7 +17,6 @@ import { HttpStatusCode } from '@angular/common/http';
styleUrls: ['./add-edit-dossier-template-dialog.component.scss'],
})
export class AddEditDossierTemplateDialogComponent extends BaseDialogComponent {
readonly form: FormGroup = this._getForm();
hasValidFrom: boolean;
hasValidTo: boolean;
downloadTypesEnum: DownloadFileType[] = ['ORIGINAL', 'PREVIEW', 'REDACTED'];
@ -25,65 +24,49 @@ export class AddEditDossierTemplateDialogComponent extends BaseDialogComponent {
key: type,
label: downloadTypesTranslations[type],
}));
readonly disabled = false;
private _previousValidFrom: Moment;
private _previousValidTo: Moment;
private _lastValidFrom: Moment;
private _lastValidTo: Moment;
constructor(
private readonly _appStateService: AppStateService,
private readonly _toaster: Toaster,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef<AddEditDossierTemplateDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddEditDossierTemplateDialogComponent>,
@Inject(MAT_DIALOG_DATA) readonly dossierTemplate: IDossierTemplate,
) {
super();
super(_injector, _dialogRef);
this.form = this._getForm();
this.initialFormValue = this.form.getRawValue();
this.hasValidFrom = !!this.dossierTemplate?.validFrom;
this.hasValidTo = !!this.dossierTemplate?.validTo;
this._previousValidFrom = this.form.get('validFrom').value;
this._previousValidTo = this.form.get('validTo').value;
this._previousValidFrom = this._lastValidFrom = this.form.get('validFrom').value;
this._previousValidTo = this._lastValidTo = this.form.get('validTo').value;
this.form.valueChanges.subscribe(value => {
this.addSubscription = this.form.valueChanges.subscribe(value => {
this._applyValidityIntervalConstraints(value);
});
this.addSubscription = this.form.controls['validFrom'].valueChanges.subscribe(value => {
this._lastValidFrom = value ? value : this._lastValidFrom;
});
this.addSubscription = this.form.controls['validTo'].valueChanges.subscribe(value => {
this._lastValidFrom = value ? value : this._lastValidFrom;
});
}
get valid(): boolean {
return this.form.valid;
}
get changed(): boolean {
if (!this.dossierTemplate) {
return true;
toggleHasValid(extremity: string) {
if (extremity === 'from') {
this.hasValidFrom = !this.hasValidFrom;
this.form.controls['validFrom'].setValue(this.hasValidFrom ? this._lastValidFrom : null);
} else {
this.hasValidTo = !this.hasValidTo;
this.form.controls['validTo'].setValue(this.hasValidTo ? this._lastValidTo : null);
}
for (const key of Object.keys(this.form.getRawValue())) {
const formValue = this.form.get(key).value;
const objectValue = this.dossierTemplate[key];
if (key === 'validFrom') {
if (this.hasValidFrom !== !!objectValue || (this.hasValidFrom && !moment(objectValue).isSame(moment(formValue)))) {
return true;
}
} else if (key === 'validTo') {
if (this.hasValidTo !== !!objectValue || (this.hasValidTo && !moment(objectValue).isSame(moment(formValue)))) {
return true;
}
} else if (formValue instanceof Array) {
if (objectValue.length !== formValue.length) {
return true;
}
for (const item of objectValue) {
if (!formValue.includes(item)) {
return true;
}
}
} else if (objectValue !== formValue) {
return true;
}
}
return false;
}
async save() {
@ -97,7 +80,7 @@ export class AddEditDossierTemplateDialogComponent extends BaseDialogComponent {
await this._dossierTemplatesService.createOrUpdate(dossierTemplate).toPromise();
await this._dossierTemplatesService.loadAll().toPromise();
await this._appStateService.loadDictionaryData();
this.dialogRef.close(true);
this._dialogRef.close(true);
} catch (error: any) {
const message =
error.status === HttpStatusCode.Conflict

View File

@ -84,11 +84,11 @@
</div>
</div>
<div class="dialog-actions">
<button (click)="save()" [disabled]="!valid || !changed" color="primary" mat-flat-button>
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button>
{{ 'add-edit-file-attribute.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,10 +1,10 @@
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
import { FormBuilder, FormGroup, 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';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { BaseDialogComponent } from '@iqser/common-ui';
import { BaseDialogComponent } from '../../../../../../../../libs/common-ui/src';
@Component({
selector: 'redaction-add-edit-file-attribute-dialog',
@ -13,12 +13,10 @@ import { BaseDialogComponent } from '@iqser/common-ui';
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
readonly disabled = false;
DISPLAYED_FILTERABLE_LIMIT = 3;
translations = fileAttributeTypesTranslations;
fileAttribute: IFileAttributeConfig = this.data.fileAttribute;
dossierTemplateId: string = this.data.dossierTemplateId;
readonly form!: FormGroup;
readonly typeOptions = Object.keys(FileAttributeConfigTypes);
readonly canSetDisplayed!: boolean;
readonly canSetFilterable!: boolean;
@ -26,7 +24,8 @@ export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
constructor(
private readonly _formBuilder: FormBuilder,
private readonly _fileAttributesService: FileAttributesService,
public dialogRef: MatDialogRef<AddEditFileAttributeDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddEditFileAttributeDialogComponent>,
@Inject(MAT_DIALOG_DATA)
public data: {
fileAttribute: IFileAttributeConfig;
@ -35,32 +34,11 @@ export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
numberOfFilterableAttrs: number;
},
) {
super();
super(_injector, _dialogRef);
this.canSetDisplayed = data.numberOfDisplayedAttrs < this.DISPLAYED_FILTERABLE_LIMIT || data.fileAttribute?.displayedInFileList;
this.canSetFilterable = data.numberOfFilterableAttrs < this.DISPLAYED_FILTERABLE_LIMIT || data.fileAttribute?.filterable;
this.form = this._getForm(this.fileAttribute);
}
get valid(): boolean {
return this.form.valid;
}
get changed(): boolean {
if (!this.fileAttribute) {
return true;
}
for (const key of Object.keys(this.form.getRawValue())) {
if (key === 'readonly') {
if (this.fileAttribute.editable === this.form.get(key).value) {
return true;
}
} else if (this.fileAttribute[key] !== this.form.get(key).value) {
return true;
}
}
return false;
this.initialFormValue = this.form.getRawValue();
}
save() {
@ -69,7 +47,7 @@ export class AddEditFileAttributeDialogComponent extends BaseDialogComponent {
editable: !this.form.get('readonly').value,
...this.form.getRawValue(),
};
this.dialogRef.close(fileAttribute);
this._dialogRef.close(fileAttribute);
}
private _getForm(fileAttribute: IFileAttributeConfig): FormGroup {

View File

@ -28,11 +28,11 @@
</div>
<div class="dialog-actions">
<button (click)="save()" [disabled]="!valid || !changed" color="primary" mat-flat-button>
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button>
{{ 'edit-color-dialog.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,4 +1,4 @@
import { Component, Inject } from '@angular/core';
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';
@ -19,10 +19,7 @@ interface IEditColorData {
styleUrls: ['./edit-color-dialog.component.scss'],
})
export class EditColorDialogComponent extends BaseDialogComponent {
readonly form: FormGroup;
translations = defaultColorsTranslations;
readonly disabled = false;
private readonly _initialColor: string;
private readonly _dossierTemplateId: string;
constructor(
@ -30,23 +27,16 @@ export class EditColorDialogComponent extends BaseDialogComponent {
private readonly _dictionaryService: DictionaryService,
private readonly _toaster: Toaster,
private readonly _translateService: TranslateService,
private readonly _dialogRef: MatDialogRef<EditColorDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<EditColorDialogComponent>,
@Inject(MAT_DIALOG_DATA)
readonly data: IEditColorData,
) {
super();
super(_injector, _dialogRef);
this._dossierTemplateId = data.dossierTemplateId;
this._initialColor = data.colors[data.colorKey];
this.form = this._getForm();
}
get changed(): boolean {
return this.form.get('color').value !== this._initialColor;
}
get valid(): boolean {
return this.form.valid;
this.initialFormValue = this.form.getRawValue();
}
async save() {

View File

@ -34,6 +34,7 @@ export class AdminDialogService extends DialogService<DialogType> {
protected readonly _config: DialogConfig<DialogType> = {
confirm: {
component: ConfirmationDialogComponent,
dialogConfig: { disableClose: false },
},
addEditDictionary: {
component: AddEditDictionaryDialogComponent,
@ -49,18 +50,19 @@ export class AdminDialogService extends DialogService<DialogType> {
},
deleteFileAttribute: {
component: ConfirmDeleteFileAttributeDialogComponent,
dialogConfig: { disableClose: false },
},
importFileAttributes: {
component: FileAttributesCsvImportDialogComponent,
dialogConfig: largeDialogConfig,
dialogConfig: { ...largeDialogConfig, ...{ disableClose: false } },
},
deleteUsers: {
component: ConfirmDeleteUsersDialogComponent,
dialogConfig: { autoFocus: true },
dialogConfig: { autoFocus: true, disableClose: false },
},
addEditUser: {
component: AddEditUserDialogComponent,
dialogConfig: { autoFocus: true },
dialogConfig: { autoFocus: true, disableClose: false },
},
smtpAuthConfig: {
component: SmtpAuthDialogComponent,

View File

@ -1,5 +1,5 @@
<section class="dialog">
<form (submit)="saveDossier()" [formGroup]="form">
<form (submit)="save()" [formGroup]="form">
<div class="dialog-header heading-l" translate="add-dossier-dialog.header-new"></div>
<div class="dialog-content">
@ -91,7 +91,7 @@
</button>
<iqser-icon-button
(action)="saveDossier(true)"
(action)="save({ addMembers: true })"
[disabled]="disabled"
[label]="'add-dossier-dialog.actions.save-and-add-members' | translate"
[type]="iconButtonTypes.dark"

View File

@ -1,10 +1,10 @@
import { Component } from '@angular/core';
import { Component, Injector } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { DownloadFileType, IDossierRequest, IDossierTemplate, IReportTemplate } from '@red/domain';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import * as moment from 'moment';
import { downloadTypesTranslations } from '../../../../translations/download-types-translations';
import { IconButtonTypes } from '@iqser/common-ui';
import { BaseDialogComponent, IconButtonTypes, SaveOptions } from '@iqser/common-ui';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { ReportTemplateService } from '@services/report-template.service';
@ -13,10 +13,9 @@ import { ReportTemplateService } from '@services/report-template.service';
templateUrl: './add-dossier-dialog.component.html',
styleUrls: ['./add-dossier-dialog.component.scss'],
})
export class AddDossierDialogComponent {
export class AddDossierDialogComponent extends BaseDialogComponent {
readonly iconButtonTypes = IconButtonTypes;
readonly form: FormGroup;
hasDueDate = false;
downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'REDACTED'].map((type: DownloadFileType) => ({
key: type,
@ -30,10 +29,13 @@ export class AddDossierDialogComponent {
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _formBuilder: FormBuilder,
private readonly _reportTemplateController: ReportTemplateService,
readonly dialogRef: MatDialogRef<AddDossierDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<AddDossierDialogComponent>,
) {
super(_injector, _dialogRef);
this._getDossierTemplates();
this.form = this._getForm();
this.initialFormValue = this.form.getRawValue();
}
private _getForm(): FormGroup {
@ -75,10 +77,10 @@ export class AddDossierDialogComponent {
reportTemplateValueMapper = (reportTemplate: IReportTemplate) => reportTemplate.templateId;
async saveDossier(addMembers = false) {
async save(options?: SaveOptions) {
const savedDossier = await this._dossiersService.createOrUpdate(this._formToObject()).toPromise();
if (savedDossier) {
this.dialogRef.close({ dossier: savedDossier, addMembers });
this._dialogRef.close({ dossier: savedDossier, addMembers: options?.addMembers });
}
}

View File

@ -38,12 +38,12 @@
</div>
<div class="dialog-actions">
<button [disabled]="!form.valid || !changed" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'change-legal-basis-dialog.actions.save' | translate }}
</button>
<div class="all-caps-label cancel" mat-dialog-close translate="change-legal-basis-dialog.actions.cancel"></div>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,4 +1,4 @@
import { Component, Inject, OnInit } from '@angular/core';
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';
@ -6,6 +6,7 @@ import { PermissionsService } from '@services/permissions.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { JustificationsService } from '@services/entity-services/justifications.service';
import { Dossier } from '@red/domain';
import { BaseDialogComponent } from '@iqser/common-ui';
export interface LegalBasisOption {
label?: string;
@ -16,8 +17,7 @@ export interface LegalBasisOption {
@Component({
templateUrl: './change-legal-basis-dialog.component.html',
})
export class ChangeLegalBasisDialogComponent implements OnInit {
form: FormGroup = this._getForm();
export class ChangeLegalBasisDialogComponent extends BaseDialogComponent implements OnInit {
isDocumentAdmin: boolean;
legalOptions: LegalBasisOption[] = [];
@ -26,16 +26,12 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
private readonly _dossiersService: DossiersService,
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
readonly dialogRef: MatDialogRef<ChangeLegalBasisDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ChangeLegalBasisDialogComponent>,
@Inject(MAT_DIALOG_DATA) private readonly _data: { annotations: AnnotationWrapper[]; dossier: Dossier },
) {}
get changed(): boolean {
return (
this.form.get('reason').value.legalBasis !== this._data.annotations[0].legalBasis ||
this.form.get('section').value !== this._data.annotations[0].section ||
this.form.get('classification').value !== this._data.annotations[0].value
);
) {
super(_injector, _dialogRef);
this.form = this._getForm();
}
get allRectangles(): boolean {
@ -43,6 +39,7 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
}
async ngOnInit() {
super.ngOnInit();
const data = await this._justificationsService.getForDossierTemplate(this._data.dossier.dossierTemplateId).toPromise();
this.legalOptions = data
@ -56,6 +53,7 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
this.form.patchValue({
reason: this.legalOptions.find(option => option.legalBasis === this._data.annotations[0].legalBasis),
});
this.initialFormValue = this.form.getRawValue();
}
private _getForm(): FormGroup {
@ -69,7 +67,7 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
}
save() {
this.dialogRef.close({
this._dialogRef.close({
legalBasis: this.form.get('reason').value.legalBasis,
section: this.form.get('section').value,
comment: this.form.get('comment').value,

View File

@ -1,7 +1,7 @@
<section *ngIf="!!form" class="dialog">
<div class="dialog-header heading-l" translate="document-info.title"></div>
<form (submit)="saveDocumentInfo()" [formGroup]="form">
<form (submit)="save()" [formGroup]="form">
<div class="dialog-content">
<div *ngFor="let attr of attributes" class="iqser-input-group w-300">
<label>{{ attr.label }}</label>
@ -9,11 +9,11 @@
</div>
</div>
<div class="dialog-actions">
<button [disabled]="form.invalid" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'document-info.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,16 +1,17 @@
import { Component, Inject, OnInit } from '@angular/core';
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup } 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';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { FilesService } from '@services/entity-services/files.service';
import { BaseDialogComponent } from '@iqser/common-ui';
@Component({
templateUrl: './document-info-dialog.component.html',
styleUrls: ['./document-info-dialog.component.scss'],
})
export class DocumentInfoDialogComponent implements OnInit {
export class DocumentInfoDialogComponent extends BaseDialogComponent implements OnInit {
form: FormGroup;
attributes: IFileAttributeConfig[];
@ -21,27 +22,31 @@ export class DocumentInfoDialogComponent implements OnInit {
private readonly _formBuilder: FormBuilder,
private readonly _fileAttributesService: FileAttributesService,
private readonly _filesService: FilesService,
public dialogRef: MatDialogRef<DocumentInfoDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<DocumentInfoDialogComponent>,
@Inject(MAT_DIALOG_DATA) readonly data: File,
) {
super(_injector, _dialogRef);
this._dossier = this._dossiersService.find(this.data.dossierId);
}
async ngOnInit() {
super.ngOnInit();
this.attributes = (
await this._fileAttributesService.getFileAttributesConfig(this._dossier.dossierTemplateId).toPromise()
).fileAttributeConfigs.filter(attr => attr.editable);
this.form = this._getForm();
this.initialFormValue = this.form.getRawValue();
}
async saveDocumentInfo() {
async save() {
const attributeIdToValue = {
...this.data.fileAttributes?.attributeIdToValue,
...this.form.getRawValue(),
};
await this._fileAttributesService.setFileAttributes({ attributeIdToValue }, this.data.dossierId, this.data.fileId).toPromise();
this._filesService.reload(this.data.dossierId, this.data.fileId);
this.dialogRef.close(true);
this._dialogRef.close(true);
}
private _getForm(): FormGroup {

View File

@ -53,7 +53,7 @@
{{ 'edit-dossier-dialog.actions.save' | translate }}
</button>
<iqser-icon-button
(action)="save(true)"
(action)="save({ closeAfterSave: true })"
[disabled]="disabled || !valid || !changed"
[label]="'edit-dossier-dialog.actions.save-and-close' | translate"
[type]="iconButtonTypes.dark"
@ -65,5 +65,5 @@
</div>
</div>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,10 +1,10 @@
import { ChangeDetectorRef, Component, Inject, ViewChild } from '@angular/core';
import { ChangeDetectorRef, Component, Inject, Injector, ViewChild } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Dossier } from '@red/domain';
import { EditDossierGeneralInfoComponent } from './general-info/edit-dossier-general-info.component';
import { EditDossierDownloadPackageComponent } from './download-package/edit-dossier-download-package.component';
import { EditDossierSectionInterface } from './edit-dossier-section.interface';
import { BaseDialogComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
import { BaseDialogComponent, ConfirmOptions, IconButtonTypes, LoadingService, SaveOptions, Toaster } from '@iqser/common-ui';
import { EditDossierDictionaryComponent } from './dictionary/edit-dossier-dictionary.component';
import { EditDossierAttributesComponent } from './attributes/edit-dossier-attributes.component';
@ -40,16 +40,17 @@ export class EditDossierDialogComponent extends BaseDialogComponent {
private readonly _toaster: Toaster,
private readonly _dossiersService: DossiersService,
private readonly _changeRef: ChangeDetectorRef,
private readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
private readonly _loadingService: LoadingService,
private readonly _permissionsService: PermissionsService,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
@Inject(MAT_DIALOG_DATA)
private readonly _data: {
dossierId: string;
section?: Section;
},
) {
super();
super(_injector, _dialogRef);
this.navItems = [
{
key: 'dossierInfo',
@ -126,7 +127,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent {
return this.activeComponent?.disabled;
}
async save(closeAfterSave: boolean = false) {
async save(options?: SaveOptions) {
this._loadingService.start();
const result = await this.activeComponent.save();
this._loadingService.stop();
@ -135,7 +136,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent {
this._toaster.success(_('edit-dossier-dialog.change-successful'), { params: { dossierName: this._dossierName } });
}
if (result.success && closeAfterSave) {
if (result.success && options?.closeAfterSave) {
this._dialogRef.close();
}
}
@ -146,9 +147,19 @@ export class EditDossierDialogComponent extends BaseDialogComponent {
changeTab(key: Section) {
if (this.changed) {
this._toaster.error(_('edit-dossier-dialog.unsaved-changes'));
return;
this._openConfirmDialog().then(async result => {
if (result in ConfirmOptions) {
if (result === ConfirmOptions.CONFIRM) {
await this.save();
} else {
this.revert();
}
this.activeNav = key;
}
this._waitingForConfirmation = false;
});
} else {
this.activeNav = key;
}
this.activeNav = key;
}
}

View File

@ -1,5 +1,5 @@
<section class="dialog">
<form (submit)="handleForceAnnotation()" [formGroup]="redactionForm">
<form (submit)="save()" [formGroup]="form">
<div class="dialog-header heading-l" translate="manual-annotation.dialog.header.force-redaction" *ngIf="!isHintDialog"></div>
<div class="dialog-header heading-l" translate="manual-annotation.dialog.header.force-hint" *ngIf="isHintDialog"></div>
@ -19,7 +19,7 @@
<div class="iqser-input-group w-400" *ngIf="!isHintDialog">
<label translate="manual-annotation.dialog.content.legalBasis"></label>
<input [value]="redactionForm.get('reason').value?.legalBasis" disabled type="text" />
<input [value]="form.get('reason').value?.legalBasis" disabled type="text" />
</div>
<div [class.required]="!isDocumentAdmin" class="iqser-input-group w-300">
@ -29,11 +29,11 @@
</div>
<div class="dialog-actions">
<button [disabled]="!redactionForm.valid" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'manual-annotation.dialog.actions.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,7 +1,7 @@
import { Component, Inject, OnInit } from '@angular/core';
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Toaster } from '@iqser/common-ui';
import { BaseDialogComponent, Toaster } from '@iqser/common-ui';
import { TranslateService } from '@ngx-translate/core';
import { UserService } from '@services/user.service';
import { ManualAnnotationService } from '../../services/manual-annotation.service';
@ -21,8 +21,7 @@ export interface LegalBasisOption {
templateUrl: './force-annotation-dialog.component.html',
styleUrls: ['./force-annotation-dialog.component.scss'],
})
export class ForceAnnotationDialogComponent implements OnInit {
redactionForm: FormGroup;
export class ForceAnnotationDialogComponent extends BaseDialogComponent implements OnInit {
isDocumentAdmin: boolean;
legalOptions: LegalBasisOption[] = [];
@ -35,10 +34,13 @@ export class ForceAnnotationDialogComponent implements OnInit {
private readonly _justificationsService: JustificationsService,
private readonly _manualAnnotationService: ManualAnnotationService,
private readonly _permissionsService: PermissionsService,
public dialogRef: MatDialogRef<ForceAnnotationDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ForceAnnotationDialogComponent>,
@Inject(MAT_DIALOG_DATA) private readonly _data: { readonly dossier: Dossier; readonly hint: boolean },
) {
this.redactionForm = this._getForm();
super(_injector, _dialogRef);
this.form = this._getForm();
this.initialFormValue = this.form.getRawValue();
}
get isHintDialog() {
@ -55,6 +57,7 @@ export class ForceAnnotationDialogComponent implements OnInit {
}
async ngOnInit() {
super.ngOnInit();
const data = await this._justificationsService.getForDossierTemplate(this._data.dossier.dossierTemplateId).toPromise();
this.legalOptions = data.map(lbm => ({
@ -66,17 +69,17 @@ export class ForceAnnotationDialogComponent implements OnInit {
this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
}
handleForceAnnotation() {
this.dialogRef.close(this._createForceRedactionRequest());
save() {
this._dialogRef.close(this._createForceRedactionRequest());
}
private _createForceRedactionRequest(): ILegalBasisChangeRequest {
const request: ILegalBasisChangeRequest = {};
const legalOption: LegalBasisOption = this.redactionForm.get('reason').value;
const legalOption: LegalBasisOption = this.form.get('reason').value;
request.legalBasis = legalOption.legalBasis;
request.comment = this.redactionForm.get('comment').value;
request.comment = this.form.get('comment').value;
return request;
}

View File

@ -1,5 +1,5 @@
<section class="dialog">
<form (submit)="handleAddRedaction()" [formGroup]="redactionForm">
<form (submit)="save()" [formGroup]="form">
<div [translate]="title" class="dialog-header heading-l"></div>
<div class="dialog-content">
@ -54,7 +54,7 @@
<div *ngIf="!isDictionaryRequest" class="iqser-input-group w-400">
<label translate="manual-annotation.dialog.content.legalBasis"></label>
<input [value]="redactionForm.get('reason').value?.legalBasis" disabled type="text" />
<input [value]="form.get('reason').value?.legalBasis" disabled type="text" />
</div>
<div *ngIf="data.manualRedactionEntryWrapper.manualRedactionEntry.rectangle" class="iqser-input-group w-400">
@ -74,11 +74,11 @@
</div>
<div class="dialog-actions">
<button [disabled]="!redactionForm.valid" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'manual-annotation.dialog.actions.save' | translate }}
</button>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,4 +1,4 @@
import { Component, Inject, OnInit } from '@angular/core';
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { AppStateService } from '@state/app-state.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@ -9,6 +9,7 @@ import { PermissionsService } from '@services/permissions.service';
import { JustificationsService } from '@services/entity-services/justifications.service';
import { Dictionary, Dossier, File, IAddRedactionRequest } from '@red/domain';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { BaseDialogComponent } from '@iqser/common-ui';
import { DictionaryService } from '@shared/services/dictionary.service';
export interface LegalBasisOption {
@ -22,9 +23,7 @@ export interface LegalBasisOption {
templateUrl: './manual-annotation-dialog.component.html',
styleUrls: ['./manual-annotation-dialog.component.scss'],
})
export class ManualAnnotationDialogComponent implements OnInit {
redactionForm: FormGroup;
export class ManualAnnotationDialogComponent extends BaseDialogComponent implements OnInit {
isDocumentAdmin: boolean;
isDictionaryRequest: boolean;
isFalsePositiveRequest: boolean;
@ -43,15 +42,19 @@ export class ManualAnnotationDialogComponent implements OnInit {
private readonly _dossiersService: DossiersService,
private readonly _dictionaryService: DictionaryService,
public dialogRef: MatDialogRef<ManualAnnotationDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ManualAnnotationDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { manualRedactionEntryWrapper: ManualRedactionEntryWrapper; file: File },
) {
super(_injector, _dialogRef);
this._dossier = this._dossiersService.find(this.data.file.dossierId);
this.isDocumentAdmin = this._permissionsService.isApprover(this._dossier);
this.isFalsePositiveRequest = this.data.manualRedactionEntryWrapper.type === 'FALSE_POSITIVE';
this.isDictionaryRequest = this.data.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest;
this.redactionForm = this._getForm();
this.form = this._getForm();
this.initialFormValue = this.form.getRawValue();
}
get title() {
@ -59,7 +62,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
}
get displayedDictionaryLabel() {
const dictType = this.redactionForm.get('dictionary').value;
const dictType = this.form.get('dictionary').value;
if (dictType) {
return this.possibleDictionaries.find(d => d.type === dictType).label;
}
@ -92,6 +95,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
}
async ngOnInit() {
super.ngOnInit();
this.possibleDictionaries = await this._getPossibleDictionaries();
const data = await this._justificationsService.getForDossierTemplate(this._dossier.dossierTemplateId).toPromise();
@ -104,11 +108,11 @@ export class ManualAnnotationDialogComponent implements OnInit {
this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
}
handleAddRedaction() {
save() {
this._enhanceManualRedaction(this.data.manualRedactionEntryWrapper.manualRedactionEntry);
this._manualAnnotationService.addAnnotation(this.data.manualRedactionEntryWrapper.manualRedactionEntry, this.data.file).subscribe(
response => this.dialogRef.close(new ManualAnnotationResponse(this.data.manualRedactionEntryWrapper, response)),
() => this.dialogRef.close(),
response => this._dialogRef.close(new ManualAnnotationResponse(this.data.manualRedactionEntryWrapper, response)),
() => this._dialogRef.close(),
);
}
@ -133,8 +137,8 @@ export class ManualAnnotationDialogComponent implements OnInit {
}
private _enhanceManualRedaction(addRedactionRequest: IAddRedactionRequest) {
const legalOption: LegalBasisOption = this.redactionForm.get('reason').value;
addRedactionRequest.type = this.redactionForm.get('dictionary').value;
const legalOption: LegalBasisOption = this.form.get('reason').value;
addRedactionRequest.type = this.form.get('dictionary').value;
if (legalOption) {
addRedactionRequest.reason = legalOption.description;
addRedactionRequest.legalBasis = legalOption.legalBasis;
@ -146,11 +150,13 @@ export class ManualAnnotationDialogComponent implements OnInit {
if (!addRedactionRequest.reason) {
addRedactionRequest.reason = 'Dictionary Request';
}
const commentValue = this.redactionForm.get('comment').value;
const commentValue = this.form.get('comment').value;
addRedactionRequest.comment = commentValue ? { text: commentValue } : null;
addRedactionRequest.section = this.redactionForm.get('section').value;
addRedactionRequest.value = addRedactionRequest.rectangle
? this.redactionForm.get('classification').value
: addRedactionRequest.value;
addRedactionRequest.section = this.form.get('section').value;
addRedactionRequest.value = addRedactionRequest.rectangle ? this.form.get('classification').value : addRedactionRequest.value;
}
get disabled() {
return this.form.invalid;
}
}

View File

@ -1,5 +1,5 @@
<section class="dialog">
<form (submit)="save()" [formGroup]="recategorizeImageForm">
<form (submit)="save()" [formGroup]="form">
<div class="dialog-header heading-l" translate="recategorize-image-dialog.header"></div>
<div class="dialog-content">
@ -23,12 +23,12 @@
</div>
<div class="dialog-actions">
<button [disabled]="!recategorizeImageForm.valid || !changed" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'recategorize-image-dialog.actions.save' | translate }}
</button>
<div class="all-caps-label cancel" mat-dialog-close translate="recategorize-image-dialog.actions.cancel"></div>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,17 +1,17 @@
import { Component, Inject, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { FormBuilder, Validators } from '@angular/forms';
import { PermissionsService } from '@services/permissions.service';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { imageCategoriesTranslations } from '../../translations/image-categories-translations';
import { ImageCategory } from '../../models/image-category.model';
import { Dossier } from '@red/domain';
import { BaseDialogComponent } from '@iqser/common-ui';
@Component({
templateUrl: './recategorize-image-dialog.component.html',
})
export class RecategorizeImageDialogComponent implements OnInit {
recategorizeImageForm: FormGroup;
export class RecategorizeImageDialogComponent extends BaseDialogComponent implements OnInit {
isDocumentAdmin: boolean;
typeOptions: ImageCategory[] = ['signature', 'logo', 'formula', 'image'];
translations = imageCategoriesTranslations;
@ -19,27 +19,32 @@ export class RecategorizeImageDialogComponent implements OnInit {
constructor(
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef<RecategorizeImageDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<RecategorizeImageDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: { annotations: AnnotationWrapper[]; dossier: Dossier },
) {}
) {
super(_injector, _dialogRef);
}
get changed(): boolean {
return this.recategorizeImageForm.get('type').value !== this.data.annotations[0].type;
return this.form.get('type').value !== this.data.annotations[0].type;
}
ngOnInit() {
super.ngOnInit();
this.isDocumentAdmin = this._permissionsService.isApprover(this.data.dossier);
this.recategorizeImageForm = this._formBuilder.group({
this.form = this._formBuilder.group({
type: [this.data.annotations[0].type, Validators.required],
comment: this.isDocumentAdmin ? [null] : [null, Validators.required],
});
this.initialFormValue = this.form.getRawValue();
}
save() {
this.dialogRef.close({
type: this.recategorizeImageForm.get('type').value,
comment: this.recategorizeImageForm.get('comment').value,
this._dialogRef.close({
type: this.form.get('type').value,
comment: this.form.get('comment').value,
});
}
}

View File

@ -7,7 +7,7 @@
) | translate: { hint: data.hint }
}}
</div>
<form (submit)="confirm()" [formGroup]="redactionForm">
<form (submit)="save()" [formGroup]="form">
<div class="dialog-content">
{{
(data.removeFromDictionary
@ -46,12 +46,12 @@
</div>
<div class="dialog-actions">
<button [disabled]="!redactionForm.valid" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'remove-annotations-dialog.confirm' | translate }}
</button>
<div class="all-caps-label cancel" mat-dialog-close translate="remove-annotations-dialog.cancel"></div>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,10 +1,10 @@
import { Component, Inject } from '@angular/core';
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 { PermissionsService } from '@services/permissions.service';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { humanize } from '@iqser/common-ui';
import { FormBuilder, Validators } from '@angular/forms';
import { BaseDialogComponent, humanize } from '@iqser/common-ui';
import { Dossier } from '@red/domain';
export interface RemoveAnnotationsDialogInput {
@ -18,23 +18,24 @@ export interface RemoveAnnotationsDialogInput {
templateUrl: './remove-annotations-dialog.component.html',
styleUrls: ['./remove-annotations-dialog.component.scss'],
})
export class RemoveAnnotationsDialogComponent {
redactionForm: FormGroup;
export class RemoveAnnotationsDialogComponent extends BaseDialogComponent {
constructor(
private readonly _translateService: TranslateService,
private readonly _formBuilder: FormBuilder,
readonly permissionsService: PermissionsService,
public dialogRef: MatDialogRef<RemoveAnnotationsDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<RemoveAnnotationsDialogComponent>,
@Inject(MAT_DIALOG_DATA) public data: RemoveAnnotationsDialogInput,
) {
this.redactionForm = this._formBuilder.group({
super(_injector, _dialogRef);
this.form = this._formBuilder.group({
comment: this.permissionsService.isApprover(this.data.dossier) ? [null] : [null, Validators.required],
});
this.initialFormValue = this.form.getRawValue();
}
confirm() {
this.dialogRef.close({ comment: this.redactionForm.getRawValue().comment });
save() {
this._dialogRef.close({ comment: this.form.getRawValue().comment });
}
printable(annotation: AnnotationWrapper) {

View File

@ -1,5 +1,5 @@
<section class="dialog">
<form (submit)="save()" [formGroup]="resizeForm">
<form (submit)="save()" [formGroup]="form">
<div class="dialog-header heading-l" translate="resize-annotation-dialog.header"></div>
<div class="dialog-content">
@ -10,12 +10,12 @@
</div>
<div class="dialog-actions">
<button [disabled]="!resizeForm.valid" color="primary" mat-flat-button type="submit">
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
{{ 'resize-annotation-dialog.actions.save' | translate }}
</button>
<div class="all-caps-label cancel" mat-dialog-close translate="resize-annotation-dialog.actions.cancel"></div>
</div>
</form>
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
</section>

View File

@ -1,34 +1,40 @@
import { Component, Inject, OnInit } from '@angular/core';
import { Component, Inject, Injector, OnInit } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { FormBuilder, Validators } from '@angular/forms';
import { PermissionsService } from '@services/permissions.service';
import { Dossier } from '@red/domain';
import { BaseDialogComponent } from '@iqser/common-ui';
@Component({
templateUrl: './resize-annotation-dialog.component.html',
})
export class ResizeAnnotationDialogComponent implements OnInit {
resizeForm: FormGroup;
export class ResizeAnnotationDialogComponent extends BaseDialogComponent implements OnInit {
isDocumentAdmin: boolean;
constructor(
private readonly _permissionsService: PermissionsService,
private readonly _formBuilder: FormBuilder,
public dialogRef: MatDialogRef<ResizeAnnotationDialogComponent>,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef<ResizeAnnotationDialogComponent>,
@Inject(MAT_DIALOG_DATA) private readonly _data: { dossier: Dossier },
) {}
) {
super(_injector, _dialogRef);
}
ngOnInit() {
super.ngOnInit();
this.isDocumentAdmin = this._permissionsService.isApprover(this._data.dossier);
this.resizeForm = this._formBuilder.group({
this.form = this._formBuilder.group({
comment: this.isDocumentAdmin ? [null] : [null, Validators.required],
});
this.initialFormValue = this.form.getRawValue();
}
save() {
this.dialogRef.close({
comment: this.resizeForm.get('comment').value,
this._dialogRef.close({
comment: this.form.get('comment').value,
});
}
}

View File

@ -5,10 +5,15 @@
[showCloseButton]="true"
[viewModeSelection]="viewModeSelection"
>
<redaction-file-download-btn [files]="entitiesService.all$ | async" tooltipPosition="below"></redaction-file-download-btn>
<redaction-file-download-btn
[disabled]="listingService.areSomeSelected$ | async"
[files]="entitiesService.all$ | async"
tooltipPosition="below"
></redaction-file-download-btn>
<iqser-circle-button
(action)="exportFilesAsCSV()"
[disabled]="listingService.areSomeSelected$ | async"
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
icon="iqser:csv"
tooltipPosition="below"
@ -17,7 +22,8 @@
<iqser-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn(dossier) && analysisForced"
[tooltipClass]="'small ' + ((listingService.areSomeSelected$ | async) ? '' : 'warn')"
[disabled]="listingService.areSomeSelected$ | async"
[tooltipClass]="'small warn'"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
[type]="circleButtonTypes.warn"
icon="iqser:refresh"

View File

@ -47,7 +47,7 @@ export class ScreenHeaderComponent implements OnInit {
) {}
ngOnInit() {
this.actionConfigs = this.configService.actionConfig(this.dossier.dossierId);
this.actionConfigs = this.configService.actionConfig(this.dossier.dossierId, this.listingService.areSomeSelected$);
}
async reanalyseDossier() {

View File

@ -102,7 +102,7 @@ export class ConfigService {
};
}
actionConfig(dossierId: string): List<ActionConfig> {
actionConfig(dossierId: string, disabled$: Observable<boolean>): List<ActionConfig> {
return [
{
label: this._translateService.instant('dossier-overview.header-actions.edit'),
@ -110,6 +110,7 @@ export class ConfigService {
icon: 'iqser:edit',
hide: !this._userService.currentUser.isManager,
helpModeKey: 'edit-dossier-attributes',
disabled$,
},
];
}

View File

@ -41,7 +41,6 @@ export class AnnotationsListComponent implements OnChanges {
if (this.canMultiSelect && ($event.ctrlKey || $event.metaKey) && this.selectedAnnotations.length > 0) {
this.multiSelectService.activate();
}
console.log('emit', annotation);
this.selectAnnotations.emit([annotation]);
}
}

View File

@ -475,24 +475,27 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
const previousFile = this._fileData?.file;
await this._loadFileData(file);
const fileHasBeenExcludedOrIncluded = previousFile?.excluded !== this._fileData?.file?.excluded;
const excludedPagesHaveChanged =
JSON.stringify(previousFile?.excludedPages) !== JSON.stringify(this._fileData?.file?.excludedPages);
if (fileHasBeenExcludedOrIncluded || excludedPagesHaveChanged) {
this._deleteAnnotations();
await this._cleanupAndRedrawAnnotations();
// file already loaded at least once
if (previousFile) {
// If it has been OCRd, we need to wait for it to load into the viewer
if (previousFile.lastOCRTime !== this._fileData?.file?.lastOCRTime) {
return;
}
// excluded pages or document exclusion has changed
const fileHasBeenExcludedOrIncluded = previousFile.excluded !== this._fileData.file.excluded;
const excludedPagesHaveChanged =
JSON.stringify(previousFile.excludedPages) !== JSON.stringify(this._fileData.file.excludedPages);
if (fileHasBeenExcludedOrIncluded || excludedPagesHaveChanged) {
await this._deleteAnnotations();
await this._cleanupAndRedrawAnnotations();
}
}
await this._stampPDF();
}
private async _stampPDF() {
if (!this._instance) {
return;
}
const document = this._instance.Core.documentViewer.getDocument();
if (!document) {
if (!this._instance?.Core.documentViewer.getDocument()) {
return;
}
@ -630,6 +633,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
}
private _deleteAnnotations(annotationsToDelete?: AnnotationWrapper[]) {
if (!this._instance?.Core.documentViewer.getDocument()) {
return;
}
if (!annotationsToDelete) {
this._instance.Core.annotationManager.deleteAnnotations(this._instance.Core.annotationManager.getAnnotationsList(), {
imported: true,
@ -645,6 +652,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
currentAnnotations?: AnnotationWrapper[],
newAnnotationsFilter?: (annotation: AnnotationWrapper) => boolean,
) {
if (!this._instance?.Core.documentViewer.getDocument()) {
return;
}
this.rebuildFilters();
if (this.viewModeService.viewMode === 'STANDARD') {

View File

@ -30,6 +30,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
protected readonly _config: DialogConfig<DialogType> = {
confirm: {
component: ConfirmationDialogComponent,
dialogConfig: { disableClose: false },
},
documentInfo: {
component: DocumentInfoDialogComponent,
@ -45,6 +46,7 @@ export class DossiersDialogService extends DialogService<DialogType> {
},
assignFile: {
component: AssignReviewerApproverDialogComponent,
dialogConfig: { disableClose: false },
},
recategorizeImage: {
component: RecategorizeImageDialogComponent,

View File

@ -98,9 +98,9 @@ export function removeBraces(str: any): string {
return str.replace(/[{}]/g, '');
}
export function toKebabCase(str: string): string {
export function toSnakeCase(str: string): string {
return str
.replace(/([a-z])([A-Z])/g, '$1-$2')
.replace(/[\s_]+/g, '-')
.replace(/[\s_]+/g, '_')
.toLowerCase();
}

View File

@ -448,6 +448,13 @@
"question": "Are you sure you want to delete {filesCount, plural, one{this document} other{these documents}}?",
"title": "Delete {filesCount, plural, one{{fileName}} other{Selected Documents}}"
},
"unsaved-changes": {
"confirmation-text": "Save and Leave",
"details": "If you leave the tab without saving, all the unsaved changes will be lost.",
"discard-changes-text": "DISCARD CHANGES",
"question": "Are you sure you want to leave the tab? You have unsaved changes.",
"title": "You have unsaved changes"
},
"upload-report-template": {
"alternate-confirmation-text": "Upload as multi-file report",
"confirmation-text": "Upload as single-file report",
@ -940,8 +947,7 @@
"members": "Members",
"team-members": "Team Members"
},
"side-nav-title": "Configurations",
"unsaved-changes": "You have unsaved changes. Save or revert before changing the tab."
"side-nav-title": "Configurations"
},
"error": {
"deleted-entity": {

@ -1 +1 @@
Subproject commit 85ec2446a35436786573dfdad8fc5c7bb16d5ac0
Subproject commit 95644f59e4e32517d76e0bd9267805a88ebdd8d1

View File

@ -1,6 +1,6 @@
{
"name": "redaction",
"version": "3.169.0",
"version": "3.173.0",
"private": true,
"license": "MIT",
"scripts": {

Binary file not shown.