@linid-dm/directory-manager-client-core
Version:
Core package by providing a set of angular components for the Directory Manager app.
173 lines • 40.3 kB
JavaScript
import { __decorate } from "tslib";
/**
* Copyright (C) 2020-2024 Linagora
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version, provided you comply with the Additional Terms applicable for
* LinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU
* Affero General Public License, subsections (b), (c), and (e), pursuant to
* which these Appropriate Legal Notices must notably (i) retain the display of
* the "LinID™" trademark/logo at the top of the interface window, the display
* of the “You are using the Open Source and free version of LinID™, powered by
* Linagora © 2009–2013. Contribute to LinID R&D by subscribing to an Enterprise
* offer!” infobox and in the e-mails sent with the Program, notice appended to
* any type of outbound messages (e.g. e-mail and meeting requests) as well as
* in the LinID Directory Manager user interface, (ii) retain all hypertext
* links between LinID Directory Manager and https://linid.org/, as well as
* between LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA
* intellectual property rights over its trademarks and commercial brands. Other
* Additional Terms apply, see <http://www.linagora.com/licenses/> for more
* details.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License and
* its applicable Additional Terms for LinID Directory Manager along with this
* program. If not, see <http://www.gnu.org/licenses/> for the GNU Affero
* General Public License version 3 and <http://www.linagora.com/licenses/> for
* the Additional Terms applicable to the LinID Directory Manager software.
*/
import { Component, EventEmitter, Input, Output, ViewChild, } from '@angular/core';
import { Select } from '@ngxs/store';
import { Subject, debounceTime, takeUntil, tap } from 'rxjs';
import { Data, UiState, } from '../../shared';
import * as i0 from "@angular/core";
import * as i1 from "@ngxs/store";
import * as i2 from "@angular/common";
import * as i3 from "@angular/forms";
import * as i4 from "@angular/flex-layout/flex";
import * as i5 from "@angular/flex-layout/extended";
import * as i6 from "@angular/material/button";
import * as i7 from "@angular/material/form-field";
import * as i8 from "@angular/material/icon";
import * as i9 from "@angular/material/input";
import * as i10 from "@angular/material/tooltip";
export class GenericDataHeaderComponent {
set advancedSearchMatHint(advancedSearchMatHint) {
if (!!advancedSearchMatHint) {
this._advancedSearchMatHint = advancedSearchMatHint;
this.lineHeight = Math.round(Number(getComputedStyle(this._advancedSearchMatHint.nativeElement)
.getPropertyValue('line-height')
.replace('px', '')));
}
}
get advancedSearchMatHint() {
return this._advancedSearchMatHint;
}
set selectedResourceRootTypeId(selectedResourceRootTypeId) {
this._largeHeaderWidth = null;
this.largeBtnAdditionnalClasses = { 'hide-btn': false };
this.smallBtnAdditionnalClasses = { 'hide-btn': false };
this._selectedResourceRootTypeId = selectedResourceRootTypeId;
this.search =
this.dataJsTable.byId[this.selectedResourceRootTypeId]?.filterValue;
}
get selectedResourceRootTypeId() {
return this._selectedResourceRootTypeId;
}
set offsetWidth(offsetWidth) {
if (!!offsetWidth) {
this._offsetWidth = offsetWidth;
this._updateButtonDisplay();
}
}
get offsetWidth() {
return this._offsetWidth;
}
constructor(_store$) {
this._store$ = _store$;
this._COMPONENT_MIN_WIDTH = 290;
this.largeBtnAdditionnalClasses = {
'hide-btn': false,
};
this.smallBtnAdditionnalClasses = {
'hide-btn': false,
};
this.clickOnAddResourceBtn = new EventEmitter();
this._onDestroy$ = new Subject();
this.search = '';
this.modelChanged = new Subject();
}
ngOnInit() {
this.modelChanged
.pipe(debounceTime(300), takeUntil(this._onDestroy$), tap((currentSearch) => {
this._store$.dispatch(new Data.SetFilterValue({
filterValue: currentSearch,
dataTypeId: this.selectedResourceRootTypeId,
}));
}))
.subscribe();
}
ngAfterViewInit() {
let largeBtnWidth = 0;
let smallBtnWidth = 0;
if (this.canCreate) {
largeBtnWidth = this.createLargeBtn._elementRef.nativeElement.offsetWidth;
smallBtnWidth =
this.createMiniFabBtn._elementRef.nativeElement.offsetWidth;
}
let filterMinWidth = this._COMPONENT_MIN_WIDTH - smallBtnWidth;
this._largeHeaderWidth = filterMinWidth + largeBtnWidth;
this._updateButtonDisplay();
}
clearInputFilter() {
this.search = '';
this.modelChanged.next('');
}
updateSearch(search) {
this.modelChanged.next(search);
}
addNewResource() {
this.clickOnAddResourceBtn.emit();
}
ngOnDestroy() {
this._onDestroy$.next();
this._onDestroy$.complete();
}
_updateButtonDisplay() {
if (this._largeHeaderWidth != null) {
const displayLargeBtn = this._largeHeaderWidth <= this.offsetWidth;
this.largeBtnAdditionnalClasses = { 'hide-btn': !displayLargeBtn };
this.smallBtnAdditionnalClasses = { 'hide-btn': displayLargeBtn };
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: GenericDataHeaderComponent, deps: [{ token: i1.Store }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.4", type: GenericDataHeaderComponent, selector: "dm-generic-data-header", inputs: { advancedSearchMatHint: "advancedSearchMatHint", canCreate: "canCreate", addBtnLabel: "addBtnLabel", dataJsTable: "dataJsTable", selectedResourceRootTypeId: "selectedResourceRootTypeId", offsetWidth: "offsetWidth", isLargeScreen: "isLargeScreen", isAdvancedSearchActivated: "isAdvancedSearchActivated" }, outputs: { clickOnAddResourceBtn: "clickOnAddResourceBtn" }, viewQueries: [{ propertyName: "createLargeBtn", first: true, predicate: ["createLargeBtn"], descendants: true }, { propertyName: "createMiniFabBtn", first: true, predicate: ["createMiniFabBtn"], descendants: true }], ngImport: i0, template: "<!-- Copyright (C) 2020-2024 Linagora\n\nThis program is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your option) any\nlater version, provided you comply with the Additional Terms applicable for\nLinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU\nAffero General Public License, subsections (b), (c), and (e), pursuant to\nwhich these Appropriate Legal Notices must notably (i) retain the display of\nthe \"LinID\u2122\" trademark/logo at the top of the interface window, the display\nof the \u201CYou are using the Open Source and free version of LinID\u2122, powered by\nLinagora \u00A9 2009\u20132013. Contribute to LinID R&D by subscribing to an Enterprise\noffer!\u201D infobox and in the e-mails sent with the Program, notice appended to\nany type of outbound messages (e.g. e-mail and meeting requests) as well as\nin the LinID Directory Manager user interface, (ii) retain all hypertext\nlinks between LinID Directory Manager and https://linid.org/, as well as\nbetween LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA\nintellectual property rights over its trademarks and commercial brands. Other\nAdditional Terms apply, see <http://www.linagora.com/licenses/> for more\ndetails.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\ndetails.\n\nYou should have received a copy of the GNU Affero General Public License and\nits applicable Additional Terms for LinID Directory Manager along with this\nprogram. If not, see <http://www.gnu.org/licenses/> for the GNU Affero\nGeneral Public License version 3 and <http://www.linagora.com/licenses/> for\nthe Additional Terms applicable to the LinID Directory Manager software. -->\n\n<div fxLayout=\"row\" class=\"div-gnc-filter\">\n <mat-form-field\n *ngIf=\"filterAccessibility$ | async as filterAccessibility\"\n fxFlex\n color=\"accent\"\n [ngClass]=\"{\n 'gnc-filter-activated':\n advancedSearchMatHint?.nativeElement.offsetHeight <= lineHeight\n }\"\n class=\"gnc-filter\"\n >\n <mat-label>\n <mat-icon aria-hidden=\"true\">filter_list_alt</mat-icon>\n {{ filterAccessibility.label }}\n </mat-label>\n <input\n type=\"text\"\n matInput\n [(ngModel)]=\"search\"\n (ngModelChange)=\"updateSearch($event)\"\n class=\"filter\"\n />\n <button\n *ngIf=\"search\"\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"filterAccessibility.clearSearch\"\n (click)=\"clearInputFilter()\"\n class=\"reset-input-btn\"\n [matTooltip]=\"filterAccessibility.clearSearch\"\n >\n <mat-icon aria-hidden=\"true\"> clear </mat-icon>\n </button>\n </mat-form-field>\n <div\n *ngIf=\"canCreate\"\n class=\"div-add-button\"\n [ngClass]=\"{\n 'div-add-button-with-advanced-search':\n advancedSearchMatHint?.nativeElement.offsetHeight <= lineHeight\n }\"\n >\n <button\n #createLargeBtn\n mat-raised-button\n color=\"accent\"\n (click)=\"addNewResource()\"\n class=\"lg-add-btn\"\n [ngClass]=\"largeBtnAdditionnalClasses\"\n >\n {{ addBtnLabel }}\n </button>\n <button\n #createMiniFabBtn\n mat-mini-fab\n color=\"accent\"\n matTooltipPosition=\"right\"\n [matTooltip]=\"addBtnLabel\"\n (click)=\"addNewResource()\"\n class=\"sm-add-btn\"\n [ngClass]=\"smallBtnAdditionnalClasses\"\n >\n <mat-icon aria-hidden=\"true\">add</mat-icon>\n </button>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.gnc-filter{padding:20px 20px 0}.gnc-filter-activated{padding-top:10px}.div-add-button{margin-top:25px;padding-right:5px}.div-add-button-with-advanced-search{margin-top:15px}.lg-add-btn{width:max-content}button.mdc-fab--mini.sm-add-btn:active:not([class*=mat-elevation-z]){box-shadow:none}.hide-btn{display:none}mat-label{display:flex}.reset-input-btn{height:1.5em;width:1.5em;padding:0;display:flex;align-items:center;justify-content:center}.reset-input-btn mat-icon{font-size:inherit;height:auto;width:auto}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i4.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i4.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { kind: "directive", type: i5.DefaultClassDirective, selector: " [ngClass], [ngClass.xs], [ngClass.sm], [ngClass.md], [ngClass.lg], [ngClass.xl], [ngClass.lt-sm], [ngClass.lt-md], [ngClass.lt-lg], [ngClass.lt-xl], [ngClass.gt-xs], [ngClass.gt-sm], [ngClass.gt-md], [ngClass.gt-lg]", inputs: ["ngClass", "ngClass.xs", "ngClass.sm", "ngClass.md", "ngClass.lg", "ngClass.xl", "ngClass.lt-sm", "ngClass.lt-md", "ngClass.lt-lg", "ngClass.lt-xl", "ngClass.gt-xs", "ngClass.gt-sm", "ngClass.gt-md", "ngClass.gt-lg"] }, { kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab]", exportAs: ["matButton"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i8.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i9.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] }); }
}
__decorate([
Select(UiState.getFilterAccessibility)
], GenericDataHeaderComponent.prototype, "filterAccessibility$", void 0);
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.4", ngImport: i0, type: GenericDataHeaderComponent, decorators: [{
type: Component,
args: [{ selector: 'dm-generic-data-header', template: "<!-- Copyright (C) 2020-2024 Linagora\n\nThis program is free software: you can redistribute it and/or modify it under\nthe terms of the GNU Affero General Public License as published by the Free\nSoftware Foundation, either version 3 of the License, or (at your option) any\nlater version, provided you comply with the Additional Terms applicable for\nLinID Directory Manager software by LINAGORA pursuant to Section 7 of the GNU\nAffero General Public License, subsections (b), (c), and (e), pursuant to\nwhich these Appropriate Legal Notices must notably (i) retain the display of\nthe \"LinID\u2122\" trademark/logo at the top of the interface window, the display\nof the \u201CYou are using the Open Source and free version of LinID\u2122, powered by\nLinagora \u00A9 2009\u20132013. Contribute to LinID R&D by subscribing to an Enterprise\noffer!\u201D infobox and in the e-mails sent with the Program, notice appended to\nany type of outbound messages (e.g. e-mail and meeting requests) as well as\nin the LinID Directory Manager user interface, (ii) retain all hypertext\nlinks between LinID Directory Manager and https://linid.org/, as well as\nbetween LINAGORA and LINAGORA.com, and (iii) refrain from infringing LINAGORA\nintellectual property rights over its trademarks and commercial brands. Other\nAdditional Terms apply, see <http://www.linagora.com/licenses/> for more\ndetails.\n\nThis program is distributed in the hope that it will be useful, but WITHOUT\nANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\nFOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more\ndetails.\n\nYou should have received a copy of the GNU Affero General Public License and\nits applicable Additional Terms for LinID Directory Manager along with this\nprogram. If not, see <http://www.gnu.org/licenses/> for the GNU Affero\nGeneral Public License version 3 and <http://www.linagora.com/licenses/> for\nthe Additional Terms applicable to the LinID Directory Manager software. -->\n\n<div fxLayout=\"row\" class=\"div-gnc-filter\">\n <mat-form-field\n *ngIf=\"filterAccessibility$ | async as filterAccessibility\"\n fxFlex\n color=\"accent\"\n [ngClass]=\"{\n 'gnc-filter-activated':\n advancedSearchMatHint?.nativeElement.offsetHeight <= lineHeight\n }\"\n class=\"gnc-filter\"\n >\n <mat-label>\n <mat-icon aria-hidden=\"true\">filter_list_alt</mat-icon>\n {{ filterAccessibility.label }}\n </mat-label>\n <input\n type=\"text\"\n matInput\n [(ngModel)]=\"search\"\n (ngModelChange)=\"updateSearch($event)\"\n class=\"filter\"\n />\n <button\n *ngIf=\"search\"\n matSuffix\n mat-icon-button\n [attr.aria-label]=\"filterAccessibility.clearSearch\"\n (click)=\"clearInputFilter()\"\n class=\"reset-input-btn\"\n [matTooltip]=\"filterAccessibility.clearSearch\"\n >\n <mat-icon aria-hidden=\"true\"> clear </mat-icon>\n </button>\n </mat-form-field>\n <div\n *ngIf=\"canCreate\"\n class=\"div-add-button\"\n [ngClass]=\"{\n 'div-add-button-with-advanced-search':\n advancedSearchMatHint?.nativeElement.offsetHeight <= lineHeight\n }\"\n >\n <button\n #createLargeBtn\n mat-raised-button\n color=\"accent\"\n (click)=\"addNewResource()\"\n class=\"lg-add-btn\"\n [ngClass]=\"largeBtnAdditionnalClasses\"\n >\n {{ addBtnLabel }}\n </button>\n <button\n #createMiniFabBtn\n mat-mini-fab\n color=\"accent\"\n matTooltipPosition=\"right\"\n [matTooltip]=\"addBtnLabel\"\n (click)=\"addNewResource()\"\n class=\"sm-add-btn\"\n [ngClass]=\"smallBtnAdditionnalClasses\"\n >\n <mat-icon aria-hidden=\"true\">add</mat-icon>\n </button>\n </div>\n</div>\n", styles: ["@charset \"UTF-8\";.gnc-filter{padding:20px 20px 0}.gnc-filter-activated{padding-top:10px}.div-add-button{margin-top:25px;padding-right:5px}.div-add-button-with-advanced-search{margin-top:15px}.lg-add-btn{width:max-content}button.mdc-fab--mini.sm-add-btn:active:not([class*=mat-elevation-z]){box-shadow:none}.hide-btn{display:none}mat-label{display:flex}.reset-input-btn{height:1.5em;width:1.5em;padding:0;display:flex;align-items:center;justify-content:center}.reset-input-btn mat-icon{font-size:inherit;height:auto;width:auto}\n"] }]
}], ctorParameters: () => [{ type: i1.Store }], propDecorators: { filterAccessibility$: [], createLargeBtn: [{
type: ViewChild,
args: ['createLargeBtn']
}], createMiniFabBtn: [{
type: ViewChild,
args: ['createMiniFabBtn']
}], advancedSearchMatHint: [{
type: Input
}], canCreate: [{
type: Input
}], addBtnLabel: [{
type: Input
}], dataJsTable: [{
type: Input
}], selectedResourceRootTypeId: [{
type: Input
}], offsetWidth: [{
type: Input
}], isLargeScreen: [{
type: Input
}], isAdvancedSearchActivated: [{
type: Input
}], clickOnAddResourceBtn: [{
type: Output
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2VuZXJpYy1kYXRhLWhlYWRlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9saWJzL2NsaWVudC1jb3JlL3NyYy9saWIvZmVhdHVyZS9nZW5lcmljLWRhdGEtaGVhZGVyL2dlbmVyaWMtZGF0YS1oZWFkZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvbGlicy9jbGllbnQtY29yZS9zcmMvbGliL2ZlYXR1cmUvZ2VuZXJpYy1kYXRhLWhlYWRlci9nZW5lcmljLWRhdGEtaGVhZGVyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ0c7QUFFSCxPQUFPLEVBRUwsU0FBUyxFQUVULFlBQVksRUFDWixLQUFLLEVBR0wsTUFBTSxFQUNOLFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQUUsTUFBTSxFQUFTLE1BQU0sYUFBYSxDQUFDO0FBQzVDLE9BQU8sRUFBYyxPQUFPLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDekUsT0FBTyxFQUNMLElBQUksRUFJSixPQUFPLEdBQ1IsTUFBTSxjQUFjLENBQUM7Ozs7Ozs7Ozs7OztBQU90QixNQUFNLE9BQU8sMEJBQTBCO0lBa0JyQyxJQUFhLHFCQUFxQixDQUFDLHFCQUFpQztRQUNsRSxJQUFJLENBQUMsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQzVCLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxxQkFBcUIsQ0FBQztZQUVwRCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQzFCLE1BQU0sQ0FDSixnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsYUFBYSxDQUFDO2lCQUN4RCxnQkFBZ0IsQ0FBQyxh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QkFFRyxXQUFXO3NCQUFuQixLQUFLO2dCQUVPLDBCQUEwQjtzQkFBdEMsS0FBSztnQkFhTyxXQUFXO3NCQUF2QixLQUFLO2dCQVdHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBRUcseUJBQXlCO3NCQUFqQyxLQUFLO2dCQUVJLHFCQUFxQjtzQkFBOUIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29weXJpZ2h0IChDKSAyMDIwLTIwMjQgTGluYWdvcmFcbiAqXG4gKiBUaGlzIHByb2dyYW0gaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yIG1vZGlmeSBpdCB1bmRlclxuICogdGhlIHRlcm1zIG9mIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlXG4gKiBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueVxuICogbGF0ZXIgdmVyc2lvbiwgcHJvdmlkZWQgeW91IGNvbXBseSB3aXRoIHRoZSBBZGRpdGlvbmFsIFRlcm1zIGFwcGxpY2FibGUgZm9yXG4gKiBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciBzb2Z0d2FyZSBieSBMSU5BR09SQSBwdXJzdWFudCB0byBTZWN0aW9uIDcgb2YgdGhlIEdOVVxuICogQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UsIHN1YnNlY3Rpb25zIChiKSwgKGMpLCBhbmQgKGUpLCBwdXJzdWFudCB0b1xuICogd2hpY2ggdGhlc2UgQXBwcm9wcmlhdGUgTGVnYWwgTm90aWNlcyBtdXN0IG5vdGFibHkgKGkpIHJldGFpbiB0aGUgZGlzcGxheSBvZlxuICogdGhlIFwiTGluSUTihKJcIiB0cmFkZW1hcmsvbG9nbyBhdCB0aGUgdG9wIG9mIHRoZSBpbnRlcmZhY2Ugd2luZG93LCB0aGUgZGlzcGxheVxuICogb2YgdGhlIOKAnFlvdSBhcmUgdXNpbmcgdGhlIE9wZW4gU291cmNlIGFuZCBmcmVlIHZlcnNpb24gb2YgTGluSUTihKIsIHBvd2VyZWQgYnlcbiAqIExpbmFnb3JhIMKpIDIwMDnigJMyMDEzLiBDb250cmlidXRlIHRvIExpbklEIFImRCBieSBzdWJzY3JpYmluZyB0byBhbiBFbnRlcnByaXNlXG4gKiBvZmZlciHigJ0gaW5mb2JveCBhbmQgaW4gdGhlIGUtbWFpbHMgc2VudCB3aXRoIHRoZSBQcm9ncmFtLCBub3RpY2UgYXBwZW5kZWQgdG9cbiAqIGFueSB0eXBlIG9mIG91dGJvdW5kIG1lc3NhZ2VzIChlLmcuIGUtbWFpbCBhbmQgbWVldGluZyByZXF1ZXN0cykgYXMgd2VsbCBhc1xuICogaW4gdGhlIExpbklEIERpcmVjdG9yeSBNYW5hZ2VyIHVzZXIgaW50ZXJmYWNlLCAoaWkpIHJldGFpbiBhbGwgaHlwZXJ0ZXh0XG4gKiBsaW5rcyBiZXR3ZWVuIExpbklEIERpcmVjdG9yeSBNYW5hZ2VyIGFuZCBodHRwczovL2xpbmlkLm9yZy8sIGFzIHdlbGwgYXNcbiAqIGJldHdlZW4gTElOQUdPUkEgYW5kIExJTkFHT1JBLmNvbSwgYW5kIChpaWkpIHJlZnJhaW4gZnJvbSBpbmZyaW5naW5nIExJTkFHT1JBXG4gKiBpbnRlbGxlY3R1YWwgcHJvcGVydHkgcmlnaHRzIG92ZXIgaXRzIHRyYWRlbWFya3MgYW5kIGNvbW1lcmNpYWwgYnJhbmRzLiBPdGhlclxuICogQWRkaXRpb25hbCBUZXJtcyBhcHBseSwgc2VlIDxodHRwOi8vd3d3LmxpbmFnb3JhLmNvbS9saWNlbnNlcy8+IGZvciBtb3JlXG4gKiBkZXRhaWxzLlxuICpcbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLCBidXQgV0lUSE9VVFxuICogQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YgTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1NcbiAqIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZSBHTlUgQWZmZXJvIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmVcbiAqIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFuZFxuICogaXRzIGFwcGxpY2FibGUgQWRkaXRpb25hbCBUZXJtcyBmb3IgTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgYWxvbmcgd2l0aCB0aGlzXG4gKiBwcm9ncmFtLiBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4gZm9yIHRoZSBHTlUgQWZmZXJvXG4gKiBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMyBhbmQgPGh0dHA6Ly93d3cubGluYWdvcmEuY29tL2xpY2Vuc2VzLz4gZm9yXG4gKiB0aGUgQWRkaXRpb25hbCBUZXJtcyBhcHBsaWNhYmxlIHRvIHRoZSBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciBzb2Z0d2FyZS5cbiAqL1xuXG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBNYXRCdXR0b24gfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9idXR0b24nO1xuaW1wb3J0IHsgU2VsZWN0LCBTdG9yZSB9IGZyb20gJ0BuZ3hzL3N0b3JlJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QsIGRlYm91bmNlVGltZSwgdGFrZVVudGlsLCB0YXAgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIERhdGEsXG4gIElGaWx0ZXJBY2Nlc3NpYmlsaXR5LFxuICBJUGVyc2lzdGVudFVpRGF0YSxcbiAgSnNUYWJsZSxcbiAgVWlTdGF0ZSxcbn0gZnJvbSAnLi4vLi4vc2hhcmVkJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZG0tZ2VuZXJpYy1kYXRhLWhlYWRlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9nZW5lcmljLWRhdGEtaGVhZGVyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZ2VuZXJpYy1kYXRhLWhlYWRlci5jb21wb25lbnQuc2NzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBHZW5lcmljRGF0YUhlYWRlckNvbXBvbmVudFxuICBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0XG57XG4gIEBTZWxlY3QoVWlTdGF0ZS5nZXRGaWx0ZXJBY2Nlc3NpYmlsaXR5KVxuICBmaWx0ZXJBY2Nlc3NpYmlsaXR5JDogT2JzZXJ2YWJsZTxJRmlsdGVyQWNjZXNzaWJpbGl0eT47XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfQ09NUE9ORU5UX01JTl9XSURUSCA9IDI5MDtcbiAgcHJpdmF0ZSBfbGFyZ2VIZWFkZXJXaWR0aDogbnVtYmVyO1xuICBwdWJsaWMgbGFyZ2VCdG5BZGRpdGlvbm5hbENsYXNzZXM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+ID0ge1xuICAgICdoaWRlLWJ0bic6IGZhbHNlLFxuICB9O1xuICBwdWJsaWMgc21hbGxCdG5BZGRpdGlvbm5hbENsYXNzZXM6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+ID0ge1xuICAgICdoaWRlLWJ0bic6IGZhbHNlLFxuICB9O1xuXG4gIEBWaWV3Q2hpbGQoJ2NyZWF0ZUxhcmdlQnRuJykgY3JlYXRlTGFyZ2VCdG46IE1hdEJ1dHRvbjtcbiAgQFZpZXdDaGlsZCgnY3JlYXRlTWluaUZhYkJ0bicpIGNyZWF0ZU1pbmlGYWJCdG46IE1hdEJ1dHRvbjtcblxuICBASW5wdXQoKSBzZXQgYWR2YW5jZWRTZWFyY2hNYXRIaW50KGFkdmFuY2VkU2VhcmNoTWF0SGludDogRWxlbWVudFJlZikge1xuICAgIGlmICghIWFkdmFuY2VkU2VhcmNoTWF0SGludCkge1xuICAgICAgdGhpcy5fYWR2YW5jZWRTZWFyY2hNYXRIaW50ID0gYWR2YW5jZWRTZWFyY2hNYXRIaW50O1xuXG4gICAgICB0aGlzLmxpbmVIZWlnaHQgPSBNYXRoLnJvdW5kKFxuICAgICAgICBOdW1iZXIoXG4gICAgICAgICAgZ2V0Q29tcHV0ZWRTdHlsZSh0aGlzLl9hZHZhbmNlZFNlYXJjaE1hdEhpbnQubmF0aXZlRWxlbWVudClcbiAgICAgICAgICAgIC5nZXRQcm9wZXJ0eVZhbHVlKCdsaW5lLWhlaWdodCcpXG4gICAgICAgICAgICAucmVwbGFjZSgncHgnLCAnJylcbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBnZXQgYWR2YW5jZWRTZWFyY2hNYXRIaW50KCk6IEVsZW1lbnRSZWYge1xuICAgIHJldHVybiB0aGlzLl9hZHZhbmNlZFNlYXJjaE1hdEhpbnQ7XG4gIH1cblxuICBASW5wdXQoKSBjYW5DcmVhdGU6IGJvb2xlYW47XG5cbiAgQElucHV0KCkgYWRkQnRuTGFiZWw6IHN0cmluZztcblxuICBASW5wdXQoKSBkYXRhSnNUYWJsZTogSnNUYWJsZTxJUGVyc2lzdGVudFVpRGF0YT47XG5cbiAgQElucHV0KCkgc2V0IHNlbGVjdGVkUmVzb3VyY2VSb290VHlwZUlkKHNlbGVjdGVkUmVzb3VyY2VSb290VHlwZUlkOiBzdHJpbmcpIHtcbiAgICB0aGlzLl9sYXJnZUhlYWRlcldpZHRoID0gbnVsbDtcbiAgICB0aGlzLmxhcmdlQnRuQWRkaXRpb25uYWxDbGFzc2VzID0geyAnaGlkZS1idG4nOiBmYWxzZSB9O1xuICAgIHRoaXMuc21hbGxCdG5BZGRpdGlvbm5hbENsYXNzZXMgPSB7ICdoaWRlLWJ0bic6IGZhbHNlIH07XG4gICAgdGhpcy5fc2VsZWN0ZWRSZXNvdXJjZVJvb3RUeXBlSWQgPSBzZWxlY3RlZFJlc291cmNlUm9vdFR5cGVJZDtcbiAgICB0aGlzLnNlYXJjaCA9XG4gICAgICB0aGlzLmRhdGFKc1RhYmxlLmJ5SWRbdGhpcy5zZWxlY3RlZFJlc291cmNlUm9vdFR5cGVJZF0/LmZpbHRlclZhbHVlO1xuICB9XG5cbiAgZ2V0IHNlbGVjdGVkUmVzb3VyY2VSb290VHlwZUlkKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX3NlbGVjdGVkUmVzb3VyY2VSb290VHlwZUlkO1xuICB9XG5cbiAgQElucHV0KCkgc2V0IG9mZnNldFdpZHRoKG9mZnNldFdpZHRoOiBudW1iZXIpIHtcbiAgICBpZiAoISFvZmZzZXRXaWR0aCkge1xuICAgICAgdGhpcy5fb2Zmc2V0V2lkdGggPSBvZmZzZXRXaWR0aDtcbiAgICAgIHRoaXMuX3VwZGF0ZUJ1dHRvbkRpc3BsYXkoKTtcbiAgICB9XG4gIH1cblxuICBnZXQgb2Zmc2V0V2lkdGgoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fb2Zmc2V0V2lkdGg7XG4gIH1cblxuICBASW5wdXQoKSBpc0xhcmdlU2NyZWVuOiBib29sZWFuO1xuXG4gIEBJbnB1dCgpIGlzQWR2YW5jZWRTZWFyY2hBY3RpdmF0ZWQ6IGJvb2xlYW47XG5cbiAgQE91dHB1dCgpIGNsaWNrT25BZGRSZXNvdXJjZUJ0biA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcblxuICBwcml2YXRlIF9vbkRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICBwcml2YXRlIF9hZHZhbmNlZFNlYXJjaE1hdEhpbnQ6IEVsZW1lbnRSZWY7XG5cbiAgcHJpdmF0ZSBfb2Zmc2V0V2lkdGg6IG51bWJlcjtcblxuICBwcml2YXRlIF9zZWxlY3RlZFJlc291cmNlUm9vdFR5cGVJZDogc3RyaW5nO1xuXG4gIHB1YmxpYyBkaXZBZGRCdXR0b25NYXhXaWR0aDogbnVtYmVyO1xuXG4gIHB1YmxpYyBzZWFyY2ggPSAnJztcblxuICBwdWJsaWMgbW9kZWxDaGFuZ2VkID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xuXG4gIHB1YmxpYyBsaW5lSGVpZ2h0OiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBfc3RvcmUkOiBTdG9yZSkge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm1vZGVsQ2hhbmdlZFxuICAgICAgLnBpcGUoXG4gICAgICAgIGRlYm91bmNlVGltZSgzMDApLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fb25EZXN0cm95JCksXG4gICAgICAgIHRhcCgoY3VycmVudFNlYXJjaCkgPT4ge1xuICAgICAgICAgIHRoaXMuX3N0b3JlJC5kaXNwYXRjaChcbiAgICAgICAgICAgIG5ldyBEYXRhLlNldEZpbHRlclZhbHVlKHtcbiAgICAgICAgICAgICAgZmlsdGVyVmFsdWU6IGN1cnJlbnRTZWFyY2gsXG4gICAgICAgICAgICAgIGRhdGFUeXBlSWQ6IHRoaXMuc2VsZWN0ZWRSZXNvdXJjZVJvb3RUeXBlSWQsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICk7XG4gICAgICAgIH0pXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgbGV0IGxhcmdlQnRuV2lkdGggPSAwO1xuICAgIGxldCBzbWFsbEJ0bldpZHRoID0gMDtcbiAgICBpZiAodGhpcy5jYW5DcmVhdGUpIHtcbiAgICAgIGxhcmdlQnRuV2lkdGggPSB0aGlzLmNyZWF0ZUxhcmdlQnRuLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gICAgICBzbWFsbEJ0bldpZHRoID1cbiAgICAgICAgdGhpcy5jcmVhdGVNaW5pRmFiQnRuLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQub2Zmc2V0V2lkdGg7XG4gICAgfVxuICAgIGxldCBmaWx0ZXJNaW5XaWR0aCA9IHRoaXMuX0NPTVBPTkVOVF9NSU5fV0lEVEggLSBzbWFsbEJ0bldpZHRoO1xuICAgIHRoaXMuX2xhcmdlSGVhZGVyV2lkdGggPSBmaWx0ZXJNaW5XaWR0aCArIGxhcmdlQnRuV2lkdGg7XG4gICAgdGhpcy5fdXBkYXRlQnV0dG9uRGlzcGxheSgpO1xuICB9XG5cbiAgY2xlYXJJbnB1dEZpbHRlcigpOiB2b2lkIHtcbiAgICB0aGlzLnNlYXJjaCA9ICcnO1xuICAgIHRoaXMubW9kZWxDaGFuZ2VkLm5leHQoJycpO1xuICB9XG5cbiAgdXBkYXRlU2VhcmNoKHNlYXJjaDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5tb2RlbENoYW5nZWQubmV4dChzZWFyY2gpO1xuICB9XG5cbiAgYWRkTmV3UmVzb3VyY2UoKTogdm9pZCB7XG4gICAgdGhpcy5jbGlja09uQWRkUmVzb3VyY2VCdG4uZW1pdCgpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5fb25EZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5fb25EZXN0cm95JC5jb21wbGV0ZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlQnV0dG9uRGlzcGxheSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fbGFyZ2VIZWFkZXJXaWR0aCAhPSBudWxsKSB7XG4gICAgICBjb25zdCBkaXNwbGF5TGFyZ2VCdG4gPSB0aGlzLl9sYXJnZUhlYWRlcldpZHRoIDw9IHRoaXMub2Zmc2V0V2lkdGg7XG4gICAgICB0aGlzLmxhcmdlQnRuQWRkaXRpb25uYWxDbGFzc2VzID0geyAnaGlkZS1idG4nOiAhZGlzcGxheUxhcmdlQnRuIH07XG4gICAgICB0aGlzLnNtYWxsQnRuQWRkaXRpb25uYWxDbGFzc2VzID0geyAnaGlkZS1idG4nOiBkaXNwbGF5TGFyZ2VCdG4gfTtcbiAgICB9XG4gIH1cbn1cbiIsIjwhLS0gQ29weXJpZ2h0IChDKSAyMDIwLTIwMjQgTGluYWdvcmFcblxuVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnkgaXQgdW5kZXJcbnRoZSB0ZXJtcyBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZVxuU29mdHdhcmUgRm91bmRhdGlvbiwgZWl0aGVyIHZlcnNpb24gMyBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnlcbmxhdGVyIHZlcnNpb24sIHByb3ZpZGVkIHlvdSBjb21wbHkgd2l0aCB0aGUgQWRkaXRpb25hbCBUZXJtcyBhcHBsaWNhYmxlIGZvclxuTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgc29mdHdhcmUgYnkgTElOQUdPUkEgcHVyc3VhbnQgdG8gU2VjdGlvbiA3IG9mIHRoZSBHTlVcbkFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlLCBzdWJzZWN0aW9ucyAoYiksIChjKSwgYW5kIChlKSwgcHVyc3VhbnQgdG9cbndoaWNoIHRoZXNlIEFwcHJvcHJpYXRlIExlZ2FsIE5vdGljZXMgbXVzdCBub3RhYmx5IChpKSByZXRhaW4gdGhlIGRpc3BsYXkgb2ZcbnRoZSBcIkxpbklE4oSiXCIgdHJhZGVtYXJrL2xvZ28gYXQgdGhlIHRvcCBvZiB0aGUgaW50ZXJmYWNlIHdpbmRvdywgdGhlIGRpc3BsYXlcbm9mIHRoZSDigJxZb3UgYXJlIHVzaW5nIHRoZSBPcGVuIFNvdXJjZSBhbmQgZnJlZSB2ZXJzaW9uIG9mIExpbklE4oSiLCBwb3dlcmVkIGJ5XG5MaW5hZ29yYSDCqSAyMDA54oCTMjAxMy4gQ29udHJpYnV0ZSB0byBMaW5JRCBSJkQgYnkgc3Vic2NyaWJpbmcgdG8gYW4gRW50ZXJwcmlzZVxub2ZmZXIh4oCdIGluZm9ib3ggYW5kIGluIHRoZSBlLW1haWxzIHNlbnQgd2l0aCB0aGUgUHJvZ3JhbSwgbm90aWNlIGFwcGVuZGVkIHRvXG5hbnkgdHlwZSBvZiBvdXRib3VuZCBtZXNzYWdlcyAoZS5nLiBlLW1haWwgYW5kIG1lZXRpbmcgcmVxdWVzdHMpIGFzIHdlbGwgYXNcbmluIHRoZSBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciB1c2VyIGludGVyZmFjZSwgKGlpKSByZXRhaW4gYWxsIGh5cGVydGV4dFxubGlua3MgYmV0d2VlbiBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciBhbmQgaHR0cHM6Ly9saW5pZC5vcmcvLCBhcyB3ZWxsIGFzXG5iZXR3ZWVuIExJTkFHT1JBIGFuZCBMSU5BR09SQS5jb20sIGFuZCAoaWlpKSByZWZyYWluIGZyb20gaW5mcmluZ2luZyBMSU5BR09SQVxuaW50ZWxsZWN0dWFsIHByb3BlcnR5IHJpZ2h0cyBvdmVyIGl0cyB0cmFkZW1hcmtzIGFuZCBjb21tZXJjaWFsIGJyYW5kcy4gT3RoZXJcbkFkZGl0aW9uYWwgVGVybXMgYXBwbHksIHNlZSA8aHR0cDovL3d3dy5saW5hZ29yYS5jb20vbGljZW5zZXMvPiBmb3IgbW9yZVxuZGV0YWlscy5cblxuVGhpcyBwcm9ncmFtIGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsIGJ1dCBXSVRIT1VUXG5BTlkgV0FSUkFOVFk7IHdpdGhvdXQgZXZlbiB0aGUgaW1wbGllZCB3YXJyYW50eSBvZiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTU1xuRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiBTZWUgdGhlIEdOVSBBZmZlcm8gR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZVxuZGV0YWlscy5cblxuWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIEFmZmVybyBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGFuZFxuaXRzIGFwcGxpY2FibGUgQWRkaXRpb25hbCBUZXJtcyBmb3IgTGluSUQgRGlyZWN0b3J5IE1hbmFnZXIgYWxvbmcgd2l0aCB0aGlzXG5wcm9ncmFtLiBJZiBub3QsIHNlZSA8aHR0cDovL3d3dy5nbnUub3JnL2xpY2Vuc2VzLz4gZm9yIHRoZSBHTlUgQWZmZXJvXG5HZW5lcmFsIFB1YmxpYyBMaWNlbnNlIHZlcnNpb24gMyBhbmQgPGh0dHA6Ly93d3cubGluYWdvcmEuY29tL2xpY2Vuc2VzLz4gZm9yXG50aGUgQWRkaXRpb25hbCBUZXJtcyBhcHBsaWNhYmxlIHRvIHRoZSBMaW5JRCBEaXJlY3RvcnkgTWFuYWdlciBzb2Z0d2FyZS4gLS0+XG5cbjxkaXYgZnhMYXlvdXQ9XCJyb3dcIiBjbGFzcz1cImRpdi1nbmMtZmlsdGVyXCI+XG4gIDxtYXQtZm9ybS1maWVsZFxuICAgICpuZ0lmPVwiZmlsdGVyQWNjZXNzaWJpbGl0eSQgfCBhc3luYyBhcyBmaWx0ZXJBY2Nlc3NpYmlsaXR5XCJcbiAgICBmeEZsZXhcbiAgICBjb2xvcj1cImFjY2VudFwiXG4gICAgW25nQ2xhc3NdPVwie1xuICAgICAgJ2duYy1maWx0ZXItYWN0aXZhdGVkJzpcbiAgICAgICAgYWR2YW5jZWRTZWFyY2hNYXRIaW50Py5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodCA8PSBsaW5lSGVpZ2h0XG4gICAgfVwiXG4gICAgY2xhc3M9XCJnbmMtZmlsdGVyXCJcbiAgPlxuICAgIDxtYXQtbGFiZWw+XG4gICAgICA8bWF0LWljb24gYXJpYS1oaWRkZW49XCJ0cnVlXCI+ZmlsdGVyX2xpc3RfYWx0PC9tYXQtaWNvbj5cbiAgICAgIHt7IGZpbHRlckFjY2Vzc2liaWxpdHkubGFiZWwgfX1cbiAgICA8L21hdC1sYWJlbD5cbiAgICA8aW5wdXRcbiAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgIG1hdElucHV0XG4gICAgICBbKG5nTW9kZWwpXT1cInNlYXJjaFwiXG4gICAgICAobmdNb2RlbENoYW5nZSk9XCJ1cGRhdGVTZWFyY2goJGV2ZW50KVwiXG4gICAgICBjbGFzcz1cImZpbHRlclwiXG4gICAgLz5cbiAgICA8YnV0dG9uXG4gICAgICAqbmdJZj1cInNlYXJjaFwiXG4gICAgICBtYXRTdWZmaXhcbiAgICAgIG1hdC1pY29uLWJ1dHRvblxuICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCJmaWx0ZXJBY2Nlc3NpYmlsaXR5LmNsZWFyU2VhcmNoXCJcbiAgICAgIChjbGljayk9XCJjbGVhcklucHV0RmlsdGVyKClcIlxuICAgICAgY2xhc3M9XCJyZXNldC1pbnB1dC1idG5cIlxuICAgICAgW21hdFRvb2x0aXBdPVwiZmlsdGVyQWNjZXNzaWJpbGl0eS5jbGVhclNlYXJjaFwiXG4gICAgPlxuICAgICAgPG1hdC1pY29uIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPiBjbGVhciA8L21hdC1pY29uPlxuICAgIDwvYnV0dG9uPlxuICA8L21hdC1mb3JtLWZpZWxkPlxuICA8ZGl2XG4gICAgKm5nSWY9XCJjYW5DcmVhdGVcIlxuICAgIGNsYXNzPVwiZGl2LWFkZC1idXR0b25cIlxuICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICdkaXYtYWRkLWJ1dHRvbi13aXRoLWFkdmFuY2VkLXNlYXJjaCc6XG4gICAgICAgIGFkdmFuY2VkU2VhcmNoTWF0SGludD8ubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQgPD0gbGluZUhlaWdodFxuICAgIH1cIlxuICA+XG4gICAgPGJ1dHRvblxuICAgICAgI2NyZWF0ZUxhcmdlQnRuXG4gICAgICBtYXQtcmFpc2VkLWJ1dHRvblxuICAgICAgY29sb3I9XCJhY2NlbnRcIlxuICAgICAgKGNsaWNrKT1cImFkZE5ld1Jlc291cmNlKClcIlxuICAgICAgY2xhc3M9XCJsZy1hZGQtYnRuXCJcbiAgICAgIFtuZ0NsYXNzXT1cImxhcmdlQnRuQWRkaXRpb25uYWxDbGFzc2VzXCJcbiAgICA+XG4gICAgICB7eyBhZGRCdG5MYWJlbCB9fVxuICAgIDwvYnV0dG9uPlxuICAgIDxidXR0b25cbiAgICAgICNjcmVhdGVNaW5pRmFiQnRuXG4gICAgICBtYXQtbWluaS1mYWJcbiAgICAgIGNvbG9yPVwiYWNjZW50XCJcbiAgICAgIG1hdFRvb2x0aXBQb3NpdGlvbj1cInJpZ2h0XCJcbiAgICAgIFttYXRUb29sdGlwXT1cImFkZEJ0bkxhYmVsXCJcbiAgICAgIChjbGljayk9XCJhZGROZXdSZXNvdXJjZSgpXCJcbiAgICAgIGNsYXNzPVwic20tYWRkLWJ0blwiXG4gICAgICBbbmdDbGFzc109XCJzbWFsbEJ0bkFkZGl0aW9ubmFsQ2xhc3Nlc1wiXG4gICAgPlxuICAgICAgPG1hdC1pY29uIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPmFkZDwvbWF0LWljb24+XG4gICAgPC9idXR0b24+XG4gIDwvZGl2PlxuPC9kaXY+XG4iXX0=