@nova-ui/bits
Version:
SolarWinds Nova Framework
222 lines • 35.1 kB
JavaScript
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, EventEmitter, forwardRef, Input, Output, Renderer2, ViewChild, ViewEncapsulation, } from "@angular/core";
import { NG_VALUE_ACCESSOR } from "@angular/forms";
import moment from "moment/moment";
import { NuiFormFieldControl } from "../form-field/public-api";
import * as i0 from "@angular/core";
import * as i1 from "../date-picker/date-picker.component";
import * as i2 from "../time-picker/time-picker.component";
// <example-url>./../examples/index.html#/date-time-picker</example-url><br />
export class DateTimePickerComponent {
/**
* Input to set aria label text
*/
get ariaLabel() {
return this._ariaLabel;
}
// changing the value with regular @Input doesn't trigger change detection
// so we need to do that manually in the setter
set ariaLabel(value) {
if (value !== this._ariaLabel) {
this._ariaLabel = value;
this.cd.markForCheck();
}
}
/** model of picker */
get model() {
return this._model;
}
set model(value) {
if (moment(value).isValid()) {
this._model = value;
}
this.updateChildrenModels();
}
constructor(renderer, cd) {
this.renderer = renderer;
this.cd = cd;
/** Callback to invoke on model change */
this.modelChanged = new EventEmitter();
this.isInErrorStateDate = false;
this.isInErrorStateTime = false;
this._ariaLabel = "";
this.onTouched = () => { };
this.onChange = (value) => { };
}
ngOnInit() {
if (!this.initEmpty && !this.model) {
this.model = moment();
this.onChange(this.model);
this.cd.markForCheck();
}
}
ngAfterViewInit() {
if (this.displayMode === "inline") {
this.renderer.addClass(this.codeElement.nativeElement, "nui-datetime-picker--inline");
this.renderer.addClass(this.codeElement.nativeElement.querySelector(".nui-timepicker"), "nui-dropdown--inline");
}
}
writeValue(value) {
this.model = value;
this.updateChildrenModels();
}
registerOnTouched(fn) {
this.onTouched = fn;
}
registerOnChange(fn) {
this.onChange = fn;
}
setDisabledState(isDisabled) {
this.isDisabled = isDisabled;
this.cd.markForCheck(); // This is needed to update "disabled" state for child date and time pickers
}
onTimeChanged(event) {
this.updateTime(event);
this.modelChanged.emit(moment(this.model));
this.onChange(this.model);
this.onTouched();
}
onDateChanged(event) {
const isDateTheSame = moment.isMoment(this.date) && this.date.isSame(event);
if (isDateTheSame) {
return;
}
this.updateDate(event);
this.modelChanged.emit(moment(this.model));
this.onChange(this.model);
this.onTouched();
}
onInputBlurred() {
this.onTouched();
if (!this.model) {
this.isInErrorStateDate =
!this.date || (this.date && !moment(this.date).isValid());
this.isInErrorStateTime =
!this.time || (this.time && !moment(this.time).isValid());
}
}
updateChildrenModels() {
if (this.model) {
this.date = this.model.clone();
this.time = this.model.clone();
}
else if (!this.model && this.initEmpty) {
// TODO: Replace with undefined
// @ts-ignore
this.date = null;
// @ts-ignore
this.time = null;
}
}
updateDate(newValue) {
if (!moment.isMoment(newValue) || !moment(newValue).isValid()) {
// TODO: Replace with undefined
// @ts-ignore
this._model = null;
// @ts-ignore
this.date = null;
return;
}
// In case 'date' is not set, this._model is set from 'time' model if 'time' model exists
this._model = this._model || (this.time && this.time.clone());
if (this._model) {
this._model.set({
year: newValue.year(),
month: newValue.month(),
date: newValue.date(),
});
}
this.date = newValue.clone();
}
updateTime(newValue) {
if (!moment.isMoment(newValue)) {
// TODO: Replace with undefined
// @ts-ignore
this._model = null;
// @ts-ignore
this.time = null;
return;
}
// In case 'time' is not set, this._model is set from 'date' model if 'date' model exists
this._model = this._model || (this.date && this.date.clone());
if (this._model) {
this._model.set({
hours: newValue.hours(),
minutes: newValue.minutes(),
seconds: newValue.seconds(),
milliseconds: newValue.millisecond(),
});
}
this.time = newValue.clone();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateTimePickerComponent, deps: [{ token: i0.Renderer2 }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: DateTimePickerComponent, selector: "nui-date-time-picker", inputs: { maxDate: "maxDate", minDate: "minDate", displayMode: "displayMode", isDisabled: "isDisabled", initEmpty: "initEmpty", handleTimezone: "handleTimezone", appendToBody: "appendToBody", ariaLabel: "ariaLabel", model: "model" }, outputs: { modelChanged: "modelChanged" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateTimePickerComponent),
multi: true,
},
{
provide: NuiFormFieldControl,
useExisting: forwardRef(() => DateTimePickerComponent),
multi: true,
},
], viewQueries: [{ propertyName: "codeElement", first: true, predicate: ["nuiDatetimePicker"], descendants: true, static: true }], ngImport: i0, template: "<div\n #nuiDatetimePicker\n class=\"nui-datetime-picker\"\n [attr.aria-label]=\"ariaLabel\"\n>\n <div class=\"nui-datetime-picker__group\">\n <nui-date-picker\n class=\"nui-datepicker--justified\"\n [value]=\"date\"\n (valueChange)=\"onDateChanged($event)\"\n (inputBlurred)=\"onInputBlurred()\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [isDisabled]=\"isDisabled\"\n [isInErrorState]=\"isInErrorStateDate\"\n [handleTimezone]=\"handleTimezone\"\n [appendToBody]=\"appendToBody\"\n [ariaLabel]=\"ariaLabel + ' date'\"\n ></nui-date-picker>\n </div>\n <div class=\"nui-datetime-picker__group nui-datetime-picker__group--last\">\n <nui-time-picker\n class=\"nui-dropdown--justified\"\n [initEmpty]=\"initEmpty\"\n [model]=\"time\"\n (timeChanged)=\"onTimeChanged($event)\"\n (inputBlurred)=\"onInputBlurred()\"\n [isDisabled]=\"isDisabled\"\n [isInErrorState]=\"isInErrorStateTime\"\n [appendToBody]=\"appendToBody\"\n [ariaLabel]=\"ariaLabel + ' time'\"\n ></nui-time-picker>\n </div>\n</div>\n", styles: [".nui .nui-datetime-picker{display:flex;flex-direction:column}.nui .nui-datetime-picker .nui-timepicker,.nui .nui-datetime-picker .nui-timepicker__input-group,.nui .nui-datetime-picker .nui-datepicker{width:100%}.nui .nui-datetime-picker__group{width:135px;margin-bottom:10px}.nui .nui-datetime-picker__group--last{margin-bottom:0}.nui .nui-datetime-picker--inline{width:auto;flex-direction:row;max-width:none}.nui .nui-datetime-picker--inline .nui-datetime-picker__label{display:inline-block;line-height:30px}.nui .nui-datetime-picker--inline .nui-datetime-picker__group,.nui .nui-datetime-picker--inline .nui-datetime-picker__label{margin-bottom:0}.nui .nui-datetime-picker--inline .nui-datetime-picker__group:not(:last-child),.nui .nui-datetime-picker--inline .nui-datetime-picker__label:not(:last-child){margin-right:10px}\n"], dependencies: [{ kind: "component", type: i1.DatePickerComponent, selector: "nui-date-picker", inputs: ["inline", "isRequired", "isDisabled", "isInErrorState", "ariaLabel", "locale", "datepickerMode", "minDate", "maxDate", "minMode", "maxMode", "showWeeks", "dateFormat", "formatDay", "formatMonth", "formatYear", "formatDayHeader", "formatDayTitle", "formatMonthTitle", "startingDay", "yearRange", "onlyCurrentMonth", "preserveInsignificant", "disabledDates", "handleTimezone", "appendToBody", "value"], outputs: ["selectionDone", "valueChange", "calendarNavigated", "inputBlurred"] }, { kind: "component", type: i2.TimePickerComponent, selector: "nui-time-picker", inputs: ["timeStep", "isDisabled", "timeFormat", "preserveInsignificant", "isInErrorState", "ariaLabel", "initEmpty", "appendToBody", "model"], outputs: ["timeChanged", "inputBlurred"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DateTimePickerComponent, decorators: [{
type: Component,
args: [{ selector: "nui-date-time-picker", providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DateTimePickerComponent),
multi: true,
},
{
provide: NuiFormFieldControl,
useExisting: forwardRef(() => DateTimePickerComponent),
multi: true,
},
], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n #nuiDatetimePicker\n class=\"nui-datetime-picker\"\n [attr.aria-label]=\"ariaLabel\"\n>\n <div class=\"nui-datetime-picker__group\">\n <nui-date-picker\n class=\"nui-datepicker--justified\"\n [value]=\"date\"\n (valueChange)=\"onDateChanged($event)\"\n (inputBlurred)=\"onInputBlurred()\"\n [maxDate]=\"maxDate\"\n [minDate]=\"minDate\"\n [isDisabled]=\"isDisabled\"\n [isInErrorState]=\"isInErrorStateDate\"\n [handleTimezone]=\"handleTimezone\"\n [appendToBody]=\"appendToBody\"\n [ariaLabel]=\"ariaLabel + ' date'\"\n ></nui-date-picker>\n </div>\n <div class=\"nui-datetime-picker__group nui-datetime-picker__group--last\">\n <nui-time-picker\n class=\"nui-dropdown--justified\"\n [initEmpty]=\"initEmpty\"\n [model]=\"time\"\n (timeChanged)=\"onTimeChanged($event)\"\n (inputBlurred)=\"onInputBlurred()\"\n [isDisabled]=\"isDisabled\"\n [isInErrorState]=\"isInErrorStateTime\"\n [appendToBody]=\"appendToBody\"\n [ariaLabel]=\"ariaLabel + ' time'\"\n ></nui-time-picker>\n </div>\n</div>\n", styles: [".nui .nui-datetime-picker{display:flex;flex-direction:column}.nui .nui-datetime-picker .nui-timepicker,.nui .nui-datetime-picker .nui-timepicker__input-group,.nui .nui-datetime-picker .nui-datepicker{width:100%}.nui .nui-datetime-picker__group{width:135px;margin-bottom:10px}.nui .nui-datetime-picker__group--last{margin-bottom:0}.nui .nui-datetime-picker--inline{width:auto;flex-direction:row;max-width:none}.nui .nui-datetime-picker--inline .nui-datetime-picker__label{display:inline-block;line-height:30px}.nui .nui-datetime-picker--inline .nui-datetime-picker__group,.nui .nui-datetime-picker--inline .nui-datetime-picker__label{margin-bottom:0}.nui .nui-datetime-picker--inline .nui-datetime-picker__group:not(:last-child),.nui .nui-datetime-picker--inline .nui-datetime-picker__label:not(:last-child){margin-right:10px}\n"] }]
}], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ChangeDetectorRef }], propDecorators: { maxDate: [{
type: Input
}], minDate: [{
type: Input
}], displayMode: [{
type: Input
}], isDisabled: [{
type: Input
}], initEmpty: [{
type: Input
}], handleTimezone: [{
type: Input
}], appendToBody: [{
type: Input
}], ariaLabel: [{
type: Input
}], codeElement: [{
type: ViewChild,
args: ["nuiDatetimePicker", { static: true }]
}], modelChanged: [{
type: Output
}], model: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL2RhdGUtdGltZS1waWNrZXIvZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9zcmMvbGliL2RhdGUtdGltZS1waWNrZXIvZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5REFBeUQ7QUFDekQsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw0RUFBNEU7QUFDNUUsOEVBQThFO0FBQzlFLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsNERBQTREO0FBQzVELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBQzVFLCtFQUErRTtBQUMvRSwwRUFBMEU7QUFDMUUsaUZBQWlGO0FBQ2pGLDZFQUE2RTtBQUM3RSxpQkFBaUI7QUFFakIsT0FBTyxFQUVILHVCQUF1QixFQUN2QixpQkFBaUIsRUFDakIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsRUFDVCxpQkFBaUIsR0FDcEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sTUFBTSxNQUFNLGVBQWUsQ0FBQztBQUduQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7OztBQUUvRCw4RUFBOEU7QUFxQjlFLE1BQU0sT0FBTyx1QkFBdUI7SUFrQmhDOztPQUVHO0lBQ0gsSUFBb0IsU0FBUztRQUN6QixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUM7SUFDM0IsQ0FBQztJQUVELDBFQUEwRTtJQUMxRSwrQ0FBK0M7SUFDL0MsSUFBVyxT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LEtBQUssRUFBRSxJQUFJO3lCQUNkO3dCQUNEOzRCQUNJLE9BQU8sRUFBRSxtQkFBbUI7NEJBQzVCLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLHdCQUF3QixDQUFDOzRCQUN0RCxLQUFLLEVBQUUsSUFBSTt5QkFDZDtxQkFDSixpQkFFYyxpQkFBaUIsQ0FBQyxJQUFJLG1CQUNwQix1QkFBdUIsQ0FBQyxNQUFNOzhHQU10QyxPQUFPO3NCQUFmLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUVHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQUVHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBRUcsWUFBWTtzQkFBcEIsS0FBSztnQkFLYyxTQUFTO3NCQUE1QixLQUFLO2dCQWNDLFdBQVc7c0JBRGpCLFNBQVM7dUJBQUMsbUJBQW1CLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUloRCxZQUFZO3NCQURYLE1BQU07Z0JBS0gsS0FBSztzQkFEUixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLy8gwqkgMjAyMiBTb2xhcldpbmRzIFdvcmxkd2lkZSwgTExDLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbi8vICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0b1xuLy8gIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyAgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yXG4vLyAgc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbi8vICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuLy8gIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbi8vICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuLy8gIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cbi8vICBUSEUgU09GVFdBUkUuXG5cbmltcG9ydCB7XG4gICAgQWZ0ZXJWaWV3SW5pdCxcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBDb21wb25lbnQsXG4gICAgRWxlbWVudFJlZixcbiAgICBFdmVudEVtaXR0ZXIsXG4gICAgZm9yd2FyZFJlZixcbiAgICBJbnB1dCxcbiAgICBPbkluaXQsXG4gICAgT3V0cHV0LFxuICAgIFJlbmRlcmVyMixcbiAgICBWaWV3Q2hpbGQsXG4gICAgVmlld0VuY2Fwc3VsYXRpb24sXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcbmltcG9ydCBtb21lbnQgZnJvbSBcIm1vbWVudC9tb21lbnRcIjtcbmltcG9ydCB7IE1vbWVudCB9IGZyb20gXCJtb21lbnQvbW9tZW50XCI7XG5cbmltcG9ydCB7IE51aUZvcm1GaWVsZENvbnRyb2wgfSBmcm9tIFwiLi4vZm9ybS1maWVsZC9wdWJsaWMtYXBpXCI7XG5cbi8vIDxleGFtcGxlLXVybD4uLy4uL2V4YW1wbGVzL2luZGV4Lmh0bWwjL2RhdGUtdGltZS1waWNrZXI8L2V4YW1wbGUtdXJsPjxiciAvPlxuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogXCJudWktZGF0ZS10aW1lLXBpY2tlclwiLFxuICAgIHRlbXBsYXRlVXJsOiBcIi4vZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuaHRtbFwiLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgICAgICAgIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IERhdGVUaW1lUGlja2VyQ29tcG9uZW50KSxcbiAgICAgICAgICAgIG11bHRpOiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgICBwcm92aWRlOiBOdWlGb3JtRmllbGRDb250cm9sLCAvLyB0aGlzIGFsbG93cyBvdXIgZm9ybSBjb250cm9sIHRvIHVzZSBydW4tdGltZSB0eXBlIGNoZWNraW5nXG4gICAgICAgICAgICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBEYXRlVGltZVBpY2tlckNvbXBvbmVudCksXG4gICAgICAgICAgICBtdWx0aTogdHJ1ZSxcbiAgICAgICAgfSxcbiAgICBdLFxuICAgIHN0eWxlVXJsczogW1wiLi9kYXRlLXRpbWUtcGlja2VyLmNvbXBvbmVudC5sZXNzXCJdLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG59KVxuZXhwb3J0IGNsYXNzIERhdGVUaW1lUGlja2VyQ29tcG9uZW50XG4gICAgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yXG57XG4gICAgLyoqIGxhdGVzdCBhdmFpbGFibGUgZGF0ZSAqL1xuICAgIEBJbnB1dCgpIG1heERhdGU6IE1vbWVudDtcbiAgICAvKiogZWFybGllc3QgYXZhaWxhYmxlIGRhdGUgKi9cbiAgICBASW5wdXQoKSBtaW5EYXRlOiBNb21lbnQ7XG4gICAgLyoqIHNldHMgbW9kZSBvZiBzaG93aW5nIGRhdGUtdGltZS1waWNrZXIgKi9cbiAgICBASW5wdXQoKSBkaXNwbGF5TW9kZTogc3RyaW5nO1xuXG4gICAgQElucHV0KCkgaXNEaXNhYmxlZDogYm9vbGVhbjtcblxuICAgIEBJbnB1dCgpIGluaXRFbXB0eTogYm9vbGVhbjtcbiAgICAvKiogSXMgdXNlZCB0byBoYW5kbGUgdGltZXpvbmUgb2YgZGF0ZSB2YWx1ZSwgcGFzc2VkIHRvIERhdGVQaWNrZXJDb21wb25lbnQgKi9cbiAgICBASW5wdXQoKSBoYW5kbGVUaW1lem9uZTogYm9vbGVhbjtcbiAgICAvKiogQWxsb3dzIHBvcHVwIGJveCB0byBiZSBhdHRhY2hlZCB0byBkb2N1bWVudC5ib2R5ICovXG4gICAgQElucHV0KCkgYXBwZW5kVG9Cb2R5OiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogSW5wdXQgdG8gc2V0IGFyaWEgbGFiZWwgdGV4dFxuICAgICAqL1xuICAgIEBJbnB1dCgpIHB1YmxpYyBnZXQgYXJpYUxhYmVsKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9hcmlhTGFiZWw7XG4gICAgfVxuXG4gICAgLy8gY2hhbmdpbmcgdGhlIHZhbHVlIHdpdGggcmVndWxhciBASW5wdXQgZG9lc24ndCB0cmlnZ2VyIGNoYW5nZSBkZXRlY3Rpb25cbiAgICAvLyBzbyB3ZSBuZWVkIHRvIGRvIHRoYXQgbWFudWFsbHkgaW4gdGhlIHNldHRlclxuICAgIHB1YmxpYyBzZXQgYXJpYUxhYmVsKHZhbHVlOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKHZhbHVlICE9PSB0aGlzLl9hcmlhTGFiZWwpIHtcbiAgICAgICAgICAgIHRoaXMuX2FyaWFMYWJlbCA9IHZhbHVlO1xuICAgICAgICAgICAgdGhpcy5jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIEBWaWV3Q2hpbGQoXCJudWlEYXRldGltZVBpY2tlclwiLCB7IHN0YXRpYzogdHJ1ZSB9KVxuICAgIHB1YmxpYyBjb2RlRWxlbWVudDogRWxlbWVudFJlZjtcbiAgICAvKiogQ2FsbGJhY2sgdG8gaW52b2tlIG9uIG1vZGVsIGNoYW5nZSAqL1xuICAgIEBPdXRwdXQoKVxuICAgIG1vZGVsQ2hhbmdlZDogRXZlbnRFbWl0dGVyPE1vbWVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPE1vbWVudD4oKTtcblxuICAgIC8qKiBtb2RlbCBvZiBwaWNrZXIgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBtb2RlbCgpOiBNb21lbnQgfCB1bmRlZmluZWQge1xuICAgICAgICByZXR1cm4gdGhpcy5fbW9kZWw7XG4gICAgfVxuXG4gICAgc2V0IG1vZGVsKHZhbHVlOiBNb21lbnQgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKG1vbWVudCh2YWx1ZSkuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICB0aGlzLl9tb2RlbCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMudXBkYXRlQ2hpbGRyZW5Nb2RlbHMoKTtcbiAgICB9XG5cbiAgICBwdWJsaWMgZGF0ZT86IE1vbWVudDtcbiAgICBwdWJsaWMgdGltZT86IE1vbWVudDtcbiAgICBwcml2YXRlIF9tb2RlbD86IE1vbWVudDtcbiAgICBwdWJsaWMgaXNJbkVycm9yU3RhdGVEYXRlID0gZmFsc2U7XG4gICAgcHVibGljIGlzSW5FcnJvclN0YXRlVGltZSA9IGZhbHNlO1xuXG4gICAgcHJpdmF0ZSBfYXJpYUxhYmVsOiBzdHJpbmcgPSBcIlwiO1xuXG4gICAgb25Ub3VjaGVkID0gKCk6IHZvaWQgPT4ge307XG4gICAgb25DaGFuZ2UgPSAodmFsdWU6IGFueSk6IHZvaWQgPT4ge307XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsIHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gICAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgICAgICBpZiAoIXRoaXMuaW5pdEVtcHR5ICYmICF0aGlzLm1vZGVsKSB7XG4gICAgICAgICAgICB0aGlzLm1vZGVsID0gbW9tZW50KCk7XG4gICAgICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMubW9kZWwpO1xuICAgICAgICAgICAgdGhpcy5jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLmRpc3BsYXlNb2RlID09PSBcImlubGluZVwiKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKFxuICAgICAgICAgICAgICAgIHRoaXMuY29kZUVsZW1lbnQubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgICAgICBcIm51aS1kYXRldGltZS1waWNrZXItLWlubGluZVwiXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhcbiAgICAgICAgICAgICAgICB0aGlzLmNvZGVFbGVtZW50Lm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihcIi5udWktdGltZXBpY2tlclwiKSxcbiAgICAgICAgICAgICAgICBcIm51aS1kcm9wZG93bi0taW5saW5lXCJcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB3cml0ZVZhbHVlKHZhbHVlOiBNb21lbnQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5tb2RlbCA9IHZhbHVlO1xuICAgICAgICB0aGlzLnVwZGF0ZUNoaWxkcmVuTW9kZWxzKCk7XG4gICAgfVxuXG4gICAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgICB9XG5cbiAgICByZWdpc3Rlck9uQ2hhbmdlKGZuOiAoKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgICAgIHRoaXMub25DaGFuZ2UgPSBmbjtcbiAgICB9XG5cbiAgICBzZXREaXNhYmxlZFN0YXRlKGlzRGlzYWJsZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pc0Rpc2FibGVkID0gaXNEaXNhYmxlZDtcbiAgICAgICAgdGhpcy5jZC5tYXJrRm9yQ2hlY2soKTsgLy8gVGhpcyBpcyBuZWVkZWQgdG8gdXBkYXRlIFwiZGlzYWJsZWRcIiBzdGF0ZSBmb3IgY2hpbGQgZGF0ZSBhbmQgdGltZSBwaWNrZXJzXG4gICAgfVxuXG4gICAgb25UaW1lQ2hhbmdlZChldmVudDogTW9tZW50KTogdm9pZCB7XG4gICAgICAgIHRoaXMudXBkYXRlVGltZShldmVudCk7XG4gICAgICAgIHRoaXMubW9kZWxDaGFuZ2VkLmVtaXQobW9tZW50KHRoaXMubW9kZWwpKTtcbiAgICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLm1vZGVsKTtcbiAgICAgICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB9XG5cbiAgICBvbkRhdGVDaGFuZ2VkKGV2ZW50OiBNb21lbnQpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgaXNEYXRlVGhlU2FtZSA9XG4gICAgICAgICAgICBtb21lbnQuaXNNb21lbnQodGhpcy5kYXRlKSAmJiB0aGlzLmRhdGUuaXNTYW1lKGV2ZW50KTtcblxuICAgICAgICBpZiAoaXNEYXRlVGhlU2FtZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy51cGRhdGVEYXRlKGV2ZW50KTtcbiAgICAgICAgdGhpcy5tb2RlbENoYW5nZWQuZW1pdChtb21lbnQodGhpcy5tb2RlbCkpO1xuICAgICAgICB0aGlzLm9uQ2hhbmdlKHRoaXMubW9kZWwpO1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgIH1cblxuICAgIG9uSW5wdXRCbHVycmVkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLm9uVG91Y2hlZCgpO1xuICAgICAgICBpZiAoIXRoaXMubW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuaXNJbkVycm9yU3RhdGVEYXRlID1cbiAgICAgICAgICAgICAgICAhdGhpcy5kYXRlIHx8ICh0aGlzLmRhdGUgJiYgIW1vbWVudCh0aGlzLmRhdGUpLmlzVmFsaWQoKSk7XG4gICAgICAgICAgICB0aGlzLmlzSW5FcnJvclN0YXRlVGltZSA9XG4gICAgICAgICAgICAgICAgIXRoaXMudGltZSB8fCAodGhpcy50aW1lICYmICFtb21lbnQodGhpcy50aW1lKS5pc1ZhbGlkKCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgcHJpdmF0ZSB1cGRhdGVDaGlsZHJlbk1vZGVscygpIHtcbiAgICAgICAgaWYgKHRoaXMubW9kZWwpIHtcbiAgICAgICAgICAgIHRoaXMuZGF0ZSA9IHRoaXMubW9kZWwuY2xvbmUoKTtcbiAgICAgICAgICAgIHRoaXMudGltZSA9IHRoaXMubW9kZWwuY2xvbmUoKTtcbiAgICAgICAgfSBlbHNlIGlmICghdGhpcy5tb2RlbCAmJiB0aGlzLmluaXRFbXB0eSkge1xuICAgICAgICAgICAgLy8gVE9ETzogUmVwbGFjZSB3aXRoIHVuZGVmaW5lZFxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5kYXRlID0gbnVsbDtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIHRoaXMudGltZSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBwcml2YXRlIHVwZGF0ZURhdGUobmV3VmFsdWU6IE1vbWVudCB8IG51bGwpIHtcbiAgICAgICAgaWYgKCFtb21lbnQuaXNNb21lbnQobmV3VmFsdWUpIHx8ICFtb21lbnQobmV3VmFsdWUpLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgLy8gVE9ETzogUmVwbGFjZSB3aXRoIHVuZGVmaW5lZFxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5fbW9kZWwgPSBudWxsO1xuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5kYXRlID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIGNhc2UgJ2RhdGUnIGlzIG5vdCBzZXQsIHRoaXMuX21vZGVsIGlzIHNldCBmcm9tICd0aW1lJyBtb2RlbCBpZiAndGltZScgbW9kZWwgZXhpc3RzXG4gICAgICAgIHRoaXMuX21vZGVsID0gdGhpcy5fbW9kZWwgfHwgKHRoaXMudGltZSAmJiB0aGlzLnRpbWUuY2xvbmUoKSk7XG4gICAgICAgIGlmICh0aGlzLl9tb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5fbW9kZWwuc2V0KHtcbiAgICAgICAgICAgICAgICB5ZWFyOiBuZXdWYWx1ZS55ZWFyKCksXG4gICAgICAgICAgICAgICAgbW9udGg6IG5ld1ZhbHVlLm1vbnRoKCksXG4gICAgICAgICAgICAgICAgZGF0ZTogbmV3VmFsdWUuZGF0ZSgpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmRhdGUgPSBuZXdWYWx1ZS5jbG9uZSgpO1xuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlVGltZShuZXdWYWx1ZTogTW9tZW50KSB7XG4gICAgICAgIGlmICghbW9tZW50LmlzTW9tZW50KG5ld1ZhbHVlKSkge1xuICAgICAgICAgICAgLy8gVE9ETzogUmVwbGFjZSB3aXRoIHVuZGVmaW5lZFxuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy5fbW9kZWwgPSBudWxsO1xuICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgdGhpcy50aW1lID0gbnVsbDtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluIGNhc2UgJ3RpbWUnIGlzIG5vdCBzZXQsIHRoaXMuX21vZGVsIGlzIHNldCBmcm9tICdkYXRlJyBtb2RlbCBpZiAnZGF0ZScgbW9kZWwgZXhpc3RzXG4gICAgICAgIHRoaXMuX21vZGVsID0gdGhpcy5fbW9kZWwgfHwgKHRoaXMuZGF0ZSAmJiB0aGlzLmRhdGUuY2xvbmUoKSk7XG4gICAgICAgIGlmICh0aGlzLl9tb2RlbCkge1xuICAgICAgICAgICAgdGhpcy5fbW9kZWwuc2V0KHtcbiAgICAgICAgICAgICAgICBob3VyczogbmV3VmFsdWUuaG91cnMoKSxcbiAgICAgICAgICAgICAgICBtaW51dGVzOiBuZXdWYWx1ZS5taW51dGVzKCksXG4gICAgICAgICAgICAgICAgc2Vjb25kczogbmV3VmFsdWUuc2Vjb25kcygpLFxuICAgICAgICAgICAgICAgIG1pbGxpc2Vjb25kczogbmV3VmFsdWUubWlsbGlzZWNvbmQoKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy50aW1lID0gbmV3VmFsdWUuY2xvbmUoKTtcbiAgICB9XG59XG4iLCI8ZGl2XG4gICAgI251aURhdGV0aW1lUGlja2VyXG4gICAgY2xhc3M9XCJudWktZGF0ZXRpbWUtcGlja2VyXCJcbiAgICBbYXR0ci5hcmlhLWxhYmVsXT1cImFyaWFMYWJlbFwiXG4+XG4gICAgPGRpdiBjbGFzcz1cIm51aS1kYXRldGltZS1waWNrZXJfX2dyb3VwXCI+XG4gICAgICAgIDxudWktZGF0ZS1waWNrZXJcbiAgICAgICAgICAgIGNsYXNzPVwibnVpLWRhdGVwaWNrZXItLWp1c3RpZmllZFwiXG4gICAgICAgICAgICBbdmFsdWVdPVwiZGF0ZVwiXG4gICAgICAgICAgICAodmFsdWVDaGFuZ2UpPVwib25EYXRlQ2hhbmdlZCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChpbnB1dEJsdXJyZWQpPVwib25JbnB1dEJsdXJyZWQoKVwiXG4gICAgICAgICAgICBbbWF4RGF0ZV09XCJtYXhEYXRlXCJcbiAgICAgICAgICAgIFttaW5EYXRlXT1cIm1pbkRhdGVcIlxuICAgICAgICAgICAgW2lzRGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiXG4gICAgICAgICAgICBbaXNJbkVycm9yU3RhdGVdPVwiaXNJbkVycm9yU3RhdGVEYXRlXCJcbiAgICAgICAgICAgIFtoYW5kbGVUaW1lem9uZV09XCJoYW5kbGVUaW1lem9uZVwiXG4gICAgICAgICAgICBbYXBwZW5kVG9Cb2R5XT1cImFwcGVuZFRvQm9keVwiXG4gICAgICAgICAgICBbYXJpYUxhYmVsXT1cImFyaWFMYWJlbCArICcgZGF0ZSdcIlxuICAgICAgICA+PC9udWktZGF0ZS1waWNrZXI+XG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cIm51aS1kYXRldGltZS1waWNrZXJfX2dyb3VwIG51aS1kYXRldGltZS1waWNrZXJfX2dyb3VwLS1sYXN0XCI+XG4gICAgICAgIDxudWktdGltZS1waWNrZXJcbiAgICAgICAgICAgIGNsYXNzPVwibnVpLWRyb3Bkb3duLS1qdXN0aWZpZWRcIlxuICAgICAgICAgICAgW2luaXRFbXB0eV09XCJpbml0RW1wdHlcIlxuICAgICAgICAgICAgW21vZGVsXT1cInRpbWVcIlxuICAgICAgICAgICAgKHRpbWVDaGFuZ2VkKT1cIm9uVGltZUNoYW5nZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAoaW5wdXRCbHVycmVkKT1cIm9uSW5wdXRCbHVycmVkKClcIlxuICAgICAgICAgICAgW2lzRGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiXG4gICAgICAgICAgICBbaXNJbkVycm9yU3RhdGVdPVwiaXNJbkVycm9yU3RhdGVUaW1lXCJcbiAgICAgICAgICAgIFthcHBlbmRUb0JvZHldPVwiYXBwZW5kVG9Cb2R5XCJcbiAgICAgICAgICAgIFthcmlhTGFiZWxdPVwiYXJpYUxhYmVsICsgJyB0aW1lJ1wiXG4gICAgICAgID48L251aS10aW1lLXBpY2tlcj5cbiAgICA8L2Rpdj5cbjwvZGl2PlxuIl19