@jsonforms/angular-material
Version:
Material Renderer Set for Angular module of JSON Forms
171 lines (167 loc) • 19.1 kB
JavaScript
/*
The MIT License
Copyright (c) 2017-2019 EclipseSource Munich
https://github.com/eclipsesource/jsonforms
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import { ChangeDetectionStrategy, Component, Input, } from '@angular/core';
import { JsonFormsAngularService, JsonFormsControl } from '@jsonforms/angular';
import { Actions, composeWithUi, isEnumControl, rankWith, } from '@jsonforms/core';
import { map, startWith } from 'rxjs/operators';
import * as i0 from "@angular/core";
import * as i1 from "@jsonforms/angular";
import * as i2 from "@angular/common";
import * as i3 from "@angular/material/form-field";
import * as i4 from "@angular/material/input";
import * as i5 from "@angular/forms";
import * as i6 from "@angular/material/core";
import * as i7 from "@angular/material/autocomplete";
/**
* To use this component you will need to add your own tester:
* <pre><code>
* ...
* export const AutocompleteControlRendererTester: RankedTester = rankWith(2, isEnumControl);
* ...
* </code></pre>
* Add the tester and renderer to JSONForms registry:
* <pre><code>
* ...
* { tester: AutocompleteControlRendererTester, renderer: AutocompleteControlRenderer },
* ...
* </code></pre>
* Furthermore you need to update your module.
* <pre><code>
* ...
* imports: [JsonFormsAngularMaterialModule, MatAutocompleteModule],
* declarations: [AutocompleteControlRenderer]
* ...
* </code></pre>
*
*/
export class AutocompleteControlRenderer extends JsonFormsControl {
options;
filteredOptions;
shouldFilter;
focused = false;
constructor(jsonformsService) {
super(jsonformsService);
}
getEventValue = (event) => event.target.value;
ngOnInit() {
super.ngOnInit();
this.shouldFilter = false;
this.filteredOptions = this.form.valueChanges.pipe(startWith(''), map((val) => this.filter(val)));
}
updateFilter(event) {
// ENTER
if (event.keyCode === 13) {
this.shouldFilter = false;
}
else {
this.shouldFilter = true;
}
}
onSelect(ev) {
const path = composeWithUi(this.uischema, this.path);
this.shouldFilter = false;
this.jsonFormsService.updateCore(Actions.update(path, () => ev.option.value));
this.triggerValidation();
}
filter(val) {
return (this.options || this.scopedSchema.enum || []).filter((option) => !this.shouldFilter ||
!val ||
option.toLowerCase().indexOf(val.toLowerCase()) === 0);
}
getOwnProps() {
return {
...super.getOwnProps(),
options: this.options,
};
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutocompleteControlRenderer, deps: [{ token: i1.JsonFormsAngularService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: AutocompleteControlRenderer, selector: "AutocompleteControlRenderer", inputs: { options: "options" }, usesInheritance: true, ngImport: i0, template: `
<mat-form-field [ngStyle]="{ display: hidden ? 'none' : '' }">
<mat-label>{{ label }}</mat-label>
<input
matInput
type="text"
(change)="onChange($event)"
[id]="id"
[formControl]="form"
[matAutocomplete]="auto"
(keydown)="updateFilter($event)"
(focus)="focused = true"
(focusout)="focused = false"
/>
<mat-autocomplete
autoActiveFirstOption
#auto="matAutocomplete"
(optionSelected)="onSelect($event)"
>
<mat-option
*ngFor="let option of filteredOptions | async"
[value]="option"
>
{{ option }}
</mat-option>
</mat-autocomplete>
<mat-hint *ngIf="shouldShowUnfocusedDescription() || focused">{{
description
}}</mat-hint>
<mat-error>{{ error }}</mat-error>
</mat-form-field>
`, isInline: true, styles: [":host{display:flex;flex-direction:row}mat-form-field{flex:1 1 auto}\n"], dependencies: [{ 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.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i3.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: i3.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "component", type: i6.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: i7.MatAutocomplete, selector: "mat-autocomplete", inputs: ["aria-label", "aria-labelledby", "displayWith", "autoActiveFirstOption", "autoSelectActiveOption", "requireSelection", "panelWidth", "disableRipple", "class", "hideSingleSelectionIndicator"], outputs: ["optionSelected", "opened", "closed", "optionActivated"], exportAs: ["matAutocomplete"] }, { kind: "directive", type: i7.MatAutocompleteTrigger, selector: "input[matAutocomplete], textarea[matAutocomplete]", inputs: ["matAutocomplete", "matAutocompletePosition", "matAutocompleteConnectedTo", "autocomplete", "matAutocompleteDisabled"], exportAs: ["matAutocompleteTrigger"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AutocompleteControlRenderer, decorators: [{
type: Component,
args: [{ selector: 'AutocompleteControlRenderer', template: `
<mat-form-field [ngStyle]="{ display: hidden ? 'none' : '' }">
<mat-label>{{ label }}</mat-label>
<input
matInput
type="text"
(change)="onChange($event)"
[id]="id"
[formControl]="form"
[matAutocomplete]="auto"
(keydown)="updateFilter($event)"
(focus)="focused = true"
(focusout)="focused = false"
/>
<mat-autocomplete
autoActiveFirstOption
#auto="matAutocomplete"
(optionSelected)="onSelect($event)"
>
<mat-option
*ngFor="let option of filteredOptions | async"
[value]="option"
>
{{ option }}
</mat-option>
</mat-autocomplete>
<mat-hint *ngIf="shouldShowUnfocusedDescription() || focused">{{
description
}}</mat-hint>
<mat-error>{{ error }}</mat-error>
</mat-form-field>
`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, styles: [":host{display:flex;flex-direction:row}mat-form-field{flex:1 1 auto}\n"] }]
}], ctorParameters: () => [{ type: i1.JsonFormsAngularService }], propDecorators: { options: [{
type: Input
}] } });
export const enumControlTester = rankWith(2, isEnumControl);
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0b2NvbXBsZXRlLnJlbmRlcmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYnJhcnkvY29udHJvbHMvYXV0b2NvbXBsZXRlLnJlbmRlcmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztFQXVCRTtBQUNGLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsU0FBUyxFQUNULEtBQUssR0FFTixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRSxPQUFPLEVBQ0wsT0FBTyxFQUNQLGFBQWEsRUFFYixhQUFhLEVBR2IsUUFBUSxHQUNULE1BQU0saUJBQWlCLENBQUM7QUFFekIsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7Ozs7O0FBRWhEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFpREgsTUFBTSxPQUFPLDJCQUNYLFNBQVEsZ0JBQWdCO0lBR2YsT0FBTyxDQUFXO0lBQzNCLGVBQWUsQ0FBdUI7SUFDdEMsWUFBWSxDQUFVO0lBQ3RCLE9BQU8sR0FBRyxLQUFLLENBQUM7SUFFaEIsWUFBWSxnQkFBeUM7UUFDbkQsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUNELGFBQWEsR0FBRyxDQUFDLEtBQVUsRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUM7SUFFbkQsUUFBUTtRQUNOLEtBQUssQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNqQixJQUFJLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztRQUMxQixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLElBQUksQ0FDaEQsU0FBUyxDQUFDLEVBQUUsQ0FBQyxFQUNiLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUMvQixDQUFDO0lBQ0osQ0FBQztJQUVELFlBQVksQ0FBQyxLQUFVO1FBQ3JCLFFBQVE7UUFDUixJQUFJLEtBQUssQ0FBQyxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLFlBQVksR0FBRyxLQUFLLENBQUM7UUFDNUIsQ0FBQzthQUFNLENBQUM7WUFDTixJQUFJLENBQUMsWUFBWSxHQUFHLElBQUksQ0FBQztRQUMzQixDQUFDO0lBQ0gsQ0FBQztJQUVELFFBQVEsQ0FBQyxFQUFnQztRQUN2QyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLFFBQTBCLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ3ZFLElBQUksQ0FBQyxZQUFZLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVLENBQzlCLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQzVDLENBQUM7UUFDRixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQsTUFBTSxDQUFDLEdBQVc7UUFDaEIsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUMxRCxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQ1QsQ0FBQyxJQUFJLENBQUMsWUFBWTtZQUNsQixDQUFDLEdBQUc7WUFDSixNQUFNLENBQUMsV0FBVyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FDeEQsQ0FBQztJQUNKLENBQUM7SUFDUyxXQUFXO1FBQ25CLE9BQU87WUFDTCxHQUFHLEtBQUssQ0FBQyxXQUFXLEVBQUU7WUFDdEIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1NBQ3RCLENBQUM7SUFDSixDQUFDO3dHQXREVSwyQkFBMkI7NEZBQTNCLDJCQUEyQiwwSEE5QzVCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBK0JUOzs0RkFlVSwyQkFBMkI7a0JBaER2QyxTQUFTOytCQUNFLDZCQUE2QixZQUM3Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQStCVCxtQkFZZ0IsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxLQUFLOzRGQU1SLE9BQU87c0JBQWYsS0FBSzs7QUFxRFIsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQWlCLFFBQVEsQ0FBQyxDQUFDLEVBQUUsYUFBYSxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICBUaGUgTUlUIExpY2Vuc2VcbiAgXG4gIENvcHlyaWdodCAoYykgMjAxNy0yMDE5IEVjbGlwc2VTb3VyY2UgTXVuaWNoXG4gIGh0dHBzOi8vZ2l0aHViLmNvbS9lY2xpcHNlc291cmNlL2pzb25mb3Jtc1xuICBcbiAgUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAgXG4gIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICBcbiAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICBUSEUgU09GVFdBUkUuXG4qL1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgdHlwZSB7IE1hdEF1dG9jb21wbGV0ZVNlbGVjdGVkRXZlbnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9hdXRvY29tcGxldGUnO1xuaW1wb3J0IHsgSnNvbkZvcm1zQW5ndWxhclNlcnZpY2UsIEpzb25Gb3Jtc0NvbnRyb2wgfSBmcm9tICdAanNvbmZvcm1zL2FuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQWN0aW9ucyxcbiAgY29tcG9zZVdpdGhVaSxcbiAgQ29udHJvbEVsZW1lbnQsXG4gIGlzRW51bUNvbnRyb2wsXG4gIE93blByb3BzT2ZDb250cm9sLFxuICBSYW5rZWRUZXN0ZXIsXG4gIHJhbmtXaXRoLFxufSBmcm9tICdAanNvbmZvcm1zL2NvcmUnO1xuaW1wb3J0IHR5cGUgeyBPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIHN0YXJ0V2l0aCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuLyoqXG4gKiBUbyB1c2UgdGhpcyBjb21wb25lbnQgeW91IHdpbGwgbmVlZCB0byBhZGQgeW91ciBvd24gdGVzdGVyOlxuICogPHByZT48Y29kZT5cbiAqIC4uLlxuICogZXhwb3J0IGNvbnN0IEF1dG9jb21wbGV0ZUNvbnRyb2xSZW5kZXJlclRlc3RlcjogUmFua2VkVGVzdGVyID0gcmFua1dpdGgoMiwgaXNFbnVtQ29udHJvbCk7XG4gKiAuLi5cbiAqIDwvY29kZT48L3ByZT5cbiAqIEFkZCB0aGUgdGVzdGVyIGFuZCByZW5kZXJlciB0byBKU09ORm9ybXMgcmVnaXN0cnk6XG4gKiA8cHJlPjxjb2RlPlxuICogLi4uXG4gKiB7IHRlc3RlcjogQXV0b2NvbXBsZXRlQ29udHJvbFJlbmRlcmVyVGVzdGVyLCByZW5kZXJlcjogQXV0b2NvbXBsZXRlQ29udHJvbFJlbmRlcmVyIH0sXG4gKiAuLi5cbiAqIDwvY29kZT48L3ByZT5cbiAqIEZ1cnRoZXJtb3JlIHlvdSBuZWVkIHRvIHVwZGF0ZSB5b3VyIG1vZHVsZS5cbiAqIDxwcmU+PGNvZGU+XG4gKiAuLi5cbiAqIGltcG9ydHM6IFtKc29uRm9ybXNBbmd1bGFyTWF0ZXJpYWxNb2R1bGUsIE1hdEF1dG9jb21wbGV0ZU1vZHVsZV0sXG4gKiBkZWNsYXJhdGlvbnM6IFtBdXRvY29tcGxldGVDb250cm9sUmVuZGVyZXJdXG4gKiAuLi5cbiAqIDwvY29kZT48L3ByZT5cbiAqXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ0F1dG9jb21wbGV0ZUNvbnRyb2xSZW5kZXJlcicsXG4gIHRlbXBsYXRlOiBgXG4gICAgPG1hdC1mb3JtLWZpZWxkIFtuZ1N0eWxlXT1cInsgZGlzcGxheTogaGlkZGVuID8gJ25vbmUnIDogJycgfVwiPlxuICAgICAgPG1hdC1sYWJlbD57eyBsYWJlbCB9fTwvbWF0LWxhYmVsPlxuICAgICAgPGlucHV0XG4gICAgICAgIG1hdElucHV0XG4gICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgKGNoYW5nZSk9XCJvbkNoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgW2lkXT1cImlkXCJcbiAgICAgICAgW2Zvcm1Db250cm9sXT1cImZvcm1cIlxuICAgICAgICBbbWF0QXV0b2NvbXBsZXRlXT1cImF1dG9cIlxuICAgICAgICAoa2V5ZG93bik9XCJ1cGRhdGVGaWx0ZXIoJGV2ZW50KVwiXG4gICAgICAgIChmb2N1cyk9XCJmb2N1c2VkID0gdHJ1ZVwiXG4gICAgICAgIChmb2N1c291dCk9XCJmb2N1c2VkID0gZmFsc2VcIlxuICAgICAgLz5cbiAgICAgIDxtYXQtYXV0b2NvbXBsZXRlXG4gICAgICAgIGF1dG9BY3RpdmVGaXJzdE9wdGlvblxuICAgICAgICAjYXV0bz1cIm1hdEF1dG9jb21wbGV0ZVwiXG4gICAgICAgIChvcHRpb25TZWxlY3RlZCk9XCJvblNlbGVjdCgkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPG1hdC1vcHRpb25cbiAgICAgICAgICAqbmdGb3I9XCJsZXQgb3B0aW9uIG9mIGZpbHRlcmVkT3B0aW9ucyB8IGFzeW5jXCJcbiAgICAgICAgICBbdmFsdWVdPVwib3B0aW9uXCJcbiAgICAgICAgPlxuICAgICAgICAgIHt7IG9wdGlvbiB9fVxuICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICA8L21hdC1hdXRvY29tcGxldGU+XG4gICAgICA8bWF0LWhpbnQgKm5nSWY9XCJzaG91bGRTaG93VW5mb2N1c2VkRGVzY3JpcHRpb24oKSB8fCBmb2N1c2VkXCI+e3tcbiAgICAgICAgZGVzY3JpcHRpb25cbiAgICAgIH19PC9tYXQtaGludD5cbiAgICAgIDxtYXQtZXJyb3I+e3sgZXJyb3IgfX08L21hdC1lcnJvcj5cbiAgICA8L21hdC1mb3JtLWZpZWxkPlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICA6aG9zdCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiByb3c7XG4gICAgICB9XG4gICAgICBtYXQtZm9ybS1maWVsZCB7XG4gICAgICAgIGZsZXg6IDEgMSBhdXRvO1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiBmYWxzZSxcbn0pXG5leHBvcnQgY2xhc3MgQXV0b2NvbXBsZXRlQ29udHJvbFJlbmRlcmVyXG4gIGV4dGVuZHMgSnNvbkZvcm1zQ29udHJvbFxuICBpbXBsZW1lbnRzIE9uSW5pdFxue1xuICBASW5wdXQoKSBvcHRpb25zOiBzdHJpbmdbXTtcbiAgZmlsdGVyZWRPcHRpb25zOiBPYnNlcnZhYmxlPHN0cmluZ1tdPjtcbiAgc2hvdWxkRmlsdGVyOiBib29sZWFuO1xuICBmb2N1c2VkID0gZmFsc2U7XG5cbiAgY29uc3RydWN0b3IoanNvbmZvcm1zU2VydmljZTogSnNvbkZvcm1zQW5ndWxhclNlcnZpY2UpIHtcbiAgICBzdXBlcihqc29uZm9ybXNTZXJ2aWNlKTtcbiAgfVxuICBnZXRFdmVudFZhbHVlID0gKGV2ZW50OiBhbnkpID0+IGV2ZW50LnRhcmdldC52YWx1ZTtcblxuICBuZ09uSW5pdCgpIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgIHRoaXMuc2hvdWxkRmlsdGVyID0gZmFsc2U7XG4gICAgdGhpcy5maWx0ZXJlZE9wdGlvbnMgPSB0aGlzLmZvcm0udmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICBzdGFydFdpdGgoJycpLFxuICAgICAgbWFwKCh2YWwpID0+IHRoaXMuZmlsdGVyKHZhbCkpXG4gICAgKTtcbiAgfVxuXG4gIHVwZGF0ZUZpbHRlcihldmVudDogYW55KSB7XG4gICAgLy8gRU5URVJcbiAgICBpZiAoZXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcbiAgICAgIHRoaXMuc2hvdWxkRmlsdGVyID0gZmFsc2U7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2hvdWxkRmlsdGVyID0gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBvblNlbGVjdChldjogTWF0QXV0b2NvbXBsZXRlU2VsZWN0ZWRFdmVudCkge1xuICAgIGNvbnN0IHBhdGggPSBjb21wb3NlV2l0aFVpKHRoaXMudWlzY2hlbWEgYXMgQ29udHJvbEVsZW1lbnQsIHRoaXMucGF0aCk7XG4gICAgdGhpcy5zaG91bGRGaWx0ZXIgPSBmYWxzZTtcbiAgICB0aGlzLmpzb25Gb3Jtc1NlcnZpY2UudXBkYXRlQ29yZShcbiAgICAgIEFjdGlvbnMudXBkYXRlKHBhdGgsICgpID0+IGV2Lm9wdGlvbi52YWx1ZSlcbiAgICApO1xuICAgIHRoaXMudHJpZ2dlclZhbGlkYXRpb24oKTtcbiAgfVxuXG4gIGZpbHRlcih2YWw6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgICByZXR1cm4gKHRoaXMub3B0aW9ucyB8fCB0aGlzLnNjb3BlZFNjaGVtYS5lbnVtIHx8IFtdKS5maWx0ZXIoXG4gICAgICAob3B0aW9uKSA9PlxuICAgICAgICAhdGhpcy5zaG91bGRGaWx0ZXIgfHxcbiAgICAgICAgIXZhbCB8fFxuICAgICAgICBvcHRpb24udG9Mb3dlckNhc2UoKS5pbmRleE9mKHZhbC50b0xvd2VyQ2FzZSgpKSA9PT0gMFxuICAgICk7XG4gIH1cbiAgcHJvdGVjdGVkIGdldE93blByb3BzKCk6IE93blByb3BzT2ZBdXRvQ29tcGxldGUge1xuICAgIHJldHVybiB7XG4gICAgICAuLi5zdXBlci5nZXRPd25Qcm9wcygpLFxuICAgICAgb3B0aW9uczogdGhpcy5vcHRpb25zLFxuICAgIH07XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IGVudW1Db250cm9sVGVzdGVyOiBSYW5rZWRUZXN0ZXIgPSByYW5rV2l0aCgyLCBpc0VudW1Db250cm9sKTtcblxuaW50ZXJmYWNlIE93blByb3BzT2ZBdXRvQ29tcGxldGUgZXh0ZW5kcyBPd25Qcm9wc09mQ29udHJvbCB7XG4gIG9wdGlvbnM6IHN0cmluZ1tdO1xufVxuIl19