[ADF-4775] Make date widget compatible with APS1 and APS2 (#4966)

* [ADF-4775] Make date widget compatible with APS1 and APS2

* Refactor and create new cloud widget
This commit is contained in:
davidcanonieto
2019-08-06 23:40:19 +01:00
committed by Eugenio Romano
parent bf828b6389
commit 8adb9b2a25
10 changed files with 558 additions and 47 deletions

View File

@@ -0,0 +1,20 @@
<div class="{{field.className}}" id="data-widget" [class.adf-invalid]="!field.isValid">
<mat-form-field class="adf-date-widget">
<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"
[required]="isRequired()"
[disabled]="field.readOnly"
[min]="minDate"
[max]="maxDate"
(focusout)="onDateChanged($event.srcElement.value)"
(dateChange)="onDateChanged($event)"
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>
</div>

View File

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

View File

@@ -0,0 +1,184 @@
/*!
* @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 { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { DateCloudWidgetComponent } from './date-cloud.widget';
import { setupTestBed, FormFieldModel, FormModel, CoreModule } from '@alfresco/adf-core';
import { FormCloudService } from '../../services/form-cloud.service';
import moment from 'moment-es6';
describe('DateWidgetComponent', () => {
let widget: DateCloudWidgetComponent;
let fixture: ComponentFixture<DateCloudWidgetComponent>;
let element: HTMLElement;
setupTestBed({
imports: [
NoopAnimationsModule,
CoreModule.forRoot()
],
declarations: [DateCloudWidgetComponent],
providers: [FormCloudService]
});
beforeEach(async(() => {
fixture = TestBed.createComponent(DateCloudWidgetComponent);
widget = fixture.componentInstance;
element = fixture.nativeElement;
}));
it('should setup min value for date picker', () => {
const minValue = '1982-03-13';
widget.field = new FormFieldModel(null, {
id: 'date-id',
name: 'date-name',
minValue: minValue
});
widget.ngOnInit();
const expected = moment(minValue, widget.DATE_FORMAT_CLOUD);
expect(widget.minDate.isSame(expected)).toBeTruthy();
});
it('should date field be present', () => {
const minValue = '1982-03-13';
widget.field = new FormFieldModel(null, {
minValue: minValue
});
fixture.detectChanges();
expect(element.querySelector('#data-widget')).toBeDefined();
expect(element.querySelector('#data-widget')).not.toBeNull();
});
it('should setup max value for date picker', () => {
const maxValue = '1982-03-13';
widget.field = new FormFieldModel(null, {
maxValue: maxValue
});
widget.ngOnInit();
const expected = moment(maxValue, widget.DATE_FORMAT_CLOUD);
expect(widget.maxDate.isSame(expected)).toBeTruthy();
});
it('should eval visibility on date changed', () => {
spyOn(widget, 'onFieldChanged').and.callThrough();
const field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
value: '9999-9-9',
type: 'date',
readOnly: 'false'
});
widget.field = field;
widget.onDateChanged({ value: moment('12/12/2012') });
expect(widget.onFieldChanged).toHaveBeenCalledWith(field);
});
describe('template check', () => {
afterEach(() => {
fixture.destroy();
TestBed.resetTestingModule();
});
it('should show visible date widget', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
value: '9999-9-9',
type: 'date',
readOnly: 'false'
});
widget.field.isVisible = true;
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('9-9-9999');
});
}));
it('should show the correct format type', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
value: '9999-30-12',
type: 'date',
readOnly: 'false'
});
widget.field.isVisible = true;
widget.field.dateDisplayFormat = 'YYYY-DD-MM';
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('9999-30-12');
});
}));
it('should disable date button when is readonly', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
value: '9999-9-9',
type: 'date',
readOnly: 'false'
});
widget.field.isVisible = true;
widget.field.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();
}));
it('should set isValid to false when the value is not a correct date value', async(() => {
widget.field = new FormFieldModel(new FormModel(), {
id: 'date-field-id',
name: 'date-name',
value: 'aa',
type: 'date',
readOnly: 'false'
});
widget.field.isVisible = true;
widget.field.readOnly = false;
fixture.detectChanges();
expect(widget.field.isValid).toBeFalsy();
}));
});
});

View File

@@ -0,0 +1,91 @@
/*!
* @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.
*/
/* tslint:disable:component-selector */
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material';
import moment from 'moment-es6';
import { Moment } from 'moment';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { MOMENT_DATE_FORMATS, MomentDateAdapter, baseHost, WidgetComponent,
UserPreferencesService, UserPreferenceValues, FormService } from '@alfresco/adf-core';
@Component({
selector: 'date-widget',
providers: [
{ provide: DateAdapter, useClass: MomentDateAdapter },
{ provide: MAT_DATE_FORMATS, useValue: MOMENT_DATE_FORMATS }],
templateUrl: './date-cloud.widget.html',
styleUrls: ['./date-cloud.widget.scss'],
host: baseHost,
encapsulation: ViewEncapsulation.None
})
export class DateCloudWidgetComponent extends WidgetComponent implements OnInit, OnDestroy {
DATE_FORMAT_CLOUD = 'YYYY-MM-DD';
minDate: Moment;
maxDate: Moment;
displayDate: Moment;
private onDestroy$ = new Subject<boolean>();
constructor(public formService: FormService,
private dateAdapter: DateAdapter<Moment>,
private userPreferencesService: UserPreferencesService) {
super(formService);
}
ngOnInit() {
this.userPreferencesService
.select(UserPreferenceValues.Locale)
.pipe(takeUntil(this.onDestroy$))
.subscribe(locale => this.dateAdapter.setLocale(locale));
const momentDateAdapter = <MomentDateAdapter> this.dateAdapter;
momentDateAdapter.overrideDisplayFormat = this.field.dateDisplayFormat;
if (this.field) {
if (this.field.minValue) {
this.minDate = moment(this.field.minValue, this.DATE_FORMAT_CLOUD);
}
if (this.field.maxValue) {
this.maxDate = moment(this.field.maxValue, this.DATE_FORMAT_CLOUD);
}
}
this.displayDate = moment(this.field.value, this.field.dateDisplayFormat);
}
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
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.onFieldChanged(this.field);
}
}

