Headless CMS and Content Managment Hub
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

219 lines
5.8 KiB

/*
* Squidex Headless CMS
*
* @license
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
*/
import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, forwardRef, Input, OnInit, ViewChild } from '@angular/core';
import { FormControl, NG_VALUE_ACCESSOR } from '@angular/forms';
import * as moment from 'moment';
import {
StatefulControlComponent,
Types,
UIOptions
} from '@app/framework/internal';
declare module 'pikaday/pikaday';
import * as Pikaday from 'pikaday/pikaday';
export const SQX_DATE_TIME_EDITOR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DateTimeEditorComponent), multi: true
};
const NO_EMIT = { emitEvent: false };
@Component({
selector: 'sqx-date-time-editor',
styleUrls: ['./date-time-editor.component.scss'],
templateUrl: './date-time-editor.component.html',
providers: [SQX_DATE_TIME_EDITOR_CONTROL_VALUE_ACCESSOR],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DateTimeEditorComponent extends StatefulControlComponent<{}, string | null> implements OnInit, AfterViewInit {
private picker: any;
private timeValue: moment.Moment | null = null;
private dateValue: moment.Moment | null = null;
private suppressEvents = false;
@Input()
public mode: 'DateTime' | 'Date';
@Input()
public enforceTime: boolean;
@Input()
public hideClear: boolean;
@ViewChild('dateInput', { static: false })
public dateInput: ElementRef;
public timeControl = new FormControl();
public dateControl = new FormControl();
public hideDateButtons: boolean;
public get showTime() {
return this.mode === 'DateTime';
}
public get hasValue() {
return !!this.dateValue;
}
constructor(changeDetector: ChangeDetectorRef, uiOptions: UIOptions) {
super(changeDetector, {});
this.hideDateButtons = !!uiOptions.get('hideDateButtons');
}
public ngOnInit() {
this.own(
this.timeControl.valueChanges.subscribe(value => {
if (!value || value.length === 0) {
this.timeValue = null;
} else {
this.timeValue = moment.utc(value, 'HH:mm:ss');
}
this.callChangeFormatted();
}));
this.own(
this.dateControl.valueChanges.subscribe(value => {
if (!value || value.length === 0) {
this.dateValue = null;
} else {
this.dateValue = moment.utc(value, 'YYYY-MM-DD');
}
this.callChangeFormatted();
}));
}
public writeValue(obj: any) {
if (Types.isString(obj) && obj.length > 0) {
const parsed = moment.parseZone(obj);
this.dateValue = parsed;
if (this.showTime) {
this.timeValue = parsed;
}
} else {
this.timeValue = null;
this.dateValue = null;
}
this.updateControls();
}
public setDisabledState(isDisabled: boolean): void {
super.setDisabledState(isDisabled);
if (isDisabled) {
this.dateControl.disable(NO_EMIT);
this.timeControl.disable(NO_EMIT);
} else {
this.dateControl.enable(NO_EMIT);
this.timeControl.enable(NO_EMIT);
}
}
public registerOnChange(fn: any) {
this.callChange = fn;
}
public registerOnTouched(fn: any) {
this.callTouched = fn;
}
public ngAfterViewInit() {
this.picker = new Pikaday({ field: this.dateInput.nativeElement, format: 'YYYY-MM-DD',
onSelect: () => {
if (this.suppressEvents) {
return;
}
this.dateValue = this.picker.getMoment();
this.callChangeFormatted();
this.callTouched();
}
});
this.updateControls();
}
public writeNow() {
this.writeValue(new Date().toUTCString());
this.updateControls();
this.callChangeFormatted();
this.callTouched();
return false;
}
public reset() {
this.timeControl.setValue(null, NO_EMIT);
this.dateControl.setValue(null, NO_EMIT);
this.dateValue = null;
this.callChange(null);
this.callTouched();
return false;
}
private callChangeFormatted() {
this.callChange(this.getValue());
}
private getValue(): string | null {
if (!this.dateValue || !this.dateValue.isValid()) {
return null;
}
if (this.timeValue && !this.timeValue.isValid()) {
return null;
}
let result = this.dateValue.format('YYYY-MM-DD');
if (this.showTime && this.timeValue) {
result += 'T';
result += this.timeValue.format('HH:mm:ss');
result += 'Z';
} else if (this.enforceTime) {
result += 'T00:00:00Z';
}
return result;
}
private updateControls() {
this.suppressEvents = true;
if (this.timeValue && this.timeValue.isValid()) {
this.timeControl.setValue(this.timeValue.format('HH:mm:ss'), NO_EMIT);
} else {
this.timeControl.setValue(null, NO_EMIT);
}
if (this.dateValue && this.dateValue.isValid() && this.picker) {
const dateString = this.dateValue.format('YYYY-MM-DD');
const dateLocal = moment(dateString);
this.dateControl.setValue(dateString, NO_EMIT);
this.picker.setMoment(dateLocal);
} else {
this.dateControl.setValue(null, NO_EMIT);
}
this.suppressEvents = false;
}
}