UNPKG

@jsonforms/angular-material

Version:

Material Renderer Set for Angular module of JSON Forms

336 lines (326 loc) 32.5 kB
/* 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 startCase from 'lodash/startCase'; import { Component, Pipe } from '@angular/core'; import { JsonFormsAngularService, JsonFormsArrayControl, } from '@jsonforms/angular'; import { createDefaultValue, deriveTypes, encode, isObjectArrayControl, isPrimitiveArrayControl, mapDispatchToArrayControlProps, or, Paths, rankWith, setReadonly, } from '@jsonforms/core'; import * as i0 from "@angular/core"; import * as i1 from "@jsonforms/angular"; import * as i2 from "@angular/common"; import * as i3 from "@angular/material/button"; import * as i4 from "@angular/material/icon"; import * as i5 from "@angular/material/table"; import * as i6 from "@angular/material/tooltip"; export class TableRenderer extends JsonFormsArrayControl { detailUiSchema; displayedColumns; items; columnsToIgnore = ['array', 'object']; addItem; moveItemUp; moveItemDown; removeItems; translations = {}; constructor(jsonformsService) { super(jsonformsService); } trackElement(index, _element) { return index ? index : null; } mapAdditionalProps(props) { this.items = this.generateCells(props.schema, props.path); this.displayedColumns = this.items.map((item) => item.property); if (this.isEnabled()) { this.displayedColumns.push('action'); } this.translations = props.translations; } remove(index) { this.removeItems(this.propsPath, [index])(); } add() { this.addItem(this.propsPath, createDefaultValue(this.scopedSchema, this.rootSchema))(); } up(index) { this.moveItemUp(this.propsPath, index)(); } down(index) { this.moveItemDown(this.propsPath, index)(); } ngOnInit() { super.ngOnInit(); const { addItem, removeItems, moveUp, moveDown } = mapDispatchToArrayControlProps(this.jsonFormsService.updateCore.bind(this.jsonFormsService)); this.addItem = addItem; this.moveItemUp = moveUp; this.moveItemDown = moveDown; this.removeItems = removeItems; } generateCells = (schema, rowPath) => { if (schema.type === 'object') { return this.getValidColumnProps(schema).map((prop) => { const encProp = encode(prop); const uischema = controlWithoutLabel(`#/properties/${encProp}`); if (!this.isEnabled()) { setReadonly(uischema); } return { property: prop, header: startCase(prop), props: { schema: schema, uischema, path: rowPath, }, }; }); } // needed to correctly render input control for multi attributes return [ { property: 'DUMMY', header: this.label, props: { schema: schema, uischema: controlWithoutLabel(`#`), path: rowPath, }, }, ]; }; getValidColumnProps = (scopedSchema) => { if (scopedSchema.type === 'object') { return Object.keys(scopedSchema.properties).filter((prop) => { const types = deriveTypes(scopedSchema.properties[prop]); if (types.length > 1) { return false; } return this.columnsToIgnore.indexOf(types[0]) === -1; }); } // primitives return ['']; }; static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: TableRenderer, deps: [{ token: i1.JsonFormsAngularService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.10", type: TableRenderer, selector: "TableRenderer", usesInheritance: true, ngImport: i0, template: ` <div class="table-container"> <table mat-table [dataSource]="data" class="mat-elevation-z8" [trackBy]="trackElement" > <ng-container matColumnDef="action" stickyEnd> <tr> <th mat-header-cell *matHeaderCellDef [ngClass]="{ 'sort-column': uischema?.options?.showSortButtons }" > <button mat-button color="primary" (click)="add()" [disabled]="!isEnabled()" [matTooltip]="translations.addTooltip" > <mat-icon>add</mat-icon> </button> </th> </tr> <tr> <td [ngClass]="{ 'sort-column': uischema?.options?.showSortButtons }" mat-cell *matCellDef=" let row; let i = index; let first = first; let last = last " > <button *ngIf="uischema?.options?.showSortButtons" class="item-up" mat-icon-button [disabled]="first" (click)="up(i)" [matTooltip]="translations.upAriaLabel" matTooltipPosition="right" > <mat-icon>arrow_upward</mat-icon> </button> <button *ngIf="uischema?.options?.showSortButtons" class="item-down" mat-icon-button [disabled]="last" (click)="down(i)" [matTooltip]="translations.downAriaLabel" matTooltipPosition="right" > <mat-icon>arrow_downward</mat-icon> </button> <button mat-icon-button color="warn" (click)="remove(i)" [disabled]="!isEnabled()" matTooltipPosition="right" [matTooltip]="translations.removeTooltip" > <mat-icon>delete</mat-icon> </button> </td> </tr> <tr></tr ></ng-container> <ng-container *ngFor="let item of items" matColumnDef="{{ item.property }}" > <th mat-header-cell *matHeaderCellDef>{{ item.header }}</th> <td mat-cell *matCellDef="let index = index"> <jsonforms-outlet [renderProps]="index | getProps : item.props" ></jsonforms-outlet> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> </table> </div> `, isInline: true, styles: ["table{width:100%}\n", ".cdk-column-action{width:15%}\n", ".sort-column{min-width:12vw}\n", ".table-container{max-width:100%;overflow:auto}\n"], dependencies: [{ kind: "directive", type: i0.forwardRef(() => i2.NgClass), selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i0.forwardRef(() => i2.NgForOf), selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i0.forwardRef(() => i2.NgIf), selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i0.forwardRef(() => i1.JsonFormsOutlet), selector: "jsonforms-outlet", inputs: ["renderProps"] }, { kind: "component", type: i0.forwardRef(() => i3.MatButton), selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i0.forwardRef(() => i3.MatIconButton), selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i0.forwardRef(() => i4.MatIcon), selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i0.forwardRef(() => i5.MatTable), selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i0.forwardRef(() => i5.MatHeaderCellDef), selector: "[matHeaderCellDef]" }, { kind: "directive", type: i0.forwardRef(() => i5.MatHeaderRowDef), selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i0.forwardRef(() => i5.MatColumnDef), selector: "[matColumnDef]", inputs: ["matColumnDef"] }, { kind: "directive", type: i0.forwardRef(() => i5.MatCellDef), selector: "[matCellDef]" }, { kind: "directive", type: i0.forwardRef(() => i5.MatRowDef), selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i0.forwardRef(() => i5.MatHeaderCell), selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i0.forwardRef(() => i5.MatCell), selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i0.forwardRef(() => i5.MatHeaderRow), selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i0.forwardRef(() => i5.MatRow), selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i0.forwardRef(() => i6.MatTooltip), selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i0.forwardRef(() => GetProps), name: "getProps" }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: TableRenderer, decorators: [{ type: Component, args: [{ selector: 'TableRenderer', template: ` <div class="table-container"> <table mat-table [dataSource]="data" class="mat-elevation-z8" [trackBy]="trackElement" > <ng-container matColumnDef="action" stickyEnd> <tr> <th mat-header-cell *matHeaderCellDef [ngClass]="{ 'sort-column': uischema?.options?.showSortButtons }" > <button mat-button color="primary" (click)="add()" [disabled]="!isEnabled()" [matTooltip]="translations.addTooltip" > <mat-icon>add</mat-icon> </button> </th> </tr> <tr> <td [ngClass]="{ 'sort-column': uischema?.options?.showSortButtons }" mat-cell *matCellDef=" let row; let i = index; let first = first; let last = last " > <button *ngIf="uischema?.options?.showSortButtons" class="item-up" mat-icon-button [disabled]="first" (click)="up(i)" [matTooltip]="translations.upAriaLabel" matTooltipPosition="right" > <mat-icon>arrow_upward</mat-icon> </button> <button *ngIf="uischema?.options?.showSortButtons" class="item-down" mat-icon-button [disabled]="last" (click)="down(i)" [matTooltip]="translations.downAriaLabel" matTooltipPosition="right" > <mat-icon>arrow_downward</mat-icon> </button> <button mat-icon-button color="warn" (click)="remove(i)" [disabled]="!isEnabled()" matTooltipPosition="right" [matTooltip]="translations.removeTooltip" > <mat-icon>delete</mat-icon> </button> </td> </tr> <tr></tr ></ng-container> <ng-container *ngFor="let item of items" matColumnDef="{{ item.property }}" > <th mat-header-cell *matHeaderCellDef>{{ item.header }}</th> <td mat-cell *matCellDef="let index = index"> <jsonforms-outlet [renderProps]="index | getProps : item.props" ></jsonforms-outlet> </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> </table> </div> `, styles: ["table{width:100%}\n", ".cdk-column-action{width:15%}\n", ".sort-column{min-width:12vw}\n", ".table-container{max-width:100%;overflow:auto}\n"] }] }], ctorParameters: () => [{ type: i1.JsonFormsAngularService }] }); export const TableRendererTester = rankWith(3, or(isObjectArrayControl, isPrimitiveArrayControl)); export const controlWithoutLabel = (scope) => ({ type: 'Control', scope: scope, label: false, }); export class GetProps { transform(index, props) { const rowPath = Paths.compose(props.path, `${index}`); return { schema: props.schema, uischema: props.uischema, path: rowPath, }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: GetProps, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "17.3.10", ngImport: i0, type: GetProps, name: "getProps" }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.10", ngImport: i0, type: GetProps, decorators: [{ type: Pipe, args: [{ name: 'getProps' }] }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUucmVuZGVyZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGlicmFyeS9vdGhlci90YWJsZS5yZW5kZXJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUF1QkU7QUFDRixPQUFPLFNBQVMsTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFVLElBQUksRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDdkUsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixxQkFBcUIsR0FDdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBSUwsa0JBQWtCLEVBQ2xCLFdBQVcsRUFDWCxNQUFNLEVBQ04sb0JBQW9CLEVBQ3BCLHVCQUF1QixFQUV2Qiw4QkFBOEIsRUFDOUIsRUFBRSxFQUVGLEtBQUssRUFFTCxRQUFRLEVBQ1IsV0FBVyxHQUVaLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7O0FBdUd6QixNQUFNLE9BQU8sYUFBYyxTQUFRLHFCQUFxQjtJQUN0RCxjQUFjLENBQWtCO0lBQ2hDLGdCQUFnQixDQUFXO0lBQzNCLEtBQUssQ0FBc0I7SUFDbEIsZUFBZSxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQy9DLE9BQU8sQ0FBMkM7SUFDbEQsVUFBVSxDQUE4QztJQUN4RCxZQUFZLENBQThDO0lBQzFELFdBQVcsQ0FBbUQ7SUFDOUQsWUFBWSxHQUFzQixFQUFFLENBQUM7SUFFckMsWUFBWSxnQkFBeUM7UUFDbkQsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUNELFlBQVksQ0FBQyxLQUFhLEVBQUUsUUFBYTtRQUN2QyxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDOUIsQ0FBQztJQUNELGtCQUFrQixDQUNoQixLQUE4RDtRQUU5RCxJQUFJLENBQUMs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QyxDQUNsRCxDQUFDO0FBUUYsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxLQUFhLEVBQWtCLEVBQUUsQ0FBQyxDQUFDO0lBQ3JFLElBQUksRUFBRSxTQUFTO0lBQ2YsS0FBSyxFQUFFLEtBQUs7SUFDWixLQUFLLEVBQUUsS0FBSztDQUNiLENBQUMsQ0FBQztBQUdILE1BQU0sT0FBTyxRQUFRO0lBQ25CLFNBQVMsQ0FBQyxLQUFhLEVBQUUsS0FBeUI7UUFDaEQsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUN0RCxPQUFPO1lBQ0wsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1lBQ3BCLFFBQVEsRUFBRSxLQUFLLENBQUMsUUFBUTtZQUN4QixJQUFJLEVBQUUsT0FBTztTQUNkLENBQUM7SUFDSixDQUFDO3dHQVJVLFFBQVE7c0dBQVIsUUFBUTs7NEZBQVIsUUFBUTtrQkFEcEIsSUFBSTttQkFBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICBUaGUgTUlUIExpY2Vuc2VcbiAgXG4gIENvcHlyaWdodCAoYykgMjAxNy0yMDE5IEVjbGlwc2VTb3VyY2UgTXVuaWNoXG4gIGh0dHBzOi8vZ2l0aHViLmNvbS9lY2xpcHNlc291cmNlL2pzb25mb3Jtc1xuICBcbiAgUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAgXG4gIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICBcbiAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICBUSEUgU09GVFdBUkUuXG4qL1xuaW1wb3J0IHN0YXJ0Q2FzZSBmcm9tICdsb2Rhc2gvc3RhcnRDYXNlJztcbmltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBQaXBlLCBQaXBlVHJhbnNmb3JtIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBKc29uRm9ybXNBbmd1bGFyU2VydmljZSxcbiAgSnNvbkZvcm1zQXJyYXlDb250cm9sLFxufSBmcm9tICdAanNvbmZvcm1zL2FuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQXJyYXlDb250cm9sUHJvcHMsXG4gIEFycmF5VHJhbnNsYXRpb25zLFxuICBDb250cm9sRWxlbWVudCxcbiAgY3JlYXRlRGVmYXVsdFZhbHVlLFxuICBkZXJpdmVUeXBlcyxcbiAgZW5jb2RlLFxuICBpc09iamVjdEFycmF5Q29udHJvbCxcbiAgaXNQcmltaXRpdmVBcnJheUNvbnRyb2wsXG4gIEpzb25TY2hlbWEsXG4gIG1hcERpc3BhdGNoVG9BcnJheUNvbnRyb2xQcm9wcyxcbiAgb3IsXG4gIE93blByb3BzT2ZSZW5kZXJlcixcbiAgUGF0aHMsXG4gIFJhbmtlZFRlc3RlcixcbiAgcmFua1dpdGgsXG4gIHNldFJlYWRvbmx5LFxuICBVSVNjaGVtYUVsZW1lbnQsXG59IGZyb20gJ0Bqc29uZm9ybXMvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ1RhYmxlUmVuZGVyZXInLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1jb250YWluZXJcIj5cbiAgICAgIDx0YWJsZVxuICAgICAgICBtYXQtdGFibGVcbiAgICAgICAgW2RhdGFTb3VyY2VdPVwiZGF0YVwiXG4gICAgICAgIGNsYXNzPVwibWF0LWVsZXZhdGlvbi16OFwiXG4gICAgICAgIFt0cmFja0J5XT1cInRyYWNrRWxlbWVudFwiXG4gICAgICA+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYWN0aW9uXCIgc3RpY2t5RW5kPlxuICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgIDx0aFxuICAgICAgICAgICAgICBtYXQtaGVhZGVyLWNlbGxcbiAgICAgICAgICAgICAgKm1hdEhlYWRlckNlbGxEZWZcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnc29ydC1jb2x1bW4nOiB1aXNjaGVtYT8ub3B0aW9ucz8uc2hvd1NvcnRCdXR0b25zIH1cIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImFkZCgpXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWlzRW5hYmxlZCgpXCJcbiAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJ0cmFuc2xhdGlvbnMuYWRkVG9vbHRpcFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+YWRkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L3RoPlxuICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPHRyPlxuICAgICAgICAgICAgPHRkXG4gICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ3NvcnQtY29sdW1uJzogdWlzY2hlbWE/Lm9wdGlvbnM/LnNob3dTb3J0QnV0dG9ucyB9XCJcbiAgICAgICAgICAgICAgbWF0LWNlbGxcbiAgICAgICAgICAgICAgKm1hdENlbGxEZWY9XCJcbiAgICAgICAgICAgICAgICBsZXQgcm93O1xuICAgICAgICAgICAgICAgIGxldCBpID0gaW5kZXg7XG4gICAgICAgICAgICAgICAgbGV0IGZpcnN0ID0gZmlyc3Q7XG4gICAgICAgICAgICAgICAgbGV0IGxhc3QgPSBsYXN0XG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAqbmdJZj1cInVpc2NoZW1hPy5vcHRpb25zPy5zaG93U29ydEJ1dHRvbnNcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiaXRlbS11cFwiXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImZpcnN0XCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwidXAoaSlcIlxuICAgICAgICAgICAgICAgIFttYXRUb29sdGlwXT1cInRyYW5zbGF0aW9ucy51cEFyaWFMYWJlbFwiXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcFBvc2l0aW9uPVwicmlnaHRcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmFycm93X3Vwd2FyZDwvbWF0LWljb24+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJ1aXNjaGVtYT8ub3B0aW9ucz8uc2hvd1NvcnRCdXR0b25zXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIml0ZW0tZG93blwiXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImxhc3RcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJkb3duKGkpXCJcbiAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJ0cmFuc2xhdGlvbnMuZG93bkFyaWFMYWJlbFwiXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcFBvc2l0aW9uPVwicmlnaHRcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmFycm93X2Rvd253YXJkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJyZW1vdmUoaSlcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhaXNFbmFibGVkKClcIlxuICAgICAgICAgICAgICAgIG1hdFRvb2x0aXBQb3NpdGlvbj1cInJpZ2h0XCJcbiAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJ0cmFuc2xhdGlvbnMucmVtb3ZlVG9vbHRpcFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L3RkPlxuICAgICAgICAgIDwvdHI+XG5cbiAgICAgICAgICA8dHI+PC90clxuICAgICAgICA+PC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zXCJcbiAgICAgICAgICBtYXRDb2x1bW5EZWY9XCJ7eyBpdGVtLnByb3BlcnR5IH19XCJcbiAgICAgICAgPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+e3sgaXRlbS5oZWFkZXIgfX08L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBpbmRleCA9IGluZGV4XCI+XG4gICAgICAgICAgICA8anNvbmZvcm1zLW91dGxldFxuICAgICAgICAgICAgICBbcmVuZGVyUHJvcHNdPVwiaW5kZXggfCBnZXRQcm9wcyA6IGl0ZW0ucHJvcHNcIlxuICAgICAgICAgICAgPjwvanNvbmZvcm1zLW91dGxldD5cbiAgICAgICAgICA8L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnNcIj48L3RyPlxuICAgICAgICA8dHIgbWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1uc1wiPjwvdHI+XG4gICAgICA8L3RhYmxlPlxuICAgIDwvZGl2PlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICAndGFibGUge3dpZHRoOiAxMDAlO30nLFxuICAgICcuY2RrLWNvbHVtbi1hY3Rpb24geyB3aWR0aDogMTUlO30nLFxuICAgICcuc29ydC1jb2x1bW4geyBtaW4td2lkdGg6IDEydnc7fScsXG4gICAgJy50YWJsZS1jb250YWluZXIge21heC13aWR0aDogMTAwJTsgb3ZlcmZsb3c6IGF1dG87fScsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIFRhYmxlUmVuZGVyZXIgZXh0ZW5kcyBKc29uRm9ybXNBcnJheUNvbnRyb2wgaW1wbGVtZW50cyBPbkluaXQge1xuICBkZXRhaWxVaVNjaGVtYTogVUlTY2hlbWFFbGVtZW50O1xuICBkaXNwbGF5ZWRDb2x1bW5zOiBzdHJpbmdbXTtcbiAgaXRlbXM6IENvbHVtbkRlc2NyaXB0aW9uW107XG4gIHJlYWRvbmx5IGNvbHVtbnNUb0lnbm9yZSA9IFsnYXJyYXknLCAnb2JqZWN0J107XG4gIGFkZEl0ZW06IChwYXRoOiBzdHJpbmcsIHZhbHVlOiBhbnkpID0+ICgpID0+IHZvaWQ7XG4gIG1vdmVJdGVtVXA6IChwYXRoOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+ICgpID0+IHZvaWQ7XG4gIG1vdmVJdGVtRG93bjogKHBhdGg6IHN0cmluZywgaW5kZXg6IG51bWJlcikgPT4gKCkgPT4gdm9pZDtcbiAgcmVtb3ZlSXRlbXM6IChwYXRoOiBzdHJpbmcsIHRvRGVsZXRlOiBudW1iZXJbXSkgPT4gKCkgPT4gdm9pZDtcbiAgdHJhbnNsYXRpb25zOiBBcnJheVRyYW5zbGF0aW9ucyA9IHt9O1xuXG4gIGNvbnN0cnVjdG9yKGpzb25mb3Jtc1NlcnZpY2U6IEpzb25Gb3Jtc0FuZ3VsYXJTZXJ2aWNlKSB7XG4gICAgc3VwZXIoanNvbmZvcm1zU2VydmljZSk7XG4gIH1cbiAgdHJhY2tFbGVtZW50KGluZGV4OiBudW1iZXIsIF9lbGVtZW50OiBhbnkpIHtcbiAgICByZXR1cm4gaW5kZXggPyBpbmRleCA6IG51bGw7XG4gIH1cbiAgbWFwQWRkaXRpb25hbFByb3BzKFxuICAgIHByb3BzOiBBcnJheUNvbnRyb2xQcm9wcyAmIHsgdHJhbnNsYXRpb25zOiBBcnJheVRyYW5zbGF0aW9ucyB9XG4gICkge1xuICAgIHRoaXMuaXRlbXMgPSB0aGlzLmdlbmVyYXRlQ2VsbHMocHJvcHMuc2NoZW1hLCBwcm9wcy5wYXRoKTtcbiAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMgPSB0aGlzLml0ZW1zLm1hcCgoaXRlbSkgPT4gaXRlbS5wcm9wZXJ0eSk7XG4gICAgaWYgKHRoaXMuaXNFbmFibGVkKCkpIHtcbiAgICAgIHRoaXMuZGlzcGxheWVkQ29sdW1ucy5wdXNoKCdhY3Rpb24nKTtcbiAgICB9XG4gICAgdGhpcy50cmFuc2xhdGlvbnMgPSBwcm9wcy50cmFuc2xhdGlvbnM7XG4gIH1cblxuICByZW1vdmUoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMucmVtb3ZlSXRlbXModGhpcy5wcm9wc1BhdGgsIFtpbmRleF0pKCk7XG4gIH1cbiAgYWRkKCk6IHZvaWQge1xuICAgIHRoaXMuYWRkSXRlbShcbiAgICAgIHRoaXMucHJvcHNQYXRoLFxuICAgICAgY3JlYXRlRGVmYXVsdFZhbHVlKHRoaXMuc2NvcGVkU2NoZW1hLCB0aGlzLnJvb3RTY2hlbWEpXG4gICAgKSgpO1xuICB9XG4gIHVwKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLm1vdmVJdGVtVXAodGhpcy5wcm9wc1BhdGgsIGluZGV4KSgpO1xuICB9XG4gIGRvd24oaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMubW92ZUl0ZW1Eb3duKHRoaXMucHJvcHNQYXRoLCBpbmRleCkoKTtcbiAgfVxuICBuZ09uSW5pdCgpIHtcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuXG4gICAgY29uc3QgeyBhZGRJdGVtLCByZW1vdmVJdGVtcywgbW92ZVVwLCBtb3ZlRG93biB9ID1cbiAgICAgIG1hcERpc3BhdGNoVG9BcnJheUNvbnRyb2xQcm9wcyhcbiAgICAgICAgdGhpcy5qc29uRm9ybXNTZXJ2aWNlLnVwZGF0ZUNvcmUuYmluZCh0aGlzLmpzb25Gb3Jtc1NlcnZpY2UpXG4gICAgICApO1xuICAgIHRoaXMuYWRkSXRlbSA9IGFkZEl0ZW07XG4gICAgdGhpcy5tb3ZlSXRlbVVwID0gbW92ZVVwO1xuICAgIHRoaXMubW92ZUl0ZW1Eb3duID0gbW92ZURvd247XG4gICAgdGhpcy5yZW1vdmVJdGVtcyA9IHJlbW92ZUl0ZW1zO1xuICB9XG5cbiAgZ2VuZXJhdGVDZWxscyA9IChcbiAgICBzY2hlbWE6IEpzb25TY2hlbWEsXG4gICAgcm93UGF0aDogc3RyaW5nXG4gICk6IENvbHVtbkRlc2NyaXB0aW9uW10gPT4ge1xuICAgIGlmIChzY2hlbWEudHlwZSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJldHVybiB0aGlzLmdldFZhbGlkQ29sdW1uUHJvcHMoc2NoZW1hKS5tYXAoKHByb3ApID0+IHtcbiAgICAgICAgY29uc3QgZW5jUHJvcCA9IGVuY29kZShwcm9wKTtcbiAgICAgICAgY29uc3QgdWlzY2hlbWEgPSBjb250cm9sV2l0aG91dExhYmVsKGAjL3Byb3BlcnRpZXMvJHtlbmNQcm9wfWApO1xuICAgICAgICBpZiAoIXRoaXMuaXNFbmFibGVkKCkpIHtcbiAgICAgICAgICBzZXRSZWFkb25seSh1aXNjaGVtYSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBwcm9wZXJ0eTogcHJvcCxcbiAgICAgICAgICBoZWFkZXI6IHN0YXJ0Q2FzZShwcm9wKSxcbiAgICAgICAgICBwcm9wczoge1xuICAgICAgICAgICAgc2NoZW1hOiBzY2hlbWEsXG4gICAgICAgICAgICB1aXNjaGVtYSxcbiAgICAgICAgICAgIHBhdGg6IHJvd1BhdGgsXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBuZWVkZWQgdG8gY29ycmVjdGx5IHJlbmRlciBpbnB1dCBjb250cm9sIGZvciBtdWx0aSBhdHRyaWJ1dGVzXG4gICAgcmV0dXJuIFtcbiAgICAgIHtcbiAgICAgICAgcHJvcGVydHk6ICdEVU1NWScsXG4gICAgICAgIGhlYWRlcjogdGhpcy5sYWJlbCxcbiAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICBzY2hlbWE6IHNjaGVtYSxcbiAgICAgICAgICB1aXNjaGVtYTogY29udHJvbFdpdGhvdXRMYWJlbChgI2ApLFxuICAgICAgICAgIHBhdGg6IHJvd1BhdGgsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgIF07XG4gIH07XG5cbiAgZ2V0VmFsaWRDb2x1bW5Qcm9wcyA9IChzY29wZWRTY2hlbWE6IEpzb25TY2hlbWEpID0+IHtcbiAgICBpZiAoc2NvcGVkU2NoZW1hLnR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gT2JqZWN0LmtleXMoc2NvcGVkU2NoZW1hLnByb3BlcnRpZXMpLmZpbHRlcigocHJvcCkgPT4ge1xuICAgICAgICBjb25zdCB0eXBlcyA9IGRlcml2ZVR5cGVzKHNjb3BlZFNjaGVtYS5wcm9wZXJ0aWVzW3Byb3BdKTtcbiAgICAgICAgaWYgKHR5cGVzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuY29sdW1uc1RvSWdub3JlLmluZGV4T2YodHlwZXNbMF0pID09PSAtMTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICAvLyBwcmltaXRpdmVzXG4gICAgcmV0dXJuIFsnJ107XG4gIH07XG59XG5leHBvcnQgY29uc3QgVGFibGVSZW5kZXJlclRlc3RlcjogUmFua2VkVGVzdGVyID0gcmFua1dpdGgoXG4gIDMsXG4gIG9yKGlzT2JqZWN0QXJyYXlDb250cm9sLCBpc1ByaW1pdGl2ZUFycmF5Q29udHJvbClcbik7XG5cbmludGVyZmFjZSBDb2x1bW5EZXNjcmlwdGlvbiB7XG4gIHByb3BlcnR5OiBzdHJpbmc7XG4gIGhlYWRlcjogc3RyaW5nO1xuICBwcm9wczogT3duUHJvcHNPZlJlbmRlcmVyO1xufVxuXG5leHBvcnQgY29uc3QgY29udHJvbFdpdGhvdXRMYWJlbCA9IChzY29wZTogc3RyaW5nKTogQ29udHJvbEVsZW1lbnQgPT4gKHtcbiAgdHlwZTogJ0NvbnRyb2wnLFxuICBzY29wZTogc2NvcGUsXG4gIGxhYmVsOiBmYWxzZSxcbn0pO1xuXG5AUGlwZSh7IG5hbWU6ICdnZXRQcm9wcycgfSlcbmV4cG9ydCBjbGFzcyBHZXRQcm9wcyBpbXBsZW1lbnRzIFBpcGVUcmFuc2Zvcm0ge1xuICB0cmFuc2Zvcm0oaW5kZXg6IG51bWJlciwgcHJvcHM6IE93blByb3BzT2ZSZW5kZXJlcikge1xuICAgIGNvbnN0IHJvd1BhdGggPSBQYXRocy5jb21wb3NlKHByb3BzLnBhdGgsIGAke2luZGV4fWApO1xuICAgIHJldHVybiB7XG4gICAgICBzY2hlbWE6IHByb3BzLnNjaGVtYSxcbiAgICAgIHVpc2NoZW1hOiBwcm9wcy51aXNjaGVtYSxcbiAgICAgIHBhdGg6IHJvd1BhdGgsXG4gICAgfTtcbiAgfVxufVxuIl19