ngx-gem-spaas
Version:
This library contains services, components, images and styles to provide a unified look and way-of-working throughout GEM SPaaS.
107 lines • 28.3 kB
JavaScript
import { Component, Input } from '@angular/core';
import { DateTime } from 'luxon';
import { FormControl } from "@angular/forms";
import { BaseComponent } from "ngx-gem-spaas";
import { takeUntil } from "rxjs/operators";
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/material/datepicker";
import * as i3 from "@angular/material/input";
import * as i4 from "@angular/material/form-field";
import * as i5 from "@angular/material/select";
import * as i6 from "@angular/material/core";
import * as i7 from "@angular/common";
import * as i8 from "../_pipes/date.pipe";
/** A stand-alone date picker (not hooked up to the date service) */
export class DatePickerComponent extends BaseComponent {
constructor() {
super();
/** The label to be displayed in the form field (optional) */
this.label = '';
/** Whether to also show the time-fields. Default is false. */
this.withTime = false;
/** Your formcontrol of type DateTime. Will be updated directly by the date picker */
this.fcDate = new FormControl(DateTime.now());
/** Whether to allow manual keyboard input */
this.allowManualInput = false;
/** Minimum date in luxon DateTime */
this.minDate = null;
/** Maximum date in luxon DateTime */
this.maxDate = null;
/** A custom function to limit which dates can be chosen.
* Takes DateTime as input and should return a boolean. */
this.dateConstraint = () => {
return true;
};
this.dateStart = this.fcDate.value.toISO();
this.hour = 0;
this.allHours = [];
this.minute = 0;
this.allMinutes = [];
}
ngOnInit() {
this.onDateChange();
this.fcDate.valueChanges
.pipe(takeUntil(this.onDestroy$))
.subscribe(() => this.onDateChange());
}
// ********************************************************************************************************
// LOAD DATA
// ********************************************************************************************************
// ********************************************************************************************************
// UI
// ********************************************************************************************************
onHourOrMinuteChange() {
if (this.fcDate.valid) {
let dt = this.fcDate.value;
this.fcDate.patchValue(dt.startOf('day').plus({ minute: this.hour * 60 + this.minute }));
}
}
onDateChange() {
this.allMinutes = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59];
if (this.fcDate.valid) {
this.hour = this.fcDate.value?.hour || 0;
this.minute = this.fcDate.value?.minute || 0;
const startOfDate = this.fcDate.value.startOf('day');
this.dateStart = startOfDate.toISO();
this.allHours = new Array(startOfDate.plus({ days: 1 }).startOf('day').diff(startOfDate, 'hours').toObject().hours).fill(0).map((_, i) => i);
// correct arrays and hours/minutes in case of minDate/maxDate
if (this.minDate && this.fcDate.value.day === this.minDate.day) {
this.allHours = this.allHours.filter((a) => a >= (this.minDate?.hour || 0));
this.allMinutes = this.allMinutes.filter((a) => a >= (this.minDate?.minute || 0));
this.hour = Math.max(this.hour, this.allHours[0]);
this.minute = Math.max(this.minute, this.allMinutes[0]);
}
else if (this.maxDate && this.fcDate.value.day === this.maxDate.day) {
this.allHours = this.allHours.filter((a) => a <= (this.maxDate?.hour || 0));
this.allMinutes = this.allMinutes.filter((a) => a <= (this.maxDate?.minute || 0));
this.hour = Math.min(this.hour, this.allHours[0]);
this.minute = Math.min(this.minute, this.allMinutes[0]);
}
}
else {
this.fcDate.markAsTouched();
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DatePickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: DatePickerComponent, selector: "spaas-date-picker", inputs: { label: "label", withTime: "withTime", fcDate: "fcDate", allowManualInput: "allowManualInput", minDate: "minDate", maxDate: "maxDate", dateConstraint: "dateConstraint" }, usesInheritance: true, ngImport: i0, template: "<div [style.--dp-min-width]=\"withTime ? '254px' : '154px'\"\r\n class=\"date-picker flex\">\r\n\r\n <mat-form-field class=\"grow-h\">\r\n @if (label) {\r\n <mat-label>{{ label }}</mat-label>\r\n }\r\n <input [formControl]=\"fcDate\"\r\n [matDatepicker]=\"picker\"\r\n [matDatepickerFilter]=\"dateConstraint\"\r\n [min]=\"minDate\"\r\n [max]=\"maxDate\"\r\n matInput\r\n [readonly]=\"!allowManualInput\">\r\n <mat-datepicker-toggle [for]=\"picker\" matIconPrefix></mat-datepicker-toggle>\r\n <mat-datepicker #picker [disabled]=\"false\"></mat-datepicker>\r\n <mat-error>\r\n @if (fcDate.hasError('matDatepickerMin') || fcDate.hasError('matDatepickerMax') || fcDate.hasError('matDatepickerFilter')) {\r\n date is not within the correct range\r\n } @else {\r\n invalid date (yyyy-mm-dd expected)\r\n }\r\n </mat-error>\r\n </mat-form-field>\r\n\r\n @if (withTime) {\r\n <div [style.--dp-time-top]=\"label ? '19px' : '11px'\"\r\n class=\"timefields flex\">\r\n <div>\r\n <mat-select (selectionChange)=\"onHourOrMinuteChange()\"\r\n [(ngModel)]=\"hour\"\r\n [disabled]=\"!fcDate.valid\"\r\n [hideSingleSelectionIndicator]=\"true\">\r\n @for (hour of allHours; track hour) {\r\n <mat-option [value]=\"hour\">\r\n {{ hour | idxToTs:dateStart:60:false:'HH' }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </div>\r\n <div>\r\n <mat-select (selectionChange)=\"onHourOrMinuteChange()\"\r\n [(ngModel)]=\"minute\"\r\n [disabled]=\"!fcDate.valid\"\r\n [hideSingleSelectionIndicator]=\"true\">\r\n @for (min of allMinutes; track min) {\r\n <mat-option [value]=\"min\">\r\n {{ min | number:'2.0-0' }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </div>\r\n </div>\r\n }\r\n\r\n</div>\r\n", styles: [".date-picker{min-width:var(--dp-min-width);position:relative}.date-picker .timefields{position:absolute;left:134px;top:var(--dp-time-top)}.date-picker .timefields>div{position:relative}.date-picker .timefields>div:before{color:hsla(var(--color-h),var(--color-s),var(--color-l),.6);font-size:12px;left:0;position:absolute;text-align:center;top:-12px;width:54px}.date-picker .timefields>div:nth-of-type(1):before{content:\"hour\"}.date-picker .timefields>div:nth-of-type(2):before{content:\"minute\"}.date-picker .timefields>div .mat-mdc-select{text-align:center;width:54px}\n"], dependencies: [{ kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i2.MatDatepicker, selector: "mat-datepicker", exportAs: ["matDatepicker"] }, { kind: "directive", type: i2.MatDatepickerInput, selector: "input[matDatepicker]", inputs: ["matDatepicker", "min", "max", "matDatepickerFilter"], exportAs: ["matDatepickerInput"] }, { kind: "component", type: i2.MatDatepickerToggle, selector: "mat-datepicker-toggle", inputs: ["for", "tabIndex", "aria-label", "disabled", "disableRipple"], exportAs: ["matDatepickerToggle"] }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i4.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i4.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i4.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "component", type: i5.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "pipe", type: i7.DecimalPipe, name: "number" }, { kind: "pipe", type: i8.IdxToTsPipe, name: "idxToTs" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: DatePickerComponent, decorators: [{
type: Component,
args: [{ selector: 'spaas-date-picker', template: "<div [style.--dp-min-width]=\"withTime ? '254px' : '154px'\"\r\n class=\"date-picker flex\">\r\n\r\n <mat-form-field class=\"grow-h\">\r\n @if (label) {\r\n <mat-label>{{ label }}</mat-label>\r\n }\r\n <input [formControl]=\"fcDate\"\r\n [matDatepicker]=\"picker\"\r\n [matDatepickerFilter]=\"dateConstraint\"\r\n [min]=\"minDate\"\r\n [max]=\"maxDate\"\r\n matInput\r\n [readonly]=\"!allowManualInput\">\r\n <mat-datepicker-toggle [for]=\"picker\" matIconPrefix></mat-datepicker-toggle>\r\n <mat-datepicker #picker [disabled]=\"false\"></mat-datepicker>\r\n <mat-error>\r\n @if (fcDate.hasError('matDatepickerMin') || fcDate.hasError('matDatepickerMax') || fcDate.hasError('matDatepickerFilter')) {\r\n date is not within the correct range\r\n } @else {\r\n invalid date (yyyy-mm-dd expected)\r\n }\r\n </mat-error>\r\n </mat-form-field>\r\n\r\n @if (withTime) {\r\n <div [style.--dp-time-top]=\"label ? '19px' : '11px'\"\r\n class=\"timefields flex\">\r\n <div>\r\n <mat-select (selectionChange)=\"onHourOrMinuteChange()\"\r\n [(ngModel)]=\"hour\"\r\n [disabled]=\"!fcDate.valid\"\r\n [hideSingleSelectionIndicator]=\"true\">\r\n @for (hour of allHours; track hour) {\r\n <mat-option [value]=\"hour\">\r\n {{ hour | idxToTs:dateStart:60:false:'HH' }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </div>\r\n <div>\r\n <mat-select (selectionChange)=\"onHourOrMinuteChange()\"\r\n [(ngModel)]=\"minute\"\r\n [disabled]=\"!fcDate.valid\"\r\n [hideSingleSelectionIndicator]=\"true\">\r\n @for (min of allMinutes; track min) {\r\n <mat-option [value]=\"min\">\r\n {{ min | number:'2.0-0' }}\r\n </mat-option>\r\n }\r\n </mat-select>\r\n </div>\r\n </div>\r\n }\r\n\r\n</div>\r\n", styles: [".date-picker{min-width:var(--dp-min-width);position:relative}.date-picker .timefields{position:absolute;left:134px;top:var(--dp-time-top)}.date-picker .timefields>div{position:relative}.date-picker .timefields>div:before{color:hsla(var(--color-h),var(--color-s),var(--color-l),.6);font-size:12px;left:0;position:absolute;text-align:center;top:-12px;width:54px}.date-picker .timefields>div:nth-of-type(1):before{content:\"hour\"}.date-picker .timefields>div:nth-of-type(2):before{content:\"minute\"}.date-picker .timefields>div .mat-mdc-select{text-align:center;width:54px}\n"] }]
}], ctorParameters: () => [], propDecorators: { label: [{
type: Input
}], withTime: [{
type: Input
}], fcDate: [{
type: Input
}], allowManualInput: [{
type: Input
}], minDate: [{
type: Input
}], maxDate: [{
type: Input
}], dateConstraint: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWdlbS1zcGFhcy9kYXRlL3NyYy9kYXRlLXBpY2tlci9kYXRlLXBpY2tlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZ2VtLXNwYWFzL2RhdGUvc3JjL2RhdGUtcGlja2VyL2RhdGUtcGlja2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBQyxTQUFTLEVBQUUsS0FBSyxFQUFTLE1BQU0sZUFBZSxDQUFDO0FBQ3ZELE9BQU8sRUFBQyxRQUFRLEVBQUMsTUFBTSxPQUFPLENBQUM7QUFDL0IsT0FBTyxFQUFDLFdBQVcsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBQyxhQUFhLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDNUMsT0FBTyxFQUFDLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7O0FBT3pDLG9FQUFvRTtBQUNwRSxNQUFNLE9BQU8sbUJBQW9CLFNBQVEsYUFBYTtJQTJCcEQ7UUFDRSxLQUFLLEVBQUUsQ0FBQztRQTFCViw2REFBNkQ7UUFDcEQsVUFBSyxHQUFXLEVBQUUsQ0FBQztRQUM1Qiw4REFBOEQ7UUFDckQsYUFBUSxHQUFZLEtBQUssQ0FBQztRQUNuQyxxRkFBcUY7UUFDNUUsV0FBTSxHQUEwQixJQUFJLFdBQVcsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQTBCLENBQUM7UUFDbEcsNkNBQTZDO1FBQ3BDLHFCQUFnQixHQUFHLEtBQUssQ0FBQztRQUVsQyxxQ0FBcUM7UUFDNUIsWUFBTyxHQUFvQixJQUFJLENBQUM7UUFDekMscUNBQXFDO1FBQzVCLFlBQU8sR0FBb0IsSUFBSSxDQUFDO1FBQ3pDO21FQUMyRDtRQUNsRCxtQkFBYyxHQUErQyxHQUFHLEVBQUU7WUFDekUsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDLENBQUM7UUFFRixjQUFTLEdBQWtCLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQ3JELFNBQUksR0FBVyxDQUFDLENBQUM7UUFDakIsYUFBUSxHQUFhLEVBQUUsQ0FBQztRQUN4QixXQUFNLEdBQVcsQ0FBQyxDQUFDO1FBQ25CLGVBQVUsR0FBYSxFQUFFLENBQUM7SUFJMUIsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZO2FBQ3JCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO2FBQ2hDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRUQsMkdBQTJHO0lBQzNHLFlBQVk7SUFDWiwyR0FBMkc7SUFFM0csMkdBQTJHO0lBQzNHLEtBQUs7SUFDTCwyR0FBMkc7SUFFM0csb0JBQW9CO1FBQ2xCLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN0QixJQUFJLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztZQUMzQixJQUFJLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3hGLENBQUM7SUFDSCxDQUFDO0lBRUQsWUFBWTtRQUNWLElBQUksQ0FBQyxVQUFVLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ3pQLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUN0QixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLElBQUksSUFBSSxDQUFDLENBQUM7WUFDekMsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQyxDQUFDO1lBQzdDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUNyRCxJQUFJLENBQUMsU0FBUyxHQUFHLFdBQVcsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNyQyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBQyxJQUFJLEVB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dCI6WyJpbXBvcnQge0NvbXBvbmVudCwgSW5wdXQsIE9uSW5pdH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7RGF0ZVRpbWV9IGZyb20gJ2x1eG9uJztcclxuaW1wb3J0IHtGb3JtQ29udHJvbH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XHJcbmltcG9ydCB7QmFzZUNvbXBvbmVudH0gZnJvbSBcIm5neC1nZW0tc3BhYXNcIjtcclxuaW1wb3J0IHt0YWtlVW50aWx9IGZyb20gXCJyeGpzL29wZXJhdG9yc1wiO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdzcGFhcy1kYXRlLXBpY2tlcicsXHJcbiAgdGVtcGxhdGVVcmw6ICcuL2RhdGUtcGlja2VyLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9kYXRlLXBpY2tlci5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbi8qKiBBIHN0YW5kLWFsb25lIGRhdGUgcGlja2VyIChub3QgaG9va2VkIHVwIHRvIHRoZSBkYXRlIHNlcnZpY2UpICovXHJcbmV4cG9ydCBjbGFzcyBEYXRlUGlja2VyQ29tcG9uZW50IGV4dGVuZHMgQmFzZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gIC8qKiBUaGUgbGFiZWwgdG8gYmUgZGlzcGxheWVkIGluIHRoZSBmb3JtIGZpZWxkIChvcHRpb25hbCkgKi9cclxuICBASW5wdXQoKSBsYWJlbDogc3RyaW5nID0gJyc7XHJcbiAgLyoqIFdoZXRoZXIgdG8gYWxzbyBzaG93IHRoZSB0aW1lLWZpZWxkcy4gRGVmYXVsdCBpcyBmYWxzZS4gKi9cclxuICBASW5wdXQoKSB3aXRoVGltZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8qKiBZb3VyIGZvcm1jb250cm9sIG9mIHR5cGUgRGF0ZVRpbWUuIFdpbGwgYmUgdXBkYXRlZCBkaXJlY3RseSBieSB0aGUgZGF0ZSBwaWNrZXIgKi9cclxuICBASW5wdXQoKSBmY0RhdGU6IEZvcm1Db250cm9sPERhdGVUaW1lPiA9IG5ldyBGb3JtQ29udHJvbChEYXRlVGltZS5ub3coKSkgYXMgRm9ybUNvbnRyb2w8RGF0ZVRpbWU+O1xyXG4gIC8qKiBXaGV0aGVyIHRvIGFsbG93IG1hbnVhbCBrZXlib2FyZCBpbnB1dCAqL1xyXG4gIEBJbnB1dCgpIGFsbG93TWFudWFsSW5wdXQgPSBmYWxzZTtcclxuXHJcbiAgLyoqIE1pbmltdW0gZGF0ZSBpbiBsdXhvbiBEYXRlVGltZSAqL1xyXG4gIEBJbnB1dCgpIG1pbkRhdGU6IERhdGVUaW1lIHwgbnVsbCA9IG51bGw7XHJcbiAgLyoqIE1heGltdW0gZGF0ZSBpbiBsdXhvbiBEYXRlVGltZSAqL1xyXG4gIEBJbnB1dCgpIG1heERhdGU6IERhdGVUaW1lIHwgbnVsbCA9IG51bGw7XHJcbiAgLyoqIEEgY3VzdG9tIGZ1bmN0aW9uIHRvIGxpbWl0IHdoaWNoIGRhdGVzIGNhbiBiZSBjaG9zZW4uXHJcbiAgICogIFRha2VzIERhdGVUaW1lIGFzIGlucHV0IGFuZCBzaG91bGQgcmV0dXJuIGEgYm9vbGVhbi4gKi9cclxuICBASW5wdXQoKSBkYXRlQ29uc3RyYWludDogKHNlbGVjdGVkRGF0ZTogRGF0ZVRpbWUgfCBudWxsKSA9PiBib29sZWFuID0gKCkgPT4ge1xyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfTtcclxuXHJcbiAgZGF0ZVN0YXJ0OiBzdHJpbmcgfCBudWxsID0gdGhpcy5mY0RhdGUudmFsdWUudG9JU08oKTtcclxuICBob3VyOiBudW1iZXIgPSAwO1xyXG4gIGFsbEhvdXJzOiBudW1iZXJbXSA9IFtdO1xyXG4gIG1pbnV0ZTogbnVtYmVyID0gMDtcclxuICBhbGxNaW51dGVzOiBudW1iZXJbXSA9IFtdO1xyXG5cclxuICBjb25zdHJ1Y3RvcigpIHtcclxuICAgIHN1cGVyKCk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIHRoaXMub25EYXRlQ2hhbmdlKCk7XHJcbiAgICB0aGlzLmZjRGF0ZS52YWx1ZUNoYW5nZXNcclxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMub25EZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5vbkRhdGVDaGFuZ2UoKSk7XHJcbiAgfVxyXG5cclxuICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gIC8vIExPQUQgREFUQVxyXG4gIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcblxyXG4gIC8vICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAgLy8gVUlcclxuICAvLyAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5cclxuICBvbkhvdXJPck1pbnV0ZUNoYW5nZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmZjRGF0ZS52YWxpZCkge1xyXG4gICAgICBsZXQgZHQgPSB0aGlzLmZjRGF0ZS52YWx1ZTtcclxuICAgICAgdGhpcy5mY0RhdGUucGF0Y2hWYWx1ZShkdC5zdGFydE9mKCdkYXknKS5wbHVzKHttaW51dGU6IHRoaXMuaG91ciAqIDYwICsgdGhpcy5taW51dGV9KSlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uRGF0ZUNoYW5nZSgpOiB2b2lkIHtcclxuICAgIHRoaXMuYWxsTWludXRlcyA9IFswLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LCAxNiwgMTcsIDE4LCAxOSwgMjAsIDIxLCAyMiwgMjMsIDI0LCAyNSwgMjYsIDI3LCAyOCwgMjksIDMwLCAzMSwgMzIsIDMzLCAzNCwgMzUsIDM2LCAzNywgMzgsIDM5LCA0MCwgNDEsIDQyLCA0MywgNDQsIDQ1LCA0NiwgNDcsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA1OCwgNTldO1xyXG4gICAgaWYgKHRoaXMuZmNEYXRlLnZhbGlkKSB7XHJcbiAgICAgIHRoaXMuaG91ciA9IHRoaXMuZmNEYXRlLnZhbHVlPy5ob3VyIHx8IDA7XHJcbiAgICAgIHRoaXMubWludXRlID0gdGhpcy5mY0RhdGUudmFsdWU/Lm1pbnV0ZSB8fCAwO1xyXG4gICAgICBjb25zdCBzdGFydE9mRGF0ZSA9IHRoaXMuZmNEYXRlLnZhbHVlLnN0YXJ0T2YoJ2RheScpO1xyXG4gICAgICB0aGlzLmRhdGVTdGFydCA9IHN0YXJ0T2ZEYXRlLnRvSVNPKCk7XHJcbiAgICAgIHRoaXMuYWxsSG91cnMgPSBuZXcgQXJyYXkoc3RhcnRPZkRhdGUucGx1cyh7ZGF5czogMX0pLnN0YXJ0T2YoJ2RheScpLmRpZmYoc3RhcnRPZkRhdGUsICdob3VycycpLnRvT2JqZWN0KCkuaG91cnMpLmZpbGwoMCkubWFwKChfLCBpKSA9PiBpKTtcclxuICAgICAgLy8gY29ycmVjdCBhcnJheXMgYW5kIGhvdXJzL21pbnV0ZXMgaW4gY2FzZSBvZiBtaW5EYXRlL21heERhdGVcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHRoaXMubWluRGF0ZSAmJiB0aGlzLmZjRGF0ZS52YWx1ZS5kYXkgPT09IHRoaXMubWluRGF0ZS5kYXlcclxuICAgICAgKSB7XHJcbiAgICAgICAgdGhpcy5hbGxIb3VycyA9IHRoaXMuYWxsSG91cnMuZmlsdGVyKChhKSA9PiBhID49ICh0aGlzLm1pbkRhdGU/LmhvdXIgfHwgMCkpO1xyXG4gICAgICAgIHRoaXMuYWxsTWludXRlcyA9IHRoaXMuYWxsTWludXRlcy5maWx0ZXIoKGEpID0+IGEgPj0gKHRoaXMubWluRGF0ZT8ubWludXRlIHx8IDApKTtcclxuICAgICAgICB0aGlzLmhvdXIgPSBNYXRoLm1heCh0aGlzLmhvdXIsIHRoaXMuYWxsSG91cnNbMF0pO1xyXG4gICAgICAgIHRoaXMubWludXRlID0gTWF0aC5tYXgodGhpcy5taW51dGUsIHRoaXMuYWxsTWludXRlc1swXSk7XHJcbiAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgdGhpcy5tYXhEYXRlICYmIHRoaXMuZmNEYXRlLnZhbHVlLmRheSA9PT0gdGhpcy5tYXhEYXRlLmRheVxyXG4gICAgICApIHtcclxuICAgICAgICB0aGlzLmFsbEhvdXJzID0gdGhpcy5hbGxIb3Vycy5maWx0ZXIoKGEpID0+IGEgPD0gKHRoaXMubWF4RGF0ZT8uaG91ciB8fCAwKSk7XHJcbiAgICAgICAgdGhpcy5hbGxNaW51dGVzID0gdGhpcy5hbGxNaW51dGVzLmZpbHRlcigoYSkgPT4gYSA8PSAodGhpcy5tYXhEYXRlPy5taW51dGUgfHwgMCkpO1xyXG4gICAgICAgIHRoaXMuaG91ciA9IE1hdGgubWluKHRoaXMuaG91ciwgdGhpcy5hbGxIb3Vyc1swXSk7XHJcbiAgICAgICAgdGhpcy5taW51dGUgPSBNYXRoLm1pbih0aGlzLm1pbnV0ZSwgdGhpcy5hbGxNaW51dGVzWzBdKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5mY0RhdGUubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbn1cclxuIiwiPGRpdiBbc3R5bGUuLS1kcC1taW4td2lkdGhdPVwid2l0aFRpbWUgPyAnMjU0cHgnIDogJzE1NHB4J1wiXHJcbiAgICAgY2xhc3M9XCJkYXRlLXBpY2tlciBmbGV4XCI+XHJcblxyXG4gIDxtYXQtZm9ybS1maWVsZCBjbGFzcz1cImdyb3ctaFwiPlxyXG4gICAgQGlmIChsYWJlbCkge1xyXG4gICAgICA8bWF0LWxhYmVsPnt7IGxhYmVsIH19PC9tYXQtbGFiZWw+XHJcbiAgICB9XHJcbiAgICA8aW5wdXQgW2Zvcm1Db250cm9sXT1cImZjRGF0ZVwiXHJcbiAgICAgICAgICAgW21hdERhdGVwaWNrZXJdPVwicGlja2VyXCJcclxuICAgICAgICAgICBbbWF0RGF0ZXBpY2tlckZpbHRlcl09XCJkYXRlQ29uc3RyYWludFwiXHJcbiAgICAgICAgICAgW21pbl09XCJtaW5EYXRlXCJcclxuICAgICAgICAgICBbbWF4XT1cIm1heERhdGVcIlxyXG4gICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgW3JlYWRvbmx5XT1cIiFhbGxvd01hbnVhbElucHV0XCI+XHJcbiAgICA8bWF0LWRhdGVwaWNrZXItdG9nZ2xlIFtmb3JdPVwicGlja2VyXCIgbWF0SWNvblByZWZpeD48L21hdC1kYXRlcGlja2VyLXRvZ2dsZT5cclxuICAgIDxtYXQtZGF0ZXBpY2tlciAjcGlja2VyIFtkaXNhYmxlZF09XCJmYWxzZVwiPjwvbWF0LWRhdGVwaWNrZXI+XHJcbiAgICA8bWF0LWVycm9yPlxyXG4gICAgICBAaWYgKGZjRGF0ZS5oYXNFcnJvcignbWF0RGF0ZXBpY2tlck1pbicpIHx8IGZjRGF0ZS5oYXNFcnJvcignbWF0RGF0ZXBpY2tlck1heCcpIHx8IGZjRGF0ZS5oYXNFcnJvcignbWF0RGF0ZXBpY2tlckZpbHRlcicpKSB7XHJcbiAgICAgICAgZGF0ZSBpcyBub3Qgd2l0aGluIHRoZSBjb3JyZWN0IHJhbmdlXHJcbiAgICAgIH0gQGVsc2Uge1xyXG4gICAgICAgIGludmFsaWQgZGF0ZSAoeXl5eS1tbS1kZCBleHBlY3RlZClcclxuICAgICAgfVxyXG4gICAgPC9tYXQtZXJyb3I+XHJcbiAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgQGlmICh3aXRoVGltZSkge1xyXG4gICAgPGRpdiBbc3R5bGUuLS1kcC10aW1lLXRvcF09XCJsYWJlbCA/ICcxOXB4JyA6ICcxMXB4J1wiXHJcbiAgICAgICAgIGNsYXNzPVwidGltZWZpZWxkcyBmbGV4XCI+XHJcbiAgICAgIDxkaXY+XHJcbiAgICAgICAgPG1hdC1zZWxlY3QgKHNlbGVjdGlvbkNoYW5nZSk9XCJvbkhvdXJPck1pbnV0ZUNoYW5nZSgpXCJcclxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImhvdXJcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhZmNEYXRlLnZhbGlkXCJcclxuICAgICAgICAgICAgICAgICAgICBbaGlkZVNpbmdsZVNlbGVjdGlvbkluZGljYXRvcl09XCJ0cnVlXCI+XHJcbiAgICAgICAgICBAZm9yIChob3VyIG9mIGFsbEhvdXJzOyB0cmFjayBob3VyKSB7XHJcbiAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJob3VyXCI+XHJcbiAgICAgICAgICAgICAge3sgaG91ciB8IGlkeFRvVHM6ZGF0ZVN0YXJ0OjYwOmZhbHNlOidISCcgfX1cclxuICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXY+XHJcbiAgICAgICAgPG1hdC1zZWxlY3QgKHNlbGVjdGlvbkNoYW5nZSk9XCJvbkhvdXJPck1pbnV0ZUNoYW5nZSgpXCJcclxuICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm1pbnV0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFmY0RhdGUudmFsaWRcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtoaWRlU2luZ2xlU2VsZWN0aW9uSW5kaWNhdG9yXT1cInRydWVcIj5cclxuICAgICAgICAgIEBmb3IgKG1pbiBvZiBhbGxNaW51dGVzOyB0cmFjayBtaW4pIHtcclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm1pblwiPlxyXG4gICAgICAgICAgICAgIHt7IG1pbiB8IG51bWJlcjonMi4wLTAnIH19XHJcbiAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgIH1cclxuICAgICAgICA8L21hdC1zZWxlY3Q+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgfVxyXG5cclxuPC9kaXY+XHJcbiJdfQ==