RED-7783: Fixed numeric and date file attrs
This commit is contained in:
parent
8f131aff23
commit
b2e7814a75
@ -1,7 +1,7 @@
|
|||||||
<ng-container *ngIf="configService.listingMode$ | async as mode">
|
<ng-container *ngIf="configService.listingMode$ | async as mode">
|
||||||
<div
|
<div
|
||||||
(mousedown)="handleClick($event)"
|
|
||||||
(click)="editFileAttribute($event)"
|
(click)="editFileAttribute($event)"
|
||||||
|
(mousedown)="handleClick($event)"
|
||||||
[ngClass]="{ 'workflow-attribute': mode === 'workflow' }"
|
[ngClass]="{ 'workflow-attribute': mode === 'workflow' }"
|
||||||
class="file-attribute"
|
class="file-attribute"
|
||||||
>
|
>
|
||||||
@ -9,8 +9,8 @@
|
|||||||
<b *ngIf="mode === 'workflow' && !isInEditMode"> {{ fileAttribute.label }}: </b>
|
<b *ngIf="mode === 'workflow' && !isInEditMode"> {{ fileAttribute.label }}: </b>
|
||||||
<span
|
<span
|
||||||
*ngIf="!isDate; else date"
|
*ngIf="!isDate; else date"
|
||||||
[ngClass]="{ hide: isInEditMode, 'clamp-3': mode !== 'workflow' }"
|
|
||||||
[matTooltip]="fileAttributeValue"
|
[matTooltip]="fileAttributeValue"
|
||||||
|
[ngClass]="{ hide: isInEditMode, 'clamp-3': mode !== 'workflow' }"
|
||||||
>
|
>
|
||||||
{{ fileAttributeValue || '-' }}</span
|
{{ fileAttributeValue || '-' }}</span
|
||||||
>
|
>
|
||||||
@ -44,7 +44,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-template #input>
|
<ng-template #input>
|
||||||
<div [ngClass]="{ 'workflow-edit-input': mode === 'workflow' }" class="edit-input">
|
<div (click)="$event.stopPropagation()" [ngClass]="{ 'workflow-edit-input': mode === 'workflow' }" class="edit-input">
|
||||||
<form (ngSubmit)="form.valid && save()" [formGroup]="form">
|
<form (ngSubmit)="form.valid && save()" [formGroup]="form">
|
||||||
<iqser-dynamic-input
|
<iqser-dynamic-input
|
||||||
(closedDatepicker)="closedDatepicker = $event"
|
(closedDatepicker)="closedDatepicker = $event"
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import { Component, HostListener, Input, OnDestroy } from '@angular/core';
|
import { Component, HostListener, Input, OnDestroy } from '@angular/core';
|
||||||
import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
|
import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain';
|
||||||
import { BaseFormComponent, Debounce, HelpModeService, ListingService, Toaster } from '@iqser/common-ui';
|
import { BaseFormComponent, HelpModeService, 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 { AbstractControl, FormBuilder, UntypedFormGroup, ValidatorFn } from '@angular/forms';
|
||||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||||
import { firstValueFrom, Subscription } from 'rxjs';
|
import { firstValueFrom, Subscription } from 'rxjs';
|
||||||
import { FilesService } from '@services/files/files.service';
|
import { FilesService } from '@services/files/files.service';
|
||||||
@ -24,7 +24,6 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
|||||||
|
|
||||||
isInEditMode = false;
|
isInEditMode = false;
|
||||||
closedDatepicker = true;
|
closedDatepicker = true;
|
||||||
readonly #subscriptions = new Subscription();
|
|
||||||
readonly shouldClose$ = this.fileAttributesService.isEditingFileAttribute$.pipe(
|
readonly shouldClose$ = this.fileAttributesService.isEditingFileAttribute$.pipe(
|
||||||
tap(value => {
|
tap(value => {
|
||||||
if (
|
if (
|
||||||
@ -39,6 +38,23 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
readonly #subscriptions = new Subscription();
|
||||||
|
|
||||||
|
get isDate(): boolean {
|
||||||
|
return this.fileAttribute.type === FileAttributeConfigTypes.DATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isNumber(): boolean {
|
||||||
|
return this.fileAttribute.type === FileAttributeConfigTypes.NUMBER;
|
||||||
|
}
|
||||||
|
|
||||||
|
get isText(): boolean {
|
||||||
|
return this.fileAttribute.type === FileAttributeConfigTypes.TEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
get fileAttributeValue(): string {
|
||||||
|
return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id];
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
router: Router,
|
router: Router,
|
||||||
@ -62,15 +78,6 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
|||||||
this.#subscriptions.add(sub2.subscribe());
|
this.#subscriptions.add(sub2.subscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
get isDate(): boolean {
|
|
||||||
return this.fileAttribute.type === FileAttributeConfigTypes.DATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
get fileAttributeValue(): string {
|
|
||||||
return this.file.fileAttributes.attributeIdToValue[this.fileAttribute.id];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Debounce(50)
|
|
||||||
@HostListener('document:click')
|
@HostListener('document:click')
|
||||||
clickOutside() {
|
clickOutside() {
|
||||||
if (this.isInEditMode && this.closedDatepicker) {
|
if (this.isInEditMode && this.closedDatepicker) {
|
||||||
@ -164,16 +171,40 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
|||||||
config[key] = [dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue];
|
config[key] = [dayjs(attrValue, 'YYYY-MM-DD', true).isValid() ? dayjs(attrValue).toDate() : attrValue];
|
||||||
});
|
});
|
||||||
return this._formBuilder.group(config, {
|
return this._formBuilder.group(config, {
|
||||||
validators: control =>
|
validators: [this.#checkEmptyInput(), this.#checkDate()],
|
||||||
(!control.get(this.fileAttribute.id)?.value?.trim().length && !this.fileAttributeValue) ||
|
|
||||||
control.get(this.fileAttribute.id)?.value === this.fileAttributeValue
|
|
||||||
? { emptyString: true }
|
|
||||||
: null,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#checkEmptyInput(): ValidatorFn {
|
||||||
|
return (control: AbstractControl) =>
|
||||||
|
(this.isText && !control.get(this.fileAttribute.id)?.value?.trim().length && !this.fileAttributeValue) ||
|
||||||
|
control.get(this.fileAttribute.id)?.value === this.fileAttributeValue
|
||||||
|
? { emptyString: true }
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#checkDate(): ValidatorFn {
|
||||||
|
return (control: AbstractControl) => {
|
||||||
|
const expr = new RegExp('(0?[1-9]|[12][0-9]|3[01])(/|.)(0?[1-9]|1[12])(/|.)\\d{2}');
|
||||||
|
return this.isDate
|
||||||
|
? (!expr.test(control.get(this.fileAttribute.id)?.value) && control.get(this.fileAttribute.id)?.value?.length) ||
|
||||||
|
this.#formatAttributeValue(control.get(this.fileAttribute.id)?.value) === this.fileAttributeValue
|
||||||
|
? { invalidDate: true }
|
||||||
|
: null
|
||||||
|
: null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#formatAttributeValue(attrValue) {
|
#formatAttributeValue(attrValue) {
|
||||||
return this.isDate ? attrValue && dayjs(attrValue).format('YYYY-MM-DD') : attrValue.trim().replaceAll(/\s\s+/g, ' ');
|
if (this.isDate) {
|
||||||
|
return attrValue && dayjs(attrValue).format('YYYY-MM-DD');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isText) {
|
||||||
|
return attrValue.trim().replaceAll(/\s\s+/g, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
#toggleEdit(): void {
|
#toggleEdit(): void {
|
||||||
@ -191,9 +222,16 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr
|
|||||||
}
|
}
|
||||||
|
|
||||||
#focusOnEditInput(): void {
|
#focusOnEditInput(): void {
|
||||||
setTimeout(() => {
|
if (this.isDate || this.isText) {
|
||||||
const input = document.getElementById(this.fileAttribute.id);
|
setTimeout(() => {
|
||||||
input?.focus();
|
const input = document.getElementById(this.fileAttribute.id) as HTMLInputElement;
|
||||||
}, 100);
|
if (!input) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const end = input.value.length;
|
||||||
|
input.setSelectionRange(end, end);
|
||||||
|
input.focus();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import { DateAdapter, MAT_DATE_LOCALE } from '@angular/material/core';
|
|||||||
import dayjs, { Dayjs } from 'dayjs';
|
import dayjs, { Dayjs } from 'dayjs';
|
||||||
import utc from 'dayjs/plugin/utc';
|
import utc from 'dayjs/plugin/utc';
|
||||||
import localeData from 'dayjs/plugin/localeData';
|
import localeData from 'dayjs/plugin/localeData';
|
||||||
import LocalizedFormat from 'dayjs/plugin/localizedFormat';
|
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||||
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
import customParseFormat from 'dayjs/plugin/customParseFormat';
|
||||||
|
|
||||||
export interface DayJsDateAdapterOptions {
|
export interface DayJsDateAdapterOptions {
|
||||||
@ -135,8 +135,7 @@ export class CustomDateAdapter extends DateAdapter<Dayjs> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
createDate(year: number, month: number, date: number): Dayjs {
|
createDate(year: number, month: number, date: number): Dayjs {
|
||||||
const returnDayjs = this._dayJs().set('year', year).set('month', month).set('date', date);
|
return this._dayJs().set('year', year).set('month', month).set('date', date);
|
||||||
return returnDayjs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
today(): Dayjs {
|
today(): Dayjs {
|
||||||
@ -145,8 +144,9 @@ export class CustomDateAdapter extends DateAdapter<Dayjs> {
|
|||||||
|
|
||||||
parse(value: any, parseFormat: string): Dayjs | null {
|
parse(value: any, parseFormat: string): Dayjs | null {
|
||||||
if (value && typeof value === 'string') {
|
if (value && typeof value === 'string') {
|
||||||
return this._dayJs(value, dayjs().localeData().longDateFormat(parseFormat), this.locale);
|
return dayjs(value, parseFormat);
|
||||||
}
|
}
|
||||||
|
// todo: is this necessary?
|
||||||
return value ? this._dayJs(value).locale(this.locale) : null;
|
return value ? this._dayJs(value).locale(this.locale) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +229,7 @@ export class CustomDateAdapter extends DateAdapter<Dayjs> {
|
|||||||
dayjs.extend(utc);
|
dayjs.extend(utc);
|
||||||
}
|
}
|
||||||
|
|
||||||
dayjs.extend(LocalizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
dayjs.extend(customParseFormat);
|
dayjs.extend(customParseFormat);
|
||||||
dayjs.extend(localeData);
|
dayjs.extend(localeData);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user