]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/datetime-select/datetime-select.component.ts
LP 2061136 follow-up: ng lint --fix
[Evergreen.git] / Open-ILS / src / eg2 / src / app / share / datetime-select / datetime-select.component.ts
1 import {Component, EventEmitter, Input, Output, 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 {DatetimeValidator} from '@eg/share/validators/datetime_validator.directive';
5 import * as moment from 'moment-timezone';
6 import {DateUtil} from '@eg/share/util/date';
7
8 @Component({
9     selector: 'eg-datetime-select',
10     templateUrl: './datetime-select.component.html',
11 })
12 export class DateTimeSelectComponent implements OnInit, ControlValueAccessor {
13     @Input() domId = '';
14     @Input() fieldName: string;
15     @Input() initialIso: string;
16     @Input() required: boolean;
17     @Input() minuteStep = 15; // eslint-disable-line no-magic-numbers
18     @Input() showTZ = true;
19     @Input() timezone: string = this.format.wsOrgTimezone;
20     @Input() readOnly = false;
21     @Input() noPast = false;
22     @Input() noFuture = false;
23     @Input() minDate: any;
24     @Input() maxDate: any;
25     @Output() onChangeAsIso: EventEmitter<string>;
26
27     dateTimeForm: FormGroup;
28
29     @ViewChild('datePicker', { static: false }) datePicker;
30
31     onChange = (_: any) => {};
32     onTouched = () => {};
33
34     constructor(
35         private format: FormatService,
36         private dtv: DatetimeValidator,
37         @Optional()
38         @Self()
39         public controlDir: NgControl, // so that the template can access validation state
40     ) {
41         if (controlDir) { controlDir.valueAccessor = this; }
42         this.onChangeAsIso = new EventEmitter<string>();
43         const startValue = moment.tz([], this.timezone);
44         this.dateTimeForm = new FormGroup({
45             'stringVersion': new FormControl(
46                 this.format.transform({value: startValue, datatype: 'timestamp', datePlusTime: true}),
47                 this.dtv.validate),
48             'date': new FormControl({
49                 year: startValue.year(),
50                 month: startValue.month() + 1,
51                 day: startValue.date() }),
52             'time': new FormControl({
53                 hour: startValue.hour(),
54                 minute: startValue.minute(),
55                 second: 0 })
56         });
57     }
58
59     ngOnInit() {
60         if (this.noPast) {
61             this.minDate = DateUtil.localYmdPartsFromDate();
62         }
63         if (this.noFuture) {
64             this.maxDate = DateUtil.localYmdPartsFromDate();
65         }
66         if (!this.timezone) {
67             this.timezone = this.format.wsOrgTimezone;
68         }
69         if (this.initialIso) {
70             this.writeValue(moment(this.initialIso).tz(this.timezone));
71         }
72         this.dateTimeForm.get('stringVersion').valueChanges.subscribe((value) => {
73             if ('VALID' === this.dateTimeForm.get('stringVersion').status) {
74                 const model = this.format.momentizeDateTimeString(value, this.timezone, false);
75                 if (model && model.isValid()) {
76                     this.onChange(model);
77                     this.onChangeAsIso.emit(model.toISOString());
78                     this.dateTimeForm.patchValue({date: {
79                         year: model.year(),
80                         month: model.month() + 1,
81                         day: model.date()}, time: {
82                         hour: model.hour(),
83                         minute: model.minute(),
84                         second: 0 }
85                     }, {emitEvent: false, onlySelf: true});
86                     this.datePicker.navigateTo({
87                         year: model.year(),
88                         month: model.month() + 1
89                     });
90                 }
91             }
92         });
93         this.dateTimeForm.get('date').valueChanges.subscribe((date) => {
94             const newDate = moment.tz([date.year, (date.month - 1), date.day,
95                 this.time.value.hour, this.time.value.minute, 0], this.timezone);
96             this.dateTimeForm.patchValue({stringVersion:
97                 this.format.transform({value: newDate, datatype: 'timestamp', datePlusTime: true})},
98             {emitEvent: false, onlySelf: true});
99             this.onChange(newDate);
100             this.onChangeAsIso.emit(newDate.toISOString());
101         });
102
103         this.dateTimeForm.get('time').valueChanges.subscribe((time) => {
104             const newDate = moment.tz([this.date.value.year,
105                 (this.date.value.month - 1),
106                 this.date.value.day,
107                 time.hour, time.minute, 0],
108             this.timezone);
109             this.dateTimeForm.patchValue({stringVersion:
110                 this.format.transform({
111                     value: newDate, datatype: 'timestamp', datePlusTime: true})},
112             {emitEvent: false, onlySelf: true});
113             this.onChange(newDate);
114             this.onChangeAsIso.emit(newDate.toISOString());
115         });
116     }
117
118     setDatePicker(current: moment.Moment) {
119         const withTZ = current ? current.tz(this.timezone) : moment.tz([], this.timezone);
120         this.dateTimeForm.patchValue({date: {
121             year: withTZ.year(),
122             month: withTZ.month() + 1,
123             day: withTZ.date() }});
124     }
125
126     setTimePicker(current: moment.Moment) {
127         const withTZ = current ? current.tz(this.timezone) : moment.tz([], this.timezone);
128         this.dateTimeForm.patchValue({time: {
129             hour: withTZ.hour(),
130             minute: withTZ.minute(),
131             second: 0 }});
132     }
133
134
135     writeValue(value: moment.Moment|string) {
136         if (typeof value === 'string') {
137             if (value.length === 0) {
138                 return;
139             }
140             value = this.format.momentizeIsoString(value, this.timezone);
141         }
142
143         if (value !== undefined && value !== null) {
144             this.dateTimeForm.patchValue({
145                 stringVersion: this.format.transform({value: value, datatype: 'timestamp', datePlusTime: true})});
146             this.setDatePicker(value);
147             this.setTimePicker(value);
148         }
149     }
150
151     registerOnChange(fn: (value: moment.Moment) => any): void {
152         this.onChange = fn;
153     }
154     registerOnTouched(fn: () => any): void {
155         this.onTouched = fn;
156     }
157
158     firstError(errors: Object) {
159         return Object.values(errors)[0];
160     }
161
162     get stringVersion(): AbstractControl {
163         return this.dateTimeForm.get('stringVersion');
164     }
165
166     get date(): AbstractControl {
167         return this.dateTimeForm.get('date');
168     }
169
170     get time(): AbstractControl {
171         return this.dateTimeForm.get('time');
172     }
173
174 }
175