UNPKG

ngx-surveys

Version:
151 lines 33.1 kB
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { Observable } from 'rxjs'; import { SurveyErrorStateMatcher } from '../index'; import { FormItem, SurveyFile } from '../form-item'; import * as _ from 'lodash'; import * as i0 from "@angular/core"; import * as i1 from "../../ngx-survey.service"; import * as i2 from "@angular/common"; import * as i3 from "@angular/material/button"; import * as i4 from "@angular/material/form-field"; import * as i5 from "ngx-file-drop"; import * as i6 from "./file-list-item-image/file-list-item-image.component"; import * as i7 from "./file-list-item-video/file-list-item-video.component"; //import { map } from 'rxjs/operators'; export class FormItemFile extends FormItem { } export class FormItemFileComponent { constructor(service, zone) { this.service = service; this.zone = zone; this.editable = true; this.changes = new EventEmitter(); this.matcher = new SurveyErrorStateMatcher(); this.fileObjects = []; this.allowDelete = true; this.uploadedFilesNumber = 0; this.uploadFilesNumber = 0; this.acceptTypes = { image: '.png, .jpg, .jpeg', video: '.mp4, .mov', file: '' }; } ngOnInit() { if (this.item.value) { this.files = this.item.value.map(f => { const obj = _.extend(new SurveyFile(), f); return obj; }); } this.matcher.item = this.item; this.accept = this.acceptTypes[this.item.fileType]; } ngOnChanges() { this.matcher.item = this.item; } checkRequired(placeholder) { if (placeholder === 'Required') { return true; } } onValueChanges(item) { this.changes.emit(item); } removeFile(file) { this.files = _.without(this.files, file); //this.fileObjects=_.without(this.fileObjects, this.fileObjects.find(f=>f.id===file.id)); this.item.value = (this.item.value || []).filter(f => f.url !== file.url); this.changes.emit(this.item); } fileOver(fileIsOver) { console.log('fileIsOver', fileIsOver); this.fileIsOver = fileIsOver; } onFileDrop(files) { const surveyFiles = []; let droppedFiles = files.filter(f => f.fileEntry.isFile && (!this.accept || this.accept.split(',').find(ext => f.fileEntry.name.indexOf(ext.trim()) > 0))); if (!this.item.multiple && droppedFiles.length > 1) { droppedFiles = [droppedFiles[0]]; } console.log('onFileDrop', files, this.files, droppedFiles); droppedFiles.forEach(droppedFile => { const fileEntry = droppedFile.fileEntry; fileEntry.file((file) => { const surveyFile = new SurveyFile(); surveyFile.size = file.size; surveyFile.name = file.name; surveyFile.mime = file.type; surveyFile.file = file; if (file.type.indexOf('image/') === 0) { if (FileReader) { var fr = new FileReader(); fr.onload = function () { surveyFile.src = fr.result; }; fr.readAsDataURL(file); } } surveyFiles.push(surveyFile); if (surveyFiles.length === droppedFiles.length) { this.uploadFiles(surveyFiles); } // Here you can access the real file console.log(droppedFile.relativePath, file); }); }); this.fileIsOver = false; } uploadFiles(files) { console.log(files); if (!files.length) { return; } this.item.busy = true; files.forEach(file => { file.uploading = true; file.progressSubject = new Observable(observer => { file.progressObserver = observer; }); file.progressSubject.subscribe(data => { this.zone.run(() => { file.progressValue = data; //console.log(file); if (file.url) { this.item.value = this.files.filter(f => f.url).map(f => { const obj = new SurveyFile; obj.url = f.url; obj.name = f.name; obj.mime = f.mime; obj.size = f.size; return obj; }); console.log(this.item); this.item.busy = !!files.find(f => f.uploading); this.changes.emit(this.item); } }); }, err => { this.item.busy = !!files.find(f => f.uploading); }); }); this.service.onFilesSelected.next(files); this.files = _.union(this.files, files); this.isFilesUploading = true; this.uploadFilesNumber = files.length; this.uploadedFilesNumber = 1; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FormItemFileComponent, deps: [{ token: i1.NgxSurveyService }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: FormItemFileComponent, selector: "ammo-form-item-file", inputs: { item: "item", editable: "editable" }, outputs: { changes: "changes" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"form-group\">\n <div class=\"col-xs-12 files-set\" [ngClass]=\"{'files-upload-editable':editable}\">\n <div *ngIf=\"item.label\" class=\"files-set-title label\" [ngClass]=\"{'has-error':item.errors && item.errors.length}\">{{item.label}} <span *ngIf=\"item.required\" class=\"required-asterix\">*</span></div>\n <div [ngClass]=\"'files-list-'+item.fileType\">\n <div class=\"file-item\" *ngFor=\"let file of files\">\n <ammo-file-list-item-image *ngIf=\"item.fileType!=='video'\"\n [type]=\"item.fileType\"\n [file]=\"file\"\n [allowDelete]=\"editable\"\n (onDelete)=\"removeFile($event)\"\n >\n </ammo-file-list-item-image>\n <ammo-file-list-item-video *ngIf=\"item.fileType==='video'\"\n [file]=\"file\"\n [allowDelete]=\"editable\"\n (onDelete)=\"removeFile($event)\"\n >\n </ammo-file-list-item-video>\n </div>\n </div>\n <div *ngIf=\"!editable && !files?.length\" class=\"no-files-message\">\n No {{item.fileType==='video' ? 'Videos' : 'Photos'}} Submitted\n </div>\n <ngx-file-drop *ngIf=\"(item.multiple || (!item.multiple && (!files || files.length<1)))\"\n dropZoneLabel=\"Drop files here\"\n (onFileDrop)=\"onFileDrop($event)\"\n (onFileOver)=\"fileOver(true)\"\n (onFileLeave)=\"fileOver(false)\"\n [multiple]=\"item.multiple\"\n [accept]=\"accept\"\n [directory]=\"false\"\n [disabled]=\"!editable\"\n [ngClass]=\"{'file-is-over':fileIsOver}\"\n >\n <ng-template ngx-file-drop-content-tmp let-openFileSelector=\"openFileSelector\">\n <span *ngIf=\"!fileIsOver && editable\">\n <ng-container *ngIf=\"item.areaLabel\"{{item.areaLabel}}></ng-container>\n <ng-container *ngIf=\"!item.areaLabel\"> Drag & Drop Files here <br />or </ng-container>\n </span>\n <span *ngIf=\"fileIsOver\">Drop files here</span>\n <br/>\n <button *ngIf=\"!fileIsOver\" mat-raised-button [disabled]=\"!editable\" color=\"primary\" type=\"button\" (click)=\"openFileSelector()\">{{item.buttonLabel || 'Browse Files'}}</button>\n </ng-template>\n </ngx-file-drop>\n <mat-error *ngIf=\"item.errors && item.errors.length\">\n <div *ngFor=\"let error of item.errors\">{{error.message}}</div>\n </mat-error>\n <mat-hint align=\"start\" *ngIf=\"!(item.errors && item.errors.length)\"><strong>{{item.hint}}</strong> </mat-hint>\n </div>\n</div>\n\n\n", styles: [":host{margin-top:10px;display:block}:host ::ng-deep .ngx-file-drop__content{display:block!important;text-align:center;padding-top:8px}:host ::ng-deep .ngx-file-drop__content .mat-raised-button{margin-top:5px}:host ::ng-deep .file-is-over .ngx-file-drop__content{display:flex!important;padding-top:0}.files-list-image,.files-list-file{display:flex;flex-flow:wrap}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: i4.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i4.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i5.NgxFileDropComponent, selector: "ngx-file-drop", inputs: ["accept", "directory", "multiple", "dropZoneLabel", "dropZoneClassName", "useDragEnter", "contentClassName", "showBrowseBtn", "browseBtnClassName", "browseBtnLabel", "disabled"], outputs: ["onFileDrop", "onFileOver", "onFileLeave"] }, { kind: "directive", type: i5.NgxFileDropContentTemplateDirective, selector: "[ngx-file-drop-content-tmp]" }, { kind: "component", type: i6.FileListItemImageComponent, selector: "ammo-file-list-item-image", inputs: ["file", "allowDelete", "type"], outputs: ["onDelete"] }, { kind: "component", type: i7.FileListItemVideoComponent, selector: "ammo-file-list-item-video", inputs: ["file", "allowDelete"], outputs: ["onDelete"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: FormItemFileComponent, decorators: [{ type: Component, args: [{ selector: 'ammo-form-item-file', template: "<div class=\"form-group\">\n <div class=\"col-xs-12 files-set\" [ngClass]=\"{'files-upload-editable':editable}\">\n <div *ngIf=\"item.label\" class=\"files-set-title label\" [ngClass]=\"{'has-error':item.errors && item.errors.length}\">{{item.label}} <span *ngIf=\"item.required\" class=\"required-asterix\">*</span></div>\n <div [ngClass]=\"'files-list-'+item.fileType\">\n <div class=\"file-item\" *ngFor=\"let file of files\">\n <ammo-file-list-item-image *ngIf=\"item.fileType!=='video'\"\n [type]=\"item.fileType\"\n [file]=\"file\"\n [allowDelete]=\"editable\"\n (onDelete)=\"removeFile($event)\"\n >\n </ammo-file-list-item-image>\n <ammo-file-list-item-video *ngIf=\"item.fileType==='video'\"\n [file]=\"file\"\n [allowDelete]=\"editable\"\n (onDelete)=\"removeFile($event)\"\n >\n </ammo-file-list-item-video>\n </div>\n </div>\n <div *ngIf=\"!editable && !files?.length\" class=\"no-files-message\">\n No {{item.fileType==='video' ? 'Videos' : 'Photos'}} Submitted\n </div>\n <ngx-file-drop *ngIf=\"(item.multiple || (!item.multiple && (!files || files.length<1)))\"\n dropZoneLabel=\"Drop files here\"\n (onFileDrop)=\"onFileDrop($event)\"\n (onFileOver)=\"fileOver(true)\"\n (onFileLeave)=\"fileOver(false)\"\n [multiple]=\"item.multiple\"\n [accept]=\"accept\"\n [directory]=\"false\"\n [disabled]=\"!editable\"\n [ngClass]=\"{'file-is-over':fileIsOver}\"\n >\n <ng-template ngx-file-drop-content-tmp let-openFileSelector=\"openFileSelector\">\n <span *ngIf=\"!fileIsOver && editable\">\n <ng-container *ngIf=\"item.areaLabel\"{{item.areaLabel}}></ng-container>\n <ng-container *ngIf=\"!item.areaLabel\"> Drag & Drop Files here <br />or </ng-container>\n </span>\n <span *ngIf=\"fileIsOver\">Drop files here</span>\n <br/>\n <button *ngIf=\"!fileIsOver\" mat-raised-button [disabled]=\"!editable\" color=\"primary\" type=\"button\" (click)=\"openFileSelector()\">{{item.buttonLabel || 'Browse Files'}}</button>\n </ng-template>\n </ngx-file-drop>\n <mat-error *ngIf=\"item.errors && item.errors.length\">\n <div *ngFor=\"let error of item.errors\">{{error.message}}</div>\n </mat-error>\n <mat-hint align=\"start\" *ngIf=\"!(item.errors && item.errors.length)\"><strong>{{item.hint}}</strong> </mat-hint>\n </div>\n</div>\n\n\n", styles: [":host{margin-top:10px;display:block}:host ::ng-deep .ngx-file-drop__content{display:block!important;text-align:center;padding-top:8px}:host ::ng-deep .ngx-file-drop__content .mat-raised-button{margin-top:5px}:host ::ng-deep .file-is-over .ngx-file-drop__content{display:flex!important;padding-top:0}.files-list-image,.files-list-file{display:flex;flex-flow:wrap}\n"] }] }], ctorParameters: () => [{ type: i1.NgxSurveyService }, { type: i0.NgZone }], propDecorators: { item: [{ type: Input }], editable: [{ type: Input }], changes: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS1pdGVtLWZpbGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1cnZleXMvc3JjL2xpYi9mb3JtLWl0ZW0vZm9ybS1pdGVtLWZpbGUvZm9ybS1pdGVtLWZpbGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXN1cnZleXMvc3JjL2xpYi9mb3JtLWl0ZW0vZm9ybS1pdGVtLWZpbGUvZm9ybS1pdGVtLWZpbGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBVSxNQUFNLGVBQWUsQ0FBQztBQUN2RixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2xDLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUNuRCxPQUFPLEVBQUUsUUFBUSxFQUFrQixVQUFVLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDcEUsT0FBTyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUM7Ozs7Ozs7OztBQUc1Qix1Q0FBdUM7QUFFdkMsTUFBTSxPQUFPLFlBQWEsU0FBUSxRQUFRO0NBTXpDO0FBT0QsTUFBTSxPQUFPLHFCQUFxQjtJQXdCOUIsWUFDWSxPQUF5QixFQUN6QixJQUFZO1FBRFosWUFBTyxHQUFQLE9BQU8sQ0FBa0I7UUFDekIsU0FBSSxHQUFKLElBQUksQ0FBUTtRQXZCZixhQUFRLEdBQVUsSUFBSSxDQUFDO1FBQ3RCLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBZ0IsQ0FBQztRQUNyRCxZQUFPLEdBQUcsSUFBSSx1QkFBdUIsRUFBRSxDQUFDO1FBRWpDLGdCQUFXLEdBQVEsRUFBRSxDQUFDO1FBTXRCLGdCQUFXLEdBQVUsSUFBSSxDQUFDO1FBQzFCLHdCQUFtQixHQUFTLENBQUMsQ0FBQztRQUM5Qixz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QjtrQkFMakMsU0FBUzsrQkFDRSxxQkFBcUI7MEdBTXBCLElBQUk7c0JBQVosS0FBSztnQkFDRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNJLE9BQU87c0JBQWhCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJcbmltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE5nWm9uZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgU3VydmV5RXJyb3JTdGF0ZU1hdGNoZXIgfSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBGb3JtSXRlbSwgRm9ybUl0ZW1XaWRnZXQsIFN1cnZleUZpbGUgfSBmcm9tICcuLi9mb3JtLWl0ZW0nO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHsgTmd4RmlsZURyb3BFbnRyeSB9IGZyb20gJ25neC1maWxlLWRyb3AnO1xuaW1wb3J0IHsgTmd4U3VydmV5U2VydmljZSB9IGZyb20gJy4uLy4uL25neC1zdXJ2ZXkuc2VydmljZSc7XG4vL2ltcG9ydCB7IG1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuZXhwb3J0IGNsYXNzIEZvcm1JdGVtRmlsZSBleHRlbmRzIEZvcm1JdGVtIHtcbiAgICBmaWxlVHlwZTogc3RyaW5nO1xuICAgIG11bHRpcGxlOiBib29sZWFuO1xuICAgIHZhbHVlOiBTdXJ2ZXlGaWxlW107XG4gICAgYXJlYUxhYmVsOiBzdHJpbmc7XG4gICAgYnV0dG9uTGFiZWw6IHN0cmluZztcbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYW1tby1mb3JtLWl0ZW0tZmlsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9mb3JtLWl0ZW0tZmlsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2Zvcm0taXRlbS1maWxlLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgRm9ybUl0ZW1GaWxlQ29tcG9uZW50IGltcGxlbWVudHMgRm9ybUl0ZW1XaWRnZXQsIE9uSW5pdCB7XG5cbiAgICBASW5wdXQoKSBpdGVtOiBGb3JtSXRlbUZpbGU7XG4gICAgQElucHV0KCkgZWRpdGFibGU6IGJvb2xlYW49dHJ1ZTtcbiAgICBAT3V0cHV0KCkgY2hhbmdlcyA9IG5ldyBFdmVudEVtaXR0ZXI8Rm9ybUl0ZW1GaWxlPigpO1xuICAgIG1hdGNoZXIgPSBuZXcgU3VydmV5RXJyb3JTdGF0ZU1hdGNoZXIoKTtcblxuICAgIHB1YmxpYyBmaWxlT2JqZWN0czogYW55W109W107XG5cbiAgICBwdWJsaWMgZmlsZXM6IFN1cnZleUZpbGVbXTtcblxuICAgIHB1YmxpYyBmaWxlSXNPdmVyOiBib29sZWFuO1xuICAgIHB1YmxpYyBpc0ZpbGVzVXBsb2FkaW5nOiBib29sZWFuO1xuICAgIHB1YmxpYyBhbGxvd0RlbGV0ZTogYm9vbGVhbj10cnVlO1xuICAgIHB1YmxpYyB1cGxvYWRlZEZpbGVzTnVtYmVyOiBudW1iZXI9MDtcbiAgICBwdWJsaWMgdXBsb2FkRmlsZXNOdW1iZXI6IG51bWJlcj0wO1xuICAgIHB1YmxpYyBhY2NlcHQ6c3RyaW5nO1xuICAgIHByaXZhdGUgYWNjZXB0VHlwZXM6IGFueT17XG4gICAgICAgIGltYWdlOiAnLnBuZywgLmpwZywgLmpwZWcnLFxuICAgICAgICB2aWRlbzogJy5tcDQsIC5tb3YnLFxuICAgICAgICBmaWxlOiAnJ1xuICAgIH1cblxuXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIHByaXZhdGUgc2VydmljZTogTmd4U3VydmV5U2VydmljZSxcbiAgICAgICAgcHJpdmF0ZSB6b25lOiBOZ1pvbmUsXG4gICAgKSB7IH1cblxuXG4gICAgbmdPbkluaXQoKSB7XG4gICAgICAgIGlmICh0aGlzLml0ZW0udmFsdWUpe1xuICAgICAgICAgICAgdGhpcy5maWxlcz10aGlzLml0ZW0udmFsdWUubWFwKGY9PntcbiAgICAgICAgICAgICAgICBjb25zdCBvYmo9Xy5leHRlbmQobmV3IFN1cnZleUZpbGUoKSwgZik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubWF0Y2hlci5pdGVtPXRoaXMuaXRlbTtcbiAgICAgICAgdGhpcy5hY2NlcHQ9dGhpcy5hY2NlcHRUeXBlc1t0aGlzLml0ZW0uZmlsZVR5cGVdO1xuICAgIH1cblxuICAgIG5nT25DaGFuZ2VzKCkge1xuICAgICAgICB0aGlzLm1hdGNoZXIuaXRlbT10aGlzLml0ZW07XG4gICAgfVxuXG4gICAgY2hlY2tSZXF1aXJlZChwbGFjZWhvbGRlcikge1xuICAgICAgICBpZiAocGxhY2Vob2xkZXIgPT09ICdSZXF1aXJlZCcpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgb25WYWx1ZUNoYW5nZXMoaXRlbSkge1xuICAgICAgICB0aGlzLmNoYW5nZXMuZW1pdChpdGVtKTtcbiAgICB9XG5cbiAgICByZW1vdmVGaWxlKGZpbGU6U3VydmV5RmlsZSl7XG4gICAgICAgIHRoaXMuZmlsZXM9Xy53aXRob3V0KHRoaXMuZmlsZXMsIGZpbGUpO1xuICAgICAgICAvL3RoaXMuZmlsZU9iamVjdHM9Xy53aXRob3V0KHRoaXMuZmlsZU9iamVjdHMsIHRoaXMuZmlsZU9iamVjdHMuZmluZChmPT5mLmlkPT09ZmlsZS5pZCkpO1xuICAgICAgICB0aGlzLml0ZW0udmFsdWU9KHRoaXMuaXRlbS52YWx1ZSB8fCBbXSkuZmlsdGVyKGY9PmYudXJsIT09ZmlsZS51cmwpO1xuICAgICAgICB0aGlzLmNoYW5nZXMuZW1pdCh0aGlzLml0ZW0pO1xuICAgIH1cblxuICAgIHB1YmxpYyBmaWxlT3ZlcihmaWxlSXNPdmVyOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdmaWxlSXNPdmVyJywgZmlsZUlzT3Zlcik7XG4gICAgICAgIHRoaXMuZmlsZUlzT3ZlciA9IGZpbGVJc092ZXI7XG4gICAgfVxuXG4gICAgcHVibGljIG9uRmlsZURyb3AoZmlsZXM6IE5neEZpbGVEcm9wRW50cnlbXSk6IHZvaWQge1xuXG4gICAgICAgIGNvbnN0IHN1cnZleUZpbGVzOlN1cnZleUZpbGVbXT1bXTtcblxuICAgICAgICBsZXQgZHJvcHBlZEZpbGVzPWZpbGVzLmZpbHRlcihmPT5mLmZpbGVFbnRyeS5pc0ZpbGUgJiYgKCF0aGlzLmFjY2VwdCB8fCB0aGlzLmFjY2VwdC5zcGxpdCgnLCcpLmZpbmQoZXh0PT5mLmZpbGVFbnRyeS5uYW1lLmluZGV4T2YoZXh0LnRyaW0oKSk+MCkpKTtcbiAgICAgICAgaWYgKCF0aGlzLml0ZW0ubXVsdGlwbGUgJiYgZHJvcHBlZEZpbGVzLmxlbmd0aD4xKXtcbiAgICAgICAgICAgIGRyb3BwZWRGaWxlcz1bZHJvcHBlZEZpbGVzWzBdXTtcbiAgICAgICAgfVxuICAgICAgICBjb25zb2xlLmxvZygnb25GaWxlRHJvcCcsIGZpbGVzLCB0aGlzLmZpbGVzLCBkcm9wcGVkRmlsZXMpO1xuICAgICAgICBkcm9wcGVkRmlsZXMuZm9yRWFjaChkcm9wcGVkRmlsZT0+e1xuICAgICAgICAgICAgY29uc3QgZmlsZUVudHJ5ID0gZHJvcHBlZEZpbGUuZmlsZUVudHJ5IGFzIEZpbGVTeXN0ZW1GaWxlRW50cnk7XG4gICAgICAgICAgICBmaWxlRW50cnkuZmlsZSgoZmlsZTogRmlsZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHN1cnZleUZpbGU9bmV3IFN1cnZleUZpbGUoKTtcbiAgICAgICAgICAgICAgICBzdXJ2ZXlGaWxlLnNpemU9ZmlsZS5zaXplO1xuICAgICAgICAgICAgICAgIHN1cnZleUZpbGUubmFtZT1maWxlLm5hbWU7XG4gICAgICAgICAgICAgICAgc3VydmV5RmlsZS5taW1lPWZpbGUudHlwZTtcbiAgICAgICAgICAgICAgICBzdXJ2ZXlGaWxlLmZpbGU9ZmlsZTtcbiAgICAgICAgICAgICAgICBpZiAoZmlsZS50eXBlLmluZGV4T2YoJ2ltYWdlLycpPT09MCl7XG4gICAgICAgICAgICAgICAgICAgIGlmIChGaWxlUmVhZGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgZnIgPSBuZXcgRmlsZVJlYWRlcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZnIub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN1cnZleUZpbGUuc3JjPWZyLnJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGZyLnJlYWRBc0RhdGFVUkwoZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3VydmV5RmlsZXMucHVzaChzdXJ2ZXlGaWxlKTtcbiAgICAgICAgICAgICAgICBpZiAoc3VydmV5RmlsZXMubGVuZ3RoPT09ZHJvcHBlZEZpbGVzLmxlbmd0aCl7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudXBsb2FkRmlsZXMoc3VydmV5RmlsZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBIZXJlIHlvdSBjYW4gYWNjZXNzIHRoZSByZWFsIGZpbGVcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhkcm9wcGVkRmlsZS5yZWxhdGl2ZVBhdGgsIGZpbGUpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pXG4gICAgICAgIHRoaXMuZmlsZUlzT3Zlcj1mYWxzZTtcblxuICAgIH1cblxuICAgIHVwbG9hZEZpbGVzKGZpbGVzOiBTdXJ2ZXlGaWxlW10pIHtcbiAgICAgICAgY29uc29sZS5sb2coZmlsZXMpO1xuICAgICAgICBpZighZmlsZXMubGVuZ3RoKXtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLml0ZW0uYnVzeT10cnVlO1xuICAgICAgICBmaWxlcy5mb3JFYWNoKGZpbGU9PntcbiAgICAgICAgICAgIGZpbGUudXBsb2FkaW5nPXRydWU7XG4gICAgICAgICAgICBmaWxlLnByb2dyZXNzU3ViamVjdCA9IG5ldyBPYnNlcnZhYmxlKG9ic2VydmVyID0+IHtcbiAgICAgICAgICAgICAgICBmaWxlLnByb2dyZXNzT2JzZXJ2ZXIgPSBvYnNlcnZlclxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBmaWxlLnByb2dyZXNzU3ViamVjdC5zdWJzY3JpYmUoXG4gICAgICAgICAgICAgIGRhdGEgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oKCk9PntcbiAgICAgICAgICAgICAgICAgICAgZmlsZS5wcm9ncmVzc1ZhbHVlPWRhdGE7XG4gICAgICAgICAgICAgICAgICAgIC8vY29uc29sZS5sb2coZmlsZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWxlLnVybCl7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLml0ZW0udmFsdWU9dGhpcy5maWxlcy5maWx0ZXIoZj0+Zi51cmwpLm1hcChmPT57XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgb2JqPW5ldyBTdXJ2ZXlGaWxlO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iai51cmw9Zi51cmw7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JqLm5hbWU9Zi5uYW1lO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iai5taW1lPWYubWltZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvYmouc2l6ZT1mLnNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9iajtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2codGhpcy5pdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaXRlbS5idXN5PSEhZmlsZXMuZmluZChmPT5mLnVwbG9hZGluZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNoYW5nZXMuZW1pdCh0aGlzLml0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgZXJyPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuaXRlbS5idXN5PSEhZmlsZXMuZmluZChmPT5mLnVwbG9hZGluZyk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgICAgIHRoaXMuc2VydmljZS5vbkZpbGVzU2VsZWN0ZWQubmV4dChmaWxlcyk7XG4gICAgICAgIHRoaXMuZmlsZXM9Xy51bmlvbih0aGlzLmZpbGVzLCBmaWxlcyk7XG5cbiAgICAgICAgdGhpcy5pc0ZpbGVzVXBsb2FkaW5nID0gdHJ1ZTtcblxuICAgICAgICB0aGlzLnVwbG9hZEZpbGVzTnVtYmVyPWZpbGVzLmxlbmd0aDtcbiAgICAgICAgdGhpcy51cGxvYWRlZEZpbGVzTnVtYmVyPTE7XG4gICAgfVxufVxuIiwiPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY29sLXhzLTEyIGZpbGVzLXNldFwiIFtuZ0NsYXNzXT1cInsnZmlsZXMtdXBsb2FkLWVkaXRhYmxlJzplZGl0YWJsZX1cIj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIml0ZW0ubGFiZWxcIiBjbGFzcz1cImZpbGVzLXNldC10aXRsZSBsYWJlbFwiIFtuZ0NsYXNzXT1cInsnaGFzLWVycm9yJzppdGVtLmVycm9ycyAmJiBpdGVtLmVycm9ycy5sZW5ndGh9XCI+e3tpdGVtLmxhYmVsfX0gPHNwYW4gKm5nSWY9XCJpdGVtLnJlcXVpcmVkXCIgY2xhc3M9XCJyZXF1aXJlZC1hc3Rlcml4XCI+Kjwvc3Bhbj48L2Rpdj5cbiAgICAgICAgPGRpdiBbbmdDbGFzc109XCInZmlsZXMtbGlzdC0nK2l0ZW0uZmlsZVR5cGVcIj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWxlLWl0ZW1cIiAqbmdGb3I9XCJsZXQgZmlsZSBvZiBmaWxlc1wiPlxuICAgICAgICAgICAgICAgIDxhbW1vLWZpbGUtbGlzdC1pdGVtLWltYWdlICpuZ0lmPVwiaXRlbS5maWxlVHlwZSE9PSd2aWRlbydcIlxuICAgICAgICAgICAgICAgICAgICBbdHlwZV09XCJpdGVtLmZpbGVUeXBlXCJcbiAgICAgICAgICAgICAgICAgICAgW2ZpbGVdPVwiZmlsZVwiXG4gICAgICAgICAgICAgICAgICAgIFthbGxvd0RlbGV0ZV09XCJlZGl0YWJsZVwiXG4gICAgICAgICAgICAgICAgICAgIChvbkRlbGV0ZSk9XCJyZW1vdmVGaWxlKCRldmVudClcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8L2FtbW8tZmlsZS1saXN0LWl0ZW0taW1hZ2U+XG4gICAgICAgICAgICAgICAgPGFtbW8tZmlsZS1saXN0LWl0ZW0tdmlkZW8gKm5nSWY9XCJpdGVtLmZpbGVUeXBlPT09J3ZpZGVvJ1wiXG4gICAgICAgICAgICAgICAgICAgIFtmaWxlXT1cImZpbGVcIlxuICAgICAgICAgICAgICAgICAgICBbYWxsb3dEZWxldGVdPVwiZWRpdGFibGVcIlxuICAgICAgICAgICAgICAgICAgICAob25EZWxldGUpPVwicmVtb3ZlRmlsZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPC9hbW1vLWZpbGUtbGlzdC1pdGVtLXZpZGVvPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiIWVkaXRhYmxlICYmICFmaWxlcz8ubGVuZ3RoXCIgY2xhc3M9XCJuby1maWxlcy1tZXNzYWdlXCI+XG4gICAgICAgICAgICBObyB7e2l0ZW0uZmlsZVR5cGU9PT0ndmlkZW8nID8gJ1ZpZGVvcycgOiAnUGhvdG9zJ319IFN1Ym1pdHRlZFxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPG5neC1maWxlLWRyb3AgKm5nSWY9XCIoaXRlbS5tdWx0aXBsZSB8fCAoIWl0ZW0ubXVsdGlwbGUgJiYgKCFmaWxlcyB8fCBmaWxlcy5sZW5ndGg8MSkpKVwiXG4gICAgICAgICAgICBkcm9wWm9uZUxhYmVsPVwiRHJvcCBmaWxlcyBoZXJlXCJcbiAgICAgICAgICAgIChvbkZpbGVEcm9wKT1cIm9uRmlsZURyb3AoJGV2ZW50KVwiXG4gICAgICAgICAgICAob25GaWxlT3Zlcik9XCJmaWxlT3Zlcih0cnVlKVwiXG4gICAgICAgICAgICAob25GaWxlTGVhdmUpPVwiZmlsZU92ZXIoZmFsc2UpXCJcbiAgICAgICAgICAgIFttdWx0aXBsZV09XCJpdGVtLm11bHRpcGxlXCJcbiAgICAgICAgICAgIFthY2NlcHRdPVwiYWNjZXB0XCJcbiAgICAgICAgICAgIFtkaXJlY3RvcnldPVwiZmFsc2VcIlxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFlZGl0YWJsZVwiXG4gICAgICAgICAgICBbbmdDbGFzc109XCJ7J2ZpbGUtaXMtb3Zlcic6ZmlsZUlzT3Zlcn1cIlxuICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG5nLXRlbXBsYXRlIG5neC1maWxlLWRyb3AtY29udGVudC10bXAgbGV0LW9wZW5GaWxlU2VsZWN0b3I9XCJvcGVuRmlsZVNlbGVjdG9yXCI+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiIWZpbGVJc092ZXIgJiYgZWRpdGFibGVcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpdGVtLmFyZWFMYWJlbFwie3tpdGVtLmFyZWFMYWJlbH19PjwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpdGVtLmFyZWFMYWJlbFwiPiBEcmFnICYgRHJvcCBGaWxlcyBoZXJlIDxiciAvPm9yIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuICpuZ0lmPVwiZmlsZUlzT3ZlclwiPkRyb3AgZmlsZXMgaGVyZTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPGJyLz5cbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiAgKm5nSWY9XCIhZmlsZUlzT3ZlclwiIG1hdC1yYWlzZWQtYnV0dG9uIFtkaXNhYmxlZF09XCIhZWRpdGFibGVcIiBjb2xvcj1cInByaW1hcnlcIiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cIm9wZW5GaWxlU2VsZWN0b3IoKVwiPnt7aXRlbS5idXR0b25MYWJlbCB8fCAnQnJvd3NlIEZpbGVzJ319PC9idXR0b24+XG4gICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPC9uZ3gtZmlsZS1kcm9wPlxuICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiaXRlbS5lcnJvcnMgJiYgaXRlbS5lcnJvcnMubGVuZ3RoXCI+XG4gICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZXJyb3Igb2YgaXRlbS5lcnJvcnNcIj57e2Vycm9yLm1lc3NhZ2V9fTwvZGl2PlxuICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgPG1hdC1oaW50IGFsaWduPVwic3RhcnRcIiAqbmdJZj1cIiEoaXRlbS5lcnJvcnMgJiYgaXRlbS5lcnJvcnMubGVuZ3RoKVwiPjxzdHJvbmc+e3tpdGVtLmhpbnR9fTwvc3Ryb25nPiA8L21hdC1oaW50PlxuICAgIDwvZGl2PlxuPC9kaXY+XG5cblxuIl19