UNPKG

@iotize/ionic

Version:

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

175 lines 25.4 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 { /** * Enable/disable edit mode */ set editMode(v) { this._editMode = v; this.field.setValue(this.currentValue); if (v) { this.enableEditMode(); } } /** * 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); } /** * 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); } } constructor(formBuilder, changeDetectorRef) { this.changeDetectorRef = changeDetectorRef; /** * Emitter when form is submit */ this.onSubmit = new EventEmitter(); this.valueChange = new EventEmitter(); this.editModeChange = new EventEmitter(); /** * True if field can be edited */ this.editable = false; /** * Input option * You can defined how input will be rendered: text, number, toggle, select, ... */ this.inputOptions = { type: 'text', }; /** * Enable/disable loader when submitting a value */ this.showLoader = true; this._editMode = false; this.destroyed = new Subject(); 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 */ InlineEditorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: InlineEditorComponent, deps: [{ token: i1.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ InlineEditorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", 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:-moz-fit-content;width:fit-content}.cell:hover{cursor:pointer}.cellInput{width:-moz-fit-content;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: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "size", "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-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: "15.2.10", 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:-moz-fit-content;width:fit-content}.cell:hover{cursor:pointer}.cellInput{width:-moz-fit-content;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: function () { return [{ 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5saW5lLWVkaXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9pb3RpemUtaW9uaWMvc3JjL2xpYi9pbmxpbmUtZWRpdG9yL2lubGluZS1lZGl0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvaW90aXplLWlvbmljL3NyYy9saWIvaW5saW5lLWVkaXRvci9pbmxpbmUtZWRpdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsU0FBUyxFQUNULFlBQVksRUFDWixLQUFLLEVBRUwsTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBRUwsV0FBVyxFQUVYLFVBQVUsR0FDWCxNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMxQyxPQUFPLEVBQUUsVUFBVSxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDekQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUNsQyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxZQUFZLENBQUM7Ozs7OztBQUVqRCxNQUFNLEdBQUcsR0FBRyx1QkFBdUIsQ0FBQztBQStDcEMsTUFBTSxPQUFPLHFCQUFxQjtJQVVoQzs7T0FFRztJQUNILElBQWEsUUFBUSxDQUFDLENBQVU7UUFDOUIsSUFBSSxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxFQUFFO1lBQ0wsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1NBQ3ZCO0lBQ0gsQ0FBQztJQXdCRDs7T0FFRztJQUNILElBQWEsS0FBSyxD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SEFBckIscUJBQXFCLHdlQ25FbEMsMGtDQW9DQTs0RkQrQmEscUJBQXFCO2tCQUxqQyxTQUFTOytCQUNFLG1CQUFtQjtrSUFRbkIsUUFBUTtzQkFBakIsTUFBTTtnQkFJRyxXQUFXO3NCQUFwQixNQUFNO2dCQUtNLFFBQVE7c0JBQXBCLEtBQUs7Z0JBUUksY0FBYztzQkFBdkIsTUFBTTtnQkFLRSxRQUFRO3NCQUFoQixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBTUcsWUFBWTtzQkFBcEIsS0FBSztnQkFPRyxVQUFVO3NCQUFsQixLQUFLO2dCQUtPLEtBQUs7c0JBQWpCLEtBQUs7Z0JBY08sVUFBVTtzQkFBdEIsS0FBSztnQkFPRyxVQUFVO3NCQUFsQixLQUFLO2dCQUtPLFVBQVU7c0JBQXRCLEtBQUs7Z0JBV2tCLFNBQVM7c0JBQWhDLFNBQVM7dUJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQWJzdHJhY3RDb250cm9sLFxuICBGb3JtQnVpbGRlcixcbiAgRm9ybUdyb3VwLFxuICBWYWxpZGF0b3JzLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBJb25JbnB1dCB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZGVidWcgfSBmcm9tICcuLi9sb2dnZXInO1xuaW1wb3J0IHsgZ2V0Rm9ybUZpZWxkT3JFcnJvciB9IGZyb20gJy4uL3V0aWxpdHknO1xuXG5jb25zdCBUQUcgPSAnSW5saW5lRWRpdG9yQ29tcG9uZW50JztcblxuZXhwb3J0IG5hbWVzcGFjZSBJbmxpbmVFZGl0b3JDb21wb25lbnQge1xuICBleHBvcnQgdHlwZSBJbnB1dE9wdGlvbnMgPVxuICAgIHwgVG9nZ2xlT3B0aW9uc1xuICAgIHwgTnVtYmVyT3B0aW9uc1xuICAgIHwgUGFzc3dvcmRPcHRpb25zXG4gICAgfCBUZXh0T3B0aW9ucztcblxuICBleHBvcnQgaW50ZXJmYWNlIFRvZ2dsZU9wdGlvbnMge1xuICAgIHR5cGU6ICd0b2dnbGUnO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBOdW1iZXJPcHRpb25zIHtcbiAgICBtaW4/OiBudW1iZXI7XG4gICAgbWF4PzogbnVtYmVyO1xuICAgIHR5cGU6ICdudW1iZXInO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBQYXNzd29yZE9wdGlvbnMge1xuICAgIHBhdHRlcm4/OiBSZWdFeHA7XG4gICAgbWluTGVuZ3RoPzogbnVtYmVyO1xuICAgIG1heExlbmd0aD86IG51bWJlcjtcbiAgICB0eXBlOiAncGFzc3dvcmQnO1xuICB9XG5cbiAgZXhwb3J0IGludGVyZmFjZSBUZXh0T3B0aW9ucyB7XG4gICAgcGF0dGVybj86IFJlZ0V4cDtcbiAgICBtaW5MZW5ndGg/OiBudW1iZXI7XG4gICAgbWF4TGVuZ3RoPzogbnVtYmVyO1xuICAgIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICAgIHR5cGU6ICd0ZXh0JztcbiAgfVxuXG4gIGV4cG9ydCBuYW1lc3BhY2UgU2VsZWN0T3B0aW9ucyB7XG4gICAgZXhwb3J0IHR5cGUgT3B0aW9ucyA9IHtcbiAgICAgIGtleTogYW55O1xuICAgICAgdGV4dDogc3RyaW5nO1xuICAgIH1bXTtcbiAgfVxufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd0YXAtaW5saW5lLWVkaXRvcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9pbmxpbmUtZWRpdG9yLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vaW5saW5lLWVkaXRvci5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBJbmxpbmVFZGl0b3JDb21wb25lbnQ8VmFsdWVUeXBlID0gYW55PiBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBFbWl0dGVyIHdoZW4gZm9ybSBpcyBzdWJtaXRcbiAgICovXG4gIEBPdXRwdXQoKSBvblN1Ym1pdDogRXZlbnRFbWl0dGVyPHtcbiAgICB0YXJnZXQ6IHsgdmFsdWU6IHN0cmluZyB9O1xuICB9PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KCkgdmFsdWVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZyB8IG51bWJlcj4oKTtcblxuICAvKipcbiAgICogRW5hYmxlL2Rpc2FibGUgZWRpdCBtb2RlXG4gICAqL1xuICBASW5wdXQoKSBzZXQgZWRpdE1vZGUodjogYm9vbGVhbikge1xuICAgIHRoaXMuX2VkaXRNb2RlID0gdjtcbiAgICB0aGlzLmZpZWxkLnNldFZhbHVlKHRoaXMuY3VycmVudFZhbHVlKTtcbiAgICBpZiAodikge1xuICAgICAgdGhpcy5lbmFibGVFZGl0TW9kZSgpO1xuICAgIH1cbiAgfVxuXG4gIEBPdXRwdXQoKSBlZGl0TW9kZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8Ym9vbGVhbj4oKTtcblxuICAvKipcbiAgICogVHJ1ZSBpZiBmaWVsZCBjYW4gYmUgZWRpdGVkXG4gICAqL1xuICBASW5wdXQoKSBlZGl0YWJsZSA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpIHVuaXRWYWx1ZT86IHN0cmluZztcblxuICAvKipcbiAgICogSW5wdXQgb3B0aW9uXG4gICAqIFlvdSBjYW4gZGVmaW5lZCBob3cgaW5wdXQgd2lsbCBiZSByZW5kZXJlZDogdGV4dCwgbnVtYmVyLCB0b2dnbGUsIHNlbGVjdCwgLi4uXG4gICAqL1xuICBASW5wdXQoKSBpbnB1dE9wdGlvbnM6IElubGluZUVkaXRvckNvbXBvbmVudC5JbnB1dE9wdGlvbnMgfCBhbnkgPSB7XG4gICAgdHlwZTogJ3RleHQnLFxuICB9O1xuXG4gIC8qKlxuICAgKiBBZGRpdGlvbmFsIHN0eWxlIGZvciB2YWx1ZVxuICAgKi9cbiAgQElucHV0KCkgdmFsdWVTdHlsZT86IHN0cmluZztcblxuICAvKipcbiAgICogU2V0IG9ic2VydmFibGUgdG8gc3Vic2NyaWJlIHRvIGdldCB2YWx1ZSB1cGRhdGVzXG4gICAqL1xuICBASW5wdXQoKSBzZXQgdmFsdWUob2JzOiBPYnNlcnZhYmxlPFZhbHVlVHlwZT4gfCBWYWx1ZVR5cGUpIHtcbiAgICB0aGlzLnZhbHVlU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIGlmIChvYnMgJiYgb2JzIGluc3RhbmNlb2YgT2JzZXJ2YWJsZSkge1xuICAgICAgdGhpcy52YWx1ZVN1YnNjcmlwdGlvbiA9IG9icy5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICAgIHRoaXMudXBkYXRlVmFsdWUodmFsdWUpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChvYnMgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy51cGRhdGVWYWx1ZShvYnMgYXMgVmFsdWVUeXBlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IHZhbHVlIHNuYXBzaG90XG4gICAqL1xuICBASW5wdXQoKSBzZXQgZm9yY2VWYWx1ZSh2YWx1ZTogYW55KSB7XG4gICAgdGhpcy51cGRhdGVWYWx1ZSh2YWx1ZSk7XG4gIH1cblxuICAvKipcbiAgICogRW5hYmxlL2Rpc2FibGUgbG9hZGVyIHdoZW4gc3VibWl0dGluZyBhIHZhbHVlXG4gICAqL1xuICBASW5wdXQoKSBzaG93TG9hZGVyID0gdHJ1ZTtcblxuICAvKipcbiAgICogU2V0IGZpZWxkIGVycm9yIG1lc3NhZ2VcbiAgICovXG4gIEBJbnB1dCgpIHNldCBmaWVsZEVycm9yKGVycjogRXJyb3IpIHtcbiAgICBpZiAoZXJyKSB7XG4gICAgICBkZWJ1ZyhUQUcsICdTZXQgZmllbGQgZXJyb3InLCBlcnIpO1xuICAgICAgdGhpcy5maWVsZC5zZXRFcnJvcnMoe1xuICAgICAgICBzdWJtaXQ6IGVyci5tZXNzYWdlLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmllbGQuc2V0RXJyb3JzKG51bGwpO1xuICAgIH1cbiAgfVxuXG4gIEBWaWV3Q2hpbGQoJ2lucHV0VmlldycpIGlucHV0VmlldyE6IElvbklucHV0O1xuXG4gIHByaXZhdGUgb3JpZ2luYWxWYWx1ZT86IFZhbHVlVHlwZTtcblxuICBwdWJsaWMgZm9ybTogRm9ybUdyb3VwO1xuICBwdWJsaWMgX2VkaXRNb2RlID0gZmFsc2U7XG5cbiAgY3VycmVudFZhbHVlOiBhbnk7XG4gIHZhbHVlU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuXG4gIGZpZWxkOiBBYnN0cmFjdENvbnRyb2w7XG5cbiAgcHJpdmF0ZSBkZXN0cm95ZWQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcbiAgICBwcml2YXRlIGNoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZlxuICApIHtcbiAgICB0aGlzLmZvcm0gPSBmb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICBmaWVsZDogWycnLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcbiAgICB9KTtcbiAgICB0aGlzLmZpZWxkID0gZ2V0Rm9ybUZpZWxkT3JFcnJvcih0aGlzLmZvcm0sICdmaWVsZCcpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5kZXN0cm95ZWQubmV4dCgpO1xuICAgIHRoaXMuZGVzdHJveWVkLmNvbXBsZXRlKCk7XG4gICAgaWYgKHRoaXMudmFsdWVTdWJzY3JpcHRpb24pIHtcbiAgICAgIHRoaXMudmFsdWVTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb25WYWx1ZVN1Ym1pdCgpIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuZmllbGQudmFsdWU7XG4gICAgaWYgKHRoaXMuZmllbGQuZXJyb3JzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMub25TdWJtaXQuZW1pdCh2YWx1ZSk7XG4gIH1cblxuICBpc0VkaXRlZCgpIHtcbiAgICByZXR1cm4gdGhpcy5maWVsZC52YWx1ZSAhPT0gdGhpcy5vcmlnaW5hbFZhbHVlO1xuICB9XG5cbiAgcmVzdG9yZVZhbHVlKCkge1xuICAgIHRoaXMuc2V0RmllbGRWYWx1ZSh0aGlzLm9yaWdpbmFsVmFsdWUpO1xuICB9XG5cbiAgc2V0RmllbGRWYWx1ZSh2YWx1ZTogVmFsdWVUeXBlIHwgdW5kZWZpbmVkKSB7XG4gICAgLy8gbGV0IGZvcm1hdHRlZFZhbHVlID0gdGhpcy5mb3JtYXR0ZXIoKVxuICAgIC8vIHRoaXMuaW5wdXRGb3JtYXR0ZXIgPyB0aGlzLl9pbmZvLmVkaXRGb3JtYXR0ZXIud3JpdGUodmFsdWUpIDogdmFsdWU7XG4gICAgdGhpcy5maWVsZC5zZXRWYWx1ZSh2YWx1ZSB8fCAnJyk7XG4gIH1cblxuICBhc3luYyBvblZhbHVlQ2xpY2soKSB7XG4gICAgaWYgKHRoaXMuZWRpdGFibGUpIHtcbiAgICAgIGF3YWl0IHRoaXMuZW5hYmxlRWRpdE1vZGUoKTtcbiAgICAgIHRoaXMuZWRpdE1vZGVDaGFuZ2UubmV4dCh0cnVlKTtcbiAgICB9XG4gIH1cblxuICBvbkNhbmNlbEVkaXQoKSB7XG4gICAgdGhpcy5fZWRpdE1vZGUgPSBmYWxzZTtcbiAgICB0aGlzLmVkaXRNb2RlQ2hhbmdlLm5leHQoZmFsc2UpO1xuICB9XG5cbiAgYXN5bmMgZW5hYmxlRWRpdE1vZGUoKSB7XG4gICAgdGhpcy5fZWRpdE1vZGUgPSB0cnVlO1xuICAgIGF3YWl0IHRoaXMuc2V0SW5wdXRGb2N1cygpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzZXRJbnB1dEZvY3VzKCkge1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICAgIGF3YWl0IHRoaXMuaW5wdXRWaWV3LnNldEZvY3VzKCk7XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZVZhbHVlKHZhbHVlOiBWYWx1ZVR5cGUpIHtcbiAgICB0aGlzLmN1cnJlbnRWYWx1ZSA9IHZhbHVlO1xuICAgIGlmICghdGhpcy5fZWRpdE1vZGUgJiYgdmFsdWUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5maWVsZC5zZXRWYWx1ZSh2YWx1ZSk7XG4gICAgfVxuICB9XG5cbiAgb25WYWx1ZUNoYW5nZShldmVudDogQ3VzdG9tRXZlbnQ8eyB2YWx1ZTogc3RyaW5nIH0+KSB7XG4gICAgY29uc3QgdmFsdWUgPSBldmVudC5kZXRhaWwudmFsdWU7XG4gICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgfVxufVxuIiwiPG5nLWNvbnRhaW5lciBbZm9ybUdyb3VwXT1cImZvcm1cIj5cbiAgPGlvbi1sYWJlbFxuICAgIChjbGljayk9XCJvblZhbHVlQ2xpY2soKVwiXG4gICAgKm5nSWY9XCIhX2VkaXRNb2RlXCJcbiAgICBbY2xhc3NdPVwiZWRpdGFibGUgPyAnY2VsbCBlZGl0b3ItdmFsdWUnIDogJ2VkaXRvci12YWx1ZSdcIlxuICA+XG4gICAgPHNwYW4gW25nU3R5bGVdPVwidmFsdWVTdHlsZVwiPnt7XG4gICAgICBjdXJyZW50VmFsdWUgfCB2YWx1ZU9yRGVmYXVsdDogJy0tLSdcbiAgICB9fTwvc3Bhbj5cbiAgICA8c3BhblxuICAgICAgKm5nSWY9XCJ1bml0VmFsdWVcIlxuICAgICAgW25nU3R5bGVdPVwidmFsdWVTdHlsZVwiXG4gICAgICBjbGFzcz1cInZhcmlhYmxlLXVuaXQgaW9uLW1hcmdpbi1zdGFydFwiXG4gICAgICA+e3sgdW5pdFZhbHVlIH19PC9zcGFuXG4gICAgPlxuICA8L2lvbi1sYWJlbD5cbiAgPGlvbi1pbnB1dFxuICAgICNpbnB1dFZpZXdcbiAgICAoa2V5ZG93bi5lbnRlcik9XCJvblZhbHVlU3VibWl0KClcIlxuICAgIChpb25DaGFuZ2UpPVwib25WYWx1ZUNoYW5nZSgkZXZlbnQpXCJcbiAgICBbY2xhc3NdPVwiZWRpdGFibGUgPyAnY2VsbCcgOiAnZWRpdG9yLXZhbHVlJ1wiXG4gICAgW25nU3R5bGVdPVwidmFsdWVTdHlsZVwiXG4gICAgKGtleWRvd24uZXNjYXBlKT1cIm9uQ2FuY2VsRWRpdCgpXCJcbiAgICAqbmdJZj1cIl9lZGl0TW9kZVwiXG4gICAgW21heF09XCJpbnB1dE9wdGlvbnMubWF4XCJcbiAgICBbbWF4bGVuZ3RoXT1cImlucHV0T3B0aW9ucy5tYXhMZW5ndGhcIlxuICAgIFttaW5dPVwiaW5wdXRPcHRpb25zLm1pblwiXG4gICAgW21pbmxlbmd0aF09XCJpbnB1dE9wdGlvbnMubWluTGVuZ3RoXCJcbiAgICBbcGF0dGVybl09XCJpbnB1dE9wdGlvbnMucGF0dGVyblwiXG4gICAgW3BsYWNlaG9sZGVyXT1cImlucHV0T3B0aW9ucy5wbGFjZWhvbGRlclwiXG4gICAgW3R5cGVdPVwiaW5wdXRPcHRpb25zLnR5cGVcIlxuICAgIGFwcEF1dG9Gb2N1c1xuICAgIGNsYXNzPVwiY2VsbElucHV0XCJcbiAgICBbZm9ybUNvbnRyb2xOYW1lXT1cIidmaWVsZCdcIlxuICA+PC9pb24taW5wdXQ+XG48L25nLWNvbnRhaW5lcj5cbiJdfQ==