UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

153 lines 32.6 kB
import { Component, EventEmitter, Input, Optional, Output } from '@angular/core'; import { gettext } from '@c8y/ngx-components'; import { mergeWith, map as _map, filter, flatten, uniqBy, identity, property, get, reduce } from 'lodash-es'; import { BehaviorSubject, combineLatest } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { Ng1RolesService, Ng1UserInventoryRolesService } from '@c8y/ngx-components/upgrade/upgraded-services'; import * as i0 from "@angular/core"; import * as i1 from "@c8y/ngx-components/upgrade/upgraded-services"; import * as i2 from "@c8y/ngx-components"; import * as i3 from "@angular/common"; import * as i4 from "../inventory-role-selector/inventory-role-selector.component"; export class RolesAssetTreeComponent { constructor(c8yUserInventoryRoles, c8yRoles) { this.c8yUserInventoryRoles = c8yUserInventoryRoles; this.c8yRoles = c8yRoles; this.onChangeRoles = new EventEmitter(); this.onChangeItemCount = new EventEmitter(); this.noSubgroupTitle = gettext('No subgroups'); this.manySubgroupsTitle = gettext('Subgroups: {{ count }}'); this.oneSubgroupTitle = gettext('Subgroup: 1'); this.clickToOpenTitle = gettext('Click to fetch subgroups'); this.expandAriaLabel = gettext('Expand'); this.collapseAriaLabel = gettext('Collapse'); this.searchTermSubject = new BehaviorSubject(''); this.flatTreeSubject = new BehaviorSubject([]); this.flatAssetTree$ = combineLatest([this.searchTermSubject, this.flatTreeSubject]).pipe(map(([searchTerm, flatTree]) => { return flatTree .filter(group => group.name.toLowerCase().includes(searchTerm.toLowerCase())) .filter(this.filterAsset.bind(this)); }), tap(flatTree => { this.onChangeItemCount.emit(flatTree.length); })); } ngOnInit() { this.loadInventoryRoles(); } loadAssetTree() { const onlyRootsUser = this.user.owner; return this.c8yUserInventoryRoles.listRootGroups({ onlyRootsUser }).then(result => { this.rootGroups = result; this.updateTree(); }); } updateTree() { this.flatAssetTree = this.c8yUserInventoryRoles.flatTree(this.rootGroups); this.setInheritedRoles(); this.flatTreeSubject.next(this.flatAssetTree); } loadChildren(mo) { if (mo.isOpened) { // eslint-disable-next-line no-underscore-dangle mo._subGroups = []; mo.isOpened = false; this.updateTree(); } else { this.c8yUserInventoryRoles.loadChildren(mo).then(_ => { this.updateTree(); }); mo.isOpened = true; } } loadInventoryRoles() { this.c8yRoles.list({ pageSize: 1000 }).then(roles => { this.inventoryRoles = roles; }); } ngOnChanges(changes) { if (changes.searchFilter) { this.searchTermSubject.next(this.searchFilter || ''); } if (changes.user && !this.loadingAssetTree) { this.loadingAssetTree = this.loadAssetTree(); } if (changes.assignedRoles || changes.ownerAssignedRoles) { this.loadingAssetTree.then(this.setInheritedRoles.bind(this)); } if (changes.expandGroups && this.expandGroups) { this.c8yUserInventoryRoles.expandAll(this.rootGroups, this.updateTree.bind(this)); } } setInheritedRoles() { if (this.assignedRoles) { this.inheritedRoles = this.getInventoryInheritedRoles(this.flatAssetTree, this.assignedRoles); } if (this.ownerAssignedRoles) { const ownerInheritedRoles = this.getInventoryInheritedRoles(this.flatAssetTree, this.ownerAssignedRoles); this.ownerAllAssignedRoles = mergeWith(ownerInheritedRoles, this.ownerAssignedRoles, (objValue, srcValue) => { if (srcValue) { if (objValue) { return uniqBy(objValue.concat(srcValue.roles), 'id'); } return srcValue.roles; } return objValue; }); } } getInventoryInheritedRoles(flatTree, assignedRoles) { return reduce(flatTree, (inheritedRoles, asset) => { // eslint-disable-next-line no-underscore-dangle let chain = asset._parentGroups; chain = _map(chain, group => get(assignedRoles, group.id)); chain = filter(chain, identity); chain = _map(chain, property('roles')); chain = flatten(chain); chain = uniqBy(chain, 'id'); inheritedRoles[asset.id] = chain; return inheritedRoles; }, {}); } onApply(ev, managedObjectId) { return this.onChangeRoles.emit({ managedObjectId: managedObjectId, roles: ev.roles }); } filterAsset(asset) { if (this.ownerAllAssignedRoles) { return get(this.ownerAllAssignedRoles, [asset.id, 'length']); } return true; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RolesAssetTreeComponent, deps: [{ token: i1.Ng1UserInventoryRolesService, optional: true }, { token: i1.Ng1RolesService, optional: true }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: RolesAssetTreeComponent, selector: "c8y-roles-asset-tree-upgraded", inputs: { user: "user", searchFilter: "searchFilter", assignedRoles: "assignedRoles", ownerAssignedRoles: "ownerAssignedRoles", expandGroups: "expandGroups", pageSize: "pageSize", paginationOffset: "paginationOffset" }, outputs: { onChangeRoles: "onChangeRoles", onChangeItemCount: "onChangeItemCount" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"c8y-list__group m-b-0 no-border-last\">\n <div\n class=\"c8y-list__item\"\n *ngFor=\"\n let asset of flatAssetTree$ | async | slice: paginationOffset:paginationOffset + pageSize\n \"\n >\n <div\n class=\"c8y-list__item__block\"\n [title]=\"\n (asset._subGroups && asset.isOpened\n ? asset._subGroups.length\n ? asset._subGroups.length > 1\n ? manySubgroupsTitle\n : oneSubgroupTitle\n : noSubgroupTitle\n : clickToOpenTitle\n ) | translate: { count: asset._subGroups?.length }\n \"\n >\n <div [ngStyle]=\"{ 'padding-left': asset._depth * 8 + 'px' }\"></div>\n <div class=\"c8y-list__item__icon m-t-4 p-l-0\">\n <button\n class=\"btn-clean\"\n [attr.aria-label]=\"(!asset.isOpened ? expandAriaLabel : collapseAriaLabel) | translate\"\n type=\"button\"\n (click)=\"loadChildren(asset)\"\n >\n <i\n class=\"c8y-icon-duocolor\"\n c8yIcon=\"c8y-group\"\n *ngIf=\"!asset.isOpened\"\n ></i>\n <i\n class=\"c8y-icon-duocolor\"\n c8yIcon=\"c8y-group-open\"\n *ngIf=\"asset.isOpened\"\n ></i>\n </button>\n </div>\n <div class=\"c8y-list__item__body\">\n <div class=\"d-flex a-i-center\">\n <div class=\"col-sm-7 p-l-0 col-xs-12\">\n <button\n class=\"btn-clean\"\n type=\"button\"\n (click)=\"loadChildren(asset)\"\n >\n <span\n class=\"text-truncate\"\n [ngStyle]=\"{ cursor: 'pointer' }\"\n title=\"{{ asset.name }}\"\n >\n {{ asset.name }}\n </span>\n </button>\n </div>\n <div class=\"p-t-8 col-xs-12 visible-xs\"></div>\n <div class=\"col-sm-5 p-l-0 col-xs-12 p-r-0\">\n <div class=\"d-flex\">\n <div class=\"flex-grow form-group-sm max-width-100\">\n <c8y-inventory-role-selector-upgraded\n [ownerAllowedRoles]=\"\n ownerAllAssignedRoles ? ownerAllAssignedRoles[asset.id] : undefined\n \"\n [inheritedRoles]=\"inheritedRoles ? inheritedRoles[asset.id] : undefined\"\n [assignedRoles]=\"assignedRoles ? assignedRoles[asset.id] : undefined\"\n [inventoryRoles]=\"inventoryRoles\"\n (onApply)=\"onApply($event, asset.id)\"\n (click)=\"$event.stopPropagation()\"\n ></c8y-inventory-role-selector-upgraded>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No matching group found among the expanded groups.' | translate\"\n [subtitle]=\"'Try to expand more groups or to refine your search term.' | translate\"\n *ngIf=\"searchFilter && !(flatAssetTree$ | async).length\"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n</div>\n", dependencies: [{ kind: "component", type: i2.EmptyStateComponent, selector: "c8y-ui-empty-state", inputs: ["icon", "title", "subtitle", "horizontal"] }, { kind: "directive", type: i2.IconDirective, selector: "[c8yIcon]", inputs: ["c8yIcon"] }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i4.InventoryRoleSelector, selector: "c8y-inventory-role-selector-upgraded", inputs: ["assignedRoles", "inheritedRoles", "inventoryRoles", "ownerAllowedRoles"], outputs: ["onApply"] }, { kind: "pipe", type: i2.C8yTranslatePipe, name: "translate" }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "pipe", type: i3.SlicePipe, name: "slice" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RolesAssetTreeComponent, decorators: [{ type: Component, args: [{ selector: 'c8y-roles-asset-tree-upgraded', template: "<div class=\"c8y-list__group m-b-0 no-border-last\">\n <div\n class=\"c8y-list__item\"\n *ngFor=\"\n let asset of flatAssetTree$ | async | slice: paginationOffset:paginationOffset + pageSize\n \"\n >\n <div\n class=\"c8y-list__item__block\"\n [title]=\"\n (asset._subGroups && asset.isOpened\n ? asset._subGroups.length\n ? asset._subGroups.length > 1\n ? manySubgroupsTitle\n : oneSubgroupTitle\n : noSubgroupTitle\n : clickToOpenTitle\n ) | translate: { count: asset._subGroups?.length }\n \"\n >\n <div [ngStyle]=\"{ 'padding-left': asset._depth * 8 + 'px' }\"></div>\n <div class=\"c8y-list__item__icon m-t-4 p-l-0\">\n <button\n class=\"btn-clean\"\n [attr.aria-label]=\"(!asset.isOpened ? expandAriaLabel : collapseAriaLabel) | translate\"\n type=\"button\"\n (click)=\"loadChildren(asset)\"\n >\n <i\n class=\"c8y-icon-duocolor\"\n c8yIcon=\"c8y-group\"\n *ngIf=\"!asset.isOpened\"\n ></i>\n <i\n class=\"c8y-icon-duocolor\"\n c8yIcon=\"c8y-group-open\"\n *ngIf=\"asset.isOpened\"\n ></i>\n </button>\n </div>\n <div class=\"c8y-list__item__body\">\n <div class=\"d-flex a-i-center\">\n <div class=\"col-sm-7 p-l-0 col-xs-12\">\n <button\n class=\"btn-clean\"\n type=\"button\"\n (click)=\"loadChildren(asset)\"\n >\n <span\n class=\"text-truncate\"\n [ngStyle]=\"{ cursor: 'pointer' }\"\n title=\"{{ asset.name }}\"\n >\n {{ asset.name }}\n </span>\n </button>\n </div>\n <div class=\"p-t-8 col-xs-12 visible-xs\"></div>\n <div class=\"col-sm-5 p-l-0 col-xs-12 p-r-0\">\n <div class=\"d-flex\">\n <div class=\"flex-grow form-group-sm max-width-100\">\n <c8y-inventory-role-selector-upgraded\n [ownerAllowedRoles]=\"\n ownerAllAssignedRoles ? ownerAllAssignedRoles[asset.id] : undefined\n \"\n [inheritedRoles]=\"inheritedRoles ? inheritedRoles[asset.id] : undefined\"\n [assignedRoles]=\"assignedRoles ? assignedRoles[asset.id] : undefined\"\n [inventoryRoles]=\"inventoryRoles\"\n (onApply)=\"onApply($event, asset.id)\"\n (click)=\"$event.stopPropagation()\"\n ></c8y-inventory-role-selector-upgraded>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n <c8y-ui-empty-state\n [icon]=\"'search'\"\n [title]=\"'No matching group found among the expanded groups.' | translate\"\n [subtitle]=\"'Try to expand more groups or to refine your search term.' | translate\"\n *ngIf=\"searchFilter && !(flatAssetTree$ | async).length\"\n [horizontal]=\"false\"\n ></c8y-ui-empty-state>\n</div>\n" }] }], ctorParameters: () => [{ type: i1.Ng1UserInventoryRolesService, decorators: [{ type: Optional }] }, { type: i1.Ng1RolesService, decorators: [{ type: Optional }] }], propDecorators: { user: [{ type: Input }], searchFilter: [{ type: Input }], assignedRoles: [{ type: Input }], ownerAssignedRoles: [{ type: Input }], expandGroups: [{ type: Input }], pageSize: [{ type: Input }], paginationOffset: [{ type: Input }], onChangeRoles: [{ type: Output }], onChangeItemCount: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm9sZXMtYXNzZXQtdHJlZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi91c2VyLXJvbGVzL3JvbGVzLWFzc2V0LXRyZWUvcm9sZXMtYXNzZXQtdHJlZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi91c2VyLXJvbGVzL3JvbGVzLWFzc2V0LXRyZWUvcm9sZXMtYXNzZXQtdHJlZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQXFCLFFBQVEsRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDcEcsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRTlDLE9BQU8sRUFDTCxTQUFTLEVBQ1QsR0FBRyxJQUFJLElBQUksRUFDWCxNQUFNLEVBQ04sT0FBTyxFQUNQLE1BQU0sRUFDTixRQUFRLEVBQ1IsUUFBUSxFQUNSLEdBQUcsRUFDSCxNQUFNLEVBQ1AsTUFBTSxXQUFXLENBQUM7QUFDbkIsT0FBTyxFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDdEQsT0FBTyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUUxQyxPQUFPLEVBQ0wsZUFBZSxFQUNmLDRCQUE0QixFQUM3QixNQUFNLCtDQUErQyxDQUFDOzs7Ozs7QUFNdkQsTUFBTSxPQUFPLHVCQUF1QjtJQXVDbEMsWUFDcUIscUJBQW1ELEVBQ25ELFFBQXlCO1FBRHpCLDBCQUFxQixHQUFyQixxQkFBcUIsQ0FBOEI7UUFDbkQsYUFBUSxHQUFSLFFBQVEsQ0FBaUI7UUFqQ3BDLGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNuQyxzQkFBaUIsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBU2pELG9CQUFlLEdBQUcsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzFDLHVCQUFrQixHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQ3ZELHFCQUFnQixHQUFHLE9BQU8sQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUMxQyxxQkFBZ0IsR0FBRyxPQUFPLENBQUMsMEJBQTBCLENBQUMsQ0FBQztRQUN2RCxvQkFBZSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNwQyxzQkFBaUIsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFeEMsc0JBQWlCLEdBQUcsSUFBSSxlQUFlLENBQVMsRUFBRSxDQUFDLENBQUM7UUFDcEQsb0JBQWUsR0FBRyxJQUFJLGVBQWUsQ0FBZ0IsRUFBRSxDQUFDLENBQUM7UUFFekQsbUJBQWMsR0FBRyxhQUFhLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUNqRixHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxFQUFFO1lBQzdCLE9BQU8sUUFBUTtpQkFDWixNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztpQkFDNUUsTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDekMsQ0FBQyxDQUFDLEVBQ0YsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFO1lBQ2IsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDL0MsQ0FBQyxDQUFDLENBQ0gsQ0FBQztJQUtDLENBQUM7SUFFSixRQUFRO1FBQ04sSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDNUIsQ0FBQztJQUVELGFBQWE7UUFDWCxNQUFNLGFBQWEsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUN0QyxPQUFPLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxjQUFjLENBQUMsRUFBRSxhQUFhLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRTtZQUNoRixJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQztZQUN6QixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDcEIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsVUFBVTtRQUNSLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDMUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ2hELENBQUM7SUFFRCxZQUFZLENBQUMsRUFBRTtRQUNiLElBQUksRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDO1lBQ2hCLGdEQUFnRDtZQUNoRCxFQUFFLENBQUMsVUFBVSxHQUFHLEVBQUUsQ0FBQztZQUNuQixFQUFFLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztZQUNwQixJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDcEIsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMscUJBQXFCLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDbkQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BCLENBQUMsQ0FBQyxDQUFDO1lBQ0gsRUFBRSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUM7UUFDckIsQ0FBQztJQUNILENBQUM7SUFFRCxrQkFBa0I7UUFDaEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDbEQsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUM7UUFDOUIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVyxDQUFDLE9BQU87UUFDakIsSUFBSSxPQUFPLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQy9DLENBQUM7UUFDRCxJQUFJLE9BQU8sQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFDLGtCQUFrQixFQUFFLENBQUM7WUFDeEQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDaEUsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLFlBQVksSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDOUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDcEYsQ0FBQztJQUNILENBQUM7SUFFRCxpQkFBaUI7UUFDZixJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQztZQUN2QixJQUFJLENBQUMsY0FBYyxHQUFHLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUNoRyxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUM1QixNQUFNLG1CQUFtQixHQUFHLElBQUksQ0FBQywwQkFBMEIsQ0FDekQsSUFBSSxDQUFDLGFBQWEsRUFDbEIsSUFBSSxDQUFDLGtCQUFrQixDQUN4QixDQUFDO1lBQ0YsSUFBSSxDQUFDLHFCQUFxQixHQUFHLFNBQVMsQ0FDcEMsbUJBQW1CLEVBQ25CLElBQUksQ0FBQyxrQkFBa0IsRUFDdkIsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLEVBQUU7Z0JBQ3JCLElBQUksUUFBUSxFQUFFLENBQUM7b0JBQ2IsSUFBSSxRQUFRLEVBQUUsQ0FBQzt3QkFDYixPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQztvQkFDdkQsQ0FBQztvQkFDRCxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUM7Z0JBQ3hCLENBQUM7Z0JBQ0QsT0FBTyxRQUFRLENBQUM7WUFDbEIsQ0FBQyxDQUNGLENBQUM7UUFDSixDQUFDO0lBQ0gsQ0FBQztJQUVELDBCQUEwQixDQUFDLFFBQVEsRUFBRSxhQUFhO1FBQ2hELE9BQU8sTUFBTSxDQUNYLFFBQVEsRUFDUixDQUFDLGNBQWMsRUFBRSxLQUFLLEVBQUUsRUFBRTtZQUN4QixnREFBZ0Q7WUFDaEQsSUFBSSxLQUFLLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQztZQUNoQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDM0QsS0FBSyxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7WUFDaEMsS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7WUFDdkMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2QixLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztZQUM1QixjQUFjLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQztZQUNqQyxPQUFPLGNBQWMsQ0FBQztRQUN4QixDQUFDLEVBQ0QsRUFBRSxDQUNILENBQUM7SUFDSixDQUFDO0lBRUQsT0FBTyxDQUFDLEVBQUUsRUFBRSxlQUFlO1FBQ3pCLE9BQU8sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUM7WUFDN0IsZUFBZSxFQUFFLGVBQWU7WUFDaEMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLO1NBQ2hCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxXQUFXLENBQUMsS0FBSztRQUNmLElBQUksSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUM7WUFDL0IsT0FBTyxHQUFHLENBQUMsSUFBSSxDQUFDLHFCQUFxQixFQUFFLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO1FBQy9ELENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7K0dBeEpVLHVCQUF1QjttR0FBdkIsdUJBQXVCLDJZQzFCcEMsd21HQXNGQTs7NEZENURhLHVCQUF1QjtrQkFKbkMsU0FBUzsrQkFDRSwrQkFBK0I7OzBCQTJDdEMsUUFBUTs7MEJBQ1IsUUFBUTt5Q0F4Q0YsSUFBSTtzQkFBWixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxrQkFBa0I7c0JBQTFCLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFDSSxhQUFhO3NCQUF0QixNQUFNO2dCQUNHLGlCQUFpQjtzQkFBMUIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkluaXQsIE9wdGlvbmFsLCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IGdldHRleHQgfSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzJztcblxuaW1wb3J0IHtcbiAgbWVyZ2VXaXRoLFxuICBtYXAgYXMgX21hcCxcbiAgZmlsdGVyLFxuICBmbGF0dGVuLFxuICB1bmlxQnksXG4gIGlkZW50aXR5LFxuICBwcm9wZXJ0eSxcbiAgZ2V0LFxuICByZWR1Y2Vcbn0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgbWFwLCB0YXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBJSWRlbnRpZmllZCB9IGZyb20gJ0BjOHkvY2xpZW50JztcbmltcG9ydCB7XG4gIE5nMVJvbGVzU2VydmljZSxcbiAgTmcxVXNlckludmVudG9yeVJvbGVzU2VydmljZVxufSBmcm9tICdAYzh5L25neC1jb21wb25lbnRzL3VwZ3JhZGUvdXBncmFkZWQtc2VydmljZXMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktcm9sZXMtYXNzZXQtdHJlZS11cGdyYWRlZCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9yb2xlcy1hc3NldC10cmVlLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBSb2xlc0Fzc2V0VHJlZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgdXNlcjtcbiAgQElucHV0KCkgc2VhcmNoRmlsdGVyO1xuICBASW5wdXQoKSBhc3NpZ25lZFJvbGVzO1xuICBASW5wdXQoKSBvd25lckFzc2lnbmVkUm9sZXM7XG4gIEBJbnB1dCgpIGV4cGFuZEdyb3VwcztcbiAgQElucHV0KCkgcGFnZVNpemU7XG4gIEBJbnB1dCgpIHBhZ2luYXRpb25PZmZzZXQ7XG4gIEBPdXRwdXQoKSBvbkNoYW5nZVJvbGVzID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgb25DaGFuZ2VJdGVtQ291bnQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcm9vdEdyb3VwcztcbiAgZmxhdEFzc2V0VHJlZTtcbiAgaW52ZW50b3J5Um9sZXM7XG4gIGxvYWRpbmdBc3NldFRyZWU7XG4gIGluaGVyaXRlZFJvbGVzO1xuICBvd25lckFsbEFzc2lnbmVkUm9sZXM7XG5cbiAgbm9TdWJncm91cFRpdGxlID0gZ2V0dGV4dCgnTm8gc3ViZ3JvdXBzJyk7XG4gIG1hbnlTdWJncm91cHNUaXRsZSA9IGdldHRleHQoJ1N1Ymdyb3Vwczoge3sgY291bnQgfX0nKTtcbiAgb25lU3ViZ3JvdXBUaXRsZSA9IGdldHRleHQoJ1N1Ymdyb3VwOiAxJyk7XG4gIGNsaWNrVG9PcGVuVGl0bGUgPSBnZXR0ZXh0KCdDbGljayB0byBmZXRjaCBzdWJncm91cHMnKTtcbiAgZXhwYW5kQXJpYUxhYmVsID0gZ2V0dGV4dCgnRXhwYW5kJyk7XG4gIGNvbGxhcHNlQXJpYUxhYmVsID0gZ2V0dGV4dCgnQ29sbGFwc2UnKTtcblxuICBzZWFyY2hUZXJtU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8c3RyaW5nPignJyk7XG4gIGZsYXRUcmVlU3ViamVjdCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8SUlkZW50aWZpZWRbXT4oW10pO1xuXG4gIGZsYXRBc3NldFRyZWUkID0gY29tYmluZUxhdGVzdChbdGhpcy5zZWFyY2hUZXJtU3ViamVjdCwgdGhpcy5mbGF0VHJlZVN1YmplY3RdKS5waXBlKFxuICAgIG1hcCgoW3NlYXJjaFRlcm0sIGZsYXRUcmVlXSkgPT4ge1xuICAgICAgcmV0dXJuIGZsYXRUcmVlXG4gICAgICAgIC5maWx0ZXIoZ3JvdXAgPT4gZ3JvdXAubmFtZS50b0xvd2VyQ2FzZSgpLmluY2x1ZGVzKHNlYXJjaFRlcm0udG9Mb3dlckNhc2UoKSkpXG4gICAgICAgIC5maWx0ZXIodGhpcy5maWx0ZXJBc3NldC5iaW5kKHRoaXMpKTtcbiAgICB9KSxcbiAgICB0YXAoZmxhdFRyZWUgPT4ge1xuICAgICAgdGhpcy5vbkNoYW5nZUl0ZW1Db3VudC5lbWl0KGZsYXRUcmVlLmxlbmd0aCk7XG4gICAgfSlcbiAgKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBAT3B0aW9uYWwoKSBwdWJsaWMgYzh5VXNlckludmVudG9yeVJvbGVzOiBOZzFVc2VySW52ZW50b3J5Um9sZXNTZXJ2aWNlLFxuICAgIEBPcHRpb25hbCgpIHB1YmxpYyBjOHlSb2xlczogTmcxUm9sZXNTZXJ2aWNlXG4gICkge31cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmxvYWRJbnZlbnRvcnlSb2xlcygpO1xuICB9XG5cbiAgbG9hZEFzc2V0VHJlZSgpIHtcbiAgICBjb25zdCBvbmx5Um9vdHNVc2VyID0gdGhpcy51c2VyLm93bmVyO1xuICAgIHJldHVybiB0aGlzLmM4eVVzZXJJbnZlbnRvcnlSb2xlcy5saXN0Um9vdEdyb3Vwcyh7IG9ubHlSb290c1VzZXIgfSkudGhlbihyZXN1bHQgPT4ge1xuICAgICAgdGhpcy5yb290R3JvdXBzID0gcmVzdWx0O1xuICAgICAgdGhpcy51cGRhdGVUcmVlKCk7XG4gICAgfSk7XG4gIH1cblxuICB1cGRhdGVUcmVlKCkge1xuICAgIHRoaXMuZmxhdEFzc2V0VHJlZSA9IHRoaXMuYzh5VXNlckludmVudG9yeVJvbGVzLmZsYXRUcmVlKHRoaXMucm9vdEdyb3Vwcyk7XG4gICAgdGhpcy5zZXRJbmhlcml0ZWRSb2xlcygpO1xuICAgIHRoaXMuZmxhdFRyZWVTdWJqZWN0Lm5leHQodGhpcy5mbGF0QXNzZXRUcmVlKTtcbiAgfVxuXG4gIGxvYWRDaGlsZHJlbihtbykge1xuICAgIGlmIChtby5pc09wZW5lZCkge1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXVuZGVyc2NvcmUtZGFuZ2xlXG4gICAgICBtby5fc3ViR3JvdXBzID0gW107XG4gICAgICBtby5pc09wZW5lZCA9IGZhbHNlO1xuICAgICAgdGhpcy51cGRhdGVUcmVlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYzh5VXNlckludmVudG9yeVJvbGVzLmxvYWRDaGlsZHJlbihtbykudGhlbihfID0+IHtcbiAgICAgICAgdGhpcy51cGRhdGVUcmVlKCk7XG4gICAgICB9KTtcbiAgICAgIG1vLmlzT3BlbmVkID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBsb2FkSW52ZW50b3J5Um9sZXMoKSB7XG4gICAgdGhpcy5jOHlSb2xlcy5saXN0KHsgcGFnZVNpemU6IDEwMDAgfSkudGhlbihyb2xlcyA9PiB7XG4gICAgICB0aGlzLmludmVudG9yeVJvbGVzID0gcm9sZXM7XG4gICAgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXMuc2VhcmNoRmlsdGVyKSB7XG4gICAgICB0aGlzLnNlYXJjaFRlcm1TdWJqZWN0Lm5leHQodGhpcy5zZWFyY2hGaWx0ZXIgfHwgJycpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy51c2VyICYmICF0aGlzLmxvYWRpbmdBc3NldFRyZWUpIHtcbiAgICAgIHRoaXMubG9hZGluZ0Fzc2V0VHJlZSA9IHRoaXMubG9hZEFzc2V0VHJlZSgpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5hc3NpZ25lZFJvbGVzIHx8IGNoYW5nZXMub3duZXJBc3NpZ25lZFJvbGVzKSB7XG4gICAgICB0aGlzLmxvYWRpbmdBc3NldFRyZWUudGhlbih0aGlzLnNldEluaGVyaXRlZFJvbGVzLmJpbmQodGhpcykpO1xuICAgIH1cbiAgICBpZiAoY2hhbmdlcy5leHBhbmRHcm91cHMgJiYgdGhpcy5leHBhbmRHcm91cHMpIHtcbiAgICAgIHRoaXMuYzh5VXNlckludmVudG9yeVJvbGVzLmV4cGFuZEFsbCh0aGlzLnJvb3RHcm91cHMsIHRoaXMudXBkYXRlVHJlZS5iaW5kKHRoaXMpKTtcbiAgICB9XG4gIH1cblxuICBzZXRJbmhlcml0ZWRSb2xlcygpIHtcbiAgICBpZiAodGhpcy5hc3NpZ25lZFJvbGVzKSB7XG4gICAgICB0aGlzLmluaGVyaXRlZFJvbGVzID0gdGhpcy5nZXRJbnZlbnRvcnlJbmhlcml0ZWRSb2xlcyh0aGlzLmZsYXRBc3NldFRyZWUsIHRoaXMuYXNzaWduZWRSb2xlcyk7XG4gICAgfVxuICAgIGlmICh0aGlzLm93bmVyQXNzaWduZWRSb2xlcykge1xuICAgICAgY29uc3Qgb3duZXJJbmhlcml0ZWRSb2xlcyA9IHRoaXMuZ2V0SW52ZW50b3J5SW5oZXJpdGVkUm9sZXMoXG4gICAgICAgIHRoaXMuZmxhdEFzc2V0VHJlZSxcbiAgICAgICAgdGhpcy5vd25lckFzc2lnbmVkUm9sZXNcbiAgICAgICk7XG4gICAgICB0aGlzLm93bmVyQWxsQXNzaWduZWRSb2xlcyA9IG1lcmdlV2l0aChcbiAgICAgICAgb3duZXJJbmhlcml0ZWRSb2xlcyxcbiAgICAgICAgdGhpcy5vd25lckFzc2lnbmVkUm9sZXMsXG4gICAgICAgIChvYmpWYWx1ZSwgc3JjVmFsdWUpID0+IHtcbiAgICAgICAgICBpZiAoc3JjVmFsdWUpIHtcbiAgICAgICAgICAgIGlmIChvYmpWYWx1ZSkge1xuICAgICAgICAgICAgICByZXR1cm4gdW5pcUJ5KG9ialZhbHVlLmNvbmNhdChzcmNWYWx1ZS5yb2xlcyksICdpZCcpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNyY1ZhbHVlLnJvbGVzO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gb2JqVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgZ2V0SW52ZW50b3J5SW5oZXJpdGVkUm9sZXMoZmxhdFRyZWUsIGFzc2lnbmVkUm9sZXMpIHtcbiAgICByZXR1cm4gcmVkdWNlKFxuICAgICAgZmxhdFRyZWUsXG4gICAgICAoaW5oZXJpdGVkUm9sZXMsIGFzc2V0KSA9PiB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlcnNjb3JlLWRhbmdsZVxuICAgICAgICBsZXQgY2hhaW4gPSBhc3NldC5fcGFyZW50R3JvdXBzO1xuICAgICAgICBjaGFpbiA9IF9tYXAoY2hhaW4sIGdyb3VwID0+IGdldChhc3NpZ25lZFJvbGVzLCBncm91cC5pZCkpO1xuICAgICAgICBjaGFpbiA9IGZpbHRlcihjaGFpbiwgaWRlbnRpdHkpO1xuICAgICAgICBjaGFpbiA9IF9tYXAoY2hhaW4sIHByb3BlcnR5KCdyb2xlcycpKTtcbiAgICAgICAgY2hhaW4gPSBmbGF0dGVuKGNoYWluKTtcbiAgICAgICAgY2hhaW4gPSB1bmlxQnkoY2hhaW4sICdpZCcpO1xuICAgICAgICBpbmhlcml0ZWRSb2xlc1thc3NldC5pZF0gPSBjaGFpbjtcbiAgICAgICAgcmV0dXJuIGluaGVyaXRlZFJvbGVzO1xuICAgICAgfSxcbiAgICAgIHt9XG4gICAgKTtcbiAgfVxuXG4gIG9uQXBwbHkoZXYsIG1hbmFnZWRPYmplY3RJZCkge1xuICAgIHJldHVybiB0aGlzLm9uQ2hhbmdlUm9sZXMuZW1pdCh7XG4gICAgICBtYW5hZ2VkT2JqZWN0SWQ6IG1hbmFnZWRPYmplY3RJZCxcbiAgICAgIHJvbGVzOiBldi5yb2xlc1xuICAgIH0pO1xuICB9XG5cbiAgZmlsdGVyQXNzZXQoYXNzZXQpIHtcbiAgICBpZiAodGhpcy5vd25lckFsbEFzc2lnbmVkUm9sZXMpIHtcbiAgICAgIHJldHVybiBnZXQodGhpcy5vd25lckFsbEFzc2lnbmVkUm9sZXMsIFthc3NldC5pZCwgJ2xlbmd0aCddKTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjOHktbGlzdF9fZ3JvdXAgbS1iLTAgbm8tYm9yZGVyLWxhc3RcIj5cbiAgPGRpdlxuICAgIGNsYXNzPVwiYzh5LWxpc3RfX2l0ZW1cIlxuICAgICpuZ0Zvcj1cIlxuICAgICAgbGV0IGFzc2V0IG9mIGZsYXRBc3NldFRyZWUkIHwgYXN5bmMgfCBzbGljZTogcGFnaW5hdGlvbk9mZnNldDpwYWdpbmF0aW9uT2Zmc2V0ICsgcGFnZVNpemVcbiAgICBcIlxuICA+XG4gICAgPGRpdlxuICAgICAgY2xhc3M9XCJjOHktbGlzdF9faXRlbV9fYmxvY2tcIlxuICAgICAgW3RpdGxlXT1cIlxuICAgICAgICAoYXNzZXQuX3N1Ykdyb3VwcyAmJiBhc3NldC5pc09wZW5lZFxuICAgICAgICAgID8gYXNzZXQuX3N1Ykdyb3Vwcy5sZW5ndGhcbiAgICAgICAgICAgID8gYXNzZXQuX3N1Ykdyb3Vwcy5sZW5ndGggPiAxXG4gICAgICAgICAgICAgID8gbWFueVN1Ymdyb3Vwc1RpdGxlXG4gICAgICAgICAgICAgIDogb25lU3ViZ3JvdXBUaXRsZVxuICAgICAgICAgICAgOiBub1N1Ymdyb3VwVGl0bGVcbiAgICAgICAgICA6IGNsaWNrVG9PcGVuVGl0bGVcbiAgICAgICAgKSB8IHRyYW5zbGF0ZTogeyBjb3VudDogYXNzZXQuX3N1Ykdyb3Vwcz8ubGVuZ3RoIH1cbiAgICAgIFwiXG4gICAgPlxuICAgICAgPGRpdiBbbmdTdHlsZV09XCJ7ICdwYWRkaW5nLWxlZnQnOiBhc3NldC5fZGVwdGggKiA4ICsgJ3B4JyB9XCI+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiYzh5LWxpc3RfX2l0ZW1fX2ljb24gbS10LTQgcC1sLTBcIj5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgIGNsYXNzPVwiYnRuLWNsZWFuXCJcbiAgICAgICAgICBbYXR0ci5hcmlhLWxhYmVsXT1cIighYXNzZXQuaXNPcGVuZWQgPyBleHBhbmRBcmlhTGFiZWwgOiBjb2xsYXBzZUFyaWFMYWJlbCkgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgIChjbGljayk9XCJsb2FkQ2hpbGRyZW4oYXNzZXQpXCJcbiAgICAgICAgPlxuICAgICAgICAgIDxpXG4gICAgICAgICAgICBjbGFzcz1cImM4eS1pY29uLWR1b2NvbG9yXCJcbiAgICAgICAgICAgIGM4eUljb249XCJjOHktZ3JvdXBcIlxuICAgICAgICAgICAgKm5nSWY9XCIhYXNzZXQuaXNPcGVuZWRcIlxuICAgICAgICAgID48L2k+XG4gICAgICAgICAgPGlcbiAgICAgICAgICAgIGNsYXNzPVwiYzh5LWljb24tZHVvY29sb3JcIlxuICAgICAgICAgICAgYzh5SWNvbj1cImM4eS1ncm91cC1vcGVuXCJcbiAgICAgICAgICAgICpuZ0lmPVwiYXNzZXQuaXNPcGVuZWRcIlxuICAgICAgICAgID48L2k+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiYzh5LWxpc3RfX2l0ZW1fX2JvZHlcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhLWktY2VudGVyXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS03IHAtbC0wIGNvbC14cy0xMlwiPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1jbGVhblwiXG4gICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAoY2xpY2spPVwibG9hZENoaWxkcmVuKGFzc2V0KVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxzcGFuXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXRydW5jYXRlXCJcbiAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJ7IGN1cnNvcjogJ3BvaW50ZXInIH1cIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwie3sgYXNzZXQubmFtZSB9fVwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICB7eyBhc3NldC5uYW1lIH19XG4gICAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJwLXQtOCBjb2wteHMtMTIgdmlzaWJsZS14c1wiPjwvZGl2PlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tNSBwLWwtMCBjb2wteHMtMTIgcC1yLTBcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXhcIj5cbiAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgtZ3JvdyBmb3JtLWdyb3VwLXNtIG1heC13aWR0aC0xMDBcIj5cbiAgICAgICAgICAgICAgICA8Yzh5LWludmVudG9yeS1yb2xlLXNlbGVjdG9yLXVwZ3JhZGVkXG4gICAgICAgICAgICAgICAgICBbb3duZXJBbGxvd2VkUm9sZXNdPVwiXG4gICAgICAgICAgICAgICAgICAgIG93bmVyQWxsQXNzaWduZWRSb2xlcyA/IG93bmVyQWxsQXNzaWduZWRSb2xlc1thc3NldC5pZF0gOiB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICAgICAgICBbaW5oZXJpdGVkUm9sZXNdPVwiaW5oZXJpdGVkUm9sZXMgPyBpbmhlcml0ZWRSb2xlc1thc3NldC5pZF0gOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgICAgICAgW2Fzc2lnbmVkUm9sZXNdPVwiYXNzaWduZWRSb2xlcyA/IGFzc2lnbmVkUm9sZXNbYXNzZXQuaWRdIDogdW5kZWZpbmVkXCJcbiAgICAgICAgICAgICAgICAgIFtpbnZlbnRvcnlSb2xlc109XCJpbnZlbnRvcnlSb2xlc1wiXG4gICAgICAgICAgICAgICAgICAob25BcHBseSk9XCJvbkFwcGx5KCRldmVudCwgYXNzZXQuaWQpXCJcbiAgICAgICAgICAgICAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgICAgID48L2M4eS1pbnZlbnRvcnktcm9sZS1zZWxlY3Rvci11cGdyYWRlZD5cbiAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxjOHktdWktZW1wdHktc3RhdGVcbiAgICBbaWNvbl09XCInc2VhcmNoJ1wiXG4gICAgW3RpdGxlXT1cIidObyBtYXRjaGluZyBncm91cCBmb3VuZCBhbW9uZyB0aGUgZXhwYW5kZWQgZ3JvdXBzLicgfCB0cmFuc2xhdGVcIlxuICAgIFtzdWJ0aXRsZV09XCInVHJ5IHRvIGV4cGFuZCBtb3JlIGdyb3VwcyBvciB0byByZWZpbmUgeW91ciBzZWFyY2ggdGVybS4nIHwgdHJhbnNsYXRlXCJcbiAgICAqbmdJZj1cInNlYXJjaEZpbHRlciAmJiAhKGZsYXRBc3NldFRyZWUkIHwgYXN5bmMpLmxlbmd0aFwiXG4gICAgW2hvcml6b250YWxdPVwiZmFsc2VcIlxuICA+PC9jOHktdWktZW1wdHktc3RhdGU+XG48L2Rpdj5cbiJdfQ==