UNPKG

@iotize/ionic

Version:

Iotize specific building blocks on top of @ionic/angular.

187 lines 25.6 kB
import { ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild, } from '@angular/core'; import { FormBuilder, Validators, } from '@angular/forms'; import { IonInput } from '@ionic/angular'; import { Observable, Subject } from 'rxjs'; import { debug } from '../logger'; import { getFormFieldOrError } from '../utility'; import * as i0 from "@angular/core"; import * as i1 from "@angular/forms"; import * as i2 from "@angular/common"; import * as i3 from "@ionic/angular"; import * as i4 from "./value-or-default.pipe"; const TAG = 'InlineEditorComponent'; export class InlineEditorComponent { changeDetectorRef; /** * Emitter when form is submit */ onSubmit = new EventEmitter(); valueChange = new EventEmitter(); /** * Enable/disable edit mode */ set editMode(v) { this._editMode = v; this.field.setValue(this.currentValue); if (v) { this.enableEditMode(); } } editModeChange = new EventEmitter(); /** * True if field can be edited */ editable = false; unitValue; /** * Input option * You can defined how input will be rendered: text, number, toggle, select, ... */ inputOptions = { type: 'text', }; /** * Additional style for value */ valueStyle; /** * Set observable to subscribe to get value updates */ set value(obs) { this.valueSubscription?.unsubscribe(); if (obs && obs instanceof Observable) { this.valueSubscription = obs.subscribe((value) => { this.updateValue(value); }); } else if (obs !== undefined) { this.updateValue(obs); } } /** * Set value snapshot */ set forceValue(value) { this.updateValue(value); } /** * Enable/disable loader when submitting a value */ showLoader = true; /** * Set field error message */ set fieldError(err) { if (err) { debug(TAG, 'Set field error', err); this.field.setErrors({ submit: err.message, }); } else { this.field.setErrors(null); } } inputView; originalValue; form; _editMode = false; currentValue; valueSubscription; field; destroyed = new Subject(); constructor(formBuilder, changeDetectorRef) { this.changeDetectorRef = changeDetectorRef; this.form = formBuilder.group({ field: ['', Validators.required], }); this.field = getFormFieldOrError(this.form, 'field'); } ngOnDestroy() { this.destroyed.next(); this.destroyed.complete(); if (this.valueSubscription) { this.valueSubscription.unsubscribe(); } } onValueSubmit() { const value = this.field.value; if (this.field.errors) { return; } this.onSubmit.emit(value); } isEdited() { return this.field.value !== this.originalValue; } restoreValue() { this.setFieldValue(this.originalValue); } setFieldValue(value) { // let formattedValue = this.formatter() // this.inputFormatter ? this._info.editFormatter.write(value) : value; this.field.setValue(value || ''); } async onValueClick() { if (this.editable) { await this.enableEditMode(); this.editModeChange.next(true); } } onCancelEdit() { this._editMode = false; this.editModeChange.next(false); } async enableEditMode() { this._editMode = true; await this.setInputFocus(); } async setInputFocus() { this.changeDetectorRef.detectChanges(); await this.inputView.setFocus(); } updateValue(value) { this.currentValue = value; if (!this._editMode && value !== undefined) { this.field.setValue(value); } } onValueChange(event) { const value = event.detail.value; this.valueChange.emit(value); } /** @nocollapse */ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InlineEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: InlineEditorComponent, selector: "tap-inline-editor", inputs: { editMode: "editMode", editable: "editable", unitValue: "unitValue", inputOptions: "inputOptions", valueStyle: "valueStyle", value: "value", forceValue: "forceValue", showLoader: "showLoader", fieldError: "fieldError" }, outputs: { onSubmit: "onSubmit", valueChange: "valueChange", editModeChange: "editModeChange" }, viewQueries: [{ propertyName: "inputView", first: true, predicate: ["inputView"], descendants: true }], ngImport: i0, template: "<ng-container [formGroup]=\"form\">\n <ion-label\n (click)=\"onValueClick()\"\n *ngIf=\"!_editMode\"\n [class]=\"editable ? 'cell editor-value' : 'editor-value'\"\n >\n <span [ngStyle]=\"valueStyle\">{{\n currentValue | valueOrDefault: '---'\n }}</span>\n <span\n *ngIf=\"unitValue\"\n [ngStyle]=\"valueStyle\"\n class=\"variable-unit ion-margin-start\"\n >{{ unitValue }}</span\n >\n </ion-label>\n <ion-input\n #inputView\n (keydown.enter)=\"onValueSubmit()\"\n (ionChange)=\"onValueChange($event)\"\n [class]=\"editable ? 'cell' : 'editor-value'\"\n [ngStyle]=\"valueStyle\"\n (keydown.escape)=\"onCancelEdit()\"\n *ngIf=\"_editMode\"\n [max]=\"inputOptions.max\"\n [maxlength]=\"inputOptions.maxLength\"\n [min]=\"inputOptions.min\"\n [minlength]=\"inputOptions.minLength\"\n [pattern]=\"inputOptions.pattern\"\n [placeholder]=\"inputOptions.placeholder\"\n [type]=\"inputOptions.type\"\n appAutoFocus\n class=\"cellInput\"\n [formControlName]=\"'field'\"\n ></ion-input>\n</ng-container>\n", styles: [".cell{width:fit-content}.cell:hover{cursor:pointer}.cellInput{width:fit-content;height:100%}ion-select{width:100%;min-width:150px;max-width:unset}:host ::ng-deep .toggle-disabled,:host ::ng-deep .select-disabled{opacity:.7}.spanToggle{vertical-align:top;margin:8px;font-weight:550}:host ::ng-deep ion-buttons[slot=end]{margin-inline-start:0px}:host ::ng-deep .native-input.sc-ion-input-md{padding-bottom:0!important;padding-top:0!important}ion-label{visibility:inherit}\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.IonInput, selector: "ion-input", inputs: ["autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearInputIcon", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "spellcheck", "step", "type", "value"] }, { kind: "component", type: i3.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "directive", type: i3.TextValueAccessor, selector: "ion-input:not([type=number]),ion-input-otp[type=text],ion-textarea,ion-searchbar" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: i4.ValueOrDefaultPipe, name: "valueOrDefault" }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InlineEditorComponent, decorators: [{ type: Component, args: [{ selector: 'tap-inline-editor', template: "<ng-container [formGroup]=\"form\">\n <ion-label\n (click)=\"onValueClick()\"\n *ngIf=\"!_editMode\"\n [class]=\"editable ? 'cell editor-value' : 'editor-value'\"\n >\n <span [ngStyle]=\"valueStyle\">{{\n currentValue | valueOrDefault: '---'\n }}</span>\n <span\n *ngIf=\"unitValue\"\n [ngStyle]=\"valueStyle\"\n class=\"variable-unit ion-margin-start\"\n >{{ unitValue }}</span\n >\n </ion-label>\n <ion-input\n #inputView\n (keydown.enter)=\"onValueSubmit()\"\n (ionChange)=\"onValueChange($event)\"\n [class]=\"editable ? 'cell' : 'editor-value'\"\n [ngStyle]=\"valueStyle\"\n (keydown.escape)=\"onCancelEdit()\"\n *ngIf=\"_editMode\"\n [max]=\"inputOptions.max\"\n [maxlength]=\"inputOptions.maxLength\"\n [min]=\"inputOptions.min\"\n [minlength]=\"inputOptions.minLength\"\n [pattern]=\"inputOptions.pattern\"\n [placeholder]=\"inputOptions.placeholder\"\n [type]=\"inputOptions.type\"\n appAutoFocus\n class=\"cellInput\"\n [formControlName]=\"'field'\"\n ></ion-input>\n</ng-container>\n", styles: [".cell{width:fit-content}.cell:hover{cursor:pointer}.cellInput{width:fit-content;height:100%}ion-select{width:100%;min-width:150px;max-width:unset}:host ::ng-deep .toggle-disabled,:host ::ng-deep .select-disabled{opacity:.7}.spanToggle{vertical-align:top;margin:8px;font-weight:550}:host ::ng-deep ion-buttons[slot=end]{margin-inline-start:0px}:host ::ng-deep .native-input.sc-ion-input-md{padding-bottom:0!important;padding-top:0!important}ion-label{visibility:inherit}\n"] }] }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i0.ChangeDetectorRef }], propDecorators: { onSubmit: [{ type: Output }], valueChange: [{ type: Output }], editMode: [{ type: Input }], editModeChange: [{ type: Output }], editable: [{ type: Input }], unitValue: [{ type: Input }], inputOptions: [{ type: Input }], valueStyle: [{ type: Input }], value: [{ type: Input }], forceValue: [{ type: Input }], showLoader: [{ type: Input }], fieldError: [{ type: Input }], inputView: [{ type: ViewChild, args: ['inputView'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pb3RpemUtaW9uaWMvc3JjL2xpYi9pbmxpbmUtZWRpdG9yL2lubGluZS1lZGl0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL3NyYy9saWIvaW5saW5lLWVkaXRvci9pbmxpbmUtZWRpdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBRUwsV0FBVyxFQUVYLFVBQVUsR0FDWCxNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7Ozs7OztBQUVqRCxNQUFNLEdBQUcsR0FBRyx1QkFBdUIsQ0FBQztBQStDcEMsTUFBTSxPQUFPLHFCQUFxQjtJQW1HdEI7SUFsR1Y7O09BRUc7SUFDTyxRQUFRLEdBRWIsSUFBSSxZQUFZLEVBQUUsQ0FBQztJQUVkLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBbUIsQ0FBQztJQUU1RDs7T0FFRztJQUNILElBQWEsUUFBUSxDQUFDLENBQVU7UUFDOUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZD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RUFBRSxDQUFDO1lBQzNDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzdCLENBQUM7SUFDSCxDQUFDO0lBRUQsYUFBYSxDQUFDLEtBQXFDO1FBQ2pELE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7MkhBektVLHFCQUFxQjsrR0FBckIscUJBQXFCLHdlQ25FbEMsMGtDQW9DQTs7NEZEK0JhLHFCQUFxQjtrQkFMakMsU0FBUzsrQkFDRSxtQkFBbUI7Z0hBUW5CLFFBQVE7c0JBQWpCLE1BQU07Z0JBSUcsV0FBVztzQkFBcEIsTUFBTTtnQkFLTSxRQUFRO3NCQUFwQixLQUFLO2dCQVFJLGNBQWM7c0JBQXZCLE1BQU07Z0JBS0UsUUFBUTtzQkFBaEIsS0FBSztnQkFFRyxTQUFTO3NCQUFqQixLQUFLO2dCQU1HLFlBQVk7c0JBQXBCLEtBQUs7Z0JBT0csVUFBVTtzQkFBbEIsS0FBSztnQkFLTyxLQUFLO3NCQUFqQixLQUFLO2dCQWNPLFVBQVU7c0JBQXRCLEtBQUs7Z0JBT0csVUFBVTtzQkFBbEIsS0FBSztnQkFLTyxVQUFVO3NCQUF0QixLQUFLO2dCQVdrQixTQUFTO3NCQUFoQyxTQUFTO3VCQUFDLFdBQVciLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEFic3RyYWN0Q29udHJvbCxcbiAgRm9ybUJ1aWxkZXIsXG4gIEZvcm1Hcm91cCxcbiAgVmFsaWRhdG9ycyxcbn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgSW9uSW5wdXQgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRlYnVnIH0gZnJvbSAnLi4vbG9nZ2VyJztcbmltcG9ydCB7IGdldEZvcm1GaWVsZE9yRXJyb3IgfSBmcm9tICcuLi91dGlsaXR5JztcblxuY29uc3QgVEFHID0gJ0lubGluZUVkaXRvckNvbXBvbmVudCc7XG5cbmV4cG9ydCBuYW1lc3BhY2UgSW5saW5lRWRpdG9yQ29tcG9uZW50IHtcbiAgZXhwb3J0IHR5cGUgSW5wdXRPcHRpb25zID1cbiAgICB8IFRvZ2dsZU9wdGlvbnNcbiAgICB8IE51bWJlck9wdGlvbnNcbiAgICB8IFBhc3N3b3JkT3B0aW9uc1xuICAgIHwgVGV4dE9wdGlvbnM7XG5cbiAgZXhwb3J0IGludGVyZmFjZSBUb2dnbGVPcHRpb25zIHtcbiAgICB0eXBlOiAndG9nZ2xlJztcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgTnVtYmVyT3B0aW9ucyB7XG4gICAgbWluPzogbnVtYmVyO1xuICAgIG1heD86IG51bWJlcjtcbiAgICB0eXBlOiAnbnVtYmVyJztcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgUGFzc3dvcmRPcHRpb25zIHtcbiAgICBwYXR0ZXJuPzogUmVnRXhwO1xuICAgIG1pbkxlbmd0aD86IG51bWJlcjtcbiAgICBtYXhMZW5ndGg/OiBudW1iZXI7XG4gICAgdHlwZTogJ3Bhc3N3b3JkJztcbiAgfVxuXG4gIGV4cG9ydCBpbnRlcmZhY2UgVGV4dE9wdGlvbnMge1xuICAgIHBhdHRlcm4/OiBSZWdFeHA7XG4gICAgbWluTGVuZ3RoPzogbnVtYmVyO1xuICAgIG1heExlbmd0aD86IG51bWJlcjtcbiAgICBwbGFjZWhvbGRlcj86IHN0cmluZztcbiAgICB0eXBlOiAndGV4dCc7XG4gIH1cblxuICBleHBvcnQgbmFtZXNwYWNlIFNlbGVjdE9wdGlvbnMge1xuICAgIGV4cG9ydCB0eXBlIE9wdGlvbnMgPSB7XG4gICAgICBrZXk6IGFueTtcbiAgICAgIHRleHQ6IHN0cmluZztcbiAgICB9W107XG4gIH1cbn1cblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAndGFwLWlubGluZS1lZGl0b3InLFxuICB0ZW1wbGF0ZVVybDogJy4vaW5saW5lLWVkaXRvci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2lubGluZS1lZGl0b3IuY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgSW5saW5lRWRpdG9yQ29tcG9uZW50PFZhbHVlVHlwZSA9IGFueT4gaW1wbGVtZW50cyBPbkRlc3Ryb3kge1xuICAvKipcbiAgICogRW1pdHRlciB3aGVuIGZvcm0gaXMgc3VibWl0XG4gICAqL1xuICBAT3V0cHV0KCkgb25TdWJtaXQ6IEV2ZW50RW1pdHRlcjx7XG4gICAgdGFyZ2V0OiB7IHZhbHVlOiBzdHJpbmcgfTtcbiAgfT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxzdHJpbmcgfCBudW1iZXI+KCk7XG5cbiAgLyoqXG4gICAqIEVuYWJsZS9kaXNhYmxlIGVkaXQgbW9kZVxuICAgKi9cbiAgQElucHV0KCkgc2V0IGVkaXRNb2RlKHY6IGJvb2xlYW4pIHtcbiAgICB0aGlzLl9lZGl0TW9kZSA9IHY7XG4gICAgdGhpcy5maWVsZC5zZXRWYWx1ZSh0aGlzLmN1cnJlbnRWYWx1ZSk7XG4gICAgaWYgKHYpIHtcbiAgICAgIHRoaXMuZW5hYmxlRWRpdE1vZGUoKTtcbiAgICB9XG4gIH1cblxuICBAT3V0cHV0KCkgZWRpdE1vZGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPGJvb2xlYW4+KCk7XG5cbiAgLyoqXG4gICAqIFRydWUgaWYgZmllbGQgY2FuIGJlIGVkaXRlZFxuICAgKi9cbiAgQElucHV0KCkgZWRpdGFibGUgPSBmYWxzZTtcblxuICBASW5wdXQoKSB1bml0VmFsdWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIElucHV0IG9wdGlvblxuICAgKiBZb3UgY2FuIGRlZmluZWQgaG93IGlucHV0IHdpbGwgYmUgcmVuZGVyZWQ6IHRleHQsIG51bWJlciwgdG9nZ2xlLCBzZWxlY3QsIC4uLlxuICAgKi9cbiAgQElucHV0KCkgaW5wdXRPcHRpb25zOiBJbmxpbmVFZGl0b3JDb21wb25lbnQuSW5wdXRPcHRpb25zIHwgYW55ID0ge1xuICAgIHR5cGU6ICd0ZXh0JyxcbiAgfTtcblxuICAvKipcbiAgICogQWRkaXRpb25hbCBzdHlsZSBmb3IgdmFsdWVcbiAgICovXG4gIEBJbnB1dCgpIHZhbHVlU3R5bGU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFNldCBvYnNlcnZhYmxlIHRvIHN1YnNjcmliZSB0byBnZXQgdmFsdWUgdXBkYXRlc1xuICAgKi9cbiAgQElucHV0KCkgc2V0IHZhbHVlKG9iczogT2JzZXJ2YWJsZTxWYWx1ZVR5cGU+IHwgVmFsdWVUeXBlKSB7XG4gICAgdGhpcy52YWx1ZVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICBpZiAob2JzICYmIG9icyBpbnN0YW5jZW9mIE9ic2VydmFibGUpIHtcbiAgICAgIHRoaXMudmFsdWVTdWJzY3JpcHRpb24gPSBvYnMuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZVZhbHVlKHZhbHVlKTtcbiAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAob2JzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMudXBkYXRlVmFsdWUob2JzIGFzIFZhbHVlVHlwZSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFNldCB2YWx1ZSBzbmFwc2hvdFxuICAgKi9cbiAgQElucHV0KCkgc2V0IGZvcmNlVmFsdWUodmFsdWU6IGFueSkge1xuICAgIHRoaXMudXBkYXRlVmFsdWUodmFsdWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVuYWJsZS9kaXNhYmxlIGxvYWRlciB3aGVuIHN1Ym1pdHRpbmcgYSB2YWx1ZVxuICAgKi9cbiAgQElucHV0KCkgc2hvd0xvYWRlciA9IHRydWU7XG5cbiAgLyoqXG4gICAqIFNldCBmaWVsZCBlcnJvciBtZXNzYWdlXG4gICAqL1xuICBASW5wdXQoKSBzZXQgZmllbGRFcnJvcihlcnI6IEVycm9yKSB7XG4gICAgaWYgKGVycikge1xuICAgICAgZGVidWcoVEFHLCAnU2V0IGZpZWxkIGVycm9yJywgZXJyKTtcbiAgICAgIHRoaXMuZmllbGQuc2V0RXJyb3JzKHtcbiAgICAgICAgc3VibWl0OiBlcnIubWVzc2FnZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmZpZWxkLnNldEVycm9ycyhudWxsKTtcbiAgICB9XG4gIH1cblxuICBAVmlld0NoaWxkKCdpbnB1dFZpZXcnKSBpbnB1dFZpZXchOiBJb25JbnB1dDtcblxuICBwcml2YXRlIG9yaWdpbmFsVmFsdWU/OiBWYWx1ZVR5cGU7XG5cbiAgcHVibGljIGZvcm06IEZvcm1Hcm91cDtcbiAgcHVibGljIF9lZGl0TW9kZSA9IGZhbHNlO1xuXG4gIGN1cnJlbnRWYWx1ZTogYW55O1xuICB2YWx1ZVN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcblxuICBmaWVsZDogQWJzdHJhY3RDb250cm9sO1xuXG4gIHByaXZhdGUgZGVzdHJveWVkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBmb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXIsXG4gICAgcHJpdmF0ZSBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWZcbiAgKSB7XG4gICAgdGhpcy5mb3JtID0gZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgZmllbGQ6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXG4gICAgfSk7XG4gICAgdGhpcy5maWVsZCA9IGdldEZvcm1GaWVsZE9yRXJyb3IodGhpcy5mb3JtLCAnZmllbGQnKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMuZGVzdHJveWVkLm5leHQoKTtcbiAgICB0aGlzLmRlc3Ryb3llZC5jb21wbGV0ZSgpO1xuICAgIGlmICh0aGlzLnZhbHVlU3Vic2NyaXB0aW9uKSB7XG4gICAgICB0aGlzLnZhbHVlU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG9uVmFsdWVTdWJtaXQoKSB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmZpZWxkLnZhbHVlO1xuICAgIGlmICh0aGlzLmZpZWxkLmVycm9ycykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm9uU3VibWl0LmVtaXQodmFsdWUpO1xuICB9XG5cbiAgaXNFZGl0ZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZmllbGQudmFsdWUgIT09IHRoaXMub3JpZ2luYWxWYWx1ZTtcbiAgfVxuXG4gIHJlc3RvcmVWYWx1ZSgpIHtcbiAgICB0aGlzLnNldEZpZWxkVmFsdWUodGhpcy5vcmlnaW5hbFZhbHVlKTtcbiAgfVxuXG4gIHNldEZpZWxkVmFsdWUodmFsdWU6IFZhbHVlVHlwZSB8IHVuZGVmaW5lZCkge1xuICAgIC8vIGxldCBmb3JtYXR0ZWRWYWx1ZSA9IHRoaXMuZm9ybWF0dGVyKClcbiAgICAvLyB0aGlzLmlucHV0Rm9ybWF0dGVyID8gdGhpcy5faW5mby5lZGl0Rm9ybWF0dGVyLndyaXRlKHZhbHVlKSA6IHZhbHVlO1xuICAgIHRoaXMuZmllbGQuc2V0VmFsdWUodmFsdWUgfHwgJycpO1xuICB9XG5cbiAgYXN5bmMgb25WYWx1ZUNsaWNrKCkge1xuICAgIGlmICh0aGlzLmVkaXRhYmxlKSB7XG4gICAgICBhd2FpdCB0aGlzLmVuYWJsZUVkaXRNb2RlKCk7XG4gICAgICB0aGlzLmVkaXRNb2RlQ2hhbmdlLm5leHQodHJ1ZSk7XG4gICAgfVxuICB9XG5cbiAgb25DYW5jZWxFZGl0KCkge1xuICAgIHRoaXMuX2VkaXRNb2RlID0gZmFsc2U7XG4gICAgdGhpcy5lZGl0TW9kZUNoYW5nZS5uZXh0KGZhbHNlKTtcbiAgfVxuXG4gIGFzeW5jIGVuYWJsZUVkaXRNb2RlKCkge1xuICAgIHRoaXMuX2VkaXRNb2RlID0gdHJ1ZTtcbiAgICBhd2FpdCB0aGlzLnNldElucHV0Rm9jdXMoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgc2V0SW5wdXRGb2N1cygpIHtcbiAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICBhd2FpdCB0aGlzLmlucHV0Vmlldy5zZXRGb2N1cygpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVWYWx1ZSh2YWx1ZTogVmFsdWVUeXBlKSB7XG4gICAgdGhpcy5jdXJyZW50VmFsdWUgPSB2YWx1ZTtcbiAgICBpZiAoIXRoaXMuX2VkaXRNb2RlICYmIHZhbHVlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuZmllbGQuc2V0VmFsdWUodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIG9uVmFsdWVDaGFuZ2UoZXZlbnQ6IEN1c3RvbUV2ZW50PHsgdmFsdWU6IHN0cmluZyB9Pikge1xuICAgIGNvbnN0IHZhbHVlID0gZXZlbnQuZGV0YWlsLnZhbHVlO1xuICAgIHRoaXMudmFsdWVDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gIH1cbn1cbiIsIjxuZy1jb250YWluZXIgW2Zvcm1Hcm91cF09XCJmb3JtXCI+XG4gIDxpb24tbGFiZWxcbiAgICAoY2xpY2spPVwib25WYWx1ZUNsaWNrKClcIlxuICAgICpuZ0lmPVwiIV9lZGl0TW9kZVwiXG4gICAgW2NsYXNzXT1cImVkaXRhYmxlID8gJ2NlbGwgZWRpdG9yLXZhbHVlJyA6ICdlZGl0b3ItdmFsdWUnXCJcbiAgPlxuICAgIDxzcGFuIFtuZ1N0eWxlXT1cInZhbHVlU3R5bGVcIj57e1xuICAgICAgY3VycmVudFZhbHVlIHwgdmFsdWVPckRlZmF1bHQ6ICctLS0nXG4gICAgfX08L3NwYW4+XG4gICAgPHNwYW5cbiAgICAgICpuZ0lmPVwidW5pdFZhbHVlXCJcbiAgICAgIFtuZ1N0eWxlXT1cInZhbHVlU3R5bGVcIlxuICAgICAgY2xhc3M9XCJ2YXJpYWJsZS11bml0IGlvbi1tYXJnaW4tc3RhcnRcIlxuICAgICAgPnt7IHVuaXRWYWx1ZSB9fTwvc3BhblxuICAgID5cbiAgPC9pb24tbGFiZWw+XG4gIDxpb24taW5wdXRcbiAgICAjaW5wdXRWaWV3XG4gICAgKGtleWRvd24uZW50ZXIpPVwib25WYWx1ZVN1Ym1pdCgpXCJcbiAgICAoaW9uQ2hhbmdlKT1cIm9uVmFsdWVDaGFuZ2UoJGV2ZW50KVwiXG4gICAgW2NsYXNzXT1cImVkaXRhYmxlID8gJ2NlbGwnIDogJ2VkaXRvci12YWx1ZSdcIlxuICAgIFtuZ1N0eWxlXT1cInZhbHVlU3R5bGVcIlxuICAgIChrZXlkb3duLmVzY2FwZSk9XCJvbkNhbmNlbEVkaXQoKVwiXG4gICAgKm5nSWY9XCJfZWRpdE1vZGVcIlxuICAgIFttYXhdPVwiaW5wdXRPcHRpb25zLm1heFwiXG4gICAgW21heGxlbmd0aF09XCJpbnB1dE9wdGlvbnMubWF4TGVuZ3RoXCJcbiAgICBbbWluXT1cImlucHV0T3B0aW9ucy5taW5cIlxuICAgIFttaW5sZW5ndGhdPVwiaW5wdXRPcHRpb25zLm1pbkxlbmd0aFwiXG4gICAgW3BhdHRlcm5dPVwiaW5wdXRPcHRpb25zLnBhdHRlcm5cIlxuICAgIFtwbGFjZWhvbGRlcl09XCJpbnB1dE9wdGlvbnMucGxhY2Vob2xkZXJcIlxuICAgIFt0eXBlXT1cImlucHV0T3B0aW9ucy50eXBlXCJcbiAgICBhcHBBdXRvRm9jdXNcbiAgICBjbGFzcz1cImNlbGxJbnB1dFwiXG4gICAgW2Zvcm1Db250cm9sTmFtZV09XCInZmllbGQnXCJcbiAgPjwvaW9uLWlucHV0PlxuPC9uZy1jb250YWluZXI+XG4iXX0=