]> git.evergreen-ils.org Git - Evergreen.git/blob - Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts
LP2061136 - Stamping 1405 DB upgrade script
[Evergreen.git] / Open-ILS / src / eg2 / src / app / share / date-select / date-select.component.ts
1 /* eslint-disable eqeqeq */
2 import {Component, OnInit, Input, Output, EventEmitter, forwardRef} from '@angular/core';
3 import {NgbDateStruct} from '@ng-bootstrap/ng-bootstrap';
4 import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
5 import {DateUtil} from '@eg/share/util/date';
6
7 /**
8  * RE: displaying locale dates in the input field:
9  * https://github.com/ng-bootstrap/ng-bootstrap/issues/754
10  * https://stackoverflow.com/questions/40664523/angular2-ngbdatepicker-how-to-format-date-in-inputfield
11  */
12
13 @Component({
14     selector: 'eg-date-select',
15     templateUrl: './date-select.component.html',
16     styleUrls: ['date-select.component.css'],
17     providers: [ {
18         provide: NG_VALUE_ACCESSOR,
19         useExisting: forwardRef(() => DateSelectComponent),
20         multi: true
21     } ]
22 })
23 export class DateSelectComponent implements OnInit, ControlValueAccessor {
24
25     @Input() initialIso: string; // ISO string
26     @Input() initialYmd: string; // YYYY-MM-DD (uses local time zone)
27     @Input() initialDate: Date;  // Date object
28     @Input() required: boolean;
29     @Input() fieldName: string;
30     @Input() domId = '';
31     @Input() disabled: boolean;
32     @Input() readOnly: boolean;
33
34     // Sometimes it's helpful to allow the date selector to expand
35     // to fill its container for visual consistency with other inputs.
36     @Input() noMaxWidth = false;
37
38     current: NgbDateStruct;
39
40     @Output() onChangeAsDate: EventEmitter<Date>;
41     @Output() onChangeAsIso: EventEmitter<string>;
42     @Output() onChangeAsYmd: EventEmitter<string>;
43     @Output() onCleared: EventEmitter<string>;
44
45     // convenience methods to access current selected date
46     currentAsYmd(): string {
47         if (this.current == null) { return null; }
48         if (!this.isValidDate(this.current)) { return null; }
49         return `${this.current.year}-${String(this.current.month).padStart(2, '0')}-${String(this.current.day).padStart(2, '0')}`;
50     }
51     currentAsIso(): string {
52         if (this.current == null) { return null; }
53         if (!this.isValidDate(this.current)) { return null; }
54         const ymd = `${this.current.year}-${String(this.current.month).padStart(2, '0')}-${String(this.current.day).padStart(2, '0')}`;
55         const date = DateUtil.localDateFromYmd(ymd);
56         const iso = date.toISOString();
57         return iso;
58     }
59     currentAsDate(): Date {
60         if (this.current == null) { return null; }
61         if (!this.isValidDate(this.current)) { return null; }
62         const ymd = `${this.current.year}-${String(this.current.month).padStart(2, '0')}-${String(this.current.day).padStart(2, '0')}`;
63         const date = DateUtil.localDateFromYmd(ymd);
64         return date;
65     }
66
67     // Stub functions required by ControlValueAccessor
68     propagateChange = (_: any) => {};
69     propagateTouch = () => {};
70
71     constructor() {
72         this.onChangeAsDate = new EventEmitter<Date>();
73         this.onChangeAsIso = new EventEmitter<string>();
74         this.onChangeAsYmd = new EventEmitter<string>();
75         this.onCleared = new EventEmitter<string>();
76     }
77
78     ngOnInit() {
79
80         if (this.initialYmd) {
81             this.initialDate = DateUtil.localDateFromYmd(this.initialYmd);
82
83         } else if (this.initialIso) {
84             this.initialDate = new Date(this.initialIso);
85         }
86
87         if (this.initialDate) {
88             this.writeValue(this.initialDate);
89         }
90     }
91
92     isValidDate(dt: NgbDateStruct): dt is NgbDateStruct {
93         if (!dt) { return false; }
94         return (<NgbDateStruct>dt).year !== undefined;
95     }
96
97     onDateEnter() {
98         if (this.current === null) {
99             this.onCleared.emit('cleared');
100         } else if (this.isValidDate(this.current)) {
101             this.onDateSelect(this.current);
102         }
103         // ignoring invalid input for now
104     }
105
106     onDateSelect(evt) {
107         const ymd = `${evt.year}-${String(evt.month).padStart(2, '0')}-${String(evt.day).padStart(2, '0')}`;
108         const date = DateUtil.localDateFromYmd(ymd);
109         const iso = date.toISOString();
110         this.onChangeAsDate.emit(date);
111         this.onChangeAsYmd.emit(ymd);
112         this.onChangeAsIso.emit(iso);
113         this.propagateChange(date);
114     }
115
116     // onDateSelect() is not called when the value is cleared.
117     // Handle that here.
118     inputChanged(value) {
119         if (value === null) {
120             this.onChangeAsDate.emit(null);
121             this.onChangeAsYmd.emit(null);
122             this.onChangeAsIso.emit(null);
123             this.propagateChange(null);
124         }
125     }
126
127     reset() {
128         this.current = {
129             year: null,
130             month: null,
131             day: null
132         };
133     }
134
135     writeValue(value: Date) {
136         if (value) {
137             this.current = {
138                 year: value.getFullYear(),
139                 month: value.getMonth() + 1,
140                 day: value.getDate()
141             };
142         } else {
143             // Allow the value to be cleared via model change.
144             this.current = null;
145         }
146     }
147
148     registerOnChange(fn) {
149         this.propagateChange = fn;
150     }
151
152     registerOnTouched(fn) {
153         this.propagateTouch = fn;
154     }
155 }
156
157