UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

92 lines 18.4 kB
import { Component, EventEmitter, inject, Input, Output } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { BsDatepickerModule } from 'ngx-bootstrap/datepicker'; import { CommonModule } from '../common/common.module'; import { CUSTOM, INTERVAL_OPTIONS, LAST_HOUR } from './time-interval.model'; import { DateFormatService } from '../common/date-format.service'; import * as i0 from "@angular/core"; import * as i1 from "../common/icon.directive"; import * as i2 from "@angular/common"; import * as i3 from "../i18n/c8y-translate.pipe"; import * as i4 from "@angular/forms"; import * as i5 from "ngx-bootstrap/datepicker"; export class TimeIntervalComponent { constructor() { this.intvervals = INTERVAL_OPTIONS; this.CUSTOM = CUSTOM; this.selectedInterval = LAST_HOUR; this.interval = new EventEmitter(); this.dateFormatService = inject(DateFormatService); } ngOnInit() { if (!this.dateRangePickerConfig.dateInputFormat) { this.dateRangePickerConfig.dateInputFormat = this.dateFormatService.getDateFormat(); } } ngAfterViewInit() { this.changeInterval(this.selectedInterval); } changeInterval(intervalOption) { if (intervalOption !== CUSTOM) { const interval = { dateFrom: intervalOption.getStartDate(), dateTo: this.getEndDate() }; this.emitInterval(interval); } } changeCustomRange(range) { this.emitInterval(this.rangeToInterval(range)); } reload() { if (this.selectedInterval === CUSTOM) { this.emitInterval(this.rangeToInterval(this.customRange)); } else { this.changeInterval(this.selectedInterval); } } getEndDate() { const end = new Date(); end.setSeconds(end.getSeconds() + 1); return end; } rangeToInterval(range) { const dateFrom = new Date(range[0]); const dateTo = new Date(range[1]); dateFrom.setHours(0, 0, 0, 0); if (!this.isToday(dateTo)) { dateTo.setHours(23, 59, 59, 999); } return { dateFrom, dateTo }; } isToday(date) { const today = new Date(); return (date?.getDate() === today.getDate() && date.getMonth() === today.getMonth() && date.getFullYear() === today.getFullYear()); } emitInterval(interval) { // only emit valid intervals if (!isNaN(interval?.dateFrom?.getTime()) && !isNaN(interval?.dateTo?.getTime())) { this.interval.emit(interval); } } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TimeIntervalComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: TimeIntervalComponent, isStandalone: true, selector: "c8y-time-interval", inputs: { minCustomDate: "minCustomDate", maxCustomDate: "maxCustomDate", dateRangePickerConfig: "dateRangePickerConfig", selectedInterval: "selectedInterval" }, outputs: { interval: "interval" }, ngImport: i0, template: "<form class=\"form-inline\">\n <div class=\"form-group\">\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n [attr.aria-label]=\"'Time interval' | translate\"\n name=\"interval\"\n [(ngModel)]=\"selectedInterval\"\n (ngModelChange)=\"changeInterval($event)\"\n data-cy=\"c8y-time-interval--select\"\n >\n <option\n *ngFor=\"let interval of intvervals\"\n [ngValue]=\"interval\"\n >\n {{ interval.label | translate }}\n </option>\n </select>\n </div>\n </div>\n\n <div\n class=\"form-group datepicker\"\n *ngIf=\"selectedInterval === CUSTOM\"\n >\n <input\n class=\"form-control\"\n [placeholder]=\"'Select date range' | translate\"\n bsDaterangepicker\n [bsConfig]=\"dateRangePickerConfig\"\n [minDate]=\"minCustomDate\"\n [maxDate]=\"maxCustomDate\"\n [(bsValue)]=\"customRange\"\n (bsValueChange)=\"changeCustomRange($event)\"\n />\n </div>\n\n <button\n class=\"btn btn-link\"\n [title]=\"'Reload' | translate\"\n type=\"button\"\n [disabled]=\"selectedInterval === CUSTOM && (!customRange || customRange.length === 0)\"\n (click)=\"reload()\"\n >\n <i c8yIcon=\"refresh\"></i>\n {{ 'Reload' | translate }}\n </button>\n</form>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i3.C8yTranslatePipe, name: "translate" }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i4.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: BsDatepickerModule }, { kind: "directive", type: i5.BsDaterangepickerDirective, selector: "[bsDaterangepicker]", inputs: ["placement", "triggers", "outsideClick", "container", "outsideEsc", "isOpen", "bsValue", "bsConfig", "isDisabled", "minDate", "maxDate", "dateCustomClasses", "daysDisabled", "datesDisabled", "datesEnabled"], outputs: ["onShown", "onHidden", "bsValueChange"], exportAs: ["bsDaterangepicker"] }, { kind: "directive", type: i5.BsDaterangepickerInputDirective, selector: "input[bsDaterangepicker]" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: TimeIntervalComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'c8y-time-interval', imports: [CommonModule, FormsModule, BsDatepickerModule], template: "<form class=\"form-inline\">\n <div class=\"form-group\">\n <div class=\"c8y-select-wrapper\">\n <select\n class=\"form-control\"\n [attr.aria-label]=\"'Time interval' | translate\"\n name=\"interval\"\n [(ngModel)]=\"selectedInterval\"\n (ngModelChange)=\"changeInterval($event)\"\n data-cy=\"c8y-time-interval--select\"\n >\n <option\n *ngFor=\"let interval of intvervals\"\n [ngValue]=\"interval\"\n >\n {{ interval.label | translate }}\n </option>\n </select>\n </div>\n </div>\n\n <div\n class=\"form-group datepicker\"\n *ngIf=\"selectedInterval === CUSTOM\"\n >\n <input\n class=\"form-control\"\n [placeholder]=\"'Select date range' | translate\"\n bsDaterangepicker\n [bsConfig]=\"dateRangePickerConfig\"\n [minDate]=\"minCustomDate\"\n [maxDate]=\"maxCustomDate\"\n [(bsValue)]=\"customRange\"\n (bsValueChange)=\"changeCustomRange($event)\"\n />\n </div>\n\n <button\n class=\"btn btn-link\"\n [title]=\"'Reload' | translate\"\n type=\"button\"\n [disabled]=\"selectedInterval === CUSTOM && (!customRange || customRange.length === 0)\"\n (click)=\"reload()\"\n >\n <i c8yIcon=\"refresh\"></i>\n {{ 'Reload' | translate }}\n </button>\n</form>\n" }] }], propDecorators: { minCustomDate: [{ type: Input }], maxCustomDate: [{ type: Input }], dateRangePickerConfig: [{ type: Input }], selectedInterval: [{ type: Input }], interval: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZS1pbnRlcnZhbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL3RpbWUtaW50ZXJ2YWwvdGltZS1pbnRlcnZhbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9jb3JlL3RpbWUtaW50ZXJ2YWwvdGltZS1pbnRlcnZhbC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsU0FBUyxFQUNULFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUVMLE1BQU0sRUFDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3ZELE9BQU8sRUFDTCxNQUFNLEVBRU4sZ0JBQWdCLEVBQ2hCLFNBQVMsRUFHVixNQUFNLHVCQUF1QixDQUFDO0FBQy9CLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDOzs7Ozs7O0FBUWxFLE1BQU0sT0FBTyxxQkFBcUI7SUFObEM7UUFPRSxlQUFVLEdBQUcsZ0JBQWdCLENBQUM7UUFDOUIsV0FBTSxHQUFHLE1BQU0sQ0FBQztRQVloQixxQkFBZ0IsR0FBdUIsU0FBUyxDQUFDO1FBR2pELGFBQVEsR0FBK0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUlsRCxzQkFBaUIsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztLQW1FdkQ7SUFqRUMsUUFBUTtRQUNOLElBQUksQ0FBQyxJQUFJLENBQUMscUJBQXFCLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDaEQsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsYUFBYSxFQUFFLENBQUM7UUFDdEYsQ0FBQztJ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LFdBRXBCLENBQUMsWUFBWSxFQUFFLFdBQVcsRUFBRSxrQkFBa0IsQ0FBQzs4QkFPeEQsYUFBYTtzQkFEWixLQUFLO2dCQUlOLGFBQWE7c0JBRFosS0FBSztnQkFJTixxQkFBcUI7c0JBRHBCLEtBQUs7Z0JBSU4sZ0JBQWdCO3NCQURmLEtBQUs7Z0JBSU4sUUFBUTtzQkFEUCxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIGluamVjdCxcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3V0cHV0XG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBCc0RhdGVwaWNrZXJNb2R1bGUgfSBmcm9tICduZ3gtYm9vdHN0cmFwL2RhdGVwaWNrZXInO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnLi4vY29tbW9uL2NvbW1vbi5tb2R1bGUnO1xuaW1wb3J0IHtcbiAgQ1VTVE9NLFxuICBEYXRlUmFuZ2VQaWNrZXJDb25maWcsXG4gIElOVEVSVkFMX09QVElPTlMsXG4gIExBU1RfSE9VUixcbiAgVGltZUludGVydmFsLFxuICBUaW1lSW50ZXJ2YWxPcHRpb25cbn0gZnJvbSAnLi90aW1lLWludGVydmFsLm1vZGVsJztcbmltcG9ydCB7IERhdGVGb3JtYXRTZXJ2aWNlIH0gZnJvbSAnLi4vY29tbW9uL2RhdGUtZm9ybWF0LnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgc2VsZWN0b3I6ICdjOHktdGltZS1pbnRlcnZhbCcsXG4gIHRlbXBsYXRlVXJsOiAnLi90aW1lLWludGVydmFsLmNvbXBvbmVudC5odG1sJyxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRm9ybXNNb2R1bGUsIEJzRGF0ZXBpY2tlck1vZHVsZV1cbn0pXG5leHBvcnQgY2xhc3MgVGltZUludGVydmFsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcbiAgaW50dmVydmFscyA9IElOVEVSVkFMX09QVElPTlM7XG4gIENVU1RPTSA9IENVU1RPTTtcblxuICBASW5wdXQoKVxuICBtaW5DdXN0b21EYXRlOiBEYXRlO1xuXG4gIEBJbnB1dCgpXG4gIG1heEN1c3RvbURhdGU6IERhdGU7XG5cbiAgQElucHV0KClcbiAgZGF0ZVJhbmdlUGlja2VyQ29uZmlnOiBEYXRlUmFuZ2VQaWNrZXJDb25maWc7XG5cbiAgQElucHV0KClcbiAgc2VsZWN0ZWRJbnRlcnZhbDogVGltZUludGVydmFsT3B0aW9uID0gTEFTVF9IT1VSO1xuXG4gIEBPdXRwdXQoKVxuICBpbnRlcnZhbDogRXZlbnRFbWl0dGVyPFRpbWVJbnRlcnZhbD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgY3VzdG9tUmFuZ2U6IERhdGVbXTtcblxuICBwcml2YXRlIGRhdGVGb3JtYXRTZXJ2aWNlID0gaW5qZWN0KERhdGVGb3JtYXRTZXJ2aWNlKTtcblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZGF0ZVJhbmdlUGlja2VyQ29uZmlnLmRhdGVJbnB1dEZvcm1hdCkge1xuICAgICAgdGhpcy5kYXRlUmFuZ2VQaWNrZXJDb25maWcuZGF0ZUlucHV0Rm9ybWF0ID0gdGhpcy5kYXRlRm9ybWF0U2VydmljZS5nZXREYXRlRm9ybWF0KCk7XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuY2hhbmdlSW50ZXJ2YWwodGhpcy5zZWxlY3RlZEludGVydmFsKTtcbiAgfVxuXG4gIGNoYW5nZUludGVydmFsKGludGVydmFsT3B0aW9uOiBUaW1lSW50ZXJ2YWxPcHRpb24pIHtcbiAgICBpZiAoaW50ZXJ2YWxPcHRpb24gIT09IENVU1RPTSkge1xuICAgICAgY29uc3QgaW50ZXJ2YWw6IFRpbWVJbnRlcnZhbCA9IHtcbiAgICAgICAgZGF0ZUZyb206IGludGVydmFsT3B0aW9uLmdldFN0YXJ0RGF0ZSgpLFxuICAgICAgICBkYXRlVG86IHRoaXMuZ2V0RW5kRGF0ZSgpXG4gICAgICB9O1xuXG4gICAgICB0aGlzLmVtaXRJbnRlcnZhbChpbnRlcnZhbCk7XG4gICAgfVxuICB9XG5cbiAgY2hhbmdlQ3VzdG9tUmFuZ2UocmFuZ2U6IERhdGVbXSkge1xuICAgIHRoaXMuZW1pdEludGVydmFsKHRoaXMucmFuZ2VUb0ludGVydmFsKHJhbmdlKSk7XG4gIH1cblxuICByZWxvYWQoKSB7XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRJbnRlcnZhbCA9PT0gQ1VTVE9NKSB7XG4gICAgICB0aGlzLmVtaXRJbnRlcnZhbCh0aGlzLnJhbmdlVG9JbnRlcnZhbCh0aGlzLmN1c3RvbVJhbmdlKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuY2hhbmdlSW50ZXJ2YWwodGhpcy5zZWxlY3RlZEludGVydmFsKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldEVuZERhdGUoKTogRGF0ZSB7XG4gICAgY29uc3QgZW5kID0gbmV3IERhdGUoKTtcbiAgICBlbmQuc2V0U2Vjb25kcyhlbmQuZ2V0U2Vjb25kcygpICsgMSk7XG4gICAgcmV0dXJuIGVuZDtcbiAgfVxuXG4gIHByaXZhdGUgcmFuZ2VUb0ludGVydmFsKHJhbmdlOiBEYXRlW10pOiBUaW1lSW50ZXJ2YWwge1xuICAgIGNvbnN0IGRhdGVGcm9tID0gbmV3IERhdGUocmFuZ2VbMF0pO1xuICAgIGNvbnN0IGRhdGVUbyA9IG5ldyBEYXRlKHJhbmdlWzFdKTtcblxuICAgIGRhdGVGcm9tLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICAgIGlmICghdGhpcy5pc1RvZGF5KGRhdGVUbykpIHtcbiAgICAgIGRhdGVUby5zZXRIb3VycygyMywgNTksIDU5LCA5OTkpO1xuICAgIH1cbiAgICByZXR1cm4geyBkYXRlRnJvbSwgZGF0ZVRvIH07XG4gIH1cblxuICBwcml2YXRlIGlzVG9kYXkoZGF0ZTogRGF0ZSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICByZXR1cm4gKFxuICAgICAgZGF0ZT8uZ2V0RGF0ZSgpID09PSB0b2RheS5nZXREYXRlKCkgJiZcbiAgICAgIGRhdGUuZ2V0TW9udGgoKSA9PT0gdG9kYXkuZ2V0TW9udGgoKSAmJlxuICAgICAgZGF0ZS5nZXRGdWxsWWVhcigpID09PSB0b2RheS5nZXRGdWxsWWVhcigpXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdEludGVydmFsKGludGVydmFsOiBUaW1lSW50ZXJ2YWwpIHtcbiAgICAvLyBvbmx5IGVtaXQgdmFsaWQgaW50ZXJ2YWxzXG4gICAgaWYgKCFpc05hTihpbnRlcnZhbD8uZGF0ZUZyb20/LmdldFRpbWUoKSkgJiYgIWlzTmFOKGludGVydmFsPy5kYXRlVG8/LmdldFRpbWUoKSkpIHtcbiAgICAgIHRoaXMuaW50ZXJ2YWwuZW1pdChpbnRlcnZhbCk7XG4gICAgfVxuICB9XG59XG4iLCI8Zm9ybSBjbGFzcz1cImZvcm0taW5saW5lXCI+XG4gIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgPGRpdiBjbGFzcz1cImM4eS1zZWxlY3Qtd3JhcHBlclwiPlxuICAgICAgPHNlbGVjdFxuICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1RpbWUgaW50ZXJ2YWwnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgbmFtZT1cImludGVydmFsXCJcbiAgICAgICAgWyhuZ01vZGVsKV09XCJzZWxlY3RlZEludGVydmFsXCJcbiAgICAgICAgKG5nTW9kZWxDaGFuZ2UpPVwiY2hhbmdlSW50ZXJ2YWwoJGV2ZW50KVwiXG4gICAgICAgIGRhdGEtY3k9XCJjOHktdGltZS1pbnRlcnZhbC0tc2VsZWN0XCJcbiAgICAgID5cbiAgICAgICAgPG9wdGlvblxuICAgICAgICAgICpuZ0Zvcj1cImxldCBpbnRlcnZhbCBvZiBpbnR2ZXJ2YWxzXCJcbiAgICAgICAgICBbbmdWYWx1ZV09XCJpbnRlcnZhbFwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyBpbnRlcnZhbC5sYWJlbCB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICA8L29wdGlvbj5cbiAgICAgIDwvc2VsZWN0PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuICA8ZGl2XG4gICAgY2xhc3M9XCJmb3JtLWdyb3VwIGRhdGVwaWNrZXJcIlxuICAgICpuZ0lmPVwic2VsZWN0ZWRJbnRlcnZhbCA9PT0gQ1VTVE9NXCJcbiAgPlxuICAgIDxpbnB1dFxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgW3BsYWNlaG9sZGVyXT1cIidTZWxlY3QgZGF0ZSByYW5nZScgfCB0cmFuc2xhdGVcIlxuICAgICAgYnNEYXRlcmFuZ2VwaWNrZXJcbiAgICAgIFtic0NvbmZpZ109XCJkYXRlUmFuZ2VQaWNrZXJDb25maWdcIlxuICAgICAgW21pbkRhdGVdPVwibWluQ3VzdG9tRGF0ZVwiXG4gICAgICBbbWF4RGF0ZV09XCJtYXhDdXN0b21EYXRlXCJcbiAgICAgIFsoYnNWYWx1ZSldPVwiY3VzdG9tUmFuZ2VcIlxuICAgICAgKGJzVmFsdWVDaGFuZ2UpPVwiY2hhbmdlQ3VzdG9tUmFuZ2UoJGV2ZW50KVwiXG4gICAgLz5cbiAgPC9kaXY+XG5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1saW5rXCJcbiAgICBbdGl0bGVdPVwiJ1JlbG9hZCcgfCB0cmFuc2xhdGVcIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgIFtkaXNhYmxlZF09XCJzZWxlY3RlZEludGVydmFsID09PSBDVVNUT00gJiYgKCFjdXN0b21SYW5nZSB8fCBjdXN0b21SYW5nZS5sZW5ndGggPT09IDApXCJcbiAgICAoY2xpY2spPVwicmVsb2FkKClcIlxuICA+XG4gICAgPGkgYzh5SWNvbj1cInJlZnJlc2hcIj48L2k+XG4gICAge3sgJ1JlbG9hZCcgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG48L2Zvcm0+XG4iXX0=