RED-6453 - Value for attribute in file list cannot be set

This commit is contained in:
Valentin Mihai 2023-04-06 13:44:02 +03:00
parent 783f6fc0e4
commit f82361633f
3 changed files with 69 additions and 73 deletions

View File

@ -4,41 +4,39 @@
<span class="clamp-3"> {{ fileAttributeValue ? (fileAttributeValue | date : 'd MMM yyyy') : '-' }}</span> <span class="clamp-3"> {{ fileAttributeValue ? (fileAttributeValue | date : 'd MMM yyyy') : '-' }}</span>
</ng-template> </ng-template>
<ng-container *ngIf="(isEditingFileAttribute$ | async) === false || isInEditMode"> <ng-container *ngIf="((fileAttributesService.isEditingFileAttribute$ | async) === false || isInEditMode) && !file.isProcessing">
<div class="edit-button" *ngIf="!isInEditMode; else input"> <div *ngIf="!isInEditMode; else input" class="edit-button">
<iqser-circle-button <iqser-circle-button
id="edit-attribute-button"
*ngIf="permissionsService.canEditFileAttributes(file, dossier)"
(action)="editFileAttribute($event)" (action)="editFileAttribute($event)"
[icon]="'iqser:edit'" *ngIf="permissionsService.canEditFileAttributes(file, dossier)"
[disabled]="!fileAttribute.editable" [disabled]="!fileAttribute.editable"
[icon]="'iqser:edit'"
[tooltip]="'file-attribute.actions.edit' | translate" [tooltip]="'file-attribute.actions.edit' | translate"
id="edit-attribute-button"
></iqser-circle-button> ></iqser-circle-button>
</div> </div>
<ng-template #input> <ng-template #input>
<div class="edit-input" (click)="$event?.stopPropagation()"> <div class="edit-input" stopPropagation>
<form (submit)="save()" [formGroup]="form"> <form (submit)="save()" [formGroup]="form">
<iqser-dynamic-input <iqser-dynamic-input
(closedDatepicker)="closedDatepicker = $event"
(keydown.escape)="close()"
[formControlName]="fileAttribute.id" [formControlName]="fileAttribute.id"
[id]="fileAttribute.id" [id]="fileAttribute.id"
[type]="fileAttribute.type" [type]="fileAttribute.type"
(keydown.escape)="close()" ></iqser-dynamic-input>
(closedDatepicker)="closedDatepicker = $event"
>
</iqser-dynamic-input>
<iqser-circle-button <iqser-circle-button
class="save"
[icon]="'iqser:check'"
[disabled]="disabled"
(action)="save($event)" (action)="save($event)"
[disabled]="disabled"
[icon]="'iqser:check'"
class="save"
></iqser-circle-button> ></iqser-circle-button>
<iqser-circle-button [icon]="'iqser:close'" (action)="close($event)"></iqser-circle-button>
<iqser-circle-button (action)="close($event)" [icon]="'iqser:close'"></iqser-circle-button>
</form> </form>
</div> </div>
</ng-template> </ng-template>
</ng-container> </ng-container>
</div> </div>
<!-- A hack to avoid subscribing in component -->
<ng-container *ngIf="selectedFile$ | async"></ng-container>

View File

