UNPKG

@alfresco/adf-content-services

Version:
134 lines 32.4 kB
/*! * @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 { EXTENDIBLE_COMPONENT, FileUtils } from '@alfresco/adf-core'; import { Component, EventEmitter, forwardRef, Input, Output, ViewEncapsulation, inject } from '@angular/core'; import { NodesApiService } from '../../common/services/nodes-api.service'; import { ContentService } from '../../common/services/content.service'; import { AllowableOperationsEnum } from '../../common/models/allowable-operations.enum'; import { Subject } from 'rxjs'; import { PermissionModel } from '../../document-list/models/permissions.model'; import { UploadBase } from './base-upload/upload-base'; import { CommonModule } from '@angular/common'; import { MatButtonModule } from '@angular/material/button'; import { TranslateModule } from '@ngx-translate/core'; import { MatIconModule } from '@angular/material/icon'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@ngx-translate/core"; import * as i3 from "@angular/material/icon"; export class UploadButtonComponent extends UploadBase { constructor() { super(...arguments); this.contentService = inject(ContentService); this.nodesApiService = inject(NodesApiService); /** Allows/disallows upload folders (only for Chrome). */ this.uploadFolders = false; /** Allows/disallows multiple files */ this.multipleFiles = false; /** Custom tooltip text. */ this.tooltip = null; /** Emitted when create permission is missing. */ this.permissionEvent = new EventEmitter(); this.hasAllowableOperations = false; this.permissionValue = new Subject(); } ngOnInit() { this.permissionValue.subscribe((permission) => { this.hasAllowableOperations = permission; }); } ngOnChanges(changes) { const rootFolderId = changes['rootFolderId']; if (rootFolderId?.currentValue) { this.checkPermission(); } } isButtonDisabled() { return this.disabled ? true : undefined; } onFilesAdded($event) { const files = FileUtils.toFileArray($event.currentTarget.files); if (this.hasAllowableOperations) { this.uploadFiles(files); } else { this.permissionEvent.emit(new PermissionModel({ type: 'content', action: 'upload', permission: 'create' })); } // reset the value of the input file $event.target.value = ''; } onClickUploadButton() { if (this.file) { const files = [this.file]; if (this.hasAllowableOperations) { this.uploadFiles(files); } else { this.permissionEvent.emit(new PermissionModel({ type: 'content', action: 'upload', permission: 'create' })); } } } onDirectoryAdded($event) { if (this.hasAllowableOperations) { const files = FileUtils.toFileArray($event.currentTarget.files); this.uploadFiles(files); } else { this.permissionEvent.emit(new PermissionModel({ type: 'content', action: 'upload', permission: 'create' })); } // reset the value of the input file $event.target.value = ''; } checkPermission() { if (this.rootFolderId) { const opts = { includeSource: true, include: ['allowableOperations'] }; this.nodesApiService.getNode(this.rootFolderId, opts).subscribe((res) => this.permissionValue.next(this.nodeHasPermission(res, AllowableOperationsEnum.CREATE)), (error) => { if (error?.error) { this.error.emit({ error: error.error.message }); } else { this.error.emit({ error: 'FILE_UPLOAD.BUTTON.PERMISSION_CHECK_ERROR' }); } }); } } nodeHasPermission(node, permission) { return this.contentService.hasAllowableOperations(node, permission); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: UploadButtonComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.1.3", type: UploadButtonComponent, isStandalone: true, selector: "adf-upload-button", inputs: { uploadFolders: "uploadFolders", multipleFiles: "multipleFiles", staticTitle: "staticTitle", tooltip: "tooltip", file: "file" }, outputs: { permissionEvent: "permissionEvent" }, usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<form class=\"adf-upload-button-file-container\">\n <!--Files Upload-->\n <div *ngIf=\"!uploadFolders\">\n\n <!--Single Files Upload-->\n <ng-container *ngIf=\"!multipleFiles\">\n <input\n class=\"adf-upload-button-file-container-upload-single-file\"\n id=\"upload-single-file\"\n data-automation-id=\"upload-single-file\"\n [type]=\"file ? 'button' : 'file'\"\n name=\"uploadFiles\"\n accept=\"{{acceptedFilesType}}\"\n [attr.disabled]=\"isButtonDisabled()\"\n [title]=\"tooltip\"\n (change)=\"onFilesAdded($event)\"\n (click)=\"onClickUploadButton()\"/>\n <label for=\"upload-single-file\" class=\"adf-upload-button-label\">\n <mat-icon class=\"adf-upload-button-icon\">file_upload</mat-icon>\n <span id=\"upload-single-file-label\" *ngIf=\"!staticTitle\">\n {{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>\n <span id=\"upload-single-file-label-static\" *ngIf=\"staticTitle\">\n {{ staticTitle }}</span>\n </label>\n </ng-container>\n\n <!--Multiple Files Upload-->\n <ng-container *ngIf=\"multipleFiles\">\n <input\n id=\"upload-multiple-files\"\n data-automation-id=\"upload-multiple-files\"\n type=\"file\"\n name=\"uploadFiles\"\n multiple=\"multiple\"\n accept=\"{{acceptedFilesType}}\"\n [attr.disabled]=\"isButtonDisabled()\"\n [title]=\"tooltip\"\n (change)=\"onFilesAdded($event)\"/>\n <label for=\"upload-multiple-files\" class=\"adf-upload-button-label\">\n <mat-icon class=\"adf-upload-button-icon\">file_upload</mat-icon>\n <span id=\"upload-multiple-file-label\" *ngIf=\"!staticTitle\">\n {{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>\n <span id=\"upload-multiple-file-label-static\" *ngIf=\"staticTitle\">\n {{ staticTitle }}</span>\n </label>\n </ng-container>\n </div>\n\n <!--Folders Upload-->\n <ng-container *ngIf=\"uploadFolders\">\n <input\n id=\"uploadFolder\"\n data-automation-id=\"uploadFolder\"\n type=\"file\"\n name=\"uploadFiles\"\n multiple=\"multiple\"\n accept=\"{{acceptedFilesType}}\"\n webkitdirectory directory\n [attr.disabled]=\"isButtonDisabled()\"\n [title]=\"tooltip\"\n (change)=\"onDirectoryAdded($event)\"/>\n <label for=\"uploadFolder\" data-automation-id=\"uploadFolder\" class=\"adf-upload-button-label\">\n <mat-icon class=\"adf-upload-button-icon\">file_upload</mat-icon>\n <span id=\"uploadFolder-label\" *ngIf=\"!staticTitle\">\n {{ 'FILE_UPLOAD.BUTTON.UPLOAD_FOLDER' | translate }}</span>\n <span id=\"uploadFolder-label-static\" *ngIf=\"staticTitle\">\n {{ staticTitle }}</span>\n </label>\n </ng-container>\n</form>\n", styles: [".adf-upload-button-file-container .adf-upload-button-icon{margin:0;font-size:24px;width:24px;height:24px}.adf-upload-button-file-container input{display:none}.adf-upload-button-label{display:flex;align-items:center;cursor:pointer;padding:8px 16px;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;border-radius:4px}.adf-upload-button-label:active{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.adf-upload-button-file-container-upload-single-file[disabled]+.adf-upload-button-label{background-color:var(--adf-disabled-button-background);color:var(--adf-theme-foreground-disabled-text-color);box-shadow:none;cursor:default}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], viewProviders: [{ provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadButtonComponent) }], encapsulation: i0.ViewEncapsulation.None }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.1.3", ngImport: i0, type: UploadButtonComponent, decorators: [{ type: Component, args: [{ selector: 'adf-upload-button', standalone: true, imports: [CommonModule, MatButtonModule, TranslateModule, MatIconModule], viewProviders: [{ provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadButtonComponent) }], encapsulation: ViewEncapsulation.None, template: "<form class=\"adf-upload-button-file-container\">\n <!--Files Upload-->\n <div *ngIf=\"!uploadFolders\">\n\n <!--Single Files Upload-->\n <ng-container *ngIf=\"!multipleFiles\">\n <input\n class=\"adf-upload-button-file-container-upload-single-file\"\n id=\"upload-single-file\"\n data-automation-id=\"upload-single-file\"\n [type]=\"file ? 'button' : 'file'\"\n name=\"uploadFiles\"\n accept=\"{{acceptedFilesType}}\"\n [attr.disabled]=\"isButtonDisabled()\"\n [title]=\"tooltip\"\n (change)=\"onFilesAdded($event)\"\n (click)=\"onClickUploadButton()\"/>\n <label for=\"upload-single-file\" class=\"adf-upload-button-label\">\n <mat-icon class=\"adf-upload-button-icon\">file_upload</mat-icon>\n <span id=\"upload-single-file-label\" *ngIf=\"!staticTitle\">\n {{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>\n <span id=\"upload-single-file-label-static\" *ngIf=\"staticTitle\">\n {{ staticTitle }}</span>\n </label>\n </ng-container>\n\n <!--Multiple Files Upload-->\n <ng-container *ngIf=\"multipleFiles\">\n <input\n id=\"upload-multiple-files\"\n data-automation-id=\"upload-multiple-files\"\n type=\"file\"\n name=\"uploadFiles\"\n multiple=\"multiple\"\n accept=\"{{acceptedFilesType}}\"\n [attr.disabled]=\"isButtonDisabled()\"\n [title]=\"tooltip\"\n (change)=\"onFilesAdded($event)\"/>\n <label for=\"upload-multiple-files\" class=\"adf-upload-button-label\">\n <mat-icon class=\"adf-upload-button-icon\">file_upload</mat-icon>\n <span id=\"upload-multiple-file-label\" *ngIf=\"!staticTitle\">\n {{ 'FILE_UPLOAD.BUTTON.UPLOAD_FILE' | translate }}</span>\n <span id=\"upload-multiple-file-label-static\" *ngIf=\"staticTitle\">\n {{ staticTitle }}</span>\n </label>\n </ng-container>\n </div>\n\n <!--Folders Upload-->\n <ng-container *ngIf=\"uploadFolders\">\n <input\n id=\"uploadFolder\"\n data-automation-id=\"uploadFolder\"\n type=\"file\"\n name=\"uploadFiles\"\n multiple=\"multiple\"\n accept=\"{{acceptedFilesType}}\"\n webkitdirectory directory\n [attr.disabled]=\"isButtonDisabled()\"\n [title]=\"tooltip\"\n (change)=\"onDirectoryAdded($event)\"/>\n <label for=\"uploadFolder\" data-automation-id=\"uploadFolder\" class=\"adf-upload-button-label\">\n <mat-icon class=\"adf-upload-button-icon\">file_upload</mat-icon>\n <span id=\"uploadFolder-label\" *ngIf=\"!staticTitle\">\n {{ 'FILE_UPLOAD.BUTTON.UPLOAD_FOLDER' | translate }}</span>\n <span id=\"uploadFolder-label-static\" *ngIf=\"staticTitle\">\n {{ staticTitle }}</span>\n </label>\n </ng-container>\n</form>\n", styles: [".adf-upload-button-file-container .adf-upload-button-icon{margin:0;font-size:24px;width:24px;height:24px}.adf-upload-button-file-container input{display:none}.adf-upload-button-label{display:flex;align-items:center;cursor:pointer;padding:8px 16px;box-shadow:0 3px 1px -2px #0003,0 2px 2px #00000024,0 1px 5px #0000001f;border-radius:4px}.adf-upload-button-label:active{box-shadow:0 5px 5px -3px #0003,0 8px 10px 1px #00000024,0 3px 14px 2px #0000001f}.adf-upload-button-file-container-upload-single-file[disabled]+.adf-upload-button-label{background-color:var(--adf-disabled-button-background);color:var(--adf-theme-foreground-disabled-text-color);box-shadow:none;cursor:default}\n"] }] }], propDecorators: { uploadFolders: [{ type: Input }], multipleFiles: [{ type: Input }], staticTitle: [{ type: Input }], tooltip: [{ type: Input }], file: [{ type: Input }], permissionEvent: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXBsb2FkLWJ1dHRvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9saWIvY29udGVudC1zZXJ2aWNlcy9zcmMvbGliL3VwbG9hZC9jb21wb25lbnRzL3VwbG9hZC1idXR0b24uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGliL2NvbnRlbnQtc2VydmljZXMvc3JjL2xpYi91cGxvYWQvY29tcG9uZW50cy91cGxvYWQtYnV0dG9uLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7R0FlRztBQUVILE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFxQixNQUFNLEVBQWlCLGlCQUFpQixFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoSixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLCtDQUErQyxDQUFDO0FBRXhGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDhDQUE4QyxDQUFDO0FBQy9FLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUV2RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQzNELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sd0JB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cUJBQXFCLG9UQ3pDbEMscXNHQXNFQSxrdUJEbkNjLFlBQVksa0lBQUUsZUFBZSw4QkFBRSxlQUFlLDJGQUFFLGFBQWEseUtBR3hELENBQUMsRUFBRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxxQkFBcUIsQ0FBQyxFQUFFLENBQUM7OzJGQUcvRixxQkFBcUI7a0JBVGpDLFNBQVM7K0JBQ0ksbUJBQW1CLGNBQ2pCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxlQUFlLEVBQUUsZUFBZSxFQUFFLGFBQWEsQ0FBQyxpQkFHekQsQ0FBQyxFQUFFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxzQkFBc0IsQ0FBQyxFQUFFLENBQUMsaUJBQ3pGLGlCQUFpQixDQUFDLElBQUk7OEJBUXJDLGFBQWE7c0JBRFosS0FBSztnQkFLTixhQUFhO3NCQURaLEtBQUs7Z0JBS04sV0FBVztzQkFEVixLQUFLO2dCQUtOLE9BQU87c0JBRE4sS0FBSztnQkFLTixJQUFJO3NCQURILEtBQUs7Z0JBS04sZUFBZTtzQkFEZCxNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiLyohXG4gKiBAbGljZW5zZVxuICogQ29weXJpZ2h0IMKpIDIwMDUtMjAyNSBIeWxhbmQgU29mdHdhcmUsIEluYy4gYW5kIGl0cyBhZmZpbGlhdGVzLiBBbGwgcmlnaHRzIHJlc2VydmVkLlxuICpcbiAqIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBFWFRFTkRJQkxFX0NPTVBPTkVOVCwgRmlsZVV0aWxzIH0gZnJvbSAnQGFsZnJlc2NvL2FkZi1jb3JlJztcbmltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBmb3J3YXJkUmVmLCBJbnB1dCwgT25DaGFuZ2VzLCBPbkluaXQsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcywgVmlld0VuY2Fwc3VsYXRpb24sIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTm9kZXNBcGlTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL3NlcnZpY2VzL25vZGVzLWFwaS5zZXJ2aWNlJztcbmltcG9ydCB7IENvbnRlbnRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29tbW9uL3NlcnZpY2VzL2NvbnRlbnQuc2VydmljZSc7XG5pbXBvcnQgeyBBbGxvd2FibGVPcGVyYXRpb25zRW51bSB9IGZyb20gJy4uLy4uL2NvbW1vbi9tb2RlbHMvYWxsb3dhYmxlLW9wZXJhdGlvbnMuZW51bSc7XG5pbXBvcnQgeyBOb2RlIH0gZnJvbSAnQGFsZnJlc2NvL2pzLWFwaSc7XG5pbXBvcnQgeyBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBQZXJtaXNzaW9uTW9kZWwgfSBmcm9tICcuLi8uLi9kb2N1bWVudC1saXN0L21vZGVscy9wZXJtaXNzaW9ucy5tb2RlbCc7XG5pbXBvcnQgeyBVcGxvYWRCYXNlIH0gZnJvbSAnLi9iYXNlLXVwbG9hZC91cGxvYWQtYmFzZSc7XG5pbXBvcnQgeyBOb2RlQWxsb3dhYmxlT3BlcmF0aW9uU3ViamVjdCB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvbm9kZS1hbGxvd2FibGUtb3BlcmF0aW9uLXN1YmplY3QuaW50ZXJmYWNlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBNYXRCdXR0b25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgVHJhbnNsYXRlTW9kdWxlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBNYXRJY29uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvaWNvbic7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAnYWRmLXVwbG9hZC1idXR0b24nLFxuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgTWF0QnV0dG9uTW9kdWxlLCBUcmFuc2xhdGVNb2R1bGUsIE1hdEljb25Nb2R1bGVdLFxuICAgIHRlbXBsYXRlVXJsOiAnLi91cGxvYWQtYnV0dG9uLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybHM6IFsnLi91cGxvYWQtYnV0dG9uLmNvbXBvbmVudC5zY3NzJ10sXG4gICAgdmlld1Byb3ZpZGVyczogW3sgcHJvdmlkZTogRVhURU5ESUJMRV9DT01QT05FTlQsIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFVwbG9hZEJ1dHRvbkNvbXBvbmVudCkgfV0sXG4gICAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZVxufSlcbmV4cG9ydCBjbGFzcyBVcGxvYWRCdXR0b25Db21wb25lbnQgZXh0ZW5kcyBVcGxvYWRCYXNlIGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMsIE5vZGVBbGxvd2FibGVPcGVyYXRpb25TdWJqZWN0IHtcbiAgICBwcml2YXRlIGNvbnRlbnRTZXJ2aWNlID0gaW5qZWN0KENvbnRlbnRTZXJ2aWNlKTtcbiAgICBwcml2YXRlIG5vZGVzQXBpU2VydmljZSA9IGluamVjdChOb2Rlc0FwaVNlcnZpY2UpO1xuXG4gICAgLyoqIEFsbG93cy9kaXNhbGxvd3MgdXBsb2FkIGZvbGRlcnMgKG9ubHkgZm9yIENocm9tZSkuICovXG4gICAgQElucHV0KClcbiAgICB1cGxvYWRGb2xkZXJzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgICAvKiogQWxsb3dzL2Rpc2FsbG93cyBtdWx0aXBsZSBmaWxlcyAqL1xuICAgIEBJbnB1dCgpXG4gICAgbXVsdGlwbGVGaWxlczogYm9vbGVhbiA9IGZhbHNlO1xuXG4gICAgLyoqIERlZmluZXMgdGhlIHRleHQgb2YgdGhlIHVwbG9hZCBidXR0b24uICovXG4gICAgQElucHV0KClcbiAgICBzdGF0aWNUaXRsZTogc3RyaW5nO1xuXG4gICAgLyoqIEN1c3RvbSB0b29sdGlwIHRleHQuICovXG4gICAgQElucHV0KClcbiAgICB0b29sdGlwOiBzdHJpbmcgPSBudWxsO1xuXG4gICAgLyoqIEN1c3RvbSBhZGRlZCBmaWxlLiBUaGUgdXBsb2FkIGJ1dHRvbiB0eXBlIHdpbGwgYmUgJ2J1dHRvbicgaW5zdGVhZCBvZiAnZmlsZScgKi9cbiAgICBASW5wdXQoKVxuICAgIGZpbGU6IEZpbGU7XG5cbiAgICAvKiogRW1pdHRlZCB3aGVuIGNyZWF0ZSBwZXJtaXNzaW9uIGlzIG1pc3NpbmcuICovXG4gICAgQE91dHB1dCgpXG4gICAgcGVybWlzc2lvbkV2ZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxQZXJtaXNzaW9uTW9kZWw+KCk7XG5cbiAgICBwcml2YXRlIGhhc0FsbG93YWJsZU9wZXJhdGlvbnM6IGJvb2xlYW4gPSBmYWxzZTtcbiAgICBwcm90ZWN0ZWQgcGVybWlzc2lvblZhbHVlID0gbmV3IFN1YmplY3Q8Ym9vbGVhbj4oKTtcblxuICAgIG5nT25Jbml0KCkge1xuICAgICAgICB0aGlzLnBlcm1pc3Npb25WYWx1ZS5zdWJzY3JpYmUoKHBlcm1pc3Npb246IGJvb2xlYW4pID0+IHtcbiAgICAgICAgICAgIHRoaXMuaGFzQWxsb3dhYmxlT3BlcmF0aW9ucyA9IHBlcm1pc3Npb247XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICAgICAgY29uc3Qgcm9vdEZvbGRlcklkID0gY2hhbmdlc1sncm9vdEZvbGRlcklkJ107XG4gICAgICAgIGlmIChyb290Rm9sZGVySWQ/LmN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5jaGVja1Blcm1pc3Npb24oKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlzQnV0dG9uRGlzYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpc2FibGVkID8gdHJ1ZSA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBvbkZpbGVzQWRkZWQoJGV2ZW50OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZmlsZXMgPSBGaWxlVXRpbHMudG9GaWxlQXJyYXkoJGV2ZW50LmN1cnJlbnRUYXJnZXQuZmlsZXMpO1xuXG4gICAgICAgIGlmICh0aGlzLmhhc0FsbG93YWJsZU9wZXJhdGlvbnMpIHtcbiAgICAgICAgICAgIHRoaXMudXBsb2FkRmlsZXMoZmlsZXMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wZXJtaXNzaW9uRXZlbnQuZW1pdChuZXcgUGVybWlzc2lvbk1vZGVsKHsgdHlwZTogJ2NvbnRlbnQnLCBhY3Rpb246ICd1cGxvYWQnLCBwZXJtaXNzaW9uOiAnY3JlYXRlJyB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzZXQgdGhlIHZhbHVlIG9mIHRoZSBpbnB1dCBmaWxlXG4gICAgICAgICRldmVudC50YXJnZXQudmFsdWUgPSAnJztcbiAgICB9XG5cbiAgICBvbkNsaWNrVXBsb2FkQnV0dG9uKCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5maWxlKSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlcyA9IFt0aGlzLmZpbGVdO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5oYXNBbGxvd2FibGVPcGVyYXRpb25zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGxvYWRGaWxlcyhmaWxlcyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMucGVybWlzc2lvbkV2ZW50LmVtaXQobmV3IFBlcm1pc3Npb25Nb2RlbCh7IHR5cGU6ICdjb250ZW50JywgYWN0aW9uOiAndXBsb2FkJywgcGVybWlzc2lvbjogJ2NyZWF0ZScgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25EaXJlY3RvcnlBZGRlZCgkZXZlbnQ6IGFueSk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5oYXNBbGxvd2FibGVPcGVyYXRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCBmaWxlcyA9IEZpbGVVdGlscy50b0ZpbGVBcnJheSgkZXZlbnQuY3VycmVudFRhcmdldC5maWxlcyk7XG4gICAgICAgICAgICB0aGlzLnVwbG9hZEZpbGVzKGZpbGVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucGVybWlzc2lvbkV2ZW50LmVtaXQobmV3IFBlcm1pc3Npb25Nb2RlbCh7IHR5cGU6ICdjb250ZW50JywgYWN0aW9uOiAndXBsb2FkJywgcGVybWlzc2lvbjogJ2NyZWF0ZScgfSkpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHJlc2V0IHRoZSB2YWx1ZSBvZiB0aGUgaW5wdXQgZmlsZVxuICAgICAgICAkZXZlbnQudGFyZ2V0LnZhbHVlID0gJyc7XG4gICAgfVxuXG4gICAgY2hlY2tQZXJtaXNzaW9uKCkge1xuICAgICAgICBpZiAodGhpcy5yb290Rm9sZGVySWQpIHtcbiAgICAgICAgICAgIGNvbnN0IG9wdHM6IGFueSA9IHtcbiAgICAgICAgICAgICAgICBpbmNsdWRlU291cmNlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGluY2x1ZGU6IFsnYWxsb3dhYmxlT3BlcmF0aW9ucyddXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICB0aGlzLm5vZGVzQXBpU2VydmljZS5nZXROb2RlKHRoaXMucm9vdEZvbGRlcklkLCBvcHRzKS5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgICAgKHJlcykgPT4gdGhpcy5wZXJtaXNzaW9uVmFsdWUubmV4dCh0aGlzLm5vZGVIYXNQZXJtaXNzaW9uKHJlcywgQWxsb3dhYmxlT3BlcmF0aW9uc0VudW0uQ1JFQVRFKSksXG4gICAgICAgICAgICAgICAgKGVycm9yOiB7IGVycm9yOiBFcnJvciB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnJvcj8uZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdCh7IGVycm9yOiBlcnJvci5lcnJvci5tZXNzYWdlIH0gYXMgYW55KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3IuZW1pdCh7IGVycm9yOiAnRklMRV9VUExPQUQuQlVUVE9OLlBFUk1JU1NJT05fQ0hFQ0tfRVJST1InIH0gYXMgYW55KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBub2RlSGFzUGVybWlzc2lvbihub2RlOiBOb2RlLCBwZXJtaXNzaW9uOiBBbGxvd2FibGVPcGVyYXRpb25zRW51bSB8IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5jb250ZW50U2VydmljZS5oYXNBbGxvd2FibGVPcGVyYXRpb25zKG5vZGUsIHBlcm1pc3Npb24pO1xuICAgIH1cbn1cbiIsIjxmb3JtIGNsYXNzPVwiYWRmLXVwbG9hZC1idXR0b24tZmlsZS1jb250YWluZXJcIj5cbiAgICA8IS0tRmlsZXMgVXBsb2FkLS0+XG4gICAgPGRpdiAqbmdJZj1cIiF1cGxvYWRGb2xkZXJzXCI+XG5cbiAgICAgICAgPCEtLVNpbmdsZSBGaWxlcyBVcGxvYWQtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFtdWx0aXBsZUZpbGVzXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBjbGFzcz1cImFkZi11cGxvYWQtYnV0dG9uLWZpbGUtY29udGFpbmVyLXVwbG9hZC1zaW5nbGUtZmlsZVwiXG4gICAgICAgICAgICAgICAgaWQ9XCJ1cGxvYWQtc2luZ2xlLWZpbGVcIlxuICAgICAgICAgICAgICAgIGRhdGEtYXV0b21hdGlvbi1pZD1cInVwbG9hZC1zaW5nbGUtZmlsZVwiXG4gICAgICAgICAgICAgICAgW3R5cGVdPVwiZmlsZSA/ICdidXR0b24nIDogJ2ZpbGUnXCJcbiAgICAgICAgICAgICAgICBuYW1lPVwidXBsb2FkRmlsZXNcIlxuICAgICAgICAgICAgICAgIGFjY2VwdD1cInt7YWNjZXB0ZWRGaWxlc1R5cGV9fVwiXG4gICAgICAgICAgICAgICAgW2F0dHIuZGlzYWJsZWRdPVwiaXNCdXR0b25EaXNhYmxlZCgpXCJcbiAgICAgICAgICAgICAgICBbdGl0bGVdPVwidG9vbHRpcFwiXG4gICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJvbkZpbGVzQWRkZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQ2xpY2tVcGxvYWRCdXR0b24oKVwiLz5cbiAgICAgICAgICAgIDxsYWJlbCBmb3I9XCJ1cGxvYWQtc2luZ2xlLWZpbGVcIiBjbGFzcz1cImFkZi11cGxvYWQtYnV0dG9uLWxhYmVsXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiYWRmLXVwbG9hZC1idXR0b24taWNvblwiPmZpbGVfdXBsb2FkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgICA8c3BhbiBpZD1cInVwbG9hZC1zaW5nbGUtZmlsZS1sYWJlbFwiICpuZ0lmPVwiIXN0YXRpY1RpdGxlXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7ICdGSUxFX1VQTE9BRC5CVVRUT04uVVBMT0FEX0ZJTEUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxzcGFuIGlkPVwidXBsb2FkLXNpbmdsZS1maWxlLWxhYmVsLXN0YXRpY1wiICpuZ0lmPVwic3RhdGljVGl0bGVcIj5cbiAgICAgICAgICAgICAgICAgICAge3sgc3RhdGljVGl0bGUgfX08L3NwYW4+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tTXVsdGlwbGUgRmlsZXMgVXBsb2FkLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJtdWx0aXBsZUZpbGVzXCI+XG4gICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBpZD1cInVwbG9hZC1tdWx0aXBsZS1maWxlc1wiXG4gICAgICAgICAgICAgICAgZGF0YS1hdXRvbWF0aW9uLWlkPVwidXBsb2FkLW11bHRpcGxlLWZpbGVzXCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiZmlsZVwiXG4gICAgICAgICAgICAgICAgbmFtZT1cInVwbG9hZEZpbGVzXCJcbiAgICAgICAgICAgICAgICBtdWx0aXBsZT1cIm11bHRpcGxlXCJcbiAgICAgICAgICAgICAgICBhY2NlcHQ9XCJ7e2FjY2VwdGVkRmlsZXNUeXBlfX1cIlxuICAgICAgICAgICAgICAgIFthdHRyLmRpc2FibGVkXT1cImlzQnV0dG9uRGlzYWJsZWQoKVwiXG4gICAgICAgICAgICAgICAgW3RpdGxlXT1cInRvb2x0aXBcIlxuICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwib25GaWxlc0FkZGVkKCRldmVudClcIi8+XG4gICAgICAgICAgICA8bGFiZWwgZm9yPVwidXBsb2FkLW11bHRpcGxlLWZpbGVzXCIgY2xhc3M9XCJhZGYtdXBsb2FkLWJ1dHRvbi1sYWJlbFwiPlxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImFkZi11cGxvYWQtYnV0dG9uLWljb25cIj5maWxlX3VwbG9hZDwvbWF0LWljb24+XG4gICAgICAgICAgICAgICAgPHNwYW4gaWQ9XCJ1cGxvYWQtbXVsdGlwbGUtZmlsZS1sYWJlbFwiICpuZ0lmPVwiIXN0YXRpY1RpdGxlXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7ICdGSUxFX1VQTE9BRC5CVVRUT04uVVBMT0FEX0ZJTEUnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDxzcGFuIGlkPVwidXBsb2FkLW11bHRpcGxlLWZpbGUtbGFiZWwtc3RhdGljXCIgKm5nSWY9XCJzdGF0aWNUaXRsZVwiPlxuICAgICAgICAgICAgICAgICAgICB7eyBzdGF0aWNUaXRsZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvZGl2PlxuXG4gICAgPCEtLUZvbGRlcnMgVXBsb2FkLS0+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInVwbG9hZEZvbGRlcnNcIj5cbiAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBpZD1cInVwbG9hZEZvbGRlclwiXG4gICAgICAgICAgICBkYXRhLWF1dG9tYXRpb24taWQ9XCJ1cGxvYWRGb2xkZXJcIlxuICAgICAgICAgICAgdHlwZT1cImZpbGVcIlxuICAgICAgICAgICAgbmFtZT1cInVwbG9hZEZpbGVzXCJcbiAgICAgICAgICAgIG11bHRpcGxlPVwibXVsdGlwbGVcIlxuICAgICAgICAgICAgYWNjZXB0PVwie3thY2NlcHRlZEZpbGVzVHlwZX19XCJcbiAgICAgICAgICAgIHdlYmtpdGRpcmVjdG9yeSBkaXJlY3RvcnlcbiAgICAgICAgICAgIFthdHRyLmRpc2FibGVkXT1cImlzQnV0dG9uRGlzYWJsZWQoKVwiXG4gICAgICAgICAgICBbdGl0bGVdPVwidG9vbHRpcFwiXG4gICAgICAgICAgICAoY2hhbmdlKT1cIm9uRGlyZWN0b3J5QWRkZWQoJGV2ZW50KVwiLz5cbiAgICAgICAgPGxhYmVsIGZvcj1cInVwbG9hZEZvbGRlclwiIGRhdGEtYXV0b21hdGlvbi1pZD1cInVwbG9hZEZvbGRlclwiIGNsYXNzPVwiYWRmLXVwbG9hZC1idXR0b24tbGFiZWxcIj5cbiAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImFkZi11cGxvYWQtYnV0dG9uLWljb25cIj5maWxlX3VwbG9hZDwvbWF0LWljb24+XG4gICAgICAgICAgICA8c3BhbiBpZD1cInVwbG9hZEZvbGRlci1sYWJlbFwiICpuZ0lmPVwiIXN0YXRpY1RpdGxlXCI+XG4gICAgICAgICAgICAgICAge3sgJ0ZJTEVfVVBMT0FELkJVVFRPTi5VUExPQURfRk9MREVSJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgIDxzcGFuIGlkPVwidXBsb2FkRm9sZGVyLWxhYmVsLXN0YXRpY1wiICpuZ0lmPVwic3RhdGljVGl0bGVcIj5cbiAgICAgICAgICAgICAgICB7eyBzdGF0aWNUaXRsZSB9fTwvc3Bhbj5cbiAgICAgICAgPC9sYWJlbD5cbiAgICA8L25nLWNvbnRhaW5lcj5cbjwvZm9ybT5cbiJdfQ==