UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

517 lines 77.6 kB
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