184 lines
4.5 KiB
TypeScript
184 lines
4.5 KiB
TypeScript
import {
|
|
Component,
|
|
EventEmitter,
|
|
forwardRef,
|
|
Input,
|
|
Output,
|
|
} from "@angular/core";
|
|
import {
|
|
ControlValueAccessor,
|
|
FormControl,
|
|
NG_VALUE_ACCESSOR,
|
|
Validators,
|
|
} from "@angular/forms";
|
|
|
|
export type DateType = "QUICK" | "RELATIVE" | "ABSOLUTE";
|
|
|
|
export class DateValue {
|
|
constructor(
|
|
public type: DateType,
|
|
public value: string,
|
|
public display: string,
|
|
) {}
|
|
}
|
|
|
|
export class DatePickerChange {
|
|
constructor(public value: DateValue) {}
|
|
}
|
|
|
|
@Component({
|
|
selector: "app-date-picker",
|
|
templateUrl: "./date-picker.component.html",
|
|
providers: [
|
|
{
|
|
provide: NG_VALUE_ACCESSOR,
|
|
useExisting: forwardRef(() => DatePickerComponent),
|
|
multi: true,
|
|
},
|
|
],
|
|
})
|
|
export class DatePickerComponent implements ControlValueAccessor {
|
|
isOpen = false;
|
|
|
|
relativeTimeRangeUnit = "relativeTimeRangeMinutes";
|
|
|
|
relativeTimeRangeAmount = 15;
|
|
|
|
relativeTimeRange = {
|
|
seconds: 0,
|
|
minutes: 15,
|
|
hours: 0,
|
|
days: 0,
|
|
months: 0,
|
|
years: 0,
|
|
};
|
|
|
|
dateRange = new FormControl<string>(
|
|
"2019-10-05 00:00:00 - 2019-10-11 23:59:59",
|
|
[
|
|
Validators.pattern(
|
|
/^\d{4}-\d{2}-\d{2} ([01][0-9]|2[0-3]):\d{2}:\d{2} - \d{4}-\d{2}-\d{2} ([01][0-9]|2[0-3]):\d{2}:\d{2}$/,
|
|
),
|
|
],
|
|
);
|
|
|
|
datePickerControl = new FormControl(
|
|
new DateValue("QUICK", "BM/EM", "this month"),
|
|
);
|
|
|
|
@Input()
|
|
isDisabled: boolean = false;
|
|
|
|
@Output()
|
|
readonly dateValueSelected: EventEmitter<DatePickerChange> = new EventEmitter<
|
|
DatePickerChange
|
|
>();
|
|
|
|
selectedTabIndex = 0;
|
|
|
|
_onChange = (_: any) => {};
|
|
|
|
_onTouched = (_: any) => {};
|
|
|
|
constructor() {}
|
|
|
|
getDateValue(): DateValue {
|
|
return this.datePickerControl.value!;
|
|
}
|
|
|
|
writeValue(obj: DateValue): void {
|
|
this.datePickerControl.setValue(obj);
|
|
switch (obj.type) {
|
|
case "QUICK":
|
|
break;
|
|
case "ABSOLUTE":
|
|
this.dateRange.setValue(obj.value);
|
|
break;
|
|
case "RELATIVE":
|
|
const x = this.relativeTimeRange;
|
|
// obj.value looks like "P1Y2M3DT4H5M6S" or "PT4H5M6S" or "P1Y2M3D" or "P1YT6S" or ...
|
|
const matches = obj.value.match(
|
|
/P(?:(\d+)Y)(?:(\d+)M)(?:(\d+)D)?(?:T(?:(\d+)H)(?:(\d+)M)(?:(\d+)S))?/,
|
|
) ?? [];
|
|
|
|
x.years = Number.parseInt(matches[1] ?? 0);
|
|
x.months = Number.parseInt(matches[2] ?? 0);
|
|
x.days = Number.parseInt(matches[3] ?? 0);
|
|
x.hours = Number.parseInt(matches[4] ?? 0);
|
|
x.minutes = Number.parseInt(matches[5] ?? 0);
|
|
x.seconds = Number.parseInt(matches[6] ?? 0);
|
|
break;
|
|
default:
|
|
}
|
|
}
|
|
registerOnChange(fn: any): void {
|
|
this._onChange = fn;
|
|
}
|
|
registerOnTouched(fn: any): void {
|
|
this._onTouched = fn;
|
|
}
|
|
setDisabledState?(isDisabled: boolean): void {
|
|
this.isDisabled = isDisabled;
|
|
}
|
|
|
|
dateDisplay(): string {
|
|
return this.datePickerControl.value?.display || "no date set";
|
|
}
|
|
|
|
tabChange() {
|
|
//(<any> window).initSimpleDatePicker(); // breaks form control
|
|
}
|
|
|
|
setDateValue(dateValue: DateValue) {
|
|
this.datePickerControl.setValue(dateValue);
|
|
this._onChange(dateValue);
|
|
this.dateValueSelected.emit(new DatePickerChange(dateValue));
|
|
//console.log("date value updated: ", dateValue);
|
|
}
|
|
|
|
applyQuick(value: string, display: string) {
|
|
const newValue = new DateValue("QUICK", value, display);
|
|
this.setDateValue(newValue);
|
|
this.isOpen = false;
|
|
}
|
|
|
|
private fixToRange(val: number, min: number, max: number) {
|
|
return val < min ? min : (val > max ? max : val);
|
|
}
|
|
|
|
applyRelativeTimeRange() {
|
|
|
|
const x = this.relativeTimeRange;
|
|
const years = x.years ? "-"+x.years + "Y" : "";
|
|
const months = x.months ? "-"+x.months + "M" : "";
|
|
const days = x.days ? "-"+x.days + "D" : "";
|
|
const hours = x.hours ? "-"+x.hours + "H" : "";
|
|
const minutes = x.minutes ? "-"+x.minutes + "m" : "";
|
|
|
|
const timeRange = `B${years}${months}${days}${hours}${minutes}/Bm`;
|
|
|
|
const newValue = new DateValue("RELATIVE", timeRange, timeRange);
|
|
this.setDateValue(newValue);
|
|
this.isOpen = false;
|
|
}
|
|
|
|
applyAbsoluteTime() {
|
|
const value = <string> this.dateRange.value;
|
|
const newValue = new DateValue("ABSOLUTE", value, value);
|
|
this.setDateValue(newValue);
|
|
this.isOpen = false;
|
|
}
|
|
|
|
scrollRelativeTimeRange(
|
|
event: WheelEvent,
|
|
unit: "seconds" | "minutes" | "hours" | "days" | "months" | "years",
|
|
max: number,
|
|
) {
|
|
this.relativeTimeRange[unit] = this.fixToRange(
|
|
this.relativeTimeRange[unit] + (event.deltaY > 0 ? -1 : 1),
|
|
0,
|
|
max,
|
|
);
|
|
}
|
|
}
|