@jsonforms/angular-material
Version:
Material Renderer Set for Angular module of JSON Forms
254 lines (250 loc) • 31.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 some from 'lodash/some';
import get from 'lodash/get';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, } from '@angular/core';
import { JsonFormsAngularService, JsonFormsArrayControl, } from '@jsonforms/angular';
import { arrayDefaultTranslations, createDefaultValue, decode, defaultJsonFormsI18nState, findUISchema, getArrayTranslations, getFirstPrimitiveProp, mapDispatchToArrayControlProps, mapStateToArrayControlProps, rankWith, setReadonly, uiTypeIs, } 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/sidenav";
import * as i4 from "@angular/material/list";
import * as i5 from "@angular/material/button";
import * as i6 from "@angular/material/icon";
import * as i7 from "./detail";
const keywords = ['#', 'properties', 'items'];
export const removeSchemaKeywords = (path) => {
return decode(path
.split('/')
.filter((s) => !some(keywords, (key) => key === s))
.join('.'));
};
export class MasterListComponent extends JsonFormsArrayControl {
changeDetectorRef;
masterItems;
selectedItem;
selectedItemIdx;
addItem;
removeItems;
highlightedIdx;
translations;
constructor(jsonformsService, changeDetectorRef) {
super(jsonformsService);
this.changeDetectorRef = changeDetectorRef;
}
onListItemHover(idx) {
this.highlightedIdx = idx;
}
trackElement(_index, element) {
return element ? element.label : null;
}
ngOnInit() {
super.ngOnInit();
const dispatch = this.jsonFormsService.updateCore.bind(this.jsonFormsService);
const { addItem, removeItems } = mapDispatchToArrayControlProps(dispatch);
this.addItem = addItem;
this.removeItems = removeItems;
}
mapAdditionalProps(props) {
const { data, path, schema, uischema } = props;
const controlElement = uischema;
this.propsPath = props.path;
const detailUISchema = findUISchema(props.uischemas, schema, `${controlElement.scope}/items`, props.path, 'VerticalLayout', controlElement, props.rootSchema);
if (!this.isEnabled()) {
setReadonly(detailUISchema);
}
this.translations = props.translations;
const masterItems = (data || []).map((d, index) => {
const labelRefInstancePath = controlElement.options?.labelRef &&
removeSchemaKeywords(controlElement.options.labelRef);
const isPrimitive = d !== undefined && typeof d !== 'object';
const masterItem = {
label: isPrimitive
? d.toString()
: get(d, labelRefInstancePath ?? getFirstPrimitiveProp(schema)),
data: d,
path: `${path}.${index}`,
schema,
uischema: detailUISchema,
};
return masterItem;
});
this.masterItems = masterItems;
let newSelectedIdx = -1;
let newSelectedItem;
if (this.masterItems.length === 0) {
// unset select if no elements anymore
this.selectedItem = undefined;
this.selectedItemIdx = -1;
}
else if (this.selectedItemIdx >= this.masterItems.length) {
// the previous index is to high, reduce it to the maximal possible
newSelectedIdx = this.masterItems.length - 1;
newSelectedItem = this.masterItems[newSelectedIdx];
}
else if (this.selectedItemIdx !== -1 &&
this.selectedItemIdx < this.masterItems.length) {
newSelectedIdx = this.selectedItemIdx;
newSelectedItem = this.masterItems[this.selectedItemIdx];
}
if (newSelectedItem !== undefined &&
this.selectedItem !== undefined &&
(newSelectedItem.label === this.selectedItem.label ||
newSelectedItem.path === this.selectedItem.path)) {
// after checking that we are on the same path, set selection
this.selectedItem = newSelectedItem;
this.selectedItemIdx = newSelectedIdx;
}
else if (this.masterItems.length > 0) {
// pre-select 1st entry if the previous selected element as fallback
this.selectedItem = this.masterItems[0];
this.selectedItemIdx = 0;
}
this.changeDetectorRef.markForCheck();
}
onSelect(item, idx) {
this.selectedItem = item;
this.selectedItemIdx = idx;
}
onAddClick() {
this.addItem(this.propsPath, createDefaultValue(this.scopedSchema, this.rootSchema))();
}
onDeleteClick(item) {
this.removeItems(this.propsPath, [item])();
}
mapToProps(state) {
const props = mapStateToArrayControlProps(state, this.getOwnProps());
const t = state.jsonforms.i18n?.translate ?? defaultJsonFormsI18nState.translate;
const translations = getArrayTranslations(t, arrayDefaultTranslations, props.i18nKeyPrefix, props.label);
return { ...props, translations };
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MasterListComponent, deps: [{ token: i1.JsonFormsAngularService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: MasterListComponent, selector: "jsonforms-list-with-detail-master", usesInheritance: true, ngImport: i0, template: `
<mat-sidenav-container
[ngStyle]="{ display: hidden ? 'none' : '' }"
autosize="true"
class="container"
>
<mat-sidenav mode="side" opened>
<mat-nav-list>
<mat-list-item *ngIf="masterItems.length === 0">{{
translations.noDataMessage
}}</mat-list-item>
<mat-list-item
*ngFor="
let item of masterItems;
let i = index;
trackBy: trackElement
"
[class.selected]="item === selectedItem"
(click)="onSelect(item, i)"
(mouseover)="onListItemHover(i)"
(mouseout)="onListItemHover(undefined)"
>
<a matLine>{{ item.label || 'No label set' }}</a>
<button
mat-icon-button
class="button item-button hide"
(click)="onDeleteClick(i)"
[ngClass]="{ show: highlightedIdx == i }"
*ngIf="isEnabled()"
>
<mat-icon mat-list-icon>delete</mat-icon>
</button>
</mat-list-item>
</mat-nav-list>
<button
mat-fab
color="primary"
class="add-button"
(click)="onAddClick()"
*ngIf="isEnabled()"
>
<mat-icon [attr.aria-label]="translations.addAriaLabel">add</mat-icon>
</button>
</mat-sidenav>
<mat-sidenav-content class="content">
<jsonforms-detail
*ngIf="selectedItem"
[item]="selectedItem"
></jsonforms-detail>
</mat-sidenav-content>
</mat-sidenav-container>
`, isInline: true, styles: ["mat-list-item.selected{background:#0000000a}.container{height:100vh}.content{padding:15px;background-color:#fff}.add-button{float:right;margin-top:.5em;margin-right:.25em}.button{float:right;margin-right:.25em}.item-button{position:absolute;top:0;right:0}.hide{display:none}.show{display:inline-block}mat-sidenav{width:20%}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { 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.MatSidenav, selector: "mat-sidenav", inputs: ["fixedInViewport", "fixedTopGap", "fixedBottomGap"], exportAs: ["matSidenav"] }, { kind: "component", type: i3.MatSidenavContainer, selector: "mat-sidenav-container", exportAs: ["matSidenavContainer"] }, { kind: "component", type: i3.MatSidenavContent, selector: "mat-sidenav-content" }, { kind: "component", type: i4.MatNavList, selector: "mat-nav-list", exportAs: ["matNavList"] }, { kind: "component", type: i4.MatListItem, selector: "mat-list-item, a[mat-list-item], button[mat-list-item]", inputs: ["activated"], exportAs: ["matListItem"] }, { kind: "component", type: i5.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i5.MatFabButton, selector: "button[mat-fab]", inputs: ["extended"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i7.JsonFormsDetailComponent, selector: "jsonforms-detail", inputs: ["item"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MasterListComponent, decorators: [{
type: Component,
args: [{ selector: 'jsonforms-list-with-detail-master', template: `
<mat-sidenav-container
[ngStyle]="{ display: hidden ? 'none' : '' }"
autosize="true"
class="container"
>
<mat-sidenav mode="side" opened>
<mat-nav-list>
<mat-list-item *ngIf="masterItems.length === 0">{{
translations.noDataMessage
}}</mat-list-item>
<mat-list-item
*ngFor="
let item of masterItems;
let i = index;
trackBy: trackElement
"
[class.selected]="item === selectedItem"
(click)="onSelect(item, i)"
(mouseover)="onListItemHover(i)"
(mouseout)="onListItemHover(undefined)"
>
<a matLine>{{ item.label || 'No label set' }}</a>
<button
mat-icon-button
class="button item-button hide"
(click)="onDeleteClick(i)"
[ngClass]="{ show: highlightedIdx == i }"
*ngIf="isEnabled()"
>
<mat-icon mat-list-icon>delete</mat-icon>
</button>
</mat-list-item>
</mat-nav-list>
<button
mat-fab
color="primary"
class="add-button"
(click)="onAddClick()"
*ngIf="isEnabled()"
>
<mat-icon [attr.aria-label]="translations.addAriaLabel">add</mat-icon>
</button>
</mat-sidenav>
<mat-sidenav-content class="content">
<jsonforms-detail
*ngIf="selectedItem"
[item]="selectedItem"
></jsonforms-detail>
</mat-sidenav-content>
</mat-sidenav-container>
`, changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, styles: ["mat-list-item.selected{background:#0000000a}.container{height:100vh}.content{padding:15px;background-color:#fff}.add-button{float:right;margin-top:.5em;margin-right:.25em}.button{float:right;margin-right:.25em}.item-button{position:absolute;top:0;right:0}.hide{display:none}.show{display:inline-block}mat-sidenav{width:20%}\n"] }]
}], ctorParameters: () => [{ type: i1.JsonFormsAngularService }, { type: i0.ChangeDetectorRef }] });
export const masterDetailTester = rankWith(4, uiTypeIs('ListWithDetail'));
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFzdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2xpYnJhcnkvb3RoZXIvbWFzdGVyLWRldGFpbC9tYXN0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0VBdUJFO0FBQ0YsT0FBTyxJQUFJLE1BQU0sYUFBYSxDQUFDO0FBQy9CLE9BQU8sR0FBRyxNQUFNLFlBQVksQ0FBQztBQUM3QixPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEdBRVYsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLHVCQUF1QixFQUN2QixxQkFBcUIsR0FDdEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBRUwsd0JBQXdCLEVBR3hCLGtCQUFrQixFQUNsQixNQUFNLEVBQ04seUJBQXlCLEVBQ3pCLFlBQVksRUFDWixvQkFBb0IsRUFDcEIscUJBQXFCLEVBRXJCLDhCQUE4QixFQUM5QiwyQkFBMkIsRUFFM0IsUUFBUSxFQUNSLFdBQVcsRUFFWCxRQUFRLEdBQ1QsTUFBTSxpQkFBaUIsQ0FBQzs7Ozs7Ozs7O0FBRXpCLE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBRyxFQUFFLFlBQVksRUFBRSxPQUFPLENBQUMsQ0FBQztBQUU5QyxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO0lBQ25ELE9BQU8sTUFBTSxDQUNYLElBQUk7U0FDRCxLQUFLLENBQUMsR0FBRyxDQUFDO1NBQ1YsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQztTQUNsRCxJQUFJLENBQUMsR0FBRyxDQUFDLENBQ2IsQ0FBQztBQUNKLENBQUMsQ0FBQztBQWlHRixNQUFNLE9BQU8sbUJBQ1gsU0FB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bUIsZ0dBN0ZwQjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbURUOzs0RkEwQ1UsbUJBQW1CO2tCQS9GL0IsU0FBUzsrQkFDRSxtQ0FBbUMsWUFDbkM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1EVCxtQkF1Q2dCLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsS0FBSzs7QUFpSm5CLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFpQixRQUFRLENBQ3RELENBQUMsRUFDRCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsQ0FDM0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gIFRoZSBNSVQgTGljZW5zZVxuICBcbiAgQ29weXJpZ2h0IChjKSAyMDE3LTIwMTkgRWNsaXBzZVNvdXJjZSBNdW5pY2hcbiAgaHR0cHM6Ly9naXRodWIuY29tL2VjbGlwc2Vzb3VyY2UvanNvbmZvcm1zXG4gIFxuICBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4gIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuICB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuICBcbiAgVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbiAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gIFxuICBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4gIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLFxuICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuICBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLFxuICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXG4gIFRIRSBTT0ZUV0FSRS5cbiovXG5pbXBvcnQgc29tZSBmcm9tICdsb2Rhc2gvc29tZSc7XG5pbXBvcnQgZ2V0IGZyb20gJ2xvZGFzaC9nZXQnO1xuaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIE9uSW5pdCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBKc29uRm9ybXNBbmd1bGFyU2VydmljZSxcbiAgSnNvbkZvcm1zQXJyYXlDb250cm9sLFxufSBmcm9tICdAanNvbmZvcm1zL2FuZ3VsYXInO1xuaW1wb3J0IHtcbiAgQXJyYXlDb250cm9sUHJvcHMsXG4gIGFycmF5RGVmYXVsdFRyYW5zbGF0aW9ucyxcbiAgQXJyYXlUcmFuc2xhdGlvbnMsXG4gIENvbnRyb2xFbGVtZW50LFxuICBjcmVhdGVEZWZhdWx0VmFsdWUsXG4gIGRlY29kZSxcbiAgZGVmYXVsdEpzb25Gb3Jtc0kxOG5TdGF0ZSxcbiAgZmluZFVJU2NoZW1hLFxuICBnZXRBcnJheVRyYW5zbGF0aW9ucyxcbiAgZ2V0Rmlyc3RQcmltaXRpdmVQcm9wLFxuICBKc29uRm9ybXNTdGF0ZSxcbiAgbWFwRGlzcGF0Y2hUb0FycmF5Q29udHJvbFByb3BzLFxuICBtYXBTdGF0ZVRvQXJyYXlDb250cm9sUHJvcHMsXG4gIFJhbmtlZFRlc3RlcixcbiAgcmFua1dpdGgsXG4gIHNldFJlYWRvbmx5LFxuICBTdGF0ZVByb3BzT2ZBcnJheUNvbnRyb2wsXG4gIHVpVHlwZUlzLFxufSBmcm9tICdAanNvbmZvcm1zL2NvcmUnO1xuXG5jb25zdCBrZXl3b3JkcyA9IFsnIycsICdwcm9wZXJ0aWVzJywgJ2l0ZW1zJ107XG5cbmV4cG9ydCBjb25zdCByZW1vdmVTY2hlbWFLZXl3b3JkcyA9IChwYXRoOiBzdHJpbmcpID0+IHtcbiAgcmV0dXJuIGRlY29kZShcbiAgICBwYXRoXG4gICAgICAuc3BsaXQoJy8nKVxuICAgICAgLmZpbHRlcigocykgPT4gIXNvbWUoa2V5d29yZHMsIChrZXkpID0+IGtleSA9PT0gcykpXG4gICAgICAuam9pbignLicpXG4gICk7XG59O1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdqc29uZm9ybXMtbGlzdC13aXRoLWRldGFpbC1tYXN0ZXInLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxtYXQtc2lkZW5hdi1jb250YWluZXJcbiAgICAgIFtuZ1N0eWxlXT1cInsgZGlzcGxheTogaGlkZGVuID8gJ25vbmUnIDogJycgfVwiXG4gICAgICBhdXRvc2l6ZT1cInRydWVcIlxuICAgICAgY2xhc3M9XCJjb250YWluZXJcIlxuICAgID5cbiAgICAgIDxtYXQtc2lkZW5hdiBtb2RlPVwic2lkZVwiIG9wZW5lZD5cbiAgICAgICAgPG1hdC1uYXYtbGlzdD5cbiAgICAgICAgICA8bWF0LWxpc3QtaXRlbSAqbmdJZj1cIm1hc3Rlckl0ZW1zLmxlbmd0aCA9PT0gMFwiPnt7XG4gICAgICAgICAgICB0cmFuc2xhdGlvbnMubm9EYXRhTWVzc2FnZVxuICAgICAgICAgIH19PC9tYXQtbGlzdC1pdGVtPlxuICAgICAgICAgIDxtYXQtbGlzdC1pdGVtXG4gICAgICAgICAgICAqbmdGb3I9XCJcbiAgICAgICAgICAgICAgbGV0IGl0ZW0gb2YgbWFzdGVySXRlbXM7XG4gICAgICAgICAgICAgIGxldCBpID0gaW5kZXg7XG4gICAgICAgICAgICAgIHRyYWNrQnk6IHRyYWNrRWxlbWVudFxuICAgICAgICAgICAgXCJcbiAgICAgICAgICAgIFtjbGFzcy5zZWxlY3RlZF09XCJpdGVtID09PSBzZWxlY3RlZEl0ZW1cIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uU2VsZWN0KGl0ZW0sIGkpXCJcbiAgICAgICAgICAgIChtb3VzZW92ZXIpPVwib25MaXN0SXRlbUhvdmVyKGkpXCJcbiAgICAgICAgICAgIChtb3VzZW91dCk9XCJvbkxpc3RJdGVtSG92ZXIodW5kZWZpbmVkKVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPGEgbWF0TGluZT57eyBpdGVtLmxhYmVsIHx8ICdObyBsYWJlbCBzZXQnIH19PC9hPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJidXR0b24gaXRlbS1idXR0b24gaGlkZVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbkRlbGV0ZUNsaWNrKGkpXCJcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyBzaG93OiBoaWdobGlnaHRlZElkeCA9PSBpIH1cIlxuICAgICAgICAgICAgICAqbmdJZj1cImlzRW5hYmxlZCgpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPG1hdC1pY29uIG1hdC1saXN0LWljb24+ZGVsZXRlPC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvbWF0LWxpc3QtaXRlbT5cbiAgICAgICAgPC9tYXQtbmF2LWxpc3Q+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICBtYXQtZmFiXG4gICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcbiAgICAgICAgICBjbGFzcz1cImFkZC1idXR0b25cIlxuICAgICAgICAgIChjbGljayk9XCJvbkFkZENsaWNrKClcIlxuICAgICAgICAgICpuZ0lmPVwiaXNFbmFibGVkKClcIlxuICAgICAgICA+XG4gICAgICAgICAgPG1hdC1pY29uIFthdHRyLmFyaWEtbGFiZWxdPVwidHJhbnNsYXRpb25zLmFkZEFyaWFMYWJlbFwiPmFkZDwvbWF0LWljb24+XG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgPC9tYXQtc2lkZW5hdj5cbiAgICAgIDxtYXQtc2lkZW5hdi1jb250ZW50IGNsYXNzPVwiY29udGVudFwiPlxuICAgICAgICA8anNvbmZvcm1zLWRldGFpbFxuICAgICAgICAgICpuZ0lmPVwic2VsZWN0ZWRJdGVtXCJcbiAgICAgICAgICBbaXRlbV09XCJzZWxlY3RlZEl0ZW1cIlxuICAgICAgICA+PC9qc29uZm9ybXMtZGV0YWlsPlxuICAgICAgPC9tYXQtc2lkZW5hdi1jb250ZW50PlxuICAgIDwvbWF0LXNpZGVuYXYtY29udGFpbmVyPlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICAvKiBUT0RPKG1kYy1taWdyYXRpb24pOiBUaGUgZm9sbG93aW5nIHJ1bGUgdGFyZ2V0cyBpbnRlcm5hbCBjbGFzc2VzIG9mIGxpc3QgdGhhdCBtYXkgbm8gbG9uZ2VyIGFwcGx5IGZvciB0aGUgTURDIHZlcnNpb24uICovXG4gICAgICBtYXQtbGlzdC1pdGVtLnNlbGVjdGVkIHtcbiAgICAgICAgYmFja2dyb3VuZDogcmdiYSgwLCAwLCAwLCAwLjA0KTtcbiAgICAgIH1cbiAgICAgIC5jb250YWluZXIge1xuICAgICAgICBoZWlnaHQ6IDEwMHZoO1xuICAgICAgfVxuICAgICAgLmNvbnRlbnQge1xuICAgICAgICBwYWRkaW5nOiAxNXB4O1xuICAgICAgICBiYWNrZ3JvdW5kLWNvbG9yOiAjZmZmO1xuICAgICAgfVxuICAgICAgLmFkZC1idXR0b24ge1xuICAgICAgICBmbG9hdDogcmlnaHQ7XG4gICAgICAgIG1hcmdpbi10b3A6IDAuNWVtO1xuICAgICAgICBtYXJnaW4tcmlnaHQ6IDAuMjVlbTtcbiAgICAgIH1cbiAgICAgIC5idXR0b24ge1xuICAgICAgICBmbG9hdDogcmlnaHQ7XG4gICAgICAgIG1hcmdpbi1yaWdodDogMC4yNWVtO1xuICAgICAgfVxuICAgICAgLml0ZW0tYnV0dG9uIHtcbiAgICAgICAgcG9zaXRpb246IGFic29sdXRlO1xuICAgICAgICB0b3A6IDA7XG4gICAgICAgIHJpZ2h0OiAwO1xuICAgICAgfVxuICAgICAgLmhpZGUge1xuICAgICAgICBkaXNwbGF5OiBub25lO1xuICAgICAgfVxuICAgICAgLnNob3cge1xuICAgICAgICBkaXNwbGF5OiBpbmxpbmUtYmxvY2s7XG4gICAgICB9XG4gICAgICBtYXQtc2lkZW5hdiB7XG4gICAgICAgIHdpZHRoOiAyMCU7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IGZhbHNlLFxufSlcbmV4cG9ydCBjbGFzcyBNYXN0ZXJMaXN0Q29tcG9uZW50XG4gIGV4dGVuZHMgSnNvbkZvcm1zQXJyYXlDb250cm9sXG4gIGltcGxlbWVudHMgT25Jbml0XG57XG4gIG1hc3Rlckl0ZW1zOiBhbnlbXTtcbiAgc2VsZWN0ZWRJdGVtOiBhbnk7XG4gIHNlbGVjdGVkSXRlbUlkeDogbnVtYmVyO1xuICBhZGRJdGVtOiAocGF0aDogc3RyaW5nLCB2YWx1ZTogYW55KSA9PiAoKSA9PiB2b2lkO1xuICByZW1vdmVJdGVtczogKHBhdGg6IHN0cmluZywgdG9EZWxldGU6IG51bWJlcltdKSA9PiAoKSA9PiB2b2lkO1xuICBoaWdobGlnaHRlZElkeDogbnVtYmVyO1xuICB0cmFuc2xhdGlvbnM6IEFycmF5VHJhbnNsYXRpb25zO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGpzb25mb3Jtc1NlcnZpY2U6IEpzb25Gb3Jtc0FuZ3VsYXJTZXJ2aWNlLFxuICAgIHByaXZhdGUgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmXG4gICkge1xuICAgIHN1cGVyKGpzb25mb3Jtc1NlcnZpY2UpO1xuICB9XG5cbiAgb25MaXN0SXRlbUhvdmVyKGlkeDogbnVtYmVyKSB7XG4gICAgdGhpcy5oaWdobGlnaHRlZElkeCA9IGlkeDtcbiAgfVxuXG4gIHRyYWNrRWxlbWVudChfaW5kZXg6IG51bWJlciwgZWxlbWVudDogYW55KSB7XG4gICAgcmV0dXJuIGVsZW1lbnQgPyBlbGVtZW50LmxhYmVsIDogbnVsbDtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHN1cGVyLm5nT25Jbml0KCk7XG4gICAgY29uc3QgZGlzcGF0Y2ggPSB0aGlzLmpzb25Gb3Jtc1NlcnZpY2UudXBkYXRlQ29yZS5iaW5kKFxuICAgICAgdGhpcy5qc29uRm9ybXNTZXJ2aWNlXG4gICAgKTtcbiAgICBjb25zdCB7IGFkZEl0ZW0sIHJlbW92ZUl0ZW1zIH0gPSBtYXBEaXNwYXRjaFRvQXJyYXlDb250cm9sUHJvcHMoZGlzcGF0Y2gpO1xuICAgIHRoaXMuYWRkSXRlbSA9IGFkZEl0ZW07XG4gICAgdGhpcy5yZW1vdmVJdGVtcyA9IHJlbW92ZUl0ZW1zO1xuICB9XG5cbiAgbWFwQWRkaXRpb25hbFByb3BzKFxuICAgIHByb3BzOiBBcnJheUNvbnRyb2xQcm9wcyAmIHsgdHJhbnNsYXRpb25zOiBBcnJheVRyYW5zbGF0aW9ucyB9XG4gICkge1xuICAgIGNvbnN0IHsgZGF0YSwgcGF0aCwgc2NoZW1hLCB1aXNjaGVtYSB9ID0gcHJvcHM7XG4gICAgY29uc3QgY29udHJvbEVsZW1lbnQgPSB1aXNjaGVtYSBhcyBDb250cm9sRWxlbWVudDtcbiAgICB0aGlzLnByb3BzUGF0aCA9IHByb3BzLnBhdGg7XG4gICAgY29uc3QgZGV0YWlsVUlTY2hlbWEgPSBmaW5kVUlTY2hlbWEoXG4gICAgICBwcm9wcy51aXNjaGVtYXMsXG4gICAgICBzY2hlbWEsXG4gICAgICBgJHtjb250cm9sRWxlbWVudC5zY29wZX0vaXRlbXNgLFxuICAgICAgcHJvcHMucGF0aCxcbiAgICAgICdWZXJ0aWNhbExheW91dCcsXG4gICAgICBjb250cm9sRWxlbWVudCxcbiAgICAgIHByb3BzLnJvb3RTY2hlbWFcbiAgICApO1xuXG4gICAgaWYgKCF0aGlzLmlzRW5hYmxlZCgpKSB7XG4gICAgICBzZXRSZWFkb25seShkZXRhaWxVSVNjaGVtYSk7XG4gICAgfVxuXG4gICAgdGhpcy50cmFuc2xhdGlvbnMgPSBwcm9wcy50cmFuc2xhdGlvbnM7XG5cbiAgICBjb25zdCBtYXN0ZXJJdGVtcyA9IChkYXRhIHx8IFtdKS5tYXAoKGQ6IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgY29uc3QgbGFiZWxSZWZJbnN0YW5jZVBhdGggPVxuICAgICAgICBjb250cm9sRWxlbWVudC5vcHRpb25zPy5sYWJlbFJlZiAmJlxuICAgICAgICByZW1vdmVTY2hlbWFLZXl3b3Jkcyhjb250cm9sRWxlbWVudC5vcHRpb25zLmxhYmVsUmVmKTtcbiAgICAgIGNvbnN0IGlzUHJpbWl0aXZlID0gZCAhPT0gdW5kZWZpbmVkICYmIHR5cGVvZiBkICE9PSAnb2JqZWN0JztcbiAgICAgIGNvbnN0IG1hc3Rlckl0ZW0gPSB7XG4gICAgICAgIGxhYmVsOiBpc1ByaW1pdGl2ZVxuICAgICAgICAgID8gZC50b1N0cmluZygpXG4gICAgICAgICAgOiBnZXQoZCwgbGFiZWxSZWZJbnN0YW5jZVBhdGggPz8gZ2V0Rmlyc3RQcmltaXRpdmVQcm9wKHNjaGVtYSkpLFxuICAgICAgICBkYXRhOiBkLFxuICAgICAgICBwYXRoOiBgJHtwYXRofS4ke2luZGV4fWAsXG4gICAgICAgIHNjaGVtYSxcbiAgICAgICAgdWlzY2hlbWE6IGRldGFpbFVJU2NoZW1hLFxuICAgICAgfTtcbiAgICAgIHJldHVybiBtYXN0ZXJJdGVtO1xuICAgIH0pO1xuICAgIHRoaXMubWFzdGVySXRlbXMgPSBtYXN0ZXJJdGVtcztcbiAgICBsZXQgbmV3U2VsZWN0ZWRJZHggPSAtMTtcbiAgICBsZXQgbmV3U2VsZWN0ZWRJdGVtO1xuICAgIGlmICh0aGlzLm1hc3Rlckl0ZW1zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgLy8gdW5zZXQgc2VsZWN0IGlmIG5vIGVsZW1lbnRzIGFueW1vcmVcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5zZWxlY3RlZEl0ZW1JZHggPSAtMTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRJdGVtSWR4ID49IHRoaXMubWFzdGVySXRlbXMubGVuZ3RoKSB7XG4gICAgICAvLyB0aGUgcHJldmlvdXMgaW5kZXggaXMgdG8gaGlnaCwgcmVkdWNlIGl0IHRvIHRoZSBtYXhpbWFsIHBvc3NpYmxlXG4gICAgICBuZXdTZWxlY3RlZElkeCA9IHRoaXMubWFzdGVySXRlbXMubGVuZ3RoIC0gMTtcbiAgICAgIG5ld1NlbGVjdGVkSXRlbSA9IHRoaXMubWFzdGVySXRlbXNbbmV3U2VsZWN0ZWRJZHhdO1xuICAgIH0gZWxzZSBpZiAoXG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbUlkeCAhPT0gLTEgJiZcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtSWR4IDwgdGhpcy5tYXN0ZXJJdGVtcy5sZW5ndGhcbiAgICApIHtcbiAgICAgIG5ld1NlbGVjdGVkSWR4ID0gdGhpcy5zZWxlY3RlZEl0ZW1JZHg7XG4gICAgICBuZXdTZWxlY3RlZEl0ZW0gPSB0aGlzLm1hc3Rlckl0ZW1zW3RoaXMuc2VsZWN0ZWRJdGVtSWR4XTtcbiAgICB9XG5cbiAgICBpZiAoXG4gICAgICBuZXdTZWxlY3RlZEl0ZW0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgdGhpcy5zZWxlY3RlZEl0ZW0gIT09IHVuZGVmaW5lZCAmJlxuICAgICAgKG5ld1NlbGVjdGVkSXRlbS5sYWJlbCA9PT0gdGhpcy5zZWxlY3RlZEl0ZW0ubGFiZWwgfHxcbiAgICAgICAgbmV3U2VsZWN0ZWRJdGVtLnBhdGggPT09IHRoaXMuc2VsZWN0ZWRJdGVtLnBhdGgpXG4gICAgKSB7XG4gICAgICAvLyBhZnRlciBjaGVja2luZyB0aGF0IHdlIGFyZSBvbiB0aGUgc2FtZSBwYXRoLCBzZXQgc2VsZWN0aW9uXG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbSA9IG5ld1NlbGVjdGVkSXRlbTtcbiAgICAgIHRoaXMuc2VsZWN0ZWRJdGVtSWR4ID0gbmV3U2VsZWN0ZWRJZHg7XG4gICAgfSBlbHNlIGlmICh0aGlzLm1hc3Rlckl0ZW1zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIHByZS1zZWxlY3QgMXN0IGVudHJ5IGlmIHRoZSBwcmV2aW91cyBzZWxlY3RlZCBlbGVtZW50IGFzIGZhbGxiYWNrXG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbSA9IHRoaXMubWFzdGVySXRlbXNbMF07XG4gICAgICB0aGlzLnNlbGVjdGVkSXRlbUlkeCA9IDA7XG4gICAgfVxuICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3JSZWYubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBvblNlbGVjdChpdGVtOiBhbnksIGlkeDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy5zZWxlY3RlZEl0ZW0gPSBpdGVtO1xuICAgIHRoaXMuc2VsZWN0ZWRJdGVtSWR4ID0gaWR4O1xuICB9XG5cbiAgb25BZGRDbGljaygpIHtcbiAgICB0aGlzLmFkZEl0ZW0oXG4gICAgICB0aGlzLnByb3BzUGF0aCxcbiAgICAgIGNyZWF0ZURlZmF1bHRWYWx1ZSh0aGlzLnNjb3BlZFNjaGVtYSwgdGhpcy5yb290U2NoZW1hKVxuICAgICkoKTtcbiAgfVxuXG4gIG9uRGVsZXRlQ2xpY2soaXRlbTogbnVtYmVyKSB7XG4gICAgdGhpcy5yZW1vdmVJdGVtcyh0aGlzLnByb3BzUGF0aCwgW2l0ZW1dKSgpO1xuICB9XG5cbiAgcHJvdGVjdGVkIG1hcFRvUHJvcHMoXG4gICAgc3RhdGU6IEpzb25Gb3Jtc1N0YXRlXG4gICk6IFN0YXRlUHJvcHNPZkFycmF5Q29udHJvbCAmIHsgdHJhbnNsYXRpb25zOiBBcnJheVRyYW5zbGF0aW9ucyB9IHtcbiAgICBjb25zdCBwcm9wcyA9IG1hcFN0YXRlVG9BcnJheUNvbnRyb2xQcm9wcyhzdGF0ZSwgdGhpcy5nZXRPd25Qcm9wcygpKTtcbiAgICBjb25zdCB0ID1cbiAgICAgIHN0YXRlLmpzb25mb3Jtcy5pMThuPy50cmFuc2xhdGUgPz8gZGVmYXVsdEpzb25Gb3Jtc0kxOG5TdGF0ZS50cmFuc2xhdGU7XG4gICAgY29uc3QgdHJhbnNsYXRpb25zID0gZ2V0QXJyYXlUcmFuc2xhdGlvbnMoXG4gICAgICB0LFxuICAgICAgYXJyYXlEZWZhdWx0VHJhbnNsYXRpb25zLFxuICAgICAgcHJvcHMuaTE4bktleVByZWZpeCxcbiAgICAgIHByb3BzLmxhYmVsXG4gICAgKTtcbiAgICByZXR1cm4geyAuLi5wcm9wcywgdHJhbnNsYXRpb25zIH07XG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IG1hc3RlckRldGFpbFRlc3RlcjogUmFua2VkVGVzdGVyID0gcmFua1dpdGgoXG4gIDQsXG4gIHVpVHlwZUlzKCdMaXN0V2l0aERldGFpbCcpXG4pO1xuIl19