mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-06-30 18:15:11 +00:00
[AAE-4241] Fix date and date time not being populated when node metadata is retrieved (#7025)
* AAE-4241 Fix date and date time not being populated when node metadata is retrieved * AAE-4241 Fix unit tests * [AAE-4241] Fix validation messages * [AAE-4241] Fix unit tests * [AAE-4241] Fix error log messages * [AAE-4241] Fix unit tests * [AAE-4241] Fix e2e tests
This commit is contained in:
parent
a4c3f3a95b
commit
8be6bbaf3c
@ -19,39 +19,40 @@ import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { setupTestBed } from '../../testing/setup-test-bed';
|
||||
import { FormRendererComponent } from './form-renderer.component';
|
||||
import { FormBaseModule } from '../form-base.module';
|
||||
import { formDisplayValueVisibility,
|
||||
formDisplayValueForm,
|
||||
formDisplayValueCombinedVisibility,
|
||||
formNumberWidgetVisibility,
|
||||
formNumberTextJson,
|
||||
formRequiredNumberWidget,
|
||||
colspanForm,
|
||||
numberNotRequiredForm,
|
||||
numberMinMaxForm,
|
||||
textWidgetVisibility,
|
||||
numberWidgetVisibilityForm,
|
||||
radioWidgetVisibiltyForm,
|
||||
customWidgetForm,
|
||||
formDateVisibility,
|
||||
customWidgetFormWithVisibility } from './mock/form-renderer.component.mock';
|
||||
import {
|
||||
formDisplayValueVisibility,
|
||||
formDisplayValueForm,
|
||||
formDisplayValueCombinedVisibility,
|
||||
formNumberWidgetVisibility,
|
||||
formNumberTextJson,
|
||||
formRequiredNumberWidget,
|
||||
colspanForm,
|
||||
numberNotRequiredForm,
|
||||
numberMinMaxForm,
|
||||
textWidgetVisibility,
|
||||
numberWidgetVisibilityForm,
|
||||
radioWidgetVisibiltyForm,
|
||||
customWidgetForm,
|
||||
formDateVisibility,
|
||||
customWidgetFormWithVisibility
|
||||
} from './mock/form-renderer.component.mock';
|
||||
import { FormService } from '../services/form.service';
|
||||
import { CoreTestingModule } from '../../testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { FormRenderingService } from '../services/form-rendering.service';
|
||||
import { TextWidgetComponent } from './widgets';
|
||||
import moment from 'moment';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
function typeIntoInput(targetInput: HTMLInputElement, message: string ) {
|
||||
function typeIntoInput(targetInput: HTMLInputElement, message: string) {
|
||||
expect(targetInput).not.toBeNull('Expected input to set to be valid and not null');
|
||||
targetInput.value = message;
|
||||
targetInput.dispatchEvent(new Event('input'));
|
||||
}
|
||||
|
||||
function typeIntoDate(targetInput: DebugElement, date: { value: moment.Moment} ) {
|
||||
function typeIntoDate(targetInput: DebugElement, date: { srcElement: { value: string } }) {
|
||||
expect(targetInput).not.toBeNull('Expected input to set to be valid and not null');
|
||||
targetInput.triggerEventHandler('dateChange', date);
|
||||
targetInput.triggerEventHandler('change', date);
|
||||
}
|
||||
|
||||
function expectElementToBeHidden(targetElement: HTMLElement): void {
|
||||
@ -119,7 +120,7 @@ describe('Form Renderer Component', () => {
|
||||
let displayTextElementContainer: HTMLInputElement = fixture.nativeElement.querySelector('#field-Text0pqd1u-container');
|
||||
expectElementToBeHidden(displayTextElementContainer);
|
||||
|
||||
typeIntoDate(inputDateTestOne, { value: moment('2019-11-19') });
|
||||
typeIntoDate(inputDateTestOne, { srcElement: { value: '2019-11-19' } });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
@ -136,7 +137,7 @@ describe('Form Renderer Component', () => {
|
||||
let displayTextElementContainer: HTMLDivElement = fixture.nativeElement.querySelector('#field-Text0uyqd3-container');
|
||||
expectElementToBeVisible(displayTextElementContainer);
|
||||
|
||||
typeIntoDate(inputDateTestOne, { value: moment('2019-11-19') });
|
||||
typeIntoDate(inputDateTestOne, { srcElement: { value: '2019-11-19' } });
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
||||
@ -371,7 +372,7 @@ describe('Form Renderer Component', () => {
|
||||
});
|
||||
|
||||
it('[C309654] - Should display Number widget spans on 2 columns when colspan is set to 2 and grid view is active', async () => {
|
||||
formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null , false, true);
|
||||
formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null, false, true);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const formSizedElement = fixture.nativeElement.querySelector('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container div.adf-grid-list');
|
||||
@ -386,7 +387,7 @@ describe('Form Renderer Component', () => {
|
||||
});
|
||||
|
||||
it('[C309654] - Should display Number widget spans on 2 columns when colspan is set to 2 and grid view is not active', async () => {
|
||||
formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null , false, false);
|
||||
formRendererComponent.formDefinition = formService.parseForm(colspanForm.formRepresentation.formDefinition, null, false, false);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
const formSizedElement = fixture.nativeElement.querySelector('#field-2bc275fb-e113-4d7d-885f-6e74a7332d40-container section.adf-grid-list-column-view');
|
||||
@ -629,7 +630,7 @@ describe('Form Renderer Component', () => {
|
||||
describe('Custom Widget', () => {
|
||||
|
||||
it('Should be able to correctly display a custom process cloud widget', async () => {
|
||||
formRenderingService.register({'bananaforevah': () => TextWidgetComponent}, true);
|
||||
formRenderingService.register({ 'bananaforevah': () => TextWidgetComponent }, true);
|
||||
formRendererComponent.formDefinition = formService.parseForm(customWidgetForm.formRepresentation.formDefinition);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
@ -640,7 +641,7 @@ describe('Form Renderer Component', () => {
|
||||
});
|
||||
|
||||
it('Should be able to correctly use visibility in a custom process cloud widget ', async () => {
|
||||
formRenderingService.register({'bananaforevah': () => TextWidgetComponent}, true);
|
||||
formRenderingService.register({ 'bananaforevah': () => TextWidgetComponent }, true);
|
||||
formRendererComponent.formDefinition = formService.parseForm(customWidgetFormWithVisibility.formRepresentation.formDefinition);
|
||||
fixture.detectChanges();
|
||||
await fixture.whenStable();
|
||||
|
@ -2,22 +2,27 @@
|
||||
<mat-form-field class="adf-date-time-widget">
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span *ngIf="isRequired()">*</span></label>
|
||||
<input matInput
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[id]="field.id"
|
||||
[(ngModel)]="displayDate"
|
||||
[value]="field.value"
|
||||
[required]="isRequired()"
|
||||
[disabled]="field.readOnly"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
(focusout)="onDateChanged($any($event).srcElement.value)"
|
||||
(dateChange)="onDateChanged($event)"
|
||||
(change)="onDateChanged($any($event).srcElement.value)"
|
||||
[placeholder]="field.placeholder"
|
||||
[matTooltip]="field.tooltip"
|
||||
matTooltipPosition="above"
|
||||
matTooltipShowDelay="1000">
|
||||
matTooltipShowDelay="1000"
|
||||
(focus)="datetimePicker.open()">
|
||||
<mat-datetimepicker-toggle matSuffix [for]="datetimePicker" [disabled]="field.readOnly"></mat-datetimepicker-toggle>
|
||||
</mat-form-field>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
<mat-datetimepicker #datetimePicker type="datetime" [openOnFocus]="true" [timeInterval]="5"></mat-datetimepicker>
|
||||
<mat-datetimepicker #datetimePicker type="datetime" [touchUi]="true" [timeInterval]="5" [disabled]="field.readOnly"></mat-datetimepicker>
|
||||
<input
|
||||
type="hidden"
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[value]="field.value | adfMomentDate: field.dateDisplayFormat"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
[disabled]="field.readOnly"
|
||||
(dateInput)="onDateChanged($any($event).targetElement.value)">
|
||||
</div>
|
||||
|
@ -24,7 +24,6 @@ import { setupTestBed } from '../../../../testing/setup-test-bed';
|
||||
import { CoreTestingModule } from '../../../../testing/core.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { SimpleChanges } from '@angular/core';
|
||||
|
||||
describe('DateTimeWidgetComponent', () => {
|
||||
|
||||
@ -103,7 +102,7 @@ describe('DateTimeWidgetComponent', () => {
|
||||
|
||||
widget.field = field;
|
||||
|
||||
widget.onDateChanged({ value: moment('1982-03-13T10:00:000Z') });
|
||||
widget.onDateChanged(moment('1982-03-13T10:00:000Z'));
|
||||
expect(widget.onFieldChanged).toHaveBeenCalledWith(field);
|
||||
});
|
||||
|
||||
@ -210,89 +209,12 @@ describe('DateTimeWidgetComponent', () => {
|
||||
const dateElement: any = element.querySelector('#date-field-id');
|
||||
expect(dateElement.value).toContain('12-30-9999 10:30 AM');
|
||||
|
||||
const newField = { ...field, value: '03-02-2020 12:00 AM' };
|
||||
widget.field.value = '03-02-2020 12:00 AM';
|
||||
|
||||
const changes: SimpleChanges = {
|
||||
'field': {
|
||||
previousValue: field,
|
||||
currentValue: newField,
|
||||
firstChange: false,
|
||||
isFirstChange(): boolean { return this.firstChange; }
|
||||
}
|
||||
};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateElement.value).toContain('03-02-2020 12:00 AM');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should not call on change when is first change or field is not set or the field value does not change', () => {
|
||||
const field = new FormFieldModel(new FormModel(), {
|
||||
id: 'datetime-field-id',
|
||||
name: 'datetime-field-name',
|
||||
value: '12-30-9999 10:30 AM',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
field.isVisible = true;
|
||||
field.dateDisplayFormat = 'MM-DD-YYYY HH:mm A',
|
||||
widget.field = field;
|
||||
widget.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#datetime-field-id')).toBeDefined();
|
||||
expect(element.querySelector('#datetime-field-id')).not.toBeNull();
|
||||
const dateTimeElement: any = element.querySelector('#datetime-field-id');
|
||||
expect(dateTimeElement.value).toContain('12-30-9999 10:30 AM');
|
||||
|
||||
const newField = { ...field, value: '03-02-2020 12:00 AM' };
|
||||
|
||||
let changes: SimpleChanges = {
|
||||
'field': {
|
||||
previousValue: field,
|
||||
currentValue: newField,
|
||||
firstChange: true,
|
||||
isFirstChange(): boolean { return this.firstChange; }
|
||||
}
|
||||
};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateTimeElement.value).toContain('12-30-9999 10:30 AM');
|
||||
changes = {};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateTimeElement.value).toContain('12-30-9999 10:30 AM');
|
||||
changes = {
|
||||
'field': {
|
||||
previousValue: field,
|
||||
currentValue: field,
|
||||
firstChange: false,
|
||||
isFirstChange(): boolean { return this.firstChange; }
|
||||
}
|
||||
};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateTimeElement.value).toContain('12-30-9999 10:30 AM');
|
||||
changes = null;
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateTimeElement.value).toContain('12-30-9999 10:30 AM');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
/* tslint:disable:component-selector */
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
import { DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core';
|
||||
import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment';
|
||||
@ -43,11 +43,10 @@ import { takeUntil } from 'rxjs/operators';
|
||||
styleUrls: ['./date-time.widget.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, OnDestroy, OnChanges {
|
||||
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
|
||||
|
||||
minDate: Moment;
|
||||
maxDate: Moment;
|
||||
displayDate: Moment;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@ -75,17 +74,6 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit,
|
||||
this.maxDate = moment(this.field.maxValue, 'YYYY-MM-DDTHH:mm:ssZ');
|
||||
}
|
||||
}
|
||||
this.displayDate = moment(this.field.value, this.field.dateDisplayFormat)
|
||||
.add(
|
||||
moment(this.field.value, this.field.dateDisplayFormat).utcOffset(),
|
||||
'minutes');
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes && changes.field && !changes.field.firstChange && changes.field.currentValue.value !== changes.field.previousValue.value) {
|
||||
this.displayDate = moment(changes.field.currentValue.value, this.field.dateDisplayFormat)
|
||||
.add(moment(changes.field.currentValue.value, this.field.dateDisplayFormat).utcOffset(), 'minutes');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -94,14 +82,12 @@ export class DateTimeWidgetComponent extends WidgetComponent implements OnInit,
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue) {
|
||||
if (newDateValue && newDateValue.value) {
|
||||
this.field.value = newDateValue.value.format(this.field.dateDisplayFormat);
|
||||
} else if (newDateValue) {
|
||||
this.field.value = newDateValue;
|
||||
const date = moment(newDateValue, this.field.dateDisplayFormat, true);
|
||||
if (date.isValid()) {
|
||||
this.field.value = date.format(this.field.dateDisplayFormat);
|
||||
} else {
|
||||
this.field.value = null;
|
||||
this.field.value = newDateValue;
|
||||
}
|
||||
this.onFieldChanged(this.field);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,18 +3,22 @@
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span *ngIf="isRequired()">*</span></label>
|
||||
<input matInput
|
||||
[id]="field.id"
|
||||
[matDatepicker]="datePicker"
|
||||
[(ngModel)]="displayDate"
|
||||
[value]="field.value"
|
||||
[required]="isRequired()"
|
||||
[disabled]="field.readOnly"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
(focusout)="onDateChanged($any($event).srcElement.value)"
|
||||
(dateChange)="onDateChanged($event)"
|
||||
(change)="onDateChanged($any($event).srcElement.value)"
|
||||
[placeholder]="field.placeholder">
|
||||
<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()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
<mat-datepicker #datePicker [touchUi]="true" [startAt]="displayDate" ></mat-datepicker>
|
||||
<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)">
|
||||
</div>
|
||||
|
@ -187,4 +187,34 @@ describe('DateWidgetComponent', () => {
|
||||
expect(widget.field.isValid).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should display always the json value', () => {
|
||||
const field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999',
|
||||
type: 'date',
|
||||
readOnly: 'false'
|
||||
});
|
||||
field.isVisible = true;
|
||||
field.dateDisplayFormat = 'MM-DD-YYYY';
|
||||
widget.field = field;
|
||||
widget.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
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');
|
||||
|
||||
widget.field.value = '03-02-2020';
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateElement.value).toContain('03-02-2020');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -55,7 +55,6 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe
|
||||
|
||||
minDate: Moment;
|
||||
maxDate: Moment;
|
||||
displayDate: Moment;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@ -83,7 +82,6 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe
|
||||
this.maxDate = moment(this.field.maxValue, this.DATE_FORMAT);
|
||||
}
|
||||
}
|
||||
this.displayDate = moment(this.field.value, this.field.dateDisplayFormat);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -92,12 +90,11 @@ export class DateWidgetComponent extends WidgetComponent implements OnInit, OnDe
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue) {
|
||||
if (newDateValue && newDateValue.value) {
|
||||
this.field.value = newDateValue.value.format(this.field.dateDisplayFormat);
|
||||
} else if (newDateValue) {
|
||||
this.field.value = newDateValue;
|
||||
const date = moment(newDateValue, this.field.dateDisplayFormat, true);
|
||||
if (date.isValid()) {
|
||||
this.field.value = date.format(this.field.dateDisplayFormat);
|
||||
} else {
|
||||
this.field.value = null;
|
||||
this.field.value = newDateValue;
|
||||
}
|
||||
this.onFieldChanged(this.field);
|
||||
}
|
||||
|
26
lib/core/pipes/moment-date.pipe.ts
Normal file
26
lib/core/pipes/moment-date.pipe.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
|
||||
@Pipe({ name: 'adfMomentDate' })
|
||||
export class MomentDatePipe implements PipeTransform {
|
||||
transform(value: moment.MomentInput, dateFormat: string): Moment {
|
||||
return moment(value, dateFormat);
|
||||
}
|
||||
}
|
29
lib/core/pipes/moment-datetime.pipe.ts
Normal file
29
lib/core/pipes/moment-datetime.pipe.ts
Normal file
@ -0,0 +1,29 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2019 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
|
||||
@Pipe({ name: 'adfMomentDateTime' })
|
||||
export class MomentDateTimePipe implements PipeTransform {
|
||||
transform(value: moment.MomentInput, dateFormat: string): Moment {
|
||||
return moment(value, dateFormat)
|
||||
.add(
|
||||
moment(value, dateFormat).utcOffset(),
|
||||
'minutes');
|
||||
}
|
||||
}
|
@ -32,6 +32,8 @@ import { LocalizedDatePipe } from './localized-date.pipe';
|
||||
import { DecimalNumberPipe } from './decimal-number.pipe';
|
||||
import { LocalizedRolePipe } from './localized-role.pipe';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MomentDatePipe } from './moment-date.pipe';
|
||||
import { MomentDateTimePipe } from './moment-datetime.pipe';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -51,7 +53,9 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
MultiValuePipe,
|
||||
LocalizedDatePipe,
|
||||
DecimalNumberPipe,
|
||||
LocalizedRolePipe
|
||||
LocalizedRolePipe,
|
||||
MomentDatePipe,
|
||||
MomentDateTimePipe
|
||||
],
|
||||
providers: [
|
||||
FileSizePipe,
|
||||
@ -65,7 +69,9 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
MultiValuePipe,
|
||||
LocalizedDatePipe,
|
||||
DecimalNumberPipe,
|
||||
LocalizedRolePipe
|
||||
LocalizedRolePipe,
|
||||
MomentDatePipe,
|
||||
MomentDateTimePipe
|
||||
],
|
||||
exports: [
|
||||
FileSizePipe,
|
||||
@ -80,7 +86,9 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||
MultiValuePipe,
|
||||
LocalizedDatePipe,
|
||||
DecimalNumberPipe,
|
||||
LocalizedRolePipe
|
||||
LocalizedRolePipe,
|
||||
MomentDatePipe,
|
||||
MomentDateTimePipe
|
||||
]
|
||||
})
|
||||
export class PipeModule {
|
||||
|
@ -3,14 +3,10 @@
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name | translate }} ({{field.dateDisplayFormat}})<span *ngIf="isRequired()">*</span></label>
|
||||
<input matInput
|
||||
[id]="field.id"
|
||||
[matDatepicker]="datePicker"
|
||||
[(ngModel)]="displayDate"
|
||||
[value]="field.value"
|
||||
[required]="isRequired()"
|
||||
[disabled]="field.readOnly"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
(focusout)="onDateChanged($any($event).srcElement.value)"
|
||||
(dateChange)="onDateChanged($event)"
|
||||
(change)="onDateChanged($any($event).srcElement.value)"
|
||||
[placeholder]="field.placeholder"
|
||||
[matTooltip]="field.tooltip"
|
||||
matTooltipPosition="above"
|
||||
@ -19,5 +15,13 @@
|
||||
</mat-form-field>
|
||||
<error-widget [error]="field.validationSummary"></error-widget>
|
||||
<error-widget *ngIf="isInvalidFieldRequired()" required="{{ 'FORM.FIELD.REQUIRED' | translate }}"></error-widget>
|
||||
<mat-datepicker #datePicker [touchUi]="true" [startAt]="displayDate" ></mat-datepicker>
|
||||
<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)">
|
||||
</div>
|
||||
|
@ -21,7 +21,6 @@ import { setupTestBed, FormFieldModel, FormModel } from '@alfresco/adf-core';
|
||||
import moment from 'moment-es6';
|
||||
import { ProcessServiceCloudTestingModule } from '../../../../testing/process-service-cloud.testing.module';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { SimpleChanges } from '@angular/core';
|
||||
|
||||
describe('DateWidgetComponent', () => {
|
||||
|
||||
@ -221,17 +220,8 @@ describe('DateWidgetComponent', () => {
|
||||
const dateElement: any = element.querySelector('#date-field-id');
|
||||
expect(dateElement.value).toContain('12-30-9999');
|
||||
|
||||
const newField = { ...field, value: '03-02-2020' };
|
||||
widget.field.value = '03-02-2020';
|
||||
|
||||
const changes: SimpleChanges = {
|
||||
'field': {
|
||||
previousValue: field,
|
||||
currentValue: newField,
|
||||
firstChange: false,
|
||||
isFirstChange(): boolean { return this.firstChange; }
|
||||
}
|
||||
};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
@ -240,70 +230,4 @@ describe('DateWidgetComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should not call on change when is first change or field is not set or the field value does not change', () => {
|
||||
const field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999',
|
||||
type: 'date',
|
||||
readOnly: 'false'
|
||||
});
|
||||
field.isVisible = true;
|
||||
field.dateDisplayFormat = 'MM-DD-YYYY';
|
||||
widget.field = field;
|
||||
widget.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
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 newField = { ...field, value: '03-02-2020' };
|
||||
|
||||
let changes: SimpleChanges = {
|
||||
'field': {
|
||||
previousValue: field,
|
||||
currentValue: newField,
|
||||
firstChange: true,
|
||||
isFirstChange(): boolean { return this.firstChange; }
|
||||
}
|
||||
};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateElement.value).toContain('12-30-9999');
|
||||
changes = {};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateElement.value).toContain('12-30-9999');
|
||||
changes = {
|
||||
'field': {
|
||||
previousValue: field,
|
||||
currentValue: field,
|
||||
firstChange: false,
|
||||
isFirstChange(): boolean { return this.firstChange; }
|
||||
}
|
||||
};
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateElement.value).toContain('12-30-9999');
|
||||
changes = null;
|
||||
widget.ngOnChanges(changes);
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(dateElement.value).toContain('12-30-9999');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -17,14 +17,16 @@
|
||||
|
||||
/* tslint:disable:component-selector */
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
|
||||
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
|
||||
import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
import { Subject } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { MOMENT_DATE_FORMATS, MomentDateAdapter, WidgetComponent,
|
||||
UserPreferencesService, UserPreferenceValues, FormService } from '@alfresco/adf-core';
|
||||
import {
|
||||
MOMENT_DATE_FORMATS, MomentDateAdapter, WidgetComponent,
|
||||
UserPreferencesService, UserPreferenceValues, FormService
|
||||
} from '@alfresco/adf-core';
|
||||
|
||||
@Component({
|
||||
selector: 'date-widget',
|
||||
@ -46,14 +48,13 @@ import { MOMENT_DATE_FORMATS, MomentDateAdapter, WidgetComponent,
|
||||
},
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy, OnChanges {
|
||||
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
|
||||
|
||||
typeId = 'DateCloudWidgetComponent';
|
||||
DATE_FORMAT_CLOUD = 'YYYY-MM-DD';
|
||||
|
||||
minDate: Moment;
|
||||
maxDate: Moment;
|
||||
displayDate: Moment;
|
||||
|
||||
private onDestroy$ = new Subject<boolean>();
|
||||
|
||||
@ -81,13 +82,6 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit,
|
||||
this.maxDate = moment(this.field.maxValue, this.DATE_FORMAT_CLOUD);
|
||||
}
|
||||
}
|
||||
this.displayDate = moment(this.field.value, this.field.dateDisplayFormat);
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
if (changes && changes.field && !changes.field.firstChange && changes.field.currentValue.value !== changes.field.previousValue.value) {
|
||||
this.displayDate = moment(changes.field.currentValue.value, this.field.dateDisplayFormat);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -96,12 +90,11 @@ export class DateCloudWidgetComponent extends WidgetComponent implements OnInit,
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue) {
|
||||
if (newDateValue && newDateValue.value) {
|
||||
this.field.value = newDateValue.value.format(this.field.dateDisplayFormat);
|
||||
} else if (newDateValue) {
|
||||
this.field.value = newDateValue;
|
||||
const date = moment(newDateValue, this.field.dateDisplayFormat, true);
|
||||
if (date.isValid()) {
|
||||
this.field.value = date.format(this.field.dateDisplayFormat);
|
||||
} else {
|
||||
this.field.value = null;
|
||||
this.field.value = newDateValue;
|
||||
}
|
||||
this.onFieldChanged(this.field);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user