@alfresco/adf-content-services
Version:
Alfresco ADF content services
216 lines • 49.3 kB
JavaScript
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ConfirmDialogComponent } from '@alfresco/adf-core';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { Component, DestroyRef, EventEmitter, inject, Input, Output, ViewChild, ViewEncapsulation } from '@angular/core';
import { ContentApi, Node, NodesApi, VersionsApi } from '@alfresco/js-api';
import { MatDialog } from '@angular/material/dialog';
import { ContentVersionService } from './content-version.service';
import { ContentService } from '../common';
import { InfiniteScrollDatasource } from '../infinite-scroll-datasource';
import { from } from 'rxjs';
import { map, take } from 'rxjs/operators';
import { CdkFixedSizeVirtualScroll, CdkVirtualForOf, CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
import { CommonModule } from '@angular/common';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { MatListModule } from '@angular/material/list';
import { MatIconModule } from '@angular/material/icon';
import { MatMenuModule } from '@angular/material/menu';
import { TranslateModule } from '@ngx-translate/core';
import { MatButtonModule } from '@angular/material/button';
import { VersionCompatibilityDirective } from '../version-compatibility';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i0 from "@angular/core";
import * as i1 from "../services/alfresco-api.service";
import * as i2 from "../common";
import * as i3 from "./content-version.service";
import * as i4 from "@angular/material/dialog";
import * as i5 from "@angular/common";
import * as i6 from "@angular/material/progress-bar";
import * as i7 from "@angular/material/list";
import * as i8 from "@angular/material/icon";
import * as i9 from "@angular/material/menu";
import * as i10 from "@ngx-translate/core";
import * as i11 from "@angular/material/button";
export class VersionListDataSource extends InfiniteScrollDatasource {
constructor(versionsApi, node) {
super();
this.versionsApi = versionsApi;
this.node = node;
}
getNextBatch(pagingOptions) {
return from(this.versionsApi.listVersionHistory(this.node.id, pagingOptions)).pipe(take(1), map((versionPaging) => versionPaging.list.entries));
}
}
export class VersionListComponent {
get contentApi() {
this._contentApi = this._contentApi ?? new ContentApi(this.alfrescoApi.getInstance());
return this._contentApi;
}
get versionsApi() {
this._versionsApi = this._versionsApi ?? new VersionsApi(this.alfrescoApi.getInstance());
return this._versionsApi;
}
get nodesApi() {
this._nodesApi = this._nodesApi ?? new NodesApi(this.alfrescoApi.getInstance());
return this._nodesApi;
}
constructor(alfrescoApi, contentService, contentVersionService, dialog) {
this.alfrescoApi = alfrescoApi;
this.contentService = contentService;
this.contentVersionService = contentVersionService;
this.dialog = dialog;
this.isLoading = true;
/** Toggles showing/hiding of comments */
this.showComments = true;
/** Enable/disable downloading a version of the current node. */
this.allowDownload = true;
/** Enable/disable viewing a version of the current node. */
this.allowViewVersions = true;
/** Toggles showing/hiding of version actions */
this.showActions = true;
/** Enable/disable deletion of version */
this.allowVersionDelete = true;
/** Emitted when a version is restored */
this.restored = new EventEmitter();
/** Emitted when a version is deleted */
this.deleted = new EventEmitter();
/** Emitted when viewing a version */
this.viewVersion = new EventEmitter();
this.destroyRef = inject(DestroyRef);
}
ngOnInit() {
this.versionsDataSource = new VersionListDataSource(this.versionsApi, this.node);
this.versionsDataSource.isLoading.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((isLoading) => {
this.isLoading = isLoading;
this.latestVersion = this.versionsDataSource.firstItem;
});
}
ngOnChanges() {
if (this.versionsDataSource) {
this.loadVersionHistory();
}
}
canUpdate() {
return this.contentService.hasAllowableOperations(this.node, 'update') && this.versionsDataSource.itemsCount > 1;
}
canDelete() {
return this.contentService.hasAllowableOperations(this.node, 'delete') && this.versionsDataSource.itemsCount > 1;
}
restore(versionId) {
if (this.canUpdate()) {
this.versionsApi
.revertVersion(this.node.id, versionId, { majorVersion: true, comment: '' })
.then(() => this.nodesApi.getNode(this.node.id, { include: ['permissions', 'path', 'isFavorite', 'allowableOperations'] }))
.then((node) => this.onVersionRestored(node));
}
}
onViewVersion(versionId) {
this.viewVersion.emit(versionId);
}
loadVersionHistory() {
this.viewport.scrollToIndex(0);
this.versionsDataSource.reset();
}
downloadVersion(versionId) {
if (this.allowDownload) {
this.contentVersionService
.getVersionContentUrl(this.node.id, versionId, true)
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((versionDownloadUrl) => this.downloadContent(versionDownloadUrl));
}
}
deleteVersion(versionId) {
if (this.canUpdate()) {
const dialogRef = this.dialog.open(ConfirmDialogComponent, {
data: {
title: 'ADF_VERSION_LIST.CONFIRM_DELETE.TITLE',
message: 'ADF_VERSION_LIST.CONFIRM_DELETE.MESSAGE',
yesLabel: 'ADF_VERSION_LIST.CONFIRM_DELETE.YES_LABEL',
noLabel: 'ADF_VERSION_LIST.CONFIRM_DELETE.NO_LABEL'
},
minWidth: '250px'
});
dialogRef
.afterClosed()
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((result) => {
if (result) {
this.versionsApi.deleteVersion(this.node.id, versionId).then(() => this.onVersionDeleted(this.node));
}
});
}
}
onVersionDeleted(node) {
this.loadVersionHistory();
this.deleted.emit(node);
}
onVersionRestored(node) {
this.loadVersionHistory();
this.restored.emit(node?.entry);
}
downloadContent(url) {
if (url) {
const link = document.createElement('a');
link.style.display = 'none';
link.href = url;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: VersionListComponent, deps: [{ token: i1.AlfrescoApiService }, { token: i2.ContentService }, { token: i3.ContentVersionService }, { token: i4.MatDialog }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: VersionListComponent, isStandalone: true, selector: "adf-version-list", inputs: { node: "node", showComments: "showComments", allowDownload: "allowDownload", allowViewVersions: "allowViewVersions", showActions: "showActions", allowVersionDelete: "allowVersionDelete" }, outputs: { restored: "restored", deleted: "deleted", viewVersion: "viewVersion" }, host: { classAttribute: "adf-version-list" }, viewQueries: [{ propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mat-progress-bar *ngIf=\"isLoading\" data-automation-id=\"version-history-loading-bar\" mode=\"indeterminate\"\n color=\"accent\" />\n<mat-list class=\"adf-version-list adf-version-list-element\" [hidden]=\"isLoading\">\n <cdk-virtual-scroll-viewport #viewport itemSize=\"88\" class=\"adf-version-list-viewport\" [minBufferPx]=\"440\" [maxBufferPx]=\"528\">\n <mat-list-item class=\"adf-version-list-item\"\n *cdkVirtualFor=\"let version of versionsDataSource; let idx = index; let latestVersion = first\">\n <mat-icon class=\"adf-version-list-icon\" matListItemIcon>insert_drive_file</mat-icon>\n <div class=\"adf-version-list-content\">\n <div class=\"adf-version-list-item-details\">\n <p class=\"adf-version-list-item-line adf-version-list-item-name\"\n [id]=\"'adf-version-list-item-name-' + version.entry.id\">{{ version.entry.name }}</p>\n <p>\n <span class=\"adf-version-list-item-line adf-version-list-item-version\"\n [id]=\"'adf-version-list-item-version-' + version.entry.id\">{{ version.entry.id }}</span> -\n <span class=\"adf-version-list-item-line adf-version-list-item-date\"\n [id]=\"'adf-version-list-item-date-' + version.entry.id\">{{ version.entry.modifiedAt | date }}</span>\n </p>\n <p\n [id]=\"'adf-version-list-item-comment-' + version.entry.id\"\n class=\"adf-version-list-item-comment\"\n *ngIf=\"showComments\"\n [title]=\"version.entry.versionComment\">\n {{ version.entry.versionComment }}\n </p>\n </div>\n <ng-container *ngIf=\"showActions\">\n <mat-menu [id]=\"'adf-version-list-action-menu-' + version.entry.id\"\n #versionMenu=\"matMenu\"\n yPosition=\"below\"\n xPosition=\"before\">\n <ng-container *adf-acs-version=\"'7'\">\n <button *ngIf=\"allowViewVersions\"\n [id]=\"'adf-version-list-action-view-' + version.entry.id\"\n mat-menu-item\n (click)=\"onViewVersion(version.entry.id)\">\n {{ 'ADF_VERSION_LIST.ACTIONS.VIEW' | translate }}\n </button>\n </ng-container>\n <button\n [id]=\"'adf-version-list-action-restore-' + version.entry.id\"\n [disabled]=\"!canUpdate() || latestVersion\"\n mat-menu-item\n (click)=\"restore(version.entry.id)\">\n {{ 'ADF_VERSION_LIST.ACTIONS.RESTORE' | translate }}\n </button>\n <button *ngIf=\"allowDownload\"\n [id]=\"'adf-version-list-action-download-' + version.entry.id\"\n mat-menu-item\n (click)=\"downloadVersion(version.entry.id)\">\n {{ 'ADF_VERSION_LIST.ACTIONS.DOWNLOAD' | translate }}\n </button>\n <button\n *ngIf=\"allowVersionDelete\"\n [disabled]=\"!canDelete()\"\n [id]=\"'adf-version-list-action-delete-' + version.entry.id\"\n (click)=\"deleteVersion(version.entry.id)\"\n mat-menu-item>\n {{ 'ADF_VERSION_LIST.ACTIONS.DELETE' | translate }}\n </button>\n </mat-menu>\n <button mat-icon-button\n [matMenuTriggerFor]=\"versionMenu\"\n [id]=\"'adf-version-list-action-menu-button-' + version.entry.id\"\n title=\"{{ 'ADF_VERSION_LIST.MANAGE_VERSION_OPTIONS' | translate }}\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </ng-container>\n </div>\n </mat-list-item>\n </cdk-virtual-scroll-viewport>\n</mat-list>\n", styles: [".adf-version-list-viewport{height:100%;overflow-x:hidden;display:flex}.adf-version-list-viewport :first-child{max-width:100%}.adf-version-list-item-details{flex:1;width:90%}.adf-version-list-content{display:flex}.adf-version-list-content p{margin:0;overflow:hidden}.adf-version-list .adf-version-list-icon{margin:0 16px;color:var(--theme-sidenav-user-menu-color)}.adf-version-list.adf-version-list-element .adf-version-list-item{border-bottom:1px solid var(--adf-theme-foreground-divider-color);width:100%;height:88px}.adf-version-list-item-version{font-weight:700}.adf-version-list-item-date{opacity:.6;white-space:normal}.adf-version-list-item-comment{width:auto;opacity:.5}@media screen and (width <= 629px){.adf-version-list-item-comment{width:97%}}.adf-version-list-item-name{white-space:normal;font-size:16px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "ngmodule", type: MatProgressBarModule }, { kind: "component", type: i6.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "ngmodule", type: MatListModule }, { kind: "component", type: i7.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "component", type: i7.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "directive", type: i7.MatListItemIcon, selector: "[matListItemIcon]" }, { kind: "component", type: CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }, { kind: "directive", type: CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { kind: "directive", type: CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i10.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i11.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: VersionCompatibilityDirective, selector: "[adf-acs-version]", inputs: ["adf-acs-version"] }], encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: VersionListComponent, decorators: [{
type: Component,
args: [{ selector: 'adf-version-list', standalone: true, imports: [
CommonModule,
MatProgressBarModule,
MatListModule,
CdkVirtualScrollViewport,
CdkFixedSizeVirtualScroll,
CdkVirtualForOf,
MatIconModule,
MatMenuModule,
TranslateModule,
MatButtonModule,
VersionCompatibilityDirective
], encapsulation: ViewEncapsulation.None, host: { class: 'adf-version-list' }, template: "<mat-progress-bar *ngIf=\"isLoading\" data-automation-id=\"version-history-loading-bar\" mode=\"indeterminate\"\n color=\"accent\" />\n<mat-list class=\"adf-version-list adf-version-list-element\" [hidden]=\"isLoading\">\n <cdk-virtual-scroll-viewport #viewport itemSize=\"88\" class=\"adf-version-list-viewport\" [minBufferPx]=\"440\" [maxBufferPx]=\"528\">\n <mat-list-item class=\"adf-version-list-item\"\n *cdkVirtualFor=\"let version of versionsDataSource; let idx = index; let latestVersion = first\">\n <mat-icon class=\"adf-version-list-icon\" matListItemIcon>insert_drive_file</mat-icon>\n <div class=\"adf-version-list-content\">\n <div class=\"adf-version-list-item-details\">\n <p class=\"adf-version-list-item-line adf-version-list-item-name\"\n [id]=\"'adf-version-list-item-name-' + version.entry.id\">{{ version.entry.name }}</p>\n <p>\n <span class=\"adf-version-list-item-line adf-version-list-item-version\"\n [id]=\"'adf-version-list-item-version-' + version.entry.id\">{{ version.entry.id }}</span> -\n <span class=\"adf-version-list-item-line adf-version-list-item-date\"\n [id]=\"'adf-version-list-item-date-' + version.entry.id\">{{ version.entry.modifiedAt | date }}</span>\n </p>\n <p\n [id]=\"'adf-version-list-item-comment-' + version.entry.id\"\n class=\"adf-version-list-item-comment\"\n *ngIf=\"showComments\"\n [title]=\"version.entry.versionComment\">\n {{ version.entry.versionComment }}\n </p>\n </div>\n <ng-container *ngIf=\"showActions\">\n <mat-menu [id]=\"'adf-version-list-action-menu-' + version.entry.id\"\n #versionMenu=\"matMenu\"\n yPosition=\"below\"\n xPosition=\"before\">\n <ng-container *adf-acs-version=\"'7'\">\n <button *ngIf=\"allowViewVersions\"\n [id]=\"'adf-version-list-action-view-' + version.entry.id\"\n mat-menu-item\n (click)=\"onViewVersion(version.entry.id)\">\n {{ 'ADF_VERSION_LIST.ACTIONS.VIEW' | translate }}\n </button>\n </ng-container>\n <button\n [id]=\"'adf-version-list-action-restore-' + version.entry.id\"\n [disabled]=\"!canUpdate() || latestVersion\"\n mat-menu-item\n (click)=\"restore(version.entry.id)\">\n {{ 'ADF_VERSION_LIST.ACTIONS.RESTORE' | translate }}\n </button>\n <button *ngIf=\"allowDownload\"\n [id]=\"'adf-version-list-action-download-' + version.entry.id\"\n mat-menu-item\n (click)=\"downloadVersion(version.entry.id)\">\n {{ 'ADF_VERSION_LIST.ACTIONS.DOWNLOAD' | translate }}\n </button>\n <button\n *ngIf=\"allowVersionDelete\"\n [disabled]=\"!canDelete()\"\n [id]=\"'adf-version-list-action-delete-' + version.entry.id\"\n (click)=\"deleteVersion(version.entry.id)\"\n mat-menu-item>\n {{ 'ADF_VERSION_LIST.ACTIONS.DELETE' | translate }}\n </button>\n </mat-menu>\n <button mat-icon-button\n [matMenuTriggerFor]=\"versionMenu\"\n [id]=\"'adf-version-list-action-menu-button-' + version.entry.id\"\n title=\"{{ 'ADF_VERSION_LIST.MANAGE_VERSION_OPTIONS' | translate }}\">\n <mat-icon>more_vert</mat-icon>\n </button>\n </ng-container>\n </div>\n </mat-list-item>\n </cdk-virtual-scroll-viewport>\n</mat-list>\n", styles: [".adf-version-list-viewport{height:100%;overflow-x:hidden;display:flex}.adf-version-list-viewport :first-child{max-width:100%}.adf-version-list-item-details{flex:1;width:90%}.adf-version-list-content{display:flex}.adf-version-list-content p{margin:0;overflow:hidden}.adf-version-list .adf-version-list-icon{margin:0 16px;color:var(--theme-sidenav-user-menu-color)}.adf-version-list.adf-version-list-element .adf-version-list-item{border-bottom:1px solid var(--adf-theme-foreground-divider-color);width:100%;height:88px}.adf-version-list-item-version{font-weight:700}.adf-version-list-item-date{opacity:.6;white-space:normal}.adf-version-list-item-comment{width:auto;opacity:.5}@media screen and (width <= 629px){.adf-version-list-item-comment{width:97%}}.adf-version-list-item-name{white-space:normal;font-size:16px}\n"] }]
}], ctorParameters: () => [{ type: i1.AlfrescoApiService }, { type: i2.ContentService }, { type: i3.ContentVersionService }, { type: i4.MatDialog }], propDecorators: { node: [{
type: Input
}], showComments: [{
type: Input
}], allowDownload: [{
type: Input
}], allowViewVersions: [{
type: Input
}], showActions: [{
type: Input
}], allowVersionDelete: [{
type: Input
}], restored: [{
type: Output
}], deleted: [{
type: Output
}], viewVersion: [{
type: Output
}], viewport: [{
type: ViewChild,
args: ['viewport']
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi1saXN0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL2xpYi9jb250ZW50LXNlcnZpY2VzL3NyYy9saWIvdmVyc2lvbi1tYW5hZ2VyL3ZlcnNpb24tbGlzdC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL3ZlcnNpb24tbWFuYWdlci92ZXJzaW9uLWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7OztHQWVHO0FBRUgsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDNUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDdEUsT0FBTyxFQUNILFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixLQUFLLEVBR0wsTUFBTSxFQUNOLFNBQVMsRUFDVCxpQkFBaUIsRUFDcEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFVBQVUsRUFBc0IsSUFBSSxFQUFhLFFBQVEsRUFBZ0IsV0FBVyxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDeEgsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDM0MsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDekUsT0FBTyxFQUFFLElBQUksRUFBYyxNQUFNLE1BQU0sQ0FBQztBQUN4QyxPQUFPLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxlQUFlLEVBQUUsd0JBQXdCLEVB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TixRQUFRO3NCQURQLE1BQU07Z0JBS1AsT0FBTztzQkFETixNQUFNO2dCQUtQLFdBQVc7c0JBRFYsTUFBTTtnQkFJUCxRQUFRO3NCQURQLFNBQVM7dUJBQUMsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbIi8qIVxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCDCqSAyMDA1LTIwMjUgSHlsYW5kIFNvZnR3YXJlLCBJbmMuIGFuZCBpdHMgYWZmaWxpYXRlcy4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xuICogeW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XG4gKlxuICogICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMFxuICpcbiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAqIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBCQVNJUyxcbiAqIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLlxuICogU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuaW1wb3J0IHsgQ29uZmlybURpYWxvZ0NvbXBvbmVudCB9IGZyb20gJ0BhbGZyZXNjby9hZGYtY29yZSc7XG5pbXBvcnQgeyBBbGZyZXNjb0FwaVNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9hbGZyZXNjby1hcGkuc2VydmljZSc7XG5pbXBvcnQge1xuICAgIENvbXBvbmVudCxcbiAgICBEZXN0cm95UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBpbmplY3QsXG4gICAgSW5wdXQsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uSW5pdCxcbiAgICBPdXRwdXQsXG4gICAgVmlld0NoaWxkLFxuICAgIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQ29udGVudEFwaSwgQ29udGVudFBhZ2luZ1F1ZXJ5LCBOb2RlLCBOb2RlRW50cnksIE5vZGVzQXBpLCBWZXJzaW9uRW50cnksIFZlcnNpb25zQXBpIH0gZnJvbSAnQGFsZnJlc2NvL2pzLWFwaSc7XG5pbXBvcnQgeyBNYXREaWFsb2cgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgQ29udGVudFZlcnNpb25TZXJ2aWNlIH0gZnJvbSAnLi9jb250ZW50LXZlcnNpb24uc2VydmljZSc7XG5pbXBvcnQgeyBDb250ZW50U2VydmljZSB9IGZyb20gJy4uL2NvbW1vbic7XG5pbXBvcnQgeyBJbmZpbml0ZVNjcm9sbERhdGFzb3VyY2UgfSBmcm9tICcuLi9pbmZpbml0ZS1zY3JvbGwtZGF0YXNvdXJjZSc7XG5pbXBvcnQgeyBmcm9tLCBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIHRha2UgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQgeyBDZGtGaXhlZFNpemVWaXJ0dWFsU2Nyb2xsLCBDZGtWaXJ0dWFsRm9yT2YsIENka1ZpcnR1YWxTY3JvbGxWaWV3cG9ydCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9zY3JvbGxpbmcnO1xuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IE1hdFByb2dyZXNzQmFyTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvcHJvZ3Jlc3MtYmFyJztcbmltcG9ydCB7IE1hdExpc3RNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9saXN0JztcbmltcG9ydCB7IE1hdEljb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcbmltcG9ydCB7IE1hdE1lbnVNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9tZW51JztcbmltcG9ydCB7IFRyYW5zbGF0ZU1vZHVsZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgTWF0QnV0dG9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvYnV0dG9uJztcbmltcG9ydCB7IFZlcnNpb25Db21wYXRpYmlsaXR5RGlyZWN0aXZlIH0gZnJvbSAnLi4vdmVyc2lvbi1jb21wYXRpYmlsaXR5JztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcblxuZXhwb3J0IGNsYXNzIFZlcnNpb25MaXN0RGF0YVNvdXJjZSBleHRlbmRzIEluZmluaXRlU2Nyb2xsRGF0YXNvdXJjZTxWZXJzaW9uRW50cnk+IHtcbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIHZlcnNpb25zQXBpOiBWZXJzaW9uc0FwaSwgcHJpdmF0ZSBub2RlOiBOb2RlKSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgfVxuXG4gICAgZ2V0TmV4dEJhdGNoKHBhZ2luZ09wdGlvbnM6IENvbnRlbnRQYWdpbmdRdWVyeSk6IE9ic2VydmFibGU8VmVyc2lvbkVudHJ5W10+IHtcbiAgICAgICAgcmV0dXJuIGZyb20odGhpcy52ZXJzaW9uc0FwaS5saXN0VmVyc2lvbkhpc3RvcnkodGhpcy5ub2RlLmlkLCBwYWdpbmdPcHRpb25zKSkucGlwZShcbiAgICAgICAgICAgIHRha2UoMSksXG4gICAgICAgICAgICBtYXAoKHZlcnNpb25QYWdpbmcpID0+IHZlcnNpb25QYWdpbmcubGlzdC5lbnRyaWVzKVxuICAgICAgICApO1xuICAgIH1cbn1cblxuQENvbXBvbmVudCh7XG4gICAgc2VsZWN0b3I6ICdhZGYtdmVyc2lvbi1saXN0JyxcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIGltcG9ydHM6IFtcbiAgICAgICAgQ29tbW9uTW9kdWxlLFxuICAgICAgICBNYXRQcm9ncmVzc0Jhck1vZHVsZSxcbiAgICAgICAgTWF0TGlzdE1vZHVsZSxcbiAgICAgICAgQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0LFxuICAgICAgICBDZGtGaXhlZFNpemVWaXJ0dWFsU2Nyb2xsLFxuICAgICAgICBDZGtWaXJ0dWFsRm9yT2YsXG4gICAgICAgIE1hdEljb25Nb2R1bGUsXG4gICAgICAgIE1hdE1lbnVNb2R1bGUsXG4gICAgICAgIFRyYW5zbGF0ZU1vZHVsZSxcbiAgICAgICAgTWF0QnV0dG9uTW9kdWxlLFxuICAgICAgICBWZXJzaW9uQ29tcGF0aWJpbGl0eURpcmVjdGl2ZVxuICAgIF0sXG4gICAgdGVtcGxhdGVVcmw6ICcuL3ZlcnNpb24tbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vdmVyc2lvbi1saXN0LmNvbXBvbmVudC5zY3NzJ10sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgICBob3N0OiB7IGNsYXNzOiAnYWRmLXZlcnNpb24tbGlzdCcgfVxufSlcbmV4cG9ydCBjbGFzcyBWZXJzaW9uTGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25Jbml0IHtcbiAgICBwcml2YXRlIF9jb250ZW50QXBpOiBDb250ZW50QXBpO1xuICAgIGdldCBjb250ZW50QXBpKCk6IENvbnRlbnRBcGkge1xuICAgICAgICB0aGlzLl9jb250ZW50QXBpID0gdGhpcy5fY29udGVudEFwaSA/PyBuZXcgQ29udGVudEFwaSh0aGlzLmFsZnJlc2NvQXBpLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fY29udGVudEFwaTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF92ZXJzaW9uc0FwaTogVmVyc2lvbnNBcGk7XG4gICAgZ2V0IHZlcnNpb25zQXBpKCk6IFZlcnNpb25zQXBpIHtcbiAgICAgICAgdGhpcy5fdmVyc2lvbnNBcGkgPSB0aGlzLl92ZXJzaW9uc0FwaSA/PyBuZXcgVmVyc2lvbnNBcGkodGhpcy5hbGZyZXNjb0FwaS5nZXRJbnN0YW5jZSgpKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ZlcnNpb25zQXBpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX25vZGVzQXBpOiBOb2Rlc0FwaTtcbiAgICBnZXQgbm9kZXNBcGkoKTogTm9kZXNBcGkge1xuICAgICAgICB0aGlzLl9ub2Rlc0FwaSA9IHRoaXMuX25vZGVzQXBpID8/IG5ldyBOb2Rlc0FwaSh0aGlzLmFsZnJlc2NvQXBpLmdldEluc3RhbmNlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbm9kZXNBcGk7XG4gICAgfVxuXG4gICAgdmVyc2lvbnNEYXRhU291cmNlOiBWZXJzaW9uTGlzdERhdGFTb3VyY2U7XG4gICAgbGF0ZXN0VmVyc2lvbjogVmVyc2lvbkVudHJ5O1xuICAgIGlzTG9hZGluZyA9IHRydWU7XG5cbiAgICAvKiogVGhlIHRhcmdldCBub2RlLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgbm9kZTogTm9kZTtcblxuICAgIC8qKiBUb2dnbGVzIHNob3dpbmcvaGlkaW5nIG9mIGNvbW1lbnRzICovXG4gICAgQElucHV0KClcbiAgICBzaG93Q29tbWVudHMgPSB0cnVlO1xuXG4gICAgLyoqIEVuYWJsZS9kaXNhYmxlIGRvd25sb2FkaW5nIGEgdmVyc2lvbiBvZiB0aGUgY3VycmVudCBub2RlLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgYWxsb3dEb3dubG9hZCA9IHRydWU7XG5cbiAgICAvKiogRW5hYmxlL2Rpc2FibGUgdmlld2luZyBhIHZlcnNpb24gb2YgdGhlIGN1cnJlbnQgbm9kZS4gKi9cbiAgICBASW5wdXQoKVxuICAgIGFsbG93Vmlld1ZlcnNpb25zID0gdHJ1ZTtcblxuICAgIC8qKiBUb2dnbGVzIHNob3dpbmcvaGlkaW5nIG9mIHZlcnNpb24gYWN0aW9ucyAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2hvd0FjdGlvbnMgPSB0cnVlO1xuXG4gICAgLyoqIEVuYWJsZS9kaXNhYmxlIGRlbGV0aW9uIG9mIHZlcnNpb24gKi9cbiAgICBASW5wdXQoKVxuICAgIGFsbG93VmVyc2lvbkRlbGV0ZSA9IHRydWU7XG5cbiAgICAvKiogRW1pdHRlZCB3aGVuIGEgdmVyc2lvbiBpcyByZXN0b3JlZCAqL1xuICAgIEBPdXRwdXQoKVxuICAgIHJlc3RvcmVkID0gbmV3IEV2ZW50RW1pdHRlcjxOb2RlPigpO1xuXG4gICAgLyoqIEVtaXR0ZWQgd2hlbiBhIHZlcnNpb24gaXMgZGVsZXRlZCAqL1xuICAgIEBPdXRwdXQoKVxuICAgIGRlbGV0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPE5vZGU+KCk7XG5cbiAgICAvKiogRW1pdHRlZCB3aGVuIHZpZXdpbmcgYSB2ZXJzaW9uICovXG4gICAgQE91dHB1dCgpXG4gICAgdmlld1ZlcnNpb24gPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICAgIEBWaWV3Q2hpbGQoJ3ZpZXdwb3J0JylcbiAgICB2aWV3cG9ydDogQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0O1xuXG4gICAgcHJpdmF0ZSByZWFkb25seSBkZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgYWxmcmVzY29BcGk6IEFsZnJlc2NvQXBpU2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSBjb250ZW50U2VydmljZTogQ29udGVudFNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgY29udGVudFZlcnNpb25TZXJ2aWNlOiBDb250ZW50VmVyc2lvblNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgZGlhbG9nOiBNYXREaWFsb2dcbiAgICApIHt9XG5cbiAgICBuZ09uSW5pdCgpIHtcbiAgICAgICAgdGhpcy52ZXJzaW9uc0RhdGFTb3VyY2UgPSBuZXcgVmVyc2lvbkxpc3REYXRhU291cmNlKHRoaXMudmVyc2lvbnNBcGksIHRoaXMubm9kZSk7XG4gICAgICAgIHRoaXMudmVyc2lvbnNEYXRhU291cmNlLmlzTG9hZGluZy5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpKS5zdWJzY3JpYmUoKGlzTG9hZGluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSBpc0xvYWRpbmc7XG4gICAgICAgICAgICB0aGlzLmxhdGVzdFZlcnNpb24gPSB0aGlzLnZlcnNpb25zRGF0YVNvdXJjZS5maXJzdEl0ZW07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG5nT25DaGFuZ2VzKCkge1xuICAgICAgICBpZiAodGhpcy52ZXJzaW9uc0RhdGFTb3VyY2UpIHtcbiAgICAgICAgICAgIHRoaXMubG9hZFZlcnNpb25IaXN0b3J5KCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxuICAgIGNhblVwZGF0ZSgpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29udGVudFNlcnZpY2UuaGFzQWxsb3dhYmxlT3BlcmF0aW9ucyh0aGlzLm5vZGUsICd1cGRhdGUnKSAmJiB0aGlzLnZlcnNpb25zRGF0YVNvdXJjZS5pdGVtc0NvdW50ID4gMTtcbiAgICB9XG5cbiAgICBjYW5EZWxldGUoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnRlbnRTZXJ2aWNlLmhhc0FsbG93YWJsZU9wZXJhdGlvbnModGhpcy5ub2RlLCAnZGVsZXRlJykgJiYgdGhpcy52ZXJzaW9uc0RhdGFTb3VyY2UuaXRlbXNDb3VudCA+IDE7XG4gICAgfVxuXG4gICAgcmVzdG9yZSh2ZXJzaW9uSWQ6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5jYW5VcGRhdGUoKSkge1xuICAgICAgICAgICAgdGhpcy52ZXJzaW9uc0FwaVxuICAgICAgICAgICAgICAgIC5yZXZlcnRWZXJzaW9uKHRoaXMubm9kZS5pZCwgdmVyc2lvbklkLCB7IG1ham9yVmVyc2lvbjogdHJ1ZSwgY29tbWVudDogJycgfSlcbiAgICAgICAgICAgICAgICAudGhlbigoKSA9PiB0aGlzLm5vZGVzQXBpLmdldE5vZGUodGhpcy5ub2RlLmlkLCB7IGluY2x1ZGU6IFsncGVybWlzc2lvbnMnLCAncGF0aCcsICdpc0Zhdm9yaXRlJywgJ2FsbG93YWJsZU9wZXJhdGlvbnMnXSB9KSlcbiAgICAgICAgICAgICAgICAudGhlbigobm9kZSkgPT4gdGhpcy5vblZlcnNpb25SZXN0b3JlZChub2RlKSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblZpZXdWZXJzaW9uKHZlcnNpb25JZDogc3RyaW5nKSB7XG4gICAgICAgIHRoaXMudmlld1ZlcnNpb24uZW1pdCh2ZXJzaW9uSWQpO1xuICAgIH1cblxuICAgIGxvYWRWZXJzaW9uSGlzdG9yeSgpIHtcbiAgICAgICAgdGhpcy52aWV3cG9ydC5zY3JvbGxUb0luZGV4KDApO1xuICAgICAgICB0aGlzLnZlcnNpb25zRGF0YVNvdXJjZS5yZXNldCgpO1xuICAgIH1cblxuICAgIGRvd25sb2FkVmVyc2lvbih2ZXJzaW9uSWQ6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5hbGxvd0Rvd25sb2FkKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnRlbnRWZXJzaW9uU2VydmljZVxuICAgICAgICAgICAgICAgIC5nZXRWZXJzaW9uQ29udGVudFVybCh0aGlzLm5vZGUuaWQsIHZlcnNpb25JZCwgdHJ1ZSlcbiAgICAgICAgICAgICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKCh2ZXJzaW9uRG93bmxvYWRVcmwpID0+IHRoaXMuZG93bmxvYWRDb250ZW50KHZlcnNpb25Eb3dubG9hZFVybCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGVsZXRlVmVyc2lvbih2ZXJzaW9uSWQ6IHN0cmluZykge1xuICAgICAgICBpZiAodGhpcy5jYW5VcGRhdGUoKSkge1xuICAgICAgICAgICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihDb25maXJtRGlhbG9nQ29tcG9uZW50LCB7XG4gICAgICAgICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgICAgICAgICB0aXRsZTogJ0FERl9WRVJTSU9OX0xJU1QuQ09ORklSTV9ERUxFVEUuVElUTEUnLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiAnQURGX1ZFUlNJT05fTElTVC5DT05GSVJNX0RFTEVURS5NRVNTQUdFJyxcbiAgICAgICAgICAgICAgICAgICAgeWVzTGFiZWw6ICdBREZfVkVSU0lPTl9MSVNULkNPTkZJUk1fREVMRVRFLllFU19MQUJFTCcsXG4gICAgICAgICAgICAgICAgICAgIG5vTGFiZWw6ICdBREZfVkVSU0lPTl9MSVNULkNPTkZJUk1fREVMRVRFLk5PX0xBQkVMJ1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgbWluV2lkdGg6ICcyNTBweCdcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBkaWFsb2dSZWZcbiAgICAgICAgICAgICAgICAuYWZ0ZXJDbG9zZWQoKVxuICAgICAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpKVxuICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKHJlc3VsdCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnZlcnNpb25zQXBpLmRlbGV0ZVZlcnNpb24odGhpcy5ub2RlLmlkLCB2ZXJzaW9uSWQpLnRoZW4oKCkgPT4gdGhpcy5vblZlcnNpb25EZWxldGVkKHRoaXMubm9kZSkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBvblZlcnNpb25EZWxldGVkKG5vZGU6IGFueSkge1xuICAgICAgICB0aGlzLmxvYWRWZXJzaW9uSGlzdG9yeSgpO1xuICAgICAgICB0aGlzLmRlbGV0ZWQuZW1pdChub2RlKTtcbiAgICB9XG5cbiAgICBvblZlcnNpb25SZXN0b3JlZChub2RlOiBOb2RlRW50cnkpIHtcbiAgICAgICAgdGhpcy5sb2FkVmVyc2lvbkhpc3RvcnkoKTtcbiAgICAgICAgdGhpcy5yZXN0b3JlZC5lbWl0KG5vZGU/LmVudHJ5KTtcbiAgICB9XG5cbiAgICBkb3dubG9hZENvbnRlbnQodXJsOiBzdHJpbmcpIHtcbiAgICAgICAgaWYgKHVybCkge1xuICAgICAgICAgICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcblxuICAgICAgICAgICAgbGluay5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgICAgICAgICAgbGluay5ocmVmID0gdXJsO1xuXG4gICAgICAgICAgICBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGxpbmspO1xuICAgICAgICAgICAgbGluay5jbGljaygpO1xuICAgICAgICAgICAgZG9jdW1lbnQuYm9keS5yZW1vdmVDaGlsZChsaW5rKTtcbiAgICAgICAgfVxuICAgIH1cbn1cbiIsIjxtYXQtcHJvZ3Jlc3MtYmFyICpuZ0lmPVwiaXNMb2FkaW5nXCIgZGF0YS1hdXRvbWF0aW9uLWlkPVwidmVyc2lvbi1oaXN0b3J5LWxvYWRpbmctYmFyXCIgbW9kZT1cImluZGV0ZXJtaW5hdGVcIlxuICAgICAgICAgICAgICAgICAgY29sb3I9XCJhY2NlbnRcIiAvPlxuPG1hdC1saXN0IGNsYXNzPVwiYWRmLXZlcnNpb24tbGlzdCBhZGYtdmVyc2lvbi1saXN0LWVsZW1lbnRcIiBbaGlkZGVuXT1cImlzTG9hZGluZ1wiPlxuICAgIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQgI3ZpZXdwb3J0IGl0ZW1TaXplPVwiODhcIiBjbGFzcz1cImFkZi12ZXJzaW9uLWxpc3Qtdmlld3BvcnRcIiBbbWluQnVmZmVyUHhdPVwiNDQwXCIgW21heEJ1ZmZlclB4XT1cIjUyOFwiPlxuICAgICAgICA8bWF0LWxpc3QtaXRlbSBjbGFzcz1cImFkZi12ZXJzaW9uLWxpc3QtaXRlbVwiXG4gICAgICAgICAgICAgICAgICAgICAgICpjZGtWaXJ0dWFsRm9yPVwibGV0IHZlcnNpb24gb2YgdmVyc2lvbnNEYXRhU291cmNlOyBsZXQgaWR4ID0gaW5kZXg7IGxldCBsYXRlc3RWZXJzaW9uID0gZmlyc3RcIj5cbiAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImFkZi12ZXJzaW9uLWxpc3QtaWNvblwiIG1hdExpc3RJdGVtSWNvbj5pbnNlcnRfZHJpdmVfZmlsZTwvbWF0LWljb24+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWRmLXZlcnNpb24tbGlzdC1jb250ZW50XCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImFkZi12ZXJzaW9uLWxpc3QtaXRlbS1kZXRhaWxzXCI+XG4gICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwiYWRmLXZlcnNpb24tbGlzdC1pdGVtLWxpbmUgYWRmLXZlcnNpb24tbGlzdC1pdGVtLW5hbWVcIlxuICAgICAgICAgICAgICAgICAgICAgICBbaWRdPVwiJ2FkZi12ZXJzaW9uLWxpc3QtaXRlbS1uYW1lLScgKyB2ZXJzaW9uLmVudHJ5LmlkXCI+e3sgdmVyc2lvbi5lbnRyeS5uYW1lIH19PC9wPlxuICAgICAgICAgICAgICAgICAgICA8cD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiYWRmLXZlcnNpb24tbGlzdC1pdGVtLWxpbmUgYWRmLXZlcnNpb24tbGlzdC1pdGVtLXZlcnNpb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbaWRdPVwiJ2FkZi12ZXJzaW9uLWxpc3QtaXRlbS12ZXJzaW9uLScgKyB2ZXJzaW9uLmVudHJ5LmlkXCI+e3sgdmVyc2lvbi5lbnRyeS5pZCB9fTwvc3Bhbj4gLVxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJhZGYtdmVyc2lvbi1saXN0LWl0ZW0tbGluZSBhZGYtdmVyc2lvbi1saXN0LWl0ZW0tZGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaWRdPVwiJ2FkZi12ZXJzaW9uLWxpc3QtaXRlbS1kYXRlLScgKyB2ZXJzaW9uLmVudHJ5LmlkXCI+e3sgdmVyc2lvbi5lbnRyeS5tb2RpZmllZEF0IHwgZGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9wPlxuICAgICAgICAgICAgICAgICAgICA8cFxuICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cIidhZGYtdmVyc2lvbi1saXN0LWl0ZW0tY29tbWVudC0nICsgdmVyc2lvbi5lbnRyeS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImFkZi12ZXJzaW9uLWxpc3QtaXRlbS1jb21tZW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwic2hvd0NvbW1lbnRzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFt0aXRsZV09XCJ2ZXJzaW9uLmVudHJ5LnZlcnNpb25Db21tZW50XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyB2ZXJzaW9uLmVudHJ5LnZlcnNpb25Db21tZW50IH19XG4gICAgICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwic2hvd0FjdGlvbnNcIj5cbiAgICAgICAgICAgICAgICA8bWF0LW1lbnUgW2lkXT1cIidhZGYtdmVyc2lvbi1saXN0LWFjdGlvbi1tZW51LScgKyB2ZXJzaW9uLmVudHJ5LmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgI3ZlcnNpb25NZW51PVwibWF0TWVudVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHlQb3NpdGlvbj1cImJlbG93XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgeFBvc2l0aW9uPVwiYmVmb3JlXCI+XG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKmFkZi1hY3MtdmVyc2lvbj1cIic3J1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImFsbG93Vmlld1ZlcnNpb25zXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cIidhZGYtdmVyc2lvbi1saXN0LWFjdGlvbi12aWV3LScgKyB2ZXJzaW9uLmVudHJ5LmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25WaWV3VmVyc2lvbih2ZXJzaW9uLmVudHJ5LmlkKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ICdBREZfVkVSU0lPTl9MSVNULkFDVElPTlMuVklFVycgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cIidhZGYtdmVyc2lvbi1saXN0LWFjdGlvbi1yZXN0b3JlLScgKyB2ZXJzaW9uLmVudHJ5LmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhY2FuVXBkYXRlKCkgfHwgbGF0ZXN0VmVyc2lvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVzdG9yZSh2ZXJzaW9uLmVudHJ5LmlkKVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgJ0FERl9WRVJTSU9OX0xJU1QuQUNUSU9OUy5SRVNUT1JFJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiAqbmdJZj1cImFsbG93RG93bmxvYWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpZF09XCInYWRmLXZlcnNpb24tbGlzdC1hY3Rpb24tZG93bmxvYWQtJyArIHZlcnNpb24uZW50cnkuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiZG93bmxvYWRWZXJzaW9uKHZlcnNpb24uZW50cnkuaWQpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyAnQURGX1ZFUlNJT05fTElTVC5BQ1RJT05TLkRPV05MT0FEJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd1ZlcnNpb25EZWxldGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFjYW5EZWxldGUoKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbaWRdPVwiJ2FkZi12ZXJzaW9uLWxpc3QtYWN0aW9uLWRlbGV0ZS0nICsgdmVyc2lvbi5lbnRyeS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiZGVsZXRlVmVyc2lvbih2ZXJzaW9uLmVudHJ5LmlkKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtPlxuICAgICAgICAgICAgICAgICAgICAgICAge3sgJ0FERl9WRVJTSU9OX0xJU1QuQUNUSU9OUy5ERUxFVEUnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIDwvbWF0LW1lbnU+XG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF0TWVudVRyaWdnZXJGb3JdPVwidmVyc2lvbk1lbnVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpZF09XCInYWRmLXZlcnNpb24tbGlzdC1hY3Rpb24tbWVudS1idXR0b24tJyArIHZlcnNpb24uZW50cnkuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPVwie3sgJ0FERl9WRVJTSU9OX0xJU1QuTUFOQUdFX1ZFUlNJT05fT1BUSU9OUycgfCB0cmFuc2xhdGUgfX1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5tb3JlX3ZlcnQ8L21hdC1pY29uPlxuICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L21hdC1saXN0LWl0ZW0+XG4gICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XG48L21hdC1saXN0PlxuIl19