UNPKG

carbon-components-angular

Version:
387 lines (385 loc) 33.1 kB
import { Component, Input, Output, ViewChild, EventEmitter, TemplateRef } from "@angular/core"; import { NG_VALUE_ACCESSOR } from "@angular/forms"; import * as i0 from "@angular/core"; import * as i1 from "carbon-components-angular/i18n"; import * as i2 from "@angular/common"; import * as i3 from "carbon-components-angular/button"; import * as i4 from "./file.component"; const noop = () => { }; /** * Get started with importing the module: * * ```typescript * import { FileUploaderModule } from 'carbon-components-angular'; * ``` * * [See demo](../../?path=/story/components-file-uploader--basic) */ export class FileUploader { constructor(i18n) { this.i18n = i18n; /** * Accessible text for the button that opens the upload window. * * Defaults to the `FILE_UPLOADER.OPEN` value from the i18n service */ this.buttonText = this.i18n.get().FILE_UPLOADER.OPEN; /** * Type set for button */ this.buttonType = "primary"; /** * Specify the types of files that the input should be able to receive */ this.accept = []; /** * Set to `false` to tell the component to only accept a single file on upload. * * Defaults to `true`. Accepts multiple files. */ this.multiple = true; /** * Set to `true` for a loading file uploader. */ this.skeleton = false; /** * Sets the size of the file items */ this.fileItemSize = "lg"; /** * Set to `true` to enable drag and drop. */ this.drop = false; /** * Provides a unique id for the underlying `<input>` node */ this.fileUploaderId = `file-uploader-${FileUploader.fileUploaderCount}`; /** * The list of files that have been submitted to be uploaded */ this.files = new Set(); /** * Set to `true` to disable upload button */ this.disabled = false; this.filesChange = new EventEmitter(); /** * Controls the state of the drag and drop file container */ this.dragOver = false; this.onTouchedCallback = noop; this.onChangeCallback = noop; FileUploader.fileUploaderCount++; } /** * Specifies the property to be used as the return value to `ngModel` and reactive forms. * Updates `this.files`. */ get value() { return this.files; } set value(v) { if (v !== this.files) { this.files = v; this.onChangeCallback(v); } } onBlur() { this.onTouchedCallback(); } get fileList() { return Array.from(this.fileInput.nativeElement.files); } /** * Propagates the injected `value`. */ writeValue(value) { if (value !== this.value) { this.files = value; } } createFileItem(file) { return { uploaded: false, state: "edit", invalid: false, invalidText: "", file: file }; } onFilesAdded() { const newFiles = new Set(this.files); if (!this.multiple) { newFiles.clear(); } for (let file of this.fileList) { const fileItem = this.createFileItem(file); newFiles.add(fileItem); } this.value = newFiles; this.filesChange.emit(newFiles); } onDragOver(event) { event.stopPropagation(); event.preventDefault(); if (this.disabled) { return; } this.dragOver = true; } onDragLeave(event) { event.stopPropagation(); event.preventDefault(); this.dragOver = false; } onDrop(event) { event.stopPropagation(); event.preventDefault(); if (this.disabled) { return; } const transferredFiles = Array.from(event.dataTransfer.files); const newFiles = new Set(this.files); transferredFiles.filter(({ name, type }) => { // Get the file extension and add a "." to the beginning. const fileExtension = name.split(".").pop().replace(/^/, "."); // Check if the accept array contains the mime type or extension of the file. return this.accept.includes(type) || this.accept.includes(fileExtension) || !this.accept.length; }).forEach(file => { if (!newFiles.size || this.multiple) { const fileItem = this.createFileItem(file); newFiles.add(fileItem); } }); this.value = newFiles; this.filesChange.emit(newFiles); this.dragOver = false; } removeFile(fileItem) { // Deleting an item from this.files removes the <ibm-file> component, // which triggers its ngOnDestroy(), which fires the (remove) event again. // So, (remove) may double-fire and we need to handle it here. if (this.files && this.files.has(fileItem)) { const newFiles = new Set(this.files); newFiles.delete(fileItem); this.filesChange.emit(newFiles); this.value = newFiles; } this.fileInput.nativeElement.value = ""; } isTemplate(value) { return value instanceof TemplateRef; } /** * Registers the injected function to control the touch use of the `FileUploader`. */ registerOnTouched(fn) { this.onTouchedCallback = fn; } /** * Sets a method in order to propagate changes back to the form. */ registerOnChange(fn) { this.onChangeCallback = fn; } /** * `ControlValueAccessor` method to programmatically disable the checkbox. * * ex: `this.formGroup.get("myFileUploader").disable();` * * @param isDisabled `true` to disable the file uploader */ setDisabledState(isDisabled) { this.disabled = isDisabled; } } /** * Counter used to create unique ids for file-uploader components */ FileUploader.fileUploaderCount = 0; FileUploader.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploader, deps: [{ token: i1.I18n }], target: i0.ɵɵFactoryTarget.Component }); FileUploader.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: FileUploader, selector: "cds-file-uploader, ibm-file-uploader", inputs: { buttonText: "buttonText", buttonType: "buttonType", title: "title", description: "description", accept: "accept", multiple: "multiple", skeleton: "skeleton", size: "size", fileItemSize: "fileItemSize", drop: "drop", dropText: "dropText", fileUploaderId: "fileUploaderId", files: "files", disabled: "disabled", fileNameTpl: "fileNameTpl", fileActionsTpl: "fileActionsTpl" }, outputs: { filesChange: "filesChange" }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: FileUploader, multi: true } ], viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true }], ngImport: i0, template: ` <ng-container *ngIf="!skeleton; else skeletonTemplate"> <label [for]="fileUploaderId" class="cds--file--label">{{title}}</label> <p class="cds--label-description" role="alert">{{description}}</p> <div class="cds--file"> <label *ngIf="drop" class="cds--file-browse-btn" (keyup.enter)="fileInput.click()" (keyup.space)="fileInput.click()" [ngClass]="{'cds--file-browse-btn--disabled': disabled}" tabindex="0"> <div class="cds--file__drop-container" [ngClass]="{'cds--file__drop-container--drag-over': dragOver}" role="button" (click)="fileInput.click()" [attr.for]="fileUploaderId" (dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)" (drop)="onDrop($event)"> <ng-container *ngIf="!isTemplate(dropText)">{{dropText}}</ng-container> <ng-template *ngIf="isTemplate(dropText)" [ngTemplateOutlet]="dropText"></ng-template> </div> </label> <button *ngIf="!drop" type="button" [cdsButton]="buttonType" (click)="fileInput.click()" [attr.for]="fileUploaderId" [size]="size" [disabled]="disabled"> {{buttonText}} </button> <input #fileInput type="file" class="cds--file-input" [accept]="accept" [id]="fileUploaderId" [multiple]="multiple" tabindex="-1" (change)="onFilesAdded()" [disabled]="disabled"/> <div class="cds--file-container"> <ng-container *ngFor="let fileItem of files"> <cds-file [fileItem]="fileItem" [nameTpl]="fileNameTpl" [actionsTpl]="fileActionsTpl" [size]="fileItemSize" (remove)="removeFile(fileItem)"> </cds-file> </ng-container> </div> </div> </ng-container> <ng-template #skeletonTemplate> <div class="cds--skeleton__text" style="width: 100px"></div> <div class="cds--skeleton__text" style="width: 225px"></div> <button cdsButton skeleton="true"></button> </ng-template> `, isInline: true, 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: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i3.Button, selector: "[cdsButton], [ibmButton]", inputs: ["ibmButton", "cdsButton", "size", "skeleton", "iconOnly", "isExpressive"] }, { kind: "component", type: i4.FileComponent, selector: "cds-file, ibm-file", inputs: ["translations", "fileItem", "size", "nameTpl", "actionsTpl"], outputs: ["remove"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FileUploader, decorators: [{ type: Component, args: [{ selector: "cds-file-uploader, ibm-file-uploader", template: ` <ng-container *ngIf="!skeleton; else skeletonTemplate"> <label [for]="fileUploaderId" class="cds--file--label">{{title}}</label> <p class="cds--label-description" role="alert">{{description}}</p> <div class="cds--file"> <label *ngIf="drop" class="cds--file-browse-btn" (keyup.enter)="fileInput.click()" (keyup.space)="fileInput.click()" [ngClass]="{'cds--file-browse-btn--disabled': disabled}" tabindex="0"> <div class="cds--file__drop-container" [ngClass]="{'cds--file__drop-container--drag-over': dragOver}" role="button" (click)="fileInput.click()" [attr.for]="fileUploaderId" (dragover)="onDragOver($event)" (dragleave)="onDragLeave($event)" (drop)="onDrop($event)"> <ng-container *ngIf="!isTemplate(dropText)">{{dropText}}</ng-container> <ng-template *ngIf="isTemplate(dropText)" [ngTemplateOutlet]="dropText"></ng-template> </div> </label> <button *ngIf="!drop" type="button" [cdsButton]="buttonType" (click)="fileInput.click()" [attr.for]="fileUploaderId" [size]="size" [disabled]="disabled"> {{buttonText}} </button> <input #fileInput type="file" class="cds--file-input" [accept]="accept" [id]="fileUploaderId" [multiple]="multiple" tabindex="-1" (change)="onFilesAdded()" [disabled]="disabled"/> <div class="cds--file-container"> <ng-container *ngFor="let fileItem of files"> <cds-file [fileItem]="fileItem" [nameTpl]="fileNameTpl" [actionsTpl]="fileActionsTpl" [size]="fileItemSize" (remove)="removeFile(fileItem)"> </cds-file> </ng-container> </div> </div> </ng-container> <ng-template #skeletonTemplate> <div class="cds--skeleton__text" style="width: 100px"></div> <div class="cds--skeleton__text" style="width: 225px"></div> <button cdsButton skeleton="true"></button> </ng-template> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: FileUploader, multi: true } ] }] }], ctorParameters: function () { return [{ type: i1.I18n }]; }, propDecorators: { buttonText: [{ type: Input }], buttonType: [{ type: Input }], title: [{ type: Input }], description: [{ type: Input }], accept: [{ type: Input }], multiple: [{ type: Input }], skeleton: [{ type: Input }], size: [{ type: Input }], fileItemSize: [{ type: Input }], drop: [{ type: Input }], dropText: [{ type: Input }], fileUploaderId: [{ type: Input }], fileInput: [{ type: ViewChild, args: ["fileInput"] }], files: [{ type: Input }], disabled: [{ type: Input }], fileNameTpl: [{ type: Input }], fileActionsTpl: [{ type: Input }], filesChange: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmlsZS11cGxvYWRlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZmlsZS11cGxvYWRlci9maWxlLXVwbG9hZGVyLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ04sU0FBUyxFQUNULEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULFlBQVksRUFDWixXQUFXLEVBQ1gsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7QUFLekUsTUFBTSxJQUFJLEdBQUcsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0FBRXZCOzs7Ozs7OztHQVFHO0FBNEVILE1BQU0sT0FBTyxZQUFZO0lBd0Z4QixZQUFzQixJQUFVO1FBQVYsU0FBSSxHQUFKLElBQUksQ0FBTTtRQW5GaEM7Ozs7V0FJRztRQUNNLGVBQVUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUM7UUFDekQ7O1dBRUc7UUFDTSxlQUFVLEdBQThELFNBQVMsQ0FBQztRQVMzRjs7V0FFRztRQUNNLFdBQU0sR0FBRyxFQUFFLENBQUM7UUFDckI7Ozs7V0FJRztRQUNNLGFBQVEsR0FBRyxJQUFJLENBQUM7UUFDekI7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBSzFCOztXQUVHO1FBQ00saUJBQVksR0FBdUIsSUFBSSxDQUFDO1FBQ2pEOztXQUVHO1FBQ00sU0FBSSxHQUFHLEtBQUssQ0FBQztRQUt0Qjs7V0FFRztRQUNNLG1CQUFjLEdBQUcsaUJBQWlCLFlBQVksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBSzVFOztXQUVHO1FBQ00sVUFBSyxHQUFHLElBQUksR0FBRyxFQUFZLENBQUM7UUFDckM7O1dBRUc7UUFDTSxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBVWhCLGdCQUFXLEdBQUcs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Yzs0QkFDekIsS0FBSyxFQUFFLElBQUk7eUJBQ1g7cUJBQ0Q7aUJBQ0Q7MkZBV1MsVUFBVTtzQkFBbEIsS0FBSztnQkFJRyxVQUFVO3NCQUFsQixLQUFLO2dCQUlHLEtBQUs7c0JBQWIsS0FBSztnQkFJRyxXQUFXO3NCQUFuQixLQUFLO2dCQUlHLE1BQU07c0JBQWQsS0FBSztnQkFNRyxRQUFRO3NCQUFoQixLQUFLO2dCQUlHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBSUcsSUFBSTtzQkFBWixLQUFLO2dCQUlHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBSUcsSUFBSTtzQkFBWixLQUFLO2dCQUlHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBSUcsY0FBYztzQkFBdEIsS0FBSztnQkFJa0IsU0FBUztzQkFBaEMsU0FBUzt1QkFBQyxXQUFXO2dCQUliLEtBQUs7c0JBQWIsS0FBSztnQkFJRyxRQUFRO3NCQUFoQixLQUFLO2dCQUlHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBSUcsY0FBYztzQkFBdEIsS0FBSztnQkFFSSxXQUFXO3NCQUFwQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcblx0Q29tcG9uZW50LFxuXHRJbnB1dCxcblx0T3V0cHV0LFxuXHRWaWV3Q2hpbGQsXG5cdEV2ZW50RW1pdHRlcixcblx0VGVtcGxhdGVSZWZcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xuXG5pbXBvcnQgeyBJMThuIH0gZnJvbSBcImNhcmJvbi1jb21wb25lbnRzLWFuZ3VsYXIvaTE4blwiO1xuaW1wb3J0IHsgRmlsZUl0ZW0gfSBmcm9tIFwiLi9maWxlLWl0ZW0uaW50ZXJmYWNlXCI7XG5cbmNvbnN0IG5vb3AgPSAoKSA9PiB7IH07XG5cbi8qKlxuICogR2V0IHN0YXJ0ZWQgd2l0aCBpbXBvcnRpbmcgdGhlIG1vZHVsZTpcbiAqXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbXBvcnQgeyBGaWxlVXBsb2FkZXJNb2R1bGUgfSBmcm9tICdjYXJib24tY29tcG9uZW50cy1hbmd1bGFyJztcbiAqIGBgYFxuICpcbiAqIFtTZWUgZGVtb10oLi4vLi4vP3BhdGg9L3N0b3J5L2NvbXBvbmVudHMtZmlsZS11cGxvYWRlci0tYmFzaWMpXG4gKi9cbkBDb21wb25lbnQoe1xuXHRzZWxlY3RvcjogXCJjZHMtZmlsZS11cGxvYWRlciwgaWJtLWZpbGUtdXBsb2FkZXJcIixcblx0dGVtcGxhdGU6IGBcblx0XHQ8bmctY29udGFpbmVyICpuZ0lmPVwiIXNrZWxldG9uOyBlbHNlIHNrZWxldG9uVGVtcGxhdGVcIj5cblx0XHRcdDxsYWJlbCBbZm9yXT1cImZpbGVVcGxvYWRlcklkXCIgY2xhc3M9XCJjZHMtLWZpbGUtLWxhYmVsXCI+e3t0aXRsZX19PC9sYWJlbD5cblx0XHRcdDxwIGNsYXNzPVwiY2RzLS1sYWJlbC1kZXNjcmlwdGlvblwiIHJvbGU9XCJhbGVydFwiPnt7ZGVzY3JpcHRpb259fTwvcD5cblx0XHRcdDxkaXYgY2xhc3M9XCJjZHMtLWZpbGVcIj5cblx0XHRcdFx0PGxhYmVsXG5cdFx0XHRcdFx0Km5nSWY9XCJkcm9wXCJcblx0XHRcdFx0XHRjbGFzcz1cImNkcy0tZmlsZS1icm93c2UtYnRuXCJcblx0XHRcdFx0XHQoa2V5dXAuZW50ZXIpPVwiZmlsZUlucHV0LmNsaWNrKClcIlxuXHRcdFx0XHRcdChrZXl1cC5zcGFjZSk9XCJmaWxlSW5wdXQuY2xpY2soKVwiXG5cdFx0XHRcdFx0W25nQ2xhc3NdPVwieydjZHMtLWZpbGUtYnJvd3NlLWJ0bi0tZGlzYWJsZWQnOiBkaXNhYmxlZH1cIlxuXHRcdFx0XHRcdHRhYmluZGV4PVwiMFwiPlxuXHRcdFx0XHRcdDxkaXZcblx0XHRcdFx0XHRcdGNsYXNzPVwiY2RzLS1maWxlX19kcm9wLWNvbnRhaW5lclwiXG5cdFx0XHRcdFx0XHRbbmdDbGFzc109XCJ7J2Nkcy0tZmlsZV9fZHJvcC1jb250YWluZXItLWRyYWctb3Zlcic6IGRyYWdPdmVyfVwiXG5cdFx0XHRcdFx0XHRyb2xlPVwiYnV0dG9uXCJcblx0XHRcdFx0XHRcdChjbGljayk9XCJmaWxlSW5wdXQuY2xpY2soKVwiXG5cdFx0XHRcdFx0XHRbYXR0ci5mb3JdPVwiZmlsZVVwbG9hZGVySWRcIlxuXHRcdFx0XHRcdFx0KGRyYWdvdmVyKT1cIm9uRHJhZ092ZXIoJGV2ZW50KVwiXG5cdFx0XHRcdFx0XHQoZHJhZ2xlYXZlKT1cIm9uRHJhZ0xlYXZlKCRldmVudClcIlxuXHRcdFx0XHRcdFx0KGRyb3ApPVwib25Ecm9wKCRldmVudClcIj5cblx0XHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nSWY9XCIhaXNUZW1wbGF0ZShkcm9wVGV4dClcIj57e2Ryb3BUZXh0fX08L25nLWNvbnRhaW5lcj5cblx0XHRcdFx0XHRcdDxuZy10ZW1wbGF0ZSAqbmdJZj1cImlzVGVtcGxhdGUoZHJvcFRleHQpXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwiZHJvcFRleHRcIj48L25nLXRlbXBsYXRlPlxuXHRcdFx0XHRcdDwvZGl2PlxuXHRcdFx0XHQ8L2xhYmVsPlxuXHRcdFx0XHQ8YnV0dG9uXG5cdFx0XHRcdFx0Km5nSWY9XCIhZHJvcFwiXG5cdFx0XHRcdFx0dHlwZT1cImJ1dHRvblwiXG5cdFx0XHRcdFx0W2Nkc0J1dHRvbl09XCJidXR0b25UeXBlXCJcblx0XHRcdFx0XHQoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIlxuXHRcdFx0XHRcdFthdHRyLmZvcl09XCJmaWxlVXBsb2FkZXJJZFwiXG5cdFx0XHRcdFx0W3NpemVdPVwic2l6ZVwiXG5cdFx0XHRcdFx0W2Rpc2FibGVkXT1cImRpc2FibGVkXCI+XG5cdFx0XHRcdFx0e3tidXR0b25UZXh0fX1cblx0XHRcdFx0PC9idXR0b24+XG5cdFx0XHRcdDxpbnB1dFxuXHRcdFx0XHRcdCNmaWxlSW5wdXRcblx0XHRcdFx0XHR0eXBlPVwiZmlsZVwiXG5cdFx0XHRcdFx0Y2xhc3M9XCJjZHMtLWZpbGUtaW5wdXRcIlxuXHRcdFx0XHRcdFthY2NlcHRdPVwiYWNjZXB0XCJcblx0XHRcdFx0XHRbaWRdPVwiZmlsZVVwbG9hZGVySWRcIlxuXHRcdFx0XHRcdFttdWx0aXBsZV09XCJtdWx0aXBsZVwiXG5cdFx0XHRcdFx0dGFiaW5kZXg9XCItMVwiXG5cdFx0XHRcdFx0KGNoYW5nZSk9XCJvbkZpbGVzQWRkZWQoKVwiXG5cdFx0XHRcdFx0W2Rpc2FibGVkXT1cImRpc2FibGVkXCIvPlxuXHRcdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1maWxlLWNvbnRhaW5lclwiPlxuXHRcdFx0XHRcdDxuZy1jb250YWluZXIgKm5nRm9yPVwibGV0IGZpbGVJdGVtIG9mIGZpbGVzXCI+XG5cdFx0XHRcdFx0XHQ8Y2RzLWZpbGVcblx0XHRcdFx0XHRcdFx0W2ZpbGVJdGVtXT1cImZpbGVJdGVtXCJcblx0XHRcdFx0XHRcdFx0W25hbWVUcGxdPVwiZmlsZU5hbWVUcGxcIlxuXHRcdFx0XHRcdFx0XHRbYWN0aW9uc1RwbF09XCJmaWxlQWN0aW9uc1RwbFwiXG5cdFx0XHRcdFx0XHRcdFtzaXplXT1cImZpbGVJdGVtU2l6ZVwiXG5cdFx0XHRcdFx0XHRcdChyZW1vdmUpPVwicmVtb3ZlRmlsZShmaWxlSXRlbSlcIj5cblx0XHRcdFx0XHRcdDwvY2RzLWZpbGU+XG5cdFx0XHRcdFx0PC9uZy1jb250YWluZXI+XG5cdFx0XHRcdDwvZGl2PlxuXHRcdFx0PC9kaXY+XG5cdFx0PC9uZy1jb250YWluZXI+XG5cblx0XHQ8bmctdGVtcGxhdGUgI3NrZWxldG9uVGVtcGxhdGU+XG5cdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1za2VsZXRvbl9fdGV4dFwiIHN0eWxlPVwid2lkdGg6IDEwMHB4XCI+PC9kaXY+XG5cdFx0XHQ8ZGl2IGNsYXNzPVwiY2RzLS1za2VsZXRvbl9fdGV4dFwiIHN0eWxlPVwid2lkdGg6IDIyNXB4XCI+PC9kaXY+XG5cdFx0XHQ8YnV0dG9uIGNkc0J1dHRvbiBza2VsZXRvbj1cInRydWVcIj48L2J1dHRvbj5cblx0XHQ8L25nLXRlbXBsYXRlPlxuXHRgLFxuXHRwcm92aWRlcnM6IFtcblx0XHR7XG5cdFx0XHRwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcblx0XHRcdHVzZUV4aXN0aW5nOiBGaWxlVXBsb2FkZXIsXG5cdFx0XHRtdWx0aTogdHJ1ZVxuXHRcdH1cblx0XVxufSlcbmV4cG9ydCBjbGFzcyBGaWxlVXBsb2FkZXIgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciB7XG5cdC8qKlxuXHQgKiBDb3VudGVyIHVzZWQgdG8gY3JlYXRlIHVuaXF1ZSBpZHMgZm9yIGZpbGUtdXBsb2FkZXIgY29tcG9uZW50c1xuXHQgKi9cblx0c3RhdGljIGZpbGVVcGxvYWRlckNvdW50ID0gMDtcblx0LyoqXG5cdCAqIEFjY2Vzc2libGUgdGV4dCBmb3IgdGhlIGJ1dHRvbiB0aGF0IG9wZW5zIHRoZSB1cGxvYWQgd2luZG93LlxuXHQgKlxuXHQgKiBEZWZhdWx0cyB0byB0aGUgYEZJTEVfVVBMT0FERVIuT1BFTmAgdmFsdWUgZnJvbSB0aGUgaTE4biBzZXJ2aWNlXG5cdCAqL1xuXHRASW5wdXQoKSBidXR0b25UZXh0ID0gdGhpcy5pMThuLmdldCgpLkZJTEVfVVBMT0FERVIuT1BFTjtcblx0LyoqXG5cdCAqIFR5cGUgc2V0IGZvciBidXR0b25cblx0ICovXG5cdEBJbnB1dCgpIGJ1dHRvblR5cGU6IFwicHJpbWFyeVwiIHwgXCJzZWNvbmRhcnlcIiB8IFwidGVydGlhcnlcIiB8IFwiZ2hvc3RcIiB8IFwiZGFuZ2VyXCIgPSBcInByaW1hcnlcIjtcblx0LyoqXG5cdCAqIFRleHQgc2V0IHRvIHRoZSB0aXRsZVxuXHQgKi9cblx0QElucHV0KCkgdGl0bGU6IHN0cmluZztcblx0LyoqXG5cdCAqIFRleHQgc2V0IHRvIHRoZSBkZXNjcmlwdGlvblxuXHQgKi9cblx0QElucHV0KCkgZGVzY3JpcHRpb246IHN0cmluZztcblx0LyoqXG5cdCAqIFNwZWNpZnkgdGhlIHR5cGVzIG9mIGZpbGVzIHRoYXQgdGhlIGlucHV0IHNob3VsZCBiZSBhYmxlIHRvIHJlY2VpdmVcblx0ICovXG5cdEBJbnB1dCgpIGFjY2VwdCA9IFtdO1xuXHQvKipcblx0ICogU2V0IHRvIGBmYWxzZWAgdG8gdGVsbCB0aGUgY29tcG9uZW50IHRvIG9ubHkgYWNjZXB0IGEgc2luZ2xlIGZpbGUgb24gdXBsb2FkLlxuXHQgKlxuXHQgKiBEZWZhdWx0cyB0byBgdHJ1ZWAuIEFjY2VwdHMgbXVsdGlwbGUgZmlsZXMuXG5cdCAqL1xuXHRASW5wdXQoKSBtdWx0aXBsZSA9IHRydWU7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIGZvciBhIGxvYWRpbmcgZmlsZSB1cGxvYWRlci5cblx0ICovXG5cdEBJbnB1dCgpIHNrZWxldG9uID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBzaXplIG9mIHRoZSBidXR0b24uXG5cdCAqL1xuXHRASW5wdXQoKSBzaXplOiBcInNtXCIgfCBcIm1kXCIgfCBcImxnXCI7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSBzaXplIG9mIHRoZSBmaWxlIGl0ZW1zXG5cdCAqL1xuXHRASW5wdXQoKSBmaWxlSXRlbVNpemU6IFwic21cIiB8IFwibWRcIiB8IFwibGdcIiA9IFwibGdcIjtcblx0LyoqXG5cdCAqIFNldCB0byBgdHJ1ZWAgdG8gZW5hYmxlIGRyYWcgYW5kIGRyb3AuXG5cdCAqL1xuXHRASW5wdXQoKSBkcm9wID0gZmFsc2U7XG5cdC8qKlxuXHQgKiBTZXRzIHRoZSB0ZXh0IHNob3duIGluIGRyYWcgYW5kIGRyb3AgYm94LlxuXHQgKi9cblx0QElucHV0KCkgZHJvcFRleHQ6IHN0cmluZyB8IFRlbXBsYXRlUmVmPGFueT47XG5cdC8qKlxuXHQgKiBQcm92aWRlcyBhIHVuaXF1ZSBpZCBmb3IgdGhlIHVuZGVybHlpbmcgYDxpbnB1dD5gIG5vZGVcblx0ICovXG5cdEBJbnB1dCgpIGZpbGVVcGxvYWRlcklkID0gYGZpbGUtdXBsb2FkZXItJHtGaWxlVXBsb2FkZXIuZmlsZVVwbG9hZGVyQ291bnR9YDtcblx0LyoqXG5cdCAqIE1haW50YWlucyBhIHJlZmVyZW5jZSB0byB0aGUgdmlldyBET00gZWxlbWVudCBvZiB0aGUgdW5kZXJseWluZyA8aW5wdXQ+IG5vZGVcblx0ICovXG5cdEBWaWV3Q2hpbGQoXCJmaWxlSW5wdXRcIikgZmlsZUlucHV0O1xuXHQvKipcblx0ICogVGhlIGxpc3Qgb2YgZmlsZXMgdGhhdCBoYXZlIGJlZW4gc3VibWl0dGVkIHRvIGJlIHVwbG9hZGVkXG5cdCAqL1xuXHRASW5wdXQoKSBmaWxlcyA9IG5ldyBTZXQ8RmlsZUl0ZW0+KCk7XG5cdC8qKlxuXHQgKiBTZXQgdG8gYHRydWVgIHRvIGRpc2FibGUgdXBsb2FkIGJ1dHRvblxuXHQgKi9cblx0QElucHV0KCkgZGlzYWJsZWQgPSBmYWxzZTtcblx0LyoqXG5cdCAqIEN1c3RvbSB0ZW1wbGF0ZSB1c2VkIHRvIHJlbmRlciB0aGUgZmlsZSBuYW1lIG9mIHVwbG9hZGVkIGZpbGVzXG5cdCAqL1xuXHRASW5wdXQoKSBmaWxlTmFtZVRwbDogVGVtcGxhdGVSZWY8dW5rbm93bj47XG5cdC8qKlxuXHQgKiBDdXN0b20gdGVtcGxhdGUgdXNlZCB0byByZW5kZXIgdGhlIGZpbGUgYWN0aW9ucyBvZiB1cGxvYWRlZCBmaWxlc1xuXHQgKi9cblx0QElucHV0KCkgZmlsZUFjdGlvbnNUcGw6IFRlbXBsYXRlUmVmPHVua25vd24+O1xuXG5cdEBPdXRwdXQoKSBmaWxlc0NoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuXG5cdC8qKlxuXHQgKiBDb250cm9scyB0aGUgc3RhdGUgb2YgdGhlIGRyYWcgYW5kIGRyb3AgZmlsZSBjb250YWluZXJcblx0ICovXG5cdHB1YmxpYyBkcmFnT3ZlciA9IGZhbHNlO1xuXG5cdHByb3RlY3RlZCBvblRvdWNoZWRDYWxsYmFjazogKCkgPT4gdm9pZCA9IG5vb3A7XG5cdHByb3RlY3RlZCBvbkNoYW5nZUNhbGxiYWNrOiAoXzogU2V0PEZpbGVJdGVtPikgPT4gdm9pZCA9IG5vb3A7XG5cblx0Y29uc3RydWN0b3IocHJvdGVjdGVkIGkxOG46IEkxOG4pIHtcblx0XHRGaWxlVXBsb2FkZXIuZmlsZVVwbG9hZGVyQ291bnQrKztcblx0fVxuXG5cdC8qKlxuXHQgKiBTcGVjaWZpZXMgdGhlIHByb3BlcnR5IHRvIGJlIHVzZWQgYXMgdGhlIHJldHVybiB2YWx1ZSB0byBgbmdNb2RlbGAgYW5kIHJlYWN0aXZlIGZvcm1zLlxuXHQgKiBVcGRhdGVzIGB0aGlzLmZpbGVzYC5cblx0ICovXG5cdGdldCB2YWx1ZSgpOiBTZXQ8RmlsZUl0ZW0+IHtcblx0XHRyZXR1cm4gdGhpcy5maWxlcztcblx0fVxuXHRzZXQgdmFsdWUodjogU2V0PEZpbGVJdGVtPikge1xuXHRcdGlmICh2ICE9PSB0aGlzLmZpbGVzKSB7XG5cdFx0XHR0aGlzLmZpbGVzID0gdjtcblx0XHRcdHRoaXMub25DaGFuZ2VDYWxsYmFjayh2KTtcblx0XHR9XG5cdH1cblxuXHRvbkJsdXIoKSB7XG5cdFx0dGhpcy5vblRvdWNoZWRDYWxsYmFjaygpO1xuXHR9XG5cblx0Z2V0IGZpbGVMaXN0KCkge1xuXHRcdHJldHVybiBBcnJheS5mcm9tKHRoaXMuZmlsZUlucHV0Lm5hdGl2ZUVsZW1lbnQuZmlsZXMpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFByb3BhZ2F0ZXMgdGhlIGluamVjdGVkIGB2YWx1ZWAuXG5cdCAqL1xuXHR3cml0ZVZhbHVlKHZhbHVlOiBTZXQ8RmlsZUl0ZW0+KSB7XG5cdFx0aWYgKHZhbHVlICE9PSB0aGlzLnZhbHVlKSB7XG5cdFx0XHR0aGlzLmZpbGVzID0gdmFsdWU7XG5cdFx0fVxuXHR9XG5cblx0Y3JlYXRlRmlsZUl0ZW0oZmlsZSk6IEZpbGVJdGVtIHtcblx0XHRyZXR1cm4ge1xuXHRcdFx0dXBsb2FkZWQ6IGZhbHNlLFxuXHRcdFx0c3RhdGU6IFwiZWRpdFwiLFxuXHRcdFx0aW52YWxpZDogZmFsc2UsXG5cdFx0XHRpbnZhbGlkVGV4dDogXCJcIixcblx0XHRcdGZpbGU6IGZpbGVcblx0XHR9O1xuXHR9XG5cblx0b25GaWxlc0FkZGVkKCkge1xuXHRcdGNvbnN0IG5ld0ZpbGVzID0gbmV3IFNldDxGaWxlSXRlbT4odGhpcy5maWxlcyk7XG5cdFx0aWYgKCF0aGlzLm11bHRpcGxlKSB7XG5cdFx0XHRuZXdGaWxlcy5jbGVhcigpO1xuXHRcdH1cblx0XHRmb3IgKGxldCBmaWxlIG9mIHRoaXMuZmlsZUxpc3QpIHtcblx0XHRcdGNvbnN0IGZpbGVJdGVtID0gdGhpcy5jcmVhdGVGaWxlSXRlbShmaWxlKTtcblx0XHRcdG5ld0ZpbGVzLmFkZChmaWxlSXRlbSk7XG5cdFx0fVxuXG5cdFx0dGhpcy52YWx1ZSA9IG5ld0ZpbGVzO1xuXHRcdHRoaXMuZmlsZXNDaGFuZ2UuZW1pdChuZXdGaWxlcyk7XG5cdH1cblxuXHRvbkRyYWdPdmVyKGV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRpZiAodGhpcy5kaXNhYmxlZCkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XHR0aGlzLmRyYWdPdmVyID0gdHJ1ZTtcblx0fVxuXG5cdG9uRHJhZ0xlYXZlKGV2ZW50KSB7XG5cdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHR0aGlzLmRyYWdPdmVyID0gZmFsc2U7XG5cdH1cblxuXHRvbkRyb3AoZXZlbnQpIHtcblx0XHRldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdGlmICh0aGlzLmRpc2FibGVkKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y29uc3QgdHJhbnNmZXJyZWRGaWxlczogQXJyYXk8RmlsZT4gPSBBcnJheS5mcm9tKGV2ZW50LmRhdGFUcmFuc2Zlci5maWxlcyk7XG5cdFx0Y29uc3QgbmV3RmlsZXMgPSBuZXcgU2V0PEZpbGVJdGVtPih0aGlzLmZpbGVzKTtcblxuXHRcdHRyYW5zZmVycmVkRmlsZXMuZmlsdGVyKCh7IG5hbWUsIHR5cGUgfSkgPT4ge1xuXHRcdFx0Ly8gR2V0IHRoZSBmaWxlIGV4dGVuc2lvbiBhbmQgYWRkIGEgXCIuXCIgdG8gdGhlIGJlZ2lubmluZy5cblx0XHRcdGNvbnN0IGZpbGVFeHRlbnNpb24gPSBuYW1lLnNwbGl0KFwiLlwiKS5wb3AoKS5yZXBsYWNlKC9eLywgXCIuXCIpO1xuXHRcdFx0Ly8gQ2hlY2sgaWYgdGhlIGFjY2VwdCBhcnJheSBjb250YWlucyB0aGUgbWltZSB0eXBlIG9yIGV4dGVuc2lvbiBvZiB0aGUgZmlsZS5cblx0XHRcdHJldHVybiB0aGlzLmFjY2VwdC5pbmNsdWRlcyh0eXBlKSB8fCB0aGlzLmFjY2VwdC5pbmNsdWRlcyhmaWxlRXh0ZW5zaW9uKSB8fCAhdGhpcy5hY2NlcHQubGVuZ3RoO1xuXHRcdH0pLmZvckVhY2goZmlsZSA9PiB7XG5cdFx0XHRpZiAoIW5ld0ZpbGVzLnNpemUgfHwgdGhpcy5tdWx0aXBsZSkge1xuXHRcdFx0XHRjb25zdCBmaWxlSXRlbSA9IHRoaXMuY3JlYXRlRmlsZUl0ZW0oZmlsZSk7XG5cdFx0XHRcdG5ld0ZpbGVzLmFkZChmaWxlSXRlbSk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR0aGlzLnZhbHVlID0gbmV3RmlsZXM7XG5cdFx0dGhpcy5maWxlc0NoYW5nZS5lbWl0KG5ld0ZpbGVzKTtcblx0XHR0aGlzLmRyYWdPdmVyID0gZmFsc2U7XG5cdH1cblxuXHRyZW1vdmVGaWxlKGZpbGVJdGVtKSB7XG5cdFx0Ly8gRGVsZXRpbmcgYW4gaXRlbSBmcm9tIHRoaXMuZmlsZXMgcmVtb3ZlcyB0aGUgPGlibS1maWxlPiBjb21wb25lbnQsXG5cdFx0Ly8gd2hpY2ggdHJpZ2dlcnMgaXRzIG5nT25EZXN0cm95KCksIHdoaWNoIGZpcmVzIHRoZSAocmVtb3ZlKSBldmVudCBhZ2Fpbi5cblx0XHQvLyBTbywgKHJlbW92ZSkgbWF5IGRvdWJsZS1maXJlIGFuZCB3ZSBuZWVkIHRvIGhhbmRsZSBpdCBoZXJlLlxuXHRcdGlmICh0aGlzLmZpbGVzICYmIHRoaXMuZmlsZXMuaGFzKGZpbGVJdGVtKSkge1xuXHRcdFx0Y29uc3QgbmV3RmlsZXMgPSBuZXcgU2V0PEZpbGVJdGVtPih0aGlzLmZpbGVzKTtcblx0XHRcdG5ld0ZpbGVzLmRlbGV0ZShmaWxlSXRlbSk7XG5cdFx0XHR0aGlzLmZpbGVzQ2hhbmdlLmVtaXQobmV3RmlsZXMpO1xuXHRcdFx0dGhpcy52YWx1ZSA9IG5ld0ZpbGVzO1xuXHRcdH1cblx0XHR0aGlzLmZpbGVJbnB1dC5uYXRpdmVFbGVtZW50LnZhbHVlID0gXCJcIjtcblx0fVxuXG5cdHB1YmxpYyBpc1RlbXBsYXRlKHZhbHVlKSB7XG5cdFx0cmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgVGVtcGxhdGVSZWY7XG5cdH1cblxuXHQvKipcblx0ICogUmVnaXN0ZXJzIHRoZSBpbmplY3RlZCBmdW5jdGlvbiB0byBjb250cm9sIHRoZSB0b3VjaCB1c2Ugb2YgdGhlIGBGaWxlVXBsb2FkZXJgLlxuXHQgKi9cblx0cmVnaXN0ZXJPblRvdWNoZWQoZm46IGFueSkge1xuXHRcdHRoaXMub25Ub3VjaGVkQ2FsbGJhY2sgPSBmbjtcblx0fVxuXHQvKipcblx0ICogU2V0cyBhIG1ldGhvZCBpbiBvcmRlciB0byBwcm9wYWdhdGUgY2hhbmdlcyBiYWNrIHRvIHRoZSBmb3JtLlxuXHQgKi9cblx0cmVnaXN0ZXJPbkNoYW5nZShmbjogYW55KSB7XG5cdFx0dGhpcy5vbkNoYW5nZUNhbGxiYWNrID0gZm47XG5cdH1cblxuXHQvKipcblx0ICogYENvbnRyb2xWYWx1ZUFjY2Vzc29yYCBtZXRob2QgdG8gcHJvZ3JhbW1hdGljYWxseSBkaXNhYmxlIHRoZSBjaGVja2JveC5cblx0ICpcblx0ICogZXg6IGB0aGlzLmZvcm1Hcm91cC5nZXQoXCJteUZpbGVVcGxvYWRlclwiKS5kaXNhYmxlKCk7YFxuXHQgKlxuXHQgKiBAcGFyYW0gaXNEaXNhYmxlZCBgdHJ1ZWAgdG8gZGlzYWJsZSB0aGUgZmlsZSB1cGxvYWRlclxuXHQgKi9cblx0c2V0RGlzYWJsZWRTdGF0ZShpc0Rpc2FibGVkOiBib29sZWFuKSB7XG5cdFx0dGhpcy5kaXNhYmxlZCA9IGlzRGlzYWJsZWQ7XG5cdH1cbn1cbiJdfQ==