kwikid-agent-dashboard
Version:
KwikID's EKYC Agent Map View Module.
202 lines • 39 kB
JavaScript
import { __awaiter } from "tslib";
/* eslint-disable no-magic-numbers */
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { FormControl, FormGroup } from "@angular/forms";
import { getObjectDeepCopy, isNotEmptyValue } from "kwikid-toolkit";
import { TuiDay, TuiDayRange } from "@taiga-ui/cdk";
import { convertKwikUIDateToStringFormat, convertNormalDateToStringFormat } from "../../../v2/helpers/date.helplers";
import { sortItems } from "../../../v2/helpers/array.helper";
import * as i0 from "@angular/core";
import * as i1 from "../../services/google-maps.service";
import * as i2 from "../../services/open-street-maps.service";
import * as i3 from "../../services/agent.service";
import * as i4 from "kwikui";
import * as i5 from "@angular/cdk/scrolling";
import * as i6 from "../customer-tile/customer-tile.component";
import * as i7 from "@angular/forms";
import * as i8 from "@angular/common";
import * as i9 from "../../pipes/search-filter.pipe";
export class CustomerListComponent {
constructor(googleMapsService, openStreetMapsService, agentService
// eslint-disable-next-line no-empty-function
) {
this.googleMapsService = googleMapsService;
this.openStreetMapsService = openStreetMapsService;
this.agentService = agentService;
this.nextStep = new EventEmitter();
this.removeTask = new EventEmitter();
this.filterTaskList = new EventEmitter();
this.filteredData = [];
this.formGroup = new FormGroup({});
this.sortInAscendingOrder = true;
this.max = new TuiDay(new Date().getFullYear(), new Date().getMonth(), new Date().getDate());
// Sorting Variables
this.sortFilterKey = "";
this.sortFilterOptions = ["user_id", "session_status"];
this.activeSearchAction = undefined;
this.onClickPerformAction = new EventEmitter();
}
ngOnInit() {
return __awaiter(this, void 0, void 0, function* () {
this.handleInitialDateRange();
this.handleSearchAndSortFormControls();
});
}
handleOnClickSearchType(type) {
if (this.activeSearchAction !== type) {
this.activeSearchAction = type;
}
else {
this.activeSearchAction = undefined;
}
}
handleInitialDateRange() {
var _a, _b, _c, _d, _e, _f;
const searchFilterStartPoint = (_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.extendedFlags) === null || _b === void 0 ? void 0 : _b.searchFilterStartPoint) !== null && _c !== void 0 ? _c : {
day: 0,
month: 0,
year: 0
};
const currentDate = new Date();
const startDate = new Date((_d = currentDate.getFullYear() - (searchFilterStartPoint === null || searchFilterStartPoint === void 0 ? void 0 : searchFilterStartPoint.year)) !== null && _d !== void 0 ? _d : 0, (_e = currentDate.getMonth() - (searchFilterStartPoint === null || searchFilterStartPoint === void 0 ? void 0 : searchFilterStartPoint.month)) !== null && _e !== void 0 ? _e : 0, (_f = currentDate.getDate() - (searchFilterStartPoint === null || searchFilterStartPoint === void 0 ? void 0 : searchFilterStartPoint.day)) !== null && _f !== void 0 ? _f : 0);
this.fromDate = convertNormalDateToStringFormat(startDate);
this.toDate = convertNormalDateToStringFormat(null);
this.searchDateFormControl = new FormControl({
value: new TuiDayRange(new TuiDay(startDate.getFullYear(), startDate.getMonth(), startDate.getDate()), this.max),
disabled: false
});
this.formGroup.addControl("search-date", this.searchDateFormControl);
}
handleSearchAndSortFormControls() {
var _a, _b, _c;
this.searchTextFormControl = new FormControl("");
this.formGroup.addControl("search-text", this.searchTextFormControl);
this.sortFilterKeyFormControl = new FormControl("");
this.formGroup.addControl("sort-filter", this.sortFilterKeyFormControl);
this.sortFilterOptions =
(_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.extendedFlags) === null || _b === void 0 ? void 0 : _b.sortFilterKeys) !== null && _c !== void 0 ? _c : this.sortFilterOptions;
}
setUpMaps() {
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function* () {
if ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.maps) === null || _b === void 0 ? void 0 : _b.isShowMaps) {
if (((_d = (_c = this.config) === null || _c === void 0 ? void 0 : _c.maps) === null || _d === void 0 ? void 0 : _d.mapType) === "open-street") {
yield this.openStreetMapsService.initializeMap();
}
else {
yield this.googleMapsService.initializeMap();
}
}
});
}
setCustomersList() {
var _a, _b;
return __awaiter(this, void 0, void 0, function* () {
if ((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.maps) === null || _b === void 0 ? void 0 : _b.isShowMaps) {
this.filteredData = yield this.plotMarkers(this.customers);
}
else {
this.filteredData = this.customers;
}
});
}
ngAfterViewInit() {
var _a, _b, _c;
this.maxLength =
(_c = (_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.extendedFlags) === null || _b === void 0 ? void 0 : _b.searchFilterThreshold) !== null && _c !== void 0 ? _c : this.maxLength;
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
yield this.setUpMaps();
yield this.setCustomersList();
}), 1000);
}
ngOnChanges() {
return __awaiter(this, void 0, void 0, function* () {
yield this.setCustomersList();
});
}
handleOnClickNext(e) {
this.nextStep.emit(e);
}
plotMarkers(customers) {
var _a, _b, _c, _d;
return __awaiter(this, void 0, void 0, function* () {
if (!((_b = (_a = this.config) === null || _a === void 0 ? void 0 : _a.utilityFlags) === null || _b === void 0 ? void 0 : _b.isPlotCompletedTaskMarkers)) {
customers = customers.filter((customer) => {
return this.agentService.canPlotMarkers(customer.session_status);
});
}
if (((_d = (_c = this.config) === null || _c === void 0 ? void 0 : _c.maps) === null || _d === void 0 ? void 0 : _d.mapType) === "open-street") {
customers =
yield this.openStreetMapsService.plotDirectionsForAllTasks(customers);
}
else {
customers =
yield this.googleMapsService.plotDirectionsForAllTasks(customers);
}
return customers;
});
}
handleOnChangeDateRange(event) {
this.handleChangeDateRangeFormat(event);
this.handleOnFilterTaskList({
from_date: this.fromDate,
to_date: this.toDate
});
}
handleOnClickChangeSortOrder() {
this.sortInAscendingOrder = !this.sortInAscendingOrder;
this.handleOnChangeSortFilter(false);
}
handleOnChangeSortFilter(event) {
if (event && isNotEmptyValue(event.value)) {
this.sortFilterKey = event.value;
this.handleOnSortTaskItems(this.sortFilterKey, this.sortInAscendingOrder);
}
}
handleOnSortTaskItems(key, order) {
const sortedTaskItems = sortItems(this.filteredData, key, order);
this.filteredData = getObjectDeepCopy(sortedTaskItems);
}
handleChangeDateRangeFormat(event) {
var _a, _b;
if (((_a = event.value) === null || _a === void 0 ? void 0 : _a.from) && ((_b = event.value) === null || _b === void 0 ? void 0 : _b.to)) {
this.fromDate = convertKwikUIDateToStringFormat(event.value.from);
this.toDate = convertKwikUIDateToStringFormat(event.value.to);
}
}
handleOnChangeSearchText(event) {
this.searchText = event.value;
}
handleOnClickRemoveTask(task) {
this.removeTask.emit(task);
}
handleOnFilterTaskList(filter) {
this.filterTaskList.emit(filter);
}
handleOnClickPerformAction(event) {
this.onClickPerformAction.emit(event);
}
}
/** @nocollapse */ CustomerListComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: CustomerListComponent, deps: [{ token: i1.GoogleMapsService }, { token: i2.OpenStreetMapsService }, { token: i3.AgentService }], target: i0.ɵɵFactoryTarget.Component });
/** @nocollapse */ CustomerListComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: CustomerListComponent, selector: "customer-list", inputs: { customers: "customers", config: "config" }, outputs: { nextStep: "nextStep", removeTask: "removeTask", filterTaskList: "filterTaskList", onClickPerformAction: "onClickPerformAction" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"customer-list-wrapper\">\n <div\n class=\"customer-list-filter\"\n [formGroup]=\"formGroup\"\n >\n <div class=\"task-list-search-icons\">\n <kwikui-button\n appearance=\"mono\"\n icon=\"tuiIconSearchLarge\"\n size=\"s\"\n type=\"button\"\n (onClick)=\"handleOnClickSearchType('search-text')\"\n ></kwikui-button>\n <kwikui-button\n appearance=\"mono\"\n icon=\"tuiIconCalendarLarge\"\n size=\"s\"\n type=\"button\"\n (onClick)=\"handleOnClickSearchType('search-date')\"\n ></kwikui-button>\n <kwikui-button\n appearance=\"mono\"\n icon=\"tuiIconFilterLarge\"\n size=\"s\"\n type=\"button\"\n (onClick)=\"handleOnClickSearchType('sort-filter')\"\n ></kwikui-button>\n </div>\n\n <div\n class=\"task-list-search-action\"\n *ngIf=\"activeSearchAction\"\n >\n <kwikui-input-date-range\n *ngIf=\"activeSearchAction == 'search-date'\"\n class=\"task-list-date-box\"\n label=\"Search by Date Range\"\n id=\"dateRange\"\n size=\"m\"\n [max]=\"max\"\n [maxLength]=\"maxLength\"\n formControlName=\"search-date\"\n [formControl]=\"searchDateFormControl\"\n (getKeyValue)=\"handleOnChangeDateRange($event)\"\n ></kwikui-input-date-range>\n\n <kwikui-input\n *ngIf=\"activeSearchAction == 'search-text'\"\n label=\"Search\"\n id=\"search\"\n icon=\"tuiIconSearch\"\n placeholder=\"Search any task from here\"\n size=\"m\"\n [formControl]=\"searchTextFormControl\"\n formControlName=\"search-text\"\n (getKeyValue)=\"handleOnChangeSearchText($event)\"\n ></kwikui-input>\n\n <div\n *ngIf=\"activeSearchAction == 'sort-filter'\"\n class=\"task-list-sort-action\"\n >\n <kwikui-button\n appearance=\"outline\"\n [icon]=\"\n sortInAscendingOrder\n ? 'tuiIconChevronsUpLarge'\n : 'tuiIconChevronsDownLarge'\n \"\n size=\"m\"\n type=\"button\"\n (onClick)=\"handleOnClickChangeSortOrder()\"\n ></kwikui-button>\n <kwikui-input-select\n class=\"task-list-sort-key\"\n formControlName=\"sort-filter\"\n label=\"Sort By Key\"\n size=\"m\"\n [formControl]=\"sortFilterKeyFormControl\"\n [options]=\"sortFilterOptions\"\n [searchable]=\"false\"\n (getKeyValue)=\"handleOnChangeSortFilter($event)\"\n ></kwikui-input-select>\n </div>\n </div>\n </div>\n\n <div class=\"customer-task-list\">\n <cdk-virtual-scroll-viewport\n itemSize=\"1\"\n class=\"customer-task-list-scroll\"\n >\n <div\n *cdkVirtualFor=\"\n let customer of filteredData | filter: searchText;\n index as index\n \"\n >\n <customer-tile\n class=\"example-item\"\n [customer]=\"customer\"\n [config]=\"config\"\n [index]=\"index\"\n (nextStep)=\"handleOnClickNext($event)\"\n (removeTask)=\"handleOnClickRemoveTask($event)\"\n (onClickPerformAction)=\"handleOnClickPerformAction($event)\"\n ></customer-tile>\n </div>\n </cdk-virtual-scroll-viewport>\n </div>\n\n <div\n class=\"customer-list-empty\"\n *ngIf=\"filteredData.length === 0\"\n >\n No Tasks for the given Date.\n </div>\n</div>\n", styles: [".customer-list-wrapper{width:100%;height:100%;display:flex;flex-direction:column}.customer-list-filter{height:-moz-fit-content;height:fit-content;width:100%;display:flex;flex-direction:column;padding:1rem;grid-gap:.8rem;gap:.8rem;border-bottom:.5px solid #ddd}.customer-list-filter .task-list-search-icons{display:flex;justify-content:flex-end;align-items:center;flex-direction:row;grid-gap:.5rem;gap:.5rem}.customer-list-filter .task-list-search-action{margin-top:.5rem}.customer-list-filter .task-list-search-action .task-list-sort-action{display:flex;flex-direction:row;grid-gap:.5rem;gap:.5rem}.customer-list-filter .task-list-search-action .task-list-sort-action .task-list-sort-key{flex:1}.customer-list-empty{height:100%;width:100%;margin-top:.5rem;font-size:1rem;text-align:center}.customer-task-list{height:100%}.customer-task-list-scroll{height:100%;width:100%}.cdk-virtual-scroll-spacer{height:0!important}.example-item{height:50px}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{border-radius:10px}::-webkit-scrollbar-thumb{background:lightgray;border-radius:10px}::-webkit-scrollbar-thumb:hover{background:gray}\n"], components: [{ type: i4.KwikUIButtonComponent, selector: "kwikui-button", inputs: ["appearance", "class", "disabled", "icon", "iconRight", "id", "label", "shape", "showLoader", "size", "styles", "type", "pseudoHover"], outputs: ["onClick"] }, { type: i4.KwikUIInputDateRangeComponent, selector: "kwikui-input-date-range", inputs: ["disabled", "focus", "formControl", "formControlName", "hintContent", "icon", "id", "invalid", "label", "max", "maxLength", "min", "minLength", "placeholder", "postfix", "prefix", "properties", "size", "validators"], outputs: ["getKeyValue"] }, { type: i4.KwikUIInputComponent, selector: "kwikui-input", inputs: ["case", "disabled", "focus", "formControl", "formControlName", "hintContent", "icon", "id", "invalid", "label", "placeholder", "postfix", "prefix", "properties", "size", "type", "validators"], outputs: ["getKeyValue"] }, { type: i4.KwikUIInputSelectComponent, selector: "kwikui-input-select", inputs: ["disabled", "focus", "formControl", "formControlName", "hintContent", "icon", "id", "invalid", "label", "options", "placeholder", "properties", "searchable", "size", "validators"], outputs: ["getKeyValue"] }, { type: i5.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { type: i6.CustomerTileComponent, selector: "customer-tile", inputs: ["customer", "index", "config"], outputs: ["onClickPerformAction", "nextStep", "removeTask"] }], directives: [{ type: i7.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i7.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i7.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i7.FormControlDirective, selector: "[formControl]", inputs: ["disabled", "formControl", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { type: i5.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { type: i5.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }], pipes: { "filter": i9.Ng2SearchPipe } });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: CustomerListComponent, decorators: [{
type: Component,
args: [{
selector: "customer-list",
templateUrl: "./customer-list.component.html",
styleUrls: ["./customer-list.component.scss"]
}]
}], ctorParameters: function () { return [{ type: i1.GoogleMapsService }, { type: i2.OpenStreetMapsService }, { type: i3.AgentService }]; }, propDecorators: { customers: [{
type: Input
}], config: [{
type: Input
}], nextStep: [{
type: Output
}], removeTask: [{
type: Output
}], filterTaskList: [{
type: Output
}], onClickPerformAction: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3VzdG9tZXItbGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9rd2lraWQtYWdlbnQtZGFzaGJvYXJkL3NyYy9saWIvdjEvY29tcG9uZW50cy9jdXN0b21lci1saXN0L2N1c3RvbWVyLWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMva3dpa2lkLWFnZW50LWRhc2hib2FyZC9zcmMvbGliL3YxL2NvbXBvbmVudHMvY3VzdG9tZXItbGlzdC9jdXN0b21lci1saXN0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSxxQ0FBcUM7QUFDckMsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUlwRCxPQUFPLEVBQ0wsK0JBQStCLEVBQy9CLCtCQUErQixFQUNoQyxNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQzs7Ozs7Ozs7Ozs7QUFPN0QsTUFBTSxPQUFPLHFCQUFxQjtJQXNEaEMsWUFDUyxpQkFBb0MsRUFDcEMscUJBQTRDLEVBQzVDLFlBQTBCO0lBQ2pDLDZDQUE2Qzs7UUFIdEMsc0JBQWlCLEdBQWpCLGlCQUFpQixDQUFtQjtRQUNwQywwQkFBcUIsR0FBckIscUJBQXFCLENBQXVCO1FBQzVDLGlCQUFZLEdBQVosWUFBWSxDQUFjO1FBakRuQyxhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FB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RCx3QkFBd0IsQ0FBQyxLQUFLO1FBQzVCLElBQUksQ0FBQyxVQUFVLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQztJQUNoQyxDQUFDO0lBRUQsdUJBQXVCLENBQUMsSUFBSTtRQUMxQixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM3QixDQUFDO0lBRUQsc0JBQXNCLENBQUMsTUFBTTtRQUMzQixJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuQyxDQUFDO0lBRUQsMEJBQTBCLENBQUMsS0FBVTtRQUNuQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLENBQUM7O3NJQXROVSxxQkFBcUI7MEhBQXJCLHFCQUFxQiw2UUNuQmxDLDQ5R0FzSEE7NEZEbkdhLHFCQUFxQjtrQkFMakMsU0FBUzttQkFBQztvQkFDVCxRQUFRLEVBQUUsZUFBZTtvQkFDekIsV0FBVyxFQUFFLGdDQUFnQztvQkFDN0MsU0FBUyxFQUFFLENBQUMsZ0NBQWdDLENBQUM7aUJBQzlDO3VLQUdDLFNBQVM7c0JBRFIsS0FBSztnQkFJTixNQUFNO3NCQURMLEtBQUs7Z0JBSU4sUUFBUTtzQkFEUCxNQUFNO2dCQUlQLFVBQVU7c0JBRFQsTUFBTTtnQkFJUCxjQUFjO3NCQURiLE1BQU07Z0JBdUNQLG9CQUFvQjtzQkFEbkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIG5vLW1hZ2ljLW51bWJlcnMgKi9cbmltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25Jbml0LCBPdXRwdXQgfSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuaW1wb3J0IHsgZ2V0T2JqZWN0RGVlcENvcHksIGlzTm90RW1wdHlWYWx1ZSB9IGZyb20gXCJrd2lraWQtdG9vbGtpdFwiO1xuaW1wb3J0IHsgVHVpRGF5LCBUdWlEYXlSYW5nZSB9IGZyb20gXCJAdGFpZ2EtdWkvY2RrXCI7XG5pbXBvcnQgeyBHb29nbGVNYXBzU2VydmljZSB9IGZyb20gXCIuLi8uLi9zZXJ2aWNlcy9nb29nbGUtbWFwcy5zZXJ2aWNlXCI7XG5pbXBvcnQgeyBBZ2VudFNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vc2VydmljZXMvYWdlbnQuc2VydmljZVwiO1xuaW1wb3J0IHsgT3BlblN0cmVldE1hcHNTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uL3NlcnZpY2VzL29wZW4tc3RyZWV0LW1hcHMuc2VydmljZVwiO1xuaW1wb3J0IHtcbiAgY29udmVydEt3aWtVSURhdGVUb1N0cmluZ0Zvcm1hdCxcbiAgY29udmVydE5vcm1hbERhdGVUb1N0cmluZ0Zvcm1hdFxufSBmcm9tIFwiLi4vLi4vLi4vdjIvaGVscGVycy9kYXRlLmhlbHBsZXJzXCI7XG5pbXBvcnQgeyBzb3J0SXRlbXMgfSBmcm9tIFwiLi4vLi4vLi4vdjIvaGVscGVycy9hcnJheS5oZWxwZXJcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImN1c3RvbWVyLWxpc3RcIixcbiAgdGVtcGxhdGVVcmw6IFwiLi9jdXN0b21lci1saXN0LmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9jdXN0b21lci1saXN0LmNvbXBvbmVudC5zY3NzXCJdXG59KVxuZXhwb3J0IGNsYXNzIEN1c3RvbWVyTGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpXG4gIGN1c3RvbWVyczogYW55O1xuXG4gIEBJbnB1dCgpXG4gIGNvbmZpZzogYW55O1xuXG4gIEBPdXRwdXQoKVxuICBuZXh0U3RlcCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgcmVtb3ZlVGFzayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgZmlsdGVyVGFza0xpc3QgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgc2VhcmNoVGV4dDtcblxuICBsYXN0SW5mb1dpbmRvd09wZW5lZDogYW55O1xuXG4gIGZpbHRlcmVkRGF0YSA9IFtdO1xuXG4gIGZvcm1Hcm91cDogRm9ybUdyb3VwID0gbmV3IEZvcm1Hcm91cCh7fSk7XG5cbiAgc2VhcmNoVGV4dEZvcm1Db250cm9sOiBGb3JtQ29udHJvbDtcblxuICBzZWFyY2hEYXRlRm9ybUNvbnRyb2w6IEZvcm1Db250cm9sO1xuXG4gIHNvcnRGaWx0ZXJLZXlGb3JtQ29udHJvbDogRm9ybUNvbnRyb2w7XG5cbiAgc29ydEluQXNjZW5kaW5nT3JkZXIgPSB0cnVlO1xuXG4gIGZyb21EYXRlOiBzdHJpbmcgfCBEYXRlO1xuXG4gIHRvRGF0ZTogc3RyaW5nIHwgRGF0ZTtcblxuICBtYXg6IFR1aURheSA9IG5ldyBUdWlEYXkoXG4gICAgbmV3IERhdGUoKS5nZXRGdWxsWWVhcigpLFxuICAgIG5ldyBEYXRlKCkuZ2V0TW9udGgoKSxcbiAgICBuZXcgRGF0ZSgpLmdldERhdGUoKVxuICApO1xuXG4gIG1heExlbmd0aDogYW55O1xuXG4gIC8vIFNvcnRpbmcgVmFyaWFibGVzXG4gIHNvcnRGaWx0ZXJLZXkgPSBcIlwiO1xuXG4gIHNvcnRGaWx0ZXJPcHRpb25zID0gW1widXNlcl9pZFwiLCBcInNlc3Npb25fc3RhdHVzXCJdO1xuXG4gIGFjdGl2ZVNlYXJjaEFjdGlvbjogc3RyaW5nID0gdW5kZWZpbmVkO1xuXG4gIEBPdXRwdXQoKVxuICBvbkNsaWNrUGVyZm9ybUFjdGlvbjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgZ29vZ2xlTWFwc1NlcnZpY2U6IEdvb2dsZU1hcHNTZXJ2aWNlLFxuICAgIHB1YmxpYyBvcGVuU3RyZWV0TWFwc1NlcnZpY2U6IE9wZW5TdHJlZXRNYXBzU2VydmljZSxcbiAgICBwdWJsaWMgYWdlbnRTZXJ2aWNlOiBBZ2VudFNlcnZpY2VcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZW1wdHktZnVuY3Rpb25cbiAgKSB7fVxuXG4gIGFzeW5jIG5nT25Jbml0KCkge1xuICAgIHRoaXMuaGFuZGxlSW5pdGlhbERhdGVSYW5nZSgpO1xuICAgIHRoaXMuaGFuZGxlU2VhcmNoQW5kU29ydEZvcm1Db250cm9scygpO1xuICB9XG5cbiAgaGFuZGxlT25DbGlja1NlYXJjaFR5cGUodHlwZSkge1xuICAgIGlmICh0aGlzLmFjdGl2ZVNlYXJjaEFjdGlvbiAhPT0gdHlwZSkge1xuICAgICAgdGhpcy5hY3RpdmVTZWFyY2hBY3Rpb24gPSB0eXBlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmFjdGl2ZVNlYXJjaEFjdGlvbiA9IHVuZGVmaW5lZDtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVJbml0aWFsRGF0ZVJhbmdlKCkge1xuICAgIGNvbnN0IHNlYXJjaEZpbHRlclN0YXJ0UG9pbnQgPSB0aGlzLmNvbmZpZz8uZXh0ZW5kZWRGbGFnc1xuICAgICAgPy5zZWFyY2hGaWx0ZXJTdGFydFBvaW50ID8/IHtcbiAgICAgIGRheTogMCxcbiAgICAgIG1vbnRoOiAwLFxuICAgICAgeWVhcjogMFxuICAgIH07XG4gICAgY29uc3QgY3VycmVudERhdGUgPSBuZXcgRGF0ZSgpO1xuICAgIGNvbnN0IHN0YXJ0RGF0ZSA9IG5ldyBEYXRlKFxuICAgICAgY3VycmVudERhdGUuZ2V0RnVsbFllYXIoKSAtIHNlYXJjaEZpbHRlclN0YXJ0UG9pbnQ/LnllYXIgPz8gMCxcbiAgICAgIGN1cnJlbnREYXRlLmdldE1vbnRoKCkgLSBzZWFyY2hGaWx0ZXJTdGFydFBvaW50Py5tb250aCA/PyAwLFxuICAgICAgY3VycmVudERhdGUuZ2V0RGF0ZSgpIC0gc2VhcmNoRmlsdGVyU3RhcnRQb2ludD8uZGF5ID8/IDBcbiAgICApO1xuXG4gICAgdGhpcy5mcm9tRGF0ZSA9IGNvbnZlcnROb3JtYWxEYXRlVG9TdHJpbmdGb3JtYXQoc3RhcnREYXRlKTtcbiAgICB0aGlzLnRvRGF0ZSA9IGNvbnZlcnROb3JtYWxEYXRlVG9TdHJpbmdGb3JtYXQobnVsbCk7XG5cbiAgICB0aGlzLnNlYXJjaERhdGVGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbCh7XG4gICAgICB2YWx1ZTogbmV3IFR1aURheVJhbmdlKFxuICAgICAgICBuZXcgVHVpRGF5KFxuICAgICAgICAgIHN0YXJ0RGF0ZS5nZXRGdWxsWWVhcigpLFxuICAgICAgICAgIHN0YXJ0RGF0ZS5nZXRNb250aCgpLFxuICAgICAgICAgIHN0YXJ0RGF0ZS5nZXREYXRlKClcbiAgICAgICAgKSxcbiAgICAgICAgdGhpcy5tYXhcbiAgICAgICksXG4gICAgICBkaXNhYmxlZDogZmFsc2VcbiAgICB9KTtcbiAgICB0aGlzLmZvcm1Hcm91cC5hZGRDb250cm9sKFwic2VhcmNoLWRhdGVcIiwgdGhpcy5zZWFyY2hEYXRlRm9ybUNvbnRyb2wpO1xuICB9XG5cbiAgaGFuZGxlU2VhcmNoQW5kU29ydEZvcm1Db250cm9scygpIHtcbiAgICB0aGlzLnNlYXJjaFRleHRGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbChcIlwiKTtcbiAgICB0aGlzLmZvcm1Hcm91cC5hZGRDb250cm9sKFwic2VhcmNoLXRleHRcIiwgdGhpcy5zZWFyY2hUZXh0Rm9ybUNvbnRyb2wpO1xuXG4gICAgdGhpcy5zb3J0RmlsdGVyS2V5Rm9ybUNvbnRyb2wgPSBuZXcgRm9ybUNvbnRyb2woXCJcIik7XG4gICAgdGhpcy5mb3JtR3JvdXAuYWRkQ29udHJvbChcInNvcnQtZmlsdGVyXCIsIHRoaXMuc29ydEZpbHRlcktleUZvcm1Db250cm9sKTtcbiAgICB0aGlzLnNvcnRGaWx0ZXJPcHRpb25zID1cbiAgICAgIHRoaXMuY29uZmlnPy5leHRlbmRlZEZsYWdzPy5zb3J0RmlsdGVyS2V5cyA/PyB0aGlzLnNvcnRGaWx0ZXJPcHRpb25zO1xuICB9XG5cbiAgYXN5bmMgc2V0VXBNYXBzKCkge1xuICAgIGlmICh0aGlzLmNvbmZpZz8ubWFwcz8uaXNTaG93TWFwcykge1xuICAgICAgaWYgKHRoaXMuY29uZmlnPy5tYXBzPy5tYXBUeXBlID09PSBcIm9wZW4tc3RyZWV0XCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5vcGVuU3RyZWV0TWFwc1NlcnZpY2UuaW5pdGlhbGl6ZU1hcCgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgdGhpcy5nb29nbGVNYXBzU2VydmljZS5pbml0aWFsaXplTWFwKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgc2V0Q3VzdG9tZXJzTGlzdCgpIHtcbiAgICBpZiAodGhpcy5jb25maWc/Lm1hcHM/LmlzU2hvd01hcHMpIHtcbiAgICAgIHRoaXMuZmlsdGVyZWREYXRhID0gYXdhaXQgdGhpcy5wbG90TWFya2Vycyh0aGlzLmN1c3RvbWVycyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmlsdGVyZWREYXRhID0gdGhpcy5jdXN0b21lcnM7XG4gICAgfVxuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMubWF4TGVuZ3RoID1cbiAgICAgIHRoaXMuY29uZmlnPy5leHRlbmRlZEZsYWdzPy5zZWFyY2hGaWx0ZXJUaHJlc2hvbGQgPz8gdGhpcy5tYXhMZW5ndGg7XG4gICAgc2V0VGltZW91dChhc3luYygpID0+IHtcbiAgICAgIGF3YWl0IHRoaXMuc2V0VXBNYXBzKCk7XG4gICAgICBhd2FpdCB0aGlzLnNldEN1c3RvbWVyc0xpc3QoKTtcbiAgICB9LCAxMDAwKTtcbiAgfVxuXG4gIGFzeW5jIG5nT25DaGFuZ2VzKCkge1xuICAgIGF3YWl0IHRoaXMuc2V0Q3VzdG9tZXJzTGlzdCgpO1xuICB9XG5cbiAgaGFuZGxlT25DbGlja05leHQoZSkge1xuICAgIHRoaXMubmV4dFN0ZXAuZW1pdChlKTtcbiAgfVxuXG4gIGFzeW5jIHBsb3RNYXJrZXJzKGN1c3RvbWVycykge1xuICAgIGlmICghdGhpcy5jb25maWc/LnV0aWxpdHlGbGFncz8uaXNQbG90Q29tcGxldGVkVGFza01hcmtlcnMpIHtcbiAgICAgIGN1c3RvbWVycyA9IGN1c3RvbWVycy5maWx0ZXIoKGN1c3RvbWVyKSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmFnZW50U2VydmljZS5jYW5QbG90TWFya2VycyhjdXN0b21lci5zZXNzaW9uX3N0YXR1cyk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb25maWc/Lm1hcHM/Lm1hcFR5cGUgPT09IFwib3Blbi1zdHJlZXRcIikge1xuICAgICAgY3VzdG9tZXJzID1cbiAgICAgICAgYXdhaXQgdGhpcy5vcGVuU3RyZWV0TWFwc1NlcnZpY2UucGxvdERpcmVjdGlvbnNGb3JBbGxUYXNrcyhjdXN0b21lcnMpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjdXN0b21lcnMgPVxuICAgICAgICBhd2FpdCB0aGlzLmdvb2dsZU1hcHNTZXJ2aWNlLnBsb3REaXJlY3Rpb25zRm9yQWxsVGFza3MoY3VzdG9tZXJzKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY3VzdG9tZXJzO1xuICB9XG5cbiAgaGFuZGxlT25DaGFuZ2VEYXRlUmFuZ2UoZXZlbnQpIHtcbiAgICB0aGlzLmhhbmRsZUNoYW5nZURhdGVSYW5nZUZvcm1hdChldmVudCk7XG4gICAgdGhpcy5oYW5kbGVPbkZpbHRlclRhc2tMaXN0KHtcbiAgICAgIGZyb21fZGF0ZTogdGhpcy5mcm9tRGF0ZSxcbiAgICAgIHRvX2RhdGU6IHRoaXMudG9EYXRlXG4gICAgfSk7XG4gIH1cblxuICBoYW5kbGVPbkNsaWNrQ2hhbmdlU29ydE9yZGVyKCkge1xuICAgIHRoaXMuc29ydEluQXNjZW5kaW5nT3JkZXIgPSAhdGhpcy5zb3J0SW5Bc2NlbmRpbmdPcmRlcjtcbiAgICB0aGlzLmhhbmRsZU9uQ2hhbmdlU29ydEZpbHRlcihmYWxzZSk7XG4gIH1cblxuICBoYW5kbGVPbkNoYW5nZVNvcnRGaWx0ZXIoZXZlbnQ6IGFueSkge1xuICAgIGlmIChldmVudCAmJiBpc05vdEVtcHR5VmFsdWUoZXZlbnQudmFsdWUpKSB7XG4gICAgICB0aGlzLnNvcnRGaWx0ZXJLZXkgPSBldmVudC52YWx1ZTtcbiAgICAgIHRoaXMuaGFuZGxlT25Tb3J0VGFza0l0ZW1zKHRoaXMuc29ydEZpbHRlcktleSwgdGhpcy5zb3J0SW5Bc2NlbmRpbmdPcmRlcik7XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlT25Tb3J0VGFza0l0ZW1zKGtleSwgb3JkZXIpIHtcbiAgICBjb25zdCBzb3J0ZWRUYXNrSXRlbXMgPSBzb3J0SXRlbXModGhpcy5maWx0ZXJlZERhdGEsIGtleSwgb3JkZXIpO1xuICAgIHRoaXMuZmlsdGVyZWREYXRhID0gZ2V0T2JqZWN0RGVlcENvcHkoc29ydGVkVGFza0l0ZW1zKTtcbiAgfVxuXG4gIGhhbmRsZUNoYW5nZURhdGVSYW5nZUZvcm1hdChldmVudDogYW55KSB7XG4gICAgaWYgKGV2ZW50LnZhbHVlPy5mcm9tICYmIGV2ZW50LnZhbHVlPy50bykge1xuICAgICAgdGhpcy5mcm9tRGF0ZSA9IGNvbnZlcnRLd2lrVUlEYXRlVG9TdHJpbmdGb3JtYXQoZXZlbnQudmFsdWUuZnJvbSk7XG4gICAgICB0aGlzLnRvRGF0ZSA9IGNvbnZlcnRLd2lrVUlEYXRlVG9TdHJpbmdGb3JtYXQoZXZlbnQudmFsdWUudG8pO1xuICAgIH1cbiAgfVxuXG4gIGhhbmRsZU9uQ2hhbmdlU2VhcmNoVGV4dChldmVudCkge1xuICAgIHRoaXMuc2VhcmNoVGV4dCA9IGV2ZW50LnZhbHVlO1xuICB9XG5cbiAgaGFuZGxlT25DbGlja1JlbW92ZVRhc2sodGFzaykge1xuICAgIHRoaXMucmVtb3ZlVGFzay5lbWl0KHRhc2spO1xuICB9XG5cbiAgaGFuZGxlT25GaWx0ZXJUYXNrTGlzdChmaWx0ZXIpIHtcbiAgICB0aGlzLmZpbHRlclRhc2tMaXN0LmVtaXQoZmlsdGVyKTtcbiAgfVxuXG4gIGhhbmRsZU9uQ2xpY2tQZXJmb3JtQWN0aW9uKGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2xpY2tQZXJmb3JtQWN0aW9uLmVtaXQoZXZlbnQpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiY3VzdG9tZXItbGlzdC13cmFwcGVyXCI+XG4gIDxkaXZcbiAgICBjbGFzcz1cImN1c3RvbWVyLWxpc3QtZmlsdGVyXCJcbiAgICBbZm9ybUdyb3VwXT1cImZvcm1Hcm91cFwiXG4gID5cbiAgICA8ZGl2IGNsYXNzPVwidGFzay1saXN0LXNlYXJjaC1pY29uc1wiPlxuICAgICAgPGt3aWt1aS1idXR0b25cbiAgICAgICAgYXBwZWFyYW5jZT1cIm1vbm9cIlxuICAgICAgICBpY29uPVwidHVpSWNvblNlYXJjaExhcmdlXCJcbiAgICAgICAgc2l6ZT1cInNcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgKG9uQ2xpY2spPVwiaGFuZGxlT25DbGlja1NlYXJjaFR5cGUoJ3NlYXJjaC10ZXh0JylcIlxuICAgICAgPjwva3dpa3VpLWJ1dHRvbj5cbiAgICAgIDxrd2lrdWktYnV0dG9uXG4gICAgICAgIGFwcGVhcmFuY2U9XCJtb25vXCJcbiAgICAgICAgaWNvbj1cInR1aUljb25DYWxlbmRhckxhcmdlXCJcbiAgICAgICAgc2l6ZT1cInNcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgKG9uQ2xpY2spPVwiaGFuZGxlT25DbGlja1NlYXJjaFR5cGUoJ3NlYXJjaC1kYXRlJylcIlxuICAgICAgPjwva3dpa3VpLWJ1dHRvbj5cbiAgICAgIDxrd2lrdWktYnV0dG9uXG4gICAgICAgIGFwcGVhcmFuY2U9XCJtb25vXCJcbiAgICAgICAgaWNvbj1cInR1aUljb25GaWx0ZXJMYXJnZVwiXG4gICAgICAgIHNpemU9XCJzXCJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgIChvbkNsaWNrKT1cImhhbmRsZU9uQ2xpY2tTZWFyY2hUeXBlKCdzb3J0LWZpbHRlcicpXCJcbiAgICAgID48L2t3aWt1aS1idXR0b24+XG4gICAgPC9kaXY+XG5cbiAgICA8ZGl2XG4gICAgICBjbGFzcz1cInRhc2stbGlzdC1zZWFyY2gtYWN0aW9uXCJcbiAgICAgICpuZ0lmPVwiYWN0aXZlU2VhcmNoQWN0aW9uXCJcbiAgICA+XG4gICAgICA8a3dpa3VpLWlucHV0LWRhdGUtcmFuZ2VcbiAgICAgICAgKm5nSWY9XCJhY3RpdmVTZWFyY2hBY3Rpb24gPT0gJ3NlYXJjaC1kYXRlJ1wiXG4gICAgICAgIGNsYXNzPVwidGFzay1saXN0LWRhdGUtYm94XCJcbiAgICAgICAgbGFiZWw9XCJTZWFyY2ggYnkgRGF0ZSBSYW5nZVwiXG4gICAgICAgIGlkPVwiZGF0ZVJhbmdlXCJcbiAgICAgICAgc2l6ZT1cIm1cIlxuICAgICAgICBbbWF4XT1cIm1heFwiXG4gICAgICAgIFttYXhMZW5ndGhdPVwibWF4TGVuZ3RoXCJcbiAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwic2VhcmNoLWRhdGVcIlxuICAgICAgICBbZm9ybUNvbnRyb2xdPVwic2VhcmNoRGF0ZUZvcm1Db250cm9sXCJcbiAgICAgICAgKGdldEtleVZhbHVlKT1cImhhbmRsZU9uQ2hhbmdlRGF0ZVJhbmdlKCRldmVudClcIlxuICAgICAgPjwva3dpa3VpLWlucHV0LWRhdGUtcmFuZ2U+XG5cbiAgICAgIDxrd2lrdWktaW5wdXRcbiAgICAgICAgKm5nSWY9XCJhY3RpdmVTZWFyY2hBY3Rpb24gPT0gJ3NlYXJjaC10ZXh0J1wiXG4gICAgICAgIGxhYmVsPVwiU2VhcmNoXCJcbiAgICAgICAgaWQ9XCJzZWFyY2hcIlxuICAgICAgICBpY29uPVwidHVpSWNvblNlYXJjaFwiXG4gICAgICAgIHBsYWNlaG9sZGVyPVwiU2VhcmNoIGFueSB0YXNrIGZyb20gaGVyZVwiXG4gICAgICAgIHNpemU9XCJtXCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cInNlYXJjaFRleHRGb3JtQ29udHJvbFwiXG4gICAgICAgIGZvcm1Db250cm9sTmFtZT1cInNlYXJjaC10ZXh0XCJcbiAgICAgICAgKGdldEtleVZhbHVlKT1cImhhbmRsZU9uQ2hhbmdlU2VhcmNoVGV4dCgkZXZlbnQpXCJcbiAgICAgID48L2t3aWt1aS1pbnB1dD5cblxuICAgICAgPGRpdlxuICAgICAgICAqbmdJZj1cImFjdGl2ZVNlYXJjaEFjdGlvbiA9PSAnc29ydC1maWx0ZXInXCJcbiAgICAgICAgY2xhc3M9XCJ0YXNrLWxpc3Qtc29ydC1hY3Rpb25cIlxuICAgICAgPlxuICAgICAgICA8a3dpa3VpLWJ1dHRvblxuICAgICAgICAgIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCJcbiAgICAgICAgICBbaWNvbl09XCJcbiAgICAgICAgICAgIHNvcnRJbkFzY2VuZGluZ09yZGVyXG4gICAgICAgICAgICAgID8gJ3R1aUljb25DaGV2cm9uc1VwTGFyZ2UnXG4gICAgICAgICAgICAgIDogJ3R1aUljb25DaGV2cm9uc0Rvd25MYXJnZSdcbiAgICAgICAgICBcIlxuICAgICAgICAgIHNpemU9XCJtXCJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAob25DbGljayk9XCJoYW5kbGVPbkNsaWNrQ2hhbmdlU29ydE9yZGVyKClcIlxuICAgICAgICA+PC9rd2lrdWktYnV0dG9uPlxuICAgICAgICA8a3dpa3VpLWlucHV0LXNlbGVjdFxuICAgICAgICAgIGNsYXNzPVwidGFzay1saXN0LXNvcnQta2V5XCJcbiAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJzb3J0LWZpbHRlclwiXG4gICAgICAgICAgbGFiZWw9XCJTb3J0IEJ5IEtleVwiXG4gICAgICAgICAgc2l6ZT1cIm1cIlxuICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJzb3J0RmlsdGVyS2V5Rm9ybUNvbnRyb2xcIlxuICAgICAgICAgIFtvcHRpb25zXT1cInNvcnRGaWx0ZXJPcHRpb25zXCJcbiAgICAgICAgICBbc2VhcmNoYWJsZV09XCJmYWxzZVwiXG4gICAgICAgICAgKGdldEtleVZhbHVlKT1cImhhbmRsZU9uQ2hhbmdlU29ydEZpbHRlcigkZXZlbnQpXCJcbiAgICAgICAgPjwva3dpa3VpLWlucHV0LXNlbGVjdD5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L2Rpdj5cblxuICA8ZGl2IGNsYXNzPVwiY3VzdG9tZXItdGFzay1saXN0XCI+XG4gICAgPGNkay12aXJ0dWFsLXNjcm9sbC12aWV3cG9ydFxuICAgICAgaXRlbVNpemU9XCIxXCJcbiAgICAgIGNsYXNzPVwiY3VzdG9tZXItdGFzay1saXN0LXNjcm9sbFwiXG4gICAgPlxuICAgICAgPGRpdlxuICAgICAgICAqY2RrVmlydHVhbEZvcj1cIlxuICAgICAgICAgIGxldCBjdXN0b21lciBvZiBmaWx0ZXJlZERhdGEgfCBmaWx0ZXI6IHNlYXJjaFRleHQ7XG4gICAgICAgICAgaW5kZXggYXMgaW5kZXhcbiAgICAgICAgXCJcbiAgICAgID5cbiAgICAgICAgPGN1c3RvbWVyLXRpbGVcbiAgICAgICAgICBjbGFzcz1cImV4YW1wbGUtaXRlbVwiXG4gICAgICAgICAgW2N1c3RvbWVyXT1cImN1c3RvbWVyXCJcbiAgICAgICAgICBbY29uZmlnXT1cImNvbmZpZ1wiXG4gICAgICAgICAgW2luZGV4XT1cImluZGV4XCJcbiAgICAgICAgICAobmV4dFN0ZXApPVwiaGFuZGxlT25DbGlja05leHQoJGV2ZW50KVwiXG4gICAgICAgICAgKHJlbW92ZVRhc2spPVwiaGFuZGxlT25DbGlja1JlbW92ZVRhc2soJGV2ZW50KVwiXG4gICAgICAgICAgKG9uQ2xpY2tQZXJmb3JtQWN0aW9uKT1cImhhbmRsZU9uQ2xpY2tQZXJmb3JtQWN0aW9uKCRldmVudClcIlxuICAgICAgICA+PC9jdXN0b21lci10aWxlPlxuICAgICAgPC9kaXY+XG4gICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XG4gIDwvZGl2PlxuXG4gIDxkaXZcbiAgICBjbGFzcz1cImN1c3RvbWVyLWxpc3QtZW1wdHlcIlxuICAgICpuZ0lmPVwiZmlsdGVyZWREYXRhLmxlbmd0aCA9PT0gMFwiXG4gID5cbiAgICBObyBUYXNrcyBmb3IgdGhlIGdpdmVuIERhdGUuXG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=