UNPKG

@harbor/ui

Version:

Harbor shared UI components based on Clarity and Angular6

434 lines (433 loc) 44.8 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Component, Input, ChangeDetectionStrategy, Output, EventEmitter, ViewChild, ChangeDetectorRef } from "@angular/core"; import { NgForm } from '@angular/forms'; import { TranslateService } from "@ngx-translate/core"; import { forkJoin, throwError } from "rxjs"; import { finalize, map, catchError } from "rxjs/operators"; import { SystemInfoService } from "../service/index"; import { ErrorHandler } from "../error-handler/error-handler"; import { toPromise, DEFAULT_PAGE_SIZE, downloadFile } from "../utils"; import { HelmChartService } from "../service/helm-chart.service"; import { DefaultHelmIcon } from "../shared/shared.const"; import { Roles } from './../shared/shared.const'; import { OperationService } from "./../operation/operation.service"; import { OperateInfo, OperationState, operateChanges } from "./../operation/operate"; import { ConfirmationDialogComponent, ConfirmationMessage } from "./../confirmation-dialog"; export class HelmChartComponent { /** * @param {?} errorHandler * @param {?} translateService * @param {?} systemInfoService * @param {?} helmChartService * @param {?} operationService * @param {?} cdr */ constructor(errorHandler, translateService, systemInfoService, helmChartService, operationService, cdr) { this.errorHandler = errorHandler; this.translateService = translateService; this.systemInfoService = systemInfoService; this.helmChartService = helmChartService; this.operationService = operationService; this.cdr = cdr; this.signedCon = {}; this.projectName = "unknown"; this.projectRoleID = Roles.OTHER; this.chartClickEvt = new EventEmitter(); this.chartDownloadEve = new EventEmitter(); this.chartDefaultIcon = DefaultHelmIcon; this.charts = []; this.chartsCopy = []; this.selectedRows = []; this.loading = true; // For Upload this.isUploading = false; this.isUploadModalOpen = false; this.cardHover = false; this.listHover = false; this.pageSize = DEFAULT_PAGE_SIZE; this.currentPage = 1; this.totalCount = 0; } /** * @return {?} */ get registryUrl() { return this.systemInfo ? this.systemInfo.registry_url : ""; } /** * @return {?} */ get developerRoleOrAbove() { return this.projectRoleID === Roles.DEVELOPER || this.hasProjectAdminRole; } /** * @return {?} */ ngOnInit() { // Get system info for tag views toPromise(this.systemInfoService.getSystemInfo()) .then(systemInfo => (this.systemInfo = systemInfo)) .catch(error => this.errorHandler.error(error)); this.lastFilteredChartName = ""; this.refresh(); } /** * @param {?} value * @return {?} */ updateFilterValue(value) { this.lastFilteredChartName = value; this.refresh(); } /** * @return {?} */ refresh() { this.loading = true; this.helmChartService .getHelmCharts(this.projectName) .pipe(finalize(() => { /** @type {?} */ let hnd = setInterval(() => this.cdr.markForCheck(), 100); setTimeout(() => clearInterval(hnd), 3000); this.loading = false; })) .subscribe(charts => { this.charts = charts.filter(x => x.name.includes(this.lastFilteredChartName)); this.chartsCopy = charts.map(x => Object.assign({}, x)); this.totalCount = charts.length; }, err => { this.errorHandler.error(err); }); } /** * @param {?} item * @return {?} */ onChartClick(item) { this.chartClickEvt.emit(item.name); } /** * @return {?} */ resetUploadForm() { this.chartFile = null; this.provFile = null; this.uploadForm.reset(); } /** * @return {?} */ onChartUpload() { this.resetUploadForm(); this.isUploadModalOpen = true; } /** * @return {?} */ cancelUpload() { this.resetUploadForm(); this.isUploadModalOpen = false; } /** * @return {?} */ upload() { if (!this.chartFile && !this.provFile) { return; } if (this.isUploading) { return; } this.isUploading = true; this.helmChartService .uploadChart(this.projectName, this.chartFile, this.provFile) .pipe(finalize(() => { this.isUploading = false; this.isUploadModalOpen = false; this.refresh(); })) .subscribe(() => { this.translateService .get("HELM_CHART.FILE_UPLOADED") .subscribe(res => this.errorHandler.info(res)); }, err => this.errorHandler.error(err)); } /** * @param {?} event * @return {?} */ onChartFileChangeEvent(event) { if (event.target.files && event.target.files.length > 0) { this.chartFile = event.target.files[0]; } } /** * @param {?} event * @return {?} */ onProvFileChangeEvent(event) { if (event.target.files && event.target.files.length > 0) { this.provFile = event.target.files[0]; } } /** * @param {?} chartName * @return {?} */ deleteChart(chartName) { /** @type {?} */ let operateMsg = new OperateInfo(); operateMsg.name = "OPERATION.DELETE_CHART"; operateMsg.data["id"] = chartName; operateMsg.state = OperationState.progressing; operateMsg.data["name"] = chartName; this.operationService.publishInfo(operateMsg); return this.helmChartService.deleteHelmChart(this.projectName, chartName) .pipe(map(() => operateChanges(operateMsg, OperationState.success), err => operateChanges(operateMsg, OperationState.failure, err))); } /** * @param {?} charts * @return {?} */ deleteCharts(charts) { if (charts && charts.length < 1) { return; } /** @type {?} */ let chartsDelete$ = charts.map(chart => this.deleteChart(chart.name)); forkJoin(chartsDelete$) .pipe(catchError(err => throwError(err)), finalize(() => { this.refresh(); this.selectedRows = []; })) .subscribe(() => { }); } /** * @param {?=} evt * @param {?=} item * @return {?} */ downloadLatestVersion(evt, item) { if (evt) { evt.stopPropagation(); } /** @type {?} */ let selectedChart; if (item) { selectedChart = item; } else { // return if selected version less then 1 if (this.selectedRows.length < 1) { return; } selectedChart = this.selectedRows[0]; } if (!selectedChart) { return; } /** @type {?} */ let filename = `charts/${selectedChart.name}-${selectedChart.latest_version}.tgz`; this.helmChartService.downloadChart(this.projectName, filename).subscribe(res => { downloadFile(res); }, error => { this.errorHandler.error(error); }); } /** * @param {?} charts * @return {?} */ openChartDeleteModal(charts) { /** @type {?} */ let chartNames = charts.map(chart => chart.name).join(","); /** @type {?} */ let message = new ConfirmationMessage("HELM_CHART.DELETE_CHART_VERSION_TITLE", "HELM_CHART.DELETE_CHART_VERSION", chartNames, charts, 12 /* HELM_CHART */, 2 /* DELETE_CANCEL */); this.confirmationDialog.open(message); } /** * @param {?} message * @return {?} */ confirmDeletion(message) { if (message && message.source === 12 /* HELM_CHART */ && message.state === 1 /* CONFIRMED */) { /** @type {?} */ let charts = message.data; this.deleteCharts(charts); } } /** * @param {?} cardView * @return {?} */ showCard(cardView) { if (this.isCardView === cardView) { return; } this.isCardView = cardView; } /** * @param {?} itemName * @return {?} */ mouseEnter(itemName) { if (itemName === "card") { this.cardHover = true; } else { this.listHover = true; } } /** * @param {?} itemName * @return {?} */ mouseLeave(itemName) { if (itemName === "card") { this.cardHover = false; } else { this.listHover = false; } } /** * @param {?} itemName * @return {?} */ isHovering(itemName) { if (itemName === "card") { return this.cardHover; } else { return this.listHover; } } /** * @param {?} chart * @return {?} */ getDefaultIcon(chart) { chart.icon = this.chartDefaultIcon; } /** * @param {?} chart * @return {?} */ getStatusString(chart) { if (chart.deprecated) { return "HELM_CHART.DEPRECATED"; } else { return "HELM_CHART.ACTIVE"; } } } HelmChartComponent.decorators = [ { type: Component, args: [{ selector: "hbr-helm-chart", template: "<div>\n <div class=\"row chart-tool\">\n <div class=\"toolbar\">\n <div class=\"row flex-items-xs-right option-right rightPos\">\n <div class=\"flex-xs-middle\">\n <hbr-filter [withDivider]=\"true\" filterPlaceholder=\"{{'HELM_CHART.FILTER_FOR_CHARTS' | translate}}\"\n [currentValue]=\"lastFilteredChartName\"\n (filterEvt)=\"updateFilterValue($event)\"></hbr-filter>\n <span class=\"card-btn\" (click)=\"showCard(true)\" (mouseenter)=\"mouseEnter('card') \" (mouseleave)=\"mouseLeave('card')\">\n <clr-icon [ngClass]=\"{'is-highlight': isCardView || isHovering('card') }\" shape=\"view-cards\"></clr-icon>\n </span>\n <span class=\"list-btn\" (click)=\"showCard(false)\" (mouseenter)=\"mouseEnter('list') \" (mouseleave)=\"mouseLeave('list')\">\n <clr-icon [ngClass]=\"{'is-highlight': !isCardView || isHovering('list') }\" shape=\"view-list\"></clr-icon>\n </span>\n <span class=\"filter-divider\"></span>\n <span class=\"refresh-btn\" (click)=\"refresh()\">\n <clr-icon shape=\"refresh\"></clr-icon>\n </span>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row\">\n <div *ngIf=\"!isCardView\" class=\"col-lg-12 col-md-12 col-sm-12 col-xs-12\">\n <clr-datagrid (clrDgRefresh)=\"refresh()\" [clrDgLoading]=\"loading\" [(clrDgSelected)]=\"selectedRows\">\n <clr-dg-action-bar>\n <button type=\"button\" class=\"btn btn-sm btn-secondary\" [disabled]=\"!developerRoleOrAbove\" (click)=\"onChartUpload()\">\n <clr-icon shape=\"upload\" size=\"16\"></clr-icon>{{'HELM_CHART.UPLOAD' | translate}}\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-secondary\" [disabled]=\"!hasProjectAdminRole || selectedRows.length<1\" (click)=\"openChartDeleteModal(selectedRows)\">\n <clr-icon shape=\"trash\" size=\"16\"></clr-icon>{{'BUTTON.DELETE' | translate}}\n </button>\n <button type=\"button\" class=\"btn btn-sm btn-secondary\" [disabled]=\"selectedRows.length!==1\" (click)=\"downloadLatestVersion()\">\n <clr-icon shape=\"download\" size=\"16\"></clr-icon>{{'HELM_CHART.DOWNLOAD' | translate}}\n </button>\n </clr-dg-action-bar>\n <clr-dg-column >{{'HELM_CHART.NAME' | translate}}</clr-dg-column>\n <clr-dg-column >{{'HELM_CHART.STATUS' | translate}}</clr-dg-column>\n <clr-dg-column>{{'HELM_CHART.CHARTVERSIONS' | translate}}</clr-dg-column>\n <clr-dg-column>{{'HELM_CHART.CREATED' | translate}}</clr-dg-column>\n <clr-dg-placeholder>{{'HELM_CHART.PLACEHOLDER' | translate }}</clr-dg-placeholder>\n <clr-dg-row *ngFor=\"let chart of charts\" [clrDgItem]=\"chart\">\n <clr-dg-cell>\n <span class=\"list-img\">\n <img class=\"size-24 margin-right-12\" [src]=\"chart.icon ?chart.icon:chartDefaultIcon\" (error)=\"getDefaultIcon(chart);\" />\n </span>\n <a href=\"javascript:void(0)\" (click)=\"onChartClick(chart)\">{{ chart.name }}</a>\n </clr-dg-cell>\n <clr-dg-cell>{{ getStatusString(chart) | translate }}</clr-dg-cell>\n <clr-dg-cell>{{ chart.total_versions }}</clr-dg-cell>\n <clr-dg-cell>{{ chart.created | date }}</clr-dg-cell>\n </clr-dg-row>\n <clr-dg-footer>\n <clr-dg-pagination #pagination [clrDgPageSize]=\"pageSize\" [clrDgTotalItems]=\"totalCount\">\n <span *ngIf=\"pagination.totalItems\">\n {{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'HELM_CHART.OF' | translate}}\n </span>\n {{pagination.totalItems}} {{'HELM_CHART.ITEMS'| translate}}\n </clr-dg-pagination>\n </clr-dg-footer>\n </clr-datagrid>\n </div>\n </div>\n <div *ngIf=\"isCardView\" class=\"row card-container\">\n <div *ngFor=\"let item of charts;\" class=\"chart-card\">\n <a let i=index; class=\"card clickable\" (click)=\"onChartClick(item)\">\n <div class=\"card-header\">\n <div class=\"card-icon\">\n <img class=\"size-60\" [src]=\"item.icon ?item.icon:chartDefaultIcon\" (error)=\"getDefaultIcon(item);\" />\n </div>\n <div class=\"card-title\">{{item.name}}</div>\n </div>\n <div class=\"card-footer\">\n <div class=\"row flex-items-xs-between\">\n <div>\n <span class=\"version-text\">{{item.total_versions}}</span>\n <label class=\"card-label\" *ngIf=\"item.total_versions !== 1\">{{'HELM_CHART.CHARTVERSIONS' | translate}}</label>\n <label class=\"card-label\" *ngIf=\"item.total_versions === 1\">{{'HELM_CHART.VERSION' | translate}}</label>\n </div>\n <div>\n <span class=\"label\"\n [class.label-danger]=\"item.deprecated\"\n [class.label-success]=\"!item.deprecated\"\n >{{getStatusString(item) | translate}}</span>\n </div>\n </div>\n </div>\n </a>\n </div>\n <div *ngIf=\"loading\">\n <span class=\"vertical-helper\"></span>\n <span class=\"spinner\"></span>\n </div>\n </div>\n <confirmation-dialog #confirmationDialog (confirmAction)=\"confirmDeletion($event)\"></confirmation-dialog>\n <clr-modal [(clrModalOpen)]=\"isUploadModalOpen\" [clrModalStaticBackdrop]=\"true\" [clrModalClosable]=\"false\">\n <h3 class=\"modal-title\">{{'HELM_CHART.UPLOAD_TITLE' | translate | titlecase}}</h3>\n <div class=\"modal-body\">\n <form #chartUploadForm=\"ngForm\" enctype=\"multipart/form-data\" (ngSubmit)=\"upload()\">\n <section class=\"form-block\">\n <div class=\"form-group\">\n <label class=\"filename-label\"> {{'HELM_CHART.CHART_FILE' | translate}} </label>\n <input class=\"filename-input\" type=\"text\" placeholder=\"{{this.chartFile?.name || 'BUTTON.NO_FILE' | translate}}\" disabled>\n <label for=\"chart\" class=\"btn btn-secondary btn-sm file-browser-btn\">{{'BUTTON.BROWSE' | translate}}</label>\n <input class=\"file-input\" type=\"file\" id=\"chart\" name=\"chart\" ngModel (change)=\"onChartFileChangeEvent($event)\">\n </div>\n <div class=\"form-group\">\n <label class=\"filename-label\"> {{'HELM_CHART.CHART_PROV' | translate}} </label>\n <input class=\"filename-input\" type=\"text\" placeholder=\"{{this.provFile?.name || 'BUTTON.NO_FILE' | translate}}\" disabled>\n <label for=\"prov\" class=\"btn btn-secondary btn-sm file-browser-btn\">{{'BUTTON.BROWSE' | translate}}</label>\n <input class=\"file-input\" type=\"file\" id=\"prov\" name=\"prov\" ngModel (change)=\"onProvFileChangeEvent($event)\">\n </div>\n </section>\n <div class=\"row flex-items-xs-right\">\n <button class=\"btn btn-secondary\" [disabled]=\"isUploading\" (click)=\"cancelUpload()\">\n <span>{{'BUTTON.CANCEL' | translate}}</span>\n </button>\n <button type=\"submit\" class=\"btn btn-primary\" [disabled]=\"isUploading\">\n <span>{{'HELM_CHART.UPLOAD' | translate}}</span>\n <span *ngIf=\"isUploading\" class=\"spinner spinner-inline\">\n Loading...\n </span>\n </button>\n </div>\n </form>\n </div>\n </clr-modal>\n</div>", changeDetection: ChangeDetectionStrategy.OnPush, styles: [".chart-tool{position:relative}.chart-tool .toolbar{overflow:hidden}.chart-tool .toolbar .rightPos{position:absolute;z-index:100;right:35px;margin-top:4px}.chart-tool .toolbar .rightPos .filter-divider{display:inline-block;height:16px;width:2px;background-color:#ccc;padding-top:12px;padding-bottom:12px;position:relative;top:9px;margin-right:6px;margin-left:6px}.card-container{margin-top:21px}.card-container .chart-card{width:200px;margin:10px}.card-container .card-header .card-icon{display:flex;justify-content:center;align-items:center}.card-container .card-header .card-title{overflow:hidden;text-overflow:ellipsis;word-wrap:break-word;white-space:nowrap;text-align:center;margin:15px}.card-container .card-footer{background-color:#d7d7d7}.card-container .card-footer .version-text{font-size:1.1rem}.card-container .card-footer .card-label{width:60px;display:inline-block}.vertical-helper{display:inline-block;height:100%;vertical-align:middle}.size-24{width:24px;height:24px}.size-60{height:60px;max-width:100%}.margin-right-12{margin-right:12px}.file-input{display:none}.filename-span{overflow:hidden;text-overflow:ellipsis;word-wrap:break-word;white-space:nowrap;display:inline-block;width:50%;vertical-align:top}clr-modal .form-group{padding-left:6rem}clr-modal .form-group .filename-label{padding-top:9px}clr-modal .form-group .filename-input{margin-top:12px;width:68%}clr-modal .form-group .file-browser-btn{margin-left:15px;max-width:25%}button clr-icon{margin-right:6px}"] }] } ]; /** @nocollapse */ HelmChartComponent.ctorParameters = () => [ { type: ErrorHandler }, { type: TranslateService }, { type: SystemInfoService }, { type: HelmChartService }, { type: OperationService }, { type: ChangeDetectorRef } ]; HelmChartComponent.propDecorators = { projectId: [{ type: Input }], projectName: [{ type: Input }], urlPrefix: [{ type: Input }], hasSignedIn: [{ type: Input }], projectRoleID: [{ type: Input }], hasProjectAdminRole: [{ type: Input }], chartClickEvt: [{ type: Output }], chartDownloadEve: [{ type: Output }], chartDefaultIcon: [{ type: Input }], uploadForm: [{ type: ViewChild, args: ['chartUploadForm',] }], confirmationDialog: [{ type: ViewChild, args: ["confirmationDialog",] }] }; if (false) { /** @type {?} */ HelmChartComponent.prototype.signedCon; /** @type {?} */ HelmChartComponent.prototype.projectId; /** @type {?} */ HelmChartComponent.prototype.projectName; /** @type {?} */ HelmChartComponent.prototype.urlPrefix; /** @type {?} */ HelmChartComponent.prototype.hasSignedIn; /** @type {?} */ HelmChartComponent.prototype.projectRoleID; /** @type {?} */ HelmChartComponent.prototype.hasProjectAdminRole; /** @type {?} */ HelmChartComponent.prototype.chartClickEvt; /** @type {?} */ HelmChartComponent.prototype.chartDownloadEve; /** @type {?} */ HelmChartComponent.prototype.chartDefaultIcon; /** @type {?} */ HelmChartComponent.prototype.lastFilteredChartName; /** @type {?} */ HelmChartComponent.prototype.charts; /** @type {?} */ HelmChartComponent.prototype.chartsCopy; /** @type {?} */ HelmChartComponent.prototype.systemInfo; /** @type {?} */ HelmChartComponent.prototype.selectedRows; /** @type {?} */ HelmChartComponent.prototype.loading; /** @type {?} */ HelmChartComponent.prototype.isUploading; /** @type {?} */ HelmChartComponent.prototype.isUploadModalOpen; /** @type {?} */ HelmChartComponent.prototype.provFile; /** @type {?} */ HelmChartComponent.prototype.chartFile; /** @type {?} */ HelmChartComponent.prototype.isCardView; /** @type {?} */ HelmChartComponent.prototype.cardHover; /** @type {?} */ HelmChartComponent.prototype.listHover; /** @type {?} */ HelmChartComponent.prototype.pageSize; /** @type {?} */ HelmChartComponent.prototype.currentPage; /** @type {?} */ HelmChartComponent.prototype.totalCount; /** @type {?} */ HelmChartComponent.prototype.currentState; /** @type {?} */ HelmChartComponent.prototype.uploadForm; /** @type {?} */ HelmChartComponent.prototype.confirmationDialog; /** @type {?} */ HelmChartComponent.prototype.errorHandler; /** @type {?} */ HelmChartComponent.prototype.translateService; /** @type {?} */ HelmChartComponent.prototype.systemInfoService; /** @type {?} */ HelmChartComponent.prototype.helmChartService; /** @type {?} */ HelmChartComponent.prototype.operationService; /** @type {?} */ HelmChartComponent.prototype.cdr; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGVsbS1jaGFydC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9AaGFyYm9yL3VpLyIsInNvdXJjZXMiOlsic3JjL2hlbG0tY2hhcnQvaGVsbS1jaGFydC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsS0FBSyxFQUVMLHVCQUF1QixFQUN2QixNQUFNLEVBQ04sWUFBWSxFQUNaLFNBQVMsRUFDVCxpQkFBaUIsRUFDbEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRXZELE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFjLE1BQU0sTUFBTSxDQUFDO0FBQ3hELE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNELE9BQU8sRUFBYyxpQkFBaUIsRUFBaUIsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDOUQsT0FBTyxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxZQUFZLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDdEUsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDakUsT0FBTyxFQUFFLGVBQWUsRUFBQyxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNqRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUNwRSxPQUFPLEVBQ0wsV0FBVyxFQUNYLGNBQWMsRUFDZCxjQUFjLEVBQ2YsTUFBTSx3QkFBd0IsQ0FBQztBQUNoQyxPQUFPLEVBQStCLDJCQUEyQixFQUFFLG1CQUFtQixFQUFFLE1B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QUc3QixnQkFBZ0I7WUFHaEIsZ0JBQWdCO1lBYnZCLGlCQUFpQjs7O3dCQWtDaEIsS0FBSzswQkFDTCxLQUFLO3dCQUNMLEtBQUs7MEJBQ0wsS0FBSzs0QkFDTCxLQUFLO2tDQUNMLEtBQUs7NEJBQ0wsTUFBTTsrQkFDTixNQUFNOytCQUNOLEtBQUs7eUJBeUJMLFNBQVMsU0FBQyxpQkFBaUI7aUNBRTNCLFNBQVMsU0FBQyxvQkFBb0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LFxuICBPdXRwdXQsXG4gIEV2ZW50RW1pdHRlcixcbiAgVmlld0NoaWxkLFxuICBDaGFuZ2VEZXRlY3RvclJlZlxufSBmcm9tIFwiQGFuZ3VsYXIvY29yZVwiO1xuaW1wb3J0IHsgTmdGb3JtIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gXCJAbmd4LXRyYW5zbGF0ZS9jb3JlXCI7XG5pbXBvcnQgeyBTdGF0ZSB9IGZyb20gXCJAY2xyL2FuZ3VsYXJcIjtcbmltcG9ydCB7IGZvcmtKb2luLCB0aHJvd0Vycm9yLCBPYnNlcnZhYmxlIH0gZnJvbSBcInJ4anNcIjtcbmltcG9ydCB7IGZpbmFsaXplLCBtYXAsIGNhdGNoRXJyb3IgfSBmcm9tIFwicnhqcy9vcGVyYXRvcnNcIjtcbmltcG9ydCB7IFN5c3RlbUluZm8sIFN5c3RlbUluZm9TZXJ2aWNlLCBIZWxtQ2hhcnRJdGVtIH0gZnJvbSBcIi4uL3NlcnZpY2UvaW5kZXhcIjtcbmltcG9ydCB7IEVycm9ySGFuZGxlciB9IGZyb20gXCIuLi9lcnJvci1oYW5kbGVyL2Vycm9yLWhhbmRsZXJcIjtcbmltcG9ydCB7IHRvUHJvbWlzZSwgREVGQVVMVF9QQUdFX1NJWkUsIGRvd25sb2FkRmlsZSB9IGZyb20gXCIuLi91dGlsc1wiO1xuaW1wb3J0IHsgSGVsbUNoYXJ0U2VydmljZSB9IGZyb20gXCIuLi9zZXJ2aWNlL2hlbG0tY2hhcnQuc2VydmljZVwiO1xuaW1wb3J0IHsgRGVmYXVsdEhlbG1JY29ufSBmcm9tIFwiLi4vc2hhcmVkL3NoYXJlZC5jb25zdFwiO1xuaW1wb3J0IHsgUm9sZXMgfSBmcm9tICcuLy4uL3NoYXJlZC9zaGFyZWQuY29uc3QnO1xuaW1wb3J0IHsgT3BlcmF0aW9uU2VydmljZSB9IGZyb20gXCIuLy4uL29wZXJhdGlvbi9vcGVyYXRpb24uc2VydmljZVwiO1xuaW1wb3J0IHtcbiAgT3BlcmF0ZUluZm8sXG4gIE9wZXJhdGlvblN0YXRlLFxuICBvcGVyYXRlQ2hhbmdlc1xufSBmcm9tIFwiLi8uLi9vcGVyYXRpb24vb3BlcmF0ZVwiO1xuaW1wb3J0IHsgQ29uZmlybWF0aW9uQWNrbm93bGVkZ2VtZW50LCBDb25maXJtYXRpb25EaWFsb2dDb21wb25lbnQsIENvbmZpcm1hdGlvbk1lc3NhZ2UgfSBmcm9tIFwiLi8uLi9jb25maXJtYXRpb24tZGlhbG9nXCI7XG5pbXBvcnQge1xuICBDb25maXJtYXRpb25CdXR0b25zLFxuICBDb25maXJtYXRpb25UYXJnZXRzLFxuICBDb25maXJtYXRpb25TdGF0ZSxcbn0gZnJvbSBcIi4vLi4vc2hhcmVkL3NoYXJlZC5jb25zdFwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiaGJyLWhlbG0tY2hhcnRcIixcbiAgdGVtcGxhdGVVcmw6IFwiLi9oZWxtLWNoYXJ0LmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9oZWxtLWNoYXJ0LmNvbXBvbmVudC5zY3NzXCJdLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaFxufSlcbmV4cG9ydCBjbGFzcyBIZWxtQ2hhcnRDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBzaWduZWRDb246IHsgW2tleTogc3RyaW5nXTogYW55IHwgc3RyaW5nW10gfSA9IHt9O1xuICBASW5wdXQoKSBwcm9qZWN0SWQ6IG51bWJlcjtcbiAgQElucHV0KCkgcHJvamVjdE5hbWUgPSBcInVua25vd25cIjtcbiAgQElucHV0KCkgdXJsUHJlZml4OiBzdHJpbmc7XG4gIEBJbnB1dCgpIGhhc1NpZ25lZEluOiBib29sZWFuO1xuICBASW5wdXQoKSBwcm9qZWN0Um9sZUlEID0gUm9sZXMuT1RIRVI7XG4gIEBJbnB1dCgpIGhhc1Byb2plY3RBZG1pblJvbGU6IGJvb2xlYW47XG4gIEBPdXRwdXQoKSBjaGFydENsaWNrRXZ0ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBjaGFydERvd25sb2FkRXZlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG4gIEBJbnB1dCgpIGNoYXJ0RGVmYXVsdEljb246IHN0cmluZyA9IERlZmF1bHRIZWxtSWNvbjtcblxuICBsYXN0RmlsdGVyZWRDaGFydE5hbWU6IHN0cmluZztcbiAgY2hhcnRzOiBIZWxtQ2hhcnRJdGVtW10gPSBbXTtcbiAgY2hhcnRzQ29weTogSGVsbUNoYXJ0SXRlbVtdID0gW107XG4gIHN5c3RlbUluZm86IFN5c3RlbUluZm87XG4gIHNlbGVjdGVkUm93czogSGVsbUNoYXJ0SXRlbVtdID0gW107XG4gIGxvYWRpbmcgPSB0cnVlO1xuXG4gIC8vIEZvciBVcGxvYWRcbiAgaXNVcGxvYWRpbmcgPSBmYWxzZTtcbiAgaXNVcGxvYWRNb2RhbE9wZW4gPSBmYWxzZTtcbiAgcHJvdkZpbGU6IEZpbGU7XG4gIGNoYXJ0RmlsZTogRmlsZTtcblxuICAvLyBGb3IgVmlldyBzd3RpY2hcbiAgaXNDYXJkVmlldzogYm9vbGVhbjtcbiAgY2FyZEhvdmVyID0gZmFsc2U7XG4gIGxpc3RIb3ZlciA9IGZhbHNlO1xuXG4gIHBhZ2VTaXplOiBudW1iZXIgPSBERUZBVUxUX1BBR0VfU0laRTtcbiAgY3VycmVudFBhZ2UgPSAxO1xuICB0b3RhbENvdW50ID0gMDtcbiAgY3VycmVudFN0YXRlOiBTdGF0ZTtcblxuICBAVmlld0NoaWxkKCdjaGFydFVwbG9hZEZvcm0nKSB1cGxvYWRGb3JtOiBOZ0Zvcm07XG5cbiAgQFZpZXdDaGlsZChcImNvbmZpcm1hdGlvbkRpYWxvZ1wiKSBjb25maXJtYXRpb25EaWFsb2c6IENvbmZpcm1hdGlvbkRpYWxvZ0NvbXBvbmVudDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVycm9ySGFuZGxlcjogRXJyb3JIYW5kbGVyLFxuICAgIHByaXZhdGUgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSxcbiAgICBwcml2YXRlIHN5c3RlbUluZm9TZXJ2aWNlOiBTeXN0ZW1JbmZvU2VydmljZSxcbiAgICBwcml2YXRlIGhlbG1DaGFydFNlcnZpY2U6IEhlbG1DaGFydFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvcGVyYXRpb25TZXJ2aWNlOiBPcGVyYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgKSB7fVxuXG4gIHB1YmxpYyBnZXQgcmVnaXN0cnlVcmwoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5zeXN0ZW1JbmZvID8gdGhpcy5zeXN0ZW1JbmZvLnJlZ2lzdHJ5X3VybCA6IFwiXCI7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGRldmVsb3BlclJvbGVPckFib3ZlKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnByb2plY3RSb2xlSUQgPT09IFJvbGVzLkRFVkVMT1BFUiB8fCB0aGlzLmhhc1Byb2plY3RBZG1pblJvbGU7XG4gIH1cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBHZXQgc3lzdGVtIGluZm8gZm9yIHRhZyB2aWV3c1xuICAgIHRvUHJvbWlzZTxTeXN0ZW1JbmZvPih0aGlzLnN5c3RlbUluZm9TZXJ2aWNlLmdldFN5c3RlbUluZm8oKSlcbiAgICAgIC50aGVuKHN5c3RlbUluZm8gPT4gKHRoaXMuc3lzdGVtSW5mbyA9IHN5c3RlbUluZm8pKVxuICAgICAgLmNhdGNoKGVycm9yID0+IHRoaXMuZXJyb3JIYW5kbGVyLmVycm9yKGVycm9yKSk7XG4gICAgdGhpcy5sYXN0RmlsdGVyZWRDaGFydE5hbWUgPSBcIlwiO1xuICAgIHRoaXMucmVmcmVzaCgpO1xuICB9XG5cbiAgdXBkYXRlRmlsdGVyVmFsdWUodmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMubGFzdEZpbHRlcmVkQ2hhcnROYW1lID0gdmFsdWU7XG4gICAgdGhpcy5yZWZyZXNoKCk7XG4gIH1cblxuICByZWZyZXNoKCkge1xuICAgIHRoaXMubG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5oZWxtQ2hhcnRTZXJ2aWNlXG4gICAgLmdldEhlbG1DaGFydHModGhpcy5wcm9qZWN0TmFtZSlcbiAgICAucGlwZShmaW5hbGl6ZSgoKSA9PiB7XG4gICAgICAgIGxldCBobmQgPSBzZXRJbnRlcnZhbCgoKSA9PiB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKSwgMTAwKTtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiBjbGVhckludGVydmFsKGhuZCksIDMwMDApO1xuICAgICAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcbiAgICB9KSlcbiAgICAuc3Vic2NyaWJlKFxuICAgICAgY2hhcnRzID0+IHtcbiAgICAgICAgdGhpcy5jaGFydHMgPSBjaGFydHMuZmlsdGVyKHggPT4geC5uYW1lLmluY2x1ZGVzKHRoaXMubGFzdEZpbHRlcmVkQ2hhcnROYW1lKSk7XG4gICAgICAgIHRoaXMuY2hhcnRzQ29weSA9IGNoYXJ0cy5tYXAoeCA9PiBPYmplY3QuYXNzaWduKHt9LCB4KSk7XG4gICAgICAgIHRoaXMudG90YWxDb3VudCA9IGNoYXJ0cy5sZW5ndGg7XG4gICAgICB9LFxuICAgICAgZXJyID0+IHtcbiAgICAgICAgdGhpcy5lcnJvckhhbmRsZXIuZXJyb3IoZXJyKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgb25DaGFydENsaWNrKGl0ZW06IEhlbG1DaGFydEl0ZW0pIHtcbiAgICB0aGlzLmNoYXJ0Q2xpY2tFdnQuZW1pdChpdGVtLm5hbWUpO1xuICB9XG5cbiAgcmVzZXRVcGxvYWRGb3JtKCkge1xuICAgIHRoaXMuY2hhcnRGaWxlID0gbnVsbDtcbiAgICB0aGlzLnByb3ZGaWxlID0gbnVsbDtcbiAgICB0aGlzLnVwbG9hZEZvcm0ucmVzZXQoKTtcbiAgfVxuXG4gIG9uQ2hhcnRVcGxvYWQoKSB7XG4gICAgdGhpcy5yZXNldFVwbG9hZEZvcm0oKTtcbiAgICB0aGlzLmlzVXBsb2FkTW9kYWxPcGVuID0gdHJ1ZTtcbiAgfVxuXG4gIGNhbmNlbFVwbG9hZCgpIHtcbiAgICB0aGlzLnJlc2V0VXBsb2FkRm9ybSgpO1xuICAgIHRoaXMuaXNVcGxvYWRNb2RhbE9wZW4gPSBmYWxzZTtcbiAgfVxuXG4gIHVwbG9hZCgpIHtcbiAgICBpZiAoIXRoaXMuY2hhcnRGaWxlICYmICF0aGlzLnByb3ZGaWxlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICh0aGlzLmlzVXBsb2FkaW5nKSB7IHJldHVybjsgfVxuICAgIHRoaXMuaXNVcGxvYWRpbmcgPSB0cnVlO1xuICAgIHRoaXMuaGVsbUNoYXJ0U2VydmljZVxuICAgICAgLnVwbG9hZENoYXJ0KHRoaXMucHJvamVjdE5hbWUsIHRoaXMuY2hhcnRGaWxlLCB0aGlzLnByb3ZGaWxlKVxuICAgICAgLnBpcGUoZmluYWxpemUoKCkgPT4ge1xuICAgICAgICB0aGlzLmlzVXBsb2FkaW5nID0gZmFsc2U7XG4gICAgICAgIHRoaXMuaXNVcGxvYWRNb2RhbE9wZW4gPSBmYWxzZTtcbiAgICAgICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgICB9KSlcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgIHRoaXMudHJhbnNsYXRlU2VydmljZVxuICAgICAgICAgICAgLmdldChcIkhFTE1fQ0hBUlQuRklMRV9VUExPQURFRFwiKVxuICAgICAgICAgICAgLnN1YnNjcmliZShyZXMgPT4gdGhpcy5lcnJvckhhbmRsZXIuaW5mbyhyZXMpKTtcbiAgICAgICAgfSxcbiAgICAgICAgZXJyID0+IHRoaXMuZXJyb3JIYW5kbGVyLmVycm9yKGVycilcbiAgICAgICk7XG4gIH1cblxuICBvbkNoYXJ0RmlsZUNoYW5nZUV2ZW50KGV2ZW50KSB7XG4gICAgaWYgKGV2ZW50LnRhcmdldC5maWxlcyAmJiBldmVudC50YXJnZXQuZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5jaGFydEZpbGUgPSBldmVudC50YXJnZXQuZmlsZXNbMF07XG4gICAgfVxuICB9XG4gIG9uUHJvdkZpbGVDaGFuZ2VFdmVudChldmVudCkge1xuICAgIGlmIChldmVudC50YXJnZXQuZmlsZXMgJiYgZXZlbnQudGFyZ2V0LmZpbGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMucHJvdkZpbGUgPSBldmVudC50YXJnZXQuZmlsZXNbMF07XG4gICAgfVxuICB9XG5cblxuICBkZWxldGVDaGFydChjaGFydE5hbWU6IHN0cmluZyk6IE9ic2VydmFibGU8YW55PiB7XG4gICAgbGV0IG9wZXJhdGVNc2cgPSBuZXcgT3BlcmF0ZUluZm8oKTtcbiAgICBvcGVyYXRlTXNnLm5hbWUgPSBcIk9QRVJBVElPTi5ERUxFVEVfQ0hBUlRcIjtcbiAgICBvcGVyYXRlTXNnLmRhdGEuaWQgPSBjaGFydE5hbWU7XG4gICAgb3BlcmF0ZU1zZy5zdGF0ZSA9IE9wZXJhdGlvblN0YXRlLnByb2dyZXNzaW5nO1xuICAgIG9wZXJhdGVNc2cuZGF0YS5uYW1lID0gY2hhcnROYW1lO1xuICAgIHRoaXMub3BlcmF0aW9uU2VydmljZS5wdWJsaXNoSW5mbyhvcGVyYXRlTXNnKTtcblxuICAgIHJldHVybiB0aGlzLmhlbG1DaGFydFNlcnZpY2UuZGVsZXRlSGVsbUNoYXJ0KHRoaXMucHJvamVjdE5hbWUsIGNoYXJ0TmFtZSlcbiAgICAucGlwZShtYXAoXG4gICAgICAoKSA9PiBvcGVyYXRlQ2hhbmdlcyhvcGVyYXRlTXNnLCBPcGVyYXRpb25TdGF0ZS5zdWNjZXNzKSxcbiAgICAgIGVyciA9PiBvcGVyYXRlQ2hhbmdlcyhvcGVyYXRlTXNnLCBPcGVyYXRpb25TdGF0ZS5mYWlsdXJlLCBlcnIpXG4gICAgKSk7XG4gIH1cblxuICBkZWxldGVDaGFydHMoY2hhcnRzOiBIZWxtQ2hhcnRJdGVtW10pIHtcbiAgICBpZiAoY2hhcnRzICYmIGNoYXJ0cy5sZW5ndGggPCAxKSB7IHJldHVybjsgfVxuICAgIGxldCBjaGFydHNEZWxldGUkID0gY2hhcnRzLm1hcChjaGFydCA9PiB0aGlzLmRlbGV0ZUNoYXJ0KGNoYXJ0Lm5hbWUpKTtcbiAgICBmb3JrSm9pbihjaGFydHNEZWxldGUkKVxuICAgIC5waXBlKFxuICAgICAgY2F0Y2hFcnJvcihlcnIgPT4gdGhyb3dFcnJvcihlcnIpKSxcbiAgICAgIGZpbmFsaXplKCgpID0+IHtcbiAgICAgICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgICAgIHRoaXMuc2VsZWN0ZWRSb3dzID0gW107XG4gICAgICB9KSlcbiAgICAuc3Vic2NyaWJlKCgpID0+IHt9KTtcbiAgfVxuXG4gIGRvd25sb2FkTGF0ZXN0VmVyc2lvbihldnQ/OiBFdmVudCwgaXRlbT86IEhlbG1DaGFydEl0ZW0pIHtcbiAgICBpZiAoZXZ0KSB7XG4gICAgICBldnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuICAgIGxldCBzZWxlY3RlZENoYXJ0OiBIZWxtQ2hhcnRJdGVtO1xuXG4gICAgaWYgKGl0ZW0pIHtcbiAgICAgIHNlbGVjdGVkQ2hhcnQgPSBpdGVtO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyByZXR1cm4gaWYgc2VsZWN0ZWQgdmVyc2lvbiBsZXNzIHRoZW4gMVxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRSb3dzLmxlbmd0aCA8IDEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgc2VsZWN0ZWRDaGFydCA9IHRoaXMuc2VsZWN0ZWRSb3dzWzBdO1xuICAgIH1cbiAgICBpZiAoIXNlbGVjdGVkQ2hhcnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgbGV0IGZpbGVuYW1lID0gYGNoYXJ0cy8ke3NlbGVjdGVkQ2hhcnQubmFtZX0tJHtzZWxlY3RlZENoYXJ0LmxhdGVzdF92ZXJzaW9ufS50Z3pgO1xuICAgIHRoaXMuaGVsbUNoYXJ0U2VydmljZS5kb3dubG9hZENoYXJ0KHRoaXMucHJvamVjdE5hbWUsIGZpbGVuYW1lKS5zdWJzY3JpYmUoXG4gICAgICByZXMgPT4ge1xuICAgICAgICBkb3dubG9hZEZpbGUocmVzKTtcbiAgICAgIH0sXG4gICAgICBlcnJvciA9PiB7XG4gICAgICAgIHRoaXMuZXJyb3JIYW5kbGVyLmVycm9yKGVycm9yKTtcbiAgICAgIH1cbiAgICApO1xuICB9XG5cbiAgb3BlbkNoYXJ0RGVsZXRlTW9kYWwoY2hhcnRzOiBIZWxtQ2hhcnRJdGVtW10pIHtcbiAgICBsZXQgY2hhcnROYW1lcyA9IGNoYXJ0cy5tYXAoY2hhcnQgPT4gY2hhcnQubmFtZSkuam9pbihcIixcIik7XG4gICAgbGV0IG1lc3NhZ2UgPSBuZXcgQ29uZmlybWF0aW9uTWVzc2FnZShcbiAgICAgIFwiSEVMTV9DSEFSVC5ERUxFVEVfQ0hBUlRfVkVSU0lPTl9USVRMRVwiLFxuICAgICAgXCJIRUxNX0NIQVJULkRFTEVURV9DSEFSVF9WRVJTSU9OXCIsXG4gICAgICBjaGFydE5hbWVzLFxuICAgICAgY2hhcnRzLFxuICAgICAgQ29uZmlybWF0aW9uVGFyZ2V0cy5IRUxNX0NIQVJULFxuICAgICAgQ29uZmlybWF0aW9uQnV0dG9ucy5ERUxFVEVfQ0FOQ0VMXG4gICAgKTtcbiAgICB0aGlzLmNvbmZpcm1hdGlvbkRpYWxvZy5vcGVuKG1lc3NhZ2UpO1xuICB9XG5cbiAgY29uZmlybURlbGV0aW9uKG1lc3NhZ2U6IENvbmZpcm1hdGlvbkFja25vd2xlZGdlbWVudCkge1xuICAgIGlmIChcbiAgICAgIG1lc3NhZ2UgJiZcbiAgICAgIG1lc3NhZ2Uuc291cmNlID09PSBDb25maXJtYXRpb25UYXJnZXRzLkhFTE1fQ0hBUlQgJiZcbiAgICAgIG1lc3NhZ2Uuc3RhdGUgPT09IENvbmZpcm1hdGlvblN0YXRlLkNPTkZJUk1FRFxuICAgICkge1xuICAgICAgbGV0IGNoYXJ0cyA9IG1lc3NhZ2UuZGF0YTtcbiAgICAgIHRoaXMuZGVsZXRlQ2hhcnRzKGNoYXJ0cyk7XG4gICAgfVxuICB9XG5cbiAgc2hvd0NhcmQoY2FyZFZpZXc6IGJvb2xlYW4pIHtcbiAgICBpZiAodGhpcy5pc0NhcmRWaWV3ID09PSBjYXJkVmlldykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmlzQ2FyZFZpZXcgPSBjYXJkVmlldztcbiAgfVxuXG4gIG1vdXNlRW50ZXIoaXRlbU5hbWU6IHN0cmluZykge1xuICAgIGlmIChpdGVtTmFtZSA9PT0gXCJjYXJkXCIpIHtcbiAgICAgIHRoaXMuY2FyZEhvdmVyID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5saXN0SG92ZXIgPSB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIG1vdXNlTGVhdmUoaXRlbU5hbWU6IHN0cmluZykge1xuICAgIGlmIChpdGVtTmFtZSA9PT0gXCJjYXJkXCIpIHtcbiAgICAgIHRoaXMuY2FyZEhvdmVyID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGlzdEhvdmVyID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgaXNIb3ZlcmluZyhpdGVtTmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKGl0ZW1OYW1lID09PSBcImNhcmRcIikge1xuICAgICAgcmV0dXJuIHRoaXMuY2FyZEhvdmVyO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5saXN0SG92ZXI7XG4gICAgfVxuICB9XG5cbiAgZ2V0RGVmYXVsdEljb24oY2hhcnQ6IEhlbG1DaGFydEl0ZW0pIHtcbiAgICBjaGFydC5pY29uID0gdGhpcy5jaGFydERlZmF1bHRJY29uO1xuICB9XG5cbiAgZ2V0U3RhdHVzU3RyaW5nKGNoYXJ0OiBIZWxtQ2hhcnRJdGVtKSB7XG4gICAgaWYgKGNoYXJ0LmRlcHJlY2F0ZWQpIHtcbiAgICAgIHJldHVybiBcIkhFTE1fQ0hBUlQuREVQUkVDQVRFRFwiO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gXCJIRUxNX0NIQVJULkFDVElWRVwiO1xuICAgIH1cbiAgfVxufVxuIl19