From e0e847784da1539a6644fcc711a3bda2240f57ee Mon Sep 17 00:00:00 2001 From: Galen Charlton <gmc@equinoxinitiative.org> Date: Mon, 25 Mar 2019 15:21:46 -0400 Subject: [PATCH] LP#1831780: various improvements to the Angular date-select widget Styling ------- - the widget is now narrower - the widget now enables form validation styles; in particular, entry of an incorrectly-formatted date is now highlighted - the calendar drop-down is now allowed to overflow the containing element when expanded, making it easier to embed the date selector in other controls - the calendar button (and any material icons button that's part of an input group) now has the same default font size as main text, making the overall date-select look cleaner API --- - add a reset() method - hitting enter in the text box can now triggers emitting date change events - a new onCleared event is emitted if the suer hits enter on an empty input - onChangeAsYmd() now pads month and day to two digits apiece, making the result conform to ISO 8601 and thus more easily plugged into queries. - adds the following methods to retrieve the current date; these are meant to be used via local template references in parent templates: currentAsYmd() currentAsIso() currentAsDate() Sponsored-by: MassLNC Sponsored-by: Georgia Public Library Service Sponsored-by: Indiana State Library Sponsored-by: CW MARS Sponsored-by: King County Library System Signed-off-by: Galen Charlton <gmc@equinoxinitiative.org> Signed-off-by: Bill Erickson <berickxx@gmail.com> --- .../share/date-select/date-select.component.css | 3 ++ .../share/date-select/date-select.component.html | 6 ++- .../app/share/date-select/date-select.component.ts | 51 +++++++++++++++++++++- Open-ILS/src/eg2/src/styles.css | 4 ++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 Open-ILS/src/eg2/src/app/share/date-select/date-select.component.css diff --git a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.css b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.css new file mode 100644 index 0000000000..277f1314ce --- /dev/null +++ b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.css @@ -0,0 +1,3 @@ +.eg-date-select { + max-width: 11em; +} diff --git a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.html b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.html index 7e65f7628e..41425339a3 100644 --- a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.html +++ b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.html @@ -1,16 +1,18 @@ -<div class="input-group"> - <input +<div class="input-group eg-date-select form-validated"> + <input class="form-control" ngbDatepicker #datePicker="ngbDatepicker" [attr.id]="domId.length ? domId : null" placeholder="yyyy-mm-dd" class="form-control" + container="body" name="{{fieldName}}" [disabled]="_disabled" [required]="required" [(ngModel)]="current" + (keyup.enter)="onDateEnter()" (dateSelect)="onDateSelect($event)"/> <div class="input-group-append"> <button class="btn btn-outline-secondary" [disabled]="_disabled" diff --git a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts index 625629026f..077058a6e8 100644 --- a/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts +++ b/Open-ILS/src/eg2/src/app/share/date-select/date-select.component.ts @@ -9,7 +9,8 @@ import {NgbDateStruct} from '@ng-bootstrap/ng-bootstrap'; @Component({ selector: 'eg-date-select', - templateUrl: './date-select.component.html' + templateUrl: './date-select.component.html', + styleUrls: ['date-select.component.css'] }) export class DateSelectComponent implements OnInit { @@ -30,11 +31,35 @@ export class DateSelectComponent implements OnInit { @Output() onChangeAsDate: EventEmitter<Date>; @Output() onChangeAsIso: EventEmitter<string>; @Output() onChangeAsYmd: EventEmitter<string>; + @Output() onCleared: EventEmitter<string>; + + // convenience methods to access current selected date + currentAsYmd(): string { + if (this.current == null) { return null; } + if (!this.isValidDate(this.current)) { return null; } + return `${this.current.year}-${String(this.current.month).padStart(2, '0')}-${String(this.current.day).padStart(2, '0')}`; + } + currentAsIso(): string { + if (this.current == null) { return null; } + if (!this.isValidDate(this.current)) { return null; } + const ymd = `${this.current.year}-${String(this.current.month).padStart(2, '0')}-${String(this.current.day).padStart(2, '0')}`; + const date = this.localDateFromYmd(ymd); + const iso = date.toISOString(); + return iso; + } + currentAsDate(): Date { + if (this.current == null) { return null; } + if (!this.isValidDate(this.current)) { return null; } + const ymd = `${this.current.year}-${String(this.current.month).padStart(2, '0')}-${String(this.current.day).padStart(2, '0')}`; + const date = this.localDateFromYmd(ymd); + return date; + } constructor() { this.onChangeAsDate = new EventEmitter<Date>(); this.onChangeAsIso = new EventEmitter<string>(); this.onChangeAsYmd = new EventEmitter<string>(); + this.onCleared = new EventEmitter<string>(); } ngOnInit() { @@ -55,8 +80,21 @@ export class DateSelectComponent implements OnInit { } } + isValidDate(dt: NgbDateStruct): dt is NgbDateStruct { + return (<NgbDateStruct>dt).year !== undefined; + } + + onDateEnter() { + if (this.current === null) { + this.onCleared.emit('cleared'); + } else if (this.isValidDate(this.current)) { + this.onDateSelect(this.current); + } + // ignoring invalid input for now + } + onDateSelect(evt) { - const ymd = `${evt.year}-${evt.month}-${evt.day}`; + const ymd = `${evt.year}-${String(evt.month).padStart(2, '0')}-${String(evt.day).padStart(2, '0')}`; const date = this.localDateFromYmd(ymd); const iso = date.toISOString(); this.onChangeAsDate.emit(date); @@ -71,6 +109,15 @@ export class DateSelectComponent implements OnInit { return new Date( Number(parts[0]), Number(parts[1]) - 1, Number(parts[2])); } + + reset() { + this.current = { + year: null, + month: null, + day: null + }; + } + } diff --git a/Open-ILS/src/eg2/src/styles.css b/Open-ILS/src/eg2/src/styles.css index 10424f2722..0ffd6b576a 100644 --- a/Open-ILS/src/eg2/src/styles.css +++ b/Open-ILS/src/eg2/src/styles.css @@ -89,6 +89,10 @@ h5 {font-size: .95rem} line-height: inherit; } +.input-group .mat-icon-in-button { + font-size: .88rem !important; /* useful for buttons that cuddle up with inputs */ +} + .material-icons { /** default is 24px which is pretty chunky */ font-size: 22px; -- 2.11.0