@ -1,10 +1,10 @@
import { ChangeDetectionStrategy, Component, HostListener, Input, OnInit } from '@angular/core'; import { Component, HostListener, Input, OnDestroy, OnInit } from '@angular/core';
import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain'; import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
import { BaseFormComponent, ListingService, Toaster } from '@iqser/common-ui'; import { BaseFormComponent, ListingService, Toaster } from '@iqser/common-ui';
import { PermissionsService } from '@services/permissions.service'; import { PermissionsService } from '@services/permissions.service';
import { FormBuilder, UntypedFormGroup } from '@angular/forms'; import { FormBuilder, UntypedFormGroup } from '@angular/forms';
import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { BehaviorSubject, firstValueFrom, Observable } from 'rxjs'; import { firstValueFrom, Subscription } from 'rxjs';
import { FilesService } from '@services/files/files.service'; import { FilesService } from '@services/files/files.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
@ -15,48 +15,34 @@ import { filter, map, tap } from 'rxjs/operators';
selector: 'redaction-file-attribute [fileAttribute] [file] [dossier]', selector: 'redaction-file-attribute [fileAttribute] [file] [dossier]',
templateUrl: './file-attribute.component.html', templateUrl: './file-attribute.component.html',
styleUrls: ['./file-attribute.component.scss'], styleUrls: ['./file-attribute.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class FileAttributeComponent extends BaseFormComponent implements OnInit { export class FileAttributeComponent extends BaseFormComponent implements OnDestroy {
@Input() fileAttribute!: IFileAttributeConfig; @Input() fileAttribute!: IFileAttributeConfig;
@Input() file!: File; @Input() file!: File;
@Input() dossier!: Dossier; @Input() dossier!: Dossier;
isInEditMode = false; isInEditMode = false;
closedDatepicker = true; closedDatepicker = true;
readonly isEditingFileAttribute$: BehaviorSubject<boolean>; readonly #subscriptions = new Subscription();
readonly selectedFile$: Observable<boolean>;
constructor( constructor(
private readonly _fileAttributesService: FileAttributesService, router: Router,
private readonly _toaster: Toaster, private readonly _toaster: Toaster,
private readonly _formBuilder: FormBuilder, private readonly _formBuilder: FormBuilder,
private readonly _filesService: FilesService, private readonly _filesService: FilesService,
private readonly _router: Router,
private readonly _listingService: ListingService<File>,
readonly permissionsService: PermissionsService, readonly permissionsService: PermissionsService,
private readonly _listingService: ListingService<File>,
readonly fileAttributesService: FileAttributesService,
) { ) {
super(); super();
this.isEditingFileAttribute$ = this._fileAttributesService.isEditingFileAttribute$; const sub = router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => this.close());
this.#subscriptions.add(sub);
_router.events.pipe(filter(event => event instanceof NavigationEnd)).subscribe(() => { const sub2 = this._listingService.selectedLength$.pipe(
this.close();
});
this.selectedFile$ = this._listingService.selectedLength$.pipe(
map(selectedLength => !!selectedLength), map(selectedLength => !!selectedLength),
tap(() => this.close()), tap(() => this.close()),
); );
} this.#subscriptions.add(sub2.subscribe());
ngOnInit(): void {
if (this.#noFileAttributes) {
this.#initFileAttributes();
}
this.form = this.#getForm();
this.initialFormValue = this.form.getRawValue();
} }
get isDate(): boolean { get isDate(): boolean {
@ -67,41 +53,27 @@ export class FileAttributeComponent extends BaseFormComponent implements OnInit
return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id]; return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id];
} }
get #noFileAttributes(): boolean { ngOnDestroy() {
return JSON.stringify(this.file.fileAttributes.attributeIdToValue) === '{}'; this.#subscriptions.unsubscribe();
}
#initFileAttributes() {
const configs = this._fileAttributesService.getFileAttributeConfig(this.file.dossierTemplateId).fileAttributeConfigs;
configs.forEach(config => (this.file.fileAttributes.attributeIdToValue[config.id] = null));
} }
async editFileAttribute($event: MouseEvent): Promise<void> { async editFileAttribute($event: MouseEvent): Promise<void> {
$event?.stopPropagation(); $event.stopPropagation();
this.#toggleEdit(); this.#toggleEdit();
} }
#getForm(): UntypedFormGroup { async save($event?: MouseEvent) {
const config = {};
const fileAttributes = this.file.fileAttributes.attributeIdToValue;
Object.keys(fileAttributes).forEach(key => {
const attrValue = fileAttributes[key];
config[key] = [dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue];
});
return this._formBuilder.group(config);
}
async save($event?: MouseEvent): Promise<void> {
$event?.stopPropagation(); $event?.stopPropagation();
const rawFormValue = this.form.getRawValue(); const rawFormValue = this.form.getRawValue();
const fileAttrValue = rawFormValue[this.fileAttribute.id]; const fileAttrValue = rawFormValue[this.fileAttribute.id];
const attributeIdToValue = { const attributeIdToValue = {
...rawFormValue, ...this.#getForm().getRawValue(),
[this.fileAttribute.id]: this.#formatAttributeValue(fileAttrValue), [this.fileAttribute.id]: this.#formatAttributeValue(fileAttrValue),
}; };
try { try {
await firstValueFrom( await firstValueFrom(
this._fileAttributesService.setFileAttributes({ attributeIdToValue }, this.file.dossierId, this.file.fileId), this.fileAttributesService.setFileAttributes({ attributeIdToValue }, this.file.dossierId, this.file.fileId),
); );
await firstValueFrom(this._filesService.reload(this.file.dossierId, this.file)); await firstValueFrom(this._filesService.reload(this.file.dossierId, this.file));
this.initialFormValue = rawFormValue; this.initialFormValue = rawFormValue;
@ -115,19 +87,52 @@ export class FileAttributeComponent extends BaseFormComponent implements OnInit
close($event?: MouseEvent): void { close($event?: MouseEvent): void {
$event?.stopPropagation(); $event?.stopPropagation();
if (this.isInEditMode) { if (this.isInEditMode) {
this.form = this.#getForm(); this.form = this.#getForm();
this.#toggleEdit(); this.#toggleEdit();
} }
} }
@HostListener('document:click')
clickOutside() {
if (this.isInEditMode && this.closedDatepicker) {
this.close();
}
}
#initFileAttributes() {
const configs = this.fileAttributesService.getFileAttributeConfig(this.file.dossierTemplateId).fileAttributeConfigs;
configs.forEach(config => {
if (!this.file.fileAttributes.attributeIdToValue[config.id]) {
this.file.fileAttributes.attributeIdToValue[config.id] = null;
}
});
}
#getForm(): UntypedFormGroup {
const config = {};
const fileAttributes = this.file.fileAttributes.attributeIdToValue;
Object.keys(fileAttributes).forEach(key => {
const attrValue = fileAttributes[key];
config[key] = [dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue];
});
return this._formBuilder.group(config);
}
#formatAttributeValue(attrValue) { #formatAttributeValue(attrValue) {
return this.isDate ? attrValue && dayjs(attrValue).format('YYYY-MM-DD') : attrValue; return this.isDate ? attrValue && dayjs(attrValue).format('YYYY-MM-DD') : attrValue;
} }
#toggleEdit(): void { #toggleEdit(): void {
if (!this.isInEditMode) {
this.#initFileAttributes();
this.form = this.#getForm();
this.initialFormValue = this.form.getRawValue();
}
this.isInEditMode = !this.isInEditMode; this.isInEditMode = !this.isInEditMode;
this.isEditingFileAttribute$.next(this.isInEditMode); this.fileAttributesService.isEditingFileAttribute$.next(this.isInEditMode);
if (this.isInEditMode) { if (this.isInEditMode) {
this.#focusOnEditInput(); this.#focusOnEditInput();
@ -140,11 +145,4 @@ export class FileAttributeComponent extends BaseFormComponent implements OnInit
input.focus(); input.focus();
}, 100); }, 100);
} }
@HostListener('document:click')
clickOutside() {
if (this.isInEditMode && this.closedDatepicker) {
this.close();
}
}
} }

@ -1 +1 @@
Subproject commit d1e095ce6a3764f19f3bb7334b4524980e8f3dbb Subproject commit 7ba2c8f3a3edb08e3163775e3c848dcd4325ce8f