UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

863 lines 112 kB
import { __decorate, __metadata } from "tslib"; import { Component, ContentChild, ElementRef, EventEmitter, forwardRef, Inject, Injector, Input, Optional, Output, SkipSelf, ViewChild } 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 { Dom } from '@microsoft/windows-admin-center-sdk/core/dom/dom'; import { take } from 'rxjs/operators'; import { ActionBarComponent } from '../actions/containers/action-bar/action-bar.component'; import { SME_LAYOUT_PROVIDER } from '../common/layout'; import { SpacerBaseDirective } from '../common/spacer-base.component'; import { DataTableDownloadDataType, DataTableDownloadService } from '../data-table/data-table-download.service'; import { DataTableComponent, TreeTableComponent } from '../data-table/data-table.component'; import { SearchFormFieldComponent } from '../form/form-field/search/search-form-field.component'; import { PivotComponent } from '../pivot/pivot.component'; import { SplitViewComponent } from '../split-view/split-view.component'; import { MasterViewContentDirective } from './master-view-content/master-view-content.component'; import { MasterViewResponsiveWindowManager } from './master-view-responsive-window-manager'; import * as i0 from "@angular/core"; import * as i1 from "../data-table/data-table-download.service"; import * as i2 from "../split-view/split-view.component"; import * as i3 from "../pivot/pivot.component"; import * as i4 from "@angular/common"; import * as i5 from "../layout/layout.component"; import * as i6 from "../layout/layout-definition.component"; import * as i7 from "./master-view-content/master-view-content.component"; import * as i8 from "../tooltip/tooltip.directive"; const _c0 = ["search"]; const _c1 = ["smeTreeTable"]; const _c2 = ["container"]; const _c3 = ["dataView"]; function MasterViewComponent_h2_0_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "h2", 21); i0.ɵɵtext(1); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r0 = i0.ɵɵnextContext(); i0.ɵɵproperty("hidden", ctx_r0.hideHeader)("id", ctx_r0.headerId); i0.ɵɵadvance(1); i0.ɵɵtextInterpolate(ctx_r0.header); } } function MasterViewComponent_div_4_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div", 22); i0.ɵɵprojection(1, 2); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r2 = i0.ɵɵnextContext(); i0.ɵɵclassProp("sme-padding-horizontal-sm", !ctx_r2.noSideMargin); } } function MasterViewComponent_button_12_Template(rf, ctx) { if (rf & 1) { const _r14 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "button", 23); i0.ɵɵlistener("click", function MasterViewComponent_button_12_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r14); const ctx_r13 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r13.doClearSelection($event)); }); i0.ɵɵelementStart(1, "i", 24); i0.ɵɵtext(2); i0.ɵɵelementEnd(); i0.ɵɵelementStart(3, "i", 25); i0.ɵɵtext(4); i0.ɵɵelementEnd(); i0.ɵɵelement(5, "i", 26); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r4 = i0.ɵɵnextContext(); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate(ctx_r4.getSelectedCountText()); i0.ɵɵadvance(2); i0.ɵɵtextInterpolate(ctx_r4.getSelectedCountAriaText()); i0.ɵɵadvance(1); i0.ɵɵproperty("title", ctx_r4.resourceStrings.selectedTitle); } } function MasterViewComponent_button_14_Template(rf, ctx) { if (rf & 1) { const _r16 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "button", 27); i0.ɵɵlistener("click", function MasterViewComponent_button_14_Template_button_click_0_listener($event) { i0.ɵɵrestoreView(_r16); const ctx_r15 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r15.onDownloadButtonClicked($event)); }); i0.ɵɵelement(1, "span", 28); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r5 = i0.ɵɵnextContext(); i0.ɵɵclassProp("sme-toggled", ctx_r5.downloadActive); } } function MasterViewComponent_button_15_Template(rf, ctx) { if (rf & 1) { const _r18 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "button", 29); i0.ɵɵlistener("click", function MasterViewComponent_button_15_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r18); const ctx_r17 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r17.columnPicker.next()); }); i0.ɵɵelement(1, "span", 30); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r6 = i0.ɵɵnextContext(); i0.ɵɵclassProp("sme-toggled", ctx_r6.columnPickerActive); i0.ɵɵproperty("title", ctx_r6.resourceStrings.columnPicker.title); i0.ɵɵattribute("aria-label", ctx_r6.getFilterAriaLabel()); } } function MasterViewComponent_button_16_Template(rf, ctx) { if (rf & 1) { const _r20 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "button", 31); i0.ɵɵlistener("click", function MasterViewComponent_button_16_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r20); const ctx_r19 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r19.refreshButtonClicked()); }); i0.ɵɵelement(1, "span", 32); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r7 = i0.ɵɵnextContext(); i0.ɵɵproperty("title", ctx_r7.refreshTooltipText || ctx_r7.resourceStrings.refresh.title); i0.ɵɵattribute("aria-disabled", ctx_r7.disableRefresh)("aria-label", ctx_r7.refreshTooltipText || ctx_r7.refreshButtonAriaLabel); } } function MasterViewComponent_button_17_Template(rf, ctx) { if (rf & 1) { const _r22 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "button", 33); i0.ɵɵlistener("click", function MasterViewComponent_button_17_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r22); const ctx_r21 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r21.filter.next()); }); i0.ɵɵelement(1, "span", 34); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r8 = i0.ɵɵnextContext(); i0.ɵɵclassProp("sme-toggled", ctx_r8.filterActive); i0.ɵɵproperty("title", ctx_r8.resourceStrings.filter.title); i0.ɵɵattribute("aria-label", ctx_r8.getFilterAriaLabel()); } } function MasterViewComponent_button_18_Template(rf, ctx) { if (rf & 1) { const _r24 = i0.ɵɵgetCurrentView(); i0.ɵɵelementStart(0, "button", 33); i0.ɵɵlistener("click", function MasterViewComponent_button_18_Template_button_click_0_listener() { i0.ɵɵrestoreView(_r24); const ctx_r23 = i0.ɵɵnextContext(); return i0.ɵɵresetView(ctx_r23.group.next()); }); i0.ɵɵelement(1, "span", 35); i0.ɵɵelementEnd(); } if (rf & 2) { const ctx_r9 = i0.ɵɵnextContext(); i0.ɵɵclassProp("sme-toggled", ctx_r9.groupActive); i0.ɵɵproperty("title", ctx_r9.resourceStrings.group.title); i0.ɵɵattribute("aria-label", ctx_r9.resourceStrings.group.title); } } function MasterViewComponent_div_20_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "div", 36); i0.ɵɵprojection(1, 3); i0.ɵɵelementEnd(); } } function MasterViewComponent_form_21_Template(rf, ctx) { if (rf & 1) { i0.ɵɵelementStart(0, "form", 37)(1, "div", 38); i0.ɵɵprojection(2, 4); i0.ɵɵelementEnd()(); } } const _c4 = [[["sme-action-bar"], ["", 8, "action-bar"]], "*", [["sme-query-editor"]], [["", 8, "sme-master-view-custom-filter"]], [["sme-form-field", "type", "search"]]]; const _c5 = ["sme-action-bar,.action-bar", "*", "sme-query-editor", ".sme-master-view-custom-filter", "sme-form-field[type=\"search\"]"]; export class MasterViewComponent extends SpacerBaseDirective { constructor(injector, hostElement, dataTableDownloadService, splitView, pivotComponent, layout) { // After the discussion, the plan is still have master view to coordinate with split view as well as tree table and data table. // It's a little tricky to let master view to talk to its parent which is the split view. // But we do need a component to implement the common behavior on the UI to avoid duplicate code in each tool. // At this moment, master view is the most proper component. // Long term wise, we will figure out a better component sitting in the top level of the UI to coordinate with other components // and implement common behaviors. super(injector); this.hostElement = hostElement; this.dataTableDownloadService = dataTableDownloadService; this.splitView = splitView; this.pivotComponent = pivotComponent; /** * The localization strings object for master view. */ this.resourceStrings = this.strings.MsftSmeShell.Angular.MasterView; /** * The localization strings object from angular common. */ this.commonStrings = this.strings.MsftSmeShell.Angular.Common; /** * True is to show the header. */ this.hideHeader = false; /** * The value of the header in string. */ this.header = ''; /** * The total count of table items in number. */ this.total = 0; /** * It determines whether to show the number of selections. */ this.showSelection = true; /** * It determine whether to show the column picker. */ this.showColumnPicker = false; /** * True is to show the download button. */ this.showDownloadButton = false; /** * It determines whether extra context parameter will be used for the download. * This usually associates with the 'download' emitter. */ this.getDownloadContextParameters = false; /** * It determines the state when the column picker dialog is opened. */ this.columnPickerActive = false; /** * It determines whether to show the refresh button. */ this.showRefresh = true; /** * It determines whether to disable the refresh button. */ this.disableRefresh = false; /** * It determines the data table min width level. */ this.dataTableMinWidth = 'md'; /** * It determines whether to show the filter button. */ this.showFilter = true; /** * It determines whether the filter dialog is opened. */ this.filterActive = false; /** * It determines there is a worker downloading in progress. */ this.downloadActive = false; /** * It determines whether to show up the query editor extension. */ this.enableQueryEditor = false; /** * The event emitter when selection(s) changed. */ this.selectionChange = new EventEmitter(); /** * It determines the group button has been clicked. */ this.groupActive = false; /** * If the value is false, the master view always renders in relative layout regardless of window size changes. */ this.stretchToAbsolute = true; /** * It determines whether to expand the details pane on first time landing on the page. */ this.autoExpandDetailsPane = true; /** * It determines the download data type. */ this.downloadDataType = DataTableDownloadDataType.CSV; /** * The event emitter for download has been prompted. */ this.downloadPrompted = new EventEmitter(); /** * The event emitter for when the download has been finished. */ this.downloadFinished = new EventEmitter(); /** * The event emitter for the column picker to render a dialog. */ this.columnPicker = new EventEmitter(); /** * The event emitter for the refreshing function to happen. */ this.refresh = new EventEmitter(); /** * The event emitter for the filter dialog to open. */ this.filter = new EventEmitter(); /** * The event emitter for the grouping dialog to open. */ this.group = new EventEmitter(); /** * The event emitter for the clear selection from the table to happen. */ this.clearSelection = new EventEmitter(); /** * The event emitter for when the data-view has been ready after ngAfterViewInit life cycle. */ this.smeDataTableFromTemplateReady = new EventEmitter(); /** * It implements the ILayout interface. It's triggered when the layout is changed. * It's used to tell the child components to coordinate with the layout change. */ this.layoutChanged = new EventEmitter(); /** * Implementation of the Layout interface */ this.windowBreakpointChanged = new EventEmitter(); this.useSearch = false; this.selectedItemCount = 0; this.dataViewHeight = 0; this.isDataListScrolledToTop = true; this.isInitialized = false; // setup host classes this.addClass('sme-arrange-stack-v'); this.addClass('sme-arrange-overflow-hide-y'); this.addClass('sme-arrange-overflow-auto-x'); this.headerId = 'master-view-header' + this.componentId; if (layout) { this.masterViewResponsiveWindowManager = new MasterViewResponsiveWindowManager(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(); } } /** * Getter for data table minimum width class in string. */ get dataTableMinWidthClassString() { return this.masterViewResponsiveWindowManager.dataTableMinWidthClassString; } /** * Getter for whether to render the search box based on window size. */ get searchBoxAutoWrapOnWindowSizeChanges() { return this.masterViewResponsiveWindowManager.searchBoxAutoWrapOnWindowSizeChanges; } /** * Getter for whether to set the overflow or not based on window size. */ get shouldDataTableParentOverflowHide() { return this.masterViewResponsiveWindowManager.shouldDataTableParentOverflowHide; } /** * Getter for whether the table would be rendered with padding horizontally. */ get shouldDataTableSlim() { return this.masterViewResponsiveWindowManager.shouldDataTableSlim; } /** * Getter for whether teh table would be rendered with bottom margin. */ get shouldDataTableRenderWithBottomMargin() { return this.masterViewResponsiveWindowManager.shouldDataTableRenderWithBottomMargin; } /** * The getter content child reference for the data-table component. */ get smeDataTable() { return this.internalSmeDataTable; } /** * The setter for the data table. */ set smeDataTable(value) { this.internalSmeDataTable = value; if (this.isInitialized) { this.setupDataTableAccessibility(); } } /** * Setter for the selection count for the data-table. */ set selection(selection) { let count = 0; if (Array.isArray(selection)) { count = selection.length; } else if (!!selection) { count = 1; } this.selectedItemCount = count; } /** * @deprecated since 7/13/18. Please use [showGroup], [groupActive], and (group) instead */ set showCustomFilter(value) { this.internalShowCustomFilter = value; } get showCustomFilter() { return this.internalShowCustomFilter; } /** * The source name to use for logging */ get logSourceName() { return 'MasterViewComponent'; } /** * The method to run after the component view initialized */ ngAfterViewInit() { setTimeout(() => { // The "ngAfterViewInit" is still in current check cycle so we should not update the following UI information immediately. // So we use setTimeout to defer the following operations to next check cycle. this.useSearch = !!this.searchElement; this.updateLayout(); }); if (this.splitView) { this.splitViewPaneToggledSubscription = this.splitView.paneToggled.subscribe(() => { if (this.dataView && this.dataViewHeight !== this.dataView.nativeElement.clientHeight) { this.updateLayout(); } }); } if (this.smeDataTable) { this.dataTableOnFilterSubscription = this.smeDataTable.filter.subscribe(() => { if (this.smeDataTable.selection) { let shouldClearSelection = true; if (!this.requireDataItemUniqueId) { if (this.smeDataTable.renderedItems.indexOf(this.smeDataTable.selection) !== -1) { shouldClearSelection = false; } } else { const selectedItemId = this.requireDataItemUniqueId(this.smeDataTable.selection); for (let i = 0; i < this.smeDataTable.renderedItems.length; i++) { const item = this.smeDataTable.renderedItems[i]; const itemId = this.requireDataItemUniqueId(item); if (itemId === selectedItemId) { shouldClearSelection = false; break; } } } if (shouldClearSelection) { this.clearSelection.emit(); } } }); } } ngOnInit() { this.isInitialized = true; if (this.stretchToAbsolute) { this.addClass('sme-layout-absolute-phone-up'); this.addClass('sme-position-inset-none'); } this.setupDataTableAccessibility(); if (this.header) { this.refreshButtonAriaLabel = this.resourceStrings.refresh.ariaLabel.header.format(this.header); } else { this.refreshButtonAriaLabel = this.resourceStrings.refresh.ariaLabel.noHeader; } } // Note: this is a bandaid fix to this bug: https://microsoft.visualstudio.com/OS/_workitems/edit/33031791/. // The screen reader doesn't announce when aria-disabled changes and the exact reason for that is unknown. // It's not best practice to be adjusting the aria-label to achieve the effect but that's the best we came up with. // TODO: fix the real issue why the screen reader doesn't announce the aria-disabled changes ngOnChanges(changes) { let refreshButtonLabel = this.resourceStrings.refresh.ariaLabel.noHeader; if (this.header) { refreshButtonLabel = this.resourceStrings.refresh.ariaLabel.header.format(this.header); } if (changes.disableRefresh?.currentValue === true) { this.refreshButtonAriaLabel = `${this.commonStrings.disabled} ${refreshButtonLabel}`; } else { this.refreshButtonAriaLabel = `${this.commonStrings.enabled} ${refreshButtonLabel}`; } } ngOnDestroy() { if (this.splitView && this.splitViewPaneToggledSubscription) { this.splitViewPaneToggledSubscription.unsubscribe(); } if (this.smeDataTable && this.dataTableOnFilterSubscription) { this.dataTableOnFilterSubscription.unsubscribe(); } } /** * Emit the event from the master view for the readiness of the templates passed in to the master view content. * This can better handling the rendering life cycle from child to parent. */ onSmeDataTableFromTemplateReady() { this.smeDataTableFromTemplateReady.emit(); } /** * The on window breakpoint changed handler. * Adding yield for component to get ElementRef after initialization. */ onLayoutChanged() { this.updateLayout(); } /** * The deferred layout changed handler. */ deferredOnLayoutChanged() { this.onLayoutChanged(); } /** * The implementation after interaction with the download button from the master view. * @param $event the button clicked event. */ onDownloadButtonClicked($event) { if (!$event || this.downloadActive || this.smeDataTable && this.smeDataTable.isBusy) { return; } $event.preventDefault(); this.downloadActive = true; this.downloadPrompted.next(); if (!this.smeDataTable || !this.smeDataTable.items) { Logging.log({ level: LogLevel.Warning, message: `Data table is not detected in the master view, custom template may be used.`, source: 'MasterViewComponent.onDownloadButtonClicked()' }); return; } if (!this.getDownloadContextParameters) { this.onDownloadPrompted(); } this.downloadFinished.next(); } /** * The function for executing the download context from data-table. * @param contextParameters the context parameter passed in from extension from outer scope. */ onDownloadPrompted(contextParameters) { try { this.dataTableDownloadService.downloadDataFinished.pipe(take(1)).subscribe(() => { this.downloadActive = false; }); this.dataTableDownloadService.downloadData(this.smeDataTable, this.downloadDataType, contextParameters); } catch (error) { Logging.log({ level: LogLevel.Error, message: `Failed to download '${error}'`, source: 'MasterViewComponent.onDownloadButtonClicked()' }); } } /** * The on window breakpoint changed handler. * Adding yield for component to get ElementRef after initialization. */ onWindowBreakpointChanged() { this.masterViewResponsiveWindowManager.onWindowSizeChanged(this.hostElement?.nativeElement, this.stretchToAbsolute); } /** * It updates the master view's layout and emits layout changed event to children. */ updateLayout() { if (!this.dataView || !this.dataView.nativeElement) { return; } this.dataViewHeight = this.dataView.nativeElement.clientHeight; this.removeClass('sme-arrange-overflow-hide-y'); if (this.masterViewResponsiveWindowManager.shouldHideYScroll) { this.addClass('sme-arrange-overflow-hide-y'); } this.layoutChanged.emit(); } ngDoCheck() { if (this.autoExpandDetailsPane) { if (this.smeDataTable) { this.handleDetailPaneExpanding(this.smeDataTable); } else if (this.smeTreeTable) { this.handleDetailPaneExpanding(this.smeTreeTable); } } } doClearSelection(event) { const next = Dom.getNextZoneElement(event.target); if (next) { next.focus(); } this.clearSelection.next(); } /** * Gets the item count in string. * @returns string value for the total count. */ getItemCountText() { return this.total === 1 ? this.resourceStrings.oneItem : this.resourceStrings.items.format(this.total); } /** * Gets selected item count in string. * @returns string value for the selected count. */ getSelectedCountText() { return this.resourceStrings.selected.format(this.selectedItemCount); } /** * Gets selected item count in string for aria support. * @returns string value for the selected count. */ getSelectedCountAriaText() { return this.resourceStrings.selectedAria.format(this.selectedItemCount); } /** * Gets filter item count in string for aria support. * @returns string value for the filtered count. */ getFilterAriaLabel() { return `${this.resourceStrings.filter.title} ${this.total ? this.resourceStrings.results.format(this.total) : this.resourceStrings.results.format(0)}`; } getColumnPickerAriaLabel() { return `${this.resourceStrings.columnPicker.title} ${this.total ? this.resourceStrings.results.format(this.total) : this.resourceStrings.results.format(0)}`; } /** * Update the action bar */ updateActionBar() { if (this.actionBarComponent) { this.actionBarComponent.updateActionBar(); } } /** * Handles clicking on the refresh button */ refreshButtonClicked() { if (this.disableRefresh) { return; } this.refresh.next(); } /** * Creates the idBag used by this master view to store unique element ids. * id values will be assigned be the @see MasterViewComponent super class. */ createIdBag() { return { filterLabel: '', columnPickerLabel: '', itemCountLabel: '' }; } handleDetailPaneExpanding(dataViewControl) { if (this.splitView) { let newDataSelection = null; newDataSelection = dataViewControl.renderedItems[dataViewControl.getActiveRenderedItemIndex()]; const hasItemSelected = !!newDataSelection; if (hasItemSelected && newDataSelection !== this.currentDataSelection) { if (!this.currentDataSelection || this.currentDataSelection.length === 0) { setTimeout(() => { if (!this.splitView.isExpanded) { this.splitView.togglePane(); } }); } } this.currentDataSelection = newDataSelection; } } setupDataTableAccessibility() { if (this.internalSmeDataTable) { if (this.header) { this.internalSmeDataTable.tableAriaLabelledBy = this.headerId; } else if (this.pivotComponent) { const selectedTab = this.pivotComponent.tabs.toArray().filter(item => this.pivotComponent.isSelected(item))[0]; if (selectedTab) { this.internalSmeDataTable.tableAriaLabel = selectedTab.label; } } } } } /** @nocollapse */ MasterViewComponent.ɵfac = function MasterViewComponent_Factory(t) { return new (t || MasterViewComponent)(i0.ɵɵdirectiveInject(i0.Injector), i0.ɵɵdirectiveInject(i0.ElementRef), i0.ɵɵdirectiveInject(i1.DataTableDownloadService, 8), i0.ɵɵdirectiveInject(i2.SplitViewComponent, 8), i0.ɵɵdirectiveInject(i3.PivotComponent, 8), i0.ɵɵdirectiveInject(SME_LAYOUT_PROVIDER, 12)); }; /** @nocollapse */ MasterViewComponent.ɵcmp = /** @pureOrBreakMyCode */ i0.ɵɵdefineComponent({ type: MasterViewComponent, selectors: [["sme-master-view"]], contentQueries: function MasterViewComponent_ContentQueries(rf, ctx, dirIndex) { if (rf & 1) { i0.ɵɵcontentQuery(dirIndex, _c0, 5); i0.ɵɵcontentQuery(dirIndex, ActionBarComponent, 5); i0.ɵɵcontentQuery(dirIndex, DataTableComponent, 5); i0.ɵɵcontentQuery(dirIndex, _c1, 5); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.searchElement = _t.first); i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.actionBarComponent = _t.first); i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.smeDataTable = _t.first); i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.smeTreeTable = _t.first); } }, viewQuery: function MasterViewComponent_Query(rf, ctx) { if (rf & 1) { i0.ɵɵviewQuery(_c2, 5); i0.ɵɵviewQuery(_c3, 5); i0.ɵɵviewQuery(MasterViewContentDirective, 5); } if (rf & 2) { let _t; i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.containerElement = _t.first); i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.dataView = _t.first); i0.ɵɵqueryRefresh(_t = i0.ɵɵloadQuery()) && (ctx.smeMasterViewContentDirective = _t.first); } }, inputs: { hideHeader: "hideHeader", header: "header", total: "total", showSelection: "showSelection", showColumnPicker: "showColumnPicker", showDownloadButton: "showDownloadButton", getDownloadContextParameters: "getDownloadContextParameters", columnPickerActive: "columnPickerActive", showRefresh: "showRefresh", disableRefresh: "disableRefresh", dataTableMinWidth: "dataTableMinWidth", showFilter: "showFilter", filterActive: "filterActive", downloadActive: "downloadActive", enableQueryEditor: "enableQueryEditor", selection: "selection", requireDataItemUniqueId: "requireDataItemUniqueId", showCustomFilter: "showCustomFilter", groupActive: "groupActive", stretchToAbsolute: "stretchToAbsolute", autoExpandDetailsPane: "autoExpandDetailsPane", showGroup: "showGroup", downloadDataType: "downloadDataType", refreshTooltipText: "refreshTooltipText" }, outputs: { selectionChange: "selectionChange", downloadPrompted: "downloadPrompted", downloadFinished: "downloadFinished", columnPicker: "columnPicker", refresh: "refresh", filter: "filter", group: "group", clearSelection: "clearSelection", smeDataTableFromTemplateReady: "smeDataTableFromTemplateReady", layoutChanged: "layoutChanged", windowBreakpointChanged: "windowBreakpointChanged" }, features: [i0.ɵɵProvidersFeature([ { provide: SME_LAYOUT_PROVIDER, useExisting: forwardRef((() => MasterViewComponent)) } ]), i0.ɵɵInheritDefinitionFeature, i0.ɵɵNgOnChangesFeature], ngContentSelectors: _c5, decls: 25, vars: 36, consts: [["class", "sme-position-flex-none sme-padding-squish-v-lg sme-arrange-word-wrap-break-word sme-font-h3", 3, "hidden", "id", 4, "ngIf"], [3, "layoutChanged"], ["layout", ""], ["name", "narrow", 3, "until"], ["class", "sme-position-flex-none", 3, "sme-padding-horizontal-sm", 4, "ngIf"], [1, "sme-position-flex-none", "sme-arrange-stack-reversed"], ["container", ""], [1, "sme-position-flex-none", "sme-arrange-stack-h"], [1, "sme-focus-zone", "sme-position-flex-none", "sme-arrange-stack-h", "sme-arrange-ws-nowrap", "sme-scheme-secondary-text"], ["role", "status", 1, "sme-layout-action-bar-item", "sme-padding-horizontal-sm", 3, "id"], ["type", "button", "role", "button", "class", "sme-button-trigger sme-layout-action-bar-item-height sme-scheme-secondary-text sme-button-auto-width", 3, "click", 4, "ngIf"], [1, "sme-focus-zone", "sme-arrange-ws-nowrap"], ["type", "button", "role", "button", "title", "Download", "class", "sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width", "data-uta-id", "download-button", 3, "sme-toggled", "click", 4, "ngIf"], ["type", "button", "role", "button", "class", "sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width", "data-uta-id", "column-picker-button", 3, "title", "sme-toggled", "click", 4, "ngIf"], ["aria-live", "polite", "type", "button", "role", "button", "class", "sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width", 3, "title", "click", 4, "ngIf"], ["type", "button", "role", "button", "class", "sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width", 3, "title", "sme-toggled", "click", 4, "ngIf"], [1, "sme-focus-zone"], ["class", "sme-margin-horizontal-sm", 4, "ngIf"], ["style", "position: relative;", 4, "ngIf"], ["smeMasterViewContentDirective", "", 3, "smeDataTableFromTemplateReady"], ["dataView", ""], [1, "sme-position-flex-none", "sme-padding-squish-v-lg", "sme-arrange-word-wrap-break-word", "sme-font-h3", 3, "hidden", "id"], [1, "sme-position-flex-none"], ["type", "button", "role", "button", 1, "sme-button-trigger", "sme-layout-action-bar-item-height", "sme-scheme-secondary-text", "sme-button-auto-width", 3, "click"], ["aria-hidden", "true"], [1, "sme-screen-reader"], ["aria-hidden", "true", 1, "sme-icon", "sme-icon-clear", "sme-margin-left-xs", 3, "title"], ["type", "button", "role", "button", "title", "Download", "data-uta-id", "download-button", 1, "sme-layout-action-bar-item-height", "sme-button-trigger", "sme-button-auto-width", 3, "click"], [1, "sme-icon", "sme-icon-download"], ["type", "button", "role", "button", "data-uta-id", "column-picker-button", 1, "sme-layout-action-bar-item-height", "sme-button-trigger", "sme-button-auto-width", 3, "title", "click"], [1, "sme-icon", "sme-icon-tripleColumn"], ["aria-live", "polite", "type", "button", "role", "button", 1, "sme-layout-action-bar-item-height", "sme-button-trigger", "sme-button-auto-width", 3, "title", "click"], [1, "sme-icon", "sme-icon-refresh"], ["type", "button", "role", "button", 1, "sme-layout-action-bar-item-height", "sme-button-trigger", "sme-button-auto-width", 3, "title", "click"], [1, "sme-icon", "sme-icon-filter"], [1, "sme-icon", "sme-icon-groupedList"], [1, "sme-margin-horizontal-sm"], [2, "position", "relative"], [1, "sme-position-flex-none", "sme-layout-action-bar-item"]], template: function MasterViewComponent_Template(rf, ctx) { if (rf & 1) { i0.ɵɵprojectionDef(_c4); i0.ɵɵtemplate(0, MasterViewComponent_h2_0_Template, 2, 3, "h2", 0); i0.ɵɵelementStart(1, "sme-layout", 1, 2); i0.ɵɵlistener("layoutChanged", function MasterViewComponent_Template_sme_layout_layoutChanged_1_listener() { return ctx.updateActionBar(); }); i0.ɵɵelement(3, "sme-layout-definition", 3); i0.ɵɵelementEnd(); i0.ɵɵtemplate(4, MasterViewComponent_div_4_Template, 2, 2, "div", 4); i0.ɵɵelementStart(5, "div", 5, 6); i0.ɵɵprojection(7); i0.ɵɵelementStart(8, "div", 7)(9, "div", 8)(10, "i", 9); i0.ɵɵtext(11); i0.ɵɵelementEnd(); i0.ɵɵtemplate(12, MasterViewComponent_button_12_Template, 6, 3, "button", 10); i0.ɵɵelementEnd(); i0.ɵɵelementStart(13, "div", 11); i0.ɵɵtemplate(14, MasterViewComponent_button_14_Template, 2, 2, "button", 12); i0.ɵɵtemplate(15, MasterViewComponent_button_15_Template, 2, 4, "button", 13); i0.ɵɵtemplate(16, MasterViewComponent_button_16_Template, 2, 3, "button", 14); i0.ɵɵtemplate(17, MasterViewComponent_button_17_Template, 2, 4, "button", 15); i0.ɵɵtemplate(18, MasterViewComponent_button_18_Template, 2, 4, "button", 15); i0.ɵɵelementEnd(); i0.ɵɵelementStart(19, "div", 16); i0.ɵɵtemplate(20, MasterViewComponent_div_20_Template, 2, 0, "div", 17); i0.ɵɵelementEnd(); i0.ɵɵtemplate(21, MasterViewComponent_form_21_Template, 3, 0, "form", 18); i0.ɵɵelementEnd()(); i0.ɵɵelementStart(22, "div", 19, 20); i0.ɵɵlistener("smeDataTableFromTemplateReady", function MasterViewComponent_Template_div_smeDataTableFromTemplateReady_22_listener() { return ctx.onSmeDataTableFromTemplateReady(); }); i0.ɵɵprojection(24, 1); i0.ɵɵelementEnd(); } if (rf & 2) { const _r1 = i0.ɵɵreference(2); i0.ɵɵproperty("ngIf", ctx.header); i0.ɵɵadvance(3); i0.ɵɵproperty("until", 768); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.enableQueryEditor); i0.ɵɵadvance(1); i0.ɵɵclassProp("sme-padding-horizontal-sm", !ctx.noSideMargin)("sme-arrange-stack-h", !(_r1.currentLayoutDefinitionName === "narrow")); i0.ɵɵadvance(3); i0.ɵɵclassProp("sme-padding-horizontal-sm", !ctx.noSideMargin)("sme-padding-left-sm", ctx.noSideMargin)("sme-arrange-stack-wrap", ctx.searchBoxAutoWrapOnWindowSizeChanges); i0.ɵɵadvance(1); i0.ɵɵclassProp("sme-padding-right-xs", ctx.selectedItemCount === 0 || !ctx.showSelection); i0.ɵɵadvance(1); i0.ɵɵproperty("id", ctx.idBag.itemCountLabel); i0.ɵɵadvance(1); i0.ɵɵtextInterpolate(ctx.getItemCountText()); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.selectedItemCount > 0 && ctx.showSelection); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", ctx.showDownloadButton); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.showColumnPicker); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.showRefresh); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.showFilter); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.showGroup); i0.ɵɵadvance(2); i0.ɵɵproperty("ngIf", ctx.showCustomFilter); i0.ɵɵadvance(1); i0.ɵɵproperty("ngIf", ctx.useSearch); i0.ɵɵadvance(1); i0.ɵɵclassMapInterpolate1("sme-layout-relative sme-position-flex-auto sme-arrange-stack-h sme-layout-minwidth-", ctx.dataTableMinWidthClassString, ""); i0.ɵɵclassProp("sme-margin-horizontal-lg", ctx.shouldDataTableSlim)("sme-padding-bottom-md", ctx.shouldDataTableRenderWithBottomMargin)("sme-arrange-overflow-hide", ctx.shouldDataTableParentOverflowHide)("sme-shadow-scrolled-content", !ctx.isDataListScrolledToTop); } }, dependencies: [i4.NgIf, i5.LayoutComponent, i6.LayoutDefinitionComponent, i7.MasterViewContentDirective, i8.TooltipDirective], encapsulation: 2 }); __decorate([ Yield(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], MasterViewComponent.prototype, "onLayoutChanged", null); __decorate([ Debounce(), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], MasterViewComponent.prototype, "deferredOnLayoutChanged", null); (function () { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(MasterViewComponent, [{ type: Component, args: [{ selector: 'sme-master-view', providers: [ { provide: SME_LAYOUT_PROVIDER, useExisting: forwardRef((() => MasterViewComponent)) } ], template: "<h2 class=\"sme-position-flex-none sme-padding-squish-v-lg sme-arrange-word-wrap-break-word sme-font-h3\" *ngIf=\"header\"\r\n [hidden]=\"hideHeader\" [id]='headerId'>{{ header }}</h2>\r\n<sme-layout #layout (layoutChanged)=\"updateActionBar()\">\r\n <sme-layout-definition name=\"narrow\" [until]=\"768\"></sme-layout-definition>\r\n</sme-layout>\r\n<div *ngIf=\"enableQueryEditor\" class=\"sme-position-flex-none\" [class.sme-padding-horizontal-sm]=\"!noSideMargin\">\r\n <!-- Query Editor -->\r\n <ng-content select='sme-query-editor'></ng-content>\r\n</div>\r\n<div class=\"sme-position-flex-none sme-arrange-stack-reversed\" #container\r\n [class.sme-padding-horizontal-sm]=\"!noSideMargin\"\r\n [class.sme-arrange-stack-h]=\"!(layout.currentLayoutDefinitionName==='narrow')\">\r\n <!-- Actions -->\r\n <ng-content select='sme-action-bar,.action-bar'></ng-content>\r\n\r\n <div class=\"sme-position-flex-none sme-arrange-stack-h\" [class.sme-padding-horizontal-sm]=\"!noSideMargin\"\r\n [class.sme-padding-left-sm]=\"noSideMargin\" [class.sme-arrange-stack-wrap]=\"searchBoxAutoWrapOnWindowSizeChanges\">\r\n <!-- Counts -->\r\n <div\r\n class=\"sme-focus-zone sme-position-flex-none sme-arrange-stack-h sme-arrange-ws-nowrap sme-scheme-secondary-text\"\r\n [class.sme-padding-right-xs]=\"selectedItemCount === 0 || !showSelection\">\r\n <i role=\"status\" [id]=\"idBag.itemCountLabel\" class=\"sme-layout-action-bar-item sme-padding-horizontal-sm\">{{\r\n getItemCountText() }}</i>\r\n <button type=\"button\" role=\"button\"\r\n class=\"sme-button-trigger sme-layout-action-bar-item-height sme-scheme-secondary-text sme-button-auto-width\"\r\n *ngIf=\"selectedItemCount > 0 && showSelection\" (click)=\"doClearSelection($event)\">\r\n <i aria-hidden=\"true\">{{ getSelectedCountText() }}</i>\r\n <i class=\"sme-screen-reader\">{{ getSelectedCountAriaText() }}</i>\r\n <i aria-hidden=\"true\" class=\"sme-icon sme-icon-clear sme-margin-left-xs\"\r\n [title]=\"resourceStrings.selectedTitle\"></i>\r\n </button>\r\n </div>\r\n <!-- Common Actions -->\r\n <div class=\"sme-focus-zone sme-arrange-ws-nowrap\">\r\n <button *ngIf=\"showDownloadButton\" (click)=\"onDownloadButtonClicked($event)\" type=\"button\" role=\"button\"\r\n title=\"Download\" class=\"sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width\"\r\n [class.sme-toggled]=\"downloadActive\" data-uta-id=\"download-button\">\r\n <span class=\"sme-icon sme-icon-download\"></span>\r\n </button>\r\n <button *ngIf=\"showColumnPicker\" (click)=\"columnPicker.next();\" type=\"button\" role=\"button\"\r\n [title]=\"resourceStrings.columnPicker.title\" [attr.aria-label]=\"getFilterAriaLabel()\"\r\n class=\"sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width\"\r\n [class.sme-toggled]=\"columnPickerActive\" data-uta-id=\"column-picker-button\">\r\n <span class=\"sme-icon sme-icon-tripleColumn\"></span>\r\n </button>\r\n <button aria-live=\"polite\" *ngIf=\"showRefresh\" [attr.aria-disabled]=\"disableRefresh\"\r\n (click)=\"refreshButtonClicked()\" type=\"button\" role=\"button\" [title]=\"refreshTooltipText || resourceStrings.refresh.title\"\r\n [attr.aria-label]=\"refreshTooltipText || refreshButtonAriaLabel\"\r\n class=\"sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width\">\r\n <span class=\"sme-icon sme-icon-refresh\"></span>\r\n </button>\r\n <button *ngIf=\"showFilter\" (click)=\"filter.next();\" type=\"button\" role=\"button\"\r\n [title]=\"resourceStrings.filter.title\" [attr.aria-label]=\"getFilterAriaLabel()\"\r\n class=\"sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width\"\r\n [class.sme-toggled]=\"filterActive\">\r\n <span class=\"sme-icon sme-icon-filter\"></span>\r\n </button>\r\n <button *ngIf=\"showGroup\" (click)=\"group.next()\" type=\"button\" role=\"button\" [title]=\"resourceStrings.group.title\"\r\n [attr.aria-label]=\"resourceStrings.group.title\"\r\n class=\"sme-layout-action-bar-item-height sme-button-trigger sme-button-auto-width\"\r\n [class.sme-toggled]=\"groupActive\">\r\n <!-- TODO: use grouping icon when available. -->\r\n <span class=\"sme-icon sme-icon-groupedList\"></span>\r\n </button>\r\n </div>\r\n <!-- Grouping (Deprecated) -->\r\n <div class=\"sme-focus-zone\">\r\n <div *ngIf=\"showCustomFilter\" class=\"sme-margin-horizontal-sm\">\r\n <ng-content select='.sme-master-view-custom-filter'></ng-content>\r\n </div>\r\n </div>\r\n <!-- Search Box -->\r\n <form *ngIf=\"useSearch\" style=\"position: relative;\">\r\n <div class=\"sme-position-flex-none sme-layout-action-bar-item\">\r\n <ng-content select='sme-form-field[type=\"search\"]'></ng-content>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n<div #dataView smeMasterViewContentDirective (smeDataTableFromTemplateReady)=\"onSmeDataTableFromTemplateReady()\"\r\n [class.sme-margin-horizontal-lg]=\"shouldDataTableSlim\"\r\n [class.sme-padding-bottom-md]=\"shouldDataTableRenderWithBottomMargin\"\r\n [class.sme-arrange-overflow-hide]=\"shouldDataTableParentOverflowHide\"\r\n class=\"sme-layout-relative sme-position-flex-auto sme-arrange-stack-h sme-layout-minwidth-{{dataTableMinWidthClassString}}\"\r\n [class.sme-shadow-scrolled-content]=\"!isDataListScrolledToTop\">\r\n <ng-content></ng-content>\r\n</div>\r\n" }] }], function () { return [{ type: i0.Injector }, { type: i0.ElementRef }, { type: i1.DataTableDownloadService, decorators: [{ type: Optional }] }, { type: i2.SplitViewComponent, decorators: [{ type: Optional }] }, { type: i3.PivotComponent, decorators: [{ type: Optional }] }, { type: undefined, decorators: [{ type: SkipSelf }, { type: Optional }, { type: Inject, args: [SME_LAYOUT_PROVIDER] }] }]; }, { searchElement: [{ type: ContentChild, args: ['search'] }], actionBarComponent: [{ type: ContentChild, args: [ActionBarComponent] }], containerElement: [{ type: ViewChild, args: ['container'] }], dataView: [{ type: ViewChild, args: ['dataView'] }], smeMasterViewContentDirective: [{ type: ViewChild, args: [MasterViewContentDirective, { static: false }] }], smeDataTable: [{ type: ContentChild, args: [DataTableComponent] }], smeTreeTable: [{ type: ContentChild, args: ['smeTreeTable'] }], hideHeader: [{ type: Input }], header: [{ type: Input }], total: [{ type: Input }], showSelection: [{ type: Input }], showColumnPicker: [{ type: Input }], showDownloadButton: [{ type: Input }], getDownloadContextParameters: [{ type: Input }], columnPickerActive: [{ type: Input }], showRefresh: [{ type: Input }], disableRefresh: [{ type: Input }], dataTableMinWidth: [{ type: Input }], showFilter: [{ type: Input }], filterActive: [{ type: Input }], downloadActive: [{ type: Input }], enableQueryEditor: [{ type: Input }], selection: [{ type: Input }], selectionChange: [{ type: Output }], requireDataItemUniqueId: [{ type: Input }], showCustomFilter: [{ type: Input }], groupActive: [{ type: Input }], stretchToAbsolute: [{ type: Input }], autoExpandDetailsPane: [{ type: Input }], showGroup: [{ type: Input }], downloadDataType: [{ type: Input }], refreshTooltipText: [{ type: Input }], downloadPrompted: [{ type: Output }], downloadFinished: [{ type: Output }], columnPicker: [{ type: Output }], refresh: [{ type: Output }], filter: [{ type: Output }], group: [{ type: Output }], clearSelection: [{ type: Output }], smeDataTableFromTemplateReady: [{ type: Output }], layoutChanged: [{ type: Output }], windowBreakpointChanged: [{ type: Output }], onLayoutChanged: [], deferredOnLayoutChanged: [] }); })(); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFzdGVyLXZpZXcuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvbWFzdGVyLXZpZXcvbWFzdGVyLXZpZXcuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vYW5ndWxhci9zcmMvY29udHJvbHMvbWFzdGVyLXZpZXcvbWFzdGVyLXZpZXcuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFSCxTQUFTLEVBQ1QsWUFBWSxFQUVaLFVBQVUsRUFDVixZQUFZLEVBQ1osVUFBVSxFQUNWLE1BQU0sRUFDTixRQUFRLEVBQ1IsS0FBSyxFQUlMLFFBQVEsRUFDUixNQUFNLEVBRU4sUUFBUSxFQUNSLFNBQVMsRUFDWixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sOEVBQThFLENBQUM7QUFDeEcsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDBFQUEwRSxDQUFDO0FBQ2pHLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxnRUFBZ0UsQ0FBQztBQUMxRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sOERBQThELENBQUM7QUFDdkYsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGtEQUFrRCxDQUFDO0FBRXZFLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN0QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx1REFBdUQsQ0FBQztBQUMzRixPQUFPLEVBQVUsbUJBQW1CLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUMvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUN0RSxPQUFPLEVBQUUseUJBQXlCLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSwyQ0FBMkMsQ0FBQztBQUNoSCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM1RixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx1REFBdUQsQ0FBQztBQUNqRyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDMUQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7QUFDeEUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0scURBQXFELENBQUM7QUFDakcsT0FBTyxFQUFFLGlDQUFpQyxFQUFFLE1BQU0seUNBQXlDLENBQUM7Ozs7Ozs7Ozs7Ozs7OztJQ3BDNUYsOEJBQ3dDO0lBQUEsWUFBW