@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
517 lines • 77.6 kB
JavaScript
import { __decorate, __metadata } from "tslib";
import { Component, ContentChildren, EventEmitter, Inject, Injector, Input, Output, QueryList } from '@angular/core';
import { Debounce } from '@microsoft/windows-admin-center-sdk/core/base/decorators/debounce.decorators';
import { Yield } from '@microsoft/windows-admin-center-sdk/core/base/decorators/yield.decorator';
import { LogLevel } from '@microsoft/windows-admin-center-sdk/core/diagnostics/log-level';
import { Logging } from '@microsoft/windows-admin-center-sdk/core/diagnostics/logging';
import { CoreBaseComponent } from '../common/base.component';
import { SME_LAYOUT_PROVIDER } from '../common/layout';
import { SmeResponsiveWindowBreakpoints } from '../common/sme-responsive-window-manager.component';
import { LayoutDrivenType, LayoutItemConfigMode, LayoutItemConfigPropertyWidthType } from './layout-config';
import { LayoutDefinitionComponent } from './layout-definition.component';
import { LayoutItemComponent } from './layout-item.component';
import { LayoutResponsiveWindowManager } from './layout-responsive-window-manager';
import * as i0 from "@angular/core";
const _c0 = [[["sme-layout-item"]]];
const _c1 = ["sme-layout-item"];
/**
* Layout component
*/
export class LayoutComponent extends CoreBaseComponent {
constructor(injector, layout) {
super(injector);
/**
* The default horizontal space in between layout items.
*/
this.itemHorizontalSpace = 32;
/**
* The default vertical space in between layout items.
*/
this.itemVerticalSpace = 32;
/**
* If true, will always use full width of the row for rendering.
*/
this.oneColumn = false;
/**
* If true, will always try to fill the whole row for each layout item.
*/
this.tryToFillWholeRow = true;
/**
* The layout definition.
*/
this.definition = {};
/**
* If false, it will not assign extra paddings to the right for the last layout item.
*/
this.padLastItem = false;
/**
* If true, not extra right padding when there is only one item that uses the whole width of the row.
*/
this.noExtraRightPaddingOneItemPerRow = true;
/**
* It determines whether the layout is for settings where it contains a left and right layout item.
* If true, will apply special design for settings layout.
* On phone-up, the left side navigation layout item will be using a fixed width by default 300px,
* the right side layout item will be using the remaining width by default.
*
* On phone-down or 400% zoom, nothing is different from the regular settings page,
* the left right layout will be transformed to top bottom layout.
*/
this.layoutConfig = {
[SmeResponsiveWindowBreakpoints.PhoneUp]: { 'mode': LayoutItemConfigMode.Default },
[SmeResponsiveWindowBreakpoints.PhoneDown]: { 'mode': LayoutItemConfigMode.Default },
[SmeResponsiveWindowBreakpoints.Reflow]: { 'mode': LayoutItemConfigMode.Default }
};
/**
* Implementation of the Layout interface
*/
this.layoutChanged = new EventEmitter();
/**
* Implementation of the Layout interface
*/
this.windowBreakpointChanged = new EventEmitter();
this.columnCount = 1;
this.columnSpanTotal = 0;
this.layoutDrivenType = LayoutDrivenType.Default;
this.stylePixel = 'px';
if (layout) {
this.layoutResponsiveWindowManager = new LayoutResponsiveWindowManager(layout);
// on parent layout changes, re-emit the layout change to our event
this.subscriptions.push(layout.layoutChanged.subscribe((() => this.onLayoutChanged())));
// on window break point changes, emit the event about critical classes and styling updates signal.
this.subscriptions.push(layout.windowBreakpointChanged.subscribe(() => this.onWindowBreakpointChanged()));
this.deferredOnLayoutChanged();
}
}
/**
* The source name to use for logging
*/
get logSourceName() {
return 'LayoutComponent';
}
get currentLayoutDefinitionName() {
return this.currentLayoutDefinition ? this.currentLayoutDefinition.name : '';
}
get currentLayoutDrivenType() {
return this.layoutDrivenType;
}
get currentWindowBreakpoint() {
return this.layoutResponsiveWindowManager?.prevSize.size;
}
get currentLayoutItems() {
return this.layoutItems;
}
ngAfterViewInit() {
this.subscriptions.push(this.layoutItems.changes.subscribe(() => this.onLayoutChanged()));
}
/**
* The open API for refreshing the control externally.
*/
refresh() {
this.resetFlex();
this.onLayoutChanged();
}
/**
* On layout changed event handler, occurs every time the layout has been changed.
*/
onLayoutChanged() {
this.updateLayout();
}
/**
* The deferred layout changed handler.
*/
deferredOnLayoutChanged() {
this.onLayoutChanged();
}
/**
* The on window breakpoint changed handler.
* Adding yield for component to get ElementRef after initialization.
*/
onWindowBreakpointChanged() {
if (!this.layoutItems || !this.layoutItems.toArray()) {
return;
}
this.layoutResponsiveWindowManager.onWindowSizeChanged();
}
// Adds classes listed to the root component
// On phone down the flex start needs to be flex start to make sure no extra space being generated.
getInitialHostClasses() {
return super.getInitialHostClasses().concat([
'sme-arrange-wrapstack-h', 'sme-layout-phone-down'
]);
}
updateLayout() {
setTimeout(() => {
if (!this.layoutItems) {
return;
}
const layoutItems = this.layoutItems.toArray();
this.getTotalColumnSpan(layoutItems);
const currentWindowSize = this.layoutResponsiveWindowManager.prevSize.size;
this.updateLayoutConfig(currentWindowSize);
const layoutWidth = this.hostElement.nativeElement.clientWidth || Number.MAX_VALUE;
if (this.layoutDrivenType === LayoutDrivenType.Default) {
const definitions = this.definitions.toArray().sort((a, b) => a.until - b.until);
const previousLayoutDefinition = this.currentLayoutDefinition;
this.updateCurrentLayoutDefinition(definitions, layoutWidth);
const itemHorizontalSpacePercentage = Math.round(this.itemHorizontalSpace * 100 / layoutWidth);
const columnCountModifier = this.padLastItem ? 0 : 1;
const availableLayoutWidthPercentage = 100 - itemHorizontalSpacePercentage * (this.columnCount - columnCountModifier);
this.layoutDefinitionWithColumnSpanCalculation(layoutItems, availableLayoutWidthPercentage, itemHorizontalSpacePercentage);
if (previousLayoutDefinition !== this.currentLayoutDefinition) {
setTimeout(() => {
this.layoutChanged.emit();
});
}
}
else if (this.layoutDrivenType === LayoutDrivenType.ResponsiveWindowManager) {
let availableLayoutWidthInPixel = layoutWidth - this.itemHorizontalSpace;
availableLayoutWidthInPixel = availableLayoutWidthInPixel > 0 ? availableLayoutWidthInPixel : 0;
if (availableLayoutWidthInPixel <= 0) {
return;
}
this.configDrivenCalculation(layoutItems, availableLayoutWidthInPixel);
}
});
}
updateLayoutConfig(currentWindowSize) {
if (!currentWindowSize) {
this.layoutDrivenType = LayoutDrivenType.Default;
return;
}
const phoneUp = this.layoutConfig.PhoneUp;
const phoneDown = this.layoutConfig.PhoneDown;
const reflow = this.layoutConfig.Reflow;
if (!phoneUp || !phoneDown || !reflow) {
Logging.log({
level: LogLevel.Debug,
message: 'Invalid layout config has been passed in',
source: 'DataTableComponent.onContentTablePressed'
});
const defaultMode = { 'mode': LayoutItemConfigMode.Default };
if (!phoneUp) {
this.layoutConfig.PhoneUp = defaultMode;
}
if (!phoneDown) {
this.layoutConfig.PhoneDown = defaultMode;
}
if (!reflow) {
this.layoutConfig.Reflow = defaultMode;
}
}
const currentConfig = this.layoutConfig[currentWindowSize];
if (currentConfig.mode === LayoutItemConfigMode.Default) {
this.setLayoutDrivenType(LayoutDrivenType.Default);
}
else if (currentConfig.mode === LayoutItemConfigMode.Custom && currentConfig.config && currentConfig.config.length) {
this.setLayoutDrivenType(LayoutDrivenType.ResponsiveWindowManager);
this.currentLayoutItemConfig = currentConfig.config;
}
}
resetFlex() {
const layoutItems = this.layoutItems.toArray();
for (let i = 0; i < layoutItems.length; i++) {
const layoutItem = layoutItems[i];
if (layoutItem.flex) {
layoutItem.flex = undefined;
}
}
}
setLayoutDrivenType(layoutDrivenType) {
if (this.layoutDrivenType === LayoutDrivenType.ResponsiveWindowManager && layoutDrivenType === LayoutDrivenType.Default) {
this.resetFlex();
}
this.layoutDrivenType = layoutDrivenType;
// The vertical space gap is determined by the itemVerticalSpace parameter.
// For the defaultMode, it is controlled by the padding bottom of the grid item.
// For the responsive manager driven mode, it is controlled by the grid-gap.
this.hostElement.nativeElement.style.gridGap = layoutDrivenType === LayoutDrivenType.ResponsiveWindowManager ? `${this.itemVerticalSpace}px 0px` : 'unset';
}
getTotalColumnSpan(layoutItems) {
this.columnSpanTotal = 0;
layoutItems.forEach(item => this.columnSpanTotal += item.columnSpan);
}
updateCurrentLayoutDefinition(definitions, layoutWidth) {
this.currentLayoutDefinition = undefined;
for (let i = definitions.length - 1; i >= 0; i--) {
const definitionColumns = definitions[i].columns;
if (layoutWidth <= definitions[i].until || (this.tryToFillWholeRow && this.columnSpanTotal <= definitionColumns) || this.oneColumn) {
this.columnCount = definitionColumns;
this.currentLayoutDefinition = definitions[i];
}
}
}
layoutDefinitionWithColumnSpanCalculation(layoutItems, availableLayoutWidthPercentage, itemHorizontalSpacePercentage) {
let percentageSoFar = 0;
let columnIndex = 0;
for (let i = 0; i < layoutItems.length; i++) {
let percentage = 0;
columnIndex += layoutItems[i].columnSpan;
if (columnIndex === this.columnCount) {
// If true, it means this layout item is the last one in the row.
// It ensures the last one in the row use rest of the percentage.
// Example: If it's a 3 column layout, the last one's percentage is 33.34%, not 33.33%
percentage = 100 - percentageSoFar;
percentageSoFar = 0;
// 1 column and 1 layout item.
if (columnIndex === 1 && this.columnCount === 1 && !this.noExtraRightPaddingOneItemPerRow) {
layoutItems[i].paddingRight = '0px';
}
else {
layoutItems[i].paddingRight = this.padLastItem ? this.itemHorizontalSpace + this.stylePixel : '0' + this.stylePixel;
}
columnIndex = 0;
}
else {
const columnPercentage = Math.round(availableLayoutWidthPercentage * 100 / this.columnCount) / 100;
percentage = layoutItems[i].columnSpan * (columnPercentage + itemHorizontalSpacePercentage);
percentageSoFar += percentage;
if (percentageSoFar > 100) {
// put item on next row if it is too big
if (percentage > 100) {
percentage = 100;
}
percentageSoFar = 0;
columnIndex = 0;
layoutItems[i].paddingRight = this.padLastItem ? this.itemHorizontalSpace + this.stylePixel : '0' + this.stylePixel;
}
else {
layoutItems[i].paddingRight = this.itemHorizontalSpace + this.stylePixel;
}
}
if (this?.currentLayoutDefinition?.addBottomPadding) {
layoutItems[i].paddingBottom = this.itemVerticalSpace + this.stylePixel;
}
else {
// If bottom padding already exists and currentLayoutDefinition.addBottomPadding is False
// Remove the bottom padding.
if (layoutItems[i].paddingBottom === this.itemVerticalSpace + this.stylePixel) {
layoutItems[i].paddingBottom = '0' + this.stylePixel;
}
}
layoutItems[i].width = percentage + '%';
layoutItems[i].ready();
}
}
configDrivenCalculation(layoutItems, availableLayoutWidthInPixel) {
const isHybridMode = this.updateCustomConfig(layoutItems);
if (isHybridMode) {
this.configDrivenCalculationHybrid(layoutItems, availableLayoutWidthInPixel);
}
else {
this.configDrivenCalculationDefault(layoutItems, availableLayoutWidthInPixel);
}
}
/**
* It deal with configurations that only has either percentage or number.
* Aiming at performance optimization.
*
* @param layoutItems The layout item object array
* @param availableLayoutWidthInPixel available width in pixel horizontally.
*/
configDrivenCalculationDefault(layoutItems, availableLayoutWidthInPixel) {
const defaultWidthForLayoutItemInPixel = 200;
let widthUsedInPixel = 0;
let percentageSoFar = 0;
for (let i = 0; i < layoutItems.length; i++) {
if (layoutItems[i].customConfig?.width) {
const widthObject = layoutItems[i].customConfig.width;
const remainingWidthInPixel = availableLayoutWidthInPixel - widthUsedInPixel;
if (widthObject.type === LayoutItemConfigPropertyWidthType.Percentage) {
if (widthObject.value > 100 || widthObject.value < 0) {
widthObject.value = 100;
}
const percentage = widthObject.value;
percentageSoFar += percentage;
const paddingRight = this.itemHorizontalSpace;
layoutItems[i].paddingRight = paddingRight.toString().concat(this.stylePixel);
layoutItems[i].width = percentage + '%';
if (percentageSoFar > 100) {
percentageSoFar = 0;
}
}
else if (widthObject.type === LayoutItemConfigPropertyWidthType.Number) {
if (widthObject.value < 0) {
widthObject.value =
defaultWidthForLayoutItemInPixel <= remainingWidthInPixel ?
defaultWidthForLayoutItemInPixel : remainingWidthInPixel;
}
widthUsedInPixel += widthObject.value;
// how to determine if it is the last item in a row?
const paddingRight = this.itemHorizontalSpace;
widthUsedInPixel += paddingRight;
layoutItems[i].paddingRight = paddingRight.toString().concat(this.stylePixel);
layoutItems[i].width = widthObject.value + this.stylePixel;
}
else {
Logging.log({
level: LogLevel.Debug,
message: 'Invalid width',
source: 'LayoutComponent.configDrivenCalculationDefault'
});
}
}
else {
Logging.log({
level: LogLevel.Debug,
message: 'Invalid width',
source: 'LayoutComponent.configDrivenCalculationDefault'
});
}
layoutItems[i].ready();
}
}
/**
* It deal with configurations that only has both percentage and number.
* Aiming at performance optimization.
*
* @param layoutItems The layout item object array
* @param availableLayoutWidthInPixel available width in pixel horizontally.
*/
configDrivenCalculationHybrid(layoutItems, availableLayoutWidthInPixel) {
const defaultWidthForLayoutItemInPixel = 200;
let widthUsedInPixel = 0;
for (let i = 0; i < layoutItems.length; i++) {
if (layoutItems[i].customConfig.width) {
const widthObject = layoutItems[i].customConfig.width;
const remainingWidthInPixel = availableLayoutWidthInPixel - widthUsedInPixel;
if (widthObject.type === LayoutItemConfigPropertyWidthType.Percentage) {
if (widthObject.value > 100 || widthObject.value < 0) {
widthObject.value = 100;
}
// how to determine if it is the last item in a row?
const paddingRight = this.itemHorizontalSpace;
widthUsedInPixel += paddingRight;
layoutItems[i].paddingRight = paddingRight.toString().concat(this.stylePixel);
let potentialWidthInPixel = (widthObject.value / 100) * remainingWidthInPixel;
if (potentialWidthInPixel === 0) {
widthUsedInPixel = 0;
widthUsedInPixel += paddingRight;
potentialWidthInPixel = (widthObject.value / 100) * (availableLayoutWidthInPixel - widthUsedInPixel);
}
else {
if (potentialWidthInPixel >= remainingWidthInPixel) {
potentialWidthInPixel = remainingWidthInPixel;
// resets the used pixel for a new row.
widthUsedInPixel = 0;
}
else {
widthUsedInPixel += potentialWidthInPixel;
}
layoutItems[i].flex = '1 0 0';
layoutItems[i].minWidth = defaultWidthForLayoutItemInPixel.toString().concat(this.stylePixel);
}
layoutItems[i].width = potentialWidthInPixel + this.stylePixel;
}
else if (widthObject.type === LayoutItemConfigPropertyWidthType.Number) {
if (widthObject.value < 0) {
widthObject.value =
defaultWidthForLayoutItemInPixel <= remainingWidthInPixel ?
defaultWidthForLayoutItemInPixel : remainingWidthInPixel;
}
widthUsedInPixel += widthObject.value;
// how to determine if it is the last item in a row?
const paddingRight = this.itemHorizontalSpace;
widthUsedInPixel += paddingRight;
layoutItems[i].paddingRight = paddingRight.toString().concat(this.stylePixel);
layoutItems[i].width = widthObject.value + this.stylePixel;
}
else {
Logging.log({
level: LogLevel.Debug,
message: 'Invalid width',
source: 'LayoutComponent.configDrivenCalculationHybrid'
});
}
}
else {
Logging.log({
level: LogLevel.Debug,
message: 'Invalid width',
source: 'LayoutComponent.configDrivenCalculationHybrid'
});
}
layoutItems[i].ready();
}
}
updateCustomConfig(layoutItems) {
const widthType = [];
for (let i = 0; i < layoutItems.length; i++) {
if (!this.currentLayoutItemConfig[i]) {
continue;
}
layoutItems[i].customConfig = this.currentLayoutItemConfig[i];
if (!widthType.includes(layoutItems[i].customConfig.width.type)) {
widthType.push(layoutItems[i].customConfig.width.type);
}
}
if (widthType.length <= 1) {
return false;
}
return true;
}
}
/** @nocollapse */ LayoutComponent.ɵfac = function LayoutComponent_Factory(t) { return new (t || LayoutComponent)(i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(SME_LAYOUT_PROVIDER)); };
/** @nocollapse */ LayoutComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: LayoutComponent, selectors: [["sme-layout"]], contentQueries: function LayoutComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) {
i0.ɵɵcontentQuery(dirIndex, LayoutItemComponent, 4);
i0.ɵɵcontentQuery(dirIndex, LayoutDefinitionComponent, 4);
} if (rf & 2) {
let _t;
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.layoutItems = _t);
i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.definitions = _t);
} }, inputs: { itemHorizontalSpace: "itemHorizontalSpace", itemVerticalSpace: "itemVerticalSpace", oneColumn: "oneColumn", tryToFillWholeRow: "tryToFillWholeRow", definition: "definition", padLastItem: "padLastItem", noExtraRightPaddingOneItemPerRow: "noExtraRightPaddingOneItemPerRow", layoutConfig: "layoutConfig" }, outputs: { layoutChanged: "layoutChanged", windowBreakpointChanged: "windowBreakpointChanged" }, features: [i0.ɵɵInheritDefinitionFeature], ngContentSelectors: _c1, decls: 1, vars: 0, template: function LayoutComponent_Template(rf, ctx) { if (rf & 1) {
i0.ɵɵprojectionDef(_c0);
i0.ɵɵprojection(0);
} }, encapsulation: 2 });
__decorate([
Debounce(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], LayoutComponent.prototype, "refresh", null);
__decorate([
Debounce(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], LayoutComponent.prototype, "deferredOnLayoutChanged", null);
__decorate([
Yield(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], LayoutComponent.prototype, "onWindowBreakpointChanged", null);
(function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(LayoutComponent, [{
type: Component,
args: [{ selector: 'sme-layout', template: "<ng-content select=\"sme-layout-item\"></ng-content>\r\n" }]
}], function () { return [{ type: i0.Injector }, { type: undefined, decorators: [{
type: Inject,
args: [SME_LAYOUT_PROVIDER]
}] }]; }, { layoutItems: [{
type: ContentChildren,
args: [LayoutItemComponent]
}], definitions: [{
type: ContentChildren,
args: [LayoutDefinitionComponent]
}], itemHorizontalSpace: [{
type: Input
}], itemVerticalSpace: [{
type: Input
}], oneColumn: [{
type: Input
}], tryToFillWholeRow: [{
type: Input
}], definition: [{
type: Input
}], padLastItem: [{
type: Input
}], noExtraRightPaddingOneItemPerRow: [{
type: Input
}], layoutConfig: [{
type: Input
}], layoutChanged: [{
type: Output
}], windowBreakpointChanged: [{
type: Output
}], refresh: [], deferredOnLayoutChanged: [], onWindowBreakpointChanged: [] }); })();
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGF5b3V0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL2FuZ3VsYXIvc3JjL2NvbnRyb2xzL2xheW91dC9sYXlvdXQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvbGF5b3V0L2xheW91dC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUFpQixTQUFTLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3BJLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSw4RUFBOEUsQ0FBQztBQUN4RyxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sMEVBQTBFLENBQUM7QUFDakcsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGdFQUFnRSxDQUFDO0FBQzFGLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSw4REFBOEQsQ0FBQztBQUN2RixPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3RCxPQUFPLEVBQVUsbUJBQW1CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsOEJBQThCLEVBQUUsTUFBTSxtREFBbUQsQ0FBQztBQUNuRyxPQUFPLEVBQWtDLGdCQUFnQixFQUFvQixvQkFBb0IsRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzlKLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQzFFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLG9DQUFvQyxDQUFDOzs7O0FBRW5GOztHQUVHO0FBS0gsTUFBTSxPQUFPLGVB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QSx1QkFBdUI7a0JBRDdCLE1BQU07WUFpREEsT0FBTyxNQWdCTix1QkFBdUIsTUFTeEIseUJBQXlCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ29tcG9uZW50LCBDb250ZW50Q2hpbGRyZW4sIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBJbmplY3RvciwgSW5wdXQsIE91dHB1dCwgUXVlcnlMaXN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IERlYm91bmNlIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9iYXNlL2RlY29yYXRvcnMvZGVib3VuY2UuZGVjb3JhdG9ycyc7XHJcbmltcG9ydCB7IFlpZWxkIH0gZnJvbSAnQG1pY3Jvc29mdC93aW5kb3dzLWFkbWluLWNlbnRlci1zZGsvY29yZS9iYXNlL2RlY29yYXRvcnMveWllbGQuZGVjb3JhdG9yJztcclxuaW1wb3J0IHsgTG9nTGV2ZWwgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RpYWdub3N0aWNzL2xvZy1sZXZlbCc7XHJcbmltcG9ydCB7IExvZ2dpbmcgfSBmcm9tICdAbWljcm9zb2Z0L3dpbmRvd3MtYWRtaW4tY2VudGVyLXNkay9jb3JlL2RpYWdub3N0aWNzL2xvZ2dpbmcnO1xyXG5pbXBvcnQgeyBDb3JlQmFzZUNvbXBvbmVudCB9IGZyb20gJy4uL2NvbW1vbi9iYXNlLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IExheW91dCwgU01FX0xBWU9VVF9QUk9WSURFUiB9IGZyb20gJy4uL2NvbW1vbi9sYXlvdXQnO1xyXG5pbXBvcnQgeyBTbWVSZXNwb25zaXZlV2luZG93QnJlYWtwb2ludHMgfSBmcm9tICcuLi9jb21tb24vc21lLXJlc3BvbnNpdmUtd2luZG93LW1hbmFnZXIuY29tcG9uZW50JztcclxuaW1wb3J0IHsgTGF5b3V0Q29uZmlnLCBMYXlvdXRDb25maWdJdGVtLCBMYXlvdXREcml2ZW5UeXBlLCBMYXlvdXRJdGVtQ29uZmlnLCBMYXlvdXRJdGVtQ29uZmlnTW9kZSwgTGF5b3V0SXRlbUNvbmZpZ1Byb3BlcnR5V2lkdGhUeXBlIH0gZnJvbSAnLi9sYXlvdXQtY29uZmlnJztcclxuaW1wb3J0IHsgTGF5b3V0RGVmaW5pdGlvbkNvbXBvbmVudCB9IGZyb20gJy4vbGF5b3V0LWRlZmluaXRpb24uY29tcG9uZW50JztcclxuaW1wb3J0IHsgTGF5b3V0SXRlbUNvbXBvbmVudCB9IGZyb20gJy4vbGF5b3V0LWl0ZW0uY29tcG9uZW50JztcclxuaW1wb3J0IHsgTGF5b3V0UmVzcG9uc2l2ZVdpbmRvd01hbmFnZXIgfSBmcm9tICcuL2xheW91dC1yZXNwb25zaXZlLXdpbmRvdy1tYW5hZ2VyJztcclxuXHJcbi8qKlxyXG4gKiBMYXlvdXQgY29tcG9uZW50XHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICAgIHNlbGVjdG9yOiAnc21lLWxheW91dCcsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vbGF5b3V0LmNvbXBvbmVudC5odG1sJ1xyXG59KVxyXG5leHBvcnQgY2xhc3MgTGF5b3V0Q29tcG9uZW50IGV4dGVuZHMgQ29yZUJhc2VDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0IHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHNvdXJjZSBuYW1lIHRvIHVzZSBmb3IgbG9nZ2luZ1xyXG4gICAgICovXHJcbiAgICBwcm90ZWN0ZWQgZ2V0IGxvZ1NvdXJjZU5hbWUoKSB7XHJcbiAgICAgICAgcmV0dXJuICdMYXlvdXRDb21wb25lbnQnO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGxheW91dCBpdGVtcyBjb250ZW50IGNoaWxkcmVuLlxyXG4gICAgICovXHJcbiAgICBAQ29udGVudENoaWxkcmVuKExheW91dEl0ZW1Db21wb25lbnQpXHJcbiAgICBwcml2YXRlIGxheW91dEl0ZW1zOiBRdWVyeUxpc3Q8TGF5b3V0SXRlbUNvbXBvbmVudD47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbGF5b3V0IGRlZmluaXRpb24gY29udGVudCBjaGlsZHJlbi5cclxuICAgICAqL1xyXG4gICAgQENvbnRlbnRDaGlsZHJlbihMYXlvdXREZWZpbml0aW9uQ29tcG9uZW50KVxyXG4gICAgcHJpdmF0ZSBkZWZpbml0aW9uczogUXVlcnlMaXN0PExheW91dERlZmluaXRpb25Db21wb25lbnQ+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGN1cnJlbnQgbGF5b3V0IGRlZmluaXRpb24gdmFsdWUgYmFzZWQgb24gY3VzdG9tIGxheW91dCBkZWZpbml0aW9uIGFuZCB0aGUgYnJvd3NlciB3aW5kb3cgc2l6ZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGN1cnJlbnRMYXlvdXREZWZpbml0aW9uOiBMYXlvdXREZWZpbml0aW9uQ29tcG9uZW50O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGRlZmF1bHQgaG9yaXpvbnRhbCBzcGFjZSBpbiBiZXR3ZWVuIGxheW91dCBpdGVtcy5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBpdGVtSG9yaXpvbnRhbFNwYWNlID0gMzI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgZGVmYXVsdCB2ZXJ0aWNhbCBzcGFjZSBpbiBiZXR3ZWVuIGxheW91dCBpdGVtcy5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBpdGVtVmVydGljYWxTcGFjZSA9IDMyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdHJ1ZSwgd2lsbCBhbHdheXMgdXNlIGZ1bGwgd2lkdGggb2YgdGhlIHJvdyBmb3IgcmVuZGVyaW5nLlxyXG4gICAgICovXHJcbiAgICBASW5wdXQoKVxyXG4gICAgcHVibGljIG9uZUNvbHVtbiA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdHJ1ZSwgd2lsbCBhbHdheXMgdHJ5IHRvIGZpbGwgdGhlIHdob2xlIHJvdyBmb3IgZWFjaCBsYXlvdXQgaXRlbS5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyB0cnlUb0ZpbGxXaG9sZVJvdyA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbGF5b3V0IGRlZmluaXRpb24uXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgZGVmaW5pdGlvbjogeyBbY29sdW1uQ291bnQ6IG51bWJlcl06IHsgbG93ZXJXaWR0aD86IG51bWJlciwgdXBwZXJXaWR0aD86IG51bWJlciB9IH0gPSB7fTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIElmIGZhbHNlLCBpdCB3aWxsIG5vdCBhc3NpZ24gZXh0cmEgcGFkZGluZ3MgdG8gdGhlIHJpZ2h0IGZvciB0aGUgbGFzdCBsYXlvdXQgaXRlbS5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBwYWRMYXN0SXRlbSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdHJ1ZSwgbm90IGV4dHJhIHJpZ2h0IHBhZGRpbmcgd2hlbiB0aGVyZSBpcyBvbmx5IG9uZSBpdGVtIHRoYXQgdXNlcyB0aGUgd2hvbGUgd2lkdGggb2YgdGhlIHJvdy5cclxuICAgICAqL1xyXG4gICAgQElucHV0KClcclxuICAgIHB1YmxpYyBub0V4dHJhUmlnaHRQYWRkaW5nT25lSXRlbVBlclJvdyA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBJdCBkZXRlcm1pbmVzIHdoZXRoZXIgdGhlIGxheW91dCBpcyBmb3Igc2V0dGluZ3Mgd2hlcmUgaXQgY29udGFpbnMgYSBsZWZ0IGFuZCByaWdodCBsYXlvdXQgaXRlbS5cclxuICAgICAqIElmIHRydWUsIHdpbGwgYXBwbHkgc3BlY2lhbCBkZXNpZ24gZm9yIHNldHRpbmdzIGxheW91dC5cclxuICAgICAqIE9uIHBob25lLXVwLCB0aGUgbGVmdCBzaWRlIG5hdmlnYXRpb24gbGF5b3V0IGl0ZW0gd2lsbCBiZSB1c2luZyBhIGZpeGVkIHdpZHRoIGJ5IGRlZmF1bHQgMzAwcHgsXHJcbiAgICAgKiB0aGUgcmlnaHQgc2lkZSBsYXlvdXQgaXRlbSB3aWxsIGJlIHVzaW5nIHRoZSByZW1haW5pbmcgd2lkdGggYnkgZGVmYXVsdC5cclxuICAgICAqXHJcbiAgICAgKiBPbiBwaG9uZS1kb3duIG9yIDQwMCUgem9vbSwgbm90aGluZyBpcyBkaWZmZXJlbnQgZnJvbSB0aGUgcmVndWxhciBzZXR0aW5ncyBwYWdlLFxyXG4gICAgICogdGhlIGxlZnQgcmlnaHQgbGF5b3V0IHdpbGwgYmUgdHJhbnNmb3JtZWQgdG8gdG9wIGJvdHRvbSBsYXlvdXQuXHJcbiAgICAgKi9cclxuICAgIEBJbnB1dCgpXHJcbiAgICBwdWJsaWMgbGF5b3V0Q29uZmlnOiBMYXlvdXRDb25maWcgPSB7XHJcbiAgICAgICAgW1NtZVJlc3BvbnNpdmVXaW5kb3dCcmVha3BvaW50cy5QaG9uZVVwXTogeyAnbW9kZSc6IExheW91dEl0ZW1Db25maWdNb2RlLkRlZmF1bHQgfSxcclxuICAgICAgICBb