[APPS-2108] migrate date widget to Angular date picker (#8975)

* migrate date widget to Angular date picker

* [ci:force] fix tests

* [ci:force] fix tests

* [ci:force] test fixes

* [ci:force] missing label attributes

* added type for value
This commit is contained in:
Denys Vuika
2023-10-09 10:28:13 +01:00
committed by GitHub
parent e42e0869ba
commit 3a374ad2a4
6 changed files with 72 additions and 84 deletions

View File

@@ -45,8 +45,6 @@ import { CoreTestingModule } from '../../testing';
import { TranslateModule } from '@ngx-translate/core';
import { FormRenderingService } from '../services/form-rendering.service';
import { TextWidgetComponent } from './widgets';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { FormRulesManager } from '../models/form-rules.model';
const typeIntoInput = (targetInput: HTMLInputElement, message: string) => {
@@ -55,11 +53,6 @@ const typeIntoInput = (targetInput: HTMLInputElement, message: string) => {
targetInput.dispatchEvent(new Event('input'));
};
const typeIntoDate = (targetInput: DebugElement, date: { srcElement: { value: string } }) => {
expect(targetInput).toBeTruthy('Expected input to set to be valid and not null');
targetInput.triggerEventHandler('change', date);
};
const expectElementToBeHidden = (targetElement: HTMLElement): void => {
expect(targetElement).toBeTruthy();
expect(targetElement.style.visibility).toBe('hidden', `${targetElement.id} should be hidden but it is not`);
@@ -113,11 +106,13 @@ describe('Form Renderer Component', () => {
fixture.detectChanges();
await fixture.whenStable();
const inputDateTestOne = fixture.debugElement.query(By.css('#Date0hwq20'));
const inputDateTestOne = fixture.nativeElement.querySelector('#Date0hwq20') as HTMLInputElement;
let displayTextElementContainer: HTMLInputElement = fixture.nativeElement.querySelector('#field-Text0pqd1u-container');
expectElementToBeHidden(displayTextElementContainer);
typeIntoDate(inputDateTestOne, { srcElement: { value: '2019-11-19' } });
inputDateTestOne.value = '2019-11-19';
inputDateTestOne.dispatchEvent(new Event('change'));
fixture.detectChanges();
await fixture.whenStable();
@@ -130,11 +125,14 @@ describe('Form Renderer Component', () => {
fixture.detectChanges();
await fixture.whenStable();
const inputDateTestOne = fixture.debugElement.query(By.css('#Date0hwq20'));
const inputDateTestOne = fixture.nativeElement.querySelector('#Date0hwq20') as HTMLInputElement;
let displayTextElementContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-Text0uyqd3-container');
expectElementToBeVisible(displayTextElementContainer);
typeIntoDate(inputDateTestOne, { srcElement: { value: '2019-11-19' } });
inputDateTestOne.value = '2019-11-19';
inputDateTestOne.dispatchEvent(new Event('change'));
fixture.detectChanges();
await fixture.whenStable();

View File

@@ -1,26 +1,25 @@
<div class="{{field.className}}" id="data-widget" [class.adf-invalid]="!field.isValid && isTouched()">
<mat-form-field class="adf-date-widget" [hideRequiredMarker]="true">
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span class="adf-asterisk"
*ngIf="isRequired()">*</span></label>
<input matInput
<mat-form-field [floatLabel]="'always'" class="adf-date-widget">
<mat-label class="adf-label"
[id]="field.id + '-label'"
[attr.for]="field.id"
>{{field.name | translate }} ({{field.dateDisplayFormat}})</mat-label>
<input matInput [matDatepicker]="datePicker"
[id]="field.id"
[value]="field.value"
[required]="isRequired()"
[disabled]="field.readOnly"
(change)="onDateChanged($any($event).srcElement.value)"
[(ngModel)]="value"
[required]="field.required"
[placeholder]="field.placeholder"
(blur)="markAsTouched()">
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly" ></mat-datepicker-toggle>
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
<mat-datepicker #datePicker [touchUi]="true" [startAt]="field.value | adfMomentDate: field.dateDisplayFormat" [disabled]="field.readOnly"></mat-datepicker>
<input
type="hidden"
[matDatepicker]="datePicker"
[value]="field.value | adfMomentDate: field.dateDisplayFormat"
[min]="minDate"
[max]="maxDate"
[disabled]="field.readOnly"
(dateInput)="onDateChanged($any($event).targetElement.value)">
(dateChange)="onDateChange($event)"
(blur)="markAsTouched()">
<mat-datepicker-toggle matSuffix [for]="datePicker" [disabled]="field.readOnly"></mat-datepicker-toggle>
<mat-datepicker #datePicker
[startAt]="startAt"
[disabled]="field.readOnly">
</mat-datepicker>
</mat-form-field>
<error-widget [error]="field.validationSummary"></error-widget>
<error-widget *ngIf="isInvalidFieldRequired() && isTouched()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
</div>

View File

@@ -1,11 +0,0 @@
.adf {
&-date-widget {
.mat-form-field-suffix {
top: 26px;
}
.mat-form-field-label-wrapper {
top: 20px;
}
}
}

View File

@@ -25,7 +25,6 @@ import { TranslateModule } from '@ngx-translate/core';
import { FormFieldTypes } from '../core/form-field-types';
describe('DateWidgetComponent', () => {
let widget: DateWidgetComponent;
let fixture: ComponentFixture<DateWidgetComponent>;
let element: HTMLElement;
@@ -101,7 +100,9 @@ describe('DateWidgetComponent', () => {
readOnly: 'false'
});
widget.field = field;
widget.onDateChanged({ value: moment('12/12/2012', widget.field.dateDisplayFormat) });
widget.onDateChange({
value: moment('12/12/2012', widget.field.dateDisplayFormat)
} as any);
expect(widget.onFieldChanged).toHaveBeenCalledWith(field);
});
@@ -126,13 +127,6 @@ describe('DateWidgetComponent', () => {
expect(fixture.nativeElement.querySelector('.adf-invalid')).toBeTruthy();
});
it('should be able to display label with asterix', () => {
const asterisk: HTMLElement = element.querySelector('.adf-asterisk');
expect(asterisk).toBeTruthy();
expect(asterisk.textContent).toEqual('*');
});
});
describe('template check', () => {
@@ -142,7 +136,7 @@ describe('DateWidgetComponent', () => {
TestBed.resetTestingModule();
});
it('should show visible date widget', () => {
it('should show visible date widget', async () => {
widget.field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
@@ -153,15 +147,15 @@ describe('DateWidgetComponent', () => {
widget.field.isVisible = true;
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('#date-field-id')).toBeDefined();
expect(element.querySelector('#date-field-id')).not.toBeNull();
const dateElement = element.querySelector<HTMLInputElement>('#date-field-id');
expect(dateElement).not.toBeNull();
const dateElement: any = element.querySelector('#date-field-id');
expect(dateElement.value).toContain('9-9-9999');
expect(dateElement?.value).toContain('9-9-9999');
});
it('[C310335] - Should be able to change display format for Date widget', () => {
it('[C310335] - Should be able to change display format for Date widget', async () => {
widget.field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
@@ -173,25 +167,20 @@ describe('DateWidgetComponent', () => {
widget.field.dateDisplayFormat = 'MM-DD-YYYY';
fixture.detectChanges();
await fixture.whenStable();
let dateElement: any = element.querySelector('#date-field-id');
expect(dateElement.value).toContain('12-30-9999');
widget.field.value = '5-6-2019 00:00';
widget.field.dateDisplayFormat = 'D-M-YYYY HH:mm';
fixture.detectChanges();
dateElement = element.querySelector('#date-field-id');
expect(dateElement.value).toContain('5-6-2019 00:00');
let dateElement = element.querySelector<HTMLInputElement>('#date-field-id');
expect(dateElement?.value).toContain('12-30-9999');
widget.field.value = '05.06.2019';
widget.field.dateDisplayFormat = 'DD.MM.YYYY';
fixture.componentInstance.ngOnInit();
fixture.detectChanges();
await fixture.whenStable();
dateElement = element.querySelector('#date-field-id');
expect(dateElement.value).toContain('05.06.2019');
dateElement = element.querySelector<HTMLInputElement>('#date-field-id');
expect(dateElement?.value).toContain('05.06.2019');
});
it('should disable date button when is readonly', () => {
@@ -233,7 +222,7 @@ describe('DateWidgetComponent', () => {
});
});
it('should display always the json value', () => {
it('should display always the json value', async () => {
const field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
@@ -241,20 +230,23 @@ describe('DateWidgetComponent', () => {
type: 'date',
readOnly: 'false'
});
field.isVisible = true;
field.dateDisplayFormat = 'MM-DD-YYYY';
widget.field = field;
fixture.detectChanges();
await fixture.whenStable();
expect(element.querySelector('#date-field-id')).toBeDefined();
expect(element.querySelector('#date-field-id')).not.toBeNull();
const dateElement: any = element.querySelector('#date-field-id');
expect(dateElement.value).toContain('12-30-9999');
const dateElement = element.querySelector<HTMLInputElement>('#date-field-id');
expect(dateElement?.value).toContain('12-30-9999');
widget.field.value = '03-02-2020';
fixture.componentInstance.ngOnInit();
fixture.detectChanges();
expect(dateElement.value).toContain('03-02-2020');
await fixture.whenStable();
expect(dateElement?.value).toContain('03-02-2020');
});
});

View File

@@ -20,13 +20,14 @@
import { UserPreferencesService, UserPreferenceValues } from '../../../../common/services/user-preferences.service';
import { MomentDateAdapter } from '../../../../common/utils/moment-date-adapter';
import { MOMENT_DATE_FORMATS } from '../../../../common/utils/moment-date-formats.model';
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
import { Component, OnInit, ViewEncapsulation, OnDestroy, Input } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import moment, { Moment } from 'moment';
import { FormService } from '../../../services/form.service';
import { WidgetComponent } from '../widget.component';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
@Component({
selector: 'date-widget',
@@ -34,7 +35,6 @@ import { takeUntil } from 'rxjs/operators';
{ provide: DateAdapter, useClass: MomentDateAdapter },
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }],
templateUrl: './date.widget.html',
styleUrls: ['./date.widget.scss'],
host: {
'(click)': 'event($event)',
'(blur)': 'event($event)',
@@ -54,6 +54,10 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe
minDate: Moment;
maxDate: Moment;
startAt: Moment;
@Input()
value: any = null;
private onDestroy$ = new Subject<boolean>();
@@ -80,6 +84,9 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe
if (this.field.maxValue) {
this.maxDate = moment(this.field.maxValue, this.DATE_FORMAT);
}
this.startAt = moment(this.field.value, this.field.dateDisplayFormat);
this.value = moment(this.field.value, this.field.dateDisplayFormat);
}
}
@@ -88,12 +95,15 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe
this.onDestroy$.complete();
}
onDateChanged(newDateValue) {
const date = moment(newDateValue, this.field.dateDisplayFormat, true);
onDateChange(event: MatDatepickerInputEvent<Moment>) {
const value = event.value;
const input = event.targetElement as HTMLInputElement;
const date = moment(value, this.field.dateDisplayFormat, true);
if (date.isValid()) {
this.field.value = date.format(this.field.dateDisplayFormat);
} else {
this.field.value = newDateValue;
this.field.value = input.value;
}
this.onFieldChanged(this.field);
}

View File

@@ -267,7 +267,7 @@ describe('StartFormComponent', () => {
const formFields = component.form.getFormFields();
const labelField = formFields.find((field) => field.id === 'date');
const dateWidget = fixture.debugElement.nativeElement.querySelector('date-widget');
const dateLabelElement = fixture.debugElement.nativeElement.querySelector('#data-widget .mat-form-field-infix> .adf-label');
const dateLabelElement = fixture.debugElement.nativeElement.querySelector('#date-label');
expect(dateWidget).toBeTruthy();
expect(labelField.type).toBe('date');
@@ -302,7 +302,7 @@ describe('StartFormComponent', () => {
const inputElement = fixture.debugElement.nativeElement.querySelector('.adf-input');
const inputLabelElement = fixture.debugElement.nativeElement.querySelector('.mat-form-field-infix > .adf-label');
const dateElement = fixture.debugElement.nativeElement.querySelector('#billdate');
const dateLabelElement = fixture.debugElement.nativeElement.querySelector('#data-widget .mat-form-field-infix> .adf-label');
const dateLabelElement = fixture.debugElement.nativeElement.querySelector('#billdate-label');
const selectElement = fixture.debugElement.nativeElement.querySelector('#claimtype');
const selectLabelElement = fixture.debugElement.nativeElement.querySelector('.adf-dropdown-widget > .adf-label');