cps-ui-kit 0.154.0 → 0.156.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -12,6 +12,7 @@
12
12
  - Datepicker
13
13
  - Dialog
14
14
  - Expansion panel
15
+ - File upload
15
16
  - Icon
16
17
  - Info circle
17
18
  - Input
@@ -0,0 +1,138 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { convertSize } from '../../utils/internal/size-utils';
4
+ import { CpsIconComponent } from '../cps-icon/cps-icon.component';
5
+ import { CpsProgressLinearComponent } from '../cps-progress-linear/cps-progress-linear.component';
6
+ import { catchError, of, take } from 'rxjs';
7
+ import * as i0 from "@angular/core";
8
+ import * as i1 from "@angular/common";
9
+ /**
10
+ * CpsFileUploadComponent is an advanced uploader with dragdrop support.
11
+ * @group Components
12
+ */
13
+ export class CpsFileUploadComponent {
14
+ constructor() {
15
+ /**
16
+ * Expected extensions of a file to be uploaded. E.g. 'doc or .doc'.
17
+ * @group Props
18
+ */
19
+ this.extensions = [];
20
+ /**
21
+ * Expected file description. E.g. 'Word document'.
22
+ * @group Props
23
+ */
24
+ this.fileDesc = 'Any file';
25
+ /**
26
+ * Width of the component, a number denoting pixels or a string.
27
+ * @group Props
28
+ */
29
+ this.width = '100%';
30
+ /**
31
+ * Callback for uploaded file processing.
32
+ * @group Props
33
+ */
34
+ this.fileProcessingCallback = undefined;
35
+ /**
36
+ * Callback to invoke when file is uploaded.
37
+ * @param {File} File
38
+ * @group Emits
39
+ */
40
+ this.fileUploaded = new EventEmitter();
41
+ /**
42
+ * Callback to invoke when file upload fails.
43
+ * @param {string} - file name
44
+ * @group Emits
45
+ */
46
+ this.fileUploadFailed = new EventEmitter();
47
+ /**
48
+ * Callback to invoke when uploaded file is removed.
49
+ * @param {string} - file name
50
+ * @group Emits
51
+ */
52
+ this.uploadedFileRemoved = new EventEmitter();
53
+ this.isDragoverFile = false;
54
+ this.extensionsString = '';
55
+ this.extensionsStringAsterisks = '';
56
+ this.isProcessingFile = false;
57
+ }
58
+ ngOnInit() {
59
+ this.width = convertSize(this.width);
60
+ this.extensions = this.extensions.map((ext) => ext.startsWith('.') ? ext : '.' + ext);
61
+ this.extensionsString = this.extensions.join(', ');
62
+ this.extensionsStringAsterisks = this.extensions
63
+ .map((ext) => '*' + ext)
64
+ .join(', ');
65
+ }
66
+ tryUploadFile(event) {
67
+ event.preventDefault();
68
+ event.stopPropagation();
69
+ this.isDragoverFile = false;
70
+ let file;
71
+ if (event.type === 'drop') {
72
+ file = event.dataTransfer?.files.item(0) ?? undefined;
73
+ }
74
+ else {
75
+ const files = event.target.files;
76
+ if (!files || files.length < 1)
77
+ return;
78
+ file = files.item(0) ?? undefined;
79
+ }
80
+ if (!this._isFileExtensionValid(file)) {
81
+ this.fileUploadFailed.emit(file?.name ?? '');
82
+ return;
83
+ }
84
+ this.uploadedFile = file;
85
+ if (this.uploadedFile) {
86
+ this.fileUploaded.emit(this.uploadedFile);
87
+ if (this.fileProcessingCallback) {
88
+ this.isProcessingFile = true;
89
+ this.fileProcessingCallback(this.uploadedFile)
90
+ .pipe(take(1), catchError(() => {
91
+ return of(false);
92
+ }))
93
+ .subscribe((res) => {
94
+ if (!res)
95
+ this.removeUploadedFile();
96
+ this.isProcessingFile = false;
97
+ });
98
+ }
99
+ }
100
+ }
101
+ removeUploadedFile() {
102
+ const name = this.uploadedFile?.name ?? '';
103
+ this.uploadedFile = undefined;
104
+ this.uploadedFileRemoved.emit(name);
105
+ }
106
+ _isFileExtensionValid(file) {
107
+ if (!file)
108
+ return false;
109
+ if (this.extensions.length < 1)
110
+ return true;
111
+ for (const ext of this.extensions) {
112
+ if (file.name.endsWith(ext))
113
+ return true;
114
+ }
115
+ return false;
116
+ }
117
+ }
118
+ CpsFileUploadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: CpsFileUploadComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
119
+ CpsFileUploadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: CpsFileUploadComponent, isStandalone: true, selector: "cps-file-upload", inputs: { extensions: "extensions", fileDesc: "fileDesc", width: "width", fileProcessingCallback: "fileProcessingCallback" }, outputs: { fileUploaded: "fileUploaded", fileUploadFailed: "fileUploadFailed", uploadedFileRemoved: "uploadedFileRemoved" }, ngImport: i0, template: "<div class=\"cps-file-upload\" [ngStyle]=\"{ width: width }\">\n <div\n class=\"cps-file-upload-dropzone\"\n [ngClass]=\"{\n 'dragged-over': isDragoverFile,\n 'with-uploads': uploadedFile?.name\n }\"\n (dragend)=\"isDragoverFile = false\"\n (dragenter)=\"isDragoverFile = true\"\n (dragleave)=\"isDragoverFile = false\"\n (dragover)=\"isDragoverFile = true\"\n (mouseleave)=\"isDragoverFile = false\"\n (drop)=\"tryUploadFile($event)\">\n <input\n (change)=\"tryUploadFile($event)\"\n type=\"file\"\n [accept]=\"extensionsString\"\n title=\"\" />\n <cps-icon icon=\"export\" size=\"large\" color=\"text-darkest\"></cps-icon>\n <div class=\"cps-file-upload-dropzone-title\">\n Drag&Drop or choose a file to upload\n </div>\n <span\n class=\"cps-file-upload-dropzone-file-desc\"\n *ngIf=\"fileDesc || extensionsStringAsterisks\"\n >{{ fileDesc }}\n {{\n extensionsStringAsterisks ? '(' + extensionsStringAsterisks + ')' : ''\n }}</span\n >\n <cps-progress-linear\n *ngIf=\"isProcessingFile && uploadedFile\"\n height=\"3\"\n radius=\"4\"\n opacity=\"0.3\"\n class=\"cps-file-upload-progress-bar\"\n bgColor=\"transparent\">\n </cps-progress-linear>\n </div>\n <div *ngIf=\"uploadedFile\" class=\"cps-file-upload-uploaded-files\">\n <div class=\"cps-file-upload-uploaded-file\">\n <div class=\"cps-file-upload-uploaded-file-title\">\n <cps-icon\n class=\"cps-file-upload-uploaded-file-status-icon\"\n [icon]=\"isProcessingFile ? 'pending' : 'toast-success'\"\n [color]=\"isProcessingFile ? 'warn' : 'success'\">\n </cps-icon>\n <div class=\"cps-file-upload-uploaded-file-name\">\n {{ uploadedFile.name }}\n </div>\n </div>\n <cps-icon\n *ngIf=\"!isProcessingFile\"\n class=\"cps-file-upload-uploaded-file-remove-icon\"\n icon=\"remove\"\n color=\"error\"\n (click)=\"removeUploadedFile()\">\n </cps-icon>\n </div>\n </div>\n</div>\n", styles: [":host{display:flex}:host .cps-file-upload .cps-file-upload-dropzone{font-family:Source Sans Pro,sans-serif;min-height:20px;padding:2rem;text-align:center;border:2px dashed var(--cps-color-calm);position:relative;border-radius:1rem}:host .cps-file-upload .cps-file-upload-dropzone:hover{background-color:var(--cps-color-highlight-hover)}:host .cps-file-upload .cps-file-upload-dropzone:active{background-color:var(--cps-color-highlight-selected)}:host .cps-file-upload .cps-file-upload-dropzone.dragged-over{background-color:var(--cps-color-highlight-selected)}:host .cps-file-upload .cps-file-upload-dropzone.with-uploads{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom:1px dashed var(--cps-color-calm)}:host .cps-file-upload .cps-file-upload-dropzone input{cursor:pointer;opacity:0;position:absolute;width:100%;height:100%;top:0;left:0}:host .cps-file-upload .cps-file-upload-dropzone .cps-file-upload-dropzone-title{font-size:16px;margin:8px 0;color:var(--cps-color-calm);font-weight:600}:host .cps-file-upload .cps-file-upload-dropzone .cps-file-upload-dropzone-file-desc{font-size:18px;color:var(--cps-color-text-dark)}:host .cps-file-upload .cps-file-upload-dropzone .cps-file-upload-progress-bar{position:absolute;bottom:-2px;left:0}:host .cps-file-upload .cps-file-upload-uploaded-files{border-bottom:2px dashed var(--cps-color-calm);border-left:2px dashed var(--cps-color-calm);border-right:2px dashed var(--cps-color-calm);border-bottom-right-radius:16px;border-bottom-left-radius:16px;background-color:var(--cps-color-highlight-hover)}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file{cursor:default;display:flex;align-items:center;justify-content:space-between;padding:8px 12px}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-title{display:flex;align-items:center}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-title .cps-file-upload-uploaded-file-name{color:var(--cps-color-text-darkest);font-size:20px;margin:0 8px}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-remove-icon{cursor:pointer}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-remove-icon:hover ::ng-deep .cps-icon{color:var(--cps-color-error-darken1)!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: CpsIconComponent, selector: "cps-icon", inputs: ["icon", "size", "color"] }, { kind: "component", type: CpsProgressLinearComponent, selector: "cps-progress-linear", inputs: ["width", "height", "color", "bgColor", "opacity", "radius"] }] });
120
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: CpsFileUploadComponent, decorators: [{
121
+ type: Component,
122
+ args: [{ selector: 'cps-file-upload', standalone: true, imports: [CommonModule, CpsIconComponent, CpsProgressLinearComponent], template: "<div class=\"cps-file-upload\" [ngStyle]=\"{ width: width }\">\n <div\n class=\"cps-file-upload-dropzone\"\n [ngClass]=\"{\n 'dragged-over': isDragoverFile,\n 'with-uploads': uploadedFile?.name\n }\"\n (dragend)=\"isDragoverFile = false\"\n (dragenter)=\"isDragoverFile = true\"\n (dragleave)=\"isDragoverFile = false\"\n (dragover)=\"isDragoverFile = true\"\n (mouseleave)=\"isDragoverFile = false\"\n (drop)=\"tryUploadFile($event)\">\n <input\n (change)=\"tryUploadFile($event)\"\n type=\"file\"\n [accept]=\"extensionsString\"\n title=\"\" />\n <cps-icon icon=\"export\" size=\"large\" color=\"text-darkest\"></cps-icon>\n <div class=\"cps-file-upload-dropzone-title\">\n Drag&Drop or choose a file to upload\n </div>\n <span\n class=\"cps-file-upload-dropzone-file-desc\"\n *ngIf=\"fileDesc || extensionsStringAsterisks\"\n >{{ fileDesc }}\n {{\n extensionsStringAsterisks ? '(' + extensionsStringAsterisks + ')' : ''\n }}</span\n >\n <cps-progress-linear\n *ngIf=\"isProcessingFile && uploadedFile\"\n height=\"3\"\n radius=\"4\"\n opacity=\"0.3\"\n class=\"cps-file-upload-progress-bar\"\n bgColor=\"transparent\">\n </cps-progress-linear>\n </div>\n <div *ngIf=\"uploadedFile\" class=\"cps-file-upload-uploaded-files\">\n <div class=\"cps-file-upload-uploaded-file\">\n <div class=\"cps-file-upload-uploaded-file-title\">\n <cps-icon\n class=\"cps-file-upload-uploaded-file-status-icon\"\n [icon]=\"isProcessingFile ? 'pending' : 'toast-success'\"\n [color]=\"isProcessingFile ? 'warn' : 'success'\">\n </cps-icon>\n <div class=\"cps-file-upload-uploaded-file-name\">\n {{ uploadedFile.name }}\n </div>\n </div>\n <cps-icon\n *ngIf=\"!isProcessingFile\"\n class=\"cps-file-upload-uploaded-file-remove-icon\"\n icon=\"remove\"\n color=\"error\"\n (click)=\"removeUploadedFile()\">\n </cps-icon>\n </div>\n </div>\n</div>\n", styles: [":host{display:flex}:host .cps-file-upload .cps-file-upload-dropzone{font-family:Source Sans Pro,sans-serif;min-height:20px;padding:2rem;text-align:center;border:2px dashed var(--cps-color-calm);position:relative;border-radius:1rem}:host .cps-file-upload .cps-file-upload-dropzone:hover{background-color:var(--cps-color-highlight-hover)}:host .cps-file-upload .cps-file-upload-dropzone:active{background-color:var(--cps-color-highlight-selected)}:host .cps-file-upload .cps-file-upload-dropzone.dragged-over{background-color:var(--cps-color-highlight-selected)}:host .cps-file-upload .cps-file-upload-dropzone.with-uploads{border-bottom-right-radius:0;border-bottom-left-radius:0;border-bottom:1px dashed var(--cps-color-calm)}:host .cps-file-upload .cps-file-upload-dropzone input{cursor:pointer;opacity:0;position:absolute;width:100%;height:100%;top:0;left:0}:host .cps-file-upload .cps-file-upload-dropzone .cps-file-upload-dropzone-title{font-size:16px;margin:8px 0;color:var(--cps-color-calm);font-weight:600}:host .cps-file-upload .cps-file-upload-dropzone .cps-file-upload-dropzone-file-desc{font-size:18px;color:var(--cps-color-text-dark)}:host .cps-file-upload .cps-file-upload-dropzone .cps-file-upload-progress-bar{position:absolute;bottom:-2px;left:0}:host .cps-file-upload .cps-file-upload-uploaded-files{border-bottom:2px dashed var(--cps-color-calm);border-left:2px dashed var(--cps-color-calm);border-right:2px dashed var(--cps-color-calm);border-bottom-right-radius:16px;border-bottom-left-radius:16px;background-color:var(--cps-color-highlight-hover)}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file{cursor:default;display:flex;align-items:center;justify-content:space-between;padding:8px 12px}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-title{display:flex;align-items:center}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-title .cps-file-upload-uploaded-file-name{color:var(--cps-color-text-darkest);font-size:20px;margin:0 8px}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-remove-icon{cursor:pointer}:host .cps-file-upload .cps-file-upload-uploaded-files .cps-file-upload-uploaded-file .cps-file-upload-uploaded-file-remove-icon:hover ::ng-deep .cps-icon{color:var(--cps-color-error-darken1)!important}\n"] }]
123
+ }], propDecorators: { extensions: [{
124
+ type: Input
125
+ }], fileDesc: [{
126
+ type: Input
127
+ }], width: [{
128
+ type: Input
129
+ }], fileProcessingCallback: [{
130
+ type: Input
131
+ }], fileUploaded: [{
132
+ type: Output
133
+ }], fileUploadFailed: [{
134
+ type: Output
135
+ }], uploadedFileRemoved: [{
136
+ type: Output
137
+ }] } });
138
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY3BzLWZpbGUtdXBsb2FkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Nwcy11aS1raXQvc3JjL2xpYi9jb21wb25lbnRzL2Nwcy1maWxlLXVwbG9hZC9jcHMtZmlsZS11cGxvYWQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY3BzLXVpLWtpdC9zcmMvbGliL2NvbXBvbmVudHMvY3BzLWZpbGUtdXBsb2FkL2Nwcy1maWxlLXVwbG9hZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQVUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9FLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbEUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sc0RBQXNELENBQUM7QUFDbEcsT0FBTyxFQUFjLFVBQVUsRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7QUFFeEQ7OztHQUdHO0FBUUgsTUFBTSxPQUFPLHNCQUFzQjtJQVBuQztRQVFFOzs7V0FHRztRQUNNLGVBQVUsR0FBYSxFQUFFLENBQUM7UUFFbkM7OztXQUdHO1FBQ00sYUFBUSxHQUFHLFVBQVUsQ0FBQztRQUUvQjs7O1dBR0c7UUFDTSxVQUFLLEdBQW9CLE1BQU0sQ0FBQztRQUV6Qzs7O1dBR0c7UUFDTSwyQkFBc0IsR0FDN0IsU0FBUyxDQUFDO1FBRVo7Ozs7V0FJRztRQUNPLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQztRQUVsRDs7OztXQUlHO1FBQ08scUJBQWdCLEdBQUcsSUFB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LE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUMzQyxJQUFJLENBQUMsWUFBWSxHQUFHLFNBQVMsQ0FBQztRQUM5QixJQUFJLENBQUMsbUJBQW1CLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFFTyxxQkFBcUIsQ0FBQyxJQUFXO1FBQ3ZDLElBQUksQ0FBQyxJQUFJO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFFeEIsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sR0FBRyxDQUFDO1lBQUUsT0FBTyxJQUFJLENBQUM7UUFFNUMsS0FBSyxNQUFNLEdBQUcsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ2pDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1NBQzFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDOzttSEF6SFUsc0JBQXNCO3VHQUF0QixzQkFBc0Isc1VDbEJuQyw0akVBNkRBLG0rRUQvQ1ksWUFBWSxzVEFBRSxnQkFBZ0Isd0ZBQUUsMEJBQTBCOzJGQUl6RCxzQkFBc0I7a0JBUGxDLFNBQVM7K0JBQ0UsaUJBQWlCLGNBQ2YsSUFBSSxXQUNQLENBQUMsWUFBWSxFQUFFLGdCQUFnQixFQUFFLDBCQUEwQixDQUFDOzhCQVM1RCxVQUFVO3NCQUFsQixLQUFLO2dCQU1HLFFBQVE7c0JBQWhCLEtBQUs7Z0JBTUcsS0FBSztzQkFBYixLQUFLO2dCQU1HLHNCQUFzQjtzQkFBOUIsS0FBSztnQkFRSSxZQUFZO3NCQUFyQixNQUFNO2dCQU9HLGdCQUFnQjtzQkFBekIsTUFBTTtnQkFPRyxtQkFBbUI7c0JBQTVCLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgY29udmVydFNpemUgfSBmcm9tICcuLi8uLi91dGlscy9pbnRlcm5hbC9zaXplLXV0aWxzJztcbmltcG9ydCB7IENwc0ljb25Db21wb25lbnQgfSBmcm9tICcuLi9jcHMtaWNvbi9jcHMtaWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgQ3BzUHJvZ3Jlc3NMaW5lYXJDb21wb25lbnQgfSBmcm9tICcuLi9jcHMtcHJvZ3Jlc3MtbGluZWFyL2Nwcy1wcm9ncmVzcy1saW5lYXIuY29tcG9uZW50JztcbmltcG9ydCB7IE9ic2VydmFibGUsIGNhdGNoRXJyb3IsIG9mLCB0YWtlIH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogQ3BzRmlsZVVwbG9hZENvbXBvbmVudCBpcyBhbiBhZHZhbmNlZCB1cGxvYWRlciB3aXRoIGRyYWdkcm9wIHN1cHBvcnQuXG4gKiBAZ3JvdXAgQ29tcG9uZW50c1xuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjcHMtZmlsZS11cGxvYWQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBDcHNJY29uQ29tcG9uZW50LCBDcHNQcm9ncmVzc0xpbmVhckNvbXBvbmVudF0sXG4gIHRlbXBsYXRlVXJsOiAnLi9jcHMtZmlsZS11cGxvYWQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jcHMtZmlsZS11cGxvYWQuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBDcHNGaWxlVXBsb2FkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgLyoqXG4gICAqIEV4cGVjdGVkIGV4dGVuc2lvbnMgb2YgYSBmaWxlIHRvIGJlIHVwbG9hZGVkLiBFLmcuICdkb2Mgb3IgLmRvYycuXG4gICAqIEBncm91cCBQcm9wc1xuICAgKi9cbiAgQElucHV0KCkgZXh0ZW5zaW9uczogc3RyaW5nW10gPSBbXTtcblxuICAvKipcbiAgICogRXhwZWN0ZWQgZmlsZSBkZXNjcmlwdGlvbi4gRS5nLiAnV29yZCBkb2N1bWVudCcuXG4gICAqIEBncm91cCBQcm9wc1xuICAgKi9cbiAgQElucHV0KCkgZmlsZURlc2MgPSAnQW55IGZpbGUnO1xuXG4gIC8qKlxuICAgKiBXaWR0aCBvZiB0aGUgY29tcG9uZW50LCBhIG51bWJlciBkZW5vdGluZyBwaXhlbHMgb3IgYSBzdHJpbmcuXG4gICAqIEBncm91cCBQcm9wc1xuICAgKi9cbiAgQElucHV0KCkgd2lkdGg6IG51bWJlciB8IHN0cmluZyA9ICcxMDAlJztcblxuICAvKipcbiAgICogQ2FsbGJhY2sgZm9yIHVwbG9hZGVkIGZpbGUgcHJvY2Vzc2luZy5cbiAgICogQGdyb3VwIFByb3BzXG4gICAqL1xuICBASW5wdXQoKSBmaWxlUHJvY2Vzc2luZ0NhbGxiYWNrPzogKGZpbGU6IEZpbGUpID0+IE9ic2VydmFibGU8Ym9vbGVhbj4gPVxuICAgIHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQ2FsbGJhY2sgdG8gaW52b2tlIHdoZW4gZmlsZSBpcyB1cGxvYWRlZC5cbiAgICogQHBhcmFtIHtGaWxlfSBGaWxlXG4gICAqIEBncm91cCBFbWl0c1xuICAgKi9cbiAgQE91dHB1dCgpIGZpbGVVcGxvYWRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8RmlsZT4oKTtcblxuICAvKipcbiAgICogQ2FsbGJhY2sgdG8gaW52b2tlIHdoZW4gZmlsZSB1cGxvYWQgZmFpbHMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSAtIGZpbGUgbmFtZVxuICAgKiBAZ3JvdXAgRW1pdHNcbiAgICovXG4gIEBPdXRwdXQoKSBmaWxlVXBsb2FkRmFpbGVkID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmc+KCk7XG5cbiAgLyoqXG4gICAqIENhbGxiYWNrIHRvIGludm9rZSB3aGVuIHVwbG9hZGVkIGZpbGUgaXMgcmVtb3ZlZC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IC0gZmlsZSBuYW1lXG4gICAqIEBncm91cCBFbWl0c1xuICAgKi9cbiAgQE91dHB1dCgpIHVwbG9hZGVkRmlsZVJlbW92ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcblxuICBpc0RyYWdvdmVyRmlsZSA9IGZhbHNlO1xuICB1cGxvYWRlZEZpbGU/OiBGaWxlO1xuICBleHRlbnNpb25zU3RyaW5nID0gJyc7XG4gIGV4dGVuc2lvbnNTdHJpbmdBc3Rlcmlza3MgPSAnJztcblxuICBpc1Byb2Nlc3NpbmdGaWxlID0gZmFsc2U7XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy53aWR0aCA9IGNvbnZlcnRTaXplKHRoaXMud2lkdGgpO1xuICAgIHRoaXMuZXh0ZW5zaW9ucyA9IHRoaXMuZXh0ZW5zaW9ucy5tYXAoKGV4dCkgPT5cbiAgICAgIGV4dC5zdGFydHNXaXRoKCcuJykgPyBleHQgOiAnLicgKyBleHRcbiAgICApO1xuICAgIHRoaXMuZXh0ZW5zaW9uc1N0cmluZyA9IHRoaXMuZXh0ZW5zaW9ucy5qb2luKCcsICcpO1xuICAgIHRoaXMuZXh0ZW5zaW9uc1N0cmluZ0FzdGVyaXNrcyA9IHRoaXMuZXh0ZW5zaW9uc1xuICAgICAgLm1hcCgoZXh0KSA9PiAnKicgKyBleHQpXG4gICAgICAuam9pbignLCAnKTtcbiAgfVxuXG4gIHRyeVVwbG9hZEZpbGUoZXZlbnQ6IEV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIHRoaXMuaXNEcmFnb3ZlckZpbGUgPSBmYWxzZTtcbiAgICBsZXQgZmlsZTogRmlsZSB8IHVuZGVmaW5lZDtcblxuICAgIGlmIChldmVudC50eXBlID09PSAnZHJvcCcpIHtcbiAgICAgIGZpbGUgPSAoZXZlbnQgYXMgRHJhZ0V2ZW50KS5kYXRhVHJhbnNmZXI/LmZpbGVzLml0ZW0oMCkgPz8gdW5kZWZpbmVkO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBmaWxlcyA9IChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkuZmlsZXM7XG4gICAgICBpZiAoIWZpbGVzIHx8IGZpbGVzLmxlbmd0aCA8IDEpIHJldHVybjtcbiAgICAgIGZpbGUgPSBmaWxlcy5pdGVtKDApID8/IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX2lzRmlsZUV4dGVuc2lvblZhbGlkKGZpbGUpKSB7XG4gICAgICB0aGlzLmZpbGVVcGxvYWRGYWlsZWQuZW1pdChmaWxlPy5uYW1lID8/ICcnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnVwbG9hZGVkRmlsZSA9IGZpbGU7XG4gICAgaWYgKHRoaXMudXBsb2FkZWRGaWxlKSB7XG4gICAgICB0aGlzLmZpbGVVcGxvYWRlZC5lbWl0KHRoaXMudXBsb2FkZWRGaWxlKTtcbiAgICAgIGlmICh0aGlzLmZpbGVQcm9jZXNzaW5nQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5pc1Byb2Nlc3NpbmdGaWxlID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5maWxlUHJvY2Vzc2luZ0NhbGxiYWNrKHRoaXMudXBsb2FkZWRGaWxlKVxuICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICAgIGNhdGNoRXJyb3IoKCkgPT4ge1xuICAgICAgICAgICAgICByZXR1cm4gb2YoZmFsc2UpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICApXG4gICAgICAgICAgLnN1YnNjcmliZSgocmVzKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXJlcykgdGhpcy5yZW1vdmVVcGxvYWRlZEZpbGUoKTtcbiAgICAgICAgICAgIHRoaXMuaXNQcm9jZXNzaW5nRmlsZSA9IGZhbHNlO1xuICAgICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJlbW92ZVVwbG9hZGVkRmlsZSgpIHtcbiAgICBjb25zdCBuYW1lID0gdGhpcy51cGxvYWRlZEZpbGU/Lm5hbWUgPz8gJyc7XG4gICAgdGhpcy51cGxvYWRlZEZpbGUgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy51cGxvYWRlZEZpbGVSZW1vdmVkLmVtaXQobmFtZSk7XG4gIH1cblxuICBwcml2YXRlIF9pc0ZpbGVFeHRlbnNpb25WYWxpZChmaWxlPzogRmlsZSkge1xuICAgIGlmICghZmlsZSkgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKHRoaXMuZXh0ZW5zaW9ucy5sZW5ndGggPCAxKSByZXR1cm4gdHJ1ZTtcblxuICAgIGZvciAoY29uc3QgZXh0IG9mIHRoaXMuZXh0ZW5zaW9ucykge1xuICAgICAgaWYgKGZpbGUubmFtZS5lbmRzV2l0aChleHQpKSByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjcHMtZmlsZS11cGxvYWRcIiBbbmdTdHlsZV09XCJ7IHdpZHRoOiB3aWR0aCB9XCI+XG4gIDxkaXZcbiAgICBjbGFzcz1cImNwcy1maWxlLXVwbG9hZC1kcm9wem9uZVwiXG4gICAgW25nQ2xhc3NdPVwie1xuICAgICAgJ2RyYWdnZWQtb3Zlcic6IGlzRHJhZ292ZXJGaWxlLFxuICAgICAgJ3dpdGgtdXBsb2Fkcyc6IHVwbG9hZGVkRmlsZT8ubmFtZVxuICAgIH1cIlxuICAgIChkcmFnZW5kKT1cImlzRHJhZ292ZXJGaWxlID0gZmFsc2VcIlxuICAgIChkcmFnZW50ZXIpPVwiaXNEcmFnb3ZlckZpbGUgPSB0cnVlXCJcbiAgICAoZHJhZ2xlYXZlKT1cImlzRHJhZ292ZXJGaWxlID0gZmFsc2VcIlxuICAgIChkcmFnb3Zlcik9XCJpc0RyYWdvdmVyRmlsZSA9IHRydWVcIlxuICAgIChtb3VzZWxlYXZlKT1cImlzRHJhZ292ZXJGaWxlID0gZmFsc2VcIlxuICAgIChkcm9wKT1cInRyeVVwbG9hZEZpbGUoJGV2ZW50KVwiPlxuICAgIDxpbnB1dFxuICAgICAgKGNoYW5nZSk9XCJ0cnlVcGxvYWRGaWxlKCRldmVudClcIlxuICAgICAgdHlwZT1cImZpbGVcIlxuICAgICAgW2FjY2VwdF09XCJleHRlbnNpb25zU3RyaW5nXCJcbiAgICAgIHRpdGxlPVwiXCIgLz5cbiAgICA8Y3BzLWljb24gaWNvbj1cImV4cG9ydFwiIHNpemU9XCJsYXJnZVwiIGNvbG9yPVwidGV4dC1kYXJrZXN0XCI+PC9jcHMtaWNvbj5cbiAgICA8ZGl2IGNsYXNzPVwiY3BzLWZpbGUtdXBsb2FkLWRyb3B6b25lLXRpdGxlXCI+XG4gICAgICBEcmFnJkRyb3Agb3IgY2hvb3NlIGEgZmlsZSB0byB1cGxvYWRcbiAgICA8L2Rpdj5cbiAgICA8c3BhblxuICAgICAgY2xhc3M9XCJjcHMtZmlsZS11cGxvYWQtZHJvcHpvbmUtZmlsZS1kZXNjXCJcbiAgICAgICpuZ0lmPVwiZmlsZURlc2MgfHwgZXh0ZW5zaW9uc1N0cmluZ0FzdGVyaXNrc1wiXG4gICAgICA+e3sgZmlsZURlc2MgfX1cbiAgICAgIHt7XG4gICAgICAgIGV4dGVuc2lvbnNTdHJpbmdBc3Rlcmlza3MgPyAnKCcgKyBleHRlbnNpb25zU3RyaW5nQXN0ZXJpc2tzICsgJyknIDogJydcbiAgICAgIH19PC9zcGFuXG4gICAgPlxuICAgIDxjcHMtcHJvZ3Jlc3MtbGluZWFyXG4gICAgICAqbmdJZj1cImlzUHJvY2Vzc2luZ0ZpbGUgJiYgdXBsb2FkZWRGaWxlXCJcbiAgICAgIGhlaWdodD1cIjNcIlxuICAgICAgcmFkaXVzPVwiNFwiXG4gICAgICBvcGFjaXR5PVwiMC4zXCJcbiAgICAgIGNsYXNzPVwiY3BzLWZpbGUtdXBsb2FkLXByb2dyZXNzLWJhclwiXG4gICAgICBiZ0NvbG9yPVwidHJhbnNwYXJlbnRcIj5cbiAgICA8L2Nwcy1wcm9ncmVzcy1saW5lYXI+XG4gIDwvZGl2PlxuICA8ZGl2ICpuZ0lmPVwidXBsb2FkZWRGaWxlXCIgY2xhc3M9XCJjcHMtZmlsZS11cGxvYWQtdXBsb2FkZWQtZmlsZXNcIj5cbiAgICA8ZGl2IGNsYXNzPVwiY3BzLWZpbGUtdXBsb2FkLXVwbG9hZGVkLWZpbGVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjcHMtZmlsZS11cGxvYWQtdXBsb2FkZWQtZmlsZS10aXRsZVwiPlxuICAgICAgICA8Y3BzLWljb25cbiAgICAgICAgICBjbGFzcz1cImNwcy1maWxlLXVwbG9hZC11cGxvYWRlZC1maWxlLXN0YXR1cy1pY29uXCJcbiAgICAgICAgICBbaWNvbl09XCJpc1Byb2Nlc3NpbmdGaWxlID8gJ3BlbmRpbmcnIDogJ3RvYXN0LXN1Y2Nlc3MnXCJcbiAgICAgICAgICBbY29sb3JdPVwiaXNQcm9jZXNzaW5nRmlsZSA/ICd3YXJuJyA6ICdzdWNjZXNzJ1wiPlxuICAgICAgICA8L2Nwcy1pY29uPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiY3BzLWZpbGUtdXBsb2FkLXVwbG9hZGVkLWZpbGUtbmFtZVwiPlxuICAgICAgICAgIHt7IHVwbG9hZGVkRmlsZS5uYW1lIH19XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgICA8Y3BzLWljb25cbiAgICAgICAgKm5nSWY9XCIhaXNQcm9jZXNzaW5nRmlsZVwiXG4gICAgICAgIGNsYXNzPVwiY3BzLWZpbGUtdXBsb2FkLXVwbG9hZGVkLWZpbGUtcmVtb3ZlLWljb25cIlxuICAgICAgICBpY29uPVwicmVtb3ZlXCJcbiAgICAgICAgY29sb3I9XCJlcnJvclwiXG4gICAgICAgIChjbGljayk9XCJyZW1vdmVVcGxvYWRlZEZpbGUoKVwiPlxuICAgICAgPC9jcHMtaWNvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj5cbiJdfQ==