@jsonforms/angular-material
Version:
Material Renderer Set for Angular module of JSON Forms
336 lines (326 loc) • 32.7 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 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: "18.2.13", ngImport: i0, type: TableRenderer, deps: [{ token: i1.JsonFormsAngularService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", 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: "18.2.13", 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>
`, standalone: false, 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: "18.2.13", ngImport: i0, type: GetProps, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: GetProps, name: "getProps" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GetProps, decorators: [{
type: Pipe,
args: [{ name: 'getProps', standalone: false }]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUucmVuZGVyZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGlicmFyeS9vdGhlci90YWJsZS5yZW5kZXJlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7RUF1QkU7QUFDRixPQUFPLFNBQVMsTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEVBQUUsU0FBUyxFQUFVLElBQUksRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDdkUsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixxQkFBcUIsR0FDdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBSUwsa0JBQWtCLEVBQ2xCLFdBQVcsRUFDWCxNQUFNLEVBQ04sb0JBQW9CLEVBQ3BCLHVCQUF1QixFQUV2Qiw4QkFBOEIsRUFDOUIsRUFBRSxFQUVGLEtBQUssRUFFTCxRQUFRLEVBQ1IsV0FBVyxHQUVaLE1BQU0saUJBQWlCLENBQUM7Ozs7Ozs7O0FBd0d6QixNQUFNLE9BQU8sYUFBYyxTQUFRLHFCQUFxQjtJQUN0RCxjQUFjLENBQWtCO0lBQ2hDLGdCQUFnQixDQUFXO0lBQzNCLEtBQUssQ0FBc0I7SUFDbEIsZUFBZSxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQy9DLE9BQU8sQ0FBMkM7SUFDbEQsVUFBVSxDQUE4QztJQUN4RCxZQUFZLENBQThDO0lBQzFELFdBQVcsQ0FBbUQ7SUFDOUQsWUFBWSxHQUFzQixFQUFFLENBQUM7SUFFckMsWUFBWSxnQkFBeUM7UUFDbkQsS0FBSyxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDMUIsQ0FBQztJQUNELFlBQVksQ0FBQyxLQUFhLEVBQUUsUUFBYTtRQUN2QyxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDOUIsQ0FBQztJQUNELGtCQUFrQixDQUNoQixLQUE4RDtRQUU5RCxJQUFJLENBQUMs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QixHQUFpQixRQUFRLENBQ3ZELENBQUMsRUFDRCxFQUFFLENBQUMsb0JBQW9CLEVBQUUsdUJBQXVCLENBQUMsQ0FDbEQsQ0FBQztBQVFGLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLENBQUMsS0FBYSxFQUFrQixFQUFFLENBQUMsQ0FBQztJQUNyRSxJQUFJLEVBQUUsU0FBUztJQUNmLEtBQUssRUFBRSxLQUFLO0lBQ1osS0FBSyxFQUFFLEtBQUs7Q0FDYixDQUFDLENBQUM7QUFHSCxNQUFNLE9BQU8sUUFBUTtJQUNuQixTQUFTLENBQUMsS0FBYSxFQUFFLEtBQXlCO1FBQ2hELE1BQU0sT0FBTyxHQUFHLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxHQUFHLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDdEQsT0FBTztZQUNMLE1BQU0sRUFBRSxLQUFLLENBQUMsTUFBTTtZQUNwQixRQUFRLEVBQUUsS0FBSyxDQUFDLFFBQVE7WUFDeEIsSUFBSSxFQUFFLE9BQU87U0FDZCxDQUFDO0lBQ0osQ0FBQzt3R0FSVSxRQUFRO3NHQUFSLFFBQVE7OzRGQUFSLFFBQVE7a0JBRHBCLElBQUk7bUJBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICBUaGUgTUlUIExpY2Vuc2VcbiAgXG4gIENvcHlyaWdodCAoYykgMjAxNy0yMDE5IEVjbGlwc2VTb3VyY2UgTXVuaWNoXG4gIGh0dHBzOi8vZ2l0aHViLmNvbS9lY2xpcHNlc291cmNlL2pzb25mb3Jtc1xuICBcbiAgUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuICBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsXG4gIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXNcbiAgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAgXG4gIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4gIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICBcbiAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbiAgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFXG4gIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbiAgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTlxuICBUSEUgU09GVFdBUkUuXG4qL1xuaW1wb3J0IHN0YXJ0Q2FzZSBmcm9tICdsb2Rhc2gvc3RhcnRDYXNlJztcbmltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBQaXBlLCBQaXBlVHJhbnNmb3JtIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBKc29uRm9ybXNBbmd1bGFyU2VydmljZSxcbiAgSnNvbkZvcm1zQXJyYXlDb250cm9sLFxufSBmcm9tICdAanNvbmZvcm1zL2FuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQXJyYXlDb250cm9sUHJvcHMsXG4gIEFycmF5VHJhbnNsYXRpb25zLFxuICBDb250cm9sRWxlbWVudCxcbiAgY3JlYXRlRGVmYXVsdFZhbHVlLFxuICBkZXJpdmVUeXBlcyxcbiAgZW5jb2RlLFxuICBpc09iamVjdEFycmF5Q29udHJvbCxcbiAgaXNQcmltaXRpdmVBcnJheUNvbnRyb2wsXG4gIEpzb25TY2hlbWEsXG4gIG1hcERpc3BhdGNoVG9BcnJheUNvbnRyb2xQcm9wcyxcbiAgb3IsXG4gIE93blByb3BzT2ZSZW5kZXJlcixcbiAgUGF0aHMsXG4gIFJhbmtlZFRlc3RlcixcbiAgcmFua1dpdGgsXG4gIHNldFJlYWRvbmx5LFxuICBVSVNjaGVtYUVsZW1lbnQsXG59IGZyb20gJ0Bqc29uZm9ybXMvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ1RhYmxlUmVuZGVyZXInLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJ0YWJsZS1jb250YWluZXJcIj5cbiAgICAgIDx0YWJsZVxuICAgICAgICBtYXQtdGFibGVcbiAgICAgICAgW2RhdGFTb3VyY2VdPVwiZGF0YVwiXG4gICAgICAgIGNsYXNzPVwibWF0LWVsZXZhdGlvbi16OFwiXG4gICAgICAgIFt0cmFja0J5XT1cInRyYWNrRWxlbWVudFwiXG4gICAgICA+XG4gICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYWN0aW9uXCIgc3RpY2t5RW5kPlxuICAgICAgICAgIDx0cj5cbiAgICAgICAgICAgIDx0aFxuICAgICAgICAgICAgICBtYXQtaGVhZGVyLWNlbGxcbiAgICAgICAgICAgICAgKm1hdEhlYWRlckNlbGxEZWZcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnc29ydC1jb2x1bW4nOiB1aXNjaGVtYT8ub3B0aW9ucz8uc2hvd1NvcnRCdXR0b25zIH1cIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImFkZCgpXCJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWlzRW5hYmxlZCgpXCJcbiAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJ0cmFuc2xhdGlvbnMuYWRkVG9vbHRpcFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+YWRkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L3RoPlxuICAgICAgICAgIDwvdHI+XG4gICAgICAgICAgPHRyPlxuICAgICAgICAgICAgPHRkXG4gICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ3NvcnQtY29sdW1uJzogdWlzY2hlbWE/Lm9wdGlvbnM/LnNob3dTb3J0QnV0dG9ucyB9XCJcbiAgICAgICAgICAgICAgbWF0LWNlbGxcbiAgICAgICAgICAgICAgKm1hdENlbGxEZWY9XCJcbiAgICAgICAgICAgICAgICBsZXQgcm93O1xuICAgICAgICAgICAgICAgIGxldCBpID0gaW5kZXg7XG4gICAgICAgICAgICAgICAgbGV0IGZpcnN0ID0gZmlyc3Q7XG4gICAgICAgICAgICAgICAgbGV0IGxhc3QgPSBsYXN0XG4gICAgICAgICAgICAgIFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAqbmdJZj1cInVpc2NoZW1hPy5vcHRpb25zPy5zaG93U29ydEJ1dHRvbnNcIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwiaXRlbS11cFwiXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImZpcnN0XCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwidXAoaSlcIlxuICAgICAgICAgICAgICAgIFttYXRUb29sdGlwXT1cInRyYW5zbGF0aW9ucy51cEFyaWFMYWJlbFwiXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcFBvc2l0aW9uPVwicmlnaHRcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmFycm93X3Vwd2FyZDwvbWF0LWljb24+XG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJ1aXNjaGVtYT8ub3B0aW9ucz8uc2hvd1NvcnRCdXR0b25zXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIml0ZW0tZG93blwiXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXG4gICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImxhc3RcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJkb3duKGkpXCJcbiAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJ0cmFuc2xhdGlvbnMuZG93bkFyaWFMYWJlbFwiXG4gICAgICAgICAgICAgICAgbWF0VG9vbHRpcFBvc2l0aW9uPVwicmlnaHRcIlxuICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmFycm93X2Rvd253YXJkPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgICBjb2xvcj1cIndhcm5cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJyZW1vdmUoaSlcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhaXNFbmFibGVkKClcIlxuICAgICAgICAgICAgICAgIG1hdFRvb2x0aXBQb3NpdGlvbj1cInJpZ2h0XCJcbiAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCJ0cmFuc2xhdGlvbnMucmVtb3ZlVG9vbHRpcFwiXG4gICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICA8bWF0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8L3RkPlxuICAgICAgICAgIDwvdHI+XG5cbiAgICAgICAgICA8dHI+PC90clxuICAgICAgICA+PC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgPG5nLWNvbnRhaW5lclxuICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGl0ZW1zXCJcbiAgICAgICAgICBtYXRDb2x1bW5EZWY9XCJ7eyBpdGVtLnByb3BlcnR5IH19XCJcbiAgICAgICAgPlxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+e3sgaXRlbS5oZWFkZXIgfX08L3RoPlxuICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBpbmRleCA9IGluZGV4XCI+XG4gICAgICAgICAgICA8anNvbmZvcm1zLW91dGxldFxuICAgICAgICAgICAgICBbcmVuZGVyUHJvcHNdPVwiaW5kZXggfCBnZXRQcm9wcyA6IGl0ZW0ucHJvcHNcIlxuICAgICAgICAgICAgPjwvanNvbmZvcm1zLW91dGxldD5cbiAgICAgICAgICA8L3RkPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImRpc3BsYXllZENvbHVtbnNcIj48L3RyPlxuICAgICAgICA8dHIgbWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1uc1wiPjwvdHI+XG4gICAgICA8L3RhYmxlPlxuICAgIDwvZGl2PlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICAndGFibGUge3dpZHRoOiAxMDAlO30nLFxuICAgICcuY2RrLWNvbHVtbi1hY3Rpb24geyB3aWR0aDogMTUlO30nLFxuICAgICcuc29ydC1jb2x1bW4geyBtaW4td2lkdGg6IDEydnc7fScsXG4gICAgJy50YWJsZS1jb250YWluZXIge21heC13aWR0aDogMTAwJTsgb3ZlcmZsb3c6IGF1dG87fScsXG4gIF0sXG4gIHN0YW5kYWxvbmU6IGZhbHNlLFxufSlcbmV4cG9ydCBjbGFzcyBUYWJsZVJlbmRlcmVyIGV4dGVuZHMgSnNvbkZvcm1zQXJyYXlDb250cm9sIGltcGxlbWVudHMgT25Jbml0IHtcbiAgZGV0YWlsVWlTY2hlbWE6IFVJU2NoZW1hRWxlbWVudDtcbiAgZGlzcGxheWVkQ29sdW1uczogc3RyaW5nW107XG4gIGl0ZW1zOiBDb2x1bW5EZXNjcmlwdGlvbltdO1xuICByZWFkb25seSBjb2x1bW5zVG9JZ25vcmUgPSBbJ2FycmF5JywgJ29iamVjdCddO1xuICBhZGRJdGVtOiAocGF0aDogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiAoKSA9PiB2b2lkO1xuICBtb3ZlSXRlbVVwOiAocGF0aDogc3RyaW5nLCBpbmRleDogbnVtYmVyKSA9PiAoKSA9PiB2b2lkO1xuICBtb3ZlSXRlbURvd246IChwYXRoOiBzdHJpbmcsIGluZGV4OiBudW1iZXIpID0+ICgpID0+IHZvaWQ7XG4gIHJlbW92ZUl0ZW1zOiAocGF0aDogc3RyaW5nLCB0b0RlbGV0ZTogbnVtYmVyW10pID0+ICgpID0+IHZvaWQ7XG4gIHRyYW5zbGF0aW9uczogQXJyYXlUcmFuc2xhdGlvbnMgPSB7fTtcblxuICBjb25zdHJ1Y3Rvcihqc29uZm9ybXNTZXJ2aWNlOiBKc29uRm9ybXNBbmd1bGFyU2VydmljZSkge1xuICAgIHN1cGVyKGpzb25mb3Jtc1NlcnZpY2UpO1xuICB9XG4gIHRyYWNrRWxlbWVudChpbmRleDogbnVtYmVyLCBfZWxlbWVudDogYW55KSB7XG4gICAgcmV0dXJuIGluZGV4ID8gaW5kZXggOiBudWxsO1xuICB9XG4gIG1hcEFkZGl0aW9uYWxQcm9wcyhcbiAgICBwcm9wczogQXJyYXlDb250cm9sUHJvcHMgJiB7IHRyYW5zbGF0aW9uczogQXJyYXlUcmFuc2xhdGlvbnMgfVxuICApIHtcbiAgICB0aGlzLml0ZW1zID0gdGhpcy5nZW5lcmF0ZUNlbGxzKHByb3BzLnNjaGVtYSwgcHJvcHMucGF0aCk7XG4gICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5pdGVtcy5tYXAoKGl0ZW0pID0+IGl0ZW0ucHJvcGVydHkpO1xuICAgIGlmICh0aGlzLmlzRW5hYmxlZCgpKSB7XG4gICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMucHVzaCgnYWN0aW9uJyk7XG4gICAgfVxuICAgIHRoaXMudHJhbnNsYXRpb25zID0gcHJvcHMudHJhbnNsYXRpb25zO1xuICB9XG5cbiAgcmVtb3ZlKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnJlbW92ZUl0ZW1zKHRoaXMucHJvcHNQYXRoLCBbaW5kZXhdKSgpO1xuICB9XG4gIGFkZCgpOiB2b2lkIHtcbiAgICB0aGlzLmFkZEl0ZW0oXG4gICAgICB0aGlzLnByb3BzUGF0aCxcbiAgICAgIGNyZWF0ZURlZmF1bHRWYWx1ZSh0aGlzLnNjb3BlZFNjaGVtYSwgdGhpcy5yb290U2NoZW1hKVxuICAgICkoKTtcbiAgfVxuICB1cChpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5tb3ZlSXRlbVVwKHRoaXMucHJvcHNQYXRoLCBpbmRleCkoKTtcbiAgfVxuICBkb3duKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLm1vdmVJdGVtRG93bih0aGlzLnByb3BzUGF0aCwgaW5kZXgpKCk7XG4gIH1cbiAgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcblxuICAgIGNvbnN0IHsgYWRkSXRlbSwgcmVtb3ZlSXRlbXMsIG1vdmVVcCwgbW92ZURvd24gfSA9XG4gICAgICBtYXBEaXNwYXRjaFRvQXJyYXlDb250cm9sUHJvcHMoXG4gICAgICAgIHRoaXMuanNvbkZvcm1zU2VydmljZS51cGRhdGVDb3JlLmJpbmQodGhpcy5qc29uRm9ybXNTZXJ2aWNlKVxuICAgICAgKTtcbiAgICB0aGlzLmFkZEl0ZW0gPSBhZGRJdGVtO1xuICAgIHRoaXMubW92ZUl0ZW1VcCA9IG1vdmVVcDtcbiAgICB0aGlzLm1vdmVJdGVtRG93biA9IG1vdmVEb3duO1xuICAgIHRoaXMucmVtb3ZlSXRlbXMgPSByZW1vdmVJdGVtcztcbiAgfVxuXG4gIGdlbmVyYXRlQ2VsbHMgPSAoXG4gICAgc2NoZW1hOiBKc29uU2NoZW1hLFxuICAgIHJvd1BhdGg6IHN0cmluZ1xuICApOiBDb2x1bW5EZXNjcmlwdGlvbltdID0+IHtcbiAgICBpZiAoc2NoZW1hLnR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRWYWxpZENvbHVtblByb3BzKHNjaGVtYSkubWFwKChwcm9wKSA9PiB7XG4gICAgICAgIGNvbnN0IGVuY1Byb3AgPSBlbmNvZGUocHJvcCk7XG4gICAgICAgIGNvbnN0IHVpc2NoZW1hID0gY29udHJvbFdpdGhvdXRMYWJlbChgIy9wcm9wZXJ0aWVzLyR7ZW5jUHJvcH1gKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzRW5hYmxlZCgpKSB7XG4gICAgICAgICAgc2V0UmVhZG9ubHkodWlzY2hlbWEpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcHJvcGVydHk6IHByb3AsXG4gICAgICAgICAgaGVhZGVyOiBzdGFydENhc2UocHJvcCksXG4gICAgICAgICAgcHJvcHM6IHtcbiAgICAgICAgICAgIHNjaGVtYTogc2NoZW1hLFxuICAgICAgICAgICAgdWlzY2hlbWEsXG4gICAgICAgICAgICBwYXRoOiByb3dQYXRoLFxuICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gbmVlZGVkIHRvIGNvcnJlY3RseSByZW5kZXIgaW5wdXQgY29udHJvbCBmb3IgbXVsdGkgYXR0cmlidXRlc1xuICAgIHJldHVybiBbXG4gICAgICB7XG4gICAgICAgIHByb3BlcnR5OiAnRFVNTVknLFxuICAgICAgICBoZWFkZXI6IHRoaXMubGFiZWwsXG4gICAgICAgIHByb3BzOiB7XG4gICAgICAgICAgc2NoZW1hOiBzY2hlbWEsXG4gICAgICAgICAgdWlzY2hlbWE6IGNvbnRyb2xXaXRob3V0TGFiZWwoYCNgKSxcbiAgICAgICAgICBwYXRoOiByb3dQYXRoLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICBdO1xuICB9O1xuXG4gIGdldFZhbGlkQ29sdW1uUHJvcHMgPSAoc2NvcGVkU2NoZW1hOiBKc29uU2NoZW1hKSA9PiB7XG4gICAgaWYgKHNjb3BlZFNjaGVtYS50eXBlID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKHNjb3BlZFNjaGVtYS5wcm9wZXJ0aWVzKS5maWx0ZXIoKHByb3ApID0+IHtcbiAgICAgICAgY29uc3QgdHlwZXMgPSBkZXJpdmVUeXBlcyhzY29wZWRTY2hlbWEucHJvcGVydGllc1twcm9wXSk7XG4gICAgICAgIGlmICh0eXBlcy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmNvbHVtbnNUb0lnbm9yZS5pbmRleE9mKHR5cGVzWzBdKSA9PT0gLTE7XG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gcHJpbWl0aXZlc1xuICAgIHJldHVybiBbJyddO1xuICB9O1xufVxuZXhwb3J0IGNvbnN0IFRhYmxlUmVuZGVyZXJUZXN0ZXI6IFJhbmtlZFRlc3RlciA9IHJhbmtXaXRoKFxuICAzLFxuICBvcihpc09iamVjdEFycmF5Q29udHJvbCwgaXNQcmltaXRpdmVBcnJheUNvbnRyb2wpXG4pO1xuXG5pbnRlcmZhY2UgQ29sdW1uRGVzY3JpcHRpb24ge1xuICBwcm9wZXJ0eTogc3RyaW5nO1xuICBoZWFkZXI6IHN0cmluZztcbiAgcHJvcHM6IE93blByb3BzT2ZSZW5kZXJlcjtcbn1cblxuZXhwb3J0IGNvbnN0IGNvbnRyb2xXaXRob3V0TGFiZWwgPSAoc2NvcGU6IHN0cmluZyk6IENvbnRyb2xFbGVtZW50ID0+ICh7XG4gIHR5cGU6ICdDb250cm9sJyxcbiAgc2NvcGU6IHNjb3BlLFxuICBsYWJlbDogZmFsc2UsXG59KTtcblxuQFBpcGUoeyBuYW1lOiAnZ2V0UHJvcHMnLCBzdGFuZGFsb25lOiBmYWxzZSB9KVxuZXhwb3J0IGNsYXNzIEdldFByb3BzIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XG4gIHRyYW5zZm9ybShpbmRleDogbnVtYmVyLCBwcm9wczogT3duUHJvcHNPZlJlbmRlcmVyKSB7XG4gICAgY29uc3Qgcm93UGF0aCA9IFBhdGhzLmNvbXBvc2UocHJvcHMucGF0aCwgYCR7aW5kZXh9YCk7XG4gICAgcmV0dXJuIHtcbiAgICAgIHNjaGVtYTogcHJvcHMuc2NoZW1hLFxuICAgICAgdWlzY2hlbWE6IHByb3BzLnVpc2NoZW1hLFxuICAgICAgcGF0aDogcm93UGF0aCxcbiAgICB9O1xuICB9XG59XG4iXX0=