@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
463 lines • 70 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Component, ElementRef, EventEmitter, HostListener, Inject, Injector, IterableDiffers, Optional, Output, Renderer2, ViewChild } from '@angular/core';
import { Yield } from '@microsoft/windows-admin-center-sdk/core/base/decorators/yield.decorator';
import { KeyCode } from '@microsoft/windows-admin-center-sdk/core/data/accessibility-manager';
import { Logging } from '@microsoft/windows-admin-center-sdk/core/diagnostics/logging';
import { take } from 'rxjs/operators';
import { SME_LAYOUT_PROVIDER } from '../../../common/layout';
import { DropdownComponent } from '../../../dropdown/dropdown.component';
import { ActionContainerComponent } from '../action-container.component';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "../../../dropdown/dropdown.component";
import * as i3 from "../../../tooltip/tooltip.directive";
import * as i4 from "../action-menu/action-menu.component";
import * as i5 from "../../items/dynamic-action-item.component";
const _c0 = ["actionBarElement"];
const _c1 = ["dropDownButton"];
const _c2 = ["dropDown"];
function ActionBarComponent_sme_dynamic_action_item_2_Template(rf, ctx) { if (rf & 1) {
const _r6 = i0.ɵɵgetCurrentView();
i0.ɵɵelementStart(0, "sme-dynamic-action-item", 10);
i0.ɵɵlistener("itemChanged", function ActionBarComponent_sme_dynamic_action_item_2_Template_sme_dynamic_action_item_itemChanged_0_listener() { i0.ɵɵrestoreView(_r6); const ctx_r5 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r5.onActionItemChanged()); });
i0.ɵɵelementEnd();
} if (rf & 2) {
const item_r4 = ctx.$implicit;
const ctx_r1 = i0.ɵɵnextContext();
i0.ɵɵclassProp("sme-action-bar-item-no-padding-v", ctx_r1.heightOverflow);
i0.ɵɵproperty("item", item_r4);
} }
const _c3 = ["*"];
/**
*
* @smeDoc {@label Actions @id sme-actions}
*
* @overview
* @file {@filepath ./examples/overview.md}
*
* @example {@label Defined actions from component @id defined-actions-from-component}
* @file {@filename component.html @filepath ./examples/defined-actions-from-component.component.html}
* @file {@filename component.ts @filepath ./examples/actions-example.component.ts}
*
* @example {@label Defined actions from html @id defined-actions-from-html}
* @file {@filename component.html @filepath ./examples/defined-actions-from-html.component.html}
* @file {@filename component.ts @filepath ./examples/actions-example.component.ts}
*
* @example {@label Defined actions from both @id defined-actions-from-both}
* @file {@filename component.html @filepath ./examples/defined-actions-from-both.component.html}
* @file {@filename component.ts @filepath ./examples/actions-example.component.ts}
*
* @example {@label All buttons disabled @id all-buttons-disabled}
* @file {@filename component.html @filepath ./examples/all-buttons-disabled.component.html}
* @file {@filename component.ts @filepath ./examples/actions-example.component.ts}
*
* @example {@label Model driven action bar @id model-driven}
* @file {@filename component.html @filepath ./examples/model-driven.component.html}
* @file {@filename component.ts @filepath ./examples/actions-example.component.ts}
*
* @example {@label Container embedded action bar @id container-embedded-action-bar}
* @file {@filename component.html @filepath ./examples/container-embedded-action-bar.component.html}
* @file {@filename component.ts @filepath ./examples/actions-example.component.ts}
*/
export class ActionBarComponent extends ActionContainerComponent {
/**
* Constructor for the ActionBarComponent.
*/
constructor(iterableDiffers, renderer, hostElement, layout, injector) {
super(iterableDiffers, injector);
this.renderer = renderer;
this.hostElement = hostElement;
/**
* List of ActionItem objects that we want to perform.
*/
this.displayedActions = [];
/**
* List of ActionItem objects that are collapsed into dropdown.
*/
this.trayActions = [];
/**
* Localized set of strings.
*/
this.strings = MsftSme.getStrings();
this.isCompact = false;
this.hovered = false;
this.focused = false;
this.shouldShow = true;
this.isVisible = true;
/**
* Event fired when list of ActionItems changes.
*/
this.actionsUpdated = new EventEmitter();
renderer.addClass(hostElement.nativeElement, 'sme-position-stretch-h');
renderer.addClass(hostElement.nativeElement, 'sme-layout-action-bar');
renderer.addClass(hostElement.nativeElement, 'sme-arrange-stack-h');
renderer.addClass(hostElement.nativeElement, 'sme-arrange-ws-nowrap');
renderer.addClass(hostElement.nativeElement, 'sme-arrange-overflow-show');
renderer.setStyle(this.hostElement.nativeElement, 'opacity', 0);
this.moreActionsDisplay = this.strings.MsftSmeShell.Angular.Common.more;
this.actionsAriaLabel = this.strings.MsftSmeShell.Angular.Common.actions;
if (layout) {
this.layoutSubscription = layout.layoutChanged.subscribe(() => this.onLayoutChanged());
}
}
/**
* Flag that when set will display minimal UI for the action bar.
*/
get compact() {
return this.isCompact;
}
/**
* Attribute that sets vertical or horizontal orientation where vertical displays action bar from top to bottom of page
* and horizontal displays action bar from left to right.
*/
get orientation() {
return 'vertical';
}
get isAttached() {
return !MsftSme.isNullOrUndefined(this.attachedTo);
}
/**
* Filters out ActionItem objects to be hidden.
* @param items ActionItem objects to check.
* @returns List of unhidden ActionItem objects.
*/
hiddenFilter(items) {
return items.filter(item => !item.hidden);
}
/**
* Callback triggered after view initializes.
*/
ngAfterViewInit() {
setTimeout(() => {
this.updateActionBar();
});
}
/**
* Callback triggered after component is destroyed.
*/
ngOnDestroy() {
super.ngOnDestroy();
this.layoutSubscription?.unsubscribe();
}
/**
* On layout changed event handler, occurs every time the layout has been changed.
*/
onLayoutChanged() {
this.updateActionBar();
}
/**
* Host listeners for focus events.
*/
onFocusEvent(event) {
// on focus in/out change focused state
this.focused = event.type === 'focusin' || (this.focused && event.type !== 'focusout');
this.updateHeight();
}
/**
* Host listeners for keyboard events.
*/
onToggleKeydown(event) {
// accessibility, take focus to the more button after a selection in dropdown elements.
switch (event.keyCode) {
case KeyCode.Enter: {
if (this.dropDown) {
if (this.moreButtonElement && this.dropDown.isOpen && this.dropDown.contentElement) {
this.moreButtonElement.focus();
}
else {
this.dropDown.onToggled.pipe(take(1)).subscribe(open => {
if (open) {
// blur/focus to refresh focus - this will make the tooltip disappear
// while menu is open (b/c tooltip will block view)
this.dropDownButtonElement.nativeElement.blur();
this.dropDownButtonElement.nativeElement.focus();
this.moreButtonElement = document.activeElement;
}
});
}
}
break;
}
}
}
/**
* Host listeners for mouse events.
*/
onMouseEvent(event) {
// on mouse enter/leave change hovered state
this.hovered = event.type === 'mouseenter' || (this.hovered && event.type !== 'mouseleave');
this.updateHeight();
}
/**
* Host listener for page resize event.
*/
onResize() {
this.updateActionBar();
}
/**
* Callback triggered after child ActionItem changes.
*/
onActionItemChanged() {
setTimeout(() => {
this.updateActionBar();
});
}
updateHeight() {
if (this.isAttached) {
if (this.isVisible && (this.shouldShow || this.focused || this.hovered)) {
this.renderer.removeStyle(this.hostElement.nativeElement, 'overflow');
this.renderer.removeClass(this.hostElement.nativeElement, 'sme-animation-fade-out-xs');
this.renderer.addClass(this.hostElement.nativeElement, 'sme-animation-fade-in-xs');
}
else {
this.renderer.setStyle(this.hostElement.nativeElement, 'opacity', 0);
this.renderer.setStyle(this.hostElement.nativeElement, 'overflow', 'hidden');
this.renderer.addClass(this.hostElement.nativeElement, 'sme-animation-fade-out-xs');
}
}
}
/**
* Method to set visibility for ActionBarComponent.
* @param isVisible True for visible, false for not.
*/
setVisibility(isVisible) {
this.isVisible = isVisible;
this.updateHeight();
}
/**
* Method to set visibility for ActionBarComponent.
* @param shouldShow True for showing, false for not.
*/
showHide(shouldShow) {
this.shouldShow = shouldShow;
this.updateHeight();
}
/**
* Repositions given HTMLElement to be relative to its sibling element.
* @param element Element to reposition.
* @param compact Boolean flag to set whether or not ActionBarComponent should be compact.
*/
repositionRelativeTo(element, compact) {
if (MsftSme.isNullOrUndefined(element.offsetParent)) {
return;
}
let isSibling = false;
const siblings = element.parentElement.children;
for (let i = 0; i < siblings.length; i++) {
const sibling = siblings.item(i);
if (sibling === this.hostElement.nativeElement) {
isSibling = true;
break;
}
}
if (!isSibling) {
Logging.logError('ActionBar.repositionRelativeTo', 'ActionBar can only be positioned relative to a sibling element.');
return;
}
const wasAttached = this.isAttached;
this.attachedTo = element;
if (!wasAttached) {
this.showHide(false);
}
// when positioning on an element, use compact settings if desired
this.isCompact = compact;
// change classes to account for different positioning mechanism
this.renderer.removeStyle(this.hostElement.nativeElement, 'position');
this.renderer.removeClass(this.hostElement.nativeElement, 'sme-position-stretch-h');
this.renderer.addClass(this.hostElement.nativeElement, 'sme-layout-absolute');
this.renderer.addClass(this.hostElement.nativeElement, 'sme-background-color-base');
// Calculate new position
const style = window.getComputedStyle(element);
const margin = {
top: parseInt(style.marginTop, 10),
bottom: parseInt(style.marginBottom, 10),
left: parseInt(style.marginLeft, 10),
right: parseInt(style.marginRight, 10)
};
const border = {
top: parseInt(style.borderTop, 10),
bottom: parseInt(style.borderBottom, 10),
left: parseInt(style.borderLeft, 10),
right: parseInt(style.borderRight, 10)
};
const availableWidth = element.clientWidth - border.left - border.right - margin.left - margin.right;
const availableHeight = element.clientHeight - border.bottom - margin.bottom;
const width = Math.min(Math.max(availableWidth / 2, 300), availableWidth);
const right = element.offsetParent.clientWidth - (element.offsetLeft + element.clientWidth);
const top = element.offsetTop + border.top + margin.top;
this.renderer.setStyle(this.hostElement.nativeElement, 'right', `${right}px`);
this.renderer.setStyle(this.hostElement.nativeElement, 'top', `${top}px`);
this.renderer.setStyle(this.hostElement.nativeElement, 'width', `unset`);
this.renderer.setStyle(this.hostElement.nativeElement, 'max-width', `${width}px`);
this.renderer.setStyle(this.hostElement.nativeElement, 'max-height', `${availableHeight}px`);
this.renderer.setStyle(this.hostElement.nativeElement, 'justify-content', `flex-end`);
// if the height of the bar is currently greater than the available height of the target,
// then make sure displayed items are adjusted accordingly
this.heightOverflow = parseInt(style.height, 10) > availableHeight;
setTimeout(() => {
this.updateActionBar();
});
}
/**
* Method to update how ActionBarComponent is displayed.
*/
updateActionBar() {
let currentFill = 0;
// Set up the following styles during the UI calculation to make sure the html element flickering won't exceed
// the action bar container.
// The following inline styles will be removed after the UI calculation is done.
const hostElement = this.hostElement.nativeElement;
this.renderer.setStyle(hostElement, 'overflow', `hidden`);
if (!this.isAttached) {
this.renderer.setStyle(hostElement, 'position', `relative`);
this.renderer.removeStyle(this.hostElement.nativeElement, 'opacity');
}
this.displayedActions = [];
this.trayActions = [];
const style = getComputedStyle(hostElement);
const padding = parseInt(style.getPropertyValue('padding-left'), 10) + parseInt(style.getPropertyValue('padding-right'), 10);
const containerWidth = (this.isAttached ? parseInt(style.maxWidth, 10) : hostElement.offsetWidth) - padding;
// Firstly, we need to calculate the total width of all buttons without "more" button.
let buttonsTotalWidth = 0;
for (let i = 0; i < this.actions.length; ++i) {
const action = this.actions[i];
// assume hidden actions have a 0 width. When they are un-hidden, there width will change and trigger another update.
const actionWidth = action.hidden ? 0 : action.width || 0;
buttonsTotalWidth += actionWidth;
}
if (buttonsTotalWidth <= containerWidth) {
for (let index = 0; index < this.actions.length; ++index) {
this.displayedActions.push(this.actions[index]);
}
}
else {
// If the buttons total width exceeds the container width, then we calculate which button should be
// displayed and which button should be put into "more" drop-down.
// Note: the available container width should be the container width - "more" button's width.
const visibleButtonContainerWidth = containerWidth - this.dropDownButtonElement.nativeElement.offsetWidth;
for (let index = 0; index < this.actions.length; ++index) {
const action = this.actions[index];
// assume hidden actions have a 0 width. When they are un-hidden, there width will change and trigger another update.
const actionWidth = action.hidden ? 0 : action.width || 0;
if (currentFill + actionWidth > visibleButtonContainerWidth) {
this.trayActions.push(action);
}
else {
this.displayedActions.push(action);
}
currentFill += actionWidth;
}
}
if (this.displayedActions.length === 0) {
this.moreActionsDisplay = this.strings.MsftSmeShell.Angular.Common.actions;
}
else {
this.moreActionsDisplay = this.strings.MsftSmeShell.Angular.Common.more;
}
// If any action bar width is NaN, that means not all the action-buttons finished rendering on the UI.
// Thus "currentFill" is still NaN. Otherwise, we consider all the action-buttons finish rendering.
// Then it's time to remove the temporary inline styles.
if (!!currentFill) {
if (!this.isAttached && (this.shouldShow || this.hovered || this.focused)) {
this.renderer.removeStyle(hostElement, 'overflow');
}
this.renderer.removeStyle(hostElement, 'position');
}
// some action item states depend on what container they reside in.
// TrayActions will be updated because they were moved into the actionMenu,
// however displayed actions should be reset as they may have moved.
if (this.displayedActions && this.displayedActions.length > 0) {
this.displayedActions.forEach(action => action.setActionState(this.target, this));
}
this.actionsUpdated.emit();
}
}
/** @nocollapse */ ActionBarComponent.ɵfac = function ActionBarComponent_Factory(t) { return new (t || ActionBarComponent)(i0.ɵɵdirectiveInject(i0.IterableDiffers), i0.ɵɵdirectiveInject(i0.Renderer2), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(SME_LAYOUT_PROVIDER, 8), i0.ɵɵdirectiveInject(i0.Injector)); };
/** @nocollapse */ ActionBarComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: ActionBarComponent, selectors: [["sme-action-bar"]], viewQuery: function ActionBarComponent_Query(rf, ctx) { if (rf & 1) {
i0.ɵɵviewQuery(_c0, 5);
i0.ɵɵviewQuery(_c1, 5);
i0.ɵɵviewQuery(_c2, 5);
} if (rf & 2) {
let _t;
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.element = _t.first);
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dropDownButtonElement = _t.first);
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dropDown = _t.first);
} }, hostBindings: function ActionBarComponent_HostBindings(rf, ctx) { if (rf & 1) {
i0.ɵɵlistener("focusin", function ActionBarComponent_focusin_HostBindingHandler($event) { return ctx.onFocusEvent($event); })("focusout", function ActionBarComponent_focusout_HostBindingHandler($event) { return ctx.onFocusEvent($event); })("keydown", function ActionBarComponent_keydown_HostBindingHandler($event) { return ctx.onToggleKeydown($event); })("mouseenter", function ActionBarComponent_mouseenter_HostBindingHandler($event) { return ctx.onMouseEvent($event); })("mouseleave", function ActionBarComponent_mouseleave_HostBindingHandler($event) { return ctx.onMouseEvent($event); })("resize", function ActionBarComponent_resize_HostBindingHandler() { return ctx.onResize(); }, false, i0.ɵɵresolveWindow);
} }, outputs: { actionsUpdated: "actionsUpdated" }, features: [i0.ɵɵInheritDefinitionFeature], ngContentSelectors: _c3, decls: 12, vars: 16, consts: [["role", "menubar", 1, "sme-position-flex-none", "sme-arrange-stack-h"], ["actionBarElement", ""], ["class", "sme-arrange-stack-h sme-arrange-stack-centered sme-arrange-stack-inline", 3, "item", "sme-action-bar-item-no-padding-v", "itemChanged", 4, "ngFor", "ngForOf"], ["role", "presentation", 1, "sme-position-flex-none", 3, "title", "smeTooltipShow"], ["dropDown", ""], ["type", "button", "role", "menuitem", "aria-haspopup", "true", "data-uta-id", "action-bar-more", 1, "sme-button-trigger", "sme-layout-action-bar-item-height", "sme-button-auto-width", "sme-dropdown-toggle"], ["dropDownButton", ""], [1, "sme-icon", "sme-icon-more", 3, "title"], [1, "sme-screen-reader"], ["role", "menu", 1, "sme-dropdown-content", 3, "actions", "target", "targetChange", "error", "executed"], [1, "sme-arrange-stack-h", "sme-arrange-stack-centered", "sme-arrange-stack-inline", 3, "item", "itemChanged"]], template: function ActionBarComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵprojectionDef();
i0.ɵɵelementStart(0, "div", 0, 1);
i0.ɵɵtemplate(2, ActionBarComponent_sme_dynamic_action_item_2_Template, 1, 3, "sme-dynamic-action-item", 2);
i0.ɵɵelementStart(3, "sme-dropdown", 3, 4)(5, "button", 5, 6);
i0.ɵɵelement(7, "span", 7);
i0.ɵɵelementStart(8, "span", 8);
i0.ɵɵtext(9);
i0.ɵɵelementEnd()();
i0.ɵɵelementStart(10, "sme-action-menu", 9);
i0.ɵɵlistener("targetChange", function ActionBarComponent_Template_sme_action_menu_targetChange_10_listener($event) { return ctx.target = $event; })("error", function ActionBarComponent_Template_sme_action_menu_error_10_listener($event) { return ctx.error.emit($event); })("executed", function ActionBarComponent_Template_sme_action_menu_executed_10_listener($event) { return ctx.executed.emit($event); });
i0.ɵɵelementEnd()();
i0.ɵɵprojection(11);
i0.ɵɵelementEnd();
} if (rf & 2) {
const _r2 = i0.ɵɵreference(4);
i0.ɵɵattribute("aria-label", ctx.actionsAriaLabel);
i0.ɵɵadvance(2);
i0.ɵɵproperty("ngForOf", ctx.hiddenFilter(ctx.displayedActions));
i0.ɵɵadvance(1);
i0.ɵɵclassProp("sme-layout-hidden", !ctx.compact && ctx.trayActions.length === 0)("sme-layout-none", ctx.compact && ctx.trayActions.length === 0);
i0.ɵɵproperty("title", ctx.moreActionsDisplay)("smeTooltipShow", !_r2.isOpen);
i0.ɵɵadvance(2);
i0.ɵɵclassProp("sme-toggled", _r2.isOpen);
i0.ɵɵattribute("aria-label", ctx.moreActionsDisplay)("aria-expanded", _r2.isOpen);
i0.ɵɵadvance(2);
i0.ɵɵproperty("title", ctx.moreActionsDisplay);
i0.ɵɵadvance(2);
i0.ɵɵtextInterpolate(ctx.moreActionsDisplay);
i0.ɵɵadvance(1);
i0.ɵɵproperty("actions", ctx.trayActions)("target", ctx.target);
} }, dependencies: [i1.NgForOf, i2.DropdownComponent, i3.TooltipDirective, i4.ActionMenuComponent, i5.DynamicActionItemComponent], encapsulation: 2 });
__decorate([
Yield(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], ActionBarComponent.prototype, "onLayoutChanged", null);
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ActionBarComponent, [{
type: Component,
args: [{ selector: 'sme-action-bar', template: "<div role=\"menubar\" [attr.aria-label]=\"actionsAriaLabel\" class=\"sme-position-flex-none sme-arrange-stack-h\" #actionBarElement>\r\n <sme-dynamic-action-item *ngFor=\"let item of hiddenFilter(displayedActions)\" [item]=\"item\"\r\n (itemChanged)=\"onActionItemChanged()\"\r\n class=\"sme-arrange-stack-h sme-arrange-stack-centered sme-arrange-stack-inline\"\r\n [class.sme-action-bar-item-no-padding-v]=\"heightOverflow\"></sme-dynamic-action-item>\r\n\r\n <sme-dropdown #dropDown role=\"presentation\" class=\"sme-position-flex-none\"\r\n [class.sme-layout-hidden]=\"!compact && trayActions.length === 0\"\r\n [class.sme-layout-none]=\"compact && trayActions.length === 0\" [title]=\"moreActionsDisplay\" [smeTooltipShow]=\"!this.dropDown.isOpen\">\r\n <button #dropDownButton type=\"button\" [attr.aria-label]=\"moreActionsDisplay\" role=\"menuitem\"\r\n class=\"sme-button-trigger sme-layout-action-bar-item-height sme-button-auto-width sme-dropdown-toggle\"\r\n [class.sme-toggled]=\"dropDown.isOpen\" [attr.aria-expanded]=\"dropDown.isOpen\" aria-haspopup=\"true\"\r\n data-uta-id=\"action-bar-more\">\r\n <span class=\"sme-icon sme-icon-more\" [title]=\"moreActionsDisplay\"></span>\r\n <span class=\"sme-screen-reader\">{{ moreActionsDisplay }}</span>\r\n </button>\r\n <sme-action-menu [actions]=\"trayActions\" role=\"menu\" class=\"sme-dropdown-content\" [(target)]=\"target\"\r\n (error)=\"error.emit($event)\" (executed)=\"executed.emit($event)\"></sme-action-menu>\r\n </sme-dropdown>\r\n <ng-content></ng-content>\r\n</div>\r\n" }]
}], function () { return [{ type: i0.IterableDiffers }, { type: i0.Renderer2 }, { type: i0.ElementRef }, { type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [SME_LAYOUT_PROVIDER]
}] }, { type: i0.Injector }]; }, { actionsUpdated: [{
type: Output
}], element: [{
type: ViewChild,
args: ['actionBarElement']
}], dropDownButtonElement: [{
type: ViewChild,
args: ['dropDownButton']
}], dropDown: [{
type: ViewChild,
args: ['dropDown']
}], onLayoutChanged: [], onFocusEvent: [{
type: HostListener,
args: ['focusin', ['$event']]
}, {
type: HostListener,
args: ['focusout', ['$event']]
}], onToggleKeydown: [{
type: HostListener,
args: ['keydown', ['$event']]
}], onMouseEvent: [{
type: HostListener,
args: ['mouseenter', ['$event']]
}, {
type: HostListener,
args: ['mouseleave', ['$event']]
}], onResize: [{
type: HostListener,
args: ['window:resize']
}] }); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9uLWJhci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9hbmd1bGFyL3NyYy9jb250cm9scy9hY3Rpb25zL2NvbnRhaW5lcnMvYWN0aW9uLWJhci9hY3Rpb24tYmFyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL2FuZ3VsYXIvc3JjL2NvbnRyb2xzL2FjdGlvbnMvY29udGFpbmVycy9hY3Rpb24tYmFyL2FjdGlvbi1iYXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFSCxTQUFTLEVBRVQsVUFBVSxFQUNWLFlBQVksRUFDWixZQUFZLEVBQ1osTUFBTSxFQUNOLFFBQVEsRUFDUixlQUFlLEVBRWYsUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsU0FBUyxFQUNaLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSwwRUFBMEUsQ0FBQztBQUNqRyxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0scUVBQXFFLENBQUM7QUFDOUYsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDhEQUE4RCxDQUFDO0FBRXZGLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUV0QyxPQUFPLEVBQVUsbUJBQW1CLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNyRSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQ0FBc0MsQ0FBQztBQUd6RSxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7Ozs7Ozs7Ozs7O0lDekJ2RSxtREFHNEQ7SUFGMUQsZ05BQWUsZUFBQSw0QkFBcUIsQ0FBQSxJQUFDO0lBRXFCLGlCQUEwQjs7OztJQUFwRix5RUFBeUQ7SUFIa0IsOEJBQWE7OztBRDJCNUY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztH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O1lBV3RDLFFBQVE7a0JBRFAsWUFBWTttQkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICAgIEFmdGVyVmlld0luaXQsXHJcbiAgICBDb21wb25lbnQsXHJcbiAgICBEb0NoZWNrLFxyXG4gICAgRWxlbWVudFJlZixcclxuICAgIEV2ZW50RW1pdHRlcixcclxuICAgIEhvc3RMaXN0ZW5lcixcclxuICAgIEluamVjdCxcclxuICAgIEluamVjdG9yLFxyXG4gICAgSXRlcmFibGVEaWZmZXJzLFxyXG4gICAgT25EZXN0cm95LFxyXG4gICAgT3B0aW9uYWwsXHJcbiAgICBPdXRwdXQsXHJcbiAgICBSZW5kZXJlcjIsXHJcbiAgICBWaWV3Q2hpbGRcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgWWllbGQgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2Jhc2UvZGVjb3JhdG9ycy95aWVsZC5kZWNvcmF0b3InO1xyXG5pbXBvcnQgeyBLZXlDb2RlIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9kYXRhL2FjY2Vzc2liaWxpdHktbWFuYWdlcic7XHJcbmltcG9ydCB7IExvZ2dpbmcgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RpYWdub3N0aWNzL2xvZ2dpbmcnO1xyXG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgdGFrZSB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcclxuaW1wb3J0IHsgU3RyaW5ncyB9IGZyb20gJy4uLy4uLy4uLy4uL2dlbmVyYXRlZC9zdHJpbmdzJztcclxuaW1wb3J0IHsgTGF5b3V0LCBTTUVfTEFZT1VUX1BST1ZJREVSIH0gZnJvbSAnLi4vLi4vLi4vY29tbW9uL2xheW91dCc7XHJcbmltcG9ydCB7IERyb3Bkb3duQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vLi4vZHJvcGRvd24vZHJvcGRvd24uY29tcG9uZW50JztcclxuaW1wb3J0IHsgQWN0aW9uSXRlbSB9IGZyb20gJy4uLy4uL2l0ZW1zL2FjdGlvbi1pdGVtLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEFjdGlvbkNvbnRhaW5lck9yaWVudGF0aW9uIH0gZnJvbSAnLi4vYWN0aW9uLWNvbnRhaW5lcic7XHJcbmltcG9ydCB7IEFjdGlvbkNvbnRhaW5lckNvbXBvbmVudCB9IGZyb20gJy4uL2FjdGlvbi1jb250YWluZXIuY29tcG9uZW50JztcclxuXHJcbi8qKlxyXG4gKlxyXG4gKiBAc21lRG9jIHtAbGFiZWwgQWN0aW9ucyBAaWQgc21lLWFjdGlvbnN9XHJcbiAqXHJcbiAqIEBvdmVydmlld1xyXG4gKiBAZmlsZSB7QGZpbGVwYXRoIC4vZXhhbXBsZXMvb3ZlcnZpZXcubWR9XHJcbiAqXHJcbiAqIEBleGFtcGxlIHtAbGFiZWwgRGVmaW5lZCBhY3Rpb25zIGZyb20gY29tcG9uZW50IEBpZCBkZWZpbmVkLWFjdGlvbnMtZnJvbS1jb21wb25lbnR9XHJcbiAqIEBmaWxlIHtAZmlsZW5hbWUgY29tcG9uZW50Lmh0bWwgQGZpbGVwYXRoIC4vZXhhbXBsZXMvZGVmaW5lZC1hY3Rpb25zLWZyb20tY29tcG9uZW50LmNvbXBvbmVudC5odG1sfVxyXG4gKiBAZmlsZSB7QGZpbGVuYW1lIGNvbXBvbmVudC50cyBAZmlsZXBhdGggLi9leGFtcGxlcy9hY3Rpb25zLWV4YW1wbGUuY29tcG9uZW50LnRzfVxyXG4gKlxyXG4gKiBAZXhhbXBsZSB7QGxhYmVsIERlZmluZWQgYWN0aW9ucyBmcm9tIGh0bWwgQGlkIGRlZmluZWQtYWN0aW9ucy1mcm9tLWh0bWx9XHJcbiAqIEBmaWxlIHtAZmlsZW5hbWUgY29tcG9uZW50Lmh0bWwgQGZpbGVwYXRoIC4vZXhhbXBsZXMvZGVmaW5lZC1hY3Rpb25zLWZyb20taHRtbC5jb21wb25lbnQuaHRtbH1cclxuICogQGZpbGUge0BmaWxlbmFtZSBjb21wb25lbnQudHMgQGZpbGVwYXRoIC4vZXhhbXBsZXMvYWN0aW9ucy1leGFtcGxlLmNvbXBvbmVudC50c31cclxuICpcclxuICogQGV4YW1wbGUge0BsYWJlbCBEZWZpbmVkIGFjdGlvbnMgZnJvbSBib3RoIEBpZCBkZWZpbmVkLWFjdGlvbnMtZnJvbS1ib3RofVxyXG4gKiBAZmlsZSB7QGZpbGVuYW1lIGNvbXBvbmVudC5odG1sIEBmaWxlcGF0aCAuL2V4YW1wbGVzL2RlZmluZWQtYWN0aW9ucy1mcm9tLWJvdGguY29tcG9uZW50Lmh0bWx9XHJcbiAqIEBmaWxlIHtAZmlsZW5hbWUgY29tcG9uZW50LnRzIEBmaWxlcGF0aCAuL2V4YW1wbGVzL2FjdGlvbnMtZXhhbXBsZS5jb21wb25lbnQudHN9XHJcbiAqXHJcbiAqIEBleGFtcGxlIHtAbGFiZWwgQWxsIGJ1dHRvbnMgZGlzYWJsZWQgQGlkIGFsbC1idXR0b25zLWRpc2FibGVkfVxyXG4gKiBAZmlsZSB7QGZpbGVuYW1lIGNvbXBvbmVudC5odG1sIEBmaWxlcGF0aCAuL2V4YW1wbGVzL2FsbC1idXR0b25zLWRpc2FibGVkLmNvbXBvbmVudC5odG1sfVxyXG4gKiBAZmlsZSB7QGZpbGVuYW1lIGNvbXBvbmVudC50cyBAZmlsZXBhdGggLi9leGFtcGxlcy9hY3Rpb25zLWV4YW1wbGUuY29tcG9uZW50LnRzfVxyXG4gKlxyXG4gKiBAZXhhbXBsZSB7QGxhYmVsIE1vZGVsIGRyaXZlbiBhY3Rpb24gYmFyIEBpZCBtb2RlbC1kcml2ZW59XHJcbiAqIEBmaWxlIHtAZmlsZW5hbWUgY29tcG9uZW50Lmh0bWwgQGZpbGVwYXRoIC4vZXhhbXBsZXMvbW9kZWwtZHJpdmVuLmNvbXBvbmVudC5odG1sfVxyXG4gKiBAZmlsZSB7QGZpbGVuYW1lIGNvbXBvbmVudC50cyBAZmlsZXBhdGggLi9leGFtcGxlcy9hY3Rpb25zLWV4YW1wbGUuY29tcG9uZW50LnRzfVxyXG4gKlxyXG4gKiBAZXhhbXBsZSB7QGxhYmVsIENvbnRhaW5lciBlbWJlZGRlZCBhY3Rpb24gYmFyIEBpZCBjb250YWluZXItZW1iZWRkZWQtYWN0aW9uLWJhcn1cclxuICogQGZpbGUge0BmaWxlbmFtZSBjb21wb25lbnQuaHRtbCBAZmlsZXBhdGggLi9leGFtcGxlcy9jb250YWluZXItZW1iZWRkZWQtYWN0aW9uLWJhci5jb21wb25lbnQuaHRtbH1cclxuICogQGZpbGUge0BmaWxlbmFtZSBjb21wb25lbnQudHMgQGZpbGVwYXRoIC4vZXhhbXBsZXMvYWN0aW9ucy1leGFtcGxlLmNvbXBvbmVudC50c31cclxuICovXHJcblxyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnc21lLWFjdGlvbi1iYXInLFxyXG4gICAgdGVtcGxhdGVVcmw6ICcuL2FjdGlvbi1iYXIuY29tcG9uZW50Lmh0bWwnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBBY3Rpb25CYXJDb21wb25lbnQgZXh0ZW5kcyBBY3Rpb25Db250YWluZXJDb21wb25lbnQgaW1wbGVtZW50cyBEb0NoZWNrLCBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xyXG4gICAgcHJvdGVjdGVkIGxvZ1NvdXJjZU5hbWU6IHN0cmluZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIEZsYWcgdGhhdCB3aGVuIHNldCB3aWxsIGRpc3BsYXkgbWluaW1hbCBVSSBmb3IgdGhlIGFjdGlvbiBiYXIuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgY29tcGFjdCgpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc0NvbXBhY3Q7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBdHRyaWJ1dGUgdGhhdCBzZXRzIHZlcnRpY2FsIG9yIGhvcml6b250YWwgb3JpZW50YXRpb24gd2hlcmUgdmVydGljYWwgZGlzcGxheXMgYWN0aW9uIGJhciBmcm9tIHRvcCB0byBib3R0b20gb2YgcGFnZVxyXG4gICAgICogYW5kIGhvcml6b250YWwgZGlzcGxheXMgYWN0aW9uIGJhciBmcm9tIGxlZnQgdG8gcmlnaHQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgb3JpZW50YXRpb24oKTogQWN0aW9uQ29udGFpbmVyT3JpZW50YXRpb24ge1xyXG4gICAgICAgIHJldHVybiAndmVydGljYWwnO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTGlzdCBvZiBBY3Rpb25JdGVtIG9iamVjdHMgdGhhdCB3ZSB3YW50IHRvIHBlcmZvcm0uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkaXNwbGF5ZWRBY3Rpb25zOiBBY3Rpb25JdGVtW10gPSBbXTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIExpc3Qgb2YgQWN0aW9uSXRlbSBvYmplY3RzIHRoYXQgYXJlIGNvbGxhcHNlZCBpbnRvIGRyb3Bkb3duLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdHJheUFjdGlvbnM6IEFjdGlvbkl0ZW1bXSA9IFtdO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGV4dCBkaXNwbGF5ZWQgZm9yIHRyYXkgZHJvcGRvd24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBtb3JlQWN0aW9uc0Rpc3BsYXk6IHN0cmluZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIExhYmVsIG9uIGFjdGlvbiBtZW51IGZvciBhY2Nlc3NpYmlsaXR5LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgYWN0aW9uc0FyaWFMYWJlbDogc3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRmxhZyB0byBtYWtlIHN1cmUgaWYgdGhlIGhlaWdodCBvZiB0aGUgYmFyIGlzIGN1cnJlbnRseSBncmVhdGVyIHRoYW4gdGhlIGF2YWlsYWJsZSBoZWlnaHQgb2YgdGhlIHRhcmdldCxcclxuICAgICAqIHRoZW4gdGhlIGl0ZW1zIGFyZSBhZGp1c3RlZCBhY2NvcmRpbmdseS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGhlaWdodE92ZXJmbG93OiBib29sZWFuO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQnV0dG9uIGVsZW1lbnQgZm9yIHRyYXkgZHJvcGRvd24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBtb3JlQnV0dG9uRWxlbWVudDogSFRNTEVsZW1lbnQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2NhbGl6ZWQgc2V0IG9mIHN0cmluZ3MuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdHJpbmdzID0gTXNmdFNtZS5nZXRTdHJpbmdzPFN0cmluZ3M+KCk7XHJcbiAgICBwcml2YXRlIGlzQ29tcGFjdCA9IGZhbHNlO1xyXG4gICAgcHJpdmF0ZSBob3ZlcmVkID0gZmFsc2U7XHJcbiAgICBwcml2YXRlIGZvY3VzZWQgPSBmYWxzZTtcclxuICAgIHByaXZhdGUgYXR0YWNoZWRUbzogSFRNTEVsZW1lbnQ7XHJcbiAgICBwcml2YXRlIHNob3VsZFNob3cgPSB0cnVlO1xyXG4gICAgcHJpdmF0ZSBpc1Zpc2libGUgPSB0cnVlO1xyXG4gICAgcHJpdmF0ZSBsYXlvdXRTdWJzY3JpcHRpb246IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEV2ZW50IGZpcmVkIHdoZW4gbGlzdCBvZiBBY3Rpb25JdGVtcyBjaGFuZ2VzLlxyXG4gICAgICovXHJcbiAgICBAT3V0cHV0KClcclxuICAgIHB1YmxpYyBhY3Rpb25zVXBkYXRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG5cclxuICAgIHByaXZhdGUgZ2V0IGlzQXR0YWNoZWQoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuICFNc2Z0U21lLmlzTnVsbE9yVW5kZWZpbmVkKHRoaXMuYXR0YWNoZWRUbyk7XHJcbiAgICB9XHJcblxyXG4gICAgQFZpZXdDaGlsZCgnYWN0aW9uQmFyRWxlbWVudCcpIHByaXZhdGUgZWxlbWVudDogRWxlbWVudFJlZjtcclxuICAgIEBWaWV3Q2hpbGQoJ2Ryb3BEb3duQnV0dG9uJykgcHJpdmF0ZSBkcm9wRG93bkJ1dHRvbkVsZW1lbnQ6IEVsZW1lbnRSZWY7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEcm9wZG93bkNvbXBvbmVudCBlbGVtZW50IGZvciBhY3Rpb24gdHJheS5cclxuICAgICAqL1xyXG4gICAgQFZpZXdDaGlsZCgnZHJvcERvd24nKSBwdWJsaWMgZHJvcERvd246IERyb3Bkb3duQ29tcG9uZW50O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29uc3RydWN0b3IgZm9yIHRoZSBBY3Rpb25CYXJDb21wb25lbnQuXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGl0ZXJhYmxlRGlmZmVyczogSXRlcmFibGVEaWZmZXJzLCBwdWJsaWMgcmVuZGVyZXI6IFJlbmRlcmVyMiwgcHVibGljIGhvc3RFbGVtZW50OiBFbGVtZW50UmVmLFxyXG4gICAgICAgIEBPcHRpb25hbCgpIEBJbmplY3QoU01FX0xBWU9VVF9QUk9WSURFUikgbGF5b3V0OiBMYXlvdXQsIGluamVjdG9yOiBJbmplY3Rvcikge1xyXG4gICAgICAgIHN1cGVyKGl0ZXJhYmxlRGlmZmVycywgaW5qZWN0b3IpO1xyXG4gICAgICAgIHJlbmRlcmVyLmFkZENsYXNzKGhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICdzbWUtcG9zaXRpb24tc3RyZXRjaC1oJyk7XHJcbiAgICAgICAgcmVuZGVyZXIuYWRkQ2xhc3MoaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudCwgJ3NtZS1sYXlvdXQtYWN0aW9uLWJhcicpO1xyXG4gICAgICAgIHJlbmRlcmVyLmFkZENsYXNzKGhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICdzbWUtYXJyYW5nZS1zdGFjay1oJyk7XHJcbiAgICAgICAgcmVuZGVyZXIuYWRkQ2xhc3MoaG9zdEVsZW1lbnQubmF0aXZlRWxlbWVudCwgJ3NtZS1hcnJhbmdlLXdzLW5vd3JhcCcpO1xyXG4gICAgICAgIHJlbmRlcmVyLmFkZENsYXNzKGhvc3RFbGVtZW50Lm5hdGl2ZUVsZW1lbnQsICdzbWUtYXJyYW5nZS1vdmVyZmxvdy1zaG93Jyk7XHJcbiAgICAgICAgcmVuZGVyZXIuc2V0U3R5bGUodGhpcy5ob3N0RWxlbWVudC5uYXRpdmVFbGVtZW50LCAnb3BhY2l0eScsIDApO1xyXG4gICAgICAgIHRoaXMu