1 import {Component, EventEmitter, Input, Output, forwardRef, ViewChild, OnInit, Optional, Self} from '@angular/core';
2 import {FormatService} from '@eg/core/format.service';
3 import {AbstractControl, ControlValueAccessor, FormControl, FormGroup, NgControl} from '@angular/forms';
4 import {NgbDatepicker, NgbTimeStruct, NgbDateStruct} from '@ng-bootstrap/ng-bootstrap';
5 import {DatetimeValidator} from '@eg/share/validators/datetime_validator.directive';
6 import * as Moment from 'moment-timezone';
9 selector: 'eg-datetime-select',
10 templateUrl: './datetime-select.component.html',
12 export class DateTimeSelectComponent implements OnInit, ControlValueAccessor {
14 @Input() fieldName: string;
15 @Input() initialIso: string;
16 @Input() required: boolean;
17 @Input() minuteStep = 15;
18 @Input() showTZ = true;
19 @Input() timezone: string = this.format.wsOrgTimezone;
20 @Input() readOnly = false;
21 @Output() onChangeAsIso: EventEmitter<string>;
23 dateTimeForm: FormGroup;
25 @ViewChild('datePicker', { static: false }) datePicker;
27 onChange = (_: any) => {};
31 private format: FormatService,
32 private dtv: DatetimeValidator,
35 public controlDir: NgControl, // so that the template can access validation state
37 if (controlDir) { controlDir.valueAccessor = this; }
38 this.onChangeAsIso = new EventEmitter<string>();
39 const startValue = Moment.tz([], this.timezone);
40 this.dateTimeForm = new FormGroup({
41 'stringVersion': new FormControl(
42 this.format.transform({value: startValue, datatype: 'timestamp', datePlusTime: true}),
44 'date': new FormControl({
45 year: startValue.year(),
46 month: startValue.month() + 1,
47 day: startValue.date() }),
48 'time': new FormControl({
49 hour: startValue.hour(),
50 minute: startValue.minute(),
57 this.timezone = this.format.wsOrgTimezone;
59 if (this.initialIso) {
60 this.writeValue(Moment(this.initialIso).tz(this.timezone));
62 this.dateTimeForm.get('stringVersion').valueChanges.subscribe((value) => {
63 if ('VALID' === this.dateTimeForm.get('stringVersion').status) {
64 const model = this.format.momentizeDateTimeString(value, this.timezone, false);
65 if (model && model.isValid()) {
67 this.onChangeAsIso.emit(model.toISOString());
68 this.dateTimeForm.patchValue({date: {
70 month: model.month() + 1,
71 day: model.date()}, time: {
73 minute: model.minute(),
75 }, {emitEvent: false, onlySelf: true});
76 this.datePicker.navigateTo({
78 month: model.month() + 1
83 this.dateTimeForm.get('date').valueChanges.subscribe((date) => {
84 const newDate = Moment.tz([date.year, (date.month - 1), date.day,
85 this.time.value.hour, this.time.value.minute, 0], this.timezone);
86 this.dateTimeForm.patchValue({stringVersion:
87 this.format.transform({value: newDate, datatype: 'timestamp', datePlusTime: true})},
88 {emitEvent: false, onlySelf: true});
89 this.onChange(newDate);
90 this.onChangeAsIso.emit(newDate.toISOString());
93 this.dateTimeForm.get('time').valueChanges.subscribe((time) => {
94 const newDate = Moment.tz([this.date.value.year,
95 (this.date.value.month - 1),
97 time.hour, time.minute, 0],
99 this.dateTimeForm.patchValue({stringVersion:
100 this.format.transform({
101 value: newDate, datatype: 'timestamp', datePlusTime: true})},
102 {emitEvent: false, onlySelf: true});
103 this.onChange(newDate);
104 this.onChangeAsIso.emit(newDate.toISOString());
108 setDatePicker(current: Moment) {
109 const withTZ = current ? current.tz(this.timezone) : Moment.tz([], this.timezone);
110 this.dateTimeForm.patchValue({date: {
112 month: withTZ.month() + 1,
113 day: withTZ.date() }});
116 setTimePicker(current: Moment) {
117 const withTZ = current ? current.tz(this.timezone) : Moment.tz([], this.timezone);
118 this.dateTimeForm.patchValue({time: {
120 minute: withTZ.minute(),
125 writeValue(value: Moment) {
126 if (value !== undefined && value !== null) {
127 this.dateTimeForm.patchValue({
128 stringVersion: this.format.transform({value: value, datatype: 'timestamp', datePlusTime: true})});
129 this.setDatePicker(value);
130 this.setTimePicker(value);
134 registerOnChange(fn: (value: Moment) => any): void {
137 registerOnTouched(fn: () => any): void {
141 firstError(errors: Object) {
142 return Object.values(errors)[0];
145 get stringVersion(): AbstractControl {
146 return this.dateTimeForm.get('stringVersion');
149 get date(): AbstractControl {
150 return this.dateTimeForm.get('date');
153 get time(): AbstractControl {
154 return this.dateTimeForm.get('time');