mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-26 17:24:56 +00:00
[ADF-1925] created datetime widget (#2929)
* [ADF-2225] created datetime widget * [ADF-2225] start fixing max and min date validation * [ADF-2225] fixed validator for date time * [ADF-2225] start adding test * [ADF-2225] removed time wrong workaround and added test to the widget * [ADF-2225] removed fdescribe * [1925] renamed variable
This commit is contained in:
parent
f2dd70a455
commit
3d19341c0d
@ -37,6 +37,7 @@ export class FormFieldTypes {
|
||||
static DATE: string = 'date';
|
||||
static AMOUNT: string = 'amount';
|
||||
static DOCUMENT: string = 'document';
|
||||
static DATETIME: string = 'datetime';
|
||||
|
||||
static READONLY_TYPES: string[] = [
|
||||
FormFieldTypes.HYPERLINK,
|
||||
|
@ -26,7 +26,9 @@ import {
|
||||
MinValueFieldValidator,
|
||||
NumberFieldValidator,
|
||||
RegExFieldValidator,
|
||||
RequiredFieldValidator
|
||||
RequiredFieldValidator,
|
||||
MaxDateTimeFieldValidator,
|
||||
MinDateTimeFieldValidator
|
||||
} from './form-field-validator';
|
||||
import { FormFieldModel } from './form-field.model';
|
||||
import { FormModel } from './form.model';
|
||||
@ -588,4 +590,192 @@ describe('FormFieldValidator', () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('MaxDateTimeFieldValidator', () => {
|
||||
|
||||
let validator: MaxDateTimeFieldValidator;
|
||||
|
||||
beforeEach(() => {
|
||||
validator = new MaxDateTimeFieldValidator();
|
||||
});
|
||||
|
||||
it('should require maxValue defined', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME
|
||||
});
|
||||
expect(validator.isSupported(field)).toBeFalsy();
|
||||
|
||||
field.maxValue = '9999-02-08 10:10 AM';
|
||||
expect(validator.isSupported(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support date time widgets only', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
maxValue: '9999-02-08 10:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.isSupported(field)).toBeTruthy();
|
||||
|
||||
field.type = FormFieldTypes.TEXT;
|
||||
expect(validator.isSupported(field)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should allow empty values', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: null,
|
||||
maxValue: '9999-02-08 10:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should succeed for unsupported types', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.TEXT
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should succeed validating value checking the time', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '08-02-9999 09:10 AM',
|
||||
maxValue: '9999-02-08 10:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fail validating value checking the time', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '08-02-9999 11:10 AM',
|
||||
maxValue: '9999-02-08 10:10 AM'
|
||||
});
|
||||
|
||||
field.validationSummary = new ErrorMessageModel();
|
||||
expect(validator.validate(field)).toBeFalsy();
|
||||
expect(field.validationSummary).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should succeed validating value checking the date', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '08-02-9999 09:10 AM',
|
||||
maxValue: '9999-02-08 10:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fail validating value checking the date', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '08-02-9999 12:10 AM',
|
||||
maxValue: '9999-02-07 10:10 AM'
|
||||
});
|
||||
|
||||
field.validationSummary = new ErrorMessageModel();
|
||||
expect(validator.validate(field)).toBeFalsy();
|
||||
expect(field.validationSummary).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('MinDateTimeFieldValidator', () => {
|
||||
|
||||
let validator: MinDateTimeFieldValidator;
|
||||
|
||||
beforeEach(() => {
|
||||
validator = new MinDateTimeFieldValidator();
|
||||
});
|
||||
|
||||
it('should require minValue defined', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME
|
||||
});
|
||||
expect(validator.isSupported(field)).toBeFalsy();
|
||||
|
||||
field.minValue = '9999-02-08 09:10 AM';
|
||||
expect(validator.isSupported(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should support date time widgets only', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
minValue: '9999-02-08 09:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.isSupported(field)).toBeTruthy();
|
||||
|
||||
field.type = FormFieldTypes.TEXT;
|
||||
expect(validator.isSupported(field)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should allow empty values', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: null,
|
||||
minValue: '9999-02-08 09:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should succeed for unsupported types', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.TEXT
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should succeed validating value by time', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '08-02-9999 09:10 AM',
|
||||
minValue: '9999-02-08 09:00 AM'
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should succeed validating value by date', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '09-02-9999 09:10 AM',
|
||||
minValue: '9999-02-08 09:10 AM'
|
||||
});
|
||||
|
||||
expect(validator.validate(field)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should fail validating value by time', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '08-02-9999 09:00 AM',
|
||||
minValue: '9999-02-08 09:10 AM'
|
||||
});
|
||||
|
||||
field.validationSummary = new ErrorMessageModel();
|
||||
expect(validator.validate(field)).toBeFalsy();
|
||||
expect(field.validationSummary).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should fail validating value by date', () => {
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
type: FormFieldTypes.DATETIME,
|
||||
value: '07-02-9999 09:10 AM',
|
||||
minValue: '9999-02-08 09:10 AM'
|
||||
});
|
||||
|
||||
field.validationSummary = new ErrorMessageModel();
|
||||
expect(validator.validate(field)).toBeFalsy();
|
||||
expect(field.validationSummary).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
@ -42,7 +42,8 @@ export class RequiredFieldValidator implements FormFieldValidator {
|
||||
FormFieldTypes.UPLOAD,
|
||||
FormFieldTypes.AMOUNT,
|
||||
FormFieldTypes.DYNAMIC_TABLE,
|
||||
FormFieldTypes.DATE
|
||||
FormFieldTypes.DATE,
|
||||
FormFieldTypes.DATETIME
|
||||
];
|
||||
|
||||
isSupported(field: FormFieldModel): boolean {
|
||||
@ -159,8 +160,6 @@ export class DateFieldValidator implements FormFieldValidator {
|
||||
|
||||
export class MinDateFieldValidator implements FormFieldValidator {
|
||||
|
||||
MIN_DATE_FORMAT = 'DD-MM-YYYY';
|
||||
|
||||
private supportedTypes = [
|
||||
FormFieldTypes.DATE
|
||||
];
|
||||
@ -171,30 +170,38 @@ export class MinDateFieldValidator implements FormFieldValidator {
|
||||
}
|
||||
|
||||
validate(field: FormFieldModel): boolean {
|
||||
let isValid = true;
|
||||
if (this.isSupported(field) && field.value) {
|
||||
const dateFormat = field.dateDisplayFormat;
|
||||
|
||||
if (!DateFieldValidator.isValidDate(field.value, dateFormat)) {
|
||||
field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE';
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove time and timezone info
|
||||
let d;
|
||||
if (typeof field.value === 'string') {
|
||||
d = moment(field.value.split('T')[0], dateFormat);
|
||||
isValid = false;
|
||||
} else {
|
||||
d = field.value;
|
||||
isValid = this.checkDate(field, dateFormat);
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
let min = moment(field.minValue, this.MIN_DATE_FORMAT);
|
||||
|
||||
if (d.isBefore(min)) {
|
||||
private checkDate(field: FormFieldModel, dateFormat: string): boolean {
|
||||
const MIN_DATE_FORMAT = 'DD-MM-YYYY';
|
||||
let isValid = true;
|
||||
// remove time and timezone info
|
||||
let fieldValueData;
|
||||
if (typeof field.value === 'string') {
|
||||
fieldValueData = moment(field.value.split('T')[0], dateFormat);
|
||||
} else {
|
||||
fieldValueData = field.value;
|
||||
}
|
||||
let min = moment(field.minValue, MIN_DATE_FORMAT);
|
||||
|
||||
if (fieldValueData.isBefore(min)) {
|
||||
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`;
|
||||
field.validationSummary.attributes.set('minValue', field.minValue.toLocaleString());
|
||||
return false;
|
||||
isValid = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,6 +246,100 @@ export class MaxDateFieldValidator implements FormFieldValidator {
|
||||
}
|
||||
}
|
||||
|
||||
export class MinDateTimeFieldValidator implements FormFieldValidator {
|
||||
|
||||
private supportedTypes = [
|
||||
FormFieldTypes.DATETIME
|
||||
];
|
||||
|
||||
isSupported(field: FormFieldModel): boolean {
|
||||
return field &&
|
||||
this.supportedTypes.indexOf(field.type) > -1 && !!field.minValue;
|
||||
}
|
||||
|
||||
validate(field: FormFieldModel): boolean {
|
||||
let isValid = true;
|
||||
if (this.isSupported(field) && field.value) {
|
||||
const dateFormat = field.dateDisplayFormat;
|
||||
|
||||
if (!DateFieldValidator.isValidDate(field.value, dateFormat)) {
|
||||
field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE';
|
||||
isValid = false;
|
||||
} else {
|
||||
isValid = this.checkDateTime(field, dateFormat);
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private checkDateTime(field: FormFieldModel, dateFormat: string): boolean {
|
||||
const MIN_DATE_FORMAT = 'YYYY-MM-DD hh:mm A';
|
||||
|
||||
let isValid = true;
|
||||
let fieldValueDate;
|
||||
if (typeof field.value === 'string') {
|
||||
fieldValueDate = moment(field.value, dateFormat);
|
||||
} else {
|
||||
fieldValueDate = field.value;
|
||||
}
|
||||
let min = moment(field.minValue, MIN_DATE_FORMAT);
|
||||
|
||||
if (fieldValueDate.isBefore(min)) {
|
||||
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_LESS_THAN`;
|
||||
field.validationSummary.attributes.set('minValue', min.format('D-M-YYYY hh-mm A'));
|
||||
isValid = false;
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
|
||||
export class MaxDateTimeFieldValidator implements FormFieldValidator {
|
||||
|
||||
private supportedTypes = [
|
||||
FormFieldTypes.DATETIME
|
||||
];
|
||||
|
||||
isSupported(field: FormFieldModel): boolean {
|
||||
return field &&
|
||||
this.supportedTypes.indexOf(field.type) > -1 && !!field.maxValue;
|
||||
}
|
||||
|
||||
validate(field: FormFieldModel): boolean {
|
||||
let isValid = true;
|
||||
if (this.isSupported(field) && field.value) {
|
||||
const dateFormat = field.dateDisplayFormat;
|
||||
|
||||
if (!DateFieldValidator.isValidDate(field.value, dateFormat)) {
|
||||
field.validationSummary.message = 'FORM.FIELD.VALIDATOR.INVALID_DATE';
|
||||
isValid = false;
|
||||
} else {
|
||||
isValid = this.checkDateTime(field, dateFormat);
|
||||
}
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
|
||||
private checkDateTime(field: FormFieldModel, dateFormat: string): boolean {
|
||||
const MAX_DATE_FORMAT = 'YYYY-MM-DD hh:mm A';
|
||||
let isValid = true;
|
||||
let fieldValueDate;
|
||||
|
||||
if (typeof field.value === 'string') {
|
||||
fieldValueDate = moment(field.value, dateFormat);
|
||||
} else {
|
||||
fieldValueDate = field.value;
|
||||
}
|
||||
let max = moment(field.maxValue, MAX_DATE_FORMAT);
|
||||
|
||||
if (fieldValueDate.isAfter(max)) {
|
||||
field.validationSummary.message = `FORM.FIELD.VALIDATOR.NOT_GREATER_THAN`;
|
||||
field.validationSummary.attributes.set('maxValue', max.format('D-M-YYYY hh-mm A'));
|
||||
isValid = false;
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
|
||||
export class MinLengthFieldValidator implements FormFieldValidator {
|
||||
|
||||
private supportedTypes = [
|
||||
@ -428,5 +529,7 @@ export const FORM_FIELD_VALIDATORS = [
|
||||
new DateFieldValidator(),
|
||||
new MinDateFieldValidator(),
|
||||
new MaxDateFieldValidator(),
|
||||
new FixedValueFieldValidator()
|
||||
new FixedValueFieldValidator(),
|
||||
new MinDateTimeFieldValidator(),
|
||||
new MaxDateTimeFieldValidator()
|
||||
];
|
||||
|
@ -36,6 +36,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
private _required: boolean = false;
|
||||
|
||||
readonly defaultDateFormat: string = 'D-M-YYYY';
|
||||
readonly deafultDateTimeFormat: string = 'D-M-YYYY hh:mm A';
|
||||
|
||||
// model members
|
||||
fieldType: string;
|
||||
@ -164,7 +165,7 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
this.visibilityCondition = <WidgetVisibilityModel> json.visibilityCondition;
|
||||
this.enableFractions = <boolean> json.enableFractions;
|
||||
this.currency = json.currency;
|
||||
this.dateDisplayFormat = json.dateDisplayFormat || this.defaultDateFormat;
|
||||
this.dateDisplayFormat = json.dateDisplayFormat || this.getDefaultDateFormat(json);
|
||||
this._value = this.parseValue(json);
|
||||
this.validationSummary = new ErrorMessageModel();
|
||||
|
||||
@ -200,6 +201,16 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
this.updateForm();
|
||||
}
|
||||
|
||||
private getDefaultDateFormat(jsonField: any): string {
|
||||
let originalType = jsonField.type;
|
||||
if (FormFieldTypes.isReadOnlyType(jsonField.type) &&
|
||||
jsonField.params &&
|
||||
jsonField.params.field) {
|
||||
originalType = jsonField.params.field.type;
|
||||
}
|
||||
return originalType === FormFieldTypes.DATETIME ? this.deafultDateTimeFormat : this.defaultDateFormat;
|
||||
}
|
||||
|
||||
private isTypeaHeadFieldType(type: string): boolean {
|
||||
return type === 'typeahead' ? true : false;
|
||||
}
|
||||
@ -311,13 +322,13 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
This is needed due to Activiti displaying/editing dates in d-M-YYYY format
|
||||
but storing on server in ISO8601 format (i.e. 2013-02-04T22:44:30.652Z)
|
||||
*/
|
||||
if (this.isDateField(json)) {
|
||||
if (this.isDateField(json) || this.isDateTimeField(json)) {
|
||||
if (value) {
|
||||
let dateValue;
|
||||
if (NumberFieldValidator.isNumber(value)) {
|
||||
dateValue = moment(value);
|
||||
} else {
|
||||
dateValue = moment(value.split('T')[0], 'YYYY-M-D');
|
||||
dateValue = this.isDateTimeField(json) ? moment(value, 'YYYY-MM-DD hh:mm A') : moment(value.split('T')[0], 'YYYY-M-D');
|
||||
}
|
||||
if (dateValue && dateValue.isValid()) {
|
||||
value = dateValue.format(this.dateDisplayFormat);
|
||||
@ -382,6 +393,15 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
this._value = this.value;
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.DATETIME:
|
||||
const dateTimeValue = moment(this.value, this.dateDisplayFormat, true);
|
||||
if (dateTimeValue && dateTimeValue.isValid()) {
|
||||
this.form.values[this.id] = dateTimeValue.format('YYYY-MM-DDTHH:mm:ssZ');
|
||||
} else {
|
||||
this.form.values[this.id] = null;
|
||||
this._value = this.value;
|
||||
}
|
||||
break;
|
||||
case FormFieldTypes.NUMBER:
|
||||
this.form.values[this.id] = parseInt(this.value, 10);
|
||||
break;
|
||||
@ -424,4 +444,12 @@ export class FormFieldModel extends FormWidgetModel {
|
||||
json.params.field.type === FormFieldTypes.DATE ) ||
|
||||
json.type === FormFieldTypes.DATE;
|
||||
}
|
||||
|
||||
private isDateTimeField(json: any): boolean {
|
||||
return (json.params &&
|
||||
json.params.field &&
|
||||
json.params.field.type === FormFieldTypes.DATETIME) ||
|
||||
json.type === FormFieldTypes.DATETIME;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
<div class="{{field.className}}" *ngIf="field?.isVisible"
|
||||
id="data-time-widget" [class.adf-invalid]="!field.isValid || field.validationSummary.message">
|
||||
<mat-form-field class="adf-date-time-widget">
|
||||
<label class="adf-label" [attr.for]="field.id">{{field.name}} ({{field.dateDisplayFormat}})<span *ngIf="isRequired()">*</span></label>
|
||||
<input matInput
|
||||
[matDatetimepicker]="datetimePicker"
|
||||
[id]="field.id"
|
||||
[(ngModel)]="displayDate"
|
||||
[required]="isRequired()"
|
||||
[disabled]="field.readOnly"
|
||||
[min]="minDate"
|
||||
[max]="maxDate"
|
||||
(focusout)="onDateChanged($event.srcElement.value)"
|
||||
(dateChange)="onDateChanged($event)"
|
||||
placeholder="{{field.placeholder}}">
|
||||
<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>
|
||||
</div>
|
@ -0,0 +1,17 @@
|
||||
@import '../form';
|
||||
|
||||
.adf {
|
||||
|
||||
&-date-time-widget {
|
||||
|
||||
.mat-input-suffix {
|
||||
text-align: right;
|
||||
position: absolute;
|
||||
margin-top: 30px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,272 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import moment from 'moment-es6';
|
||||
import { ActivitiContentService } from '../../../services/activiti-alfresco.service';
|
||||
import { MaterialModule } from '../../../../material.module';
|
||||
import { ErrorWidgetComponent } from '../error/error.component';
|
||||
import { EcmModelService } from './../../../services/ecm-model.service';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { FormFieldModel } from './../core/form-field.model';
|
||||
import { FormModel } from './../core/form.model';
|
||||
import { DateTimeWidgetComponent } from './date-time.widget';
|
||||
import { UserPreferencesService } from '../../../../services/user-preferences.service';
|
||||
|
||||
describe('DateTimeWidgetComponent', () => {
|
||||
|
||||
let widget: DateTimeWidgetComponent;
|
||||
let fixture: ComponentFixture<DateTimeWidgetComponent>;
|
||||
let element: HTMLElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
MaterialModule
|
||||
],
|
||||
declarations: [
|
||||
DateTimeWidgetComponent,
|
||||
ErrorWidgetComponent
|
||||
],
|
||||
providers: [
|
||||
FormService,
|
||||
UserPreferencesService,
|
||||
EcmModelService,
|
||||
ActivitiContentService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DateTimeWidgetComponent);
|
||||
|
||||
element = fixture.nativeElement;
|
||||
widget = fixture.componentInstance;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
TestBed.resetTestingModule();
|
||||
});
|
||||
|
||||
it('should setup min value for date picker', () => {
|
||||
let minValue = '1982-03-13T10:00Z';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
id: 'date-id',
|
||||
name: 'date-name',
|
||||
type: 'datetime',
|
||||
minValue: minValue
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
let expected = moment(minValue, 'YYYY-MM-DDTHH:mm:ssZ');
|
||||
expect(widget.minDate.isSame(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should date field be present', () => {
|
||||
widget.field = new FormFieldModel(null, {
|
||||
id: 'date-id',
|
||||
name: 'date-name',
|
||||
type: 'datetime'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(element.querySelector('#data-time-widget')).toBeDefined();
|
||||
expect(element.querySelector('#data-time-widget')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should setup max value for date picker', () => {
|
||||
let maxValue = '1982-03-13T10:00Z';
|
||||
widget.field = new FormFieldModel(null, {
|
||||
maxValue: maxValue
|
||||
});
|
||||
fixture.detectChanges();
|
||||
|
||||
let expected = moment(maxValue, 'YYYY-MM-DDTHH:mm:ssZ');
|
||||
expect(widget.maxDate.isSame(expected)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should eval visibility on date changed', () => {
|
||||
spyOn(widget, 'checkVisibility').and.callThrough();
|
||||
|
||||
let field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '9-12-9999 10:00 AM',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
|
||||
widget.field = field;
|
||||
|
||||
widget.onDateChanged({ value: moment('13-03-1982 10:00 AM') });
|
||||
expect(widget.checkVisibility).toHaveBeenCalledWith(field);
|
||||
});
|
||||
|
||||
describe('template check', () => {
|
||||
|
||||
it('should show visible date widget', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '30-11-9999 10:30 AM',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#date-field-id')).toBeDefined();
|
||||
expect(element.querySelector('#date-field-id')).not.toBeNull();
|
||||
let dateElement: any = element.querySelector('#date-field-id');
|
||||
expect(dateElement.value).toBe('30-11-9999 10:30 AM');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should check correctly the min value with different formats', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '11-29-9999 10:30 AM',
|
||||
dateDisplayFormat: 'MM-DD-YYYY HH:mm A',
|
||||
type: 'datetime',
|
||||
readOnly: 'false',
|
||||
minValue: '9999-11-30T10:30Z'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
widget.field.validate();
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#date-field-id')).toBeDefined();
|
||||
expect(element.querySelector('#date-field-id')).not.toBeNull();
|
||||
let dateElement: any = element.querySelector('#date-field-id');
|
||||
expect(dateElement.value).toContain('11-29-9999 10:30 AM');
|
||||
expect(element.querySelector('.adf-error-text').textContent).toBe('FORM.FIELD.VALIDATOR.NOT_LESS_THAN');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should show the correct format type', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999 10:30 AM',
|
||||
dateDisplayFormat: 'MM-DD-YYYY HH:mm A',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#date-field-id')).toBeDefined();
|
||||
expect(element.querySelector('#date-field-id')).not.toBeNull();
|
||||
let dateElement: any = element.querySelector('#date-field-id');
|
||||
expect(dateElement.value).toContain('12-30-9999 10:30 AM');
|
||||
});
|
||||
}));
|
||||
|
||||
it('should hide not visible date widget', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999 10:30 AM',
|
||||
dateDisplayFormat: 'MM-DD-YYYY HH:mm A',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#data-time-widget')).not.toBeNull();
|
||||
widget.field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#data-time-widget')).toBeNull();
|
||||
});
|
||||
}));
|
||||
|
||||
it('should become visibile if the visibility change to true', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999 10:30 AM',
|
||||
dateDisplayFormat: 'MM-DD-YYYY HH:mm A',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
widget.field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#data-time-widget')).toBeNull();
|
||||
widget.fieldChanged.subscribe((field) => {
|
||||
field.isVisible = true;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#data-time-widget')).toBeDefined();
|
||||
expect(element.querySelector('#data-time-widget')).not.toBeNull();
|
||||
let dateElement: any = element.querySelector('#date-field-id');
|
||||
expect(dateElement.value).toContain('12-30-9999 10:30 AM');
|
||||
});
|
||||
});
|
||||
widget.checkVisibility(widget.field);
|
||||
}));
|
||||
|
||||
it('should be hided if the visibility change to false', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999 10:30 AM',
|
||||
dateDisplayFormat: 'MM-DD-YYYY HH:mm A',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
expect(element.querySelector('#data-time-widget')).not.toBeNull();
|
||||
widget.fieldChanged.subscribe((field) => {
|
||||
field.isVisible = false;
|
||||
fixture.detectChanges();
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
expect(element.querySelector('#data-time-widget')).toBeNull();
|
||||
});
|
||||
});
|
||||
widget.checkVisibility(widget.field);
|
||||
}));
|
||||
|
||||
it('should disable date button when is readonly', async(() => {
|
||||
widget.field = new FormFieldModel(new FormModel(), {
|
||||
id: 'date-field-id',
|
||||
name: 'date-name',
|
||||
value: '12-30-9999 10:30 AM',
|
||||
dateDisplayFormat: 'MM-DD-YYYY HH:mm A',
|
||||
type: 'datetime',
|
||||
readOnly: 'false'
|
||||
});
|
||||
fixture.detectChanges();
|
||||
|
||||
let dateButton = <HTMLButtonElement> element.querySelector('button');
|
||||
expect(dateButton.disabled).toBeFalsy();
|
||||
|
||||
widget.field.readOnly = true;
|
||||
fixture.detectChanges();
|
||||
|
||||
dateButton = <HTMLButtonElement> element.querySelector('button');
|
||||
expect(dateButton.disabled).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
});
|
@ -0,0 +1,86 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
/* tslint:disable:component-selector */
|
||||
|
||||
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
|
||||
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
|
||||
import { DatetimeAdapter, MAT_DATETIME_FORMATS } from '@mat-datetimepicker/core';
|
||||
import { MomentDatetimeAdapter, MAT_MOMENT_DATETIME_FORMATS } from '@mat-datetimepicker/moment';
|
||||
import moment from 'moment-es6';
|
||||
import { Moment } from 'moment';
|
||||
import { UserPreferencesService } from '../../../../services/user-preferences.service';
|
||||
import { MomentDateAdapter } from '../../../../utils/momentDateAdapter';
|
||||
import { MOMENT_DATE_FORMATS } from '../../../../utils/moment-date-formats.model';
|
||||
import { FormService } from './../../../services/form.service';
|
||||
import { WidgetComponent } from './../widget.component';
|
||||
|
||||
@Component({
|
||||
providers: [
|
||||
{ provide: DateAdapter, useClass: MomentDateAdapter },
|
||||
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS },
|
||||
{ provide: DatetimeAdapter, useClass: MomentDatetimeAdapter },
|
||||
{ provide: MAT_DATETIME_FORMATS, useValue: MAT_MOMENT_DATETIME_FORMATS }
|
||||
],
|
||||
selector: 'date-time-widget',
|
||||
templateUrl: './date-time.widget.html',
|
||||
styleUrls: ['./date-time.widget.scss'],
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DateTimeWidgetComponent extends WidgetComponent implements OnInit {
|
||||
|
||||
minDate: Moment;
|
||||
maxDate: Moment;
|
||||
displayDate: Moment;
|
||||
|
||||
constructor(public formService: FormService,
|
||||
private dateAdapter: DateAdapter<Moment>,
|
||||
private preferences: UserPreferencesService) {
|
||||
super(formService);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.preferences.locale$.subscribe((locale) => {
|
||||
this.dateAdapter.setLocale(locale);
|
||||
});
|
||||
let momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
|
||||
momentDateAdapter.overrideDisplyaFormat = this.field.dateDisplayFormat;
|
||||
|
||||
if (this.field) {
|
||||
if (this.field.minValue) {
|
||||
this.minDate = moment(this.field.minValue, 'YYYY-MM-DDTHH:mm:ssZ');
|
||||
}
|
||||
|
||||
if (this.field.maxValue) {
|
||||
this.maxDate = moment(this.field.maxValue, 'YYYY-MM-DDTHH:mm:ssZ');
|
||||
}
|
||||
}
|
||||
this.displayDate = moment(this.field.value, this.field.dateDisplayFormat);
|
||||
}
|
||||
|
||||
onDateChanged(newDateValue) {
|
||||
if (newDateValue && newDateValue.value) {
|
||||
this.field.value = newDateValue.value.format(this.field.dateDisplayFormat);
|
||||
} else if (newDateValue) {
|
||||
this.field.value = newDateValue;
|
||||
} else {
|
||||
this.field.value = null;
|
||||
}
|
||||
this.checkVisibility(this.field);
|
||||
}
|
||||
|
||||
}
|
@ -76,9 +76,10 @@ describe('DateWidgetComponent', () => {
|
||||
minValue: minValue
|
||||
});
|
||||
|
||||
widget.ngOnInit();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(element.querySelector('#dropdown-id')).toBeDefined();
|
||||
expect(element.querySelector('#data-widget')).toBeDefined();
|
||||
expect(element.querySelector('#data-widget')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should setup max value for date picker', () => {
|
||||
@ -129,8 +130,7 @@ describe('DateWidgetComponent', () => {
|
||||
});
|
||||
|
||||
it('should show visible date widget', async(() => {
|
||||
fixture.whenStable()
|
||||
.then(() => {
|
||||
fixture.whenStable().then(() => {
|
||||
expect(element.querySelector('#date-field-id')).toBeDefined();
|
||||
expect(element.querySelector('#date-field-id')).not.toBeNull();
|
||||
let dateElement: any = element.querySelector('#date-field-id');
|
||||
|
@ -42,6 +42,7 @@ import { InputMaskDirective } from './text/text-mask.component';
|
||||
import { TextWidgetComponent } from './text/text.widget';
|
||||
import { TypeaheadWidgetComponent } from './typeahead/typeahead.widget';
|
||||
import { UploadWidgetComponent } from './upload/upload.widget';
|
||||
import { DateTimeWidgetComponent } from './date-time/date-time.widget';
|
||||
|
||||
// core
|
||||
export * from './widget.component';
|
||||
@ -70,6 +71,7 @@ export * from './amount/amount.widget';
|
||||
export * from './dynamic-table/dynamic-table.widget';
|
||||
export * from './error/error.component';
|
||||
export { DocumentWidgetComponent } from './document/document.widget';
|
||||
export * from './date-time/date-time.widget';
|
||||
|
||||
// editors (dynamic table)
|
||||
export * from './dynamic-table/dynamic-table.widget.model';
|
||||
@ -105,7 +107,8 @@ export const WIDGET_DIRECTIVES: any[] = [
|
||||
TextEditorComponent,
|
||||
RowEditorComponent,
|
||||
ErrorWidgetComponent,
|
||||
DocumentWidgetComponent
|
||||
DocumentWidgetComponent,
|
||||
DateTimeWidgetComponent
|
||||
];
|
||||
|
||||
export const MASK_DIRECTIVE: any[] = [
|
||||
|
@ -44,6 +44,7 @@ import { FormService } from './services/form.service';
|
||||
import { NodeService } from './services/node.service';
|
||||
import { ProcessContentService } from './services/process-content.service';
|
||||
import { WidgetVisibilityService } from './services/widget-visibility.service';
|
||||
import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@ -55,7 +56,9 @@ import { WidgetVisibilityService } from './services/widget-visibility.service';
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
DataColumnModule,
|
||||
PipeModule
|
||||
PipeModule,
|
||||
MatDatetimepickerModule,
|
||||
MatNativeDatetimeModule
|
||||
],
|
||||
declarations: [
|
||||
ContentWidgetComponent,
|
||||
|
@ -36,7 +36,8 @@ import {
|
||||
TextWidgetComponent,
|
||||
TypeaheadWidgetComponent,
|
||||
UnknownWidgetComponent,
|
||||
UploadWidgetComponent
|
||||
UploadWidgetComponent,
|
||||
DateTimeWidgetComponent
|
||||
} from './../components/widgets/index';
|
||||
|
||||
@Injectable()
|
||||
@ -62,7 +63,8 @@ export class FormRenderingService extends DynamicComponentMapper {
|
||||
'container': DynamicComponentResolver.fromType(ContainerWidgetComponent),
|
||||
'group': DynamicComponentResolver.fromType(ContainerWidgetComponent),
|
||||
'document': DynamicComponentResolver.fromType(DocumentWidgetComponent),
|
||||
'upload': DynamicComponentResolver.fromType(UploadWidgetComponent)
|
||||
'upload': DynamicComponentResolver.fromType(UploadWidgetComponent),
|
||||
'datetime': DynamicComponentResolver.fromType(DateTimeWidgetComponent)
|
||||
};
|
||||
|
||||
constructor() {
|
||||
|
@ -16,6 +16,8 @@
|
||||
*/
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatDatetimepickerModule, MatNativeDatetimeModule } from '@mat-datetimepicker/core';
|
||||
|
||||
import {
|
||||
MatAutocompleteModule, MatButtonModule, MatCardModule, MatCheckboxModule,
|
||||
MatChipsModule, MatDatepickerModule, MatDialogModule, MatGridListModule, MatIconModule,
|
||||
@ -32,7 +34,7 @@ export function modules() {
|
||||
MatInputModule, MatListModule, MatNativeDateModule, MatOptionModule, MatProgressSpinnerModule, MatRadioModule,
|
||||
MatRippleModule, MatSelectModule, MatSlideToggleModule, MatTableModule, MatTabsModule,
|
||||
MatMenuModule, MatProgressBarModule, MatSidenavModule, MatSnackBarModule, MatToolbarModule,
|
||||
MatTooltipModule
|
||||
MatTooltipModule, MatDatetimepickerModule, MatNativeDatetimeModule
|
||||
];
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user