UNPKG

@harbor/ui

Version:

Harbor shared UI components based on Clarity and Angular6

547 lines (546 loc) 56 kB
/** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,uselessCode} checked by tsc */ import { Component, ViewChild, Input, Output, EventEmitter } from "@angular/core"; import { forkJoin, timer } from "rxjs"; import { TranslateService } from "@ngx-translate/core"; import { ListReplicationRuleComponent } from "../list-replication-rule/list-replication-rule.component"; import { CreateEditRuleComponent } from "../create-edit-rule/create-edit-rule.component"; import { ErrorHandler } from "../error-handler/error-handler"; import { ReplicationService } from "../service/replication.service"; import { RequestQueryParams } from "../service/RequestQueryParams"; import { toPromise, CustomComparator, DEFAULT_PAGE_SIZE, doFiltering, doSorting, calculatePage } from "../utils"; import { ConfirmationMessage } from "../confirmation-dialog/confirmation-message"; import { ConfirmationDialogComponent } from "../confirmation-dialog/confirmation-dialog.component"; import { operateChanges, OperationState, OperateInfo } from "../operation/operate"; import { OperationService } from "../operation/operation.service"; /** @type {?} */ const ruleStatus = [ { key: "all", description: "REPLICATION.ALL_STATUS" }, { key: "1", description: "REPLICATION.ENABLED" }, { key: "0", description: "REPLICATION.DISABLED" } ]; /** @type {?} */ const jobStatus = [ { key: "all", description: "REPLICATION.ALL" }, { key: "pending", description: "REPLICATION.PENDING" }, { key: "running", description: "REPLICATION.RUNNING" }, { key: "error", description: "REPLICATION.ERROR" }, { key: "retrying", description: "REPLICATION.RETRYING" }, { key: "stopped", description: "REPLICATION.STOPPED" }, { key: "finished", description: "REPLICATION.FINISHED" }, { key: "canceled", description: "REPLICATION.CANCELED" } ]; /** @type {?} */ const optionalSearch = { 0: "REPLICATION.ADVANCED", 1: "REPLICATION.SIMPLE" }; export class SearchOption { constructor() { this.ruleName = ""; this.repoName = ""; this.status = ""; this.startTime = ""; this.startTimestamp = ""; this.endTime = ""; this.endTimestamp = ""; this.page = 1; this.pageSize = DEFAULT_PAGE_SIZE; } } if (false) { /** @type {?} */ SearchOption.prototype.ruleId; /** @type {?} */ SearchOption.prototype.ruleName; /** @type {?} */ SearchOption.prototype.repoName; /** @type {?} */ SearchOption.prototype.status; /** @type {?} */ SearchOption.prototype.startTime; /** @type {?} */ SearchOption.prototype.startTimestamp; /** @type {?} */ SearchOption.prototype.endTime; /** @type {?} */ SearchOption.prototype.endTimestamp; /** @type {?} */ SearchOption.prototype.page; /** @type {?} */ SearchOption.prototype.pageSize; } export class ReplicationComponent { /** * @param {?} errorHandler * @param {?} replicationService * @param {?} operationService * @param {?} translateService */ constructor(errorHandler, replicationService, operationService, translateService) { this.errorHandler = errorHandler; this.replicationService = replicationService; this.operationService = operationService; this.translateService = translateService; this.redirect = new EventEmitter(); this.openCreateRule = new EventEmitter(); this.openEdit = new EventEmitter(); this.goToRegistry = new EventEmitter(); this.search = new SearchOption(); this.ruleStatus = ruleStatus; this.jobStatus = jobStatus; this.hiddenJobList = true; this.toggleJobSearchOption = optionalSearch; this.creationTimeComparator = new CustomComparator("creation_time", "date"); this.updateTimeComparator = new CustomComparator("update_time", "date"); // Server driven pagination this.currentPage = 1; this.totalCount = 0; this.pageSize = DEFAULT_PAGE_SIZE; this.jobsLoading = false; } /** * @return {?} */ get showPaginationIndex() { return this.totalCount > 0; } /** * @return {?} */ ngOnInit() { this.currentRuleStatus = this.ruleStatus[0]; this.currentJobStatus = this.jobStatus[0]; this.currentJobSearchOption = 0; } /** * @return {?} */ ngOnDestroy() { if (this.timerDelay) { this.timerDelay.unsubscribe(); } } /** * @return {?} */ openModal() { this.createEditPolicyComponent.openCreateEditRule(); } /** * @param {?} rule * @return {?} */ openEditRule(rule) { if (rule) { this.createEditPolicyComponent.openCreateEditRule(rule.id); } } /** * @return {?} */ goRegistry() { this.goToRegistry.emit(); } /** * @param {?} state * @return {?} */ clrLoadJobs(state) { if (!state || !state.page || !this.search.ruleId) { return; } this.currentState = state; /** @type {?} */ let pageNumber = calculatePage(state); if (pageNumber <= 0) { pageNumber = 1; } /** @type {?} */ let params = new RequestQueryParams(); // Pagination params.set("page", "" + pageNumber); params.set("page_size", "" + this.pageSize); // Search by status if (this.search.status.trim()) { params.set("status", this.search.status); } // Search by repository if (this.search.repoName.trim()) { params.set("repository", this.search.repoName); } // Search by timestamps if (this.search.startTimestamp.trim()) { params.set("start_time", this.search.startTimestamp); } if (this.search.endTimestamp.trim()) { params.set("end_time", this.search.endTimestamp); } this.jobsLoading = true; // Do filtering and sorting this.jobs = doFiltering(this.jobs, state); this.jobs = doSorting(this.jobs, state); this.jobsLoading = false; toPromise(this.replicationService.getJobs(this.search.ruleId, params)) .then(response => { this.totalCount = response.metadata.xTotalCount; this.jobs = response.data; if (!this.timerDelay) { this.timerDelay = timer(10000, 10000).subscribe(() => { /** @type {?} */ let count = 0; this.jobs.forEach(job => { if (job.status === "pending" || job.status === "running" || job.status === "retrying") { count++; } }); if (count > 0) { this.clrLoadJobs(this.currentState); } else { this.timerDelay.unsubscribe(); this.timerDelay = null; } }); } // Do filtering and sorting this.jobs = doFiltering(this.jobs, state); this.jobs = doSorting(this.jobs, state); this.jobsLoading = false; }) .catch(error => { this.jobsLoading = false; this.errorHandler.error(error); }); } /** * @return {?} */ loadFirstPage() { /** @type {?} */ let st = this.currentState; if (!st) { st = { page: {} }; } st.page.size = this.pageSize; st.page.from = 0; st.page.to = this.pageSize - 1; this.clrLoadJobs(st); } /** * @param {?} rule * @return {?} */ selectOneRule(rule) { if (rule && rule.id) { this.hiddenJobList = false; this.search.ruleId = rule.id || ""; this.search.repoName = ""; this.search.status = ""; this.currentJobSearchOption = 0; this.currentJobStatus = { key: "all", description: "REPLICATION.ALL" }; this.loadFirstPage(); } } /** * @param {?} rule * @return {?} */ replicateManualRule(rule) { if (rule) { /** @type {?} */ let replicationMessage = new ConfirmationMessage("REPLICATION.REPLICATION_TITLE", "REPLICATION.REPLICATION_SUMMARY", rule.name, rule, 6 /* TARGET */, 4 /* REPLICATE_CANCEL */); this.replicationConfirmDialog.open(replicationMessage); } } /** * @param {?} message * @return {?} */ confirmReplication(message) { if (message && message.source === 6 /* TARGET */ && message.state === 1 /* CONFIRMED */) { /** @type {?} */ let rule = message.data; if (rule) { Promise.all([this.replicationOperate(rule)]).then((item) => { this.selectOneRule(rule); }); } } } /** * @param {?} rule * @return {?} */ replicationOperate(rule) { /** @type {?} */ let operMessage = new OperateInfo(); operMessage.name = 'OPERATION.REPLICATION'; operMessage.data["id"] = rule.id; operMessage.state = OperationState.progressing; operMessage.data["name"] = rule.name; this.operationService.publishInfo(operMessage); return toPromise(this.replicationService.replicateRule(+rule.id)) .then(response => { this.translateService.get('BATCH.REPLICATE_SUCCESS') .subscribe(res => operateChanges(operMessage, OperationState.success)); }) .catch(error => { if (error && error.status === 412) { forkJoin(this.translateService.get('BATCH.REPLICATE_FAILURE'), this.translateService.get('REPLICATION.REPLICATE_SUMMARY_FAILURE')) .subscribe(function (res) { operateChanges(operMessage, OperationState.failure, res[1]); }); } else { this.translateService.get('BATCH.REPLICATE_FAILURE').subscribe(res => { operateChanges(operMessage, OperationState.failure, res); }); } }); } /** * @param {?} rule * @return {?} */ customRedirect(rule) { this.redirect.emit(rule); } /** * @param {?} ruleName * @return {?} */ doSearchRules(ruleName) { this.search.ruleName = ruleName; this.listReplicationRule.retrieveRules(ruleName); } /** * @param {?} $event * @return {?} */ doFilterJobStatus($event) { if ($event && $event.target && $event.target["value"]) { /** @type {?} */ let status = $event.target["value"]; this.currentJobStatus = this.jobStatus["find"]((r) => r.key === status); if (this.currentJobStatus.key === "all") { status = ""; } this.search.status = status; this.doSearchJobs(this.search.repoName); } } /** * @param {?} repoName * @return {?} */ doSearchJobs(repoName) { this.search.repoName = repoName; this.loadFirstPage(); } /** * @return {?} */ hideJobs() { this.search.ruleId = 0; this.jobs = []; this.hiddenJobList = true; } /** * @return {?} */ stopJobs() { if (this.jobs && this.jobs.length) { this.isStopOnGoing = true; toPromise(this.replicationService.stopJobs(this.jobs[0].policy_id)) .then(res => { this.refreshJobs(); this.isStopOnGoing = false; }) .catch(error => this.errorHandler.error(error)); } } /** * @param {?} isReady * @return {?} */ reloadRules(isReady) { if (isReady) { this.search.ruleName = ""; this.listReplicationRule.retrieveRules(this.search.ruleName); } } /** * @return {?} */ refreshRules() { this.listReplicationRule.retrieveRules(); } /** * @return {?} */ refreshJobs() { this.currentJobStatus = this.jobStatus[0]; this.search.startTime = " "; this.search.endTime = " "; this.search.repoName = ""; this.search.startTimestamp = ""; this.search.endTimestamp = ""; this.search.status = ""; this.currentPage = 1; /** @type {?} */ let st = { page: { from: 0, to: this.pageSize - 1, size: this.pageSize } }; this.clrLoadJobs(st); } /** * @param {?} option * @return {?} */ toggleSearchJobOptionalName(option) { option === 1 ? (this.currentJobSearchOption = 0) : (this.currentJobSearchOption = 1); } /** * @param {?} fromTimestamp * @return {?} */ doJobSearchByStartTime(fromTimestamp) { this.search.startTimestamp = fromTimestamp; this.loadFirstPage(); } /** * @param {?} toTimestamp * @return {?} */ doJobSearchByEndTime(toTimestamp) { this.search.endTimestamp = toTimestamp; this.loadFirstPage(); } /** * @param {?} jobId * @return {?} */ viewLog(jobId) { return this.replicationService.getJobBaseUrl() + "/" + jobId + "/log"; } } ReplicationComponent.decorators = [ { type: Component, args: [{ selector: "hbr-replication", template: "<div class=\"row\" style=\"position:relative;\">\n <div>\n <div class=\"row flex-items-xs-between rightPos\">\n <div class=\"flex-xs-middle option-right\">\n <hbr-filter [withDivider]=\"true\" filterPlaceholder='{{\"REPLICATION.FILTER_POLICIES_PLACEHOLDER\" | translate}}' (filterEvt)=\"doSearchRules($event)\"\n [currentValue]=\"search.ruleName\"></hbr-filter>\n <span class=\"refresh-btn\" (click)=\"refreshRules()\">\n <clr-icon shape=\"refresh\"></clr-icon>\n </span>\n </div>\n </div>\n </div>\n <div class=\"col-lg-12 col-md-12 col-sm-12 col-xs-12\">\n <hbr-list-replication-rule #listReplicationRule [projectId]=\"projectId\" [isSystemAdmin]=\"isSystemAdmin\" (replicateManual)=replicateManualRule($event)\n (selectOne)=\"selectOneRule($event)\" (hideJobs)=\"hideJobs()\" (openNewRule)=\"openModal()\" (editOne)=\"openEditRule($event)\"\n (reload)=\"reloadRules($event)\" [loading]=\"loading\" [withReplicationJob]=\"withReplicationJob\" (redirect)=\"customRedirect($event)\"></hbr-list-replication-rule>\n </div>\n <div class=\"col-lg-12 col-md-12 col-sm-12 col-xs-12\" style=\"padding-left:0px;\" [hidden]='hiddenJobList'>\n <div *ngIf=\"withReplicationJob\" class=\"col-lg-12 col-md-12 col-sm-12 col-xs-12\">\n <div class=\"row flex-items-xs-between\" style=\"height:60px;\">\n <h5 class=\"flex-items-xs-bottom option-left-down\" style=\"margin-left: 14px;\">{{'REPLICATION.REPLICATION_JOBS' | translate}}</h5>\n <div class=\"flex-items-xs-bottom option-right-down\">\n <button class=\"btn btn-link\" (click)=\"toggleSearchJobOptionalName(currentJobSearchOption)\">{{toggleJobSearchOption[currentJobSearchOption] | translate}}</button>\n <hbr-filter [withDivider]=\"true\" filterPlaceholder='{{\"REPLICATION.FILTER_JOBS_PLACEHOLDER\" | translate}}' (filterEvt)=\"doSearchJobs($event)\"\n [currentValue]=\"search.repoName\"></hbr-filter>\n <span class=\"refresh-btn\" (click)=\"refreshJobs()\">\n <clr-icon shape=\"refresh\"></clr-icon>\n </span>\n </div>\n </div>\n <div class=\"row flex-items-xs-right row-right\" [hidden]=\"currentJobSearchOption === 0\">\n <div class=\"select select-status\">\n <select (change)=\"doFilterJobStatus($event)\">\n <option *ngFor=\"let j of jobStatus\" value=\"{{j.key}}\" [selected]=\"currentJobStatus.key === j.key\">{{j.description | translate}}</option>\n </select>\n </div>\n <div class=\"flex-items-xs-middle\">\n <hbr-datetime [dateInput]=\"search.startTime\" (search)=\"doJobSearchByStartTime($event)\"></hbr-datetime>\n <hbr-datetime [dateInput]=\"search.endTime\" [oneDayOffset]=\"true\" (search)=\"doJobSearchByEndTime($event)\"></hbr-datetime>\n </div>\n </div>\n </div>\n <div *ngIf=\"withReplicationJob\" class=\"col-lg-12 col-md-12 col-sm-12 col-xs-12\">\n <clr-datagrid [clrDgLoading]=\"jobsLoading\" (clrDgRefresh)=\"clrLoadJobs($event)\">\n <clr-dg-action-bar>\n <div class=\"btn-group\">\n <button type=\"button\" class=\"btn btn-sm btn-secondary\" *ngIf=\"isSystemAdmin\" [disabled]=\"!(jobs && jobs.length>0) || isStopOnGoing\"\n (click)=\"stopJobs()\">{{'REPLICATION.STOPJOB' | translate}}</button>\n </div>\n </clr-dg-action-bar>\n <clr-dg-column [clrDgField]=\"'repository'\">{{'REPLICATION.NAME' | translate}}</clr-dg-column>\n <clr-dg-column [clrDgField]=\"'status'\">{{'REPLICATION.STATUS' | translate}}</clr-dg-column>\n <clr-dg-column [clrDgField]=\"'operation'\">{{'REPLICATION.OPERATION' | translate}}</clr-dg-column>\n <clr-dg-column [clrDgSortBy]=\"creationTimeComparator\">{{'REPLICATION.CREATION_TIME' | translate}}</clr-dg-column>\n <clr-dg-column [clrDgSortBy]=\"updateTimeComparator\">{{'REPLICATION.UPDATE_TIME' | translate}}</clr-dg-column>\n <clr-dg-column>{{'REPLICATION.LOGS' | translate}}</clr-dg-column>\n <clr-dg-placeholder>{{'REPLICATION.JOB_PLACEHOLDER' | translate }}</clr-dg-placeholder>\n <clr-dg-row *ngFor=\"let j of jobs\">\n <clr-dg-cell>{{j.repository}}</clr-dg-cell>\n <clr-dg-cell>{{j.status}}</clr-dg-cell>\n <clr-dg-cell>{{j.operation}}</clr-dg-cell>\n <clr-dg-cell>{{j.creation_time | date: 'short'}}</clr-dg-cell>\n <clr-dg-cell>{{j.update_time | date: 'short'}}</clr-dg-cell>\n <clr-dg-cell>\n <span *ngIf=\"j.status=='pending'; else elseBlock\" class=\"label\">{{'REPLICATION.NO_LOGS' | translate}}</span>\n <ng-template #elseBlock>\n <a target=\"_blank\" [href]=\"viewLog(j.id)\">\n <clr-icon shape=\"list\"></clr-icon>\n </a>\n </ng-template>\n </clr-dg-cell>\n </clr-dg-row>\n <clr-dg-footer>\n <span *ngIf=\"showPaginationIndex\">{{pagination.firstItem + 1}} - {{pagination.lastItem + 1}} {{'REPLICATION.OF' | translate}}</span>\n {{pagination.totalItems}} {{'REPLICATION.ITEMS' | translate}}\n <clr-dg-pagination #pagination [(clrDgPage)]=\"currentPage\" [clrDgPageSize]=\"pageSize\" [clrDgTotalItems]=\"totalCount\"></clr-dg-pagination>\n </clr-dg-footer>\n </clr-datagrid>\n </div>\n </div>\n <hbr-create-edit-rule *ngIf=\"isSystemAdmin\" [withAdmiral]=\"withAdmiral\" [projectId]=\"projectId\" [projectName]=\"projectName\"\n (goToRegistry)=\"goRegistry()\" (reload)=\"reloadRules($event)\"></hbr-create-edit-rule>\n <confirmation-dialog #replicationConfirmDialog (confirmAction)=\"confirmReplication($event)\"></confirmation-dialog>\n</div>", styles: [".refresh-btn{cursor:pointer}.refresh-btn:hover{color:#007cbb}.option-left{padding-left:16px}.option-right{padding-right:16px}.option-left-down{margin-top:36px}.option-right-down{padding-right:16px;margin-top:24px}.rightPos{position:absolute;right:35px;margin-top:5px;z-index:100;height:32px}.select-status{float:left;margin-top:6px;margin-right:5px}.row-right{padding-right:50px}"] }] } ]; /** @nocollapse */ ReplicationComponent.ctorParameters = () => [ { type: ErrorHandler }, { type: ReplicationService }, { type: OperationService }, { type: TranslateService } ]; ReplicationComponent.propDecorators = { projectId: [{ type: Input }], projectName: [{ type: Input }], isSystemAdmin: [{ type: Input }], withAdmiral: [{ type: Input }], withReplicationJob: [{ type: Input }], redirect: [{ type: Output }], openCreateRule: [{ type: Output }], openEdit: [{ type: Output }], goToRegistry: [{ type: Output }], listReplicationRule: [{ type: ViewChild, args: [ListReplicationRuleComponent,] }], createEditPolicyComponent: [{ type: ViewChild, args: [CreateEditRuleComponent,] }], replicationConfirmDialog: [{ type: ViewChild, args: ["replicationConfirmDialog",] }] }; if (false) { /** @type {?} */ ReplicationComponent.prototype.projectId; /** @type {?} */ ReplicationComponent.prototype.projectName; /** @type {?} */ ReplicationComponent.prototype.isSystemAdmin; /** @type {?} */ ReplicationComponent.prototype.withAdmiral; /** @type {?} */ ReplicationComponent.prototype.withReplicationJob; /** @type {?} */ ReplicationComponent.prototype.redirect; /** @type {?} */ ReplicationComponent.prototype.openCreateRule; /** @type {?} */ ReplicationComponent.prototype.openEdit; /** @type {?} */ ReplicationComponent.prototype.goToRegistry; /** @type {?} */ ReplicationComponent.prototype.search; /** @type {?} */ ReplicationComponent.prototype.ruleStatus; /** @type {?} */ ReplicationComponent.prototype.currentRuleStatus; /** @type {?} */ ReplicationComponent.prototype.jobStatus; /** @type {?} */ ReplicationComponent.prototype.currentJobStatus; /** @type {?} */ ReplicationComponent.prototype.changedRules; /** @type {?} */ ReplicationComponent.prototype.rules; /** @type {?} */ ReplicationComponent.prototype.loading; /** @type {?} */ ReplicationComponent.prototype.isStopOnGoing; /** @type {?} */ ReplicationComponent.prototype.hiddenJobList; /** @type {?} */ ReplicationComponent.prototype.jobs; /** @type {?} */ ReplicationComponent.prototype.toggleJobSearchOption; /** @type {?} */ ReplicationComponent.prototype.currentJobSearchOption; /** @type {?} */ ReplicationComponent.prototype.listReplicationRule; /** @type {?} */ ReplicationComponent.prototype.createEditPolicyComponent; /** @type {?} */ ReplicationComponent.prototype.replicationConfirmDialog; /** @type {?} */ ReplicationComponent.prototype.creationTimeComparator; /** @type {?} */ ReplicationComponent.prototype.updateTimeComparator; /** @type {?} */ ReplicationComponent.prototype.currentPage; /** @type {?} */ ReplicationComponent.prototype.totalCount; /** @type {?} */ ReplicationComponent.prototype.pageSize; /** @type {?} */ ReplicationComponent.prototype.currentState; /** @type {?} */ ReplicationComponent.prototype.jobsLoading; /** @type {?} */ ReplicationComponent.prototype.timerDelay; /** @type {?} */ ReplicationComponent.prototype.errorHandler; /** @type {?} */ ReplicationComponent.prototype.replicationService; /** @type {?} */ ReplicationComponent.prototype.operationService; /** @type {?} */ ReplicationComponent.prototype.translateService; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwbGljYXRpb24uY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vQGhhcmJvci91aS8iLCJzb3VyY2VzIjpbInNyYy9yZXBsaWNhdGlvbi9yZXBsaWNhdGlvbi5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7OztBQWFBLE9BQU8sRUFDTCxTQUFTLEVBRVQsU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBRU4sWUFBWSxFQUNiLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBZ0IsUUFBUSxFQUFFLEtBQUssRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUdwRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsNEJBQTRCLEVBQUUsTUFBTSwwREFBMEQsQ0FBQztBQUN4RyxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxnREFBZ0QsQ0FBQztBQUN6RixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFFOUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFPbkUsT0FBTyxFQUNMLFNBQVMsRUFDVCxnQkFBZ0IsRUFDaEIsaUJBQWlCLEVBQ2pCLFdBQVcsRUFDWCxTQUFTLEVBQ1QsYUFBYSxFQUNkLE1BQU0sVUFBVSxDQUFDO0FBT2xCLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2xGLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHNEQUFzRCxDQUFDO0FBRW5HLE9BQU8sRUFBQyxjQUFjLEVBQUUsY0FBYyxFQUFFLFdBQVcsRUFBQyxNQUFNLHNCQUFzQixDQUFDO0FBQ2pGLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGdDQUFnQyxDQUFDOztBQUVoRSxNQUFNLFVBQVUsR0FBMkI7SUFDekMsRUFBRSxHQUFHLEVBQUUs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QW1CO1FBQ3RDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxHQUFHLFdBQVcsQ0FBQztRQUN2QyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7S0FDdEI7Ozs7O0lBRUQsT0FBTyxDQUFDLEtBQXNCO1FBQzVCLE9BQU8sSUFBSSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsRUFBRSxHQUFHLEdBQUcsR0FBRyxLQUFLLEdBQUcsTUFBTSxDQUFDO0tBQ3ZFOzs7WUF2V0YsU0FBUyxTQUFDO2dCQUNULFFBQVEsRUFBRSxpQkFBaUI7Z0JBQzNCLDhtTEFBMkM7O2FBRTVDOzs7O1lBckVRLFlBQVk7WUFFWixrQkFBa0I7WUEwQm5CLGdCQUFnQjtZQWhDZixnQkFBZ0I7Ozt3QkEyRXRCLEtBQUs7MEJBQ0wsS0FBSzs0QkFDTCxLQUFLOzBCQUNMLEtBQUs7aUNBQ0wsS0FBSzt1QkFFTCxNQUFNOzZCQUNOLE1BQU07dUJBQ04sTUFBTTsyQkFDTixNQUFNO2tDQXNCTixTQUFTLFNBQUMsNEJBQTRCO3dDQUd0QyxTQUFTLFNBQUMsdUJBQXVCO3VDQUlqQyxTQUFTLFNBQUMsMEJBQTBCIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IChjKSAyMDE3IFZNd2FyZSwgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuLy9cbi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4vLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4vLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbi8vXG4vLyAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbi8vXG4vLyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4vLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgQkFTSVMsXG4vLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbi8vIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbi8vIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBPbkluaXQsXG4gIFZpZXdDaGlsZCxcbiAgSW5wdXQsXG4gIE91dHB1dCxcbiAgT25EZXN0cm95LFxuICBFdmVudEVtaXR0ZXJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IENvbXBhcmF0b3IsIFN0YXRlIH0gZnJvbSBcIkBjbHIvYW5ndWxhclwiO1xuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCBmb3JrSm9pbiwgdGltZXJ9IGZyb20gXCJyeGpzXCI7XG5cblxuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gXCJAbmd4LXRyYW5zbGF0ZS9jb3JlXCI7XG5cbmltcG9ydCB7IExpc3RSZXBsaWNhdGlvblJ1bGVDb21wb25lbnQgfSBmcm9tIFwiLi4vbGlzdC1yZXBsaWNhdGlvbi1ydWxlL2xpc3QtcmVwbGljYXRpb24tcnVsZS5jb21wb25lbnRcIjtcbmltcG9ydCB7IENyZWF0ZUVkaXRSdWxlQ29tcG9uZW50IH0gZnJvbSBcIi4uL2NyZWF0ZS1lZGl0LXJ1bGUvY3JlYXRlLWVkaXQtcnVsZS5jb21wb25lbnRcIjtcbmltcG9ydCB7IEVycm9ySGFuZGxlciB9IGZyb20gXCIuLi9lcnJvci1oYW5kbGVyL2Vycm9yLWhhbmRsZXJcIjtcblxuaW1wb3J0IHsgUmVwbGljYXRpb25TZXJ2aWNlIH0gZnJvbSBcIi4uL3NlcnZpY2UvcmVwbGljYXRpb24uc2VydmljZVwiO1xuaW1wb3J0IHsgUmVxdWVzdFF1ZXJ5UGFyYW1zIH0gZnJvbSBcIi4uL3NlcnZpY2UvUmVxdWVzdFF1ZXJ5UGFyYW1zXCI7XG5pbXBvcnQge1xuICBSZXBsaWNhdGlvblJ1bGUsXG4gIFJlcGxpY2F0aW9uSm9iLFxuICBSZXBsaWNhdGlvbkpvYkl0ZW1cbn0gZnJvbSBcIi4uL3NlcnZpY2UvaW50ZXJmYWNlXCI7XG5cbmltcG9ydCB7XG4gIHRvUHJvbWlzZSxcbiAgQ3VzdG9tQ29tcGFyYXRvcixcbiAgREVGQVVMVF9QQUdFX1NJWkUsXG4gIGRvRmlsdGVyaW5nLFxuICBkb1NvcnRpbmcsXG4gIGNhbGN1bGF0ZVBhZ2Vcbn0gZnJvbSBcIi4uL3V0aWxzXCI7XG5cbmltcG9ydCB7XG4gIENvbmZpcm1hdGlvblRhcmdldHMsXG4gIENvbmZpcm1hdGlvbkJ1dHRvbnMsXG4gIENvbmZpcm1hdGlvblN0YXRlXG59IGZyb20gXCIuLi9zaGFyZWQvc2hhcmVkLmNvbnN0XCI7XG5pbXBvcnQgeyBDb25maXJtYXRpb25NZXNzYWdlIH0gZnJvbSBcIi4uL2NvbmZpcm1hdGlvbi1kaWFsb2cvY29uZmlybWF0aW9uLW1lc3NhZ2VcIjtcbmltcG9ydCB7IENvbmZpcm1hdGlvbkRpYWxvZ0NvbXBvbmVudCB9IGZyb20gXCIuLi9jb25maXJtYXRpb24tZGlhbG9nL2NvbmZpcm1hdGlvbi1kaWFsb2cuY29tcG9uZW50XCI7XG5pbXBvcnQgeyBDb25maXJtYXRpb25BY2tub3dsZWRnZW1lbnQgfSBmcm9tIFwiLi4vY29uZmlybWF0aW9uLWRpYWxvZy9jb25maXJtYXRpb24tc3RhdGUtbWVzc2FnZVwiO1xuaW1wb3J0IHtvcGVyYXRlQ2hhbmdlcywgT3BlcmF0aW9uU3RhdGUsIE9wZXJhdGVJbmZvfSBmcm9tIFwiLi4vb3BlcmF0aW9uL29wZXJhdGVcIjtcbmltcG9ydCB7T3BlcmF0aW9uU2VydmljZX0gZnJvbSBcIi4uL29wZXJhdGlvbi9vcGVyYXRpb24uc2VydmljZVwiO1xuXG5jb25zdCBydWxlU3RhdHVzOiB7IFtrZXk6IHN0cmluZ106IGFueSB9ID0gW1xuICB7IGtleTogXCJhbGxcIiwgZGVzY3JpcHRpb246IFwiUkVQTElDQVRJT04uQUxMX1NUQVRVU1wiIH0sXG4gIHsga2V5OiBcIjFcIiwgZGVzY3JpcHRpb246IFwiUkVQTElDQVRJT04uRU5BQkxFRFwiIH0sXG4gIHsga2V5OiBcIjBcIiwgZGVzY3JpcHRpb246IFwiUkVQTElDQVRJT04uRElTQUJMRURcIiB9XG5dO1xuXG5jb25zdCBqb2JTdGF0dXM6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSBbXG4gIHsga2V5OiBcImFsbFwiLCBkZXNjcmlwdGlvbjogXCJSRVBMSUNBVElPTi5BTExcIiB9LFxuICB7IGtleTogXCJwZW5kaW5nXCIsIGRlc2NyaXB0aW9uOiBcIlJFUExJQ0FUSU9OLlBFTkRJTkdcIiB9LFxuICB7IGtleTogXCJydW5uaW5nXCIsIGRlc2NyaXB0aW9uOiBcIlJFUExJQ0FUSU9OLlJVTk5JTkdcIiB9LFxuICB7IGtleTogXCJlcnJvclwiLCBkZXNjcmlwdGlvbjogXCJSRVBMSUNBVElPTi5FUlJPUlwiIH0sXG4gIHsga2V5OiBcInJldHJ5aW5nXCIsIGRlc2NyaXB0aW9uOiBcIlJFUExJQ0FUSU9OLlJFVFJZSU5HXCIgfSxcbiAgeyBrZXk6IFwic3RvcHBlZFwiLCBkZXNjcmlwdGlvbjogXCJSRVBMSUNBVElPTi5TVE9QUEVEXCIgfSxcbiAgeyBrZXk6IFwiZmluaXNoZWRcIiwgZGVzY3JpcHRpb246IFwiUkVQTElDQVRJT04uRklOSVNIRURcIiB9LFxuICB7IGtleTogXCJjYW5jZWxlZFwiLCBkZXNjcmlwdGlvbjogXCJSRVBMSUNBVElPTi5DQU5DRUxFRFwiIH1cbl07XG5cbmNvbnN0IG9wdGlvbmFsU2VhcmNoOiB7fSA9IHtcbiAgMDogXCJSRVBMSUNBVElPTi5BRFZBTkNFRFwiLFxuICAxOiBcIlJFUExJQ0FUSU9OLlNJTVBMRVwiXG59O1xuXG5leHBvcnQgY2xhc3MgU2VhcmNoT3B0aW9uIHtcbiAgcnVsZUlkOiBudW1iZXIgfCBzdHJpbmc7XG4gIHJ1bGVOYW1lOiBzdHJpbmcgPSBcIlwiO1xuICByZXBvTmFtZTogc3RyaW5nID0gXCJcIjtcbiAgc3RhdHVzOiBzdHJpbmcgPSBcIlwiO1xuICBzdGFydFRpbWU6IHN0cmluZyA9IFwiXCI7XG4gIHN0YXJ0VGltZXN0YW1wOiBzdHJpbmcgPSBcIlwiO1xuICBlbmRUaW1lOiBzdHJpbmcgPSBcIlwiO1xuICBlbmRUaW1lc3RhbXA6IHN0cmluZyA9IFwiXCI7XG4gIHBhZ2U6IG51bWJlciA9IDE7XG4gIHBhZ2VTaXplOiBudW1iZXIgPSBERUZBVUxUX1BBR0VfU0laRTtcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImhici1yZXBsaWNhdGlvblwiLFxuICB0ZW1wbGF0ZVVybDogXCIuL3JlcGxpY2F0aW9uLmNvbXBvbmVudC5odG1sXCIsXG4gIHN0eWxlVXJsczogW1wiLi9yZXBsaWNhdGlvbi5jb21wb25lbnQuc2Nzc1wiXVxufSlcbmV4cG9ydCBjbGFzcyBSZXBsaWNhdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgQElucHV0KCkgcHJvamVjdElkOiBudW1iZXIgfCBzdHJpbmc7XG4gIEBJbnB1dCgpIHByb2plY3ROYW1lOiBzdHJpbmc7XG4gIEBJbnB1dCgpIGlzU3lzdGVtQWRtaW46IGJvb2xlYW47XG4gIEBJbnB1dCgpIHdpdGhBZG1pcmFsOiBib29sZWFuO1xuICBASW5wdXQoKSB3aXRoUmVwbGljYXRpb25Kb2I6IGJvb2xlYW47XG5cbiAgQE91dHB1dCgpIHJlZGlyZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxSZXBsaWNhdGlvblJ1bGU+KCk7XG4gIEBPdXRwdXQoKSBvcGVuQ3JlYXRlUnVsZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICBAT3V0cHV0KCkgb3BlbkVkaXQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bWJlcj4oKTtcbiAgQE91dHB1dCgpIGdvVG9SZWdpc3RyeSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG4gIHNlYXJjaDogU2VhcmNoT3B0aW9uID0gbmV3IFNlYXJjaE9wdGlvbigpO1xuXG4gIHJ1bGVTdGF0dXMgPSBydWxlU3RhdHVzO1xuICBjdXJyZW50UnVsZVN0YXR1czogeyBrZXk6IHN0cmluZzsgZGVzY3JpcHRpb246IHN0cmluZyB9O1xuXG4gIGpvYlN0YXR1cyA9IGpvYlN0YXR1cztcbiAgY3VycmVudEpvYlN0YXR1czogeyBrZXk6IHN0cmluZzsgZGVzY3JpcHRpb246IHN0cmluZyB9O1xuXG4gIGNoYW5nZWRSdWxlczogUmVwbGljYXRpb25SdWxlW107XG5cbiAgcnVsZXM6IFJlcGxpY2F0aW9uUnVsZVtdO1xuICBsb2FkaW5nOiBib29sZWFuO1xuICBpc1N0b3BPbkdvaW5nOiBib29sZWFuO1xuICBoaWRkZW5Kb2JMaXN0ID0gdHJ1ZTtcblxuICBqb2JzOiBSZXBsaWNhdGlvbkpvYkl0ZW1bXTtcblxuICB0b2dnbGVKb2JTZWFyY2hPcHRpb24gPSBvcHRpb25hbFNlYXJjaDtcbiAgY3VycmVudEpvYlNlYXJjaE9wdGlvbjogbnVtYmVyO1xuXG4gIEBWaWV3Q2hpbGQoTGlzdFJlcGxpY2F0aW9uUnVsZUNvbXBvbmVudClcbiAgbGlzdFJlcGxpY2F0aW9uUnVsZTogTGlzdFJlcGxpY2F0aW9uUnVsZUNvbXBvbmVudDtcblxuICBAVmlld0NoaWxkKENyZWF0ZUVkaXRSdWxlQ29tcG9uZW50KVxuICBjcmVhdGVFZGl0UG9saWN5Q29tcG9uZW50OiBDcmVhdGVFZGl0UnVsZUNvbXBvbmVudDtcblxuXG4gIEBWaWV3Q2hpbGQoXCJyZXBsaWNhdGlvbkNvbmZpcm1EaWFsb2dcIilcbiAgcmVwbGljYXRpb25Db25maXJtRGlhbG9nOiBDb25maXJtYXRpb25EaWFsb2dDb21wb25lbnQ7XG5cbiAgY3JlYXRpb25UaW1lQ29tcGFyYXRvcjogQ29tcGFyYXRvcjxSZXBsaWNhdGlvbkpvYj4gPSBuZXcgQ3VzdG9tQ29tcGFyYXRvcjxcbiAgICBSZXBsaWNhdGlvbkpvYlxuICA+KFwiY3JlYXRpb25fdGltZVwiLCBcImRhdGVcIik7XG4gIHVwZGF0ZVRpbWVDb21wYXJhdG9yOiBDb21wYXJhdG9yPFJlcGxpY2F0aW9uSm9iPiA9IG5ldyBDdXN0b21Db21wYXJhdG9yPFxuICAgIFJlcGxpY2F0aW9uSm9iXG4gID4oXCJ1cGRhdGVfdGltZVwiLCBcImRhdGVcIik7XG5cbiAgLy8gU2VydmVyIGRyaXZlbiBwYWdpbmF0aW9uXG4gIGN1cnJlbnRQYWdlOiBudW1iZXIgPSAxO1xuICB0b3RhbENvdW50OiBudW1iZXIgPSAwO1xuICBwYWdlU2l6ZTogbnVtYmVyID0gREVGQVVMVF9QQUdFX1NJWkU7XG4gIGN1cnJlbnRTdGF0ZTogU3RhdGU7XG4gIGpvYnNMb2FkaW5nOiBib29sZWFuID0gZmFsc2U7XG4gIHRpbWVyRGVsYXk6IFN1YnNjcmlwdGlvbjtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGVycm9ySGFuZGxlcjogRXJyb3JIYW5kbGVyLFxuICAgIHByaXZhdGUgcmVwbGljYXRpb25TZXJ2aWNlOiBSZXBsaWNhdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvcGVyYXRpb25TZXJ2aWNlOiBPcGVyYXRpb25TZXJ2aWNlLFxuICAgIHByaXZhdGUgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSkge31cblxuICBwdWJsaWMgZ2V0IHNob3dQYWdpbmF0aW9uSW5kZXgoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudG90YWxDb3VudCA+IDA7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmN1cnJlbnRSdWxlU3RhdHVzID0gdGhpcy5ydWxlU3RhdHVzWzBdO1xuICAgIHRoaXMuY3VycmVudEpvYlN0YXR1cyA9IHRoaXMuam9iU3RhdHVzWzBdO1xuICAgIHRoaXMuY3VycmVudEpvYlNlYXJjaE9wdGlvbiA9IDA7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy50aW1lckRlbGF5KSB7XG4gICAgICB0aGlzLnRpbWVyRGVsYXkudW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICAvLyBvcGVuIHJlcGxpY2F0aW9uIHJ1bGVcbiAgb3Blbk1vZGFsKCk6IHZvaWQge1xuICAgIHRoaXMuY3JlYXRlRWRpdFBvbGljeUNvbXBvbmVudC5vcGVuQ3JlYXRlRWRpdFJ1bGUoKTtcbiAgfVxuXG4gIC8vIGVkaXQgcmVwbGljYXRpb24gcnVsZVxuICBvcGVuRWRpdFJ1bGUocnVsZTogUmVwbGljYXRpb25SdWxlKSB7XG4gICAgaWYgKHJ1bGUpIHtcbiAgICAgIHRoaXMuY3JlYXRlRWRpdFBvbGljeUNvbXBvbmVudC5vcGVuQ3JlYXRlRWRpdFJ1bGUocnVsZS5pZCk7XG4gICAgfVxuICB9XG5cbiAgZ29SZWdpc3RyeSgpOiB2b2lkIHtcbiAgICB0aGlzLmdvVG9SZWdpc3RyeS5lbWl0KCk7XG4gIH1cblxuICAvLyBTZXJ2ZXIgZHJpdmVuIGRhdGEgbG9hZGluZ1xuICBjbHJMb2FkSm9icyhzdGF0ZTogU3RhdGUpOiB2b2lkIHtcbiAgICBpZiAoIXN0YXRlIHx8ICFzdGF0ZS5wYWdlIHx8ICF0aGlzLnNlYXJjaC5ydWxlSWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50U3RhdGUgPSBzdGF0ZTtcblxuICAgIGxldCBwYWdlTnVtYmVyOiBudW1iZXIgPSBjYWxjdWxhdGVQYWdlKHN0YXRlKTtcbiAgICBpZiAocGFnZU51bWJlciA8PSAwKSB7XG4gICAgICBwYWdlTnVtYmVyID0gMTtcbiAgICB9XG5cbiAgICBsZXQgcGFyYW1zOiBSZXF1ZXN0UXVlcnlQYXJhbXMgPSBuZXcgUmVxdWVzdFF1ZXJ5UGFyYW1zKCk7XG4gICAgLy8gUGFnaW5hdGlvblxuICAgIHBhcmFtcy5zZXQoXCJwYWdlXCIsIFwiXCIgKyBwYWdlTnVtYmVyKTtcbiAgICBwYXJhbXMuc2V0KFwicGFnZV9zaXplXCIsIFwiXCIgKyB0aGlzLnBhZ2VTaXplKTtcbiAgICAvLyBTZWFyY2ggYnkgc3RhdHVzXG4gICAgaWYgKHRoaXMuc2VhcmNoLnN0YXR1cy50cmltKCkpIHtcbiAgICAgIHBhcmFtcy5zZXQoXCJzdGF0dXNcIiwgdGhpcy5zZWFyY2guc3RhdHVzKTtcbiAgICB9XG4gICAgLy8gU2VhcmNoIGJ5IHJlcG9zaXRvcnlcbiAgICBpZiAodGhpcy5zZWFyY2gucmVwb05hbWUudHJpbSgpKSB7XG4gICAgICBwYXJhbXMuc2V0KFwicmVwb3NpdG9yeVwiLCB0aGlzLnNlYXJjaC5yZXBvTmFtZSk7XG4gICAgfVxuICAgIC8vIFNlYXJjaCBieSB0aW1lc3RhbXBzXG4gICAgaWYgKHRoaXMuc2VhcmNoLnN0YXJ0VGltZXN0YW1wLnRyaW0oKSkge1xuICAgICAgcGFyYW1zLnNldChcInN0YXJ0X3RpbWVcIiwgdGhpcy5zZWFyY2guc3RhcnRUaW1lc3RhbXApO1xuICAgIH1cbiAgICBpZiAodGhpcy5zZWFyY2guZW5kVGltZXN0YW1wLnRyaW0oKSkge1xuICAgICAgcGFyYW1zLnNldChcImVuZF90aW1lXCIsIHRoaXMuc2VhcmNoLmVuZFRpbWVzdGFtcCk7XG4gICAgfVxuXG4gICAgdGhpcy5qb2JzTG9hZGluZyA9IHRydWU7XG5cbiAgICAvLyBEbyBmaWx0ZXJpbmcgYW5kIHNvcnRpbmdcbiAgICB0aGlzLmpvYnMgPSBkb0ZpbHRlcmluZzxSZXBsaWNhdGlvbkpvYkl0ZW0+KHRoaXMuam9icywgc3RhdGUpO1xuICAgIHRoaXMuam9icyA9IGRvU29ydGluZzxSZXBsaWNhdGlvbkpvYkl0ZW0+KHRoaXMuam9icywgc3RhdGUpO1xuXG4gICAgdGhpcy5qb2JzTG9hZGluZyA9IGZhbHNlO1xuICAgIHRvUHJvbWlzZTxSZXBsaWNhdGlvbkpvYj4oXG4gICAgICB0aGlzLnJlcGxpY2F0aW9uU2VydmljZS5nZXRKb2JzKHRoaXMuc2VhcmNoLnJ1bGVJZCwgcGFyYW1zKVxuICAgIClcbiAgICAgIC50aGVuKHJlc3BvbnNlID0+IHtcbiAgICAgICAgdGhpcy50b3RhbENvdW50ID0gcmVzcG9uc2UubWV0YWRhdGEueFRvdGFsQ291bnQ7XG4gICAgICAgIHRoaXMuam9icyA9IHJlc3BvbnNlLmRhdGE7XG5cbiAgICAgICAgaWYgKCF0aGlzLnRpbWVyRGVsYXkpIHtcbiAgICAgICAgICB0aGlzLnRpbWVyRGVsYXkgPSB0aW1lcigxMDAwMCwgMTAwMDApLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICBsZXQgY291bnQ6IG51bWJlciA9IDA7XG4gICAgICAgICAgICB0aGlzLmpvYnMuZm9yRWFjaChqb2IgPT4ge1xuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgam9iLnN0YXR1cyA9PT0gXCJwZW5kaW5nXCIgfHxcbiAgICAgICAgICAgICAgICBqb2Iuc3RhdHVzID09PSBcInJ1bm5pbmdcIiB8fFxuICAgICAgICAgICAgICAgIGpvYi5zdGF0dXMgPT09IFwicmV0cnlpbmdcIlxuICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBjb3VudCsrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChjb3VudCA+IDApIHtcbiAgICAgICAgICAgICAgdGhpcy5jbHJMb2FkSm9icyh0aGlzLmN1cnJlbnRTdGF0ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICB0aGlzLnRpbWVyRGVsYXkudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgdGhpcy50aW1lckRlbGF5ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERvIGZpbHRlcmluZyBhbmQgc29ydGluZ1xuICAgICAgICB0aGlzLmpvYnMgPSBkb0ZpbHRlcmluZzxSZXBsaWNhdGlvbkpvYkl0ZW0+KHRoaXMuam9icywgc3RhdGUpO1xuICAgICAgICB0aGlzLmpvYnMgPSBkb1NvcnRpbmc8UmVwbGljYXRpb25Kb2JJdGVtPih0aGlzLmpvYnMsIHN0YXRlKTtcblxuICAgICAgICB0aGlzLmpvYnNMb2FkaW5nID0gZmFsc2U7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKGVycm9yID0+IHtcbiAgICAgICAgdGhpcy5qb2JzTG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmVycm9ySGFuZGxlci5lcnJvcihlcnJvcik7XG4gICAgICB9KTtcbiAgfVxuXG4gIGxvYWRGaXJzdFBhZ2UoKTogdm9pZCB7XG4gICAgbGV0IHN0OiBTdGF0ZSA9IHRoaXMuY3VycmVudFN0YXRlO1xuICAgIGlmICghc3QpIHtcbiAgICAgIHN0ID0ge1xuICAgICAgICBwYWdlOiB7fVxuICAgICAgfTtcbiAgICB9XG4gICAgc3QucGFnZS5zaXplID0gdGhpcy5wYWdlU2l6ZTtcbiAgICBzdC5wYWdlLmZyb20gPSAwO1xuICAgIHN0LnBhZ2UudG8gPSB0aGlzLnBhZ2VTaXplIC0gMTtcblxuICAgIHRoaXMuY2xyTG9hZEpvYnMoc3QpO1xuICB9XG5cbiAgc2VsZWN0T25lUnVsZShydWxlOiBSZXBsaWNhdGlvblJ1bGUpIHtcbiAgICBpZiAocnVsZSAmJiBydWxlLmlkKSB7XG4gICAgICB0aGlzLmhpZGRlbkpvYkxpc3QgPSBmYWxzZTtcbiAgICAgIHRoaXMuc2VhcmNoLnJ1bGVJZCA9IHJ1bGUuaWQgfHwgXCJcIjtcbiAgICAgIHRoaXMuc2VhcmNoLnJlcG9OYW1lID0gXCJcIjtcbiAgICAgIHRoaXMuc2VhcmNoLnN0YXR1cyA9IFwiXCI7XG4gICAgICB0aGlzLmN1cnJlbnRKb2JTZWFyY2hPcHRpb24gPSAwO1xuICAgICAgdGhpcy5jdXJyZW50Sm9iU3RhdHVzID0geyBrZXk6IFwiYWxsXCIsIGRlc2NyaXB0aW9uOiBcIlJFUExJQ0FUSU9OLkFMTFwiIH07XG4gICAgICB0aGlzLmxvYWRGaXJzdFBhZ2UoKTtcbiAgICB9XG4gIH1cblxuICByZXBsaWNhdGVNYW51YWxSdWxlKHJ1bGU6IFJlcGxpY2F0aW9uUnVsZSkge1xuICAgIGlmIChydWxlKSB7XG