UNPKG

angular-bootstrap-datetimepicker

Version:

Native Angular (8+) datetime picker component styled by Twitter Bootstrap 4.

532 lines 55.9 kB
/** * @license * Copyright 2013-present Dale Lotts All Rights Reserved. * http://www.dalelotts.com * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/dalelotts/angular-bootstrap-datetimepicker/blob/master/LICENSE */ import * as tslib_1 from "tslib"; import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, NgZone, OnChanges, OnInit, Output, SimpleChanges } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import * as _moment from 'moment'; import { take } from 'rxjs/operators'; import { DlDateAdapter } from '../core/public-api'; import { DlDateTimePickerChange } from './dl-date-time-picker-change'; import { DlDayModelProvider } from './dl-model-provider-day'; import { DlHourModelProvider } from './dl-model-provider-hour'; import { DlMinuteModelProvider } from './dl-model-provider-minute'; import { DlMonthModelProvider } from './dl-model-provider-month'; import { DlYearModelProvider } from './dl-model-provider-year'; /** * Work around for moment namespace conflict when used with webpack and rollup. * See https://github.com/dherges/ng-packagr/issues/163 * * Depending on whether rollup is used, moment needs to be imported differently. * Since Moment.js doesn't have a default export, we normally need to import using * the `* as`syntax. * * rollup creates a synthetic default module and we thus need to import it using * the `default as` syntax. * * @internal **/ var moment = _moment; /** * Maps key codes to the model provider function name * that should be called to perform the action. * * @internal **/ var keyCodeToModelProviderMethod = { 'ArrowDown': 'goDown', 'ArrowLeft': 'goLeft', 'ArrowRight': 'goRight', 'ArrowUp': 'goUp', 'Down': 'goDown', 'End': 'goEnd', 'Home': 'goHome', 'Left': 'goLeft', 'PageDown': 'pageDown', 'PageUp': 'pageUp', 'Right': 'goRight', 'Up': 'goUp', 33: 'pageUp', 34: 'pageDown', 35: 'goEnd', 36: 'goHome', 37: 'goLeft', 38: 'goUp', 39: 'goRight', 40: 'goDown', }; /** * List of view names for the calendar. * * This list must be in order from * smallest increment of time to largest increment of time. * * @internal **/ var VIEWS = [ 'minute', 'hour', 'day', 'month', 'year' ]; /** * Component that provides all of the user facing functionality of the date/time picker. */ var DlDateTimePickerComponent = /** @class */ (function () { /** * Used to construct a new instance of a date/time picker. * * @param _elementRef * reference to this element. * @param _ngZone * reference to an NgZone instance used to select the active element outside of angular. * @param _dateAdapter * date adapter for the date type in the model. * @param yearModelComponent * provider for the year view model. * @param monthModelComponent * provider for the month view model. * @param dayModelComponent * provider for the day view model. * @param hourModelComponent * provider for the hour view model. * @param minuteModelComponent * provider for the minute view model. */ function DlDateTimePickerComponent(_elementRef, _ngZone, _dateAdapter, // @ts-ignore yearModelComponent, // @ts-ignore monthModelComponent, // @ts-ignore dayModelComponent, // @ts-ignore hourModelComponent, // @ts-ignore minuteModelComponent) { this._elementRef = _elementRef; this._ngZone = _ngZone; this._dateAdapter = _dateAdapter; this.yearModelComponent = yearModelComponent; this.monthModelComponent = monthModelComponent; this.dayModelComponent = dayModelComponent; this.hourModelComponent = hourModelComponent; this.minuteModelComponent = minuteModelComponent; /** * Change listener callback functions registered * via `registerOnChange` * @internal **/ this._changed = []; /** * Maps view name to the next view (the view for the next smallest increment of time). * @internal **/ this._nextView = { 'year': 'month', 'month': 'day', 'day': 'hour', 'hour': 'minute' }; /** * Maps view name to the previous view (the view for the next largest increment of time). * @internal **/ this._previousView = { 'minute': 'hour', 'hour': 'day', 'day': 'month', 'month': 'year' }; /** * Touch listener callback functions registered * via `registerOnChange` * @internal **/ this._touched = []; /** * Emits when a `change` event when date/time is selected or * the value of the date/time picker changes. **/ this.change = new EventEmitter(); /** * Specifies the classes used to display the left icon. * * This component uses OPENICONIC https://useiconic.com/open * by default but any icon library may be used. */ this.leftIconClass = [ 'oi', 'oi-chevron-left' ]; /** * The highest view that the date/time picker can show. * Setting this to a view less than year could make it more * difficult for the end-user to navigate to certain dates. */ this.maxView = 'year'; /** * The view that will be used for date/time selection. * * The default of `minute means that selection will not happen * until the end-user clicks on a cell in the minute view. * * for example, if you want the end-user to select a only day (date), * setting `minView` to `day` will cause selection to happen when the * end-user selects a cell in the day view. * * NOTE: This must be set lower than or equal to `startView' */ this.minView = 'minute'; /** * The number of minutes between each `.dl-abdtp-minute` button. * * Must be greater than `0` and less than `60`. */ this.minuteStep = 5; /** * Specifies the classes used to display the right icon. * * This component uses OPENICONIC https://useiconic.com/open * by default but any icon library may be used. */ this.rightIconClass = [ 'oi', 'oi-chevron-right' ]; /* tslint:disable:member-ordering */ /** * Determine whether or not the `DateButton` is selectable by the end user. */ this.selectFilter = function () { return true; }; /** * The initial view that the date/time picker will show. * The picker will also return to this view after a date/time * is selected. * * NOTE: This must be set lower than or equal to `maxView' */ this.startView = 'day'; /** * Specifies the classes used to display the up icon. * * This component uses OPENICONIC https://useiconic.com/open * by default but any icon library may be used. */ this.upIconClass = [ 'oi', 'oi-chevron-top' ]; this._viewToModelProvider = { year: yearModelComponent, month: monthModelComponent, day: dayModelComponent, hour: hourModelComponent, minute: minuteModelComponent, }; } DlDateTimePickerComponent_1 = DlDateTimePickerComponent; Object.defineProperty(DlDateTimePickerComponent.prototype, "model", { /* tslint:enable:member-ordering */ /** * Set's the model for the current view after applying the selection filter. * * @internal **/ set: function (model) { this._model = this.applySelectFilter(model); }, enumerable: true, configurable: true }); Object.defineProperty(DlDateTimePickerComponent.prototype, "value", { /** * Returns `D` value of the date/time picker or undefined/null if no value is set. **/ get: function () { return this._value; }, /** * Sets value of the date/time picker and emits a change event if the * new value is different from the previous value. **/ set: function (value) { if (this._value !== value) { this._value = value; this.model = this._viewToModelProvider[this._model.viewName].getModel(this.getStartDate(), this.valueOf); this._changed.forEach(function (f) { return f(value); }); this.change.emit(new DlDateTimePickerChange(value)); } }, enumerable: true, configurable: true }); Object.defineProperty(DlDateTimePickerComponent.prototype, "valueOf", { /** * Returns `milliseconds` value of the date/time picker or undefined/null if no value is set. **/ get: function () { return this._dateAdapter.toMilliseconds(this._value); }, enumerable: true, configurable: true }); /** * Applies the `selectionFilter` by adding the `dl-abdtp-disabled` * class to any `DateButton` where `selectFilter` returned false. * * @param model * the new model * * @returns * the supplied model with zero or more `DateButton`'s * having the `dl-abdtp-disabled` class set to `true` if the * selection for that date should be disabled. * * @internal */ DlDateTimePickerComponent.prototype.applySelectFilter = function (model) { var _this = this; if (this.selectFilter) { model.rows = model.rows.map(function (row) { row.cells.map(function (dateButton) { var disabled = !_this.selectFilter(dateButton, model.viewName); dateButton.classes['dl-abdtp-disabled'] = disabled; if (disabled) { dateButton.classes['aria-disabled'] = true; } return dateButton; }); return row; }); } return model; }; /** * Focuses the `.dl-abdtp-active` cell after the microtask queue is empty. * @internal **/ DlDateTimePickerComponent.prototype.focusActiveCell = function () { var _this = this; this._ngZone.runOutsideAngular(function () { _this._ngZone.onStable.asObservable().pipe(take(1)).subscribe(function () { _this._elementRef.nativeElement.querySelector('.dl-abdtp-active').focus(); }); }); }; /** * Determines the start date for the picker. * @internal **/ DlDateTimePickerComponent.prototype.getStartDate = function () { if (hasValue(this._value)) { return this._dateAdapter.toMilliseconds(this._value); } if (hasValue(this.startDate)) { return this.startDate; } return moment().valueOf(); }; /** * Determine the start view for the picker * @returns * the largest time increment view between the `minView` or `minute` view and the `startView` or `day` view. */ DlDateTimePickerComponent.prototype.getStartView = function () { var startIndex = Math.max(VIEWS.indexOf(this.minView || 'minute'), VIEWS.indexOf(this.startView || 'day')); return VIEWS[startIndex]; }; /** * Calls all registered `touch` callback functions. * @internal **/ DlDateTimePickerComponent.prototype.onTouch = function () { this._touched.forEach(function (onTouched) { return onTouched(); }); }; /** * Receives configuration changes detected by Angular and passes the changes on * to the model providers so the provider is aware of any necessary configuration * changes (i.e. minuteStep) * * @param changes * the input changes detected by Angular. */ DlDateTimePickerComponent.prototype.ngOnChanges = function (changes) { Object.values(this._viewToModelProvider).forEach(function (provider) { return provider.onChanges(changes); }); if (this._model) { // only update the model after ngOnInit has set it the first time. this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.activeDate, this.valueOf); } }; /** * Sets the initial model. * * @internal **/ DlDateTimePickerComponent.prototype.ngOnInit = function () { this.model = this._viewToModelProvider[this.getStartView()].getModel(this.getStartDate(), this.valueOf); }; /** * Handles click (and enter & space key down) events on the date elements. * * If the current view is the minimum view then the date value is selected * and the picker returns to the start view. * * Otherwise the picker displays the next view with the next * smallest time increment. * * @internal **/ DlDateTimePickerComponent.prototype._onDateClick = function (dateButton) { if (dateButton.classes['dl-abdtp-disabled']) { return; } var nextView = this._nextView[this._model.viewName]; if ((this.minView || 'minute') === this._model.viewName) { this.value = this._dateAdapter.fromMilliseconds(dateButton.value); nextView = this.startView; } this.model = this._viewToModelProvider[nextView].getModel(dateButton.value, this.valueOf); this.onTouch(); }; /** * Handles click (and enter & space key down) events on the left button. * * Changes the displayed time range of the picker to the previous time range. * For example, in year view, the previous decade is displayed. * * @internal **/ DlDateTimePickerComponent.prototype._onLeftClick = function () { this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.leftButton.value, this.valueOf); this.onTouch(); }; /** * Handles click (and enter & space key down) events on the up button. * * Changes the view of the picker to the next largest time increment. * For example, in day view, the next view displayed will be month view. * * @internal **/ DlDateTimePickerComponent.prototype._onUpClick = function () { this.model = this._viewToModelProvider[this._previousView[this._model.viewName]].getModel(this._model.upButton.value, this.valueOf); }; /** * Handles click (and enter & space key down) events on the right button. * * Changes the displayed time range of the picker to the next time range. * For example, in year view, the next decade is displayed. * * @internal **/ DlDateTimePickerComponent.prototype._onRightClick = function () { this.model = this._viewToModelProvider[this._model.viewName].getModel(this._model.rightButton.value, this.valueOf); this.onTouch(); }; /** * Handles various key down events to move the `active date` around the calendar. * * @internal **/ DlDateTimePickerComponent.prototype._handleKeyDown = function ($event) { var functionName = keyCodeToModelProviderMethod[$event.key]; if (functionName) { var modelProvider = this._viewToModelProvider[this._model.viewName]; this.model = modelProvider[functionName](this._model.activeDate, this.valueOf); this.focusActiveCell(); // Prevent unexpected default actions such as form submission. $event.preventDefault(); } }; /** * Implements ControlValueAccessor.registerOnChange to register change listeners. * @internal **/ DlDateTimePickerComponent.prototype.registerOnChange = function (fn) { this._changed.push(fn); }; /** * Implements ControlValueAccessor.registerOnTouched to register touch listeners. * @internal **/ DlDateTimePickerComponent.prototype.registerOnTouched = function (fn) { this._touched.push(fn); }; /** * Implements ControlValueAccessor.writeValue to store the value from the model. * @internal **/ DlDateTimePickerComponent.prototype.writeValue = function (value) { this.value = value; }; var DlDateTimePickerComponent_1; DlDateTimePickerComponent.ctorParameters = function () { return [ { type: ElementRef }, { type: NgZone }, { type: DlDateAdapter }, { type: DlYearModelProvider }, { type: DlMonthModelProvider }, { type: DlDayModelProvider }, { type: DlHourModelProvider }, { type: DlMinuteModelProvider } ]; }; tslib_1.__decorate([ Output() ], DlDateTimePickerComponent.prototype, "change", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "leftIconClass", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "maxView", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "minView", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "minuteStep", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "rightIconClass", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "selectFilter", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "startDate", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "startView", void 0); tslib_1.__decorate([ Input() ], DlDateTimePickerComponent.prototype, "upIconClass", void 0); DlDateTimePickerComponent = DlDateTimePickerComponent_1 = tslib_1.__decorate([ Component({ changeDetection: ChangeDetectionStrategy.OnPush, preserveWhitespaces: false, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: DlDateTimePickerComponent_1, multi: true } ], selector: 'dl-date-time-picker', template: "<div class=\"text-center dl-abdtp-{{_model.viewName}}-view\" [attr.data-dl-abdtp-view]=\"_model.viewName\">\n <div class=\"row align-items-center no-gutters\">\n <button class=\"col dl-abdtp-left-button align-items-center\"\n type=\"button\"\n [attr.aria-label]=\"_model.leftButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.leftButton.value\"\n [attr.title]=\"_model.leftButton.ariaLabel\"\n (click)=\"_onLeftClick()\"\n ><span class=\"left-icon\" [ngClass]=\"leftIconClass\"></span>\n </button>\n\n <div *ngIf=\"_model.viewName === (this.maxView || 'year'); then maxViewLabel else defaultViewLabel;\"></div>\n\n <button class=\"col dl-abdtp-right-button\"\n type=\"button\"\n [attr.aria-label]=\"_model.rightButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.rightButton.value\"\n [attr.title]=\"_model.rightButton.ariaLabel\"\n (click)=\"_onRightClick()\"\n ><span class=\"right-icon\" [ngClass]=\"rightIconClass\"></span>\n </button>\n </div>\n <div (keydown)=\"_handleKeyDown($event)\">\n <div *ngIf=\"_model.rowLabels?.length\" class=\"row no-gutters\">\n <div *ngFor=\"let label of _model.rowLabels\"\n class=\"col align-items-center no-gutters dl-abdtp-col-label\">{{label}}</div>\n </div>\n <div *ngFor=\"let row of _model.rows\" class=\"row align-items-center no-gutters\">\n <div *ngFor=\"let cell of row.cells\"\n role=\"gridcell\"\n class=\"col dl-abdtp-date-button dl-abdtp-{{_model.viewName}}\"\n [ngClass]=\"cell.classes\"\n [attr.aria-label]=\"cell.ariaLabel\"\n [attr.aria-disabled]=\"cell.classes['dl-abdtp-disabled']\"\n [attr.dl-abdtp-value]=\"cell.value\"\n [attr.tabindex]=\"cell.classes['dl-abdtp-active'] ? 0 : -1\"\n (click)=\"_onDateClick(cell)\"\n (keydown.space)=\"_onDateClick(cell)\"\n (keydown.enter)=\"_onDateClick(cell)\"\n >{{cell.display}}</div>\n </div>\n </div>\n</div>\n\n<ng-template #maxViewLabel>\n <div class=\"col-10 dl-abdtp-view-label\">{{_model.viewLabel}}</div>\n</ng-template>\n<ng-template #defaultViewLabel>\n <button class=\"col-10 dl-abdtp-view-label dl-abdtp-up-button\"\n type=\"button\"\n [attr.aria-label]=\"_model.upButton.ariaLabel\"\n [attr.dl-abdtp-value]=\"_model.upButton.value\"\n [attr.title]=\"_model.upButton.ariaLabel\"\n (click)=\"_onUpClick()\"\n [ngClass]=\"_model.upButton.classes\"\n >{{_model.viewLabel}}&nbsp;<span class=\"up-icon\" [ngClass]=\"upIconClass\"></span>\n </button>\n</ng-template>\n", styles: [":host{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dl-abdtp-col-label,.dl-abdtp-view-label{font-weight:700}.dl-abdtp-date-button,.dl-abdtp-left-button,.dl-abdtp-right-button,.dl-abdtp-view-label{padding:5px;border-radius:999px;cursor:pointer;color:rgba(0,0,0,.87);outline:0}.dl-abdtp-date-button,.dl-abdtp-left-button,.dl-abdtp-right-button,.dl-abdtp-up-button{border-width:0}.dl-abdtp-active:focus,.dl-abdtp-date-button:focus,.dl-abdtp-date-button:hover,.dl-abdtp-left-button:focus,.dl-abdtp-left-button:hover,.dl-abdtp-right-button:focus,.dl-abdtp-right-button:hover,.dl-abdtp-up-button:focus,.dl-abdtp-up-button:hover,.dl-abdtp-view-label:focus{background:rgba(0,0,0,.04)}.dl-abdtp-future,.dl-abdtp-past{color:rgba(0,0,0,.04)}.dl-abdtp-now,.dl-abdtp-now.disabled,.dl-abdtp-now.disabled:hover,.dl-abdtp-now:hover{border-radius:999px;border:1px solid rgba(0,0,0,.25)}.dl-abdtp-selected{color:#fff;background:rgba(0,82,204,.75)}.dl-abdtp-selected:focus,.dl-abdtp-selected:hover{background:#0052cc}.dl-abdtp-disabled{cursor:default;color:rgba(0,0,0,.25)}"] }) ], DlDateTimePickerComponent); return DlDateTimePickerComponent; }()); export { DlDateTimePickerComponent }; /** @internal */ function hasValue(value) { return (typeof value !== 'undefined') && (value !== null); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGwtZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9hbmd1bGFyLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci8iLCJzb3VyY2VzIjpbImRsLWRhdGUtdGltZS1waWNrZXIvZGwtZGF0ZS10aW1lLXBpY2tlci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRzs7QUFFSCxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sYUFBYSxFQUNkLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBdUIsaUJBQWlCLEVBQUMsTUFBTSxnQkFBZ0IsQ0FBQztBQUN2RSxPQUFPLEtBQUssT0FBTyxNQUFNLFFBQVEsQ0FBQztBQUNsQyxPQUFPLEVBQUMsSUFBSSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDcEMsT0FBTyxFQUFDLGFBQWEsRUFBQyxNQUFNLG9CQUFvQixDQUFDO0FBQ2pELE9BQU8sRUFBQyxzQkFBc0IsRUFBQyxNQUFNLDhCQUE4QixDQUFDO0FBSXBFLE9BQU8sRUFBQyxrQkFBa0IsRUFBQyxNQUFNLHlCQUF5QixDQUFDO0FBQzNELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBQzdELE9BQU8sRUFBQyxxQkFBcUIsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ2pFLE9BQU8sRUFBQyxvQkFBb0IsRUFBQyxNQUFNLDJCQUEyQixDQUFDO0FBQy9ELE9BQU8sRUFBQyxtQkFBbUIsRUFBQyxNQUFNLDBCQUEwQixDQUFDO0FBRTdEOzs7Ozs7Ozs7Ozs7SUFZSTtBQUNKLElBQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQztBQUd2Qjs7Ozs7SUFLSTtBQUVKLElBQU0sNEJBQTRCLEdBQUc7SUFDbkMsV0FBVyxFQUFFLFFBQVE7SUFD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QkFDdEMsS0FBSyxFQUFFLElBQUk7aUJBQ1o7YUFDRjtZQUNELFFBQVEsRUFBRSxxQkFBcUI7WUFFL0IsNHBGQUFtRDs7U0FDcEQsQ0FBQztPQUNXLHlCQUF5QixDQXFickM7SUFBRCxnQ0FBQztDQUFBLEFBcmJELElBcWJDO1NBcmJZLHlCQUF5QjtBQXVidEMsZ0JBQWdCO0FBQ2hCLFNBQVMsUUFBUSxDQUFDLEtBQVU7SUFDMUIsT0FBTyxDQUFDLE9BQU8sS0FBSyxLQUFLLFdBQVcsQ0FBQyxJQUFJLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDO0FBQzVELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBsaWNlbnNlXG4gKiBDb3B5cmlnaHQgMjAxMy1wcmVzZW50IERhbGUgTG90dHMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqIGh0dHA6Ly93d3cuZGFsZWxvdHRzLmNvbVxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9kYWxlbG90dHMvYW5ndWxhci1ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXIvYmxvYi9tYXN0ZXIvTElDRU5TRVxuICovXG5cbmltcG9ydCB7XG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE5nWm9uZSxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlc1xufSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHtDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1J9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCAqIGFzIF9tb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7dGFrZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtEbERhdGVBZGFwdGVyfSBmcm9tICcuLi9jb3JlL3B1YmxpYy1hcGknO1xuaW1wb3J0IHtEbERhdGVUaW1lUGlja2VyQ2hhbmdlfSBmcm9tICcuL2RsLWRhdGUtdGltZS1waWNrZXItY2hhbmdlJztcbmltcG9ydCB7RGF0ZUJ1dHRvbn0gZnJvbSAnLi9kbC1kYXRlLXRpbWUtcGlja2VyLWRhdGUtYnV0dG9uJztcbmltcG9ydCB7RGxEYXRlVGltZVBpY2tlck1vZGVsfSBmcm9tICcuL2RsLWRhdGUtdGltZS1waWNrZXItbW9kZWwnO1xuaW1wb3J0IHtEbE1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXInO1xuaW1wb3J0IHtEbERheU1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXItZGF5JztcbmltcG9ydCB7RGxIb3VyTW9kZWxQcm92aWRlcn0gZnJvbSAnLi9kbC1tb2RlbC1wcm92aWRlci1ob3VyJztcbmltcG9ydCB7RGxNaW51dGVNb2RlbFByb3ZpZGVyfSBmcm9tICcuL2RsLW1vZGVsLXByb3ZpZGVyLW1pbnV0ZSc7XG5pbXBvcnQge0RsTW9udGhNb2RlbFByb3ZpZGVyfSBmcm9tICcuL2RsLW1vZGVsLXByb3ZpZGVyLW1vbnRoJztcbmltcG9ydCB7RGxZZWFyTW9kZWxQcm92aWRlcn0gZnJvbSAnLi9kbC1tb2RlbC1wcm92aWRlci15ZWFyJztcblxuLyoqXG4gKiBXb3JrIGFyb3VuZCBmb3IgbW9tZW50IG5hbWVzcGFjZSBjb25mbGljdCB3aGVuIHVzZWQgd2l0aCB3ZWJwYWNrIGFuZCByb2xsdXAuXG4gKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2RoZXJnZXMvbmctcGFja2Fnci9pc3N1ZXMvMTYzXG4gKlxuICogRGVwZW5kaW5nIG9uIHdoZXRoZXIgcm9sbHVwIGlzIHVzZWQsIG1vbWVudCBuZWVkcyB0byBiZSBpbXBvcnRlZCBkaWZmZXJlbnRseS5cbiAqIFNpbmNlIE1vbWVudC5qcyBkb2Vzbid0IGhhdmUgYSBkZWZhdWx0IGV4cG9ydCwgd2Ugbm9ybWFsbHkgbmVlZCB0byBpbXBvcnQgdXNpbmdcbiAqIHRoZSBgKiBhc2BzeW50YXguXG4gKlxuICogcm9sbHVwIGNyZWF0ZXMgYSBzeW50aGV0aWMgZGVmYXVsdCBtb2R1bGUgYW5kIHdlIHRodXMgbmVlZCB0byBpbXBvcnQgaXQgdXNpbmdcbiAqIHRoZSBgZGVmYXVsdCBhc2Agc3ludGF4LlxuICpcbiAqIEBpbnRlcm5hbFxuICoqL1xuY29uc3QgbW9tZW50ID0gX21vbWVudDtcblxuXG4vKipcbiAqIE1hcHMga2V5IGNvZGVzIHRvIHRoZSBtb2RlbCBwcm92aWRlciBmdW5jdGlvbiBuYW1lXG4gKiB0aGF0IHNob3VsZCBiZSBjYWxsZWQgdG8gcGVyZm9ybSB0aGUgYWN0aW9uLlxuICpcbiAqIEBpbnRlcm5hbFxuICoqL1xuXG5jb25zdCBrZXlDb2RlVG9Nb2RlbFByb3ZpZGVyTWV0aG9kID0ge1xuICAnQXJyb3dEb3duJzogJ2dvRG93bicsXG4gICdBcnJvd0xlZnQnOiAnZ29MZWZ0JyxcbiAgJ0Fycm93UmlnaHQnOiAnZ29SaWdodCcsXG4gICdBcnJvd1VwJzogJ2dvVXAnLFxuICAnRG93bic6ICdnb0Rvd24nLFxuICAnRW5kJzogJ2dvRW5kJyxcbiAgJ0hvbWUnOiAnZ29Ib21lJyxcbiAgJ0xlZnQnOiAnZ29MZWZ0JyxcbiAgJ1BhZ2VEb3duJzogJ3BhZ2VEb3duJyxcbiAgJ1BhZ2VVcCc6ICdwYWdlVXAnLFxuICAnUmlnaHQnOiAnZ29SaWdodCcsXG4gICdVcCc6ICdnb1VwJyxcbiAgMzM6ICdwYWdlVXAnLFxuICAzNDogJ3BhZ2VEb3duJyxcbiAgMzU6ICdnb0VuZCcsXG4gIDM2OiAnZ29Ib21lJyxcbiAgMzc6ICdnb0xlZnQnLFxuICAzODogJ2dvVXAnLFxuICAzOTogJ2dvUmlnaHQnLFxuICA0MDogJ2dvRG93bicsXG59O1xuXG5cbi8qKlxuICogTGlzdCBvZiB2aWV3IG5hbWVzIGZvciB0aGUgY2FsZW5kYXIuXG4gKlxuICogVGhpcyBsaXN0IG11c3QgYmUgaW4gb3JkZXIgZnJvbVxuICogc21hbGxlc3QgaW5jcmVtZW50IG9mIHRpbWUgdG8gbGFyZ2VzdCBpbmNyZW1lbnQgb2YgdGltZS5cbiAqXG4gKiBAaW50ZXJuYWxcbiAqKi9cbmNvbnN0IFZJRVdTID0gW1xuICAnbWludXRlJyxcbiAgJ2hvdXInLFxuICAnZGF5JyxcbiAgJ21vbnRoJyxcbiAgJ3llYXInXG5dO1xuXG4vKipcbiAqIENvbXBvbmVudCB0aGF0IHByb3ZpZGVzIGFsbCBvZiB0aGUgdXNlciBmYWNpbmcgZnVuY3Rpb25hbGl0eSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlci5cbiAqL1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHByZXNlcnZlV2hpdGVzcGFjZXM6IGZhbHNlLFxuICBwcm92aWRlcnM6IFtcbiAgICB7XG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcbiAgICAgIHVzZUV4aXN0aW5nOiBEbERhdGVUaW1lUGlja2VyQ29tcG9uZW50LFxuICAgICAgbXVsdGk6IHRydWVcbiAgICB9XG4gIF0sXG4gIHNlbGVjdG9yOiAnZGwtZGF0ZS10aW1lLXBpY2tlcicsXG4gIHN0eWxlVXJsczogWycuL2RsLWRhdGUtdGltZS1waWNrZXIuY29tcG9uZW50LnNjc3MnXSxcbiAgdGVtcGxhdGVVcmw6ICcuL2RsLWRhdGUtdGltZS1waWNrZXIuY29tcG9uZW50Lmh0bWwnLFxufSlcbmV4cG9ydCBjbGFzcyBEbERhdGVUaW1lUGlja2VyQ29tcG9uZW50PEQ+IGltcGxlbWVudHMgT25DaGFuZ2VzLCBPbkluaXQsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIHtcblxuICAvKipcbiAgICogQ2hhbmdlIGxpc3RlbmVyIGNhbGxiYWNrIGZ1bmN0aW9ucyByZWdpc3RlcmVkXG4gICAqIHZpYSBgcmVnaXN0ZXJPbkNoYW5nZWBcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfY2hhbmdlZDogKCh2YWx1ZTogRCkgPT4gdm9pZClbXSA9IFtdO1xuICAvKipcbiAgICogTW9kZWwgZm9yIHRoZSBjdXJyZW50IHZpZXcuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKiovXG4gIF9tb2RlbDogRGxEYXRlVGltZVBpY2tlck1vZGVsO1xuICAvKipcbiAgICogTWFwcyB2aWV3IG5hbWUgdG8gdGhlIG5leHQgdmlldyAodGhlIHZpZXcgZm9yIHRoZSBuZXh0IHNtYWxsZXN0IGluY3JlbWVudCBvZiB0aW1lKS5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfbmV4dFZpZXcgPSB7XG4gICAgJ3llYXInOiAnbW9udGgnLFxuICAgICdtb250aCc6ICdkYXknLFxuICAgICdkYXknOiAnaG91cicsXG4gICAgJ2hvdXInOiAnbWludXRlJ1xuICB9O1xuICAvKipcbiAgICogTWFwcyB2aWV3IG5hbWUgdG8gdGhlIHByZXZpb3VzIHZpZXcgKHRoZSB2aWV3IGZvciB0aGUgbmV4dCBsYXJnZXN0IGluY3JlbWVudCBvZiB0aW1lKS5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfcHJldmlvdXNWaWV3ID0ge1xuICAgICdtaW51dGUnOiAnaG91cicsXG4gICAgJ2hvdXInOiAnZGF5JyxcbiAgICAnZGF5JzogJ21vbnRoJyxcbiAgICAnbW9udGgnOiAneWVhcidcbiAgfTtcbiAgLyoqXG4gICAqIFRvdWNoIGxpc3RlbmVyIGNhbGxiYWNrIGZ1bmN0aW9ucyByZWdpc3RlcmVkXG4gICAqIHZpYSBgcmVnaXN0ZXJPbkNoYW5nZWBcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBfdG91Y2hlZDogKCgpID0+IHZvaWQpW10gPSBbXTtcbiAgLyoqXG4gICAqIFN0b3JlcyB0aGUgc2VsZWN0ZWQgdmFsdWUgZm9yIHRoaXMgcGlja2VyLlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIF92YWx1ZTogRDtcbiAgLyoqXG4gICAqIE1hcHMgdmlldyBuYW1lIHRvIHRoZSBtb2RlbCBwcm92aWRlciBmb3IgdGhhdCB2aWV3LlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIHJlYWRvbmx5IF92aWV3VG9Nb2RlbFByb3ZpZGVyOiB7XG4gICAgeWVhcjogRGxNb2RlbFByb3ZpZGVyO1xuICAgIG1vbnRoOiBEbE1vZGVsUHJvdmlkZXI7XG4gICAgZGF5OiBEbE1vZGVsUHJvdmlkZXI7XG4gICAgaG91cjogRGxNb2RlbFByb3ZpZGVyO1xuICAgIG1pbnV0ZTogRGxNb2RlbFByb3ZpZGVyO1xuICB9O1xuICAvKipcbiAgICogRW1pdHMgd2hlbiBhIGBjaGFuZ2VgIGV2ZW50IHdoZW4gZGF0ZS90aW1lIGlzIHNlbGVjdGVkIG9yXG4gICAqIHRoZSB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlciBjaGFuZ2VzLlxuICAgKiovXG4gIEBPdXRwdXQoKVxuICByZWFkb25seSBjaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPERsRGF0ZVRpbWVQaWNrZXJDaGFuZ2U8RD4+KCk7XG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgdGhlIGNsYXNzZXMgdXNlZCB0byBkaXNwbGF5IHRoZSBsZWZ0IGljb24uXG4gICAqXG4gICAqIFRoaXMgY29tcG9uZW50IHVzZXMgT1BFTklDT05JQyBodHRwczovL3VzZWljb25pYy5jb20vb3BlblxuICAgKiBieSBkZWZhdWx0IGJ1dCBhbnkgaWNvbiBsaWJyYXJ5IG1heSBiZSB1c2VkLlxuICAgKi9cbiAgQElucHV0KClcbiAgbGVmdEljb25DbGFzczogc3RyaW5nIHwgc3RyaW5nW10gfCBTZXQ8c3RyaW5nPiB8IHt9ID0gW1xuICAgICdvaScsXG4gICAgJ29pLWNoZXZyb24tbGVmdCdcbiAgXTtcbiAgLyoqXG4gICAqIFRoZSBoaWdoZXN0IHZpZXcgdGhhdCB0aGUgZGF0ZS90aW1lIHBpY2tlciBjYW4gc2hvdy5cbiAgICogU2V0dGluZyB0aGlzIHRvIGEgdmlldyBsZXNzIHRoYW4geWVhciBjb3VsZCBtYWtlIGl0IG1vcmVcbiAgICogZGlmZmljdWx0IGZvciB0aGUgZW5kLXVzZXIgdG8gbmF2aWdhdGUgdG8gY2VydGFpbiBkYXRlcy5cbiAgICovXG4gIEBJbnB1dCgpXG4gIG1heFZpZXc6ICd5ZWFyJyB8ICdtb250aCcgfCAnZGF5JyB8ICdob3VyJyB8ICdtaW51dGUnID0gJ3llYXInO1xuICAvKipcbiAgICogVGhlIHZpZXcgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIGRhdGUvdGltZSBzZWxlY3Rpb24uXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IG9mIGBtaW51dGUgIG1lYW5zIHRoYXQgc2VsZWN0aW9uIHdpbGwgbm90IGhhcHBlblxuICAgKiB1bnRpbCB0aGUgZW5kLXVzZXIgY2xpY2tzIG9uIGEgY2VsbCBpbiB0aGUgbWludXRlIHZpZXcuXG4gICAqXG4gICAqIGZvciBleGFtcGxlLCBpZiB5b3Ugd2FudCB0aGUgZW5kLXVzZXIgdG8gc2VsZWN0IGEgb25seSBkYXkgKGRhdGUpLFxuICAgKiBzZXR0aW5nIGBtaW5WaWV3YCB0byBgZGF5YCB3aWxsIGNhdXNlIHNlbGVjdGlvbiB0byBoYXBwZW4gd2hlbiB0aGVcbiAgICogZW5kLXVzZXIgc2VsZWN0cyBhIGNlbGwgaW4gdGhlIGRheSB2aWV3LlxuICAgKlxuICAgKiBOT1RFOiBUaGlzIG11c3QgYmUgc2V0IGxvd2VyIHRoYW4gb3IgZXF1YWwgdG8gYHN0YXJ0VmlldydcbiAgICovXG4gIEBJbnB1dCgpXG4gIG1pblZpZXc6ICd5ZWFyJyB8ICdtb250aCcgfCAnZGF5JyB8ICdob3VyJyB8ICdtaW51dGUnID0gJ21pbnV0ZSc7XG4gIC8qKlxuICAgKiBUaGUgbnVtYmVyIG9mIG1pbnV0ZXMgYmV0d2VlbiBlYWNoIGAuZGwtYWJkdHAtbWludXRlYCBidXR0b24uXG4gICAqXG4gICAqIE11c3QgYmUgZ3JlYXRlciB0aGFuIGAwYCBhbmQgbGVzcyB0aGFuIGA2MGAuXG4gICAqL1xuICBASW5wdXQoKVxuICBtaW51dGVTdGVwID0gNTtcbiAgLyoqXG4gICAqIFNwZWNpZmllcyB0aGUgY2xhc3NlcyB1c2VkIHRvIGRpc3BsYXkgdGhlIHJpZ2h0IGljb24uXG4gICAqXG4gICAqIFRoaXMgY29tcG9uZW50IHVzZXMgT1BFTklDT05JQyBodHRwczovL3VzZWljb25pYy5jb20vb3BlblxuICAgKiBieSBkZWZhdWx0IGJ1dCBhbnkgaWNvbiBsaWJyYXJ5IG1heSBiZSB1c2VkLlxuICAgKi9cbiAgQElucHV0KClcbiAgcmlnaHRJY29uQ2xhc3MgPSBbXG4gICAgJ29pJyxcbiAgICAnb2ktY2hldnJvbi1yaWdodCdcbiAgXTtcblxuICAvKiB0c2xpbnQ6ZGlzYWJsZTptZW1iZXItb3JkZXJpbmcgKi9cbiAgLyoqXG4gICAqICBEZXRlcm1pbmUgd2hldGhlciBvciBub3QgdGhlIGBEYXRlQnV0dG9uYCBpcyBzZWxlY3RhYmxlIGJ5IHRoZSBlbmQgdXNlci5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHNlbGVjdEZpbHRlcjogKGRhdGVCdXR0b246IERhdGVCdXR0b24sIHZpZXdOYW1lOiBzdHJpbmcpID0+IGJvb2xlYW4gPSAoKSA9PiB0cnVlXG5cbiAgLyoqXG4gICAqICBTdGFydCBhdCB0aGUgdmlldyBjb250YWluaW5nIHN0YXJ0RGF0ZSB3aGVuIG5vIHZhbHVlIGlzIHNlbGVjdGVkLlxuICAgKi9cbiAgQElucHV0KClcbiAgc3RhcnREYXRlOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFRoZSBpbml0aWFsIHZpZXcgdGhhdCB0aGUgZGF0ZS90aW1lIHBpY2tlciB3aWxsIHNob3cuXG4gICAqIFRoZSBwaWNrZXIgd2lsbCBhbHNvIHJldHVybiB0byB0aGlzIHZpZXcgYWZ0ZXIgYSBkYXRlL3RpbWVcbiAgICogaXMgc2VsZWN0ZWQuXG4gICAqXG4gICAqIE5PVEU6IFRoaXMgbXVzdCBiZSBzZXQgbG93ZXIgdGhhbiBvciBlcXVhbCB0byBgbWF4VmlldydcbiAgICovXG4gIEBJbnB1dCgpXG4gIHN0YXJ0VmlldzogJ3llYXInIHwgJ21vbnRoJyB8ICdkYXknIHwgJ2hvdXInIHwgJ21pbnV0ZScgPSAnZGF5JztcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHRoZSBjbGFzc2VzIHVzZWQgdG8gZGlzcGxheSB0aGUgdXAgaWNvbi5cbiAgICpcbiAgICogVGhpcyBjb21wb25lbnQgdXNlcyBPUEVOSUNPTklDIGh0dHBzOi8vdXNlaWNvbmljLmNvbS9vcGVuXG4gICAqIGJ5IGRlZmF1bHQgYnV0IGFueSBpY29uIGxpYnJhcnkgbWF5IGJlIHVzZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICB1cEljb25DbGFzcyA9IFtcbiAgICAnb2knLFxuICAgICdvaS1jaGV2cm9uLXRvcCdcbiAgXTtcblxuICAvKipcbiAgICogVXNlZCB0byBjb25zdHJ1Y3QgYSBuZXcgaW5zdGFuY2Ugb2YgYSBkYXRlL3RpbWUgcGlja2VyLlxuICAgKlxuICAgKiBAcGFyYW0gX2VsZW1lbnRSZWZcbiAgICogIHJlZmVyZW5jZSB0byB0aGlzIGVsZW1lbnQuXG4gICAqIEBwYXJhbSBfbmdab25lXG4gICAqICByZWZlcmVuY2UgdG8gYW4gTmdab25lIGluc3RhbmNlIHVzZWQgdG8gc2VsZWN0IHRoZSBhY3RpdmUgZWxlbWVudCBvdXRzaWRlIG9mIGFuZ3VsYXIuXG4gICAqIEBwYXJhbSBfZGF0ZUFkYXB0ZXJcbiAgICogIGRhdGUgYWRhcHRlciBmb3IgdGhlIGRhdGUgdHlwZSBpbiB0aGUgbW9kZWwuXG4gICAqIEBwYXJhbSB5ZWFyTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgeWVhciB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gbW9udGhNb2RlbENvbXBvbmVudFxuICAgKiAgcHJvdmlkZXIgZm9yIHRoZSBtb250aCB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gZGF5TW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgZGF5IHZpZXcgbW9kZWwuXG4gICAqIEBwYXJhbSBob3VyTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgaG91ciB2aWV3IG1vZGVsLlxuICAgKiBAcGFyYW0gbWludXRlTW9kZWxDb21wb25lbnRcbiAgICogIHByb3ZpZGVyIGZvciB0aGUgbWludXRlIHZpZXcgbW9kZWwuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9lbGVtZW50UmVmOiBFbGVtZW50UmVmLFxuICAgICAgICAgICAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfZGF0ZUFkYXB0ZXI6IERsRGF0ZUFkYXB0ZXI8RD4sXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSB5ZWFyTW9kZWxDb21wb25lbnQ6IERsWWVhck1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBtb250aE1vZGVsQ29tcG9uZW50OiBEbE1vbnRoTW9kZWxQcm92aWRlcixcbiAgICAgICAgICAgICAgLy8gQHRzLWlnbm9yZVxuICAgICAgICAgICAgICBwcml2YXRlIGRheU1vZGVsQ29tcG9uZW50OiBEbERheU1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBob3VyTW9kZWxDb21wb25lbnQ6IERsSG91ck1vZGVsUHJvdmlkZXIsXG4gICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgcHJpdmF0ZSBtaW51dGVNb2RlbENvbXBvbmVudDogRGxNaW51dGVNb2RlbFByb3ZpZGVyKSB7XG5cbiAgICB0aGlzLl92aWV3VG9Nb2RlbFByb3ZpZGVyID0ge1xuICAgICAgeWVhcjogeWVhck1vZGVsQ29tcG9uZW50LFxuICAgICAgbW9udGg6IG1vbnRoTW9kZWxDb21wb25lbnQsXG4gICAgICBkYXk6IGRheU1vZGVsQ29tcG9uZW50LFxuICAgICAgaG91cjogaG91ck1vZGVsQ29tcG9uZW50LFxuICAgICAgbWludXRlOiBtaW51dGVNb2RlbENvbXBvbmVudCxcbiAgICB9O1xuICB9XG5cbiAgLyogdHNsaW50OmVuYWJsZTptZW1iZXItb3JkZXJpbmcgKi9cbiAgLyoqXG4gICAqIFNldCdzIHRoZSBtb2RlbCBmb3IgdGhlIGN1cnJlbnQgdmlldyBhZnRlciBhcHBseWluZyB0aGUgc2VsZWN0aW9uIGZpbHRlci5cbiAgICpcbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBzZXQgbW9kZWwobW9kZWw6IERsRGF0ZVRpbWVQaWNrZXJNb2RlbCkge1xuICAgIHRoaXMuX21vZGVsID0gdGhpcy5hcHBseVNlbGVjdEZpbHRlcihtb2RlbCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBgRGAgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIgb3IgdW5kZWZpbmVkL251bGwgaWYgbm8gdmFsdWUgaXMgc2V0LlxuICAgKiovXG4gIGdldCB2YWx1ZSgpOiBEIHtcbiAgICByZXR1cm4gdGhpcy5fdmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogU2V0cyB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlciBhbmQgZW1pdHMgYSBjaGFuZ2UgZXZlbnQgaWYgdGhlXG4gICAqIG5ldyB2YWx1ZSBpcyBkaWZmZXJlbnQgZnJvbSB0aGUgcHJldmlvdXMgdmFsdWUuXG4gICAqKi9cbiAgc2V0IHZhbHVlKHZhbHVlOiBEKSB7XG4gICAgaWYgKHRoaXMuX3ZhbHVlICE9PSB2YWx1ZSkge1xuICAgICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTtcbiAgICAgIHRoaXMubW9kZWwgPSB0aGlzLl92aWV3VG9Nb2RlbFByb3ZpZGVyW3RoaXMuX21vZGVsLnZpZXdOYW1lXS5nZXRNb2RlbCh0aGlzLmdldFN0YXJ0RGF0ZSgpLCB0aGlzLnZhbHVlT2YpO1xuICAgICAgdGhpcy5fY2hhbmdlZC5mb3JFYWNoKGYgPT4gZih2YWx1ZSkpO1xuICAgICAgdGhpcy5jaGFuZ2UuZW1pdChuZXcgRGxEYXRlVGltZVBpY2tlckNoYW5nZTxEPih2YWx1ZSkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGBtaWxsaXNlY29uZHNgIHZhbHVlIG9mIHRoZSBkYXRlL3RpbWUgcGlja2VyIG9yIHVuZGVmaW5lZC9udWxsIGlmIG5vIHZhbHVlIGlzIHNldC5cbiAgICoqL1xuICBnZXQgdmFsdWVPZigpOiBudW1iZXIgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fZGF0ZUFkYXB0ZXIudG9NaWxsaXNlY29uZHModGhpcy5fdmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgdGhlIGBzZWxlY3Rpb25GaWx0ZXJgIGJ5IGFkZGluZyB0aGUgYGRsLWFiZHRwLWRpc2FibGVkYFxuICAgKiBjbGFzcyB0byBhbnkgYERhdGVCdXR0b25gIHdoZXJlIGBzZWxlY3RGaWx0ZXJgIHJldHVybmVkIGZhbHNlLlxuICAgKlxuICAgKiBAcGFyYW0gbW9kZWxcbiAgICogIHRoZSBuZXcgbW9kZWxcbiAgICpcbiAgICogQHJldHVybnNcbiAgICogIHRoZSBzdXBwbGllZCBtb2RlbCB3aXRoIHplcm8gb3IgbW9yZSBgRGF0ZUJ1dHRvbmAnc1xuICAgKiAgaGF2aW5nIHRoZSBgZGwtYWJkdHAtZGlzYWJsZWRgIGNsYXNzIHNldCB0byBgdHJ1ZWAgaWYgdGhlXG4gICAqICBzZWxlY3Rpb24gZm9yIHRoYXQgZGF0ZSBzaG91bGQgYmUgZGlzYWJsZWQuXG4gICAqXG4gICAqIEBpbnRlcm5hbFxuICAgKi9cbiAgcHJpdmF0ZSBhcHBseVNlbGVjdEZpbHRlcihtb2RlbDogRGxEYXRlVGltZVBpY2tlck1vZGVsKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICBpZiAodGhpcy5zZWxlY3RGaWx0ZXIpIHtcbiAgICAgIG1vZGVsLnJvd3MgPSBtb2RlbC5yb3dzLm1hcCgocm93KSA9PiB7XG4gICAgICAgIHJvdy5jZWxscy5tYXAoKGRhdGVCdXR0b246IERhdGVCdXR0b24pID0+IHtcbiAgICAgICAgICBjb25zdCBkaXNhYmxlZCA9ICF0aGlzLnNlbGVjdEZpbHRlcihkYXRlQnV0dG9uLCBtb2RlbC52aWV3TmFtZSk7XG4gICAgICAgICAgZGF0ZUJ1dHRvbi5jbGFzc2VzWydkbC1hYmR0cC1kaXNhYmxlZCddID0gZGlzYWJsZWQ7XG4gICAgICAgICAgaWYgKGRpc2FibGVkKSB7XG4gICAgICAgICAgICBkYXRlQnV0dG9uLmNsYXNzZXNbJ2FyaWEtZGlzYWJsZWQnXSA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBkYXRlQnV0dG9uO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHJvdztcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHJldHVybiBtb2RlbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBGb2N1c2VzIHRoZSBgLmRsLWFiZHRwLWFjdGl2ZWAgY2VsbCBhZnRlciB0aGUgbWljcm90YXNrIHF1ZXVlIGlzIGVtcHR5LlxuICAgKiBAaW50ZXJuYWxcbiAgICoqL1xuICBwcml2YXRlIGZvY3VzQWN0aXZlQ2VsbCgpIHtcbiAgICB0aGlzLl9uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgdGhpcy5fbmdab25lLm9uU3RhYmxlLmFzT2JzZXJ2YWJsZSgpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5kbC1hYmR0cC1hY3RpdmUnKS5mb2N1cygpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyB0aGUgc3RhcnQgZGF0ZSBmb3IgdGhlIHBpY2tlci5cbiAgICogQGludGVybmFsXG4gICAqKi9cbiAgcHJpdmF0ZSBnZXRTdGFydERhdGUoKSB7XG4gICAgaWYgKGhhc1ZhbHVlKHRoaXMuX3ZhbHVlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuX2RhdGVBZGFwdGVyLnRvTWlsbGlzZWNvbmRzKHRoaXMuX3ZhbHVlKTtcbiAgICB9XG4gICAgaWYgKGhhc1ZhbHVlKHRoaXMuc3RhcnREYXRlKSkge1xuICAgICAgcmV0dXJuIHRoaXMuc3RhcnREYXRlO1xuICAgIH1cbiAgICByZXR1cm4gbW9tZW50KCkudmFsdWVPZigpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVybWluZSB0aGUgc3RhcnQgdmlldyBmb3IgdGhlIHBpY2tlclxuICAgKiBAcmV0dXJuc1xuICAgKiAgdGhlIGxhcmdlc3QgdGltZSBpbmNyZW1lbnQgdmlldyBiZXR3ZWVuIHRoZSBgbWluVmlld2Agb3IgYG1pbnV0ZWAgdmlldyBhbmQgdGhlIGBzdGFydFZpZXdgIG9yIGBkYXlgIHZpZXcuXG4gICAqL1xuICBwcml2YXRlIGdldFN0YXJ0VmlldygpOiBzdHJpbmcge1xuICAgIGNvbnN0IHN0YXJ0SW5kZXggPSBNYXRoLm1heChWSUVXUy5pbmRleE9mKHRoaXMubWluVmlldyB8fCAnbWludXRlJyksIFZJRVdTLmluZGV4T2YodGhpcy5zdGFydFZpZXcgfHwgJ2RheScpKTtcbiAgICByZXR1cm4gVklFV1Nbc3RhcnRJbmRleF07XG4gIH1cblxuICAvKipcbiAgICogQ2FsbHMgYWxsIHJlZ2lzdGVyZWQgYHRvdWNoYCBjYWxsYmFjayBmdW5