@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
231 lines • 34 kB
JavaScript
import { CdkStep } from '@angular/cdk/stepper';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { GainsightService } from '../product-experience/gainsight.service';
import { ACTIONS_STEPPER } from './stepper-px.constants';
import { C8yStepper } from './stepper.component';
import * as i0 from "@angular/core";
import * as i1 from "./stepper.component";
import * as i2 from "@angular/cdk/stepper";
import * as i3 from "../product-experience/gainsight.service";
import * as i4 from "@angular/common";
import * as i5 from "../i18n/c8y-translate.pipe";
/**
* `C8yStepperButtons` provides a convenient way to have, according to
* the `C8yStepper` and each `cdk-step`, buttons to navigate between steps or to cancel the whole
* step-process. Buttons rendered with the help of this component will use the branding css.
*
* By default all steps with this component in use will render a next button, expect the last step.
* The other way around, every step using this component will render a back button, expect the first step.
* To get a cancel button rendered you need to handle the onCancel event.
* For next and back button you don't need to handle the available events `onNext` and `onBack` because default behavior
* is implemented. The default will just call, according to the button, the `stepper.next()` or `stepper.previous()`
* methods and moves the stepper forth or back. Using the `EventEmitter` `onNext` and `onBack` will emit for you the following
* object: `{stepper: C8yStepper, step: CdkStep}`. This is useful if you need to implement custom logic before moving
* to the next step or sending data to a backend. In this case you need to tell the stepper to move forward or back
* on your own.
*
* With the component input `[labels]` you can change the label of each button in each step. It takes an object like this:
* `{next?: string, back?: string, cancel?: string}`
*
* The `[pending]` input is of type boolean and will enable css animation for the next button when true.
*
* If the `cdk-step` provides a `stepControl` the component will set the next button disabled when the formGroup
* behind it is invalid. As long as the `[pending]` input is true the back and next button is also disabled.
* This will prevent multiple clicks while running a request or stepping back while a request is ongoing.
*
* ```html
* <c8y-stepper>
* <cdk-step>
* <!--
* your html code
* ...
* ... -->
* <c8y-stepper-buttons
* (onNext)="save()"
* [labels]="{ next: 'Save' }"
* [pending]="pendingStatus"
* ></c8y-stepper-buttons>
* </cdk-step>
* </c8y-stepper>
* ```
*
* ```js
* // in your component:
* async save() {
* this.pendingStatus = true;
* // your async request goes here ...
* // await something();
* this.pendingStatus = false;
* this.stepper.next();
* }
* ```
*/
export class C8yStepperButtons {
constructor(stepper, step, gainsightService) {
this.stepper = stepper;
this.step = step;
this.gainsightService = gainsightService;
/**
* Optional
* Indicates if a request is pending and sets the next button
* to disabled when true
*/
this.pending = false;
/**
* Disabled state of a button
*/
this.disabled = false;
/**
* EventEmitter which emits when cancel button is clicked
*/
this.onCancel = new EventEmitter();
/**
* EventEmitter which emits {stepper: C8yStepper; step: CdkStep} when next button is clicked.
*/
this.onNext = new EventEmitter();
/**
* EventEmitter which emits {stepper: C8yStepper; step: CdkStep} when back button is clicked.
*/
this.onBack = new EventEmitter();
/**
* EventEmitter which emits when the optional custom button is clicked
*/
this.onCustom = new EventEmitter();
/**
* Indicator which button should be shown.
* Based on the cdk-steps within the c8y-stepper
* next and back buttons are rendered.
*/
this.showBtns = {
cancel: false,
back: false,
next: false,
custom: false
};
/**
* Flag that indicates that the default settings defined in the showBtns have been overwritten.
*/
this.forceShowBtns = false;
}
/**
* This option forces the display of the buttons passed by the input.
* It will override the default settings and take precedence over the standard settings.
*
* ```html
* <c8y-stepper-buttons
* [labels]="{ custom: 'Custom btn', cancel: 'Cancel btn' }"
* [showButtons]="{ custom: true, cancel: true }"
* ></c8y-stepper-buttons>
* ```
*
* @param btns An object that contains options for displaying buttons.
*/
set showButtons(btns) {
if (btns) {
this.showBtns = btns;
this.forceShowBtns = true;
}
}
/**
* @ignore
*/
ngAfterContentInit() {
if (!this.forceShowBtns) {
this.showBtns.cancel = this.onCancel.observers.length > 0;
this.showBtns.custom = this.onCustom.observers.length > 0;
}
if (this.stepper && this.stepper._steps && this.step && !this.forceShowBtns) {
this.showBtns.back = this.stepper._steps.first !== this.step;
this.showBtns.next = this.stepper._steps.last !== this.step;
}
if (this.step && this.step.stepControl) {
this.disabled = this.step.stepControl.invalid;
this.statusChangeSubscription = this.step.stepControl.statusChanges.subscribe(() => {
this.disabled = this.step.stepControl.invalid;
});
}
}
ngOnDestroy() {
if (this.statusChangeSubscription && !this.statusChangeSubscription.closed) {
this.statusChangeSubscription.unsubscribe();
}
}
/**
* Gets called when cancel button is clicked.
* It will emit immediate.
*/
cancel() {
this.onCancel.emit();
this.triggerEvent(ACTIONS_STEPPER.CLICK_STEPPER_CANCEL_BTN);
}
/**
* Gets called when next button is clicked. When onNext EventEmitter has an observer registered
* it will emit the following object {stepper: C8yStepper; step: CdkStep}.
* Otherwise it will call stepper.next() as default.
*/
next() {
this.stepper.selected.completed = true;
if (this.onNext.observers.length > 0) {
this.onNext.emit({ stepper: this.stepper, step: this.step });
}
else {
this.stepper.next();
}
this.triggerEvent(ACTIONS_STEPPER.CLICK_STEPPER_NEXT_BTN);
}
/**
* Gets called when back button is clicked. When onBack EventEmitter has an observer registered
* it will emit the following object {stepper: C8yStepper; step: CdkStep}.
* Otherwise it will call stepper.previous() as default.
*/
back() {
this.stepper.selected.completed = false;
if (this.onBack.observers.length > 0) {
this.onBack.emit({ stepper: this.stepper, step: this.step });
}
else {
this.stepper.previous();
}
this.triggerEvent(ACTIONS_STEPPER.CLICK_STEPPER_BACK_BTN);
}
/**
* Gets called when the custom button is clicked.
* It will emit immediately.
*/
custom() {
this.onCustom.emit();
this.triggerEvent(ACTIONS_STEPPER.CLICK_STEPPER_CUSTOM_BTN);
}
triggerEvent(action) {
const eventData = {
...this.stepper.productExperienceEvent?.data,
action,
step: this.gainsightService.translateToEnglish(this.step.label)
};
const eventName = this.stepper.productExperienceEvent?.eventName || 'c8yStepper';
this.gainsightService.triggerEvent(eventName, eventData);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C8yStepperButtons, deps: [{ token: i1.C8yStepper }, { token: i2.CdkStep }, { token: i3.GainsightService }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: C8yStepperButtons, selector: "c8y-stepper-buttons", inputs: { labels: "labels", pending: "pending", disabled: "disabled", showButtons: "showButtons" }, outputs: { onCancel: "onCancel", onNext: "onNext", onBack: "onBack", onCustom: "onCustom" }, ngImport: i0, template: "<div class=\"text-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ labels?.cancel || 'Cancel' | translate }}\"\n data-cy=\"cancel\"\n type=\"button\"\n *ngIf=\"showBtns.cancel\"\n (click)=\"cancel()\"\n >\n <span\n title=\"{{ labels?.cancel | translate }}\"\n *ngIf=\"labels?.cancel; else cancelLabel\"\n >\n {{ labels?.cancel | translate }}\n </span>\n <ng-template #cancelLabel>\n <span title=\"{{ 'Cancel' | translate }}\">{{ 'Cancel' | translate }}</span>\n </ng-template>\n </button>\n <button\n class=\"btn btn-default\"\n title=\"{{ labels?.back || 'Back' | translate }}\"\n type=\"button\"\n *ngIf=\"showBtns.back\"\n (click)=\"back()\"\n [disabled]=\"pending\"\n data-cy=\"back\"\n >\n <span\n title=\"{{ labels?.back | translate }}\"\n *ngIf=\"labels?.back; else backLabel\"\n >\n {{ labels?.back | translate }}\n </span>\n <ng-template #backLabel>\n <span title=\"{{ 'Back' | translate }}\">{{ 'Back' | translate }}</span>\n </ng-template>\n </button>\n <button\n class=\"btn\"\n title=\"{{ labels?.custom || 'Complete' | translate }}\"\n type=\"button\"\n *ngIf=\"showBtns.custom\"\n (click)=\"custom()\"\n [ngClass]=\"{\n 'btn-default': showBtns.next,\n 'btn-primary': !showBtns.next,\n 'btn-pending': pending\n }\"\n [disabled]=\"disabled\"\n data-cy=\"custom\"\n >\n <span\n title=\"{{ labels?.custom | translate }}\"\n *ngIf=\"labels?.custom; else customLabel\"\n >\n {{ labels?.custom | translate }}\n </span>\n <ng-template #customLabel>\n <span title=\"{{ 'Complete' | translate }}\">{{ 'Complete' | translate }}</span>\n </ng-template>\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ labels?.next || 'Next' | translate }}\"\n type=\"button\"\n (click)=\"next()\"\n *ngIf=\"showBtns.next\"\n [ngClass]=\"{ 'btn-pending': pending }\"\n [disabled]=\"disabled\"\n data-cy=\"next\"\n >\n <span\n title=\"{{ labels?.next | translate }}\"\n *ngIf=\"labels?.next; else nextLabel\"\n >\n {{ labels?.next | translate }}\n </span>\n <ng-template #nextLabel>\n <span title=\"{{ 'Next' | translate }}\">{{ 'Next' | translate }}</span>\n </ng-template>\n </button>\n <ng-content select=\"button\"></ng-content>\n</div>\n", dependencies: [{ kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i5.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C8yStepperButtons, decorators: [{
type: Component,
args: [{ selector: 'c8y-stepper-buttons', template: "<div class=\"text-center\">\n <button\n class=\"btn btn-default\"\n title=\"{{ labels?.cancel || 'Cancel' | translate }}\"\n data-cy=\"cancel\"\n type=\"button\"\n *ngIf=\"showBtns.cancel\"\n (click)=\"cancel()\"\n >\n <span\n title=\"{{ labels?.cancel | translate }}\"\n *ngIf=\"labels?.cancel; else cancelLabel\"\n >\n {{ labels?.cancel | translate }}\n </span>\n <ng-template #cancelLabel>\n <span title=\"{{ 'Cancel' | translate }}\">{{ 'Cancel' | translate }}</span>\n </ng-template>\n </button>\n <button\n class=\"btn btn-default\"\n title=\"{{ labels?.back || 'Back' | translate }}\"\n type=\"button\"\n *ngIf=\"showBtns.back\"\n (click)=\"back()\"\n [disabled]=\"pending\"\n data-cy=\"back\"\n >\n <span\n title=\"{{ labels?.back | translate }}\"\n *ngIf=\"labels?.back; else backLabel\"\n >\n {{ labels?.back | translate }}\n </span>\n <ng-template #backLabel>\n <span title=\"{{ 'Back' | translate }}\">{{ 'Back' | translate }}</span>\n </ng-template>\n </button>\n <button\n class=\"btn\"\n title=\"{{ labels?.custom || 'Complete' | translate }}\"\n type=\"button\"\n *ngIf=\"showBtns.custom\"\n (click)=\"custom()\"\n [ngClass]=\"{\n 'btn-default': showBtns.next,\n 'btn-primary': !showBtns.next,\n 'btn-pending': pending\n }\"\n [disabled]=\"disabled\"\n data-cy=\"custom\"\n >\n <span\n title=\"{{ labels?.custom | translate }}\"\n *ngIf=\"labels?.custom; else customLabel\"\n >\n {{ labels?.custom | translate }}\n </span>\n <ng-template #customLabel>\n <span title=\"{{ 'Complete' | translate }}\">{{ 'Complete' | translate }}</span>\n </ng-template>\n </button>\n <button\n class=\"btn btn-primary\"\n title=\"{{ labels?.next || 'Next' | translate }}\"\n type=\"button\"\n (click)=\"next()\"\n *ngIf=\"showBtns.next\"\n [ngClass]=\"{ 'btn-pending': pending }\"\n [disabled]=\"disabled\"\n data-cy=\"next\"\n >\n <span\n title=\"{{ labels?.next | translate }}\"\n *ngIf=\"labels?.next; else nextLabel\"\n >\n {{ labels?.next | translate }}\n </span>\n <ng-template #nextLabel>\n <span title=\"{{ 'Next' | translate }}\">{{ 'Next' | translate }}</span>\n </ng-template>\n </button>\n <ng-content select=\"button\"></ng-content>\n</div>\n" }]
}], ctorParameters: () => [{ type: i1.C8yStepper }, { type: i2.CdkStep }, { type: i3.GainsightService }], propDecorators: { labels: [{
type: Input
}], pending: [{
type: Input
}], disabled: [{
type: Input
}], onCancel: [{
type: Output
}], onNext: [{
type: Output
}], onBack: [{
type: Output
}], onCustom: [{
type: Output
}], showButtons: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcHBlci1idXR0b25zLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2NvcmUvc3RlcHBlci9zdGVwcGVyLWJ1dHRvbnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vY29yZS9zdGVwcGVyL3N0ZXBwZXItYnV0dG9ucy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDL0MsT0FBTyxFQUFvQixTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFcEcsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDM0UsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3pELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7Ozs7OztBQUdqRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrREc7QUFLSCxNQUFNLE9BQU8saUJBQWlCO0lBc0Q1QixZQUNVLE9BQW1CLEVBQ25CLElBQWEsRUFDYixnQkFBa0M7UUFGbEMsWUFBTyxHQUFQLE9BQU8sQ0FBWTtRQUNuQixTQUFJLEdBQUosSUFBSSxDQUFTO1FBQ2IscUJBQWdCLEdBQWhCLGdCQUFnQixDQUFrQjtRQW5ENUM7Ozs7V0FJRztRQUNNLFlBQU8sR0FBYSxLQUFLLENBQUM7UUFFbkM7O1dBRUc7UUFDTSxhQUFRLEdBQWEsS0FBSyxDQUFDO1FBRXBDOztXQUVHO1FBQ08sYUFBUSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDeEM7O1dBRUc7UUFDTyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQTBDLENBQUM7UUFFOUU7O1dBRUc7UUFDTyxXQUFNLEdBQUcsSUFBSSxZQUFZLEVBQTBDLENBQUM7UUFFOUU7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QUFDO1FBQ2pGLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzNELENBQUM7K0dBcktVLGlCQUFpQjttR0FBakIsaUJBQWlCLDRQQy9EOUIsNjJFQW9GQTs7NEZEckJhLGlCQUFpQjtrQkFKN0IsU0FBUzsrQkFDRSxxQkFBcUI7b0lBUXRCLE1BQU07c0JBQWQsS0FBSztnQkFNRyxPQUFPO3NCQUFmLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFLSSxRQUFRO3NCQUFqQixNQUFNO2dCQUlHLE1BQU07c0JBQWYsTUFBTTtnQkFLRyxNQUFNO3NCQUFmLE1BQU07Z0JBS0csUUFBUTtzQkFBakIsTUFBTTtnQkFzQ00sV0FBVztzQkFBdkIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENka1N0ZXAgfSBmcm9tICdAYW5ndWxhci9jZGsvc3RlcHBlcic7XG5pbXBvcnQgeyBBZnRlckNvbnRlbnRJbml0LCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uRGVzdHJveSwgT3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEdhaW5zaWdodFNlcnZpY2UgfSBmcm9tICcuLi9wcm9kdWN0LWV4cGVyaWVuY2UvZ2FpbnNpZ2h0LnNlcnZpY2UnO1xuaW1wb3J0IHsgQUNUSU9OU19TVEVQUEVSIH0gZnJvbSAnLi9zdGVwcGVyLXB4LmNvbnN0YW50cyc7XG5pbXBvcnQgeyBDOHlTdGVwcGVyIH0gZnJvbSAnLi9zdGVwcGVyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTdGVwcGVyQnV0dG9uc1Zpc2liaWxpdHkgfSBmcm9tICcuL3N0ZXBwZXIubW9kZWwnO1xuXG4vKipcbiAqIGBDOHlTdGVwcGVyQnV0dG9uc2AgcHJvdmlkZXMgYSBjb252ZW5pZW50IHdheSB0byBoYXZlLCBhY2NvcmRpbmcgdG9cbiAqIHRoZSBgQzh5U3RlcHBlcmAgYW5kIGVhY2ggYGNkay1zdGVwYCwgYnV0dG9ucyB0byBuYXZpZ2F0ZSBiZXR3ZWVuIHN0ZXBzIG9yIHRvIGNhbmNlbCB0aGUgd2hvbGVcbiAqIHN0ZXAtcHJvY2Vzcy4gQnV0dG9ucyByZW5kZXJlZCB3aXRoIHRoZSBoZWxwIG9mIHRoaXMgY29tcG9uZW50IHdpbGwgdXNlIHRoZSBicmFuZGluZyBjc3MuXG4gKlxuICogQnkgZGVmYXVsdCBhbGwgc3RlcHMgd2l0aCB0aGlzIGNvbXBvbmVudCBpbiB1c2Ugd2lsbCByZW5kZXIgYSBuZXh0IGJ1dHRvbiwgZXhwZWN0IHRoZSBsYXN0IHN0ZXAuXG4gKiBUaGUgb3RoZXIgd2F5IGFyb3VuZCwgZXZlcnkgc3RlcCB1c2luZyB0aGlzIGNvbXBvbmVudCB3aWxsIHJlbmRlciBhIGJhY2sgYnV0dG9uLCBleHBlY3QgdGhlIGZpcnN0IHN0ZXAuXG4gKiBUbyBnZXQgYSBjYW5jZWwgYnV0dG9uIHJlbmRlcmVkIHlvdSBuZWVkIHRvIGhhbmRsZSB0aGUgb25DYW5jZWwgZXZlbnQuXG4gKiBGb3IgbmV4dCBhbmQgYmFjayBidXR0b24geW91IGRvbid0IG5lZWQgdG8gaGFuZGxlIHRoZSBhdmFpbGFibGUgZXZlbnRzIGBvbk5leHRgIGFuZCBgb25CYWNrYCBiZWNhdXNlIGRlZmF1bHQgYmVoYXZpb3JcbiAqIGlzIGltcGxlbWVudGVkLiBUaGUgZGVmYXVsdCB3aWxsIGp1c3QgY2FsbCwgYWNjb3JkaW5nIHRvIHRoZSBidXR0b24sIHRoZSBgc3RlcHBlci5uZXh0KClgIG9yIGBzdGVwcGVyLnByZXZpb3VzKClgXG4gKiBtZXRob2RzIGFuZCBtb3ZlcyB0aGUgc3RlcHBlciBmb3J0aCBvciBiYWNrLiBVc2luZyB0aGUgYEV2ZW50RW1pdHRlcmAgYG9uTmV4dGAgYW5kIGBvbkJhY2tgIHdpbGwgZW1pdCBmb3IgeW91IHRoZSBmb2xsb3dpbmdcbiAqIG9iamVjdDogYHtzdGVwcGVyOiBDOHlTdGVwcGVyLCBzdGVwOiBDZGtTdGVwfWAuIFRoaXMgaXMgdXNlZnVsIGlmIHlvdSBuZWVkIHRvIGltcGxlbWVudCBjdXN0b20gbG9naWMgYmVmb3JlIG1vdmluZ1xuICogdG8gdGhlIG5leHQgc3RlcCBvciBzZW5kaW5nIGRhdGEgdG8gYSBiYWNrZW5kLiBJbiB0aGlzIGNhc2UgeW91IG5lZWQgdG8gdGVsbCB0aGUgc3RlcHBlciB0byBtb3ZlIGZvcndhcmQgb3IgYmFja1xuICogb24geW91ciBvd24uXG4gKlxuICogV2l0aCB0aGUgY29tcG9uZW50IGlucHV0IGBbbGFiZWxzXWAgeW91IGNhbiBjaGFuZ2UgdGhlIGxhYmVsIG9mIGVhY2ggYnV0dG9uIGluIGVhY2ggc3RlcC4gSXQgdGFrZXMgYW4gb2JqZWN0IGxpa2UgdGhpczpcbiAqIGB7bmV4dD86IHN0cmluZywgYmFjaz86IHN0cmluZywgY2FuY2VsPzogc3RyaW5nfWBcbiAqXG4gKiBUaGUgYFtwZW5kaW5nXWAgaW5wdXQgaXMgb2YgdHlwZSBib29sZWFuIGFuZCB3aWxsIGVuYWJsZSBjc3MgYW5pbWF0aW9uIGZvciB0aGUgbmV4dCBidXR0b24gd2hlbiB0cnVlLlxuICpcbiAqIElmIHRoZSBgY2RrLXN0ZXBgIHByb3ZpZGVzIGEgYHN0ZXBDb250cm9sYCB0aGUgY29tcG9uZW50IHdpbGwgc2V0IHRoZSBuZXh0IGJ1dHRvbiBkaXNhYmxlZCB3aGVuIHRoZSBmb3JtR3JvdXBcbiAqIGJlaGluZCBpdCBpcyBpbnZhbGlkLiBBcyBsb25nIGFzIHRoZSBgW3BlbmRpbmddYCBpbnB1dCBpcyB0cnVlIHRoZSBiYWNrIGFuZCBuZXh0IGJ1dHRvbiBpcyBhbHNvIGRpc2FibGVkLlxuICogVGhpcyB3aWxsIHByZXZlbnQgbXVsdGlwbGUgY2xpY2tzIHdoaWxlIHJ1bm5pbmcgYSByZXF1ZXN0IG9yIHN0ZXBwaW5nIGJhY2sgd2hpbGUgYSByZXF1ZXN0IGlzIG9uZ29pbmcuXG4gKlxuICogYGBgaHRtbFxuICogPGM4eS1zdGVwcGVyPlxuICogIDxjZGstc3RlcD5cbiAqICAgIDwhLS1cbiAqICAgICAgeW91ciBodG1sIGNvZGVcbiAqICAgICAgICAgIC4uLlxuICogICAgICAgICAgLi4uICAgIC0tPlxuICogICAgPGM4eS1zdGVwcGVyLWJ1dHRvbnNcbiAqICAgICAob25OZXh0KT1cInNhdmUoKVwiXG4gKiAgICAgW2xhYmVsc109XCJ7IG5leHQ6ICdTYXZlJyB9XCJcbiAqICAgICBbcGVuZGluZ109XCJwZW5kaW5nU3RhdHVzXCJcbiAqICAgICA+PC9jOHktc3RlcHBlci1idXR0b25zPlxuICogIDwvY2RrLXN0ZXA+XG4gKiA8L2M4eS1zdGVwcGVyPlxuICogYGBgXG4gKlxuICogYGBganNcbiAqIC8vIGluIHlvdXIgY29tcG9uZW50OlxuICogYXN5bmMgc2F2ZSgpIHtcbiAqICAgdGhpcy5wZW5kaW5nU3RhdHVzID0gdHJ1ZTtcbiAqICAgLy8geW91ciBhc3luYyByZXF1ZXN0IGdvZXMgaGVyZSAuLi5cbiAqICAgLy8gYXdhaXQgc29tZXRoaW5nKCk7XG4gKiAgIHRoaXMucGVuZGluZ1N0YXR1cyA9IGZhbHNlO1xuICogICB0aGlzLnN0ZXBwZXIubmV4dCgpO1xuICogfVxuICogYGBgXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2M4eS1zdGVwcGVyLWJ1dHRvbnMnLFxuICB0ZW1wbGF0ZVVybDogJy4vc3RlcHBlci1idXR0b25zLmNvbXBvbmVudC5odG1sJ1xufSlcbmV4cG9ydCBjbGFzcyBDOHlTdGVwcGVyQnV0dG9ucyBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQsIE9uRGVzdHJveSB7XG4gIC8qKlxuICAgKiBPcHRpb25hbFxuICAgKiBTcGVjaWZ5IGN1c3RvbSBsYWJlbHMgZm9yIGVhY2ggYnV0dG9uIChjYW5jZWwsIGJhY2sgb3IgbmV4dClcbiAgICovXG4gIEBJbnB1dCgpIGxhYmVscz86IHsgY2FuY2VsPzogc3RyaW5nOyBiYWNrPzogc3RyaW5nOyBuZXh0Pzogc3RyaW5nOyBjdXN0b20/OiBzdHJpbmcgfTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsXG4gICAqIEluZGljYXRlcyBpZiBhIHJlcXVlc3QgaXMgcGVuZGluZyBhbmQgc2V0cyB0aGUgbmV4dCBidXR0b25cbiAgICogdG8gZGlzYWJsZWQgd2hlbiB0cnVlXG4gICAqL1xuICBASW5wdXQoKSBwZW5kaW5nPzogYm9vbGVhbiA9IGZhbHNlO1xuXG4gIC8qKlxuICAgKiBEaXNhYmxlZCBzdGF0ZSBvZiBhIGJ1dHRvblxuICAgKi9cbiAgQElucHV0KCkgZGlzYWJsZWQ/OiBib29sZWFuID0gZmFsc2U7XG5cbiAgLyoqXG4gICAqIEV2ZW50RW1pdHRlciB3aGljaCBlbWl0cyB3aGVuIGNhbmNlbCBidXR0b24gaXMgY2xpY2tlZFxuICAgKi9cbiAgQE91dHB1dCgpIG9uQ2FuY2VsID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAvKipcbiAgICogRXZlbnRFbWl0dGVyIHdoaWNoIGVtaXRzIHtzdGVwcGVyOiBDOHlTdGVwcGVyOyBzdGVwOiBDZGtTdGVwfSB3aGVuIG5leHQgYnV0dG9uIGlzIGNsaWNrZWQuXG4gICAqL1xuICBAT3V0cHV0KCkgb25OZXh0ID0gbmV3IEV2ZW50RW1pdHRlcjx7IHN0ZXBwZXI6IEM4eVN0ZXBwZXI7IHN0ZXA6IENka1N0ZXAgfT4oKTtcblxuICAvKipcbiAgICogRXZlbnRFbWl0dGVyIHdoaWNoIGVtaXRzIHtzdGVwcGVyOiBDOHlTdGVwcGVyOyBzdGVwOiBDZGtTdGVwfSB3aGVuIGJhY2sgYnV0dG9uIGlzIGNsaWNrZWQuXG4gICAqL1xuICBAT3V0cHV0KCkgb25CYWNrID0gbmV3IEV2ZW50RW1pdHRlcjx7IHN0ZXBwZXI6IEM4eVN0ZXBwZXI7IHN0ZXA6IENka1N0ZXAgfT4oKTtcblxuICAvKipcbiAgICogRXZlbnRFbWl0dGVyIHdoaWNoIGVtaXRzIHdoZW4gdGhlIG9wdGlvbmFsIGN1c3RvbSBidXR0b24gaXMgY2xpY2tlZFxuICAgKi9cbiAgQE91dHB1dCgpIG9uQ3VzdG9tID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIC8qKlxuICAgKiBJbmRpY2F0b3Igd2hpY2ggYnV0dG9uIHNob3VsZCBiZSBzaG93bi5cbiAgICogQmFzZWQgb24gdGhlIGNkay1zdGVwcyB3aXRoaW4gdGhlIGM4eS1zdGVwcGVyXG4gICAqIG5leHQgYW5kIGJhY2sgYnV0dG9ucyBhcmUgcmVuZGVyZWQuXG4gICAqL1xuICBzaG93QnRuczogU3RlcHBlckJ1dHRvbnNWaXNpYmlsaXR5ID0ge1xuICAgIGNhbmNlbDogZmFsc2UsXG4gICAgYmFjazogZmFsc2UsXG4gICAgbmV4dDogZmFsc2UsXG4gICAgY3VzdG9tOiBmYWxzZVxuICB9O1xuICAvKipcbiAgICogRmxhZyB0aGF0IGluZGljYXRlcyB0aGF0IHRoZSBkZWZhdWx0IHNldHRpbmdzIGRlZmluZWQgaW4gdGhlIHNob3dCdG5zIGhhdmUgYmVlbiBvdmVyd3JpdHRlbi5cbiAgICovXG4gIGZvcmNlU2hvd0J0bnMgPSBmYWxzZTtcblxuICBwcml2YXRlIHN0YXR1c0NoYW5nZVN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHN0ZXBwZXI6IEM4eVN0ZXBwZXIsXG4gICAgcHJpdmF0ZSBzdGVwOiBDZGtTdGVwLFxuICAgIHByaXZhdGUgZ2FpbnNpZ2h0U2VydmljZTogR2FpbnNpZ2h0U2VydmljZVxuICApIHt9XG5cbiAgLyoqXG4gICAqIFRoaXMgb3B0aW9uIGZvcmNlcyB0aGUgZGlzcGxheSBvZiB0aGUgYnV0dG9ucyBwYXNzZWQgYnkgdGhlIGlucHV0LlxuICAgKiBJdCB3aWxsIG92ZXJyaWRlIHRoZSBkZWZhdWx0IHNldHRpbmdzIGFuZCB0YWtlIHByZWNlZGVuY2Ugb3ZlciB0aGUgc3RhbmRhcmQgc2V0dGluZ3MuXG4gICAqXG4gICAqIGBgYGh0bWxcbiAgICogPGM4eS1zdGVwcGVyLWJ1dHRvbnNcbiAgICogICBbbGFiZWxzXT1cInsgY3VzdG9tOiAnQ3VzdG9tIGJ0bicsIGNhbmNlbDogJ0NhbmNlbCBidG4nIH1cIlxuICAgKiAgIFtzaG93QnV0dG9uc109XCJ7IGN1c3RvbTogdHJ1ZSwgY2FuY2VsOiB0cnVlIH1cIlxuICAgKiA+PC9jOHktc3RlcHBlci1idXR0b25zPlxuICAgKiBgYGBcbiAgICpcbiAgICogQHBhcmFtIGJ0bnMgQW4gb2JqZWN0IHRoYXQgY29udGFpbnMgb3B0aW9ucyBmb3IgZGlzcGxheWluZyBidXR0b25zLlxuICAgKi9cbiAgQElucHV0KCkgc2V0IHNob3dCdXR0b25zKGJ0bnM6IFN0ZXBwZXJCdXR0b25zVmlzaWJpbGl0eSkge1xuICAgIGlmIChidG5zKSB7XG4gICAgICB0aGlzLnNob3dCdG5zID0gYnRucztcbiAgICAgIHRoaXMuZm9yY2VTaG93QnRucyA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBpZ25vcmVcbiAgICovXG4gIG5nQWZ0ZXJDb250ZW50SW5pdCgpIHtcbiAgICBpZiAoIXRoaXMuZm9yY2VTaG93QnRucykge1xuICAgICAgdGhpcy5zaG93QnRucy5jYW5jZWwgPSB0aGlzLm9uQ2FuY2VsLm9ic2VydmVycy5sZW5ndGggPiAwO1xuICAgICAgdGhpcy5zaG93QnRucy5jdXN0b20gPSB0aGlzLm9uQ3VzdG9tLm9ic2VydmVycy5sZW5ndGggPiAwO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnN0ZXBwZXIgJiYgdGhpcy5zdGVwcGVyLl9zdGVwcyAmJiB0aGlzLnN0ZXAgJiYgIXRoaXMuZm9yY2VTaG93QnRucykge1xuICAgICAgdGhpcy5zaG93QnRucy5iYWNrID0gdGhpcy5zdGVwcGVyLl9zdGVwcy5maXJzdCAhPT0gdGhpcy5zdGVwO1xuICAgICAgdGhpcy5zaG93QnRucy5uZXh0ID0gdGhpcy5zdGVwcGVyLl9zdGVwcy5sYXN0ICE9PSB0aGlzLnN0ZXA7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc3RlcCAmJiB0aGlzLnN0ZXAuc3RlcENvbnRyb2wpIHtcbiAgICAgIHRoaXMuZGlzYWJsZWQgPSB0aGlzLnN0ZXAuc3RlcENvbnRyb2wuaW52YWxpZDtcblxuICAgICAgdGhpcy5zdGF0dXNDaGFuZ2VTdWJzY3JpcHRpb24gPSB0aGlzLnN0ZXAuc3RlcENvbnRyb2wuc3RhdHVzQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLmRpc2FibGVkID0gdGhpcy5zdGVwLnN0ZXBDb250cm9sLmludmFsaWQ7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBpZiAodGhpcy5zdGF0dXNDaGFuZ2VTdWJzY3JpcHRpb24gJiYgIXRoaXMuc3RhdHVzQ2hhbmdlU3Vic2NyaXB0aW9uLmNsb3NlZCkge1xuICAgICAgdGhpcy5zdGF0dXNDaGFuZ2VTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBjYWxsZWQgd2hlbiBjYW5jZWwgYnV0dG9uIGlzIGNsaWNrZWQuXG4gICAqIEl0IHdpbGwgZW1pdCBpbW1lZGlhdGUuXG4gICAqL1xuICBjYW5jZWwoKSB7XG4gICAgdGhpcy5vbkNhbmNlbC5lbWl0KCk7XG4gICAgdGhpcy50cmlnZ2VyRXZlbnQoQUNUSU9OU19TVEVQUEVSLkNMSUNLX1NURVBQRVJfQ0FOQ0VMX0JUTik7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBjYWxsZWQgd2hlbiBuZXh0IGJ1dHRvbiBpcyBjbGlja2VkLiBXaGVuIG9uTmV4dCBFdmVudEVtaXR0ZXIgaGFzIGFuIG9ic2VydmVyIHJlZ2lzdGVyZWRcbiAgICogaXQgd2lsbCBlbWl0IHRoZSBmb2xsb3dpbmcgb2JqZWN0IHtzdGVwcGVyOiBDOHlTdGVwcGVyOyBzdGVwOiBDZGtTdGVwfS5cbiAgICogT3RoZXJ3aXNlIGl0IHdpbGwgY2FsbCBzdGVwcGVyLm5leHQoKSBhcyBkZWZhdWx0LlxuICAgKi9cbiAgbmV4dCgpIHtcbiAgICB0aGlzLnN0ZXBwZXIuc2VsZWN0ZWQuY29tcGxldGVkID0gdHJ1ZTtcbiAgICBpZiAodGhpcy5vbk5leHQub2JzZXJ2ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMub25OZXh0LmVtaXQoeyBzdGVwcGVyOiB0aGlzLnN0ZXBwZXIsIHN0ZXA6IHRoaXMuc3RlcCB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGVwcGVyLm5leHQoKTtcbiAgICB9XG4gICAgdGhpcy50cmlnZ2VyRXZlbnQoQUNUSU9OU19TVEVQUEVSLkNMSUNLX1NURVBQRVJfTkVYVF9CVE4pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgY2FsbGVkIHdoZW4gYmFjayBidXR0b24gaXMgY2xpY2tlZC4gV2hlbiBvbkJhY2sgRXZlbnRFbWl0dGVyIGhhcyBhbiBvYnNlcnZlciByZWdpc3RlcmVkXG4gICAqIGl0IHdpbGwgZW1pdCB0aGUgZm9sbG93aW5nIG9iamVjdCB7c3RlcHBlcjogQzh5U3RlcHBlcjsgc3RlcDogQ2RrU3RlcH0uXG4gICAqIE90aGVyd2lzZSBpdCB3aWxsIGNhbGwgc3RlcHBlci5wcmV2aW91cygpIGFzIGRlZmF1bHQuXG4gICAqL1xuICBiYWNrKCkge1xuICAgIHRoaXMuc3RlcHBlci5zZWxlY3RlZC5jb21wbGV0ZWQgPSBmYWxzZTtcbiAgICBpZiAodGhpcy5vbkJhY2sub2JzZXJ2ZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHRoaXMub25CYWNrLmVtaXQoeyBzdGVwcGVyOiB0aGlzLnN0ZXBwZXIsIHN0ZXA6IHRoaXMuc3RlcCB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGVwcGVyLnByZXZpb3VzKCk7XG4gICAgfVxuICAgIHRoaXMudHJpZ2dlckV2ZW50KEFDVElPTlNfU1RFUFBFUi5DTElDS19TVEVQUEVSX0JBQ0tfQlROKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIGNhbGxlZCB3aGVuIHRoZSBjdXN0b20gYnV0dG9uIGlzIGNsaWNrZWQuXG4gICAqIEl0IHdpbGwgZW1pdCBpbW1lZGlhdGVseS5cbiAgICovXG4gIGN1c3RvbSgpIHtcbiAgICB0aGlzLm9uQ3VzdG9tLmVtaXQoKTtcbiAgICB0aGlzLnRyaWdnZXJFdmVudChBQ1RJT05TX1NURVBQRVIuQ0xJQ0tfU1RFUFBFUl9DVVNUT01fQlROKTtcbiAgfVxuXG4gIHByaXZhdGUgdHJpZ2dlckV2ZW50KGFjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgZXZlbnREYXRhID0ge1xuICAgICAgLi4udGhpcy5zdGVwcGVyLnByb2R1Y3RFeHBlcmllbmNlRXZlbnQ/LmRhdGEsXG4gICAgICBhY3Rpb24sXG4gICAgICBzdGVwOiB0aGlzLmdhaW5zaWdodFNlcnZpY2UudHJhbnNsYXRlVG9FbmdsaXNoKHRoaXMuc3RlcC5sYWJlbClcbiAgICB9O1xuICAgIGNvbnN0IGV2ZW50TmFtZSA9IHRoaXMuc3RlcHBlci5wcm9kdWN0RXhwZXJpZW5jZUV2ZW50Py5ldmVudE5hbWUgfHwgJ2M4eVN0ZXBwZXInO1xuICAgIHRoaXMuZ2FpbnNpZ2h0U2VydmljZS50cmlnZ2VyRXZlbnQoZXZlbnROYW1lLCBldmVudERhdGEpO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwidGV4dC1jZW50ZXJcIj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuIGJ0bi1kZWZhdWx0XCJcbiAgICB0aXRsZT1cInt7IGxhYmVscz8uY2FuY2VsIHx8ICdDYW5jZWwnIHwgdHJhbnNsYXRlIH19XCJcbiAgICBkYXRhLWN5PVwiY2FuY2VsXCJcbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAqbmdJZj1cInNob3dCdG5zLmNhbmNlbFwiXG4gICAgKGNsaWNrKT1cImNhbmNlbCgpXCJcbiAgPlxuICAgIDxzcGFuXG4gICAgICB0aXRsZT1cInt7IGxhYmVscz8uY2FuY2VsIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgICpuZ0lmPVwibGFiZWxzPy5jYW5jZWw7IGVsc2UgY2FuY2VsTGFiZWxcIlxuICAgID5cbiAgICAgIHt7IGxhYmVscz8uY2FuY2VsIHwgdHJhbnNsYXRlIH19XG4gICAgPC9zcGFuPlxuICAgIDxuZy10ZW1wbGF0ZSAjY2FuY2VsTGFiZWw+XG4gICAgICA8c3BhbiB0aXRsZT1cInt7ICdDYW5jZWwnIHwgdHJhbnNsYXRlIH19XCI+e3sgJ0NhbmNlbCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9idXR0b24+XG4gIDxidXR0b25cbiAgICBjbGFzcz1cImJ0biBidG4tZGVmYXVsdFwiXG4gICAgdGl0bGU9XCJ7eyBsYWJlbHM/LmJhY2sgfHwgJ0JhY2snIHwgdHJhbnNsYXRlIH19XCJcbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAqbmdJZj1cInNob3dCdG5zLmJhY2tcIlxuICAgIChjbGljayk9XCJiYWNrKClcIlxuICAgIFtkaXNhYmxlZF09XCJwZW5kaW5nXCJcbiAgICBkYXRhLWN5PVwiYmFja1wiXG4gID5cbiAgICA8c3BhblxuICAgICAgdGl0bGU9XCJ7eyBsYWJlbHM/LmJhY2sgfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgKm5nSWY9XCJsYWJlbHM/LmJhY2s7IGVsc2UgYmFja0xhYmVsXCJcbiAgICA+XG4gICAgICB7eyBsYWJlbHM/LmJhY2sgfCB0cmFuc2xhdGUgfX1cbiAgICA8L3NwYW4+XG4gICAgPG5nLXRlbXBsYXRlICNiYWNrTGFiZWw+XG4gICAgICA8c3BhbiB0aXRsZT1cInt7ICdCYWNrJyB8IHRyYW5zbGF0ZSB9fVwiPnt7ICdCYWNrJyB8IHRyYW5zbGF0ZSB9fTwvc3Bhbj5cbiAgICA8L25nLXRlbXBsYXRlPlxuICA8L2J1dHRvbj5cbiAgPGJ1dHRvblxuICAgIGNsYXNzPVwiYnRuXCJcbiAgICB0aXRsZT1cInt7IGxhYmVscz8uY3VzdG9tIHx8ICdDb21wbGV0ZScgfCB0cmFuc2xhdGUgfX1cIlxuICAgIHR5cGU9XCJidXR0b25cIlxuICAgICpuZ0lmPVwic2hvd0J0bnMuY3VzdG9tXCJcbiAgICAoY2xpY2spPVwiY3VzdG9tKClcIlxuICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICdidG4tZGVmYXVsdCc6IHNob3dCdG5zLm5leHQsXG4gICAgICAnYnRuLXByaW1hcnknOiAhc2hvd0J0bnMubmV4dCxcbiAgICAgICdidG4tcGVuZGluZyc6IHBlbmRpbmdcbiAgICB9XCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIGRhdGEtY3k9XCJjdXN0b21cIlxuICA+XG4gICAgPHNwYW5cbiAgICAgIHRpdGxlPVwie3sgbGFiZWxzPy5jdXN0b20gfCB0cmFuc2xhdGUgfX1cIlxuICAgICAgKm5nSWY9XCJsYWJlbHM/LmN1c3RvbTsgZWxzZSBjdXN0b21MYWJlbFwiXG4gICAgPlxuICAgICAge3sgbGFiZWxzPy5jdXN0b20gfCB0cmFuc2xhdGUgfX1cbiAgICA8L3NwYW4+XG4gICAgPG5nLXRlbXBsYXRlICNjdXN0b21MYWJlbD5cbiAgICAgIDxzcGFuIHRpdGxlPVwie3sgJ0NvbXBsZXRlJyB8IHRyYW5zbGF0ZSB9fVwiPnt7ICdDb21wbGV0ZScgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgPC9idXR0b24+XG4gIDxidXR0b25cbiAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiXG4gICAgdGl0bGU9XCJ7eyBsYWJlbHM/Lm5leHQgfHwgJ05leHQnIHwgdHJhbnNsYXRlIH19XCJcbiAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAoY2xpY2spPVwibmV4dCgpXCJcbiAgICAqbmdJZj1cInNob3dCdG5zLm5leHRcIlxuICAgIFtuZ0NsYXNzXT1cInsgJ2J0bi1wZW5kaW5nJzogcGVuZGluZyB9XCJcbiAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgIGRhdGEtY3k9XCJuZXh0XCJcbiAgPlxuICAgIDxzcGFuXG4gICAgICB0aXRsZT1cInt7IGxhYmVscz8ubmV4dCB8IHRyYW5zbGF0ZSB9fVwiXG4gICAgICAqbmdJZj1cImxhYmVscz8ubmV4dDsgZWxzZSBuZXh0TGFiZWxcIlxuICAgID5cbiAgICAgIHt7IGxhYmVscz8ubmV4dCB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvc3Bhbj5cbiAgICA8bmctdGVtcGxhdGUgI25leHRMYWJlbD5cbiAgICAgIDxzcGFuIHRpdGxlPVwie3sgJ05leHQnIHwgdHJhbnNsYXRlIH19XCI+e3sgJ05leHQnIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvYnV0dG9uPlxuICA8bmctY29udGVudCBzZWxlY3Q9XCJidXR0b25cIj48L25nLWNvbnRlbnQ+XG48L2Rpdj5cbiJdfQ==