ng-zorro-antd
Version:
An enterprise-class UI components based on Ant Design and Angular
351 lines • 36.4 kB
JavaScript
/**
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/NG-ZORRO/ng-zorro-antd/blob/master/LICENSE
*/
import { ChangeDetectionStrategy, Component, ElementRef, EventEmitter, Input, Output, ViewChild, ViewChildren, ViewEncapsulation } from '@angular/core';
import { Observable, fromEvent, merge } from 'rxjs';
import { startWith, switchMap } from 'rxjs/operators';
import { NzCheckboxComponent } from 'ng-zorro-antd/checkbox';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "ng-zorro-antd/checkbox";
import * as i3 from "ng-zorro-antd/empty";
import * as i4 from "./transfer-search.component";
export class NzTransferListComponent {
get validData() {
return this.dataSource.filter(w => !w.hide);
}
trackByHide(_index, item) {
// The `validData` is a getter which returns new array each time the property is read.
// This may lead to unexpected re-renders, tho the array hasn't been updated.
return item.hide;
}
updateCheckStatus() {
const validCount = this.dataSource.filter(w => !w.disabled).length;
this.stat.checkCount = this.dataSource.filter(w => w.checked && !w.disabled).length;
this.stat.shownCount = this.validData.length;
this.stat.checkAll = validCount > 0 && validCount === this.stat.checkCount;
this.stat.checkHalf = this.stat.checkCount > 0 && !this.stat.checkAll;
// Note: this is done explicitly since the internal `nzChecked` value may not be updated in edge cases.
// Consider the following flow:
// 1) the initial value of `stat.checkAll` is `false`
// 2) the user filters items
// 3) the user clicks "Select All" checkbox
// 4) the `NzCheckboxComponent` sets `nzChecked` to `true` internally
// 5) the user clicks "Move to right"
// 6) items are moved and the `updateCheckStatus` is invoked
// 7) the `stat.checkAll` value has never been updated in this flow, it's always been `false`
// 8) the `nzChecked` is still `true` and the checkbox is not unchecked
// This is because Angular checks bindings and it checked that `[nzChecked]="stat.checkAll"` has
// never been updated, so Angular did not set new `nzChecked` value on the checkbox.
this.headerCheckbox && (this.headerCheckbox.nzChecked = this.stat.checkAll);
}
// #endregion
// #region search
handleFilter(value) {
this.filter = value;
this.dataSource.forEach(item => {
item.hide = value.length > 0 && !this.matchFilter(value, item);
});
this.stat.shownCount = this.validData.length;
this.filterChange.emit({ direction: this.direction, value });
}
handleClear() {
this.handleFilter('');
}
matchFilter(text, item) {
if (this.filterOption) {
return this.filterOption(text, item);
}
return item.title.includes(text);
}
// #endregion
constructor(ngZone, cdr) {
this.ngZone = ngZone;
this.cdr = cdr;
// #region fields
this.direction = 'left';
this.titleText = '';
this.showSelectAll = true;
this.dataSource = [];
this.itemUnit = '';
this.itemsUnit = '';
this.filter = '';
this.disabled = false;
this.renderList = null;
this.render = null;
this.footer = null;
// events
this.handleSelectAll = new EventEmitter();
this.handleSelect = new EventEmitter();
this.filterChange = new EventEmitter();
this.stat = {
checkAll: false,
checkHalf: false,
checkCount: 0,
shownCount: 0
};
this.onItemSelect = (item) => {
if (this.disabled || item.disabled) {
return;
}
item.checked = !item.checked;
this.updateCheckStatus();
this.handleSelect.emit(item);
};
this.onItemSelectAll = (status) => {
this.dataSource.forEach(item => {
if (!item.disabled && !item.hide) {
item.checked = status;
}
});
this.updateCheckStatus();
this.handleSelectAll.emit(status);
};
}
markForCheck() {
this.updateCheckStatus();
this.cdr.markForCheck();
}
ngAfterViewInit() {
this.checkboxes.changes
.pipe(startWith(this.checkboxes), switchMap(() => {
const checkboxes = this.checkboxes.toArray();
// Caretaker note: we explicitly should call `subscribe()` within the root zone.
// `runOutsideAngular(() => fromEvent(...))` will just create an observable within the root zone,
// but `addEventListener` is called when the `fromEvent` is subscribed.
return new Observable(subscriber => this.ngZone.runOutsideAngular(() => merge(...checkboxes.map(checkbox => fromEvent(checkbox.nativeElement, 'click'))).subscribe(subscriber)));
}))
.subscribe(event => {
event.stopPropagation();
});
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.0.3", ngImport: i0, type: NzTransferListComponent, deps: [{ token: i0.NgZone }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.0.3", type: NzTransferListComponent, selector: "nz-transfer-list", inputs: { direction: "direction", titleText: "titleText", showSelectAll: "showSelectAll", dataSource: "dataSource", itemUnit: "itemUnit", itemsUnit: "itemsUnit", filter: "filter", disabled: "disabled", showSearch: "showSearch", searchPlaceholder: "searchPlaceholder", notFoundContent: "notFoundContent", filterOption: "filterOption", renderList: "renderList", render: "render", footer: "footer" }, outputs: { handleSelectAll: "handleSelectAll", handleSelect: "handleSelect", filterChange: "filterChange" }, host: { properties: { "class.ant-transfer-list-with-footer": "!!footer" }, classAttribute: "ant-transfer-list" }, viewQueries: [{ propertyName: "headerCheckbox", first: true, predicate: ["headerCheckbox"], descendants: true, read: NzCheckboxComponent }, { propertyName: "checkboxes", predicate: ["checkboxes"], descendants: true, read: ElementRef }], exportAs: ["nzTransferList"], ngImport: i0, template: `
<ng-template #defaultRenderList>
<ul *ngIf="stat.shownCount > 0" class="ant-transfer-list-content">
<li
*ngFor="let item of validData; trackBy: trackByHide"
(click)="onItemSelect(item)"
class="ant-transfer-list-content-item"
[ngClass]="{ 'ant-transfer-list-content-item-disabled': disabled || item.disabled }"
>
<label
#checkboxes
nz-checkbox
[nzChecked]="item.checked"
(nzCheckedChange)="onItemSelect(item)"
[nzDisabled]="disabled || item.disabled"
>
<ng-container *ngIf="!render; else renderContainer">{{ item.title }}</ng-container>
<ng-template
#renderContainer
[ngTemplateOutlet]="render"
[ngTemplateOutletContext]="{ $implicit: item }"
></ng-template>
</label>
</li>
</ul>
<div *ngIf="stat.shownCount === 0" class="ant-transfer-list-body-not-found">
<nz-embed-empty [nzComponentName]="'transfer'" [specificContent]="notFoundContent"></nz-embed-empty>
</div>
</ng-template>
<div class="ant-transfer-list-header">
<label
*ngIf="showSelectAll"
class="ant-transfer-list-checkbox"
nz-checkbox
#headerCheckbox
[nzChecked]="stat.checkAll"
(nzCheckedChange)="onItemSelectAll($event)"
[nzIndeterminate]="stat.checkHalf"
[nzDisabled]="stat.shownCount === 0 || disabled"
></label>
<span class="ant-transfer-list-header-selected">
<span>
{{ (stat.checkCount > 0 ? stat.checkCount + '/' : '') + stat.shownCount }}
{{ validData.length > 1 ? itemsUnit : itemUnit }}
</span>
</span>
<span *ngIf="titleText" class="ant-transfer-list-header-title">{{ titleText }}</span>
</div>
<div
class="{{ showSearch ? 'ant-transfer-list-body ant-transfer-list-body-with-search' : 'ant-transfer-list-body' }}"
[ngClass]="{ 'ant-transfer__nodata': stat.shownCount === 0 }"
>
<div *ngIf="showSearch" class="ant-transfer-list-body-search-wrapper">
<span
nz-transfer-search
class="ant-input-affix-wrapper ant-transfer-list-search"
(valueChanged)="handleFilter($event)"
(valueClear)="handleClear()"
[placeholder]="searchPlaceholder"
[disabled]="disabled"
[value]="filter"
></span>
</div>
<ng-container *ngIf="renderList; else defaultRenderList">
<div class="ant-transfer-list-body-customize-wrapper">
<ng-container
*ngTemplateOutlet="
renderList;
context: {
$implicit: validData,
direction: direction,
disabled: disabled,
onItemSelectAll: onItemSelectAll,
onItemSelect: onItemSelect,
stat: stat
}
"
></ng-container>
</div>
</ng-container>
</div>
<div *ngIf="footer" class="ant-transfer-list-footer">
<ng-template [ngTemplateOutlet]="footer" [ngTemplateOutletContext]="{ $implicit: direction }"></ng-template>
</div>
`, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2.NzCheckboxComponent, selector: "[nz-checkbox]", inputs: ["nzValue", "nzAutoFocus", "nzDisabled", "nzIndeterminate", "nzChecked", "nzId"], outputs: ["nzCheckedChange"], exportAs: ["nzCheckbox"] }, { kind: "component", type: i3.NzEmbedEmptyComponent, selector: "nz-embed-empty", inputs: ["nzComponentName", "specificContent"], exportAs: ["nzEmbedEmpty"] }, { kind: "component", type: i4.NzTransferSearchComponent, selector: "[nz-transfer-search]", inputs: ["placeholder", "value", "disabled"], outputs: ["valueChanged", "valueClear"], exportAs: ["nzTransferSearch"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.0.3", ngImport: i0, type: NzTransferListComponent, decorators: [{
type: Component,
args: [{
selector: 'nz-transfer-list',
exportAs: 'nzTransferList',
preserveWhitespaces: false,
template: `
<ng-template #defaultRenderList>
<ul *ngIf="stat.shownCount > 0" class="ant-transfer-list-content">
<li
*ngFor="let item of validData; trackBy: trackByHide"
(click)="onItemSelect(item)"
class="ant-transfer-list-content-item"
[ngClass]="{ 'ant-transfer-list-content-item-disabled': disabled || item.disabled }"
>
<label
#checkboxes
nz-checkbox
[nzChecked]="item.checked"
(nzCheckedChange)="onItemSelect(item)"
[nzDisabled]="disabled || item.disabled"
>
<ng-container *ngIf="!render; else renderContainer">{{ item.title }}</ng-container>
<ng-template
#renderContainer
[ngTemplateOutlet]="render"
[ngTemplateOutletContext]="{ $implicit: item }"
></ng-template>
</label>
</li>
</ul>
<div *ngIf="stat.shownCount === 0" class="ant-transfer-list-body-not-found">
<nz-embed-empty [nzComponentName]="'transfer'" [specificContent]="notFoundContent"></nz-embed-empty>
</div>
</ng-template>
<div class="ant-transfer-list-header">
<label
*ngIf="showSelectAll"
class="ant-transfer-list-checkbox"
nz-checkbox
#headerCheckbox
[nzChecked]="stat.checkAll"
(nzCheckedChange)="onItemSelectAll($event)"
[nzIndeterminate]="stat.checkHalf"
[nzDisabled]="stat.shownCount === 0 || disabled"
></label>
<span class="ant-transfer-list-header-selected">
<span>
{{ (stat.checkCount > 0 ? stat.checkCount + '/' : '') + stat.shownCount }}
{{ validData.length > 1 ? itemsUnit : itemUnit }}
</span>
</span>
<span *ngIf="titleText" class="ant-transfer-list-header-title">{{ titleText }}</span>
</div>
<div
class="{{ showSearch ? 'ant-transfer-list-body ant-transfer-list-body-with-search' : 'ant-transfer-list-body' }}"
[ngClass]="{ 'ant-transfer__nodata': stat.shownCount === 0 }"
>
<div *ngIf="showSearch" class="ant-transfer-list-body-search-wrapper">
<span
nz-transfer-search
class="ant-input-affix-wrapper ant-transfer-list-search"
(valueChanged)="handleFilter($event)"
(valueClear)="handleClear()"
[placeholder]="searchPlaceholder"
[disabled]="disabled"
[value]="filter"
></span>
</div>
<ng-container *ngIf="renderList; else defaultRenderList">
<div class="ant-transfer-list-body-customize-wrapper">
<ng-container
*ngTemplateOutlet="
renderList;
context: {
$implicit: validData,
direction: direction,
disabled: disabled,
onItemSelectAll: onItemSelectAll,
onItemSelect: onItemSelect,
stat: stat
}
"
></ng-container>
</div>
</ng-container>
</div>
<div *ngIf="footer" class="ant-transfer-list-footer">
<ng-template [ngTemplateOutlet]="footer" [ngTemplateOutletContext]="{ $implicit: direction }"></ng-template>
</div>
`,
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: 'ant-transfer-list',
'[class.ant-transfer-list-with-footer]': '!!footer'
}
}]
}], ctorParameters: () => [{ type: i0.NgZone }, { type: i0.ChangeDetectorRef }], propDecorators: { direction: [{
type: Input
}], titleText: [{
type: Input
}], showSelectAll: [{
type: Input
}], dataSource: [{
type: Input
}], itemUnit: [{
type: Input
}], itemsUnit: [{
type: Input
}], filter: [{
type: Input
}], disabled: [{
type: Input
}], showSearch: [{
type: Input
}], searchPlaceholder: [{
type: Input
}], notFoundContent: [{
type: Input
}], filterOption: [{
type: Input
}], renderList: [{
type: Input
}], render: [{
type: Input
}], footer: [{
type: Input
}], handleSelectAll: [{
type: Output
}], handleSelect: [{
type: Output
}], filterChange: [{
type: Output
}], headerCheckbox: [{
type: ViewChild,
args: ['headerCheckbox', { read: NzCheckboxComponent }]
}], checkboxes: [{
type: ViewChildren,
args: ['checkboxes', { read: ElementRef }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNmZXItbGlzdC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9jb21wb25lbnRzL3RyYW5zZmVyL3RyYW5zZmVyLWxpc3QuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7R0FHRztBQUVILE9BQU8sRUFFTCx1QkFBdUIsRUFFdkIsU0FBUyxFQUNULFVBQVUsRUFDVixZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFHTixTQUFTLEVBQ1QsWUFBWSxFQUNaLGlCQUFpQixFQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDcEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0RCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQzs7Ozs7O0FBb0c3RCxNQUFNLE9BQU8sdUJBQXVCO0lBc0NsQyxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVELFdBQVcsQ0FBQyxNQUFjLEVBQUUsSUFBa0I7UUFDNUMsc0ZBQXNGO1FBQ3RGLDZFQUE2RTtRQUM3RSxPQUFPLElBQUksQ0FBQyxJQUFJLENBQUM7SUFDbkIsQ0FBQztJQXNCTyxpQkFBaUI7UUFDdkIsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDbkUsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFD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QUFFLG1CQUFtQjt3QkFDMUIsdUNBQXVDLEVBQUUsVUFBVTtxQkFDcEQ7aUJBQ0Y7MkdBSVUsU0FBUztzQkFBakIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBRUcsVUFBVTtzQkFBbEIsS0FBSztnQkFFRyxRQUFRO3NCQUFoQixLQUFLO2dCQUNHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxZQUFZO3NCQUFwQixLQUFLO2dCQUVHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFHYSxlQUFlO3NCQUFqQyxNQUFNO2dCQUNZLFlBQVk7c0JBQTlCLE1BQU07Z0JBQ1ksWUFBWTtzQkFBOUIsTUFBTTtnQkFFcUQsY0FBYztzQkFBekUsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLElBQUksRUFBRSxtQkFBbUIsRUFBRTtnQkFFUixVQUFVO3NCQUEzRCxZQUFZO3VCQUFDLFlBQVksRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS9ORy1aT1JSTy9uZy16b3Jyby1hbnRkL2Jsb2IvbWFzdGVyL0xJQ0VOU0VcbiAqL1xuXG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPdXRwdXQsXG4gIFF1ZXJ5TGlzdCxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0NoaWxkcmVuLFxuICBWaWV3RW5jYXBzdWxhdGlvblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIGZyb21FdmVudCwgbWVyZ2UgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IHN0YXJ0V2l0aCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBOekNoZWNrYm94Q29tcG9uZW50IH0gZnJvbSAnbmctem9ycm8tYW50ZC9jaGVja2JveCc7XG5cbmltcG9ydCB7IFJlbmRlckxpc3RDb250ZXh0LCBUcmFuc2ZlckRpcmVjdGlvbiwgVHJhbnNmZXJJdGVtLCBUcmFuc2ZlclN0YXQgfSBmcm9tICcuL2ludGVyZmFjZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ256LXRyYW5zZmVyLWxpc3QnLFxuICBleHBvcnRBczogJ256VHJhbnNmZXJMaXN0JyxcbiAgcHJlc2VydmVXaGl0ZXNwYWNlczogZmFsc2UsXG4gIHRlbXBsYXRlOiBgXG4gICAgPG5nLXRlbXBsYXRlICNkZWZhdWx0UmVuZGVyTGlzdD5cbiAgICAgIDx1bCAqbmdJZj1cInN0YXQuc2hvd25Db3VudCA+IDBcIiBjbGFzcz1cImFudC10cmFuc2Zlci1saXN0LWNvbnRlbnRcIj5cbiAgICAgICAgPGxpXG4gICAgICAgICAgKm5nRm9yPVwibGV0IGl0ZW0gb2YgdmFsaWREYXRhOyB0cmFja0J5OiB0cmFja0J5SGlkZVwiXG4gICAgICAgICAgKGNsaWNrKT1cIm9uSXRlbVNlbGVjdChpdGVtKVwiXG4gICAgICAgICAgY2xhc3M9XCJhbnQtdHJhbnNmZXItbGlzdC1jb250ZW50LWl0ZW1cIlxuICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ2FudC10cmFuc2Zlci1saXN0LWNvbnRlbnQtaXRlbS1kaXNhYmxlZCc6IGRpc2FibGVkIHx8IGl0ZW0uZGlzYWJsZWQgfVwiXG4gICAgICAgID5cbiAgICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgICNjaGVja2JveGVzXG4gICAgICAgICAgICBuei1jaGVja2JveFxuICAgICAgICAgICAgW256Q2hlY2tlZF09XCJpdGVtLmNoZWNrZWRcIlxuICAgICAgICAgICAgKG56Q2hlY2tlZENoYW5nZSk9XCJvbkl0ZW1TZWxlY3QoaXRlbSlcIlxuICAgICAgICAgICAgW256RGlzYWJsZWRdPVwiZGlzYWJsZWQgfHwgaXRlbS5kaXNhYmxlZFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFyZW5kZXI7IGVsc2UgcmVuZGVyQ29udGFpbmVyXCI+e3sgaXRlbS50aXRsZSB9fTwvbmctY29udGFpbmVyPlxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgICAgICNyZW5kZXJDb250YWluZXJcbiAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwicmVuZGVyXCJcbiAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBpdGVtIH1cIlxuICAgICAgICAgICAgPjwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgPC9saT5cbiAgICAgIDwvdWw+XG4gICAgICA8ZGl2ICpuZ0lmPVwic3RhdC5zaG93bkNvdW50ID09PSAwXCIgY2xhc3M9XCJhbnQtdHJhbnNmZXItbGlzdC1ib2R5LW5vdC1mb3VuZFwiPlxuICAgICAgICA8bnotZW1iZWQtZW1wdHkgW256Q29tcG9uZW50TmFtZV09XCIndHJhbnNmZXInXCIgW3NwZWNpZmljQ29udGVudF09XCJub3RGb3VuZENvbnRlbnRcIj48L256LWVtYmVkLWVtcHR5PlxuICAgICAgPC9kaXY+XG4gICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8ZGl2IGNsYXNzPVwiYW50LXRyYW5zZmVyLWxpc3QtaGVhZGVyXCI+XG4gICAgICA8bGFiZWxcbiAgICAgICAgKm5nSWY9XCJzaG93U2VsZWN0QWxsXCJcbiAgICAgICAgY2xhc3M9XCJhbnQtdHJhbnNmZXItbGlzdC1jaGVja2JveFwiXG4gICAgICAgIG56LWNoZWNrYm94XG4gICAgICAgICNoZWFkZXJDaGVja2JveFxuICAgICAgICBbbnpDaGVja2VkXT1cInN0YXQuY2hlY2tBbGxcIlxuICAgICAgICAobnpDaGVja2VkQ2hhbmdlKT1cIm9uSXRlbVNlbGVjdEFsbCgkZXZlbnQpXCJcbiAgICAgICAgW256SW5kZXRlcm1pbmF0ZV09XCJzdGF0LmNoZWNrSGFsZlwiXG4gICAgICAgIFtuekRpc2FibGVkXT1cInN0YXQuc2hvd25Db3VudCA9PT0gMCB8fCBkaXNhYmxlZFwiXG4gICAgICA+PC9sYWJlbD5cbiAgICAgIDxzcGFuIGNsYXNzPVwiYW50LXRyYW5zZmVyLWxpc3QtaGVhZGVyLXNlbGVjdGVkXCI+XG4gICAgICAgIDxzcGFuPlxuICAgICAgICAgIHt7IChzdGF0LmNoZWNrQ291bnQgPiAwID8gc3RhdC5jaGVja0NvdW50ICsgJy8nIDogJycpICsgc3RhdC5zaG93bkNvdW50IH19XG4gICAgICAgICAge3sgdmFsaWREYXRhLmxlbmd0aCA+IDEgPyBpdGVtc1VuaXQgOiBpdGVtVW5pdCB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICA8L3NwYW4+XG4gICAgICA8c3BhbiAqbmdJZj1cInRpdGxlVGV4dFwiIGNsYXNzPVwiYW50LXRyYW5zZmVyLWxpc3QtaGVhZGVyLXRpdGxlXCI+e3sgdGl0bGVUZXh0IH19PC9zcGFuPlxuICAgIDwvZGl2PlxuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwie3sgc2hvd1NlYXJjaCA/ICdhbnQtdHJhbnNmZXItbGlzdC1ib2R5IGFudC10cmFuc2Zlci1saXN0LWJvZHktd2l0aC1zZWFyY2gnIDogJ2FudC10cmFuc2Zlci1saXN0LWJvZHknIH19XCJcbiAgICAgIFtuZ0NsYXNzXT1cInsgJ2FudC10cmFuc2Zlcl9fbm9kYXRhJzogc3RhdC5zaG93bkNvdW50ID09PSAwIH1cIlxuICAgID5cbiAgICAgIDxkaXYgKm5nSWY9XCJzaG93U2VhcmNoXCIgY2xhc3M9XCJhbnQtdHJhbnNmZXItbGlzdC1ib2R5LXNlYXJjaC13cmFwcGVyXCI+XG4gICAgICAgIDxzcGFuXG4gICAgICAgICAgbnotdHJhbnNmZXItc2VhcmNoXG4gICAgICAgICAgY2xhc3M9XCJhbnQtaW5wdXQtYWZmaXgtd3JhcHBlciBhbnQtdHJhbnNmZXItbGlzdC1zZWFyY2hcIlxuICAgICAgICAgICh2YWx1ZUNoYW5nZWQpPVwiaGFuZGxlRmlsdGVyKCRldmVudClcIlxuICAgICAgICAgICh2YWx1ZUNsZWFyKT1cImhhbmRsZUNsZWFyKClcIlxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCJzZWFyY2hQbGFjZWhvbGRlclwiXG4gICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcbiAgICAgICAgICBbdmFsdWVdPVwiZmlsdGVyXCJcbiAgICAgICAgPjwvc3Bhbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInJlbmRlckxpc3Q7IGVsc2UgZGVmYXVsdFJlbmRlckxpc3RcIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImFudC10cmFuc2Zlci1saXN0LWJvZHktY3VzdG9taXplLXdyYXBwZXJcIj5cbiAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAqbmdUZW1wbGF0ZU91dGxldD1cIlxuICAgICAgICAgICAgICByZW5kZXJMaXN0O1xuICAgICAgICAgICAgICBjb250ZXh0OiB7XG4gICAgICAgICAgICAgICAgJGltcGxpY2l0OiB2YWxpZERhdGEsXG4gICAgICAgICAgICAgICAgZGlyZWN0aW9uOiBkaXJlY3Rpb24sXG4gICAgICAgICAgICAgICAgZGlzYWJsZWQ6IGRpc2FibGVkLFxuICAgICAgICAgICAgICAgIG9uSXRlbVNlbGVjdEFsbDogb25JdGVtU2VsZWN0QWxsLFxuICAgICAgICAgICAgICAgIG9uSXRlbVNlbGVjdDogb25JdGVtU2VsZWN0LFxuICAgICAgICAgICAgICAgIHN0YXQ6IHN0YXRcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgXCJcbiAgICAgICAgICA+PC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9kaXY+XG4gICAgPGRpdiAqbmdJZj1cImZvb3RlclwiIGNsYXNzPVwiYW50LXRyYW5zZmVyLWxpc3QtZm9vdGVyXCI+XG4gICAgICA8bmctdGVtcGxhdGUgW25nVGVtcGxhdGVPdXRsZXRdPVwiZm9vdGVyXCIgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBkaXJlY3Rpb24gfVwiPjwvbmctdGVtcGxhdGU+XG4gICAgPC9kaXY+XG4gIGAsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBob3N0OiB7XG4gICAgY2xhc3M6ICdhbnQtdHJhbnNmZXItbGlzdCcsXG4gICAgJ1tjbGFzcy5hbnQtdHJhbnNmZXItbGlzdC13aXRoLWZvb3Rlcl0nOiAnISFmb290ZXInXG4gIH1cbn0pXG5leHBvcnQgY2xhc3MgTnpUcmFuc2Zlckxpc3RDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0IHtcbiAgLy8gI3JlZ2lvbiBmaWVsZHNcblxuICBASW5wdXQoKSBkaXJlY3Rpb246IFRyYW5zZmVyRGlyZWN0aW9uID0gJ2xlZnQnO1xuICBASW5wdXQoKSB0aXRsZVRleHQgPSAnJztcbiAgQElucHV0KCkgc2hvd1NlbGVjdEFsbCA9IHRydWU7XG5cbiAgQElucHV0KCkgZGF0YVNvdXJjZTogVHJhbnNmZXJJdGVtW10gPSBbXTtcblxuICBASW5wdXQoKSBpdGVtVW5pdDogc3RyaW5nIHwgdW5kZWZpbmVkID0gJyc7XG4gIEBJbnB1dCgpIGl0ZW1zVW5pdDogc3RyaW5nIHwgdW5kZWZpbmVkID0gJyc7XG4gIEBJbnB1dCgpIGZpbHRlciA9ICcnO1xuICBASW5wdXQoKSBkaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xuICBASW5wdXQoKSBzaG93U2VhcmNoPzogYm9vbGVhbjtcbiAgQElucHV0KCkgc2VhcmNoUGxhY2Vob2xkZXI/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIG5vdEZvdW5kQ29udGVudD86IHN0cmluZztcbiAgQElucHV0KCkgZmlsdGVyT3B0aW9uPzogKGlucHV0VmFsdWU6IHN0cmluZywgaXRlbTogVHJhbnNmZXJJdGVtKSA9PiBib29sZWFuO1xuXG4gIEBJbnB1dCgpIHJlbmRlckxpc3Q6IFRlbXBsYXRlUmVmPFJlbmRlckxpc3RDb250ZXh0PiB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSByZW5kZXI6IFRlbXBsYXRlUmVmPHsgJGltcGxpY2l0OiBUcmFuc2Zlckl0ZW0gfT4gfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgZm9vdGVyOiBUZW1wbGF0ZVJlZjx7ICRpbXBsaWNpdDogVHJhbnNmZXJEaXJlY3Rpb24gfT4gfCBudWxsID0gbnVsbDtcblxuICAvLyBldmVudHNcbiAgQE91dHB1dCgpIHJlYWRvbmx5IGhhbmRsZVNlbGVjdEFsbDogRXZlbnRFbWl0dGVyPGJvb2xlYW4+ID0gbmV3IEV2ZW50RW1pdHRlcjxib29sZWFuPigpO1xuICBAT3V0cHV0KCkgcmVhZG9ubHkgaGFuZGxlU2VsZWN0OiBFdmVudEVtaXR0ZXI8VHJhbnNmZXJJdGVtPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHJlYWRvbmx5IGZpbHRlckNoYW5nZTogRXZlbnRFbWl0dGVyPHsgZGlyZWN0aW9uOiBUcmFuc2ZlckRpcmVjdGlvbjsgdmFsdWU6IHN0cmluZyB9PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAVmlld0NoaWxkKCdoZWFkZXJDaGVja2JveCcsIHsgcmVhZDogTnpDaGVja2JveENvbXBvbmVudCB9KSBoZWFkZXJDaGVja2JveD86IE56Q2hlY2tib3hDb21wb25lbnQ7XG5cbiAgQFZpZXdDaGlsZHJlbignY2hlY2tib3hlcycsIHsgcmVhZDogRWxlbWVudFJlZiB9KSBjaGVja2JveGVzITogUXVlcnlMaXN0PEVsZW1lbnRSZWY8SFRNTExhYmVsRWxlbWVudD4+O1xuXG4gIHN0YXQ6IFRyYW5zZmVyU3RhdCA9IHtcbiAgICBjaGVja0FsbDogZmFsc2UsXG4gICAgY2hlY2tIYWxmOiBmYWxzZSxcbiAgICBjaGVja0NvdW50OiAwLFxuICAgIHNob3duQ291bnQ6IDBcbiAgfTtcblxuICBnZXQgdmFsaWREYXRhKCk6IFRyYW5zZmVySXRlbVtdIHtcbiAgICByZXR1cm4gdGhpcy5kYXRhU291cmNlLmZpbHRlcih3ID0+ICF3LmhpZGUpO1xuICB9XG5cbiAgdHJhY2tCeUhpZGUoX2luZGV4OiBudW1iZXIsIGl0ZW06IFRyYW5zZmVySXRlbSk6IGJvb2xlYW4gfCB1bmRlZmluZWQge1xuICAgIC8vIFRoZSBgdmFsaWREYXRhYCBpcyBhIGdldHRlciB3aGljaCByZXR1cm5zIG5ldyBhcnJheSBlYWNoIHRpbWUgdGhlIHByb3BlcnR5IGlzIHJlYWQuXG4gICAgLy8gVGhpcyBtYXkgbGVhZCB0byB1bmV4cGVjdGVkIHJlLXJlbmRlcnMsIHRobyB0aGUgYXJyYXkgaGFzbid0IGJlZW4gdXBkYXRlZC5cbiAgICByZXR1cm4gaXRlbS5oaWRlO1xuICB9XG5cbiAgb25JdGVtU2VsZWN0ID0gKGl0ZW06IFRyYW5zZmVySXRlbSk6IHZvaWQgPT4ge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IGl0ZW0uZGlzYWJsZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaXRlbS5jaGVja2VkID0gIWl0ZW0uY2hlY2tlZDtcbiAgICB0aGlzLnVwZGF0ZUNoZWNrU3RhdHVzKCk7XG4gICAgdGhpcy5oYW5kbGVTZWxlY3QuZW1pdChpdGVtKTtcbiAgfTtcblxuICBvbkl0ZW1TZWxlY3RBbGwgPSAoc3RhdHVzOiBib29sZWFuKTogdm9pZCA9PiB7XG4gICAgdGhpcy5kYXRhU291cmNlLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICBpZiAoIWl0ZW0uZGlzYWJsZWQgJiYgIWl0ZW0uaGlkZSkge1xuICAgICAgICBpdGVtLmNoZWNrZWQgPSBzdGF0dXM7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLnVwZGF0ZUNoZWNrU3RhdHVzKCk7XG4gICAgdGhpcy5oYW5kbGVTZWxlY3RBbGwuZW1pdChzdGF0dXMpO1xuICB9O1xuXG4gIHByaXZhdGUgdXBkYXRlQ2hlY2tTdGF0dXMoKTogdm9pZCB7XG4gICAgY29uc3QgdmFsaWRDb3VudCA9IHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIodyA9PiAhdy5kaXNhYmxlZCkubGVuZ3RoO1xuICAgIHRoaXMuc3RhdC5jaGVja0NvdW50ID0gdGhpcy5kYXRhU291cmNlLmZpbHRlcih3ID0+IHcuY2hlY2tlZCAmJiAhdy5kaXNhYmxlZCkubGVuZ3RoO1xuICAgIHRoaXMuc3RhdC5zaG93bkNvdW50ID0gdGhpcy52YWxpZERhdGEubGVuZ3RoO1xuICAgIHRoaXMuc3RhdC5jaGVja0FsbCA9IHZhbGlkQ291bnQgPiAwICYmIHZhbGlkQ291bnQgPT09IHRoaXMuc3RhdC5jaGVja0NvdW50O1xuICAgIHRoaXMuc3RhdC5jaGVja0hhbGYgPSB0aGlzLnN0YXQuY2hlY2tDb3VudCA+IDAgJiYgIXRoaXMuc3RhdC5jaGVja0FsbDtcbiAgICAvLyBOb3RlOiB0aGlzIGlzIGRvbmUgZXhwbGljaXRseSBzaW5jZSB0aGUgaW50ZXJuYWwgYG56Q2hlY2tlZGAgdmFsdWUgbWF5IG5vdCBiZSB1cGRhdGVkIGluIGVkZ2UgY2FzZXMuXG4gICAgLy8gQ29uc2lkZXIgdGhlIGZvbGxvd2luZyBmbG93OlxuICAgIC8vIDEpIHRoZSBpbml0aWFsIHZhbHVlIG9mIGBzdGF0LmNoZWNrQWxsYCBpcyBgZmFsc2VgXG4gICAgLy8gMikgdGhlIHVzZXIgZmlsdGVycyBpdGVtc1xuICAgIC8vIDMpIHRoZSB1c2VyIGNsaWNrcyBcIlNlbGVjdCBBbGxcIiBjaGVja2JveFxuICAgIC8vIDQpIHRoZSBgTnpDaGVja2JveENvbXBvbmVudGAgc2V0cyBgbnpDaGVja2VkYCB0byBgdHJ1ZWAgaW50ZXJuYWxseVxuICAgIC8vIDUpIHRoZSB1c2VyIGNsaWNrcyBcIk1vdmUgdG8gcmlnaHRcIlxuICAgIC8vIDYpIGl0ZW1zIGFyZSBtb3ZlZCBhbmQgdGhlIGB1cGRhdGVDaGVja1N0YXR1c2AgaXMgaW52b2tlZFxuICAgIC8vIDcpIHRoZSBgc3RhdC5jaGVja0FsbGAgdmFsdWUgaGFzIG5ldmVyIGJlZW4gdXBkYXRlZCBpbiB0aGlzIGZsb3csIGl0J3MgYWx3YXlzIGJlZW4gYGZhbHNlYFxuICAgIC8vIDgpIHRoZSBgbnpDaGVja2VkYCBpcyBzdGlsbCBgdHJ1ZWAgYW5kIHRoZSBjaGVja2JveCBpcyBub3QgdW5jaGVja2VkXG4gICAgLy8gVGhpcyBpcyBiZWNhdXNlIEFuZ3VsYXIgY2hlY2tzIGJpbmRpbmdzIGFuZCBpdCBjaGVja2VkIHRoYXQgYFtuekNoZWNrZWRdPVwic3RhdC5jaGVja0FsbFwiYCBoYXNcbiAgICAvLyBuZXZlciBiZWVuIHVwZGF0ZWQsIHNvIEFuZ3VsYXIgZGlkIG5vdCBzZXQgbmV3IGBuekNoZWNrZWRgIHZhbHVlIG9uIHRoZSBjaGVja2JveC5cbiAgICB0aGlzLmhlYWRlckNoZWNrYm94ICYmICh0aGlzLmhlYWRlckNoZWNrYm94Lm56Q2hlY2tlZCA9IHRoaXMuc3RhdC5jaGVja0FsbCk7XG4gIH1cblxuICAvLyAjZW5kcmVnaW9uXG5cbiAgLy8gI3JlZ2lvbiBzZWFyY2hcblxuICBoYW5kbGVGaWx0ZXIodmFsdWU6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuZmlsdGVyID0gdmFsdWU7XG4gICAgdGhpcy5kYXRhU291cmNlLmZvckVhY2goaXRlbSA9PiB7XG4gICAgICBpdGVtLmhpZGUgPSB2YWx1ZS5sZW5ndGggPiAwICYmICF0aGlzLm1hdGNoRmlsdGVyKHZhbHVlLCBpdGVtKTtcbiAgICB9KTtcbiAgICB0aGlzLnN0YXQuc2hvd25Db3VudCA9IHRoaXMudmFsaWREYXRhLmxlbmd0aDtcbiAgICB0aGlzLmZpbHRlckNoYW5nZS5lbWl0KHsgZGlyZWN0aW9uOiB0aGlzLmRpcmVjdGlvbiwgdmFsdWUgfSk7XG4gIH1cblxuICBoYW5kbGVDbGVhcigpOiB2b2lkIHtcbiAgICB0aGlzLmhhbmRsZUZpbHRlcignJyk7XG4gIH1cblxuICBwcml2YXRlIG1hdGNoRmlsdGVyKHRleHQ6IHN0cmluZywgaXRlbTogVHJhbnNmZXJJdGVtKTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMuZmlsdGVyT3B0aW9uKSB7XG4gICAgICByZXR1cm4gdGhpcy5maWx0ZXJPcHRpb24odGV4dCwgaXRlbSk7XG4gICAgfVxuICAgIHJldHVybiBpdGVtLnRpdGxlLmluY2x1ZGVzKHRleHQpO1xuICB9XG5cbiAgLy8gI2VuZHJlZ2lvblxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgbmdab25lOiBOZ1pvbmUsIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZikge31cblxuICBtYXJrRm9yQ2hlY2soKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVDaGVja1N0YXR1cygpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuY2hlY2tib3hlcy5jaGFuZ2VzXG4gICAgICAucGlwZShcbiAgICAgICAgc3RhcnRXaXRoKHRoaXMuY2hlY2tib3hlcyksXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB7XG4gICAgICAgICAgY29uc3QgY2hlY2tib3hlcyA9IHRoaXMuY2hlY2tib3hlcy50b0FycmF5KCk7XG4gICAgICAgICAgLy8gQ2FyZXRha2VyIG5vdGU6IHdlIGV4cGxpY2l0bHkgc2hvdWxkIGNhbGwgYHN1YnNjcmliZSgpYCB3aXRoaW4gdGhlIHJvb3Qgem9uZS5cbiAgICAgICAgICAvLyBgcnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4gZnJvbUV2ZW50KC4uLikpYCB3aWxsIGp1c3QgY3JlYXRlIGFuIG9ic2VydmFibGUgd2l0aGluIHRoZSByb290IHpvbmUsXG4gICAgICAgICAgLy8gYnV0IGBhZGRFdmVudExpc3RlbmVyYCBpcyBjYWxsZWQgd2hlbiB0aGUgYGZyb21FdmVudGAgaXMgc3Vic2NyaWJlZC5cbiAgICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8TW91c2VFdmVudD4oc3Vic2NyaWJlciA9PlxuICAgICAgICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT5cbiAgICAgICAgICAgICAgbWVyZ2UoLi4uY2hlY2tib3hlcy5tYXAoY2hlY2tib3ggPT4gZnJvbUV2ZW50PE1vdXNlRXZlbnQ+KGNoZWNrYm94Lm5hdGl2ZUVsZW1lbnQsICdjbGljaycpKSkuc3Vic2NyaWJlKFxuICAgICAgICAgICAgICAgIHN1YnNjcmliZXJcbiAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHtcbiAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICB9KTtcbiAgfVxufVxuIl19