UNPKG

@ux-aspects/ux-aspects

Version:

Open source user interface framework for building modern, responsive, mobile big data applications

144 lines 40 kB
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==