@datarailsshared/datarailsshared 1.6.107 → 1.6.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/datarailsshared-datarailsshared-1.6.111.tgz +0 -0
- package/esm2022/lib/date-tags/date-tag.component.mjs +10 -5
- package/esm2022/lib/date-tags/forecast-tag/forecast-tag.component.mjs +3 -3
- package/esm2022/lib/dr-dialog/components/dialog-wrapper/dialog-wrapper.component.mjs +2 -2
- package/esm2022/lib/dr-dynamic-tag/dr-dynamic-tag.component.mjs +52 -45
- package/esm2022/lib/dr-inputs/date-pickers/date-time-picker/date-time-picker.component.mjs +169 -0
- package/esm2022/lib/dr-inputs/date-pickers/time-picker/time-picker.component.mjs +187 -0
- package/esm2022/lib/dr-tags/dr-tag.component.mjs +10 -8
- package/esm2022/lib/dr-tags/dr-tag.types.mjs +1 -1
- package/esm2022/public-api.mjs +3 -1
- package/fesm2022/datarailsshared-datarailsshared.mjs +681 -333
- package/fesm2022/datarailsshared-datarailsshared.mjs.map +1 -1
- package/lib/date-tags/date-tag.component.d.ts +1 -1
- package/lib/dr-dynamic-tag/dr-dynamic-tag.component.d.ts +2 -2
- package/lib/dr-inputs/date-pickers/date-time-picker/date-time-picker.component.d.ts +35 -0
- package/lib/dr-inputs/date-pickers/time-picker/time-picker.component.d.ts +45 -0
- package/lib/dr-tags/dr-tag.types.d.ts +5 -2
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
- package/datarailsshared-datarailsshared-1.6.107.tgz +0 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, forwardRef, ChangeDetectionStrategy, inject, Input, HostBinding, DestroyRef } from '@angular/core';
|
|
3
|
+
import { FormBuilder, FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
|
4
|
+
import { LOCAL_TIME_ZONE_OFFSET, TimePickerComponent } from '../time-picker/time-picker.component';
|
|
5
|
+
import { distinctUntilChanged, map, Subject, takeUntil } from 'rxjs';
|
|
6
|
+
import { cloneDeep, isEqual, isNil } from 'lodash';
|
|
7
|
+
import { DrInputsModule } from '../../dr-inputs.module';
|
|
8
|
+
import moment from 'moment';
|
|
9
|
+
import * as i0 from "@angular/core";
|
|
10
|
+
import * as i1 from "@angular/common";
|
|
11
|
+
import * as i2 from "../dr-date-picker/dr-date-picker.component";
|
|
12
|
+
import * as i3 from "@angular/forms";
|
|
13
|
+
const DEFAULT_FORM_VALUE = {
|
|
14
|
+
date: null,
|
|
15
|
+
time: {
|
|
16
|
+
hour: 12,
|
|
17
|
+
minute: 0,
|
|
18
|
+
timePeriod: 'AM',
|
|
19
|
+
timeZone: LOCAL_TIME_ZONE_OFFSET,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
export class DateTimePickerComponent {
|
|
23
|
+
constructor() {
|
|
24
|
+
this.fb = inject(FormBuilder);
|
|
25
|
+
this.destroy$ = new Subject();
|
|
26
|
+
this.hostId = null;
|
|
27
|
+
this.LOCAL_TIME_ZONE_OFFSET = LOCAL_TIME_ZONE_OFFSET;
|
|
28
|
+
this.dateTimeForm = this.fb.group({
|
|
29
|
+
date: this.fb.control(null),
|
|
30
|
+
time: this.fb.control({
|
|
31
|
+
hour: 12,
|
|
32
|
+
minute: 0,
|
|
33
|
+
timePeriod: 'AM',
|
|
34
|
+
timeZone: this.LOCAL_TIME_ZONE_OFFSET,
|
|
35
|
+
}),
|
|
36
|
+
});
|
|
37
|
+
this.innerTime = null;
|
|
38
|
+
this.onChange = () => { };
|
|
39
|
+
this.onTouched = () => { };
|
|
40
|
+
inject(DestroyRef).onDestroy(() => {
|
|
41
|
+
this.destroy$.next();
|
|
42
|
+
this.destroy$.complete();
|
|
43
|
+
});
|
|
44
|
+
this.dateTimeForm.valueChanges
|
|
45
|
+
.pipe(map((value) => ({
|
|
46
|
+
value: this.getCombinedTimestamp(value),
|
|
47
|
+
timezone: value.time?.timeZone || null,
|
|
48
|
+
})), distinctUntilChanged((a, b) => isEqual(a, b)), takeUntil(this.destroy$))
|
|
49
|
+
.subscribe((value) => {
|
|
50
|
+
this.innerTime = value.value;
|
|
51
|
+
this.onChange(value);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
writeValue(value) {
|
|
55
|
+
if (this.innerTime === value?.value)
|
|
56
|
+
return;
|
|
57
|
+
if (value && typeof value === 'object' && !isNil(value.value) && typeof value.value === 'number') {
|
|
58
|
+
const formValue = this.getFormValueFromTimestamp(value.value, value.timezone || null);
|
|
59
|
+
this.dateTimeForm.setValue(formValue);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
this.dateTimeForm.setValue(cloneDeep(DEFAULT_FORM_VALUE), { emitEvent: false });
|
|
63
|
+
}
|
|
64
|
+
getFormValueFromTimestamp(timestamp, _timezone = this.LOCAL_TIME_ZONE_OFFSET) {
|
|
65
|
+
const dateMoment = moment.unix(timestamp).utc();
|
|
66
|
+
const timezone = _timezone || 0;
|
|
67
|
+
const adjustedDate = dateMoment.clone().utcOffset(-(timezone || 0));
|
|
68
|
+
let hours = adjustedDate.hours();
|
|
69
|
+
let timePeriod = 'AM';
|
|
70
|
+
if (hours >= 12) {
|
|
71
|
+
timePeriod = 'PM';
|
|
72
|
+
if (hours > 12) {
|
|
73
|
+
hours -= 12;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else if (hours === 0) {
|
|
77
|
+
hours = 12;
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
date: dateMoment.clone().add({ hours: -timezone }).unix(),
|
|
81
|
+
time: {
|
|
82
|
+
hour: hours,
|
|
83
|
+
minute: adjustedDate.minutes(),
|
|
84
|
+
timePeriod,
|
|
85
|
+
timeZone: timezone,
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
getCombinedTimestamp({ date, time }) {
|
|
90
|
+
if (!date || !time) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
let hours = time.hour;
|
|
94
|
+
if (time.timePeriod === 'PM' && hours < 12) {
|
|
95
|
+
hours += 12;
|
|
96
|
+
}
|
|
97
|
+
else if (time.timePeriod === 'AM' && hours === 12) {
|
|
98
|
+
hours = 0;
|
|
99
|
+
}
|
|
100
|
+
const dateObj = moment.unix(date).utc();
|
|
101
|
+
const combinedDate = dateObj.startOf('day').add({ hour: hours, minute: time.minute });
|
|
102
|
+
return combinedDate.unix();
|
|
103
|
+
}
|
|
104
|
+
registerOnChange(fn) {
|
|
105
|
+
this.onChange = fn;
|
|
106
|
+
}
|
|
107
|
+
registerOnTouched(fn) {
|
|
108
|
+
this.onTouched = fn;
|
|
109
|
+
}
|
|
110
|
+
setDisabledState(isDisabled) {
|
|
111
|
+
if (isDisabled) {
|
|
112
|
+
this.dateTimeForm.disable();
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.dateTimeForm.enable();
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** @nocollapse */ static { this.ɵfac = function DateTimePickerComponent_Factory(t) { return new (t || DateTimePickerComponent)(); }; }
|
|
119
|
+
/** @nocollapse */ static { this.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: DateTimePickerComponent, selectors: [["dr-date-time-picker"]], hostVars: 1, hostBindings: function DateTimePickerComponent_HostBindings(rf, ctx) { if (rf & 2) {
|
|
120
|
+
i0.ɵɵattribute("id", ctx.hostId);
|
|
121
|
+
} }, inputs: { id: "id", min: "min", max: "max" }, standalone: true, features: [i0.ɵɵProvidersFeature([
|
|
122
|
+
{
|
|
123
|
+
provide: NG_VALUE_ACCESSOR,
|
|
124
|
+
useExisting: forwardRef((() => DateTimePickerComponent)),
|
|
125
|
+
multi: true,
|
|
126
|
+
},
|
|
127
|
+
]), i0.ɵɵStandaloneFeature], decls: 8, vars: 10, consts: [[1, "dr-date-time-picker"], ["type", "hidden", 3, "value"], [1, "dr-date-time-picker__date", 3, "id", "formControl", "min", "max", "ngModelChange"], [1, "dr-date-time-picker__time"], [1, "dr-date-time-picker__at"], ["data-testid", "date-time-picker-time-picker", 1, "dr-date-time-picker__time-picker", 3, "formControl", "ngModelChange"]], template: function DateTimePickerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
128
|
+
i0.ɵɵelementStart(0, "div", 0);
|
|
129
|
+
i0.ɵɵelement(1, "input", 1);
|
|
130
|
+
i0.ɵɵpipe(2, "date");
|
|
131
|
+
i0.ɵɵelementStart(3, "dr-date-picker", 2);
|
|
132
|
+
i0.ɵɵlistener("ngModelChange", function DateTimePickerComponent_Template_dr_date_picker_ngModelChange_3_listener() { return ctx.onTouched(); });
|
|
133
|
+
i0.ɵɵelementEnd();
|
|
134
|
+
i0.ɵɵelementStart(4, "div", 3)(5, "span", 4);
|
|
135
|
+
i0.ɵɵtext(6, "At");
|
|
136
|
+
i0.ɵɵelementEnd();
|
|
137
|
+
i0.ɵɵelementStart(7, "dr-time-picker", 5);
|
|
138
|
+
i0.ɵɵlistener("ngModelChange", function DateTimePickerComponent_Template_dr_time_picker_ngModelChange_7_listener() { return ctx.onTouched(); });
|
|
139
|
+
i0.ɵɵelementEnd()()();
|
|
140
|
+
} if (rf & 2) {
|
|
141
|
+
i0.ɵɵadvance(1);
|
|
142
|
+
i0.ɵɵproperty("value", i0.ɵɵpipeBind2(2, 7, ctx.innerTime, "DD-MM-YYYY HH:mm"));
|
|
143
|
+
i0.ɵɵattribute("id", ctx.id);
|
|
144
|
+
i0.ɵɵadvance(2);
|
|
145
|
+
i0.ɵɵproperty("id", ctx.id)("formControl", ctx.dateTimeForm.controls.date)("min", ctx.min)("max", ctx.max);
|
|
146
|
+
i0.ɵɵadvance(4);
|
|
147
|
+
i0.ɵɵproperty("formControl", ctx.dateTimeForm.controls.time);
|
|
148
|
+
} }, dependencies: [CommonModule, i1.DatePipe, DrInputsModule, i2.DrDatePickerComponent, FormsModule, i3.NgControlStatus, ReactiveFormsModule, i3.FormControlDirective, TimePickerComponent], styles: ["[_nghost-%COMP%] .dr-date-time-picker[_ngcontent-%COMP%]{display:flex;flex-direction:column}[_nghost-%COMP%] .dr-date-time-picker__date[_ngcontent-%COMP%]{margin-bottom:8px}[_nghost-%COMP%] .dr-date-time-picker__time[_ngcontent-%COMP%]{display:flex;align-items:center}[_nghost-%COMP%] .dr-date-time-picker__time-picker[_ngcontent-%COMP%]{flex-grow:1}[_nghost-%COMP%] .dr-date-time-picker__at[_ngcontent-%COMP%]{margin-right:4px}"], changeDetection: 0 }); }
|
|
149
|
+
}
|
|
150
|
+
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DateTimePickerComponent, [{
|
|
151
|
+
type: Component,
|
|
152
|
+
args: [{ selector: 'dr-date-time-picker', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, DrInputsModule, FormsModule, ReactiveFormsModule, TimePickerComponent], providers: [
|
|
153
|
+
{
|
|
154
|
+
provide: NG_VALUE_ACCESSOR,
|
|
155
|
+
useExisting: forwardRef((() => DateTimePickerComponent)),
|
|
156
|
+
multi: true,
|
|
157
|
+
},
|
|
158
|
+
], template: "<div class=\"dr-date-time-picker\">\n <input [attr.id]=\"id\" type=\"hidden\" [value]=\"innerTime | date: 'DD-MM-YYYY HH:mm'\" />\n <dr-date-picker\n [id]=\"id\"\n [formControl]=\"dateTimeForm.controls.date\"\n [min]=\"min\"\n [max]=\"max\"\n (ngModelChange)=\"onTouched()\"\n class=\"dr-date-time-picker__date\" />\n\n <div class=\"dr-date-time-picker__time\">\n <span class=\"dr-date-time-picker__at\">At</span>\n <dr-time-picker\n class=\"dr-date-time-picker__time-picker\"\n [formControl]=\"dateTimeForm.controls.time\"\n (ngModelChange)=\"onTouched()\"\n data-testid=\"date-time-picker-time-picker\" />\n </div>\n</div>\n", styles: [":host .dr-date-time-picker{display:flex;flex-direction:column}:host .dr-date-time-picker__date{margin-bottom:8px}:host .dr-date-time-picker__time{display:flex;align-items:center}:host .dr-date-time-picker__time-picker{flex-grow:1}:host .dr-date-time-picker__at{margin-right:4px}\n"] }]
|
|
159
|
+
}], function () { return []; }, { id: [{
|
|
160
|
+
type: Input
|
|
161
|
+
}], hostId: [{
|
|
162
|
+
type: HostBinding,
|
|
163
|
+
args: ['attr.id']
|
|
164
|
+
}], min: [{
|
|
165
|
+
type: Input
|
|
166
|
+
}], max: [{
|
|
167
|
+
type: Input
|
|
168
|
+
}] }); })();
|
|
169
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRhcmFpbHNzaGFyZWQvc3JjL2xpYi9kci1pbnB1dHMvZGF0ZS1waWNrZXJzL2RhdGUtdGltZS1waWNrZXIvZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRhcmFpbHNzaGFyZWQvc3JjL2xpYi9kci1pbnB1dHMvZGF0ZS1waWNrZXJzL2RhdGUtdGltZS1waWNrZXIvZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZILE9BQU8sRUFBd0IsV0FBVyxFQUFFLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hILE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxtQkFBbUIsRUFBbUIsTUFBTSxzQ0FBc0MsQ0FBQztBQUNwSCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckUsT0FBTyxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sUUFBUSxDQUFDO0FBQ25ELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN4RCxPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7Ozs7O0FBTzVCLE1BQU0sa0JBQWtCLEdBQWtCO0lBQ3RDLElBQUksRUFBRSxJQUFJO0lBQ1Ys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aUIsZUFBVyxJQUFDO1lBTGpDLGlCQU13QztZQUV4Qyw4QkFBdUMsY0FBQTtZQUNHLGtCQUFFO1lBQUEsaUJBQU87WUFDL0MseUNBSWlEO1lBRDdDLDRIQUFpQixlQUFXLElBQUM7WUFIakMsaUJBSWlELEVBQUEsRUFBQTs7WUFmakIsZUFBOEM7WUFBOUMsK0VBQThDO1lBQTNFLDRCQUFjO1lBRWpCLGVBQVM7WUFBVCwyQkFBUywrQ0FBQSxnQkFBQSxnQkFBQTtZQVdMLGVBQTBDO1lBQTFDLDREQUEwQzs0QkRjeEMsWUFBWSxlQUFFLGNBQWMsNEJBQUUsV0FBVyxzQkFBRSxtQkFBbUIsMkJBQUUsbUJBQW1COzt1RkFXcEYsdUJBQXVCO2NBZm5DLFNBQVM7MkJBQ0kscUJBQXFCLG1CQUNkLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsbUJBQW1CLENBQUMsYUFHbkY7b0JBQ1A7d0JBQ0ksT0FBTyxFQUFFLGlCQUFpQjt3QkFDMUIsV0FBVyxFQUFFLFVBQVUsRUFBQyxHQUFHLEVBQUUsd0JBQXdCLEVBQUM7d0JBQ3RELEtBQUssRUFBRSxJQUFJO3FCQUNkO2lCQUNKO3NDQU9ELEVBQUU7a0JBREQsS0FBSztZQUdOLE1BQU07a0JBREwsV0FBVzttQkFBQyxTQUFTO1lBR3RCLEdBQUc7a0JBREYsS0FBSztZQUdOLEdBQUc7a0JBREYsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBDb21wb25lbnQsIGZvcndhcmRSZWYsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBpbmplY3QsIElucHV0LCBIb3N0QmluZGluZywgRGVzdHJveVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEZvcm1CdWlsZGVyLCBGb3Jtc01vZHVsZSwgTkdfVkFMVUVfQUNDRVNTT1IsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBMT0NBTF9USU1FX1pPTkVfT0ZGU0VULCBUaW1lUGlja2VyQ29tcG9uZW50LCBUaW1lcGlja2VyTW9kZWwgfSBmcm9tICcuLi90aW1lLXBpY2tlci90aW1lLXBpY2tlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgZGlzdGluY3RVbnRpbENoYW5nZWQsIG1hcCwgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjbG9uZURlZXAsIGlzRXF1YWwsIGlzTmlsIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IERySW5wdXRzTW9kdWxlIH0gZnJvbSAnLi4vLi4vZHItaW5wdXRzLm1vZHVsZSc7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5cbmV4cG9ydCB0eXBlIERhdGVUaW1lTW9kZWwgPSB7XG4gICAgZGF0ZTogbnVtYmVyIHwgbnVsbDsgLy8gVVRDIHRpbWVzdGFtcFxuICAgIHRpbWU6IFRpbWVwaWNrZXJNb2RlbCB8IG51bGw7XG59O1xuXG5jb25zdCBERUZBVUxUX0ZPUk1fVkFMVUU6IERhdGVUaW1lTW9kZWwgPSB7XG4gICAgZGF0ZTogbnVsbCxcbiAgICB0aW1lOiB7XG4gICAgICAgIGhvdXI6IDEyLFxuICAgICAgICBtaW51dGU6IDAsXG4gICAgICAgIHRpbWVQZXJpb2Q6ICdBTScsXG4gICAgICAgIHRpbWVab25lOiBMT0NBTF9USU1FX1pPTkVfT0ZGU0VULFxuICAgIH0sXG59O1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2RyLWRhdGUtdGltZS1waWNrZXInLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRHJJbnB1dHNNb2R1bGUsIEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlLCBUaW1lUGlja2VyQ29tcG9uZW50XSxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuc2NzcyddLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgICAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVUaW1lUGlja2VyQ29tcG9uZW50KSxcbiAgICAgICAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgICB9LFxuICAgIF0sXG59KVxuZXhwb3J0IGNsYXNzIERhdGVUaW1lUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZmIgPSBpbmplY3QoRm9ybUJ1aWxkZXIpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gICAgQElucHV0KClcbiAgICBpZD86IHN0cmluZztcbiAgICBASG9zdEJpbmRpbmcoJ2F0dHIuaWQnKVxuICAgIGhvc3RJZCA9IG51bGw7XG4gICAgQElucHV0KClcbiAgICBtaW4hOiBudW1iZXI7XG4gICAgQElucHV0KClcbiAgICBtYXghOiBudW1iZXI7XG5cbiAgICByZWFkb25seSBMT0NBTF9USU1FX1pPTkVfT0ZGU0VUID0gTE9DQUxfVElNRV9aT05FX09GRlNFVDtcblxuICAgIHJlYWRvbmx5IGRhdGVUaW1lRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xuICAgICAgICBkYXRlOiB0aGlzLmZiLmNvbnRyb2w8bnVtYmVyIHwgbnVsbD4obnVsbCksXG4gICAgICAgIHRpbWU6IHRoaXMuZmIuY29udHJvbDxEYXRlVGltZU1vZGVsWyd0aW1lJ10gfCBudWxsPih7XG4gICAgICAgICAgICBob3VyOiAxMixcbiAgICAgICAgICAgIG1pbnV0ZTogMCxcbiAgICAgICAgICAgIHRpbWVQZXJpb2Q6ICdBTScsXG4gICAgICAgICAgICB0aW1lWm9uZTogdGhpcy5MT0NBTF9USU1FX1pPTkVfT0ZGU0VULFxuICAgICAgICB9KSxcbiAgICB9KTtcblxuICAgIHByb3RlY3RlZCBpbm5lclRpbWU6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gICAgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGluamVjdChEZXN0cm95UmVmKS5vbkRlc3Ryb3koKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XG4gICAgICAgICAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZGF0ZVRpbWVGb3JtLnZhbHVlQ2hhbmdlc1xuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKCh2YWx1ZSkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMuZ2V0Q29tYmluZWRUaW1lc3RhbXAodmFsdWUpLFxuICAgICAgICAgICAgICAgICAgICB0aW1lem9uZTogdmFsdWUudGltZT8udGltZVpvbmUgfHwgbnVsbCxcbiAgICAgICAgICAgICAgICB9KSksXG4gICAgICAgICAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKGEsIGIpID0+IGlzRXF1YWwoYSwgYikpLFxuICAgICAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSxcbiAgICAgICAgICAgIClcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbm5lclRpbWUgPSB2YWx1ZS52YWx1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgb25DaGFuZ2U6ICh2YWx1ZTogeyB2YWx1ZTogbnVtYmVyIHwgbnVsbDsgdGltZXpvbmU6IG51bWJlciB8IG51bGwgfSkgPT4gdm9pZCA9ICgpID0+IHt9O1xuICAgIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gICAgd3JpdGVWYWx1ZSh2YWx1ZT86IHsgdmFsdWU6IG51bWJlciB8IG51bGw7IHRpbWV6b25lOiBudW1iZXIgfSB8IG51bGwpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXMuaW5uZXJUaW1lID09PSB2YWx1ZT8udmFsdWUpIHJldHVybjtcblxuICAgICAgICBpZiAodmFsdWUgJiYgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiAhaXNOaWwodmFsdWUudmFsdWUpICYmIHR5cGVvZiB2YWx1ZS52YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1WYWx1ZSA9IHRoaXMuZ2V0Rm9ybVZhbHVlRnJvbVRpbWVzdGFtcCh2YWx1ZS52YWx1ZSwgdmFsdWUudGltZXpvbmUgfHwgbnVsbCk7XG4gICAgICAgICAgICB0aGlzLmRhdGVUaW1lRm9ybS5zZXRWYWx1ZShmb3JtVmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5kYXRlVGltZUZvcm0uc2V0VmFsdWUoY2xvbmVEZWVwKERFRkFVTFRfRk9STV9WQUxVRSksIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldEZvcm1WYWx1ZUZyb21UaW1lc3RhbXAodGltZXN0YW1wOiBudW1iZXIsIF90aW1lem9uZTogbnVtYmVyIHwgbnVsbCA9IHRoaXMuTE9DQUxfVElNRV9aT05FX09GRlNFVCk6IERhdGVUaW1lTW9kZWwge1xuICAgICAgICBjb25zdCBkYXRlTW9tZW50ID0gbW9tZW50LnVuaXgodGltZXN0YW1wKS51dGMoKTtcbiAgICAgICAgY29uc3QgdGltZXpvbmUgPSBfdGltZXpvbmUgfHwgMDtcbiAgICAgICAgY29uc3QgYWRqdXN0ZWREYXRlID0gZGF0ZU1vbWVudC5jbG9uZSgpLnV0Y09mZnNldCgtKHRpbWV6b25lIHx8IDApKTtcblxuICAgICAgICBsZXQgaG91cnMgPSBhZGp1c3RlZERhdGUuaG91cnMoKTtcbiAgICAgICAgbGV0IHRpbWVQZXJpb2Q6ICdBTScgfCAnUE0nID0gJ0FNJztcblxuICAgICAgICBpZiAoaG91cnMgPj0gMTIpIHtcbiAgICAgICAgICAgIHRpbWVQZXJpb2QgPSAnUE0nO1xuICAgICAgICAgICAgaWYgKGhvdXJzID4gMTIpIHtcbiAgICAgICAgICAgICAgICBob3VycyAtPSAxMjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChob3VycyA9PT0gMCkge1xuICAgICAgICAgICAgaG91cnMgPSAxMjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkYXRlOiBkYXRlTW9tZW50LmNsb25lKCkuYWRkKHsgaG91cnM6IC10aW1lem9uZSB9KS51bml4KCksXG4gICAgICAgICAgICB0aW1lOiB7XG4gICAgICAgICAgICAgICAgaG91cjogaG91cnMsXG4gICAgICAgICAgICAgICAgbWludXRlOiBhZGp1c3RlZERhdGUubWludXRlcygpLFxuICAgICAgICAgICAgICAgIHRpbWVQZXJpb2QsXG4gICAgICAgICAgICAgICAgdGltZVpvbmU6IHRpbWV6b25lLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBwcml2YXRlIGdldENvbWJpbmVkVGltZXN0YW1wKHsgZGF0ZSwgdGltZSB9OiBQYXJ0aWFsPERhdGVUaW1lTW9kZWw+KTogbnVtYmVyIHwgbnVsbCB7XG4gICAgICAgIGlmICghZGF0ZSB8fCAhdGltZSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgaG91cnMgPSB0aW1lLmhvdXI7XG5cbiAgICAgICAgaWYgKHRpbWUudGltZVBlcmlvZCA9PT0gJ1BNJyAmJiBob3VycyA8IDEyKSB7XG4gICAgICAgICAgICBob3VycyArPSAxMjtcbiAgICAgICAgfSBlbHNlIGlmICh0aW1lLnRpbWVQZXJpb2QgPT09ICdBTScgJiYgaG91cnMgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VycyA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkYXRlT2JqID0gbW9tZW50LnVuaXgoZGF0ZSkudXRjKCk7XG4gICAgICAgIGNvbnN0IGNvbWJpbmVkRGF0ZSA9IGRhdGVPYmouc3RhcnRPZignZGF5JykuYWRkKHsgaG91cjogaG91cnMsIG1pbnV0ZTogdGltZS5taW51dGUgfSk7XG4gICAgICAgIHJldHVybiBjb21iaW5lZERhdGUudW5peCgpO1xuICAgIH1cblxuICAgIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICAgIH1cblxuICAgIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAoaXNEaXNhYmxlZCkge1xuICAgICAgICAgICAgdGhpcy5kYXRlVGltZUZvcm0uZGlzYWJsZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5kYXRlVGltZUZvcm0uZW5hYmxlKCk7XG4gICAgICAgIH1cbiAgICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiZHItZGF0ZS10aW1lLXBpY2tlclwiPlxuICAgIDxpbnB1dCBbYXR0ci5pZF09XCJpZFwiIHR5cGU9XCJoaWRkZW5cIiBbdmFsdWVdPVwiaW5uZXJUaW1lIHwgZGF0ZTogJ0RELU1NLVlZWVkgSEg6bW0nXCIgLz5cbiAgICA8ZHItZGF0ZS1waWNrZXJcbiAgICAgICAgW2lkXT1cImlkXCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cImRhdGVUaW1lRm9ybS5jb250cm9scy5kYXRlXCJcbiAgICAgICAgW21pbl09XCJtaW5cIlxuICAgICAgICBbbWF4XT1cIm1heFwiXG4gICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uVG91Y2hlZCgpXCJcbiAgICAgICAgY2xhc3M9XCJkci1kYXRlLXRpbWUtcGlja2VyX19kYXRlXCIgLz5cblxuICAgIDxkaXYgY2xhc3M9XCJkci1kYXRlLXRpbWUtcGlja2VyX190aW1lXCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiZHItZGF0ZS10aW1lLXBpY2tlcl9fYXRcIj5BdDwvc3Bhbj5cbiAgICAgICAgPGRyLXRpbWUtcGlja2VyXG4gICAgICAgICAgICBjbGFzcz1cImRyLWRhdGUtdGltZS1waWNrZXJfX3RpbWUtcGlja2VyXCJcbiAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJkYXRlVGltZUZvcm0uY29udHJvbHMudGltZVwiXG4gICAgICAgICAgICAobmdNb2RlbENoYW5nZSk9XCJvblRvdWNoZWQoKVwiXG4gICAgICAgICAgICBkYXRhLXRlc3RpZD1cImRhdGUtdGltZS1waWNrZXItdGltZS1waWNrZXJcIiAvPlxuICAgIDwvZGl2PlxuPC9kaXY+XG4iXX0=
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { CommonModule } from '@angular/common';
|
|
2
|
+
import { Component, forwardRef, ChangeDetectionStrategy, ViewEncapsulation, inject, ChangeDetectorRef, Input, HostBinding, } from '@angular/core';
|
|
3
|
+
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
4
|
+
import { isNil } from 'lodash';
|
|
5
|
+
import { DrInputsModule } from '../../dr-inputs.module';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "@angular/common";
|
|
8
|
+
import * as i2 from "../../dr-input/dr-input.component";
|
|
9
|
+
import * as i3 from "../../dr-select/dr-select.component";
|
|
10
|
+
import * as i4 from "@angular/forms";
|
|
11
|
+
function TimePickerComponent_ng_template_16_Template(rf, ctx) { if (rf & 1) {
|
|
12
|
+
i0.ɵɵtext(0);
|
|
13
|
+
} if (rf & 2) {
|
|
14
|
+
const item_r2 = ctx.item;
|
|
15
|
+
const ctx_r1 = i0.ɵɵnextContext();
|
|
16
|
+
i0.ɵɵtextInterpolate1(" ", ctx_r1.LOCAL_TIME_ZONE_OFFSET !== ctx_r1.cronModel.timeZone ? item_r2.label : "Local Time", " ");
|
|
17
|
+
} }
|
|
18
|
+
export const LOCAL_TIME_ZONE_OFFSET = new Date().getTimezoneOffset() / 60;
|
|
19
|
+
export const getGMTLabel = (offset) => {
|
|
20
|
+
const sign = offset < 0 ? '-' : '+';
|
|
21
|
+
const offsetPrefix = Math.abs(offset) > 9 ? '' : '0';
|
|
22
|
+
return `GMT${sign}${offsetPrefix}${Math.abs(offset)}:00`;
|
|
23
|
+
};
|
|
24
|
+
export const GMT_OFFSETS = new Array(27).fill(null).map((v, index) => {
|
|
25
|
+
const offset = index - 12;
|
|
26
|
+
return {
|
|
27
|
+
value: -offset,
|
|
28
|
+
label: `${getGMTLabel(offset)}${LOCAL_TIME_ZONE_OFFSET === -offset ? ' (Local Time)' : ''}`,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
export class TimePickerComponent {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
34
|
+
this.hostId = null;
|
|
35
|
+
this.uniqueId = `time-picker-${TimePickerComponent.nextUniqueId++}`;
|
|
36
|
+
this.CRON_TIME_PERIOD_ARRAY = ['AM', 'PM'];
|
|
37
|
+
this.LOCAL_TIME_ZONE_OFFSET = LOCAL_TIME_ZONE_OFFSET;
|
|
38
|
+
this.GMT_OFFSETS = GMT_OFFSETS;
|
|
39
|
+
this.cronModel = {
|
|
40
|
+
hour: 12,
|
|
41
|
+
minute: 0,
|
|
42
|
+
timePeriod: 'AM',
|
|
43
|
+
timeZone: this.LOCAL_TIME_ZONE_OFFSET,
|
|
44
|
+
};
|
|
45
|
+
this.onChange = () => { };
|
|
46
|
+
this.onTouched = () => { };
|
|
47
|
+
}
|
|
48
|
+
// Unique ID for each instance
|
|
49
|
+
static { this.nextUniqueId = 0; }
|
|
50
|
+
// Helper to generate unique IDs for controls
|
|
51
|
+
get hourInputId() {
|
|
52
|
+
return `${this.uniqueId}-hour`;
|
|
53
|
+
}
|
|
54
|
+
get minuteInputId() {
|
|
55
|
+
return `${this.uniqueId}-minute`;
|
|
56
|
+
}
|
|
57
|
+
get periodSelectId() {
|
|
58
|
+
return `${this.uniqueId}-period`;
|
|
59
|
+
}
|
|
60
|
+
get timezoneSelectId() {
|
|
61
|
+
return `${this.uniqueId}-timezone`;
|
|
62
|
+
}
|
|
63
|
+
get labelId() {
|
|
64
|
+
return `${this.uniqueId}-label`;
|
|
65
|
+
}
|
|
66
|
+
onSelectionChange(model) {
|
|
67
|
+
const value = { ...this.getTimeValue(), ...model };
|
|
68
|
+
this.onChange(value);
|
|
69
|
+
this.onTouched();
|
|
70
|
+
}
|
|
71
|
+
getTimeValue() {
|
|
72
|
+
return {
|
|
73
|
+
hour: this.cronModel.hour,
|
|
74
|
+
minute: this.cronModel.minute,
|
|
75
|
+
timePeriod: this.cronModel.timePeriod,
|
|
76
|
+
timeZone: this.cronModel.timeZone,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
writeValue(value) {
|
|
80
|
+
if (value && typeof value === 'object') {
|
|
81
|
+
this.cronModel = {
|
|
82
|
+
hour: value.hour !== undefined ? value.hour : this.cronModel.hour,
|
|
83
|
+
minute: value.minute !== undefined ? value.minute : this.cronModel.minute,
|
|
84
|
+
timePeriod: TimePickerComponent.validTimePeriod(value.timePeriod) ? value.timePeriod : this.cronModel.timePeriod,
|
|
85
|
+
timeZone: isNil(value.timeZone) ? this.cronModel.timeZone : value.timeZone,
|
|
86
|
+
};
|
|
87
|
+
this.cdr.detectChanges();
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
this.cronModel = {
|
|
91
|
+
hour: 12,
|
|
92
|
+
minute: 0,
|
|
93
|
+
timePeriod: 'AM',
|
|
94
|
+
timeZone: this.LOCAL_TIME_ZONE_OFFSET,
|
|
95
|
+
};
|
|
96
|
+
this.cdr.detectChanges();
|
|
97
|
+
}
|
|
98
|
+
registerOnChange(fn) {
|
|
99
|
+
this.onChange = fn;
|
|
100
|
+
}
|
|
101
|
+
registerOnTouched(fn) {
|
|
102
|
+
this.onTouched = fn;
|
|
103
|
+
}
|
|
104
|
+
setDisabledState(isDisabled) {
|
|
105
|
+
this._disabled = isDisabled;
|
|
106
|
+
this.cdr.markForCheck();
|
|
107
|
+
}
|
|
108
|
+
static validTimePeriod(value) {
|
|
109
|
+
return value === 'AM' || value === 'PM';
|
|
110
|
+
}
|
|
111
|
+
/** @nocollapse */ static { this.ɵfac = function TimePickerComponent_Factory(t) { return new (t || TimePickerComponent)(); }; }
|
|
112
|
+
/** @nocollapse */ static { this.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: TimePickerComponent, selectors: [["dr-time-picker"]], hostVars: 1, hostBindings: function TimePickerComponent_HostBindings(rf, ctx) { if (rf & 2) {
|
|
113
|
+
i0.ɵɵattribute("id", ctx.hostId);
|
|
114
|
+
} }, inputs: { id: "id" }, standalone: true, features: [i0.ɵɵProvidersFeature([
|
|
115
|
+
{
|
|
116
|
+
provide: NG_VALUE_ACCESSOR,
|
|
117
|
+
useExisting: forwardRef((() => TimePickerComponent)),
|
|
118
|
+
multi: true,
|
|
119
|
+
},
|
|
120
|
+
]), i0.ɵɵStandaloneFeature], decls: 18, vars: 30, consts: [[1, "visually-hidden", 3, "id", "for"], ["type", "hidden", "name", "time-picker-value", 3, "value"], ["aria-label", "Hour", "type", "number", 1, "hours-input", 3, "id", "ngModel", "mask", "min", "max", "disabled", "ngModelChange"], ["aria-hidden", "true", 1, "time-dots"], [1, "visually-hidden", 3, "for"], ["aria-label", "Minute", "type", "number", 1, "minutes-input", 3, "id", "ngModel", "mask", "min", "max", "disabled", "ngModelChange"], ["aria-label", "AM or PM", 1, "time-period-selector", 3, "id", "ngModel", "items", "disabled", "ngModelChange", "change"], ["aria-label", "Time Zone", "bindLabel", "label", "bindValue", "value", 1, "gmt-offsets", 3, "id", "ngModel", "items", "textView", "disabled", "ngModelChange", "change"], ["labelTemplate", ""]], template: function TimePickerComponent_Template(rf, ctx) { if (rf & 1) {
|
|
121
|
+
i0.ɵɵelementStart(0, "label", 0);
|
|
122
|
+
i0.ɵɵtext(1, "Time Picker");
|
|
123
|
+
i0.ɵɵelementEnd();
|
|
124
|
+
i0.ɵɵelement(2, "input", 1);
|
|
125
|
+
i0.ɵɵpipe(3, "json");
|
|
126
|
+
i0.ɵɵelementStart(4, "dr-input", 2);
|
|
127
|
+
i0.ɵɵlistener("ngModelChange", function TimePickerComponent_Template_dr_input_ngModelChange_4_listener($event) { return ctx.cronModel.hour = $event; })("ngModelChange", function TimePickerComponent_Template_dr_input_ngModelChange_4_listener($event) { return ctx.onSelectionChange({ hour: $event }); });
|
|
128
|
+
i0.ɵɵelementEnd();
|
|
129
|
+
i0.ɵɵelementStart(5, "span", 3);
|
|
130
|
+
i0.ɵɵtext(6, ":");
|
|
131
|
+
i0.ɵɵelementEnd();
|
|
132
|
+
i0.ɵɵelementStart(7, "label", 4);
|
|
133
|
+
i0.ɵɵtext(8, "Minute");
|
|
134
|
+
i0.ɵɵelementEnd();
|
|
135
|
+
i0.ɵɵelementStart(9, "dr-input", 5);
|
|
136
|
+
i0.ɵɵlistener("ngModelChange", function TimePickerComponent_Template_dr_input_ngModelChange_9_listener($event) { return ctx.cronModel.minute = $event; })("ngModelChange", function TimePickerComponent_Template_dr_input_ngModelChange_9_listener($event) { return ctx.onSelectionChange({ minute: $event }); });
|
|
137
|
+
i0.ɵɵelementEnd();
|
|
138
|
+
i0.ɵɵelementStart(10, "label", 4);
|
|
139
|
+
i0.ɵɵtext(11, "AM or PM");
|
|
140
|
+
i0.ɵɵelementEnd();
|
|
141
|
+
i0.ɵɵelementStart(12, "dr-select", 6);
|
|
142
|
+
i0.ɵɵlistener("ngModelChange", function TimePickerComponent_Template_dr_select_ngModelChange_12_listener($event) { return ctx.cronModel.timePeriod = $event; })("change", function TimePickerComponent_Template_dr_select_change_12_listener($event) { return ctx.onSelectionChange({ timePeriod: $event }); });
|
|
143
|
+
i0.ɵɵelementEnd();
|
|
144
|
+
i0.ɵɵelementStart(13, "label", 4);
|
|
145
|
+
i0.ɵɵtext(14, "Time Zone");
|
|
146
|
+
i0.ɵɵelementEnd();
|
|
147
|
+
i0.ɵɵelementStart(15, "dr-select", 7);
|
|
148
|
+
i0.ɵɵlistener("ngModelChange", function TimePickerComponent_Template_dr_select_ngModelChange_15_listener($event) { return ctx.cronModel.timeZone = $event; })("change", function TimePickerComponent_Template_dr_select_change_15_listener($event) { return ctx.onSelectionChange({ timeZone: $event }); });
|
|
149
|
+
i0.ɵɵtemplate(16, TimePickerComponent_ng_template_16_Template, 1, 1, "ng-template", null, 8, i0.ɵɵtemplateRefExtractor);
|
|
150
|
+
i0.ɵɵelementEnd();
|
|
151
|
+
} if (rf & 2) {
|
|
152
|
+
i0.ɵɵproperty("id", ctx.labelId)("for", ctx.id);
|
|
153
|
+
i0.ɵɵadvance(2);
|
|
154
|
+
i0.ɵɵproperty("value", i0.ɵɵpipeBind1(3, 28, ctx.cronModel));
|
|
155
|
+
i0.ɵɵattribute("id", ctx.id);
|
|
156
|
+
i0.ɵɵadvance(2);
|
|
157
|
+
i0.ɵɵproperty("id", ctx.hourInputId)("ngModel", ctx.cronModel.hour)("mask", "00")("min", 0)("max", 12)("disabled", !!ctx._disabled);
|
|
158
|
+
i0.ɵɵadvance(3);
|
|
159
|
+
i0.ɵɵproperty("for", ctx.minuteInputId);
|
|
160
|
+
i0.ɵɵadvance(2);
|
|
161
|
+
i0.ɵɵproperty("id", ctx.minuteInputId)("ngModel", ctx.cronModel.minute)("mask", "00")("min", 0)("max", 59)("disabled", !!ctx._disabled);
|
|
162
|
+
i0.ɵɵadvance(1);
|
|
163
|
+
i0.ɵɵproperty("for", ctx.periodSelectId);
|
|
164
|
+
i0.ɵɵadvance(2);
|
|
165
|
+
i0.ɵɵproperty("id", ctx.periodSelectId)("ngModel", ctx.cronModel.timePeriod)("items", ctx.CRON_TIME_PERIOD_ARRAY)("disabled", !!ctx._disabled);
|
|
166
|
+
i0.ɵɵadvance(1);
|
|
167
|
+
i0.ɵɵproperty("for", ctx.timezoneSelectId);
|
|
168
|
+
i0.ɵɵadvance(2);
|
|
169
|
+
i0.ɵɵproperty("id", ctx.timezoneSelectId)("ngModel", ctx.cronModel.timeZone)("items", ctx.GMT_OFFSETS)("textView", true)("disabled", !!ctx._disabled);
|
|
170
|
+
} }, dependencies: [CommonModule, i1.JsonPipe, DrInputsModule, i2.DrInputComponent, i3.DrSelectComponent, FormsModule, i4.NgControlStatus, i4.NgModel], styles: ["dr-time-picker{display:flex;align-items:center}dr-time-picker .hours-input{min-width:62px;flex:1;margin-left:8px}dr-time-picker .minutes-input{min-width:62px;flex:1}dr-time-picker .time-period-selector{min-width:64px;flex:1;margin-left:8px}dr-time-picker .time-dots{margin:0 4px}dr-time-picker .gmt-offsets{margin-left:16px}dr-time-picker .visually-hidden{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}\n"], encapsulation: 2, changeDetection: 0 }); }
|
|
171
|
+
}
|
|
172
|
+
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(TimePickerComponent, [{
|
|
173
|
+
type: Component,
|
|
174
|
+
args: [{ selector: 'dr-time-picker', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [CommonModule, DrInputsModule, FormsModule], providers: [
|
|
175
|
+
{
|
|
176
|
+
provide: NG_VALUE_ACCESSOR,
|
|
177
|
+
useExisting: forwardRef((() => TimePickerComponent)),
|
|
178
|
+
multi: true,
|
|
179
|
+
},
|
|
180
|
+
], encapsulation: ViewEncapsulation.None, template: "<label [id]=\"labelId\" class=\"visually-hidden\" [for]=\"id\">Time Picker</label>\n<input type=\"hidden\" [attr.id]=\"id\" [value]=\"cronModel | json\" name=\"time-picker-value\" />\n<dr-input\n [id]=\"hourInputId\"\n aria-label=\"Hour\"\n [(ngModel)]=\"cronModel.hour\"\n (ngModelChange)=\"onSelectionChange({ hour: $event })\"\n [mask]=\"'00'\"\n [min]=\"0\"\n [max]=\"12\"\n [disabled]=\"!!_disabled\"\n type=\"number\"\n class=\"hours-input\">\n</dr-input>\n<span class=\"time-dots\" aria-hidden=\"true\">:</span>\n<label class=\"visually-hidden\" [for]=\"minuteInputId\">Minute</label>\n<dr-input\n [id]=\"minuteInputId\"\n aria-label=\"Minute\"\n [(ngModel)]=\"cronModel.minute\"\n (ngModelChange)=\"onSelectionChange({ minute: $event })\"\n [mask]=\"'00'\"\n [min]=\"0\"\n [max]=\"59\"\n [disabled]=\"!!_disabled\"\n type=\"number\"\n class=\"minutes-input\">\n</dr-input>\n<label class=\"visually-hidden\" [for]=\"periodSelectId\">AM or PM</label>\n<dr-select\n [id]=\"periodSelectId\"\n aria-label=\"AM or PM\"\n [(ngModel)]=\"cronModel.timePeriod\"\n (change)=\"onSelectionChange({ timePeriod: $event })\"\n [items]=\"CRON_TIME_PERIOD_ARRAY\"\n [disabled]=\"!!_disabled\"\n class=\"time-period-selector\"></dr-select>\n<label class=\"visually-hidden\" [for]=\"timezoneSelectId\">Time Zone</label>\n<dr-select\n [id]=\"timezoneSelectId\"\n aria-label=\"Time Zone\"\n [(ngModel)]=\"cronModel.timeZone\"\n (change)=\"onSelectionChange({ timeZone: $event })\"\n [items]=\"GMT_OFFSETS\"\n [textView]=\"true\"\n [disabled]=\"!!_disabled\"\n bindLabel=\"label\"\n bindValue=\"value\"\n class=\"gmt-offsets\">\n <ng-template #labelTemplate let-item=\"item\">\n {{ LOCAL_TIME_ZONE_OFFSET !== cronModel.timeZone ? item.label : 'Local Time' }}\n </ng-template>\n</dr-select>\n", styles: ["dr-time-picker{display:flex;align-items:center}dr-time-picker .hours-input{min-width:62px;flex:1;margin-left:8px}dr-time-picker .minutes-input{min-width:62px;flex:1}dr-time-picker .time-period-selector{min-width:64px;flex:1;margin-left:8px}dr-time-picker .time-dots{margin:0 4px}dr-time-picker .gmt-offsets{margin-left:16px}dr-time-picker .visually-hidden{position:absolute!important;height:1px;width:1px;overflow:hidden;clip:rect(1px,1px,1px,1px);white-space:nowrap}\n"] }]
|
|
181
|
+
}], null, { id: [{
|
|
182
|
+
type: Input
|
|
183
|
+
}], hostId: [{
|
|
184
|
+
type: HostBinding,
|
|
185
|
+
args: ['attr.id']
|
|
186
|
+
}] }); })();
|
|
187
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZGF0YXJhaWxzc2hhcmVkL3NyYy9saWIvZHItaW5wdXRzL2RhdGUtcGlja2Vycy90aW1lLXBpY2tlci90aW1lLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kYXRhcmFpbHNzaGFyZWQvc3JjL2xpYi9kci1pbnB1dHMvZGF0ZS1waWNrZXJzL3RpbWUtcGlja2VyL3RpbWUtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQ0gsU0FBUyxFQUNULFVBQVUsRUFDVix1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLE1BQU0sRUFDTixpQkFBaUIsRUFDakIsS0FBSyxFQUNMLFdBQVcsR0FDZCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLFdBQVcsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxRQUFRLENBQUM7QUFDL0IsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDOzs7Ozs7O0lDcUNoRCxZQUNKOzs7O0lBREksMkhBQ0o7O0FEN0JKLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLElBQUksSUFBSSxFQUFFLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFMUUsTUFBTSxDQUFDLE1BQU0sV0FBVyxHQUFHLENBQUMsTUFBYyxFQUFVLEVBQUU7SUFDbEQsTUFBTSxJQUFJLEdBQUcsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDcEMsTUFBTSxZQUFZLEdBQUcs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WUFZUyxlQUFxQjtZQUFyQix1Q0FBcUI7WUFFaEQsZUFBb0I7WUFBcEIsc0NBQW9CLGlDQUFBLGNBQUEsVUFBQSxXQUFBLDZCQUFBO1lBV08sZUFBc0I7WUFBdEIsd0NBQXNCO1lBRWpELGVBQXFCO1lBQXJCLHVDQUFxQixxQ0FBQSxxQ0FBQSw2QkFBQTtZQU9NLGVBQXdCO1lBQXhCLDBDQUF3QjtZQUVuRCxlQUF1QjtZQUF2Qix5Q0FBdUIsbUNBQUEsMEJBQUEsa0JBQUEsNkJBQUE7NEJER2IsWUFBWSxlQUFFLGNBQWMsNkNBQUUsV0FBVzs7dUZBYTFDLG1CQUFtQjtjQWpCL0IsU0FBUzsyQkFDSSxnQkFBZ0IsbUJBQ1QsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJLFdBQ1AsQ0FBQyxZQUFZLEVBQUUsY0FBYyxFQUFFLFdBQVcsQ0FBQyxhQUd6QztvQkFDUDt3QkFDSSxPQUFPLEVBQUUsaUJBQWlCO3dCQUMxQixXQUFXLEVBQUUsVUFBVSxFQUFDLEdBQUcsRUFBRSxvQkFBb0IsRUFBQzt3QkFDbEQsS0FBSyxFQUFFLElBQUk7cUJBQ2Q7aUJBQ0osaUJBRWMsaUJBQWlCLENBQUMsSUFBSTtnQkFNckMsRUFBRTtrQkFERCxLQUFLO1lBR04sTUFBTTtrQkFETCxXQUFXO21CQUFDLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHtcbiAgICBDb21wb25lbnQsXG4gICAgZm9yd2FyZFJlZixcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgICBpbmplY3QsXG4gICAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgSW5wdXQsXG4gICAgSG9zdEJpbmRpbmcsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udHJvbFZhbHVlQWNjZXNzb3IsIEZvcm1zTW9kdWxlLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IGlzTmlsIH0gZnJvbSAnbG9kYXNoJztcbmltcG9ydCB7IERySW5wdXRzTW9kdWxlIH0gZnJvbSAnLi4vLi4vZHItaW5wdXRzLm1vZHVsZSc7XG5cbmV4cG9ydCB0eXBlIFRpbWVwaWNrZXJNb2RlbCA9IHtcbiAgICBob3VyOiBudW1iZXI7XG4gICAgbWludXRlOiBudW1iZXI7XG4gICAgdGltZVBlcmlvZDogJ0FNJyB8ICdQTSc7XG4gICAgdGltZVpvbmU6IG51bWJlcjtcbn07XG5cbmV4cG9ydCBjb25zdCBMT0NBTF9USU1FX1pPTkVfT0ZGU0VUID0gbmV3IERhdGUoKS5nZXRUaW1lem9uZU9mZnNldCgpIC8gNjA7XG5cbmV4cG9ydCBjb25zdCBnZXRHTVRMYWJlbCA9IChvZmZzZXQ6IG51bWJlcik6IHN0cmluZyA9PiB7XG4gICAgY29uc3Qgc2lnbiA9IG9mZnNldCA8IDAgPyAnLScgOiAnKyc7XG4gICAgY29uc3Qgb2Zmc2V0UHJlZml4ID0gTWF0aC5hYnMob2Zmc2V0KSA+IDkgPyAnJyA6ICcwJztcbiAgICByZXR1cm4gYEdNVCR7c2lnbn0ke29mZnNldFByZWZpeH0ke01hdGguYWJzKG9mZnNldCl9OjAwYDtcbn07XG5cbmV4cG9ydCBjb25zdCBHTVRfT0ZGU0VUUyA9IG5ldyBBcnJheSgyNykuZmlsbChudWxsKS5tYXAoKHYsIGluZGV4KSA9PiB7XG4gICAgY29uc3Qgb2Zmc2V0ID0gaW5kZXggLSAxMjtcbiAgICByZXR1cm4ge1xuICAgICAgICB2YWx1ZTogLW9mZnNldCxcbiAgICAgICAgbGFiZWw6IGAke2dldEdNVExhYmVsKG9mZnNldCl9JHtMT0NBTF9USU1FX1pPTkVfT0ZGU0VUID09PSAtb2Zmc2V0ID8gJyAoTG9jYWwgVGltZSknIDogJyd9YCxcbiAgICB9O1xufSk7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnZHItdGltZS1waWNrZXInLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRHJJbnB1dHNNb2R1bGUsIEZvcm1zTW9kdWxlXSxcbiAgICB0ZW1wbGF0ZVVybDogJy4vdGltZS1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxuICAgIHN0eWxlVXJsczogWycuL3RpbWUtcGlja2VyLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAgICAgICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGltZVBpY2tlckNvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICBdLFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAYW5ndWxhci1lc2xpbnQvdXNlLWNvbXBvbmVudC12aWV3LWVuY2Fwc3VsYXRpb25cbiAgICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxufSlcbmV4cG9ydCBjbGFzcyBUaW1lUGlja2VyQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3Ige1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICAgIEBJbnB1dCgpXG4gICAgaWQ/OiBzdHJpbmc7XG4gICAgQEhvc3RCaW5kaW5nKCdhdHRyLmlkJylcbiAgICBob3N0SWQgPSBudWxsO1xuXG4gICAgLy8gVW5pcXVlIElEIGZvciBlYWNoIGluc3RhbmNlXG4gICAgcHJpdmF0ZSBzdGF0aWMgbmV4dFVuaXF1ZUlkID0gMDtcbiAgICByZWFkb25seSB1bmlxdWVJZCA9IGB0aW1lLXBpY2tlci0ke1RpbWVQaWNrZXJDb21wb25lbnQubmV4dFVuaXF1ZUlkKyt9YDtcblxuICAgIHJlYWRvbmx5IENST05fVElNRV9QRVJJT0RfQVJSQVk6ICgnQU0nIHwgJ1BNJylbXSA9IFsnQU0nLCAnUE0nXTtcblxuICAgIHJlYWRvbmx5IExPQ0FMX1RJTUVfWk9ORV9PRkZTRVQgPSBMT0NBTF9USU1FX1pPTkVfT0ZGU0VUO1xuXG4gICAgcmVhZG9ubHkgR01UX09GRlNFVFMgPSBHTVRfT0ZGU0VUUztcblxuICAgIGNyb25Nb2RlbDogVGltZXBpY2tlck1vZGVsID0ge1xuICAgICAgICBob3VyOiAxMixcbiAgICAgICAgbWludXRlOiAwLFxuICAgICAgICB0aW1lUGVyaW9kOiAnQU0nLFxuICAgICAgICB0aW1lWm9uZTogdGhpcy5MT0NBTF9USU1FX1pPTkVfT0ZGU0VULFxuICAgIH07XG5cbiAgICBfZGlzYWJsZWQ/OiBib29sZWFuO1xuXG4gICAgcHJpdmF0ZSBvbkNoYW5nZTogKHZhbHVlOiBhbnkpID0+IHZvaWQgPSAoKSA9PiB7fTtcbiAgICBwcml2YXRlIG9uVG91Y2hlZDogKCkgPT4gdm9pZCA9ICgpID0+IHt9O1xuXG4gICAgLy8gSGVscGVyIHRvIGdlbmVyYXRlIHVuaXF1ZSBJRHMgZm9yIGNvbnRyb2xzXG4gICAgZ2V0IGhvdXJJbnB1dElkKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy51bmlxdWVJZH0taG91cmA7XG4gICAgfVxuICAgIGdldCBtaW51dGVJbnB1dElkKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy51bmlxdWVJZH0tbWludXRlYDtcbiAgICB9XG4gICAgZ2V0IHBlcmlvZFNlbGVjdElkKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy51bmlxdWVJZH0tcGVyaW9kYDtcbiAgICB9XG4gICAgZ2V0IHRpbWV6b25lU2VsZWN0SWQoKSB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLnVuaXF1ZUlkfS10aW1lem9uZWA7XG4gICAgfVxuICAgIGdldCBsYWJlbElkKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy51bmlxdWVJZH0tbGFiZWxgO1xuICAgIH1cblxuICAgIG9uU2VsZWN0aW9uQ2hhbmdlKG1vZGVsOiBQYXJ0aWFsPFRpbWVwaWNrZXJNb2RlbD4pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSB7IC4uLnRoaXMuZ2V0VGltZVZhbHVlKCksIC4uLm1vZGVsIH07XG5cbiAgICAgICAgdGhpcy5vbkNoYW5nZSh2YWx1ZSk7XG4gICAgICAgIHRoaXMub25Ub3VjaGVkKCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBnZXRUaW1lVmFsdWUoKTogVGltZXBpY2tlck1vZGVsIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGhvdXI6IHRoaXMuY3Jvbk1vZGVsLmhvdXIsXG4gICAgICAgICAgICBtaW51dGU6IHRoaXMuY3Jvbk1vZGVsLm1pbnV0ZSxcbiAgICAgICAgICAgIHRpbWVQZXJpb2Q6IHRoaXMuY3Jvbk1vZGVsLnRpbWVQZXJpb2QsXG4gICAgICAgICAgICB0aW1lWm9uZTogdGhpcy5jcm9uTW9kZWwudGltZVpvbmUsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgd3JpdGVWYWx1ZSh2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgICAgIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB0aGlzLmNyb25Nb2RlbCA9IHtcbiAgICAgICAgICAgICAgICBob3VyOiB2YWx1ZS5ob3VyICE9PSB1bmRlZmluZWQgPyB2YWx1ZS5ob3VyIDogdGhpcy5jcm9uTW9kZWwuaG91cixcbiAgICAgICAgICAgICAgICBtaW51dGU6IHZhbHVlLm1pbnV0ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUubWludXRlIDogdGhpcy5jcm9uTW9kZWwubWludXRlLFxuICAgICAgICAgICAgICAgIHRpbWVQZXJpb2Q6IFRpbWVQaWNrZXJDb21wb25lbnQudmFsaWRUaW1lUGVyaW9kKHZhbHVlLnRpbWVQZXJpb2QpID8gdmFsdWUudGltZVBlcmlvZCA6IHRoaXMuY3Jvbk1vZGVsLnRpbWVQZXJpb2QsXG4gICAgICAgICAgICAgICAgdGltZVpvbmU6IGlzTmlsKHZhbHVlLnRpbWVab25lKSA/IHRoaXMuY3Jvbk1vZGVsLnRpbWVab25lIDogdmFsdWUudGltZVpvbmUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuY3Jvbk1vZGVsID0ge1xuICAgICAgICAgICAgaG91cjogMTIsXG4gICAgICAgICAgICBtaW51dGU6IDAsXG4gICAgICAgICAgICB0aW1lUGVyaW9kOiAnQU0nLFxuICAgICAgICAgICAgdGltZVpvbmU6IHRoaXMuTE9DQUxfVElNRV9aT05FX09GRlNFVCxcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIH1cblxuICAgIHJlZ2lzdGVyT25DaGFuZ2UoZm46IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICAgIH1cblxuICAgIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICB0aGlzLl9kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG4gICAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIH1cblxuICAgIHN0YXRpYyB2YWxpZFRpbWVQZXJpb2QodmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBUaW1lcGlja2VyTW9kZWxbJ3RpbWVQZXJpb2QnXSB7XG4gICAgICAgIHJldHVybiB2YWx1ZSA9PT0gJ0FNJyB8fCB2YWx1ZSA9PT0gJ1BNJztcbiAgICB9XG59XG4iLCI8bGFiZWwgW2lkXT1cImxhYmVsSWRcIiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiIFtmb3JdPVwiaWRcIj5UaW1lIFBpY2tlcjwvbGFiZWw+XG48aW5wdXQgdHlwZT1cImhpZGRlblwiIFthdHRyLmlkXT1cImlkXCIgW3ZhbHVlXT1cImNyb25Nb2RlbCB8IGpzb25cIiBuYW1lPVwidGltZS1waWNrZXItdmFsdWVcIiAvPlxuPGRyLWlucHV0XG4gICAgW2lkXT1cImhvdXJJbnB1dElkXCJcbiAgICBhcmlhLWxhYmVsPVwiSG91clwiXG4gICAgWyhuZ01vZGVsKV09XCJjcm9uTW9kZWwuaG91clwiXG4gICAgKG5nTW9kZWxDaGFuZ2UpPVwib25TZWxlY3Rpb25DaGFuZ2UoeyBob3VyOiAkZXZlbnQgfSlcIlxuICAgIFttYXNrXT1cIicwMCdcIlxuICAgIFttaW5dPVwiMFwiXG4gICAgW21heF09XCIxMlwiXG4gICAgW2Rpc2FibGVkXT1cIiEhX2Rpc2FibGVkXCJcbiAgICB0eXBlPVwibnVtYmVyXCJcbiAgICBjbGFzcz1cImhvdXJzLWlucHV0XCI+XG48L2RyLWlucHV0PlxuPHNwYW4gY2xhc3M9XCJ0aW1lLWRvdHNcIiBhcmlhLWhpZGRlbj1cInRydWVcIj46PC9zcGFuPlxuPGxhYmVsIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCIgW2Zvcl09XCJtaW51dGVJbnB1dElkXCI+TWludXRlPC9sYWJlbD5cbjxkci1pbnB1dFxuICAgIFtpZF09XCJtaW51dGVJbnB1dElkXCJcbiAgICBhcmlhLWxhYmVsPVwiTWludXRlXCJcbiAgICBbKG5nTW9kZWwpXT1cImNyb25Nb2RlbC5taW51dGVcIlxuICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uU2VsZWN0aW9uQ2hhbmdlKHsgbWludXRlOiAkZXZlbnQgfSlcIlxuICAgIFttYXNrXT1cIicwMCdcIlxuICAgIFttaW5dPVwiMFwiXG4gICAgW21heF09XCI1OVwiXG4gICAgW2Rpc2FibGVkXT1cIiEhX2Rpc2FibGVkXCJcbiAgICB0eXBlPVwibnVtYmVyXCJcbiAgICBjbGFzcz1cIm1pbnV0ZXMtaW5wdXRcIj5cbjwvZHItaW5wdXQ+XG48bGFiZWwgY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIiBbZm9yXT1cInBlcmlvZFNlbGVjdElkXCI+QU0gb3IgUE08L2xhYmVsPlxuPGRyLXNlbGVjdFxuICAgIFtpZF09XCJwZXJpb2RTZWxlY3RJZFwiXG4gICAgYXJpYS1sYWJlbD1cIkFNIG9yIFBNXCJcbiAgICBbKG5nTW9kZWwpXT1cImNyb25Nb2RlbC50aW1lUGVyaW9kXCJcbiAgICAoY2hhbmdlKT1cIm9uU2VsZWN0aW9uQ2hhbmdlKHsgdGltZVBlcmlvZDogJGV2ZW50IH0pXCJcbiAgICBbaXRlbXNdPVwiQ1JPTl9USU1FX1BFUklPRF9BUlJBWVwiXG4gICAgW2Rpc2FibGVkXT1cIiEhX2Rpc2FibGVkXCJcbiAgICBjbGFzcz1cInRpbWUtcGVyaW9kLXNlbGVjdG9yXCI+PC9kci1zZWxlY3Q+XG48bGFiZWwgY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIiBbZm9yXT1cInRpbWV6b25lU2VsZWN0SWRcIj5UaW1lIFpvbmU8L2xhYmVsPlxuPGRyLXNlbGVjdFxuICAgIFtpZF09XCJ0aW1lem9uZVNlbGVjdElkXCJcbiAgICBhcmlhLWxhYmVsPVwiVGltZSBab25lXCJcbiAgICBbKG5nTW9kZWwpXT1cImNyb25Nb2RlbC50aW1lWm9uZVwiXG4gICAgKGNoYW5nZSk9XCJvblNlbGVjdGlvbkNoYW5nZSh7IHRpbWVab25lOiAkZXZlbnQgfSlcIlxuICAgIFtpdGVtc109XCJHTVRfT0ZGU0VUU1wiXG4gICAgW3RleHRWaWV3XT1cInRydWVcIlxuICAgIFtkaXNhYmxlZF09XCIhIV9kaXNhYmxlZFwiXG4gICAgYmluZExhYmVsPVwibGFiZWxcIlxuICAgIGJpbmRWYWx1ZT1cInZhbHVlXCJcbiAgICBjbGFzcz1cImdtdC1vZmZzZXRzXCI+XG4gICAgPG5nLXRlbXBsYXRlICNsYWJlbFRlbXBsYXRlIGxldC1pdGVtPVwiaXRlbVwiPlxuICAgICAgICB7eyBMT0NBTF9USU1FX1pPTkVfT0ZGU0VUICE9PSBjcm9uTW9kZWwudGltZVpvbmUgPyBpdGVtLmxhYmVsIDogJ0xvY2FsIFRpbWUnIH19XG4gICAgPC9uZy10ZW1wbGF0ZT5cbjwvZHItc2VsZWN0PlxuIl19
|