UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

170 lines 43.3 kB
import { Component, EventEmitter, Output } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { AlertService, GainsightService, ModalService, OptionsService, Permissions, PluginsService, Status, gettext } from '@c8y/ngx-components'; import { EcosystemService, PRODUCT_EXPERIENCE_ECOSYSTEM } from '@c8y/ngx-components/ecosystem/shared'; import { TranslateService } from '@ngx-translate/core'; import * as i0 from "@angular/core"; import * as i1 from "@angular/router"; import * as i2 from "@c8y/ngx-components"; import * as i3 from "@c8y/ngx-components/ecosystem/shared"; import * as i4 from "@ngx-translate/core"; import * as i5 from "@angular/common"; import * as i6 from "ngx-bootstrap/dropdown"; const DEFAULT_VERSIONS_LIMIT = 20; export class PackageVersionsListComponent { constructor(activatedRoute, pluginsService, ecosystemService, translateService, modal, alertService, optionsService, permissions, gainsightService) { this.activatedRoute = activatedRoute; this.pluginsService = pluginsService; this.ecosystemService = ecosystemService; this.translateService = translateService; this.modal = modal; this.alertService = alertService; this.optionsService = optionsService; this.permissions = permissions; this.gainsightService = gainsightService; this.CURRENT_LOCATION = location.href; this.isLoading = false; this.hasAdminPermissions = false; this.isPackageOwnedByCurrentTenant = false; this.onVersionSelect = new EventEmitter(); } async ngOnInit() { this.isLoading = true; this.hasAdminPermissions = this.permissions.hasRole(Permissions.ROLE_APPLICATION_MANAGEMENT_ADMIN); this.package = this.activatedRoute?.snapshot?.parent?.data?.contextData; this.isPackageOwnedByCurrentTenant = this.ecosystemService.isOwner(this.package); this.versionsLimit = (await this.optionsService.getSystemOption('application', 'versions.limit', DEFAULT_VERSIONS_LIMIT)); this.sortVersions(); this.isLoading = false; } async downloadArchive(appVersion) { this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_VERSIONS, { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PACKAGE_VERSIONS, action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.DOWNLOAD, url: this.CURRENT_LOCATION }); const archiveMO = await this.ecosystemService.getArchiveManagedObject(appVersion.binaryId); await this.ecosystemService.downloadArchive(this.package, { id: appVersion.binaryId, name: archiveMO.name }); } packageVersionUploaded() { this.activatedRoute.snapshot.parent.data.contextData = this.package; this.sortVersions(); this.setUploadedVersionAsLatest(); } selectVersion(version) { this.selectedVersion = version; this.onVersionSelect.emit(version); } async removeVersionPackage(version) { try { await this.ecosystemService.deletePackageVersion(this.package, { version }); this.alertService.success(this.translateService.instant(gettext('Package version {{version}} has been removed'), { version })); this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_VERSIONS, { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PACKAGE_VERSIONS, action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.DELETE, result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SUCCESS, url: this.CURRENT_LOCATION }); } catch (e) { this.alertService.addServerFailure(e); this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_VERSIONS, { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PACKAGE_VERSIONS, action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.DELETE, result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SERVER_FAILURE, url: this.CURRENT_LOCATION }); } if (version === this.selectedVersion) { this.selectVersion(null); } await this.refreshPackage(); } async setVersionAsLatest(appVersion) { try { await this.ecosystemService.setPackageVersionTag(this.package, appVersion.version, [ ...appVersion.tags, 'latest' ]); // TODO added it due to: https://cumulocity.atlassian.net/browse/MTM-48553 // Remove it when BE fixes issues with activeVersion. await this.ecosystemService.setAppActiveVersion(this.package, appVersion.binaryId); this.alertService.success(gettext('Tag has been set.')); this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_VERSIONS, { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PACKAGE_VERSIONS, action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.SET_AS_LATEST, result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SUCCESS, url: this.CURRENT_LOCATION }); } catch (e) { this.alertService.addServerFailure(e); this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_VERSIONS, { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PACKAGE_VERSIONS, action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.SET_AS_LATEST, result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SERVER_FAILURE, url: this.CURRENT_LOCATION }); return; } await this.refreshPackage(); } async acknowledgeLimitReached() { await this.modal.acknowledge(gettext('Package limit exceeded'), this.translateService.instant(gettext('You have reached the maximum number of {{ versionsLimit }} package versions. To add another version, first delete one from the list.'), { versionsLimit: this.versionsLimit }), Status.INFO, gettext('Close')); throw undefined; } async refreshPackage() { this.isLoading = true; this.package = await this.ecosystemService.getApplication(this.package.id); this.activatedRoute.snapshot.parent.data.contextData = this.package; this.sortVersions(); this.isLoading = false; } sortVersions() { this.sortedVersions = this.pluginsService.sortVersions({ list: this.package.applicationVersions, path: ['version'] }, 'desc'); this.toggleUploadPossibility(); } async setUploadedVersionAsLatest() { const uploadedVersion = this.package.applicationVersions[this.package.applicationVersions.length - 1]; try { this.gainsightService.triggerEvent(PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.EVENTS.PACKAGE_VERSIONS, { component: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.COMPONENTS.PACKAGE_VERSIONS, action: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.ACTIONS.UPLOAD, result: PRODUCT_EXPERIENCE_ECOSYSTEM.APPLICATIONS.RESULTS.SUCCESS, url: this.CURRENT_LOCATION }); await this.modal.confirm(gettext('Upload successful'), this.translateService.instant(gettext('Do you want to set version {{version}} as the latest? Deploying a new application will always use this version.'), { version: uploadedVersion.version }), Status.SUCCESS, { ok: gettext('Set as latest`version`'), cancel: gettext('Keep unchanged`version`') }); } catch (e) { await this.refreshPackage(); return; } await this.setVersionAsLatest(uploadedVersion); } toggleUploadPossibility() { this.preUploadCallback = this.sortedVersions.length < this.versionsLimit ? null : this.acknowledgeLimitReached.bind(this); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PackageVersionsListComponent, deps: [{ token: i1.ActivatedRoute }, { token: i2.PluginsService }, { token: i3.EcosystemService }, { token: i4.TranslateService }, { token: i2.ModalService }, { token: i2.AlertService }, { token: i2.OptionsService }, { token: i2.Permissions }, { token: i2.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: PackageVersionsListComponent, selector: "c8y-package-versions-list", outputs: { onVersionSelect: "onVersionSelect" }, ngImport: i0, template: "<div class=\"inner-scroll split-view__list\">\n <div class=\"card-header separator sticky-top bg-component\">\n <div class=\"card-title\" translate>Versions</div>\n </div>\n\n <div class=\"bg-level-1 flex-grow\">\n <div class=\"p-16\" *ngIf=\"isLoading\">\n <c8y-loading></c8y-loading>\n </div>\n <ul class=\"nav c8y-nav-stacked\" *ngIf=\"!isLoading\">\n <li\n class=\"c8y-stacked-item p-t-0 p-b-0 p-r-4\"\n [ngClass]=\"{ active: selectedVersion === applicationVersion.version }\"\n *ngFor=\"let applicationVersion of sortedVersions\"\n >\n <div\n class=\"flex-grow d-flex a-i-center gap-4 p-t-8 p-b-8\"\n (click)=\"selectVersion(applicationVersion.version)\"\n >\n <i c8yIcon=\"big-parcel\" class=\"icon-20\"></i>\n <span class=\"text-label-small\">\n {{ 'Version' | translate }}\n </span>\n <span class=\"text-medium\">{{ applicationVersion.version }}</span>\n <div class=\"text-truncate d-flex j-c-end flex-grow gap-4 flex-wrap m-l-auto\">\n <span *ngFor=\"let tag of applicationVersion.tags\" class=\"label label-info\">\n {{ tag }}\n </span>\n </div>\n </div>\n <div class=\"dropdown\" dropdown *ngIf=\"hasAdminPermissions && isPackageOwnedByCurrentTenant\">\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n type=\"button\"\n title=\"{{ 'Settings' | translate }}\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul *dropdownMenu class=\"dropdown-menu dropdown-menu-right\">\n <li>\n <button\n type=\"button\"\n title=\"{{ 'Set as latest`version`' | translate }}\"\n (click)=\"setVersionAsLatest(applicationVersion)\"\n [disabled]=\"applicationVersion.tags?.includes('latest')\"\n >\n <i c8yIcon=\"collect\" class=\"m-r-4\"></i>\n {{ 'Set as latest`version`' | translate }}\n </button>\n </li>\n <li>\n <button\n type=\"button\"\n title=\"{{ 'Download' | translate }}\"\n (click)=\"downloadArchive(applicationVersion)\"\n >\n <i c8yIcon=\"download\" class=\"m-r-4\"></i>\n {{ 'Download' | translate }}\n </button>\n </li>\n <li>\n <button\n type=\"button\"\n title=\"{{ 'Delete' | translate }}\"\n (click)=\"removeVersionPackage(applicationVersion.version)\"\n [disabled]=\"applicationVersion.tags?.includes('latest')\"\n >\n <i c8yIcon=\"trash\" class=\"m-r-4\"></i>\n {{ 'Delete' | translate }}\n </button>\n </li>\n </ul>\n </div>\n </li>\n </ul>\n </div>\n\n <div\n class=\"card-footer separator sticky-bottom\"\n *ngIf=\"!isLoading && isPackageOwnedByCurrentTenant\"\n >\n <div class=\"form-group m-b-0\">\n <label translate>Upload a new version</label>\n <c8y-upload-archive\n [(application)]=\"package\"\n [uploadNewVersion]=\"true\"\n (refresh)=\"packageVersionUploaded()\"\n [preUploadCallback]=\"preUploadCallback\"\n ></c8y-upload-archive>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i2.C8yTranslateDirective, selector: "[translate],[ngx-translate]" }, { kind: "directive", type: i5.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.LoadingComponent, selector: "c8y-loading", inputs: ["layout", "progress", "message"] }, { kind: "directive", type: i6.BsDropdownMenuDirective, selector: "[bsDropdownMenu],[dropdownMenu]", exportAs: ["bs-dropdown-menu"] }, { kind: "directive", type: i6.BsDropdownToggleDirective, selector: "[bsDropdownToggle],[dropdownToggle]", exportAs: ["bs-dropdown-toggle"] }, { kind: "directive", type: i6.BsDropdownDirective, selector: "[bsDropdown], [dropdown]", inputs: ["placement", "triggers", "container", "dropup", "autoClose", "isAnimated", "insideClick", "isDisabled", "isOpen"], outputs: ["isOpenChange", "onShown", "onHidden"], exportAs: ["bs-dropdown"] }, { kind: "component", type: i3.UploadArchiveComponent, selector: "c8y-upload-archive", inputs: ["application", "uploadNewVersion", "preUploadCallback"], outputs: ["applicationChange", "refresh"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: PackageVersionsListComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-package-versions-list', template: "<div class=\"inner-scroll split-view__list\">\n <div class=\"card-header separator sticky-top bg-component\">\n <div class=\"card-title\" translate>Versions</div>\n </div>\n\n <div class=\"bg-level-1 flex-grow\">\n <div class=\"p-16\" *ngIf=\"isLoading\">\n <c8y-loading></c8y-loading>\n </div>\n <ul class=\"nav c8y-nav-stacked\" *ngIf=\"!isLoading\">\n <li\n class=\"c8y-stacked-item p-t-0 p-b-0 p-r-4\"\n [ngClass]=\"{ active: selectedVersion === applicationVersion.version }\"\n *ngFor=\"let applicationVersion of sortedVersions\"\n >\n <div\n class=\"flex-grow d-flex a-i-center gap-4 p-t-8 p-b-8\"\n (click)=\"selectVersion(applicationVersion.version)\"\n >\n <i c8yIcon=\"big-parcel\" class=\"icon-20\"></i>\n <span class=\"text-label-small\">\n {{ 'Version' | translate }}\n </span>\n <span class=\"text-medium\">{{ applicationVersion.version }}</span>\n <div class=\"text-truncate d-flex j-c-end flex-grow gap-4 flex-wrap m-l-auto\">\n <span *ngFor=\"let tag of applicationVersion.tags\" class=\"label label-info\">\n {{ tag }}\n </span>\n </div>\n </div>\n <div class=\"dropdown\" dropdown *ngIf=\"hasAdminPermissions && isPackageOwnedByCurrentTenant\">\n <button\n class=\"dropdown-toggle c8y-dropdown\"\n type=\"button\"\n title=\"{{ 'Settings' | translate }}\"\n dropdownToggle\n >\n <i c8yIcon=\"ellipsis-v\"></i>\n </button>\n <ul *dropdownMenu class=\"dropdown-menu dropdown-menu-right\">\n <li>\n <button\n type=\"button\"\n title=\"{{ 'Set as latest`version`' | translate }}\"\n (click)=\"setVersionAsLatest(applicationVersion)\"\n [disabled]=\"applicationVersion.tags?.includes('latest')\"\n >\n <i c8yIcon=\"collect\" class=\"m-r-4\"></i>\n {{ 'Set as latest`version`' | translate }}\n </button>\n </li>\n <li>\n <button\n type=\"button\"\n title=\"{{ 'Download' | translate }}\"\n (click)=\"downloadArchive(applicationVersion)\"\n >\n <i c8yIcon=\"download\" class=\"m-r-4\"></i>\n {{ 'Download' | translate }}\n </button>\n </li>\n <li>\n <button\n type=\"button\"\n title=\"{{ 'Delete' | translate }}\"\n (click)=\"removeVersionPackage(applicationVersion.version)\"\n [disabled]=\"applicationVersion.tags?.includes('latest')\"\n >\n <i c8yIcon=\"trash\" class=\"m-r-4\"></i>\n {{ 'Delete' | translate }}\n </button>\n </li>\n </ul>\n </div>\n </li>\n </ul>\n </div>\n\n <div\n class=\"card-footer separator sticky-bottom\"\n *ngIf=\"!isLoading && isPackageOwnedByCurrentTenant\"\n >\n <div class=\"form-group m-b-0\">\n <label translate>Upload a new version</label>\n <c8y-upload-archive\n [(application)]=\"package\"\n [uploadNewVersion]=\"true\"\n (refresh)=\"packageVersionUploaded()\"\n [preUploadCallback]=\"preUploadCallback\"\n ></c8y-upload-archive>\n </div>\n </div>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.ActivatedRoute }, { type: i2.PluginsService }, { type: i3.EcosystemService }, { type: i4.TranslateService }, { type: i2.ModalService }, { type: i2.AlertService }, { type: i2.OptionsService }, { type: i2.Permissions }, { type: i2.GainsightService }], propDecorators: { onVersionSelect: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFja2FnZS12ZXJzaW9ucy1saXN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2Vjb3N5c3RlbS9wYWNrYWdlcy9wYWNrYWdlLXZlcnNpb25zL3BhY2thZ2UtdmVyc2lvbnMtbGlzdC9wYWNrYWdlLXZlcnNpb25zLWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vZWNvc3lzdGVtL3BhY2thZ2VzL3BhY2thZ2UtdmVyc2lvbnMvcGFja2FnZS12ZXJzaW9ucy1saXN0L3BhY2thZ2UtdmVyc2lvbnMtbGlzdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDeEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRWpELE9BQU8sRUFDTCxZQUFZLEVBQ1osZ0JBQWdCLEVBQ2hCLFlBQVksRUFDWixjQUFjLEVBQ2QsV0FBVyxFQUNYLGNBQWMsRUFDZCxNQUFNLEVBQ04sT0FBTyxFQUNSLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxFQUNMLGdCQUFnQixFQUNoQiw0QkFBNEIsRUFDN0IsTUFBTSxzQ0FBc0MsQ0FBQztBQUM5QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7Ozs7Ozs7QUFFdkQsTUFBTSxzQkFBc0IsR0FBRyxFQUFFLENBQUM7QUFNbEMsTUFBTSxPQUFPLDRCQUE0QjtJQWN2QyxZQUNVLGNBQThCLEVBQzlCLGNBQThCLEVBQzlCLGdCQUFrQyxFQUNsQyxnQkFBa0MsRUFDbEMsS0FBbUIsRUFDbkIsWUFBMEIsRUFDMUIsY0FBOEIsRUFDOUIsV0FBd0IsRUFDeEIsZ0JBQWtDO1FBUmxDLG1CQUFjLEdBQWQsY0FBYyxDQUFnQjtRQUM5QixtQkFBYyxHQUFkLGNBQWMsQ0FBZ0I7UUFDOUIs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QXlCLENBQUM7YUFDM0MsQ0FDRixDQUFDO1FBQ0osQ0FBQztRQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUM1QixPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sSUFBSSxDQUFDLGtCQUFrQixDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBQ2pELENBQUM7SUFFTyx1QkFBdUI7UUFDN0IsSUFBSSxDQUFDLGlCQUFpQjtZQUNwQixJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYTtnQkFDN0MsQ0FBQyxDQUFDLElBQUk7Z0JBQ04sQ0FBQyxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEQsQ0FBQzsrR0FyTlUsNEJBQTRCO21HQUE1Qiw0QkFBNEIsa0hDekJ6QywrN0dBNkZBOzs0RkRwRWEsNEJBQTRCO2tCQUp4QyxTQUFTOytCQUNFLDJCQUEyQjswVEFlM0IsZUFBZTtzQkFBeEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgSUFwcGxpY2F0aW9uLCBJQXBwbGljYXRpb25WZXJzaW9uIH0gZnJvbSAnQGM4eS9jbGllbnQnO1xuaW1wb3J0IHtcbiAgQWxlcnRTZXJ2aWNlLFxuICBHYWluc2lnaHRTZXJ2aWNlLFxuICBNb2RhbFNlcnZpY2UsXG4gIE9wdGlvbnNTZXJ2aWNlLFxuICBQZXJtaXNzaW9ucyxcbiAgUGx1Z2luc1NlcnZpY2UsXG4gIFN0YXR1cyxcbiAgZ2V0dGV4dFxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcbmltcG9ydCB7XG4gIEVjb3N5c3RlbVNlcnZpY2UsXG4gIFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU1cbn0gZnJvbSAnQGM4eS9uZ3gtY29tcG9uZW50cy9lY29zeXN0ZW0vc2hhcmVkJztcbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcblxuY29uc3QgREVGQVVMVF9WRVJTSU9OU19MSU1JVCA9IDIwO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktcGFja2FnZS12ZXJzaW9ucy1saXN0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL3BhY2thZ2UtdmVyc2lvbnMtbGlzdC5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgUGFja2FnZVZlcnNpb25zTGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIENVUlJFTlRfTE9DQVRJT04gPSBsb2NhdGlvbi5ocmVmO1xuXG4gIHZlcnNpb25zTGltaXQ6IG51bWJlcjtcbiAgaXNMb2FkaW5nID0gZmFsc2U7XG4gIHBhY2thZ2U6IElBcHBsaWNhdGlvbjtcbiAgc29ydGVkVmVyc2lvbnM6IElBcHBsaWNhdGlvblZlcnNpb25bXTtcbiAgc2VsZWN0ZWRWZXJzaW9uOiBzdHJpbmc7XG4gIHByZVVwbG9hZENhbGxiYWNrOiAoKSA9PiBQcm9taXNlPGFueT47XG4gIGhhc0FkbWluUGVybWlzc2lvbnMgPSBmYWxzZTtcbiAgaXNQYWNrYWdlT3duZWRCeUN1cnJlbnRUZW5hbnQgPSBmYWxzZTtcblxuICBAT3V0cHV0KCkgb25WZXJzaW9uU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmcgfCBudWxsPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgYWN0aXZhdGVkUm91dGU6IEFjdGl2YXRlZFJvdXRlLFxuICAgIHByaXZhdGUgcGx1Z2luc1NlcnZpY2U6IFBsdWdpbnNTZXJ2aWNlLFxuICAgIHByaXZhdGUgZWNvc3lzdGVtU2VydmljZTogRWNvc3lzdGVtU2VydmljZSxcbiAgICBwcml2YXRlIHRyYW5zbGF0ZVNlcnZpY2U6IFRyYW5zbGF0ZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBtb2RhbDogTW9kYWxTZXJ2aWNlLFxuICAgIHByaXZhdGUgYWxlcnRTZXJ2aWNlOiBBbGVydFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBvcHRpb25zU2VydmljZTogT3B0aW9uc1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBwZXJtaXNzaW9uczogUGVybWlzc2lvbnMsXG4gICAgcHJpdmF0ZSBnYWluc2lnaHRTZXJ2aWNlOiBHYWluc2lnaHRTZXJ2aWNlXG4gICkge31cblxuICBhc3luYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmlzTG9hZGluZyA9IHRydWU7XG4gICAgdGhpcy5oYXNBZG1pblBlcm1pc3Npb25zID0gdGhpcy5wZXJtaXNzaW9ucy5oYXNSb2xlKFxuICAgICAgUGVybWlzc2lvbnMuUk9MRV9BUFBMSUNBVElPTl9NQU5BR0VNRU5UX0FETUlOXG4gICAgKTtcbiAgICB0aGlzLnBhY2thZ2UgPSB0aGlzLmFjdGl2YXRlZFJvdXRlPy5zbmFwc2hvdD8ucGFyZW50Py5kYXRhPy5jb250ZXh0RGF0YTtcbiAgICB0aGlzLmlzUGFja2FnZU93bmVkQnlDdXJyZW50VGVuYW50ID0gdGhpcy5lY29zeXN0ZW1TZXJ2aWNlLmlzT3duZXIodGhpcy5wYWNrYWdlKTtcbiAgICB0aGlzLnZlcnNpb25zTGltaXQgPSAoYXdhaXQgdGhpcy5vcHRpb25zU2VydmljZS5nZXRTeXN0ZW1PcHRpb24oXG4gICAgICAnYXBwbGljYXRpb24nLFxuICAgICAgJ3ZlcnNpb25zLmxpbWl0JyxcbiAgICAgIERFRkFVTFRfVkVSU0lPTlNfTElNSVRcbiAgICApKSBhcyBudW1iZXI7XG4gICAgdGhpcy5zb3J0VmVyc2lvbnMoKTtcbiAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xuICB9XG5cbiAgYXN5bmMgZG93bmxvYWRBcmNoaXZlKGFwcFZlcnNpb246IElBcHBsaWNhdGlvblZlcnNpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLmdhaW5zaWdodFNlcnZpY2UudHJpZ2dlckV2ZW50KFxuICAgICAgUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuRVZFTlRTLlBBQ0tBR0VfVkVSU0lPTlMsXG4gICAgICB7XG4gICAgICAgIGNvbXBvbmVudDogUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuQ09NUE9ORU5UUy5QQUNLQUdFX1ZFUlNJT05TLFxuICAgICAgICBhY3Rpb246IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkFDVElPTlMuRE9XTkxPQUQsXG4gICAgICAgIHVybDogdGhpcy5DVVJSRU5UX0xPQ0FUSU9OXG4gICAgICB9XG4gICAgKTtcbiAgICBjb25zdCBhcmNoaXZlTU8gPSBhd2FpdCB0aGlzLmVjb3N5c3RlbVNlcnZpY2UuZ2V0QXJjaGl2ZU1hbmFnZWRPYmplY3QoYXBwVmVyc2lvbi5iaW5hcnlJZCk7XG4gICAgYXdhaXQgdGhpcy5lY29zeXN0ZW1TZXJ2aWNlLmRvd25sb2FkQXJjaGl2ZSh0aGlzLnBhY2thZ2UsIHtcbiAgICAgIGlkOiBhcHBWZXJzaW9uLmJpbmFyeUlkLFxuICAgICAgbmFtZTogYXJjaGl2ZU1PLm5hbWVcbiAgICB9KTtcbiAgfVxuXG4gIHBhY2thZ2VWZXJzaW9uVXBsb2FkZWQoKSB7XG4gICAgdGhpcy5hY3RpdmF0ZWRSb3V0ZS5zbmFwc2hvdC5wYXJlbnQuZGF0YS5jb250ZXh0RGF0YSA9IHRoaXMucGFja2FnZTtcbiAgICB0aGlzLnNvcnRWZXJzaW9ucygpO1xuICAgIHRoaXMuc2V0VXBsb2FkZWRWZXJzaW9uQXNMYXRlc3QoKTtcbiAgfVxuXG4gIHNlbGVjdFZlcnNpb24odmVyc2lvbjogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIHRoaXMuc2VsZWN0ZWRWZXJzaW9uID0gdmVyc2lvbjtcbiAgICB0aGlzLm9uVmVyc2lvblNlbGVjdC5lbWl0KHZlcnNpb24pO1xuICB9XG5cbiAgYXN5bmMgcmVtb3ZlVmVyc2lvblBhY2thZ2UodmVyc2lvbjogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWNvc3lzdGVtU2VydmljZS5kZWxldGVQYWNrYWdlVmVyc2lvbih0aGlzLnBhY2thZ2UsIHsgdmVyc2lvbiB9KTtcbiAgICAgIHRoaXMuYWxlcnRTZXJ2aWNlLnN1Y2Nlc3MoXG4gICAgICAgIHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ1BhY2thZ2UgdmVyc2lvbiB7e3ZlcnNpb259fSBoYXMgYmVlbiByZW1vdmVkJyksIHtcbiAgICAgICAgICB2ZXJzaW9uXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgICAgdGhpcy5nYWluc2lnaHRTZXJ2aWNlLnRyaWdnZXJFdmVudChcbiAgICAgICAgUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuRVZFTlRTLlBBQ0tBR0VfVkVSU0lPTlMsXG4gICAgICAgIHtcbiAgICAgICAgICBjb21wb25lbnQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkNPTVBPTkVOVFMuUEFDS0FHRV9WRVJTSU9OUyxcbiAgICAgICAgICBhY3Rpb246IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkFDVElPTlMuREVMRVRFLFxuICAgICAgICAgIHJlc3VsdDogUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuUkVTVUxUUy5TVUNDRVNTLFxuICAgICAgICAgIHVybDogdGhpcy5DVVJSRU5UX0xPQ0FUSU9OXG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2UuYWRkU2VydmVyRmFpbHVyZShlKTtcbiAgICAgIHRoaXMuZ2FpbnNpZ2h0U2VydmljZS50cmlnZ2VyRXZlbnQoXG4gICAgICAgIFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkVWRU5UUy5QQUNLQUdFX1ZFUlNJT05TLFxuICAgICAgICB7XG4gICAgICAgICAgY29tcG9uZW50OiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5DT01QT05FTlRTLlBBQ0tBR0VfVkVSU0lPTlMsXG4gICAgICAgICAgYWN0aW9uOiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5BQ1RJT05TLkRFTEVURSxcbiAgICAgICAgICByZXN1bHQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLlJFU1VMVFMuU0VSVkVSX0ZBSUxVUkUsXG4gICAgICAgICAgdXJsOiB0aGlzLkNVUlJFTlRfTE9DQVRJT05cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKHZlcnNpb24gPT09IHRoaXMuc2VsZWN0ZWRWZXJzaW9uKSB7XG4gICAgICB0aGlzLnNlbGVjdFZlcnNpb24obnVsbCk7XG4gICAgfVxuICAgIGF3YWl0IHRoaXMucmVmcmVzaFBhY2thZ2UoKTtcbiAgfVxuXG4gIGFzeW5jIHNldFZlcnNpb25Bc0xhdGVzdChhcHBWZXJzaW9uOiBJQXBwbGljYXRpb25WZXJzaW9uKSB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuZWNvc3lzdGVtU2VydmljZS5zZXRQYWNrYWdlVmVyc2lvblRhZyh0aGlzLnBhY2thZ2UsIGFwcFZlcnNpb24udmVyc2lvbiwgW1xuICAgICAgICAuLi5hcHBWZXJzaW9uLnRhZ3MsXG4gICAgICAgICdsYXRlc3QnXG4gICAgICBdKTtcblxuICAgICAgLy8gVE9ETyBhZGRlZCBpdCBkdWUgdG86IGh0dHBzOi8vY3VtdWxvY2l0eS5hdGxhc3NpYW4ubmV0L2Jyb3dzZS9NVE0tNDg1NTNcbiAgICAgIC8vIFJlbW92ZSBpdCB3aGVuIEJFIGZpeGVzIGlzc3VlcyB3aXRoIGFjdGl2ZVZlcnNpb24uXG4gICAgICBhd2FpdCB0aGlzLmVjb3N5c3RlbVNlcnZpY2Uuc2V0QXBwQWN0aXZlVmVyc2lvbih0aGlzLnBhY2thZ2UsIGFwcFZlcnNpb24uYmluYXJ5SWQpO1xuICAgICAgdGhpcy5hbGVydFNlcnZpY2Uuc3VjY2VzcyhnZXR0ZXh0KCdUYWcgaGFzIGJlZW4gc2V0LicpKTtcbiAgICAgIHRoaXMuZ2FpbnNpZ2h0U2VydmljZS50cmlnZ2VyRXZlbnQoXG4gICAgICAgIFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkVWRU5UUy5QQUNLQUdFX1ZFUlNJT05TLFxuICAgICAgICB7XG4gICAgICAgICAgY29tcG9uZW50OiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5DT01QT05FTlRTLlBBQ0tBR0VfVkVSU0lPTlMsXG4gICAgICAgICAgYWN0aW9uOiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5BQ1RJT05TLlNFVF9BU19MQVRFU1QsXG4gICAgICAgICAgcmVzdWx0OiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5SRVNVTFRTLlNVQ0NFU1MsXG4gICAgICAgICAgdXJsOiB0aGlzLkNVUlJFTlRfTE9DQVRJT05cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0aGlzLmFsZXJ0U2VydmljZS5hZGRTZXJ2ZXJGYWlsdXJlKGUpO1xuICAgICAgdGhpcy5nYWluc2lnaHRTZXJ2aWNlLnRyaWdnZXJFdmVudChcbiAgICAgICAgUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuRVZFTlRTLlBBQ0tBR0VfVkVSU0lPTlMsXG4gICAgICAgIHtcbiAgICAgICAgICBjb21wb25lbnQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkNPTVBPTkVOVFMuUEFDS0FHRV9WRVJTSU9OUyxcbiAgICAgICAgICBhY3Rpb246IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLkFDVElPTlMuU0VUX0FTX0xBVEVTVCxcbiAgICAgICAgICByZXN1bHQ6IFBST0RVQ1RfRVhQRVJJRU5DRV9FQ09TWVNURU0uQVBQTElDQVRJT05TLlJFU1VMVFMuU0VSVkVSX0ZBSUxVUkUsXG4gICAgICAgICAgdXJsOiB0aGlzLkNVUlJFTlRfTE9DQVRJT05cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5yZWZyZXNoUGFja2FnZSgpO1xuICB9XG5cbiAgYXN5bmMgYWNrbm93bGVkZ2VMaW1pdFJlYWNoZWQoKSB7XG4gICAgYXdhaXQgdGhpcy5tb2RhbC5hY2tub3dsZWRnZShcbiAgICAgIGdldHRleHQoJ1BhY2thZ2UgbGltaXQgZXhjZWVkZWQnKSxcbiAgICAgIHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KFxuICAgICAgICBnZXR0ZXh0KFxuICAgICAgICAgICdZb3UgaGF2ZSByZWFjaGVkIHRoZSBtYXhpbXVtIG51bWJlciBvZiB7eyB2ZXJzaW9uc0xpbWl0IH19IHBhY2thZ2UgdmVyc2lvbnMuIFRvIGFkZCBhbm90aGVyIHZlcnNpb24sIGZpcnN0IGRlbGV0ZSBvbmUgZnJvbSB0aGUgbGlzdC4nXG4gICAgICAgICksXG4gICAgICAgIHsgdmVyc2lvbnNMaW1pdDogdGhpcy52ZXJzaW9uc0xpbWl0IH1cbiAgICAgICksXG4gICAgICBTdGF0dXMuSU5GTyxcbiAgICAgIGdldHRleHQoJ0Nsb3NlJylcbiAgICApO1xuICAgIHRocm93IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcmVmcmVzaFBhY2thZ2UoKSB7XG4gICAgdGhpcy5pc0xvYWRpbmcgPSB0cnVlO1xuICAgIHRoaXMucGFja2FnZSA9IGF3YWl0IHRoaXMuZWNvc3lzdGVtU2VydmljZS5nZXRBcHBsaWNhdGlvbih0aGlzLnBhY2thZ2UuaWQpO1xuICAgIHRoaXMuYWN0aXZhdGVkUm91dGUuc25hcHNob3QucGFyZW50LmRhdGEuY29udGV4dERhdGEgPSB0aGlzLnBhY2thZ2U7XG4gICAgdGhpcy5zb3J0VmVyc2lvbnMoKTtcbiAgICB0aGlzLmlzTG9hZGluZyA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBzb3J0VmVyc2lvbnMoKSB7XG4gICAgdGhpcy5zb3J0ZWRWZXJzaW9ucyA9IHRoaXMucGx1Z2luc1NlcnZpY2Uuc29ydFZlcnNpb25zKFxuICAgICAge1xuICAgICAgICBsaXN0OiB0aGlzLnBhY2thZ2UuYXBwbGljYXRpb25WZXJzaW9ucyxcbiAgICAgICAgcGF0aDogWyd2ZXJzaW9uJ11cbiAgICAgIH0sXG4gICAgICAnZGVzYydcbiAgICApO1xuICAgIHRoaXMudG9nZ2xlVXBsb2FkUG9zc2liaWxpdHkoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2V0VXBsb2FkZWRWZXJzaW9uQXNMYXRlc3QoKSB7XG4gICAgY29uc3QgdXBsb2FkZWRWZXJzaW9uID1cbiAgICAgIHRoaXMucGFja2FnZS5hcHBsaWNhdGlvblZlcnNpb25zW3RoaXMucGFja2FnZS5hcHBsaWNhdGlvblZlcnNpb25zLmxlbmd0aCAtIDFdO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmdhaW5zaWdodFNlcnZpY2UudHJpZ2dlckV2ZW50KFxuICAgICAgICBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5FVkVOVFMuUEFDS0FHRV9WRVJTSU9OUyxcbiAgICAgICAge1xuICAgICAgICAgIGNvbXBvbmVudDogUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuQ09NUE9ORU5UUy5QQUNLQUdFX1ZFUlNJT05TLFxuICAgICAgICAgIGFjdGlvbjogUFJPRFVDVF9FWFBFUklFTkNFX0VDT1NZU1RFTS5BUFBMSUNBVElPTlMuQUNUSU9OUy5VUExPQUQsXG4gICAgICAgICAgcmVzdWx0OiBQUk9EVUNUX0VYUEVSSUVOQ0VfRUNPU1lTVEVNLkFQUExJQ0FUSU9OUy5SRVNVTFRTLlNVQ0NFU1MsXG4gICAgICAgICAgdXJsOiB0aGlzLkNVUlJFTlRfTE9DQVRJT05cbiAgICAgICAgfVxuICAgICAgKTtcbiAgICAgIGF3YWl0IHRoaXMubW9kYWwuY29uZmlybShcbiAgICAgICAgZ2V0dGV4dCgnVXBsb2FkIHN1Y2Nlc3NmdWwnKSxcbiAgICAgICAgdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoXG4gICAgICAgICAgZ2V0dGV4dChcbiAgICAgICAgICAgICdEbyB5b3Ugd2FudCB0byBzZXQgdmVyc2lvbiB7e3ZlcnNpb259fSBhcyB0aGUgbGF0ZXN0PyBEZXBsb3lpbmcgYSBuZXcgYXBwbGljYXRpb24gd2lsbCBhbHdheXMgdXNlIHRoaXMgdmVyc2lvbi4nXG4gICAgICAgICAgKSxcbiAgICAgICAgICB7IHZlcnNpb246IHVwbG9hZGVkVmVyc2lvbi52ZXJzaW9uIH1cbiAgICAgICAgKSxcbiAgICAgICAgU3RhdHVzLlNVQ0NFU1MsXG4gICAgICAgIHtcbiAgICAgICAgICBvazogZ2V0dGV4dCgnU2V0IGFzIGxhdGVzdGB2ZXJzaW9uYCcpLFxuICAgICAgICAgIGNhbmNlbDogZ2V0dGV4dCgnS2VlcCB1bmNoYW5nZWRgdmVyc2lvbmAnKVxuICAgICAgICB9XG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGF3YWl0IHRoaXMucmVmcmVzaFBhY2thZ2UoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5zZXRWZXJzaW9uQXNMYXRlc3QodXBsb2FkZWRWZXJzaW9uKTtcbiAgfVxuXG4gIHByaXZhdGUgdG9nZ2xlVXBsb2FkUG9zc2liaWxpdHkoKSB7XG4gICAgdGhpcy5wcmVVcGxvYWRDYWxsYmFjayA9XG4gICAgICB0aGlzLnNvcnRlZFZlcnNpb25zLmxlbmd0aCA8IHRoaXMudmVyc2lvbnNMaW1pdFxuICAgICAgICA/IG51bGxcbiAgICAgICAgOiB0aGlzLmFja25vd2xlZGdlTGltaXRSZWFjaGVkLmJpbmQodGhpcyk7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJpbm5lci1zY3JvbGwgc3BsaXQtdmlld19fbGlzdFwiPlxuICA8ZGl2IGNsYXNzPVwiY2FyZC1oZWFkZXIgc2VwYXJhdG9yIHN0aWNreS10b3AgYmctY29tcG9uZW50XCI+XG4gICAgPGRpdiBjbGFzcz1cImNhcmQtdGl0bGVcIiB0cmFuc2xhdGU+VmVyc2lvbnM8L2Rpdj5cbiAgPC9kaXY+XG5cbiAgPGRpdiBjbGFzcz1cImJnLWxldmVsLTEgZmxleC1ncm93XCI+XG4gICAgPGRpdiBjbGFzcz1cInAtMTZcIiAqbmdJZj1cImlzTG9hZGluZ1wiPlxuICAgICAgPGM4eS1sb2FkaW5nPjwvYzh5LWxvYWRpbmc+XG4gICAgPC9kaXY+XG4gICAgPHVsIGNsYXNzPVwibmF2IGM4eS1uYXYtc3RhY2tlZFwiICpuZ0lmPVwiIWlzTG9hZGluZ1wiPlxuICAgICAgPGxpXG4gICAgICAgIGNsYXNzPVwiYzh5LXN0YWNrZWQtaXRlbSBwLXQtMCBwLWItMCBwLXItNFwiXG4gICAgICAgIFtuZ0NsYXNzXT1cInsgYWN0aXZlOiBzZWxlY3RlZFZlcnNpb24gPT09IGFwcGxpY2F0aW9uVmVyc2lvbi52ZXJzaW9uIH1cIlxuICAgICAgICAqbmdGb3I9XCJsZXQgYXBwbGljYXRpb25WZXJzaW9uIG9mIHNvcnRlZFZlcnNpb25zXCJcbiAgICAgID5cbiAgICAgICAgPGRpdlxuICAgICAgICAgIGNsYXNzPVwiZmxleC1ncm93IGQtZmxleCBhLWktY2VudGVyIGdhcC00IHAtdC04IHAtYi04XCJcbiAgICAgICAgICAoY2xpY2spPVwic2VsZWN0VmVyc2lvbihhcHBsaWNhdGlvblZlcnNpb24udmVyc2lvbilcIlxuICAgICAgICA+XG4gICAgICAgICAgPGkgYzh5SWNvbj1cImJpZy1wYXJjZWxcIiBjbGFzcz1cImljb24tMjBcIj48L2k+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LWxhYmVsLXNtYWxsXCI+XG4gICAgICAgICAgICB7eyAnVmVyc2lvbicgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LW1lZGl1bVwiPnt7IGFwcGxpY2F0aW9uVmVyc2lvbi52ZXJzaW9uIH19PC9zcGFuPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlIGQtZmxleCBqLWMtZW5kIGZsZXgtZ3JvdyBnYXAtNCBmbGV4LXdyYXAgbS1sLWF1dG9cIj5cbiAgICAgICAgICAgIDxzcGFuICpuZ0Zvcj1cImxldCB0YWcgb2YgYXBwbGljYXRpb25WZXJzaW9uLnRhZ3NcIiBjbGFzcz1cImxhYmVsIGxhYmVsLWluZm9cIj5cbiAgICAgICAgICAgICAge3sgdGFnIH19XG4gICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZHJvcGRvd25cIiBkcm9wZG93biAqbmdJZj1cImhhc0FkbWluUGVybWlzc2lvbnMgJiYgaXNQYWNrYWdlT3duZWRCeUN1cnJlbnRUZW5hbnRcIj5cbiAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICBjbGFzcz1cImRyb3Bkb3duLXRvZ2dsZSBjOHktZHJvcGRvd25cIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICB0aXRsZT1cInt7ICdTZXR0aW5ncycgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgZHJvcGRvd25Ub2dnbGVcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8aSBjOHlJY29uPVwiZWxsaXBzaXMtdlwiPjwvaT5cbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8dWwgKmRyb3Bkb3duTWVudSBjbGFzcz1cImRyb3Bkb3duLW1lbnUgZHJvcGRvd24tbWVudS1yaWdodFwiPlxuICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJ7eyAnU2V0IGFzIGxhdGVzdGB2ZXJzaW9uYCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJzZXRWZXJzaW9uQXNMYXRlc3QoYXBwbGljYXRpb25WZXJzaW9uKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImFwcGxpY2F0aW9uVmVyc2lvbi50YWdzPy5pbmNsdWRlcygnbGF0ZXN0JylcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGkgYzh5SWNvbj1cImNvbGxlY3RcIiBjbGFzcz1cIm0tci00XCI+PC9pPlxuICAgICAgICAgICAgICAgIHt7ICdTZXQgYXMgbGF0ZXN0YHZlcnNpb25gJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICA8bGk+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICB0aXRsZT1cInt7ICdEb3dubG9hZCcgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJkb3dubG9hZEFyY2hpdmUoYXBwbGljYXRpb25WZXJzaW9uKVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8aSBjOHlJY29uPVwiZG93bmxvYWRcIiBjbGFzcz1cIm0tci00XCI+PC9pPlxuICAgICAgICAgICAgICAgIHt7ICdEb3dubG9hZCcgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L2xpPlxuICAgICAgICAgICAgPGxpPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJ7eyAnRGVsZXRlJyB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZVZlcnNpb25QYWNrYWdlKGFwcGxpY2F0aW9uVmVyc2lvbi52ZXJzaW9uKVwiXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImFwcGxpY2F0aW9uVmVyc2lvbi50YWdzPy5pbmNsdWRlcygnbGF0ZXN0JylcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGkgYzh5SWNvbj1cInRyYXNoXCIgY2xhc3M9XCJtLXItNFwiPjwvaT5cbiAgICAgICAgICAgICAgICB7eyAnRGVsZXRlJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgPC91bD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2xpPlxuICAgIDwvdWw+XG4gIDwvZGl2PlxuXG4gIDxkaXZcbiAgICBjbGFzcz1cImNhcmQtZm9vdGVyIHNlcGFyYXRvciBzdGlja3ktYm90dG9tXCJcbiAgICAqbmdJZj1cIiFpc0xvYWRpbmcgJiYgaXNQYWNrYWdlT3duZWRCeUN1cnJlbnRUZW5hbnRcIlxuICA+XG4gICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXAgbS1iLTBcIj5cbiAgICAgIDxsYWJlbCB0cmFuc2xhdGU+VXBsb2FkIGEgbmV3IHZlcnNpb248L2xhYmVsPlxuICAgICAgPGM4eS11cGxvYWQtYXJjaGl2ZVxuICAgICAgICBbKGFwcGxpY2F0aW9uKV09XCJwYWNrYWdlXCJcbiAgICAgICAgW3VwbG9hZE5ld1ZlcnNpb25dPVwidHJ1ZVwiXG4gICAgICAgIChyZWZyZXNoKT1cInBhY2thZ2VWZXJzaW9uVXBsb2FkZWQoKVwiXG4gICAgICAgIFtwcmVVcGxvYWRDYWxsYmFja109XCJwcmVVcGxvYWRDYWxsYmFja1wiXG4gICAgICA+PC9jOHktdXBsb2FkLWFyY2hpdmU+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=