UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

119 lines 38.8 kB
import { Component, Output, EventEmitter } from '@angular/core'; import { BsModalRef } from 'ngx-bootstrap/modal'; import { ActionType } from './export-schedules.interface'; import { CronService } from './cron.service'; import { cloneDeep } from 'lodash-es'; import { gettext } from '@c8y/ngx-components'; import { ReportsService } from './reports.service'; import * as i0 from "@angular/core"; import * as i1 from "./reports.service"; import * as i2 from "ngx-bootstrap/modal"; import * as i3 from "./cron.service"; import * as i4 from "@c8y/ngx-components"; import * as i5 from "@angular/common"; import * as i6 from "@angular/forms"; import * as i7 from "./cron.component"; export class ScheduleModalComponent { constructor(reportsService, modalRef, cronService) { this.reportsService = reportsService; this.modalRef = modalRef; this.cronService = cronService; this.emitter = new EventEmitter(); this.ActionType = ActionType; this.cronExpression = '* * * * *'; this.validCron = false; this.emitterPayload = { success: false, message: '', schedule: { timestamp: undefined, emailConfig: undefined, cronConfig: undefined } }; this.placeholdersInfo = gettext('Available placeholders: {tenant-domain}, {host}, {binaryId}. Whole link to downloadable file is: {tenant-domain}/inventory/binaries/{binaryId}.'); } ngOnInit() { this.oldSchedule = cloneDeep(this.schedule); this.populateEmailFieldsFromSchedule(this.schedule); this.cronExpression = this.cronService.generateCron(this.schedule.cronConfig); this.validCron = this.cronService.validateModels(this.cronService.getBase(this.schedule.cronConfig), this.schedule.cronConfig); } populateEmailFieldsFromSchedule(schedule) { if (schedule.emailConfig.to && schedule.emailConfig.to.length) { this.emailTo = schedule.emailConfig.to.toString(); } if (schedule.emailConfig.cc && schedule.emailConfig.cc.length) { this.emailCc = schedule.emailConfig.cc.toString(); } if (schedule.emailConfig.bcc && schedule.emailConfig.bcc.length) { this.emailBcc = schedule.emailConfig.bcc.toString(); } if (schedule.emailConfig.replyTo) { this.emailReplyTo = schedule.emailConfig.replyTo; } if (schedule.emailConfig.subject) { this.emailSubject = schedule.emailConfig.subject; } if (schedule.emailConfig.text) { this.emailText = schedule.emailConfig.text; } } save() { this.populateScheduleFromCronExpression(); this.populateScheduleFromEmailFields(); if (this.actionType === ActionType.CREATE || this.actionType === ActionType.DUPLICATE) { const date = new Date(); const timestamp = date.getTime(); this.schedule.timestamp = timestamp; } this.emitterPayload.success = true; this.emitterPayload.schedule = this.schedule; this.modalRef.hide(); // signal to the parent component to update list this.emitter.emit(this.emitterPayload); } cancel() { this.modalRef.hide(); } getCron(cron) { this.validCron = cron.valid; if (cron.valid) { this.cronExpression = cron.cron; } } populateScheduleFromCronExpression() { this.schedule.cronConfig = this.cronService.generateCronConfig(this.cronExpression); } convertStringOfEmailsToArray(stringOfEmails) { const arr = []; if (stringOfEmails) { const parts = stringOfEmails.split(','); parts.forEach(item => { if (item) { arr.push(item); } }); } return arr; } populateScheduleFromEmailFields() { this.schedule.emailConfig.to = this.emailTo ? this.convertStringOfEmailsToArray(this.emailTo) : null; this.schedule.emailConfig.cc = this.emailCc ? this.convertStringOfEmailsToArray(this.emailCc) : null; this.schedule.emailConfig.bcc = this.emailBcc ? this.convertStringOfEmailsToArray(this.emailBcc) : null; this.schedule.emailConfig.replyTo = this.emailReplyTo; this.schedule.emailConfig.subject = this.emailSubject; this.schedule.emailConfig.text = this.emailText; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScheduleModalComponent, deps: [{ token: i1.ReportsService }, { token: i2.BsModalRef }, { token: i3.CronService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: ScheduleModalComponent, selector: "schedule-modal", outputs: { emitter: "emitter" }, ngImport: i0, template: "<div class=\"modal-header dialog-header\">\n <i c8yIcon=\"c8y-report\"></i>\n <h4 id=\"modal-title\">\n <span *ngIf=\"actionType === ActionType.CREATE\" translate>New export schedule</span>\n <span *ngIf=\"actionType === ActionType.EDIT\" translate>Edit export schedule</span>\n <span *ngIf=\"actionType === ActionType.DUPLICATE\" translate>Duplicate export schedule</span>\n </h4>\n</div>\n\n<div class=\"modal-body\" id=\"modal-body\">\n <p class=\"lead text-center p-t-24 m-b-0\" translate>On schedule send export via email</p>\n</div>\n<div class=\"modal-inner-scroll smart-rule-control\">\n <form #scheduleForm=\"ngForm\" class=\"edit-smart-rule-details\">\n <div class=\"list-group\">\n <div class=\"list-group-item bg-level-1\">\n <div class=\"smart-list-icon-label\">\n <span class=\"dot bg-primary-light m-r-8\">1</span>\n <strong translate>Frequency</strong>\n </div>\n <div class=\"p-t-16\">\n <div class=\"form-group\">\n <cron [cronIn]=\"cronExpression\" (emitter)=\"getCron($event)\" name=\"cron\"></cron>\n </div>\n </div>\n </div>\n <div class=\"list-group-item\">\n <div class=\"smart-list-icon-label\">\n <span class=\"dot bg-primary-light m-r-8\">2</span>\n <div class=\"d-inline-block\">\n <strong translate>Send email</strong>\n <p class=\"help-block text-muted small p-absolute\">\n <i class=\"text-info m-r-4 text-14\" c8yIcon=\"info-circle\"></i>\n <span translate\n >Enter one or more valid email addresses, separated with a comma.</span\n >\n </p>\n </div>\n </div>\n <div class=\"p-t-24\">\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Send to</label>\n <c8y-form-group>\n <input\n emails\n type=\"text\"\n class=\"form-control\"\n name=\"to\"\n [(ngModel)]=\"emailTo\"\n placeholder=\"{{\n 'e.g. joe.doe@example.com,john.smith@example.com`LOCALIZE`' | translate\n }}\"\n required\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>CC</label>\n <c8y-form-group>\n <input\n emails\n type=\"text\"\n class=\"form-control span\"\n name=\"cc\"\n placeholder=\"{{\n 'e.g. joe.doe@example.com,john.smith@example.com`LOCALIZE`' | translate\n }}\"\n [(ngModel)]=\"emailCc\"\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>BCC</label>\n <c8y-form-group>\n <input\n emails\n type=\"text\"\n class=\"form-control span\"\n name=\"bcc\"\n placeholder=\"{{\n 'e.g. joe.doe@example.com,john.smith@example.com`LOCALIZE`' | translate\n }}\"\n [(ngModel)]=\"emailBcc\"\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Reply to (single email address)</label>\n <c8y-form-group>\n <input\n email\n type=\"text\"\n class=\"form-control span\"\n name=\"replyTo\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"emailReplyTo\"\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Subject</label>\n <c8y-form-group>\n <input\n type=\"text\"\n class=\"form-control span\"\n name=\"subject\"\n [(ngModel)]=\"emailSubject\"\n placeholder=\"{{ 'e.g. Daily report' | translate }}\"\n required\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Message</label>\n <c8y-form-group>\n <textarea\n class=\"form-control\"\n name=\"text\"\n [(ngModel)]=\"emailText\"\n placeholder=\"{{ 'Message' | translate }}\"\n rows=\"4\"\n required\n ></textarea>\n <p class=\"help-block text-muted\">\n {{ placeholdersInfo | translate }}\n </p>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </form>\n</div>\n\n<div class=\"modal-footer\">\n <button class=\"btn btn-default\" (click)=\"cancel()\" title=\"{{ 'Cancel' | translate }}\">\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n (click)=\"save()\"\n [disabled]=\"!validCron || !scheduleForm.form.valid\"\n >\n <span>\n <span *ngIf=\"actionType === ActionType.CREATE\" title=\"{{ 'Create' | translate }}\">\n {{ 'Create' | translate }}\n </span>\n <span *ngIf=\"actionType === ActionType.EDIT\" title=\"{{ 'Save' | translate }}\">\n {{ 'Save' | translate }}\n </span>\n <span *ngIf=\"actionType === ActionType.DUPLICATE\" title=\"{{ 'Duplicate' | translate }}\">\n {{ 'Duplicate' | translate }}\n </span>\n </span>\n </button>\n</div>\n", dependencies: [{ kind: "directive", type: i4.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i4.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i6.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: i6.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i6.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i6.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i6.EmailValidator, selector: "[email][formControlName],[email][formControl],[email][ngModel]", inputs: ["email"] }, { kind: "directive", type: i6.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i6.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: i4.FormGroupComponent, selector: "c8y-form-group", inputs: ["hasError", "hasWarning", "hasSuccess", "novalidation", "status"] }, { kind: "directive", type: i4.RequiredInputPlaceholderDirective, selector: "input[required], input[formControlName]" }, { kind: "directive", type: i4.EmailsValidatorDirective, selector: "[emails][formControlName],[emails][formControl],[emails][ngModel]", inputs: ["emails"] }, { kind: "component", type: i7.CronComponent, selector: "cron", inputs: ["cronIn"], outputs: ["emitter"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ScheduleModalComponent, decorators: [{ type: Component, args: [{ selector: 'schedule-modal', template: "<div class=\"modal-header dialog-header\">\n <i c8yIcon=\"c8y-report\"></i>\n <h4 id=\"modal-title\">\n <span *ngIf=\"actionType === ActionType.CREATE\" translate>New export schedule</span>\n <span *ngIf=\"actionType === ActionType.EDIT\" translate>Edit export schedule</span>\n <span *ngIf=\"actionType === ActionType.DUPLICATE\" translate>Duplicate export schedule</span>\n </h4>\n</div>\n\n<div class=\"modal-body\" id=\"modal-body\">\n <p class=\"lead text-center p-t-24 m-b-0\" translate>On schedule send export via email</p>\n</div>\n<div class=\"modal-inner-scroll smart-rule-control\">\n <form #scheduleForm=\"ngForm\" class=\"edit-smart-rule-details\">\n <div class=\"list-group\">\n <div class=\"list-group-item bg-level-1\">\n <div class=\"smart-list-icon-label\">\n <span class=\"dot bg-primary-light m-r-8\">1</span>\n <strong translate>Frequency</strong>\n </div>\n <div class=\"p-t-16\">\n <div class=\"form-group\">\n <cron [cronIn]=\"cronExpression\" (emitter)=\"getCron($event)\" name=\"cron\"></cron>\n </div>\n </div>\n </div>\n <div class=\"list-group-item\">\n <div class=\"smart-list-icon-label\">\n <span class=\"dot bg-primary-light m-r-8\">2</span>\n <div class=\"d-inline-block\">\n <strong translate>Send email</strong>\n <p class=\"help-block text-muted small p-absolute\">\n <i class=\"text-info m-r-4 text-14\" c8yIcon=\"info-circle\"></i>\n <span translate\n >Enter one or more valid email addresses, separated with a comma.</span\n >\n </p>\n </div>\n </div>\n <div class=\"p-t-24\">\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Send to</label>\n <c8y-form-group>\n <input\n emails\n type=\"text\"\n class=\"form-control\"\n name=\"to\"\n [(ngModel)]=\"emailTo\"\n placeholder=\"{{\n 'e.g. joe.doe@example.com,john.smith@example.com`LOCALIZE`' | translate\n }}\"\n required\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>CC</label>\n <c8y-form-group>\n <input\n emails\n type=\"text\"\n class=\"form-control span\"\n name=\"cc\"\n placeholder=\"{{\n 'e.g. joe.doe@example.com,john.smith@example.com`LOCALIZE`' | translate\n }}\"\n [(ngModel)]=\"emailCc\"\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>BCC</label>\n <c8y-form-group>\n <input\n emails\n type=\"text\"\n class=\"form-control span\"\n name=\"bcc\"\n placeholder=\"{{\n 'e.g. joe.doe@example.com,john.smith@example.com`LOCALIZE`' | translate\n }}\"\n [(ngModel)]=\"emailBcc\"\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Reply to (single email address)</label>\n <c8y-form-group>\n <input\n email\n type=\"text\"\n class=\"form-control span\"\n name=\"replyTo\"\n placeholder=\"{{ 'e.g. joe.doe@example.com`LOCALIZE`' | translate }}\"\n [(ngModel)]=\"emailReplyTo\"\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Subject</label>\n <c8y-form-group>\n <input\n type=\"text\"\n class=\"form-control span\"\n name=\"subject\"\n [(ngModel)]=\"emailSubject\"\n placeholder=\"{{ 'e.g. Daily report' | translate }}\"\n required\n />\n </c8y-form-group>\n </div>\n\n <div class=\"form-group\">\n <label class=\"control-label\" translate>Message</label>\n <c8y-form-group>\n <textarea\n class=\"form-control\"\n name=\"text\"\n [(ngModel)]=\"emailText\"\n placeholder=\"{{ 'Message' | translate }}\"\n rows=\"4\"\n required\n ></textarea>\n <p class=\"help-block text-muted\">\n {{ placeholdersInfo | translate }}\n </p>\n </c8y-form-group>\n </div>\n </div>\n </div>\n </div>\n </form>\n</div>\n\n<div class=\"modal-footer\">\n <button class=\"btn btn-default\" (click)=\"cancel()\" title=\"{{ 'Cancel' | translate }}\">\n {{ 'Cancel' | translate }}\n </button>\n <button\n class=\"btn btn-primary\"\n (click)=\"save()\"\n [disabled]=\"!validCron || !scheduleForm.form.valid\"\n >\n <span>\n <span *ngIf=\"actionType === ActionType.CREATE\" title=\"{{ 'Create' | translate }}\">\n {{ 'Create' | translate }}\n </span>\n <span *ngIf=\"actionType === ActionType.EDIT\" title=\"{{ 'Save' | translate }}\">\n {{ 'Save' | translate }}\n </span>\n <span *ngIf=\"actionType === ActionType.DUPLICATE\" title=\"{{ 'Duplicate' | translate }}\">\n {{ 'Duplicate' | translate }}\n </span>\n </span>\n </button>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.ReportsService }, { type: i2.BsModalRef }, { type: i3.CronService }], propDecorators: { emitter: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZWR1bGUtbW9kYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vcmVwb3J0cy9zY2hlZHVsZS1tb2RhbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi9yZXBvcnRzL3NjaGVkdWxlLW1vZGFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN4RSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxFQUFZLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBRXBFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7Ozs7Ozs7OztBQU1uRCxNQUFNLE9BQU8sc0JBQXNCO0lBMEJqQyxZQUNTLGNBQThCLEVBQzlCLFFBQW9CLEVBQ25CLFdBQXdCO1FBRnpCLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixhQUFRLEdBQVIsUUFBUSxDQUFZO1FBQ25CLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBMUJ4QixZQUFPLEdBQWlDLElBQUksWUFBWSxFQUFFLENBQUM7UUFHckUsZUFBVSxHQUFHLFVBQVUsQ0FBQztRQUN4QixtQkFBYyxHQUFHLFdBQVcsQ0FBQztRQUM3QixjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQ2xCLG1CQUFjLEdBQW1CO1lBQy9CLE9BQU8sRUFBRSxLQUFLO1lBQ2QsT0FBTyxFQUFFLEVBQUU7WUFDWCxRQUFRLEVBQUUsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVB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Q0FBQztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTztZQUN6QyxDQUFDLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUM7WUFDakQsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsUUFBUTtZQUMzQyxDQUFDLENBQUMsSUFBSSxDQUFDLDRCQUE0QixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUM7WUFDbEQsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3RELElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDO1FBQ3RELElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQ2xELENBQUM7K0dBdkhVLHNCQUFzQjttR0FBdEIsc0JBQXNCLHVGQ2JuQyxndUxBaUtBOzs0RkRwSmEsc0JBQXNCO2tCQUpsQyxTQUFTOytCQUNFLGdCQUFnQjtzSUFNaEIsT0FBTztzQkFBaEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQnNNb2RhbFJlZiB9IGZyb20gJ25neC1ib290c3RyYXAvbW9kYWwnO1xuaW1wb3J0IHsgU2NoZWR1bGUsIEFjdGlvblR5cGUgfSBmcm9tICcuL2V4cG9ydC1zY2hlZHVsZXMuaW50ZXJmYWNlJztcbmltcG9ydCB7IEVtaXR0ZWRDcm9uLCBFbWl0dGVyUGF5bG9hZCB9IGZyb20gJy4vZXhwb3J0LXNjaGVkdWxlcy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ3JvblNlcnZpY2UgfSBmcm9tICcuL2Nyb24uc2VydmljZSc7XG5pbXBvcnQgeyBjbG9uZURlZXAgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgZ2V0dGV4dCB9IGZyb20gJ0BjOHkvbmd4LWNvbXBvbmVudHMnO1xuaW1wb3J0IHsgUmVwb3J0c1NlcnZpY2UgfSBmcm9tICcuL3JlcG9ydHMuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3NjaGVkdWxlLW1vZGFsJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3NjaGVkdWxlLW1vZGFsLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBTY2hlZHVsZU1vZGFsQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgc2NoZWR1bGU6IFNjaGVkdWxlO1xuICBvbGRTY2hlZHVsZTogU2NoZWR1bGU7XG4gIEBPdXRwdXQoKSBlbWl0dGVyOiBFdmVudEVtaXR0ZXI8RW1pdHRlclBheWxvYWQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBleHBvcnRJZDogbnVtYmVyO1xuICBhY3Rpb25UeXBlOiBBY3Rpb25UeXBlO1xuICBBY3Rpb25UeXBlID0gQWN0aW9uVHlwZTtcbiAgY3JvbkV4cHJlc3Npb24gPSAnKiAqICogKiAqJztcbiAgdmFsaWRDcm9uID0gZmFsc2U7XG4gIGVtaXR0ZXJQYXlsb2FkOiBFbWl0dGVyUGF5bG9hZCA9IHtcbiAgICBzdWNjZXNzOiBmYWxzZSxcbiAgICBtZXNzYWdlOiAnJyxcbiAgICBzY2hlZHVsZTogeyB0aW1lc3RhbXA6IHVuZGVmaW5lZCwgZW1haWxDb25maWc6IHVuZGVmaW5lZCwgY3JvbkNvbmZpZzogdW5kZWZpbmVkIH1cbiAgfTtcblxuICBlbWFpbFRvOiBzdHJpbmc7XG4gIGVtYWlsQ2M6IHN0cmluZztcbiAgZW1haWxCY2M6IHN0cmluZztcbiAgZW1haWxSZXBseVRvOiBzdHJpbmc7XG4gIGVtYWlsU3ViamVjdDogc3RyaW5nO1xuICBlbWFpbFRleHQ6IHN0cmluZztcblxuICBwbGFjZWhvbGRlcnNJbmZvID0gZ2V0dGV4dChcbiAgICAnQXZhaWxhYmxlIHBsYWNlaG9sZGVyczoge3RlbmFudC1kb21haW59LCB7aG9zdH0sIHtiaW5hcnlJZH0uIFdob2xlIGxpbmsgdG8gZG93bmxvYWRhYmxlIGZpbGUgaXM6IHt0ZW5hbnQtZG9tYWlufS9pbnZlbnRvcnkvYmluYXJpZXMve2JpbmFyeUlkfS4nXG4gICk7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHJlcG9ydHNTZXJ2aWNlOiBSZXBvcnRzU2VydmljZSxcbiAgICBwdWJsaWMgbW9kYWxSZWY6IEJzTW9kYWxSZWYsXG4gICAgcHJpdmF0ZSBjcm9uU2VydmljZTogQ3JvblNlcnZpY2VcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMub2xkU2NoZWR1bGUgPSBjbG9uZURlZXAodGhpcy5zY2hlZHVsZSk7XG4gICAgdGhpcy5wb3B1bGF0ZUVtYWlsRmllbGRzRnJvbVNjaGVkdWxlKHRoaXMuc2NoZWR1bGUpO1xuICAgIHRoaXMuY3JvbkV4cHJlc3Npb24gPSB0aGlzLmNyb25TZXJ2aWNlLmdlbmVyYXRlQ3Jvbih0aGlzLnNjaGVkdWxlLmNyb25Db25maWcpO1xuICAgIHRoaXMudmFsaWRDcm9uID0gdGhpcy5jcm9uU2VydmljZS52YWxpZGF0ZU1vZGVscyhcbiAgICAgIHRoaXMuY3JvblNlcnZpY2UuZ2V0QmFzZSh0aGlzLnNjaGVkdWxlLmNyb25Db25maWcpLFxuICAgICAgdGhpcy5zY2hlZHVsZS5jcm9uQ29uZmlnXG4gICAgKTtcbiAgfVxuXG4gIHBvcHVsYXRlRW1haWxGaWVsZHNGcm9tU2NoZWR1bGUoc2NoZWR1bGU6IFNjaGVkdWxlKSB7XG4gICAgaWYgKHNjaGVkdWxlLmVtYWlsQ29uZmlnLnRvICYmIHNjaGVkdWxlLmVtYWlsQ29uZmlnLnRvLmxlbmd0aCkge1xuICAgICAgdGhpcy5lbWFpbFRvID0gc2NoZWR1bGUuZW1haWxDb25maWcudG8udG9TdHJpbmcoKTtcbiAgICB9XG4gICAgaWYgKHNjaGVkdWxlLmVtYWlsQ29uZmlnLmNjICYmIHNjaGVkdWxlLmVtYWlsQ29uZmlnLmNjLmxlbmd0aCkge1xuICAgICAgdGhpcy5lbWFpbENjID0gc2NoZWR1bGUuZW1haWxDb25maWcuY2MudG9TdHJpbmcoKTtcbiAgICB9XG4gICAgaWYgKHNjaGVkdWxlLmVtYWlsQ29uZmlnLmJjYyAmJiBzY2hlZHVsZS5lbWFpbENvbmZpZy5iY2MubGVuZ3RoKSB7XG4gICAgICB0aGlzLmVtYWlsQmNjID0gc2NoZWR1bGUuZW1haWxDb25maWcuYmNjLnRvU3RyaW5nKCk7XG4gICAgfVxuICAgIGlmIChzY2hlZHVsZS5lbWFpbENvbmZpZy5yZXBseVRvKSB7XG4gICAgICB0aGlzLmVtYWlsUmVwbHlUbyA9IHNjaGVkdWxlLmVtYWlsQ29uZmlnLnJlcGx5VG87XG4gICAgfVxuICAgIGlmIChzY2hlZHVsZS5lbWFpbENvbmZpZy5zdWJqZWN0KSB7XG4gICAgICB0aGlzLmVtYWlsU3ViamVjdCA9IHNjaGVkdWxlLmVtYWlsQ29uZmlnLnN1YmplY3Q7XG4gICAgfVxuICAgIGlmIChzY2hlZHVsZS5lbWFpbENvbmZpZy50ZXh0KSB7XG4gICAgICB0aGlzLmVtYWlsVGV4dCA9IHNjaGVkdWxlLmVtYWlsQ29uZmlnLnRleHQ7XG4gICAgfVxuICB9XG5cbiAgc2F2ZSgpIHtcbiAgICB0aGlzLnBvcHVsYXRlU2NoZWR1bGVGcm9tQ3JvbkV4cHJlc3Npb24oKTtcbiAgICB0aGlzLnBvcHVsYXRlU2NoZWR1bGVGcm9tRW1haWxGaWVsZHMoKTtcbiAgICBpZiAodGhpcy5hY3Rpb25UeXBlID09PSBBY3Rpb25UeXBlLkNSRUFURSB8fCB0aGlzLmFjdGlvblR5cGUgPT09IEFjdGlvblR5cGUuRFVQTElDQVRFKSB7XG4gICAgICBjb25zdCBkYXRlID0gbmV3IERhdGUoKTtcbiAgICAgIGNvbnN0IHRpbWVzdGFtcCA9IGRhdGUuZ2V0VGltZSgpO1xuICAgICAgdGhpcy5zY2hlZHVsZS50aW1lc3RhbXAgPSB0aW1lc3RhbXA7XG4gICAgfVxuICAgIHRoaXMuZW1pdHRlclBheWxvYWQuc3VjY2VzcyA9IHRydWU7XG4gICAgdGhpcy5lbWl0dGVyUGF5bG9hZC5zY2hlZHVsZSA9IHRoaXMuc2NoZWR1bGU7XG4gICAgdGhpcy5tb2RhbFJlZi5oaWRlKCk7XG4gICAgLy8gc2lnbmFsIHRvIHRoZSBwYXJlbnQgY29tcG9uZW50IHRvIHVwZGF0ZSBsaXN0XG4gICAgdGhpcy5lbWl0dGVyLmVtaXQodGhpcy5lbWl0dGVyUGF5bG9hZCk7XG4gIH1cblxuICBjYW5jZWwoKSB7XG4gICAgdGhpcy5tb2RhbFJlZi5oaWRlKCk7XG4gIH1cblxuICBnZXRDcm9uKGNyb246IEVtaXR0ZWRDcm9uKSB7XG4gICAgdGhpcy52YWxpZENyb24gPSBjcm9uLnZhbGlkO1xuICAgIGlmIChjcm9uLnZhbGlkKSB7XG4gICAgICB0aGlzLmNyb25FeHByZXNzaW9uID0gY3Jvbi5jcm9uO1xuICAgIH1cbiAgfVxuXG4gIHBvcHVsYXRlU2NoZWR1bGVGcm9tQ3JvbkV4cHJlc3Npb24oKSB7XG4gICAgdGhpcy5zY2hlZHVsZS5jcm9uQ29uZmlnID0gdGhpcy5jcm9uU2VydmljZS5nZW5lcmF0ZUNyb25Db25maWcodGhpcy5jcm9uRXhwcmVzc2lvbik7XG4gIH1cblxuICBjb252ZXJ0U3RyaW5nT2ZFbWFpbHNUb0FycmF5KHN0cmluZ09mRW1haWxzOiBzdHJpbmcpIHtcbiAgICBjb25zdCBhcnIgPSBbXTtcbiAgICBpZiAoc3RyaW5nT2ZFbWFpbHMpIHtcbiAgICAgIGNvbnN0IHBhcnRzID0gc3RyaW5nT2ZFbWFpbHMuc3BsaXQoJywnKTtcbiAgICAgIHBhcnRzLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgICAgYXJyLnB1c2goaXRlbSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xuICB9XG5cbiAgcG9wdWxhdGVTY2hlZHVsZUZyb21FbWFpbEZpZWxkcygpIHtcbiAgICB0aGlzLnNjaGVkdWxlLmVtYWlsQ29uZmlnLnRvID0gdGhpcy5lbWFpbFRvXG4gICAgICA/IHRoaXMuY29udmVydFN0cmluZ09mRW1haWxzVG9BcnJheSh0aGlzLmVtYWlsVG8pXG4gICAgICA6IG51bGw7XG4gICAgdGhpcy5zY2hlZHVsZS5lbWFpbENvbmZpZy5jYyA9IHRoaXMuZW1haWxDY1xuICAgICAgPyB0aGlzLmNvbnZlcnRTdHJpbmdPZkVtYWlsc1RvQXJyYXkodGhpcy5lbWFpbENjKVxuICAgICAgOiBudWxsO1xuICAgIHRoaXMuc2NoZWR1bGUuZW1haWxDb25maWcuYmNjID0gdGhpcy5lbWFpbEJjY1xuICAgICAgPyB0aGlzLmNvbnZlcnRTdHJpbmdPZkVtYWlsc1RvQXJyYXkodGhpcy5lbWFpbEJjYylcbiAgICAgIDogbnVsbDtcbiAgICB0aGlzLnNjaGVkdWxlLmVtYWlsQ29uZmlnLnJlcGx5VG8gPSB0aGlzLmVtYWlsUmVwbHlUbztcbiAgICB0aGlzLnNjaGVkdWxlLmVtYWlsQ29uZmlnLnN1YmplY3QgPSB0aGlzLmVtYWlsU3ViamVjdDtcbiAgICB0aGlzLnNjaGVkdWxlLmVtYWlsQ29uZmlnLnRleHQgPSB0aGlzLmVtYWlsVGV4dDtcbiAgfVxufVxuIiwiPGRpdiBjbGFzcz1cIm1vZGFsLWhlYWRlciBkaWFsb2ctaGVhZGVyXCI+XG4gIDxpIGM4eUljb249XCJjOHktcmVwb3J0XCI+PC9pPlxuICA8aDQgaWQ9XCJtb2RhbC10aXRsZVwiPlxuICAgIDxzcGFuICpuZ0lmPVwiYWN0aW9uVHlwZSA9PT0gQWN0aW9uVHlwZS5DUkVBVEVcIiB0cmFuc2xhdGU+TmV3IGV4cG9ydCBzY2hlZHVsZTwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cImFjdGlvblR5cGUgPT09IEFjdGlvblR5cGUuRURJVFwiIHRyYW5zbGF0ZT5FZGl0IGV4cG9ydCBzY2hlZHVsZTwvc3Bhbj5cbiAgICA8c3BhbiAqbmdJZj1cImFjdGlvblR5cGUgPT09IEFjdGlvblR5cGUuRFVQTElDQVRFXCIgdHJhbnNsYXRlPkR1cGxpY2F0ZSBleHBvcnQgc2NoZWR1bGU8L3NwYW4+XG4gIDwvaDQ+XG48L2Rpdj5cblxuPGRpdiBjbGFzcz1cIm1vZGFsLWJvZHlcIiBpZD1cIm1vZGFsLWJvZHlcIj5cbiAgPHAgY2xhc3M9XCJsZWFkIHRleHQtY2VudGVyIHAtdC0yNCBtLWItMFwiIHRyYW5zbGF0ZT5PbiBzY2hlZHVsZSBzZW5kIGV4cG9ydCB2aWEgZW1haWw8L3A+XG48L2Rpdj5cbjxkaXYgY2xhc3M9XCJtb2RhbC1pbm5lci1zY3JvbGwgc21hcnQtcnVsZS1jb250cm9sXCI+XG4gIDxmb3JtICNzY2hlZHVsZUZvcm09XCJuZ0Zvcm1cIiBjbGFzcz1cImVkaXQtc21hcnQtcnVsZS1kZXRhaWxzXCI+XG4gICAgPGRpdiBjbGFzcz1cImxpc3QtZ3JvdXBcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctbGV2ZWwtMVwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwic21hcnQtbGlzdC1pY29uLWxhYmVsXCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJkb3QgYmctcHJpbWFyeS1saWdodCBtLXItOFwiPjE8L3NwYW4+XG4gICAgICAgICAgPHN0cm9uZyB0cmFuc2xhdGU+RnJlcXVlbmN5PC9zdHJvbmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC10LTE2XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICAgIDxjcm9uIFtjcm9uSW5dPVwiY3JvbkV4cHJlc3Npb25cIiAoZW1pdHRlcik9XCJnZXRDcm9uKCRldmVudClcIiBuYW1lPVwiY3JvblwiPjwvY3Jvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW1cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInNtYXJ0LWxpc3QtaWNvbi1sYWJlbFwiPlxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZG90IGJnLXByaW1hcnktbGlnaHQgbS1yLThcIj4yPC9zcGFuPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWlubGluZS1ibG9ja1wiPlxuICAgICAgICAgICAgPHN0cm9uZyB0cmFuc2xhdGU+U2VuZCBlbWFpbDwvc3Ryb25nPlxuICAgICAgICAgICAgPHAgY2xhc3M9XCJoZWxwLWJsb2NrIHRleHQtbXV0ZWQgc21hbGwgcC1hYnNvbHV0ZVwiPlxuICAgICAgICAgICAgICA8aSBjbGFzcz1cInRleHQtaW5mbyBtLXItNCB0ZXh0LTE0XCIgYzh5SWNvbj1cImluZm8tY2lyY2xlXCI+PC9pPlxuICAgICAgICAgICAgICA8c3BhbiB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICA+RW50ZXIgb25lIG9yIG1vcmUgdmFsaWQgZW1haWwgYWRkcmVzc2VzLCBzZXBhcmF0ZWQgd2l0aCBhIGNvbW1hLjwvc3BhblxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICA8L3A+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwicC10LTI0XCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbnRyb2wtbGFiZWxcIiB0cmFuc2xhdGU+U2VuZCB0bzwvbGFiZWw+XG4gICAgICAgICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIGVtYWlsc1xuICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICAgICAgbmFtZT1cInRvXCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVtYWlsVG9cIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3tcbiAgICAgICAgICAgICAgICAgICdlLmcuIGpvZS5kb2VAZXhhbXBsZS5jb20sam9obi5zbWl0aEBleGFtcGxlLmNvbWBMT0NBTElaRWAnIHwgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgfX1cIlxuICAgICAgICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbnRyb2wtbGFiZWxcIiB0cmFuc2xhdGU+Q0M8L2xhYmVsPlxuICAgICAgICAgICAgPGM4eS1mb3JtLWdyb3VwPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBlbWFpbHNcbiAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgc3BhblwiXG4gICAgICAgICAgICAgICAgbmFtZT1cImNjXCJcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7XG4gICAgICAgICAgICAgICAgICAnZS5nLiBqb2UuZG9lQGV4YW1wbGUuY29tLGpvaG4uc21pdGhAZXhhbXBsZS5jb21gTE9DQUxJWkVgJyB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICAgIH19XCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVtYWlsQ2NcIlxuICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC9jOHktZm9ybS1ncm91cD5cbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJjb250cm9sLWxhYmVsXCIgdHJhbnNsYXRlPkJDQzwvbGFiZWw+XG4gICAgICAgICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIGVtYWlsc1xuICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBzcGFuXCJcbiAgICAgICAgICAgICAgICBuYW1lPVwiYmNjXCJcbiAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7XG4gICAgICAgICAgICAgICAgICAnZS5nLiBqb2UuZG9lQGV4YW1wbGUuY29tLGpvaG4uc21pdGhAZXhhbXBsZS5jb21gTE9DQUxJWkVgJyB8IHRyYW5zbGF0ZVxuICAgICAgICAgICAgICAgIH19XCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVtYWlsQmNjXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiY29udHJvbC1sYWJlbFwiIHRyYW5zbGF0ZT5SZXBseSB0byAoc2luZ2xlIGVtYWlsIGFkZHJlc3MpPC9sYWJlbD5cbiAgICAgICAgICAgIDxjOHktZm9ybS1ncm91cD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgZW1haWxcbiAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgc3BhblwiXG4gICAgICAgICAgICAgICAgbmFtZT1cInJlcGx5VG9cIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ2UuZy4gam9lLmRvZUBleGFtcGxlLmNvbWBMT0NBTElaRWAnIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVtYWlsUmVwbHlUb1wiXG4gICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImNvbnRyb2wtbGFiZWxcIiB0cmFuc2xhdGU+U3ViamVjdDwvbGFiZWw+XG4gICAgICAgICAgICA8Yzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbCBzcGFuXCJcbiAgICAgICAgICAgICAgICBuYW1lPVwic3ViamVjdFwiXG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJlbWFpbFN1YmplY3RcIlxuICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3sgJ2UuZy4gRGFpbHkgcmVwb3J0JyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiY29udHJvbC1sYWJlbFwiIHRyYW5zbGF0ZT5NZXNzYWdlPC9sYWJlbD5cbiAgICAgICAgICAgIDxjOHktZm9ybS1ncm91cD5cbiAgICAgICAgICAgICAgPHRleHRhcmVhXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImVtYWlsVGV4dFwiXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJ7eyAnTWVzc2FnZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgICAgIHJvd3M9XCI0XCJcbiAgICAgICAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAgICAgICA+PC90ZXh0YXJlYT5cbiAgICAgICAgICAgICAgPHAgY2xhc3M9XCJoZWxwLWJsb2NrIHRleHQtbXV0ZWRcIj5cbiAgICAgICAgICAgICAgICB7eyBwbGFjZWhvbGRlcnNJbmZvIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgIDwvYzh5LWZvcm0tZ3JvdXA+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIDwvZm9ybT5cbjwvZGl2PlxuXG48ZGl2IGNsYXNzPVwibW9kYWwtZm9vdGVyXCI+XG4gIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLWRlZmF1bHRcIiAoY2xpY2spPVwiY2FuY2VsKClcIiB0aXRsZT1cInt7ICdDYW5jZWwnIHwgdHJhbnNsYXRlIH19XCI+XG4gICAge3sgJ0NhbmNlbCcgfCB0cmFuc2xhdGUgfX1cbiAgPC9idXR0b24+XG4gIDxidXR0b25cbiAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiXG4gICAgKGNsaWNrKT1cInNhdmUoKVwiXG4gICAgW2Rpc2FibGVkXT1cIiF2YWxpZENyb24gfHwgIXNjaGVkdWxlRm9ybS5mb3JtLnZhbGlkXCJcbiAgPlxuICAgIDxzcGFuPlxuICAgICAgPHNwYW4gKm5nSWY9XCJhY3Rpb25UeXBlID09PSBBY3Rpb25UeXBlLkNSRUFURVwiIHRpdGxlPVwie3sgJ0NyZWF0ZScgfCB0cmFuc2xhdGUgfX1cIj5cbiAgICAgICAge3sgJ0NyZWF0ZScgfCB0cmFuc2xhdGUgfX1cbiAgICAgIDwvc3Bhbj5cbiAgICAgIDxzcGFuICpuZ0lmPVwiYWN0aW9uVHlwZSA9PT0gQWN0aW9uVHlwZS5FRElUXCIgdGl0bGU9XCJ7eyAnU2F2ZScgfCB0cmFuc2xhdGUgfX1cIj5cbiAgICAgICAge3sgJ1NhdmUnIHwgdHJhbnNsYXRlIH19XG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cImFjdGlvblR5cGUgPT09IEFjdGlvblR5cGUuRFVQTElDQVRFXCIgdGl0bGU9XCJ7eyAnRHVwbGljYXRlJyB8IHRyYW5zbGF0ZSB9fVwiPlxuICAgICAgICB7eyAnRHVwbGljYXRlJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgPC9zcGFuPlxuICAgIDwvc3Bhbj5cbiAgPC9idXR0b24+XG48L2Rpdj5cbiJdfQ==