View File

@@ -39,6 +39,7 @@ import { FormCloud } from '../models/form-cloud.model';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
import { DropdownCloudWidgetComponent } from './dropdown-cloud/dropdown-cloud.widget';
import { AttachFileCloudWidgetComponent } from './attach-file-cloud-widget/attach-file-cloud-widget.component';
import { DateCloudWidgetComponent } from './date-cloud/date-cloud.widget';
@Component({
selector: 'adf-cloud-form',
@@ -112,6 +113,7 @@ export class FormCloudComponent extends FormBaseComponent implements OnChanges,
});
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true);
this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true);
this.formRenderingService.setComponentTypeResolver('date', () => DateCloudWidgetComponent, true);
}
ngOnChanges(changes: SimpleChanges) {

View File

@@ -29,6 +29,7 @@ import { FormCustomOutcomesComponent } from './components/form-cloud-custom-outc
import { DropdownCloudWidgetComponent } from './components/dropdown-cloud/dropdown-cloud.widget';
import { AttachFileCloudWidgetComponent } from './components/attach-file-cloud-widget/attach-file-cloud-widget.component';
import { ContentNodeSelectorModule } from '@alfresco/adf-content-services';
import { DateCloudWidgetComponent } from './components/date-cloud/date-cloud.widget';
@NgModule({
imports: [
@@ -49,7 +50,9 @@ import { ContentNodeSelectorModule } from '@alfresco/adf-content-services';
FormDefinitionSelectorCloudComponent,
FormCustomOutcomesComponent,
DropdownCloudWidgetComponent,
AttachFileCloudWidgetComponent],
AttachFileCloudWidgetComponent,
DateCloudWidgetComponent
],
providers: [
FormDefinitionSelectorCloudService,
FormRenderingService
@@ -57,10 +60,15 @@ import { ContentNodeSelectorModule } from '@alfresco/adf-content-services';
entryComponents: [
UploadCloudWidgetComponent,
DropdownCloudWidgetComponent,
AttachFileCloudWidgetComponent
AttachFileCloudWidgetComponent,
DateCloudWidgetComponent
],
exports: [
FormCloudComponent, UploadCloudWidgetComponent, FormDefinitionSelectorCloudComponent, FormCustomOutcomesComponent, AttachFileCloudWidgetComponent
FormCloudComponent,
UploadCloudWidgetComponent,
FormDefinitionSelectorCloudComponent,
FormCustomOutcomesComponent,
AttachFileCloudWidgetComponent
]
})
export class FormCloudModule {

View File

@@ -25,6 +25,7 @@ import { TaskCloudService } from '../../services/task-cloud.service';
import { FormRenderingService } from '@alfresco/adf-core';
import { AttachFileCloudWidgetComponent } from '../../../form/components/attach-file-cloud-widget/attach-file-cloud-widget.component';
import { DropdownCloudWidgetComponent } from '../../../form/components/dropdown-cloud/dropdown-cloud.widget';
import { DateCloudWidgetComponent } from '../../../form/components/date-cloud/date-cloud.widget';
@Component({
selector: 'adf-cloud-task-form',
@@ -98,6 +99,7 @@ export class TaskFormCloudComponent implements OnChanges {
private formRenderingService: FormRenderingService) {
this.formRenderingService.setComponentTypeResolver('upload', () => AttachFileCloudWidgetComponent, true);
this.formRenderingService.setComponentTypeResolver('dropdown', () => DropdownCloudWidgetComponent, true);
this.formRenderingService.setComponentTypeResolver('date', () => DateCloudWidgetComponent, true);
}
ngOnChanges(changes: SimpleChanges) {