@ux-aspects/ux-aspects
Version:
Open source user interface framework for building modern, responsive, mobile big data applications
144 lines • 40 kB
JavaScript
import { Component, ContentChild, ContentChildren, EventEmitter, inject, Input, Output, TemplateRef } from '@angular/core';
import { ColorService } from '../../services/color/index';
import { PageHeaderCustomMenuDirective } from './custom-menu/custom-menu.directive';
import { PageHeaderService } from './page-header.service';
import * as i0 from "@angular/core";
import * as i1 from "../../directives/accessibility/focus-indicator/focus-indicator.directive";
import * as i2 from "../breadcrumbs/breadcrumbs.component";
import * as i3 from "@angular/common";
import * as i4 from "../icon/icon.component";
import * as i5 from "../tabset/tabset.component";
import * as i6 from "../tabset/tab/tab.component";
import * as i7 from "./icon-menu/icon-menu.component";
import * as i8 from "./navigation/navigation.component";
import * as i9 from "./navigation/navigation-secondary-item/navigation-secondary-item.directive";
export class PageHeaderComponent {
constructor() {
this._colorService = inject(ColorService);
this._pageHeaderService = inject(PageHeaderService);
/** The alignment of the primary navigation tabs. */
this.alignment = 'center';
/** Determines whether or not to display the page header in the regular or condensed form. */
this.condensed = false;
/** Determines whether or not a back button should be visible in the page header. */
this.backVisible = true;
/** The alignment of the secondary navigation tabs. */
this.secondaryNavigationAlignment = 'center';
/**
* The style of the breadcrumbs.
* - standard: The breadcrumbs use the same styling as the navigation tabs.
* - small: The breadcrumbs use a smaller font, and case is not adjusted.
*/
this.crumbsStyle = 'standard';
/** Emit whenever the back button is clicked */
this.backClick = new EventEmitter();
/** Emit whenever the product logo in the left corner is clicked. */
this.logoClick = new EventEmitter();
/** The currently selected page header item */
this.selected$ = this._pageHeaderService.selected$;
/** The currently selected root menu item - this may be different from selected$ if a child menu item is selected */
this.selectedRoot$ = this._pageHeaderService.selectedRoot$;
this._crumbs = [];
}
/** If set, the first child item will get selected when the parent item is selected. */
set secondaryNavigationAutoselect(value) {
this._pageHeaderService.secondaryNavigationAutoselect = value;
}
get secondaryNavigationAutoselect() {
return this._pageHeaderService.secondaryNavigationAutoselect;
}
/** The primary navigation tabs. Use the children property in combination with [secondaryNavigation]="true" to include secondary navigation tabs. */
set items(items) {
this._pageHeaderService.setItems(items);
}
/** Whether to show a second level of navigation for any items with children. */
set secondaryNavigation(enabled) {
this._pageHeaderService.setSecondaryNavigation(enabled);
}
get secondaryNavigation() {
return this._pageHeaderService.secondary$.getValue();
}
/** The optional set of breadcrumbs to display on the left side of the masthead. */
set crumbs(crumbs) {
this._crumbs = crumbs;
}
get crumbs() {
return this.condensed ? [...this._crumbs, { title: this.header }] : this._crumbs;
}
/** The logo background color. This can either be the name of a color from the color palette, or a CSS color value. */
set logoBackground(color) {
this._logoBackground = this._colorService.resolve(color);
}
get logoBackground() {
return this._logoBackground;
}
/** The logo text color, when a product acronym is specified via header. This can either be the name of a color from the color palette, or a CSS color value. */
set logoForeground(color) {
this._logoForeground = this._colorService.resolve(color);
}
get logoForeground() {
return this._logoForeground;
}
get _hasLogoClick() {
return this.logoClick.observers.length > 0;
}
select(item, navigate) {
this._pageHeaderService.select(item, navigate);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: PageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.12", type: PageHeaderComponent, selector: "ux-page-header", inputs: { logo: "logo", header: "header", subheader: "subheader", alignment: "alignment", condensed: "condensed", iconMenus: "iconMenus", backVisible: "backVisible", secondaryNavigationAlignment: "secondaryNavigationAlignment", secondaryNavigationAutoselect: "secondaryNavigationAutoselect", items: "items", secondaryNavigation: "secondaryNavigation", crumbs: "crumbs", crumbsStyle: "crumbsStyle", logoBackground: "logoBackground", logoForeground: "logoForeground" }, outputs: { backClick: "backClick", logoClick: "logoClick" }, providers: [PageHeaderService], queries: [{ propertyName: "subheaderTemplate", first: true, predicate: ["subheader"], descendants: true }, { propertyName: "logoTemplate", first: true, predicate: ["logoTemplate"], descendants: true }, { propertyName: "secondaryNavigationLeadingContentTemplate", first: true, predicate: ["secondaryNavigationLeadingContent"], descendants: true }, { propertyName: "secondaryNavigationTrailingContentTemplate", first: true, predicate: ["secondaryNavigationTrailingContent"], descendants: true }, { propertyName: "customMenus", predicate: PageHeaderCustomMenuDirective, read: TemplateRef }], exportAs: ["ux-page-header"], ngImport: i0, template: "<div class=\"ux-page-header\" [class.page-header-condensed]=\"condensed\" role=\"banner\">\n\n @if (!condensed) {\n <div class=\"page-header-content\">\n <!-- Logo/product acronym -->\n <div uxFocusIndicator (keydown.enter)=\"logoClick.emit($event)\" [attr.tabindex]=\"_hasLogoClick ? 0: -1\"\n [class.page-header-logo-template]=\"logoTemplate\" [class.clickable]=\"_hasLogoClick\"\n class=\"page-header-logo-container\"\n role=\"presentation\" [style.backgroundColor]=\"logoBackground\" [style.color]=\"logoForeground\" (click)=\"logoClick.emit($event)\">\n @if (logo && !logoTemplate) {\n <img [attr.src]=\"logo\" [alt]=\"header\" class=\"page-header-logo\">\n }\n @if (header && !logo && !logoTemplate) {\n <h1 class=\"page-header-acronym\">{{header}}</h1>\n }\n @if (logoTemplate) {\n <ng-container [ngTemplateOutlet]=\"logoTemplate\"></ng-container>\n }\n </div>\n <!-- Sub-title -->\n @if (subheader || subheaderTemplate) {\n <div class=\"page-header-subtitle-container\">\n @if (subheader) {\n <span class=\"page-header-subtitle\">{{subheader}}</span>\n }\n <ng-container [ngTemplateOutlet]=\"subheaderTemplate\"></ng-container>\n </div>\n }\n <div class=\"page-header-state-container\" role=\"navigation\">\n <!-- Back button -->\n @if (backVisible === true) {\n <button uxFocusIndicator type=\"button\" class=\"page-header-back-button\" (click)=\"backClick.emit($event)\" aria-label=\"Go Back\">\n <ux-icon name=\"previous\" class=\"text-primary\"></ux-icon>\n </button>\n }\n <!-- Breadcrumbs and header -->\n <div class=\"page-header-title-container\">\n @if (crumbs && crumbs.length > 0) {\n <ux-breadcrumbs\n [class.ux-breadcrumbs-small]=\"crumbsStyle === 'small'\"\n [crumbs]=\"crumbs\"></ux-breadcrumbs>\n }\n <h1 class=\"page-header-title\">{{header}}</h1>\n </div>\n </div>\n <!-- Primary navigation -->\n <div class=\"page-header-navigation\" [ngClass]=\"alignment\" role=\"navigation\" aria-label=\"Primary Navigation\">\n <ux-page-header-horizontal-navigation></ux-page-header-horizontal-navigation>\n </div>\n <!-- Icon menus -->\n <div class=\"page-header-icon-menus\" role=\"toolbar\">\n @for (menu of customMenus; track menu) {\n <ng-container [ngTemplateOutlet]=\"menu\"></ng-container>\n }\n @for (menu of iconMenus; track menu) {\n <ux-page-header-icon-menu [menu]=\"menu\"></ux-page-header-icon-menu>\n }\n </div>\n </div>\n }\n\n <!-- Display This Section Optimized for Condensed Mode -->\n @if (condensed) {\n <div class=\"page-header-condensed-content\">\n <div class=\"page-header-breadcrumbs\" role=\"navigation\">\n <ux-breadcrumbs [crumbs]=\"crumbs\"></ux-breadcrumbs>\n </div>\n <div class=\"page-header-navigation\" [ngClass]=\"alignment\" role=\"navigation\" aria-label=\"Primary Navigation\">\n <!-- The Top Navigation Options -->\n <ux-page-header-horizontal-navigation></ux-page-header-horizontal-navigation>\n </div>\n <div class=\"page-header-icon-menus\" role=\"toolbar\">\n @for (menu of customMenus; track menu) {\n <ng-container [ngTemplateOutlet]=\"menu\"></ng-container>\n }\n @for (menu of iconMenus; track menu) {\n <ux-page-header-icon-menu [menu]=\"menu\"></ux-page-header-icon-menu>\n }\n </div>\n </div>\n }\n\n</div>\n\n<!-- Secondary Header Section -->\n@if (secondaryNavigation && ((selectedRoot$ | async) !== (selected$ | async))) {\n <div class=\"ux-page-header-secondary\">\n <!-- Secondary Navigation Leading Content -->\n @if (secondaryNavigationLeadingContentTemplate || secondaryNavigationTrailingContentTemplate) {\n <div class=\"page-header-secondary-leading-content\">\n <ng-container [ngTemplateOutlet]=\"secondaryNavigationLeadingContentTemplate\"></ng-container>\n </div>\n }\n <!-- Secondary Navigation (children of top level items) -->\n <div [ngClass]=\"['page-header-navigation', secondaryNavigationAlignment]\" role=\"navigation\">\n @if ((selectedRoot$ | async)?.children; as children) {\n <ux-tabset [manual]=\"true\">\n @for (child of children; track child) {\n <ux-tab\n [heading]=\"child.title\"\n [route]=\"child.routerLink\"\n [id]=\"child.id\"\n [routerLinkExtras]=\"child.routerExtras\"\n [active]=\"child === (selected$ | async)\"\n (activated)=\"select(child, false)\"\n [uxPageHeaderNavigationSecondaryItem]=\"child\"\n [disabled]=\"child.disabled\">\n </ux-tab>\n }\n </ux-tabset>\n }\n </div>\n <!-- Secondary Navigation Trialing Content -->\n @if (secondaryNavigationTrailingContentTemplate) {\n <div class=\"page-header-secondary-trailing-content\">\n <ng-container [ngTemplateOutlet]=\"secondaryNavigationTrailingContentTemplate\"></ng-container>\n </div>\n }\n </div>\n}\n", dependencies: [{ kind: "directive", type: i1.FocusIndicatorDirective, selector: "[uxFocusIndicator]", inputs: ["checkChildren", "mouseFocusIndicator", "touchFocusIndicator", "keyboardFocusIndicator", "programmaticFocusIndicator"], outputs: ["indicator"], exportAs: ["ux-focus-indicator"] }, { kind: "component", type: i2.BreadcrumbsComponent, selector: "ux-breadcrumbs", inputs: ["crumbs"] }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i4.IconComponent, selector: "ux-icon", inputs: ["name", "size", "rotate", "flipHorizontal", "flipVertical"] }, { kind: "component", type: i5.TabsetComponent, selector: "ux-tabset", inputs: ["minimal", "stacked", "manual", "aria-label"] }, { kind: "component", type: i6.TabComponent, selector: "ux-tab", inputs: ["id", "active", "disabled", "heading", "route", "routerLinkExtras", "customClass"], outputs: ["activeChange", "activated", "deactivated"] }, { kind: "component", type: i7.PageHeaderIconMenuComponent, selector: "ux-page-header-icon-menu", inputs: ["menu"] }, { kind: "component", type: i8.PageHeaderNavigationComponent, selector: "ux-page-header-horizontal-navigation" }, { kind: "directive", type: i9.PageHeaderNavigationSecondaryItemDirective, selector: "[uxPageHeaderNavigationSecondaryItem]", inputs: ["uxPageHeaderNavigationSecondaryItem"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: PageHeaderComponent, decorators: [{
type: Component,
args: [{ selector: 'ux-page-header', exportAs: 'ux-page-header', providers: [PageHeaderService], template: "<div class=\"ux-page-header\" [class.page-header-condensed]=\"condensed\" role=\"banner\">\n\n @if (!condensed) {\n <div class=\"page-header-content\">\n <!-- Logo/product acronym -->\n <div uxFocusIndicator (keydown.enter)=\"logoClick.emit($event)\" [attr.tabindex]=\"_hasLogoClick ? 0: -1\"\n [class.page-header-logo-template]=\"logoTemplate\" [class.clickable]=\"_hasLogoClick\"\n class=\"page-header-logo-container\"\n role=\"presentation\" [style.backgroundColor]=\"logoBackground\" [style.color]=\"logoForeground\" (click)=\"logoClick.emit($event)\">\n @if (logo && !logoTemplate) {\n <img [attr.src]=\"logo\" [alt]=\"header\" class=\"page-header-logo\">\n }\n @if (header && !logo && !logoTemplate) {\n <h1 class=\"page-header-acronym\">{{header}}</h1>\n }\n @if (logoTemplate) {\n <ng-container [ngTemplateOutlet]=\"logoTemplate\"></ng-container>\n }\n </div>\n <!-- Sub-title -->\n @if (subheader || subheaderTemplate) {\n <div class=\"page-header-subtitle-container\">\n @if (subheader) {\n <span class=\"page-header-subtitle\">{{subheader}}</span>\n }\n <ng-container [ngTemplateOutlet]=\"subheaderTemplate\"></ng-container>\n </div>\n }\n <div class=\"page-header-state-container\" role=\"navigation\">\n <!-- Back button -->\n @if (backVisible === true) {\n <button uxFocusIndicator type=\"button\" class=\"page-header-back-button\" (click)=\"backClick.emit($event)\" aria-label=\"Go Back\">\n <ux-icon name=\"previous\" class=\"text-primary\"></ux-icon>\n </button>\n }\n <!-- Breadcrumbs and header -->\n <div class=\"page-header-title-container\">\n @if (crumbs && crumbs.length > 0) {\n <ux-breadcrumbs\n [class.ux-breadcrumbs-small]=\"crumbsStyle === 'small'\"\n [crumbs]=\"crumbs\"></ux-breadcrumbs>\n }\n <h1 class=\"page-header-title\">{{header}}</h1>\n </div>\n </div>\n <!-- Primary navigation -->\n <div class=\"page-header-navigation\" [ngClass]=\"alignment\" role=\"navigation\" aria-label=\"Primary Navigation\">\n <ux-page-header-horizontal-navigation></ux-page-header-horizontal-navigation>\n </div>\n <!-- Icon menus -->\n <div class=\"page-header-icon-menus\" role=\"toolbar\">\n @for (menu of customMenus; track menu) {\n <ng-container [ngTemplateOutlet]=\"menu\"></ng-container>\n }\n @for (menu of iconMenus; track menu) {\n <ux-page-header-icon-menu [menu]=\"menu\"></ux-page-header-icon-menu>\n }\n </div>\n </div>\n }\n\n <!-- Display This Section Optimized for Condensed Mode -->\n @if (condensed) {\n <div class=\"page-header-condensed-content\">\n <div class=\"page-header-breadcrumbs\" role=\"navigation\">\n <ux-breadcrumbs [crumbs]=\"crumbs\"></ux-breadcrumbs>\n </div>\n <div class=\"page-header-navigation\" [ngClass]=\"alignment\" role=\"navigation\" aria-label=\"Primary Navigation\">\n <!-- The Top Navigation Options -->\n <ux-page-header-horizontal-navigation></ux-page-header-horizontal-navigation>\n </div>\n <div class=\"page-header-icon-menus\" role=\"toolbar\">\n @for (menu of customMenus; track menu) {\n <ng-container [ngTemplateOutlet]=\"menu\"></ng-container>\n }\n @for (menu of iconMenus; track menu) {\n <ux-page-header-icon-menu [menu]=\"menu\"></ux-page-header-icon-menu>\n }\n </div>\n </div>\n }\n\n</div>\n\n<!-- Secondary Header Section -->\n@if (secondaryNavigation && ((selectedRoot$ | async) !== (selected$ | async))) {\n <div class=\"ux-page-header-secondary\">\n <!-- Secondary Navigation Leading Content -->\n @if (secondaryNavigationLeadingContentTemplate || secondaryNavigationTrailingContentTemplate) {\n <div class=\"page-header-secondary-leading-content\">\n <ng-container [ngTemplateOutlet]=\"secondaryNavigationLeadingContentTemplate\"></ng-container>\n </div>\n }\n <!-- Secondary Navigation (children of top level items) -->\n <div [ngClass]=\"['page-header-navigation', secondaryNavigationAlignment]\" role=\"navigation\">\n @if ((selectedRoot$ | async)?.children; as children) {\n <ux-tabset [manual]=\"true\">\n @for (child of children; track child) {\n <ux-tab\n [heading]=\"child.title\"\n [route]=\"child.routerLink\"\n [id]=\"child.id\"\n [routerLinkExtras]=\"child.routerExtras\"\n [active]=\"child === (selected$ | async)\"\n (activated)=\"select(child, false)\"\n [uxPageHeaderNavigationSecondaryItem]=\"child\"\n [disabled]=\"child.disabled\">\n </ux-tab>\n }\n </ux-tabset>\n }\n </div>\n <!-- Secondary Navigation Trialing Content -->\n @if (secondaryNavigationTrailingContentTemplate) {\n <div class=\"page-header-secondary-trailing-content\">\n <ng-container [ngTemplateOutlet]=\"secondaryNavigationTrailingContentTemplate\"></ng-container>\n </div>\n }\n </div>\n}\n" }]
}], propDecorators: { logo: [{
type: Input
}], header: [{
type: Input
}], subheader: [{
type: Input
}], alignment: [{
type: Input
}], condensed: [{
type: Input
}], iconMenus: [{
type: Input
}], backVisible: [{
type: Input
}], secondaryNavigationAlignment: [{
type: Input
}], secondaryNavigationAutoselect: [{
type: Input
}], items: [{
type: Input
}], secondaryNavigation: [{
type: Input
}], crumbs: [{
type: Input
}], crumbsStyle: [{
type: Input
}], logoBackground: [{
type: Input
}], logoForeground: [{
type: Input
}], backClick: [{
type: Output
}], logoClick: [{
type: Output
}], subheaderTemplate: [{
type: ContentChild,
args: ['subheader', { static: false }]
}], logoTemplate: [{
type: ContentChild,
args: ['logoTemplate', { static: false }]
}], secondaryNavigationLeadingContentTemplate: [{
type: ContentChild,
args: ['secondaryNavigationLeadingContent', { static: false }]
}], secondaryNavigationTrailingContentTemplate: [{
type: ContentChild,
args: ['secondaryNavigationTrailingContent', { static: false }]
}], customMenus: [{
type: ContentChildren,
args: [PageHeaderCustomMenuDirective, { read: TemplateRef }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnZS1oZWFkZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvcGFnZS1oZWFkZXIvcGFnZS1oZWFkZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvcGFnZS1oZWFkZXIvcGFnZS1oZWFkZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBYSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFdEksT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRTFELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBR3BGLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7Ozs7Ozs7Ozs7QUFVaEYsTUFBTSxPQUFPLG1CQUFtQjtJQU5oQztRQU9xQixrQkFBYSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUVyQyx1QkFBa0IsR0FBRyxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQztRQVdoRSxvREFBb0Q7UUFDM0MsY0FBUyxHQUFrQyxRQUFRLENBQUM7UUFFN0QsNkZBQTZGO1FBQ3BGLGNBQVMsR0FBWSxLQUFLLENBQUM7UUFLcEMsb0ZBQW9GO1FBQzNFLGdCQUFXLEdBQVksSUFBSSxDQUFDO1FBRXJDLHNEQUFzRDtRQUM3QyxpQ0FBNEIsR0FBa0MsUUFBUSxDQUFDO1FBc0NoRjs7OztXQUlHO1FBQ00sZ0JBQVcsR0FBeUIsVUFBVSxDQUFDO1FBMEJ4RCwrQ0FBK0M7UUFDckMsY0FBUyxHQUFHLElBQUksWUFBWSxFQUFjLENBQUM7UUFFckQsb0VBQW9FO1FBQzFELGNBQVMsR0FBRyxJQUFJLFlBQVks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Riw2QkFBNkI7c0JBRGhDLEtBQUs7Z0JBV0YsS0FBSztzQkFEUixLQUFLO2dCQU9GLG1CQUFtQjtzQkFEdEIsS0FBSztnQkFXRixNQUFNO3NCQURULEtBQUs7Z0JBY0csV0FBVztzQkFBbkIsS0FBSztnQkFJRixjQUFjO3NCQURqQixLQUFLO2dCQVdGLGNBQWM7c0JBRGpCLEtBQUs7Z0JBY0ksU0FBUztzQkFBbEIsTUFBTTtnQkFHRyxTQUFTO3NCQUFsQixNQUFNO2dCQUd1QyxpQkFBaUI7c0JBQTlELFlBQVk7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFHSyxZQUFZO3NCQUE1RCxZQUFZO3VCQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBR3VCLHlDQUF5QztzQkFBOUcsWUFBWTt1QkFBQyxtQ0FBbUMsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBR0csMENBQTBDO3NCQUFoSCxZQUFZO3VCQUFDLG9DQUFvQyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFHRSxXQUFXO3NCQUFqRixlQUFlO3VCQUFDLDZCQUE2QixFQUFFLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgQ29udGVudENoaWxkLCBDb250ZW50Q2hpbGRyZW4sIEV2ZW50RW1pdHRlciwgaW5qZWN0LCBJbnB1dCwgT3V0cHV0LCBRdWVyeUxpc3QsIFRlbXBsYXRlUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IENvbG9yU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2NvbG9yL2luZGV4JztcbmltcG9ydCB7IEJyZWFkY3J1bWIgfSBmcm9tICcuLi9icmVhZGNydW1icy9pbmRleCc7XG5pbXBvcnQgeyBQYWdlSGVhZGVyQ3VzdG9tTWVudURpcmVjdGl2ZSB9IGZyb20gJy4vY3VzdG9tLW1lbnUvY3VzdG9tLW1lbnUuZGlyZWN0aXZlJztcbmltcG9ydCB7IFBhZ2VIZWFkZXJJY29uTWVudSB9IGZyb20gJy4vaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW0gfSBmcm9tICcuL25hdmlnYXRpb24vbmF2aWdhdGlvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgUGFnZUhlYWRlck5hdmlnYXRpb24sIFBhZ2VIZWFkZXJTZXJ2aWNlIH0gZnJvbSAnLi9wYWdlLWhlYWRlci5zZXJ2aWNlJztcblxuZXhwb3J0IHR5cGUgUGFnZUhlYWRlck5hdmlnYXRpb25BbGlnbm1lbnQgPSAnbGVmdCcgfCAncmlnaHQnIHwgJ2NlbnRlcic7XG5cbkBDb21wb25lbnQoe1xuICAgIHNlbGVjdG9yOiAndXgtcGFnZS1oZWFkZXInLFxuICAgIGV4cG9ydEFzOiAndXgtcGFnZS1oZWFkZXInLFxuICAgIHRlbXBsYXRlVXJsOiAncGFnZS1oZWFkZXIuY29tcG9uZW50Lmh0bWwnLFxuICAgIHByb3ZpZGVyczogW1BhZ2VIZWFkZXJTZXJ2aWNlXVxufSlcbmV4cG9ydCBjbGFzcyBQYWdlSGVhZGVyQ29tcG9uZW50IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9jb2xvclNlcnZpY2UgPSBpbmplY3QoQ29sb3JTZXJ2aWNlKTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3BhZ2VIZWFkZXJTZXJ2aWNlID0gaW5qZWN0KFBhZ2VIZWFkZXJTZXJ2aWNlKTtcblxuICAgIC8qKiBUaGUgcGF0aCB0byBhbiBpbWFnZSB0byBkaXNwbGF5IGFzIHRoZSBwcm9kdWN0IGxvZ28gaW4gdGhlIGxlZnQgY29ybmVyLiAqL1xuICAgIEBJbnB1dCgpIGxvZ286IHN0cmluZztcblxuICAgIC8qKiBUaGUgcHJvZHVjdCBhY3JvbnltIHRvIGRpc3BsYXkgaW4gdGhlIGxlZnQgY29ybmVyLiBUaGlzIHdpbGwgb25seSBiZSBkaXNwbGF5ZWQgaWYgbG9nbyBpcyB1bnNldDsgb3RoZXJ3aXNlIGl0IHdpbGwgYmUgdXNlZCBhcyB0aGUgYWx0IHRleHQgZm9yIHRoZSBsb2dvLiAqL1xuICAgIEBJbnB1dCgpIGhlYWRlcjogc3RyaW5nO1xuXG4gICAgLyoqIFRoZSBvcHRpb25hbCBoZWFkZXIgdG8gZGlzcGxheSBvbiB0aGUgbGVmdCBzaWRlIG9mIHRoZSBtYXN0aGVhZC4gKi9cbiAgICBASW5wdXQoKSBzdWJoZWFkZXI6IHN0cmluZztcblxuICAgIC8qKiBUaGUgYWxpZ25tZW50IG9mIHRoZSBwcmltYXJ5IG5hdmlnYXRpb24gdGFicy4gKi9cbiAgICBASW5wdXQoKSBhbGlnbm1lbnQ6IFBhZ2VIZWFkZXJOYXZpZ2F0aW9uQWxpZ25tZW50ID0gJ2NlbnRlcic7XG5cbiAgICAvKiogRGV0ZXJtaW5lcyB3aGV0aGVyIG9yIG5vdCB0byBkaXNwbGF5IHRoZSBwYWdlIGhlYWRlciBpbiB0aGUgcmVndWxhciBvciBjb25kZW5zZWQgZm9ybS4gKi9cbiAgICBASW5wdXQoKSBjb25kZW5zZWQ6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAgIC8qKiBUaGUgbGlzdCBvZiBpY29uIG1lbnVzIHRvIGRpc3BsYXkgaW4gdGhlIHRvcCByaWdodCBhcmVhIG9mIHRoZSBwYWdlIGhlYWRlci4gKi9cbiAgICBASW5wdXQoKSBpY29uTWVudXM6IFBhZ2VIZWFkZXJJY29uTWVudVtdO1xuXG4gICAgLyoqIERldGVybWluZXMgd2hldGhlciBvciBub3QgYSBiYWNrIGJ1dHRvbiBzaG91bGQgYmUgdmlzaWJsZSBpbiB0aGUgcGFnZSBoZWFkZXIuICovXG4gICAgQElucHV0KCkgYmFja1Zpc2libGU6IGJvb2xlYW4gPSB0cnVlO1xuXG4gICAgLyoqIFRoZSBhbGlnbm1lbnQgb2YgdGhlIHNlY29uZGFyeSBuYXZpZ2F0aW9uIHRhYnMuICovXG4gICAgQElucHV0KCkgc2Vjb25kYXJ5TmF2aWdhdGlvbkFsaWdubWVudDogUGFnZUhlYWRlck5hdmlnYXRpb25BbGlnbm1lbnQgPSAnY2VudGVyJztcblxuICAgIC8qKiBJZiBzZXQsIHRoZSBmaXJzdCBjaGlsZCBpdGVtIHdpbGwgZ2V0IHNlbGVjdGVkIHdoZW4gdGhlIHBhcmVudCBpdGVtIGlzIHNlbGVjdGVkLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IHNlY29uZGFyeU5hdmlnYXRpb25BdXRvc2VsZWN0KHZhbHVlOiBib29sZWFuKSB7XG4gICAgICAgIHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNlY29uZGFyeU5hdmlnYXRpb25BdXRvc2VsZWN0ID0gdmFsdWU7XG4gICAgfVxuXG4gICAgZ2V0IHNlY29uZGFyeU5hdmlnYXRpb25BdXRvc2VsZWN0KCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGFnZUhlYWRlclNlcnZpY2Uuc2Vjb25kYXJ5TmF2aWdhdGlvbkF1dG9zZWxlY3Q7XG4gICAgfVxuXG4gICAgLyoqIFRoZSBwcmltYXJ5IG5hdmlnYXRpb24gdGFicy4gVXNlIHRoZSBjaGlsZHJlbiBwcm9wZXJ0eSBpbiBjb21iaW5hdGlvbiB3aXRoIFtzZWNvbmRhcnlOYXZpZ2F0aW9uXT1cInRydWVcIiB0byBpbmNsdWRlIHNlY29uZGFyeSBuYXZpZ2F0aW9uIHRhYnMuICovXG4gICAgQElucHV0KClcbiAgICBzZXQgaXRlbXMoaXRlbXM6IFBhZ2VIZWFkZXJOYXZpZ2F0aW9uSXRlbVtdKSB7XG4gICAgICAgIHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNldEl0ZW1zKGl0ZW1zKTtcbiAgICB9XG5cbiAgICAvKiogV2hldGhlciB0byBzaG93IGEgc2Vjb25kIGxldmVsIG9mIG5hdmlnYXRpb24gZm9yIGFueSBpdGVtcyB3aXRoIGNoaWxkcmVuLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IHNlY29uZGFyeU5hdmlnYXRpb24oZW5hYmxlZDogYm9vbGVhbikge1xuICAgICAgICB0aGlzLl9wYWdlSGVhZGVyU2VydmljZS5zZXRTZWNvbmRhcnlOYXZpZ2F0aW9uKGVuYWJsZWQpO1xuICAgIH1cblxuICAgIGdldCBzZWNvbmRhcnlOYXZpZ2F0aW9uKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fcGFnZUhlYWRlclNlcnZpY2Uuc2Vjb25kYXJ5JC5nZXRWYWx1ZSgpO1xuICAgIH1cblxuICAgIC8qKiBUaGUgb3B0aW9uYWwgc2V0IG9mIGJyZWFkY3J1bWJzIHRvIGRpc3BsYXkgb24gdGhlIGxlZnQgc2lkZSBvZiB0aGUgbWFzdGhlYWQuICovXG4gICAgQElucHV0KClcbiAgICBzZXQgY3J1bWJzKGNydW1iczogQnJlYWRjcnVtYltdKSB7XG4gICAgICAgIHRoaXMuX2NydW1icyA9IGNydW1icztcbiAgICB9XG5cbiAgICBnZXQgY3J1bWJzKCk6IEJyZWFkY3J1bWJbXSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbmRlbnNlZCA/IFsuLi50aGlzLl9jcnVtYnMsIHsgdGl0bGU6IHRoaXMuaGVhZGVyIH1dIDogdGhpcy5fY3J1bWJzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRoZSBzdHlsZSBvZiB0aGUgYnJlYWRjcnVtYnMuXG4gICAgICogICAtIHN0YW5kYXJkOiBUaGUgYnJlYWRjcnVtYnMgdXNlIHRoZSBzYW1lIHN0eWxpbmcgYXMgdGhlIG5hdmlnYXRpb24gdGFicy5cbiAgICAgKiAgIC0gc21hbGw6IFRoZSBicmVhZGNydW1icyB1c2UgYSBzbWFsbGVyIGZvbnQsIGFuZCBjYXNlIGlzIG5vdCBhZGp1c3RlZC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBjcnVtYnNTdHlsZTogJ3N0YW5kYXJkJyB8ICdzbWFsbCcgPSAnc3RhbmRhcmQnO1xuXG4gICAgLyoqIFRoZSBsb2dvIGJhY2tncm91bmQgY29sb3IuIFRoaXMgY2FuIGVpdGhlciBiZSB0aGUgbmFtZSBvZiBhIGNvbG9yIGZyb20gdGhlIGNvbG9yIHBhbGV0dGUsIG9yIGEgQ1NTIGNvbG9yIHZhbHVlLiAqL1xuICAgIEBJbnB1dCgpXG4gICAgc2V0IGxvZ29CYWNrZ3JvdW5kKGNvbG9yOiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5fbG9nb0JhY2tncm91bmQgPSB0aGlzLl9jb2xvclNlcnZpY2UucmVzb2x2ZShjb2xvcik7XG4gICAgfVxuXG4gICAgZ2V0IGxvZ29CYWNrZ3JvdW5kKCk6IHN0cmluZyB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sb2dvQmFja2dyb3VuZDtcbiAgICB9XG5cbiAgICAvKiogVGhlIGxvZ28gdGV4dCBjb2xvciwgd2hlbiBhIHByb2R1Y3QgYWNyb255bSBpcyBzcGVjaWZpZWQgdmlhIGhlYWRlci4gVGhpcyBjYW4gZWl0aGVyIGJlIHRoZSBuYW1lIG9mIGEgY29sb3IgZnJvbSB0aGUgY29sb3IgcGFsZXR0ZSwgb3IgYSBDU1MgY29sb3IgdmFsdWUuICovXG4gICAgQElucHV0KClcbiAgICBzZXQgbG9nb0ZvcmVncm91bmQoY29sb3I6IHN0cmluZykge1xuICAgICAgICB0aGlzLl9sb2dvRm9yZWdyb3VuZCA9IHRoaXMuX2NvbG9yU2VydmljZS5yZXNvbHZlKGNvbG9yKTtcbiAgICB9XG5cbiAgICBnZXQgbG9nb0ZvcmVncm91bmQoKTogc3RyaW5nIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvZ29Gb3JlZ3JvdW5kO1xuICAgIH1cblxuICAgIGdldCBfaGFzTG9nb0NsaWNrKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2dvQ2xpY2sub2JzZXJ2ZXJzLmxlbmd0aCA+IDA7XG4gICAgfVxuXG4gICAgLyoqIEVtaXQgd2hlbmV2ZXIgdGhlIGJhY2sgYnV0dG9uIGlzIGNsaWNrZWQgKi9cbiAgICBAT3V0cHV0KCkgYmFja0NsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxNb3VzZUV2ZW50PigpO1xuXG4gICAgLyoqIEVtaXQgd2hlbmV2ZXIgdGhlIHByb2R1Y3QgbG9nbyBpbiB0aGUgbGVmdCBjb3JuZXIgaXMgY2xpY2tlZC4gKi9cbiAgICBAT3V0cHV0KCkgbG9nb0NsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxFdmVudD4oKTtcblxuICAgIC8qKiBBY2Nlc3MgYSBjdXN0b20gc3ViaGVhZGVyIHRlbXBsYXRlICovXG4gICAgQENvbnRlbnRDaGlsZCgnc3ViaGVhZGVyJywgeyBzdGF0aWM6IGZhbHNlIH0pIHN1YmhlYWRlclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjx2b2lkPjtcblxuICAgIC8qKiBEZWZpbmUgYSBjdXN0b20gbG9nbyB0ZW1wbGF0ZSAgKi9cbiAgICBAQ29udGVudENoaWxkKCdsb2dvVGVtcGxhdGUnLCB7IHN0YXRpYzogZmFsc2UgfSkgbG9nb1RlbXBsYXRlOiBUZW1wbGF0ZVJlZjx2b2lkPjtcblxuICAgIC8qKiBEZWZpbmUgYSBsZWFkaW5nIGNvbnRlbnQgc2Vjb25kYXJ5IG5hdmlnYXRpb24gdGVtcGxhdGUgKi9cbiAgICBAQ29udGVudENoaWxkKCdzZWNvbmRhcnlOYXZpZ2F0aW9uTGVhZGluZ0NvbnRlbnQnLCB7IHN0YXRpYzogZmFsc2UgfSkgc2Vjb25kYXJ5TmF2aWdhdGlvbkxlYWRpbmdDb250ZW50VGVtcGxhdGU6IFRlbXBsYXRlUmVmPHZvaWQ+O1xuXG4gICAgLyoqIERlZmluZSBhIHRyYWlsaW5nIGNvbnRlbnQgc2Vjb25kYXJ5IG5hdmlnYXRpb24gdGVtcGxhdGUgKi9cbiAgICBAQ29udGVudENoaWxkKCdzZWNvbmRhcnlOYXZpZ2F0aW9uVHJhaWxpbmdDb250ZW50JywgeyBzdGF0aWM6IGZhbHNlIH0pIHNlY29uZGFyeU5hdmlnYXRpb25UcmFpbGluZ0NvbnRlbnRUZW1wbGF0ZTogVGVtcGxhdGVSZWY8dm9pZD47XG5cbiAgICAvKiogQWNjZXNzIGFsbCB0aGUgY3VzdG9tIG1lbnUgVGVtcGxhdGVSZWZzICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihQYWdlSGVhZGVyQ3VzdG9tTWVudURpcmVjdGl2ZSwgeyByZWFkOiBUZW1wbGF0ZVJlZiB9KSBjdXN0b21NZW51czogUXVlcnlMaXN0PFRlbXBsYXRlUmVmPHZvaWQ+PjtcblxuICAgIC8qKiBUaGUgY3VycmVudGx5IHNlbGVjdGVkIHBhZ2UgaGVhZGVyIGl0ZW0gKi9cbiAgICBzZWxlY3RlZCQ6IEJlaGF2aW9yU3ViamVjdDxQYWdlSGVhZGVyTmF2aWdhdGlvbkl0ZW0+ID0gdGhpcy5fcGFnZUhlYWRlclNlcnZpY2Uuc2VsZWN0ZWQkO1xuXG4gICAgLyoqIFRoZSBjdXJyZW50bHkgc2VsZWN0ZWQgcm9vdCBtZW51IGl0ZW0gLSB0aGlzIG1heSBiZSBkaWZmZXJlbnQgZnJvbSBzZWxlY3RlZCQgaWYgYSBjaGlsZCBtZW51IGl0ZW0gaXMgc2VsZWN0ZWQgKi9cbiAgICBzZWxlY3RlZFJvb3QkOiBCZWhhdmlvclN1YmplY3Q8UGFnZUhlYWRlck5hdmlnYXRpb25JdGVtPiA9IHRoaXMuX3BhZ2VIZWFkZXJTZXJ2aWNlLnNlbGVjdGVkUm9vdCQ7XG5cbiAgICBwcml2YXRlIF9jcnVtYnM6IEJyZWFkY3J1bWJbXSA9IFtdO1xuICAgIHByaXZhdGUgX2xvZ29CYWNrZ3JvdW5kOiBzdHJpbmc7XG4gICAgcHJpdmF0ZSBfbG9nb0ZvcmVncm91bmQ6IHN0cmluZztcblxuICAgIHNlbGVjdChpdGVtOiBQYWdlSGVhZGVyTmF2aWdhdGlvbiwgbmF2aWdhdGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgdGhpcy5fcGFnZUhlYWRlclNlcnZpY2Uuc2VsZWN0KGl0ZW0sIG5hdmlnYXRlKTtcbiAgICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwidXgtcGFnZS1oZWFkZXJcIiBbY2xhc3MucGFnZS1oZWFkZXItY29uZGVuc2VkXT1cImNvbmRlbnNlZFwiIHJvbGU9XCJiYW5uZXJcIj5cblxuICBAaWYgKCFjb25kZW5zZWQpIHtcbiAgICA8ZGl2IGNsYXNzPVwicGFnZS1oZWFkZXItY29udGVudFwiPlxuICAgICAgPCEtLSBMb2dvL3Byb2R1Y3QgYWNyb255bSAtLT5cbiAgICAgIDxkaXYgdXhGb2N1c0luZGljYXRvciAoa2V5ZG93bi5lbnRlcik9XCJsb2dvQ2xpY2suZW1pdCgkZXZlbnQpXCIgW2F0dHIudGFiaW5kZXhdPVwiX2hhc0xvZ29DbGljayA/IDA6IC0xXCJcbiAgICAgICAgW2NsYXNzLnBhZ2UtaGVhZGVyLWxvZ28tdGVtcGxhdGVdPVwibG9nb1RlbXBsYXRlXCIgW2NsYXNzLmNsaWNrYWJsZV09XCJfaGFzTG9nb0NsaWNrXCJcbiAgICAgICAgY2xhc3M9XCJwYWdlLWhlYWRlci1sb2dvLWNvbnRhaW5lclwiXG4gICAgICAgIHJvbGU9XCJwcmVzZW50YXRpb25cIiBbc3R5bGUuYmFja2dyb3VuZENvbG9yXT1cImxvZ29CYWNrZ3JvdW5kXCIgW3N0eWxlLmNvbG9yXT1cImxvZ29Gb3JlZ3JvdW5kXCIgKGNsaWNrKT1cImxvZ29DbGljay5lbWl0KCRldmVudClcIj5cbiAgICAgICAgQGlmIChsb2dvICYmICFsb2dvVGVtcGxhdGUpIHtcbiAgICAgICAgICA8aW1nIFthdHRyLnNyY109XCJsb2dvXCIgW2FsdF09XCJoZWFkZXJcIiBjbGFzcz1cInBhZ2UtaGVhZGVyLWxvZ29cIj5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGhlYWRlciAmJiAhbG9nbyAmJiAhbG9nb1RlbXBsYXRlKSB7XG4gICAgICAgICAgPGgxIGNsYXNzPVwicGFnZS1oZWFkZXItYWNyb255bVwiPnt7aGVhZGVyfX08L2gxPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAobG9nb1RlbXBsYXRlKSB7XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJsb2dvVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgICA8IS0tIFN1Yi10aXRsZSAtLT5cbiAgICAgIEBpZiAoc3ViaGVhZGVyIHx8IHN1YmhlYWRlclRlbXBsYXRlKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJwYWdlLWhlYWRlci1zdWJ0aXRsZS1jb250YWluZXJcIj5cbiAgICAgICAgICBAaWYgKHN1YmhlYWRlcikge1xuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwYWdlLWhlYWRlci1zdWJ0aXRsZVwiPnt7c3ViaGVhZGVyfX08L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwic3ViaGVhZGVyVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgICA8ZGl2IGNsYXNzPVwicGFnZS1oZWFkZXItc3RhdGUtY29udGFpbmVyXCIgcm9sZT1cIm5hdmlnYXRpb25cIj5cbiAgICAgICAgPCEtLSBCYWNrIGJ1dHRvbiAtLT5cbiAgICAgICAgQGlmIChiYWNrVmlzaWJsZSA9PT0gdHJ1ZSkge1xuICAgICAgICAgIDxidXR0b24gdXhGb2N1c0luZGljYXRvciB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJwYWdlLWhlYWRlci1iYWNrLWJ1dHRvblwiIChjbGljayk9XCJiYWNrQ2xpY2suZW1pdCgkZXZlbnQpXCIgYXJpYS1sYWJlbD1cIkdvIEJhY2tcIj5cbiAgICAgICAgICAgIDx1eC1pY29uIG5hbWU9XCJwcmV2aW91c1wiIGNsYXNzPVwidGV4dC1wcmltYXJ5XCI+PC91eC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgICAgIDwhLS0gQnJlYWRjcnVtYnMgYW5kIGhlYWRlciAtLT5cbiAgICAgICAgPGRpdiBjbGFzcz1cInBhZ2UtaGVhZGVyLXRpdGxlLWNvbnRhaW5lclwiPlxuICAgICAgICAgIEBpZiAoY3J1bWJzICYmIGNydW1icy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICA8dXgtYnJlYWRjcnVtYnNcbiAgICAgICAgICAgICAgW2NsYXNzLnV4LWJyZWFkY3J1bWJzLXNtYWxsXT1cImNydW1ic1N0eWxlID09PSAnc21hbGwnXCJcbiAgICAgICAgICAgIFtjcnVtYnNdPVwiY3J1bWJzXCI+PC91eC1icmVhZGNydW1icz5cbiAgICAgICAgICB9XG4gICAgICAgICAgPGgxIGNsYXNzPVwicGFnZS1oZWFkZXItdGl0bGVcIj57e2hlYWRlcn19PC9oMT5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICAgIDwhLS0gUHJpbWFyeSBuYXZpZ2F0aW9uIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInBhZ2UtaGVhZGVyLW5hdmlnYXRpb25cIiBbbmdDbGFzc109XCJhbGlnbm1lbnRcIiByb2xlPVwibmF2aWdhdGlvblwiIGFyaWEtbGFiZWw9XCJQcmltYXJ5IE5hdmlnYXRpb25cIj5cbiAgICAgICAgPHV4LXBhZ2UtaGVhZGVyLWhvcml6b250YWwtbmF2aWdhdGlvbj48L3V4LXBhZ2UtaGVhZGVyLWhvcml6b250YWwtbmF2aWdhdGlvbj5cbiAgICAgIDwvZGl2PlxuICAgICAgPCEtLSBJY29uIG1lbnVzIC0tPlxuICAgICAgPGRpdiBjbGFzcz1cInBhZ2UtaGVhZGVyLWljb24tbWVudXNcIiByb2xlPVwidG9vbGJhclwiPlxuICAgICAgICBAZm9yIChtZW51IG9mIGN1c3RvbU1lbnVzOyB0cmFjayBtZW51KSB7XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJtZW51XCI+PC9uZy1jb250YWluZXI+XG4gICAgICAgIH1cbiAgICAgICAgQGZvciAobWVudSBvZiBpY29uTWVudXM7IHRyYWNrIG1lbnUpIHtcbiAgICAgICAgICA8dXgtcGFnZS1oZWFkZXItaWNvbi1tZW51IFttZW51XT1cIm1lbnVcIj48L3V4LXBhZ2UtaGVhZGVyLWljb24tbWVudT5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIH1cblxuICA8IS0tIERpc3BsYXkgVGhpcyBTZWN0aW9uIE9wdGltaXplZCBmb3IgQ29uZGVuc2VkIE1vZGUgLS0+XG4gIEBpZiAoY29uZGVuc2VkKSB7XG4gICAgPGRpdiBjbGFzcz1cInBhZ2UtaGVhZGVyLWNvbmRlbnNlZC1jb250ZW50XCI+XG4gICAgICA8ZGl2IGNsYXNzPVwicGFnZS1oZWFkZXItYnJlYWRjcnVtYnNcIiByb2xlPVwibmF2aWdhdGlvblwiPlxuICAgICAgICA8dXgtYnJlYWRjcnVtYnMgW2NydW1ic109XCJjcnVtYnNcIj48L3V4LWJyZWFkY3J1bWJzPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicGFnZS1oZWFkZXItbmF2aWdhdGlvblwiIFtuZ0NsYXNzXT1cImFsaWdubWVudFwiIHJvbGU9XCJuYXZpZ2F0aW9uXCIgYXJpYS1sYWJlbD1cIlByaW1hcnkgTmF2aWdhdGlvblwiPlxuICAgICAgICA8IS0tIFRoZSBUb3AgTmF2aWdhdGlvbiBPcHRpb25zIC0tPlxuICAgICAgICA8dXgtcGFnZS1oZWFkZXItaG9yaXpvbnRhbC1uYXZpZ2F0aW9uPjwvdXgtcGFnZS1oZWFkZXItaG9yaXpvbnRhbC1uYXZpZ2F0aW9uPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwicGFnZS1oZWFkZXItaWNvbi1tZW51c1wiIHJvbGU9XCJ0b29sYmFyXCI+XG4gICAgICAgIEBmb3IgKG1lbnUgb2YgY3VzdG9tTWVudXM7IHRyYWNrIG1lbnUpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cIm1lbnVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgfVxuICAgICAgICBAZm9yIChtZW51IG9mIGljb25NZW51czsgdHJhY2sgbWVudSkge1xuICAgICAgICAgIDx1eC1wYWdlLWhlYWRlci1pY29uLW1lbnUgW21lbnVdPVwibWVudVwiPjwvdXgtcGFnZS1oZWFkZXItaWNvbi1tZW51PlxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgfVxuXG48L2Rpdj5cblxuPCEtLSBTZWNvbmRhcnkgSGVhZGVyIFNlY3Rpb24gLS0+XG5AaWYgKHNlY29uZGFyeU5hdmlnYXRpb24gJiYgKChzZWxlY3RlZFJvb3QkIHwgYXN5bmMpICE9PSAoc2VsZWN0ZWQkIHwgYXN5bmMpKSkge1xuICA8ZGl2IGNsYXNzPVwidXgtcGFnZS1oZWFkZXItc2Vjb25kYXJ5XCI+XG4gICAgPCEtLSBTZWNvbmRhcnkgTmF2aWdhdGlvbiBMZWFkaW5nIENvbnRlbnQgLS0+XG4gICAgQGlmIChzZWNvbmRhcnlOYXZpZ2F0aW9uTGVhZGluZ0NvbnRlbnRUZW1wbGF0ZSB8fCBzZWNvbmRhcnlOYXZpZ2F0aW9uVHJhaWxpbmdDb250ZW50VGVtcGxhdGUpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJwYWdlLWhlYWRlci1zZWNvbmRhcnktbGVhZGluZy1jb250ZW50XCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2Vjb25kYXJ5TmF2aWdhdGlvbkxlYWRpbmdDb250ZW50VGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICA8IS0tIFNlY29uZGFyeSBOYXZpZ2F0aW9uIChjaGlsZHJlbiBvZiB0b3AgbGV2ZWwgaXRlbXMpIC0tPlxuICAgIDxkaXYgW25nQ2xhc3NdPVwiWydwYWdlLWhlYWRlci1uYXZpZ2F0aW9uJywgc2Vjb25kYXJ5TmF2aWdhdGlvbkFsaWdubWVudF1cIiByb2xlPVwibmF2aWdhdGlvblwiPlxuICAgICAgQGlmICgoc2VsZWN0ZWRSb290JCB8IGFzeW5jKT8uY2hpbGRyZW47IGFzIGNoaWxkcmVuKSB7XG4gICAgICAgIDx1eC10YWJzZXQgW21hbnVhbF09XCJ0cnVlXCI+XG4gICAgICAgICAgQGZvciAoY2hpbGQgb2YgY2hpbGRyZW47IHRyYWNrIGNoaWxkKSB7XG4gICAgICAgICAgICA8dXgtdGFiXG4gICAgICAgICAgICAgIFtoZWFkaW5nXT1cImNoaWxkLnRpdGxlXCJcbiAgICAgICAgICAgICAgW3JvdXRlXT1cImNoaWxkLnJvdXRlckxpbmtcIlxuICAgICAgICAgICAgICBbaWRdPVwiY2hpbGQuaWRcIlxuICAgICAgICAgICAgICBbcm91dGVyTGlua0V4dHJhc109XCJjaGlsZC5yb3V0ZXJFeHRyYXNcIlxuICAgICAgICAgICAgICBbYWN0aXZlXT1cImNoaWxkID09PSAoc2VsZWN0ZWQkIHwgYXN5bmMpXCJcbiAgICAgICAgICAgICAgKGFjdGl2YXRlZCk9XCJzZWxlY3QoY2hpbGQsIGZhbHNlKVwiXG4gICAgICAgICAgICAgIFt1eFBhZ2VIZWFkZXJOYXZpZ2F0aW9uU2Vjb25kYXJ5SXRlbV09XCJjaGlsZFwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJjaGlsZC5kaXNhYmxlZFwiPlxuICAgICAgICAgICAgPC91eC10YWI+XG4gICAgICAgICAgfVxuICAgICAgICA8L3V4LXRhYnNldD5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgICA8IS0tIFNlY29uZGFyeSBOYXZpZ2F0aW9uIFRyaWFsaW5nIENvbnRlbnQgLS0+XG4gICAgQGlmIChzZWNvbmRhcnlOYXZpZ2F0aW9uVHJhaWxpbmdDb250ZW50VGVtcGxhdGUpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJwYWdlLWhlYWRlci1zZWNvbmRhcnktdHJhaWxpbmctY29udGVudFwiPlxuICAgICAgICA8bmctY29udGFpbmVyIFtuZ1RlbXBsYXRlT3V0bGV0XT1cInNlY29uZGFyeU5hdmlnYXRpb25UcmFpbGluZ0NvbnRlbnRUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9kaXY+XG4gICAgfVxuICA8L2Rpdj5cbn1cbiJdfQ==