UNPKG

ontimize-web-ngx

Version:
359 lines 63.6 kB
import { __decorate, __metadata } from "tslib"; import { Component, ElementRef, EventEmitter, forwardRef, Inject, Injector, NgZone, QueryList, ViewChild, ViewChildren, ViewContainerRef, ViewEncapsulation } from '@angular/core'; import { MatTabGroup } from '@angular/material/tabs'; import { ActivatedRoute, Router } from '@angular/router'; import { BehaviorSubject, concatMap, delay, from, of, Subject, Subscription } from 'rxjs'; import { BooleanInputConverter } from '../../../decorators/input-converter'; import { DialogService } from '../../../services/dialog.service'; import { OFormLayoutManagerService } from '../../../services/o-form-layout-manager.service'; import { Codes } from '../../../util/codes'; import { Util } from '../../../util/util'; import { OFormLayoutManagerContentDirective } from '../directives/o-form-layout-manager-content.directive'; import { OFormLayoutManagerBase } from '../o-form-layout-manager-base.class'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "@angular/flex-layout/flex"; import * as i3 from "../../../directives/o-tab-group.directive"; import * as i4 from "@angular/material/icon"; import * as i5 from "@angular/material/progress-spinner"; import * as i6 from "@angular/material/tabs"; import * as i7 from "../directives/o-form-layout-manager-content.directive"; import * as i8 from "../../../pipes/o-translate.pipe"; import * as i9 from "../o-form-layout-manager-base.class"; export const DEFAULT_INPUTS_O_FORM_LAYOUT_TABGROUP = [ 'title', 'options', 'stretchTabs: stretch-tabs' ]; export const DEFAULT_OUTPUTS_O_FORM_LAYOUT_TABGROUP = [ 'onMainTabSelected', 'onSelectedTabChange', 'onCloseTab' ]; export class OFormLayoutTabGroupComponent { constructor(injector, location, elementRef, formLayoutManager) { this.injector = injector; this.location = location; this.elementRef = elementRef; this.formLayoutManager = formLayoutManager; this.data = []; this.showLoading = new BehaviorSubject(false); this.stretchTabs = false; this.subscriptions = new Subscription(); this.onMainTabSelected = new EventEmitter(); this.onSelectedTabChange = new EventEmitter(); this.onCloseTab = new EventEmitter(); this.updateTabComponentsState = new Subject(); this.tabsModificationsCache = []; this.dialogService = injector.get(DialogService); this.router = this.injector.get(Router); this.actRoute = this.injector.get(ActivatedRoute); } get state() { return this.formLayoutManager.state; } ngAfterViewInit() { this.initializeComponentState(); this.subscriptions.add(this.tabsDirectives.changes.subscribe(changes => { if (this.tabsDirectives.length) { const tabItem = this.tabsDirectives.last; const tabData = this.data[tabItem.index]; if (tabData && !tabData.rendered) { this.createTabComponent(tabData, tabItem); } } })); } ngOnDestroy() { if (this.subscriptions) { this.subscriptions.unsubscribe(); } } get mainTabTitle() { return (this.options.title || this.title || 'LAYOUT_MANANGER.MAIN_TAB_LABEL'); } get disableAnimation() { return this.options && this.options.disableAnimation; } get headerPosition() { let headerPosition; if (this.options && this.options.headerPosition) { headerPosition = this.options.headerPosition; } return headerPosition; } get color() { let color; if (this.options && this.options.color) { color = this.options.color; } return color; } get backgroundColor() { let backgroundColor; if (this.options && this.options.backgroundColor) { backgroundColor = this.options.backgroundColor; } return backgroundColor; } get templateMatTabLabel() { let templateMatTabLabel; if (this.options && this.options.templateMatTabLabel) { templateMatTabLabel = this.options.templateMatTabLabel; } return templateMatTabLabel; } get icon() { let icon; if (this.options && this.options.icon) { icon = this.options.icon; } return icon; } get isIconPositionLeft() { return this.options && this.options.iconPosition === 'left'; } get maxTabs() { let maxTabs; if (this.options && this.options.maxTabs) { maxTabs = this.options.maxTabs; } return maxTabs; } addTab(compData) { let addNewComp = true; if (compData.insertionMode) { const alreadyExistingInsertionTab = Util.isDefined(this.data.find(item => item.insertionMode)); addNewComp = !alreadyExistingInsertionTab; } const newCompParams = compData.params; if (addNewComp) { this.data.forEach(comp => { const currParams = comp.params || {}; let someDiffParams = true; if (Object.keys(currParams).length > 0) { someDiffParams = Object.keys(currParams).some(key => currParams[key] != newCompParams[key]); } addNewComp = addNewComp && someDiffParams; }); } if (addNewComp) { this.data.push(compData); } else { this.reloadTab(compData); } } reloadTab(compData) { let compIndex = -1; const compParams = compData.params; this.data.forEach((comp, i) => { const currParams = comp.params || {}; const sameParams = Util.isEquivalent(currParams, compParams); if (sameParams) { compIndex = i; } }); if (compIndex >= 0) { this.tabGroup.selectedIndex = (compIndex + 1); } compData.rendererSubject.next(true); } onTabSelectChange(arg) { if (this.formLayoutManager && this.tabGroup.selectedIndex === 0) { this.formLayoutManager.updateIfNeeded(); this.onMainTabSelected.emit(); } const isLoading = this.showLoading.getValue(); if (isLoading && Util.isDefined(this.state) && Util.isDefined(this.state.tabsData) && arg.index === this.state.tabsData.length - 1) { this.tabGroup.selectedIndex = this.state.selectedIndex; this.showLoading.next(false); } if (!isLoading) { this.onSelectedTabChange.emit({ data: this.data[this.tabGroup.selectedIndex - 1], index: this.tabGroup.selectedIndex, previousIndex: this.previousSelectedIndex }); } this.previousSelectedIndex = this.tabGroup.selectedIndex; } closeTab(index, options) { if (!this.formLayoutManager) { return; } const tabData = this.data[index]; const onCloseTabAccepted = new EventEmitter(); this.subscriptions.add(onCloseTabAccepted.asObservable().subscribe(res => { if (res) { this.data.splice(index, 1); this.onCloseTab.emit({ data: tabData, index: index + 1 }); } })); if (Util.isDefined(tabData) && this.formLayoutManager.hasToConfirmExit(tabData, options)) { this.dialogService.confirm('CONFIRM', 'MESSAGES.FORM_CHANGES_WILL_BE_LOST').then(res => { onCloseTabAccepted.emit(res); }); } else { onCloseTabAccepted.emit(true); } } createTabComponent(tabData, content) { const component = tabData.component; const viewContainerRef = content.viewContainerRef; viewContainerRef.clear(); viewContainerRef.createComponent(component); tabData.rendered = true; } getFormCacheData() { return this.data.length > 0 ? this.data[this.data.length - 1] : undefined; } getRouteOfActiveItem() { const route = []; if (this.data.length && this.tabGroup.selectedIndex > 0) { const urlSegments = this.data[this.tabGroup.selectedIndex - 1].urlSegments || []; urlSegments.forEach((segment) => { route.push(segment.path); }); return route; } return route; } setModifiedState(formAttr, modified, confirmExit) { if (this.tabGroup.selectedIndex > 0) { const selectedData = this.data[this.tabGroup.selectedIndex - 1]; if (Util.isDefined(selectedData)) { selectedData.innerFormsInfo[formAttr] = { modified: modified, confirmOnExit: confirmExit }; } } } updateNavigation(data, keysValues, insertionMode) { let index; if (insertionMode) { index = this.data.findIndex((item) => item.insertionMode !== false); } else { index = this.data.findIndex((item) => Object.keys(keysValues).every(key => keysValues[key] == item.params[key])); } if (index >= 0) { const oFormLayoutManagerService = this.injector.get(OFormLayoutManagerService); const context = oFormLayoutManagerService.context; let label = context?.label || this.formLayoutManager.getLabelFromData(data); this.tabGroup.selectedIndex = (index + 1); label = label.length ? label : this.formLayoutManager.getLabelFromUrlParams(this.data[index].params); this.data[index].label = label; this.data[index].insertionMode = insertionMode; if (Object.keys(data).length > 0) { this.data[index].formDataByLabelColumns = this.formLayoutManager.getFormDataFromLabelColumns(data); } } } updateActiveData(data) { const index = this.tabGroup.selectedIndex - 1; if (Util.isDefined(this.data[index])) { this.data[index] = Object.assign(this.data[index], data); } } getDataToStore() { const tabsData = this.data .filter((data) => !data.insertionMode) .map((data) => ({ params: data.params, queryParams: data.queryParams, urlSegments: data.urlSegments, url: data.url, label: data.label, insertionMode: data.insertionMode })); return { tabsData: tabsData, selectedIndex: this.tabGroup.selectedIndex }; } initializeComponentState() { if (!Util.isDefined(this.state) || !Util.isDefined(this.state.tabsData)) { return; } this.state.tabsData = this.state.tabsData.filter(tabData => !tabData.insertionMode); if (this.state.tabsData.length >= 1 && (this.state.tabsData[0].url || '').length > 0) { this.showLoading.next(true); const zone = this.injector.get(NgZone); from(this.state.tabsData).pipe(concatMap(tab => of(tab).pipe(delay(100)))).subscribe((tab) => { const extras = {}; extras['relativeTo'] = this.actRoute; extras[Codes.QUERY_PARAMS] = tab.queryParams; extras[Codes.QUERY_PARAMS][Codes.INSERTION_MODE] = tab.insertionMode; if (this.formLayoutManager) { this.formLayoutManager.setAsActiveFormLayoutManager(); } zone.run(() => this.router.navigate([tab.url], extras) .then(() => this.showLoading.next(false)) .catch(() => this.showLoading.next(true))); }); } } getParams() { return Util.isDefined(this.data[0]) ? this.data[0].params : undefined; } isMainComponent(comp) { const firstTab = this.elementRef.nativeElement.getElementsByTagName('mat-tab-body')[0]; return firstTab && comp.elementRef && firstTab.contains(comp.elementRef.nativeElement); } openDetail(detail) { this.addTab(detail); } closeDetail(options) { this.closeTab(this.tabGroup.selectedIndex - 1, options); } canAddDetailComponent() { const maxReached = (this.data.length + 1) >= this.maxTabs; if (maxReached) { this.dialogService.info('INFO', 'LAYOUT_MANANGER.MAX_TABS_NUMBER_REACHED'); } return !maxReached; } isTabDataModified(tabData) { return Object.keys(tabData.innerFormsInfo).some(formAttr => tabData.innerFormsInfo[formAttr].modified); } closeDetails(detailsKeysData = [], options) { detailsKeysData.forEach((detailData) => { const index = this.data.findIndex((item) => Util.isEquivalent(detailData, item.params || {})); if (index !== -1) { this.closeTab(index, options); } }); } getIdOfActiveItem() { return this.data[this.data.length - 1] ? this.data[this.data.length - 1].id : this.data.length.toString(); } } OFormLayoutTabGroupComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OFormLayoutTabGroupComponent, deps: [{ token: i0.Injector }, { token: i0.ViewContainerRef }, { token: i0.ElementRef }, { token: forwardRef(() => OFormLayoutManagerBase) }], target: i0.ɵɵFactoryTarget.Component }); OFormLayoutTabGroupComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: OFormLayoutTabGroupComponent, selector: "o-form-layout-tabgroup", inputs: { title: "title", options: "options", stretchTabs: ["stretch-tabs", "stretchTabs"] }, outputs: { onMainTabSelected: "onMainTabSelected", onSelectedTabChange: "onSelectedTabChange", onCloseTab: "onCloseTab" }, host: { properties: { "class.o-form-layout-tabgroup": "true" } }, viewQueries: [{ propertyName: "tabGroup", first: true, predicate: ["tabGroup"], descendants: true }, { propertyName: "tabsDirectives", predicate: OFormLayoutManagerContentDirective, descendants: true }], ngImport: i0, template: "<mat-tab-group #tabGroup oTabGroup=\"ontimize\" fxFill (selectedTabChange)=\"onTabSelectChange($event)\" [color]=\"color\"\n [backgroundColor]=\"backgroundColor\" [headerPosition]=\"headerPosition\" [@.disabled]=\"disableAnimation\" [mat-stretch-tabs]=\"stretchTabs\">\n <mat-tab label=\"{{ mainTabTitle | oTranslate }}\">\n <ng-content></ng-content>\n </mat-tab>\n <mat-tab *ngFor=\"let tabData of data; let i = index\">\n <ng-template mat-tab-label>\n <span class=\"tab-label\" [class.modified]=\"isTabDataModified(tabData)\">\n <ng-container *ngIf=\"icon && isIconPositionLeft\">\n <mat-icon>{{ icon }}</mat-icon>\n </ng-container>\n <ng-container *ngIf=\"templateMatTabLabel && tabData.formDataByLabelColumns && !tabData.insertionMode \">\n <ng-container *ngTemplateOutlet=\"templateMatTabLabel;context:{$implicit:tabData.formDataByLabelColumns}\">\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!templateMatTabLabel || tabData.insertionMode\">\n {{ tabData.label }}\n </ng-container>\n <ng-container *ngIf=\"icon && !isIconPositionLeft\">\n <mat-icon>{{ icon }}</mat-icon>\n </ng-container>\n <span class=\"gradient-layer\"></span>\n </span>\n <mat-icon (click)=\"closeTab(i)\" svgIcon=\"ontimize:close\"></mat-icon>\n </ng-template>\n <ng-template o-form-layout-manager-content [index]=\"i\"></ng-template>\n </mat-tab>\n</mat-tab-group>\n<div *ngIf=\"showLoading | async\" class=\"spinner-container\" fxLayout=\"column\" fxLayoutAlign=\"center center\">\n <mat-progress-spinner mode=\"indeterminate\" strokeWidth=\"3\"></mat-progress-spinner>\n</div>\n", styles: [".o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.mdc-tab__ripple{display:none}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.tab-label{width:100%;max-width:120px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.tab-label.modified{font-weight:700}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.tab-label.modified:after{content:\"*\"}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab .mat-icon{height:14px;width:14px;min-width:14px;font-size:8px;margin-left:6px;vertical-align:middle}.o-form-layout-tabgroup .mat-mdc-tab-group .mat-mdc-tab-body-wrapper{flex:1 1 auto}.o-form-layout-tabgroup .mat-mdc-tab-group o-form-toolbar{padding:0;top:0px!important}.o-form-layout-tabgroup .mat-mdc-tab-group o-form-toolbar .mat-toolbar{box-shadow:none;border-radius:0}.o-form-layout-tabgroup>.spinner-container{position:absolute;top:0;left:0;right:0;bottom:0;z-index:500;visibility:visible;opacity:1;transition:opacity .25s linear}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { kind: "directive", type: i2.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }, { kind: "directive", type: i2.FlexFillDirective, selector: "[fxFill], [fxFlexFill]" }, { kind: "directive", type: i3.OTabGroupDirective, selector: "[oTabGroup]", inputs: ["oTabGroup"] }, { kind: "component", type: i4.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i6.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i6.MatTab, selector: "mat-tab", inputs: ["disabled"], exportAs: ["matTab"] }, { kind: "component", type: i6.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "disableRipple", "fitInkBarToContent", "mat-stretch-tabs"], exportAs: ["matTabGroup"] }, { kind: "directive", type: i7.OFormLayoutManagerContentDirective, selector: "[o-form-layout-manager-content]", inputs: ["index"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.OTranslatePipe, name: "oTranslate" }], encapsulation: i0.ViewEncapsulation.None }); __decorate([ BooleanInputConverter(), __metadata("design:type", Boolean) ], OFormLayoutTabGroupComponent.prototype, "stretchTabs", void 0); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: OFormLayoutTabGroupComponent, decorators: [{ type: Component, args: [{ selector: 'o-form-layout-tabgroup', inputs: DEFAULT_INPUTS_O_FORM_LAYOUT_TABGROUP, outputs: DEFAULT_OUTPUTS_O_FORM_LAYOUT_TABGROUP, encapsulation: ViewEncapsulation.None, host: { '[class.o-form-layout-tabgroup]': 'true' }, template: "<mat-tab-group #tabGroup oTabGroup=\"ontimize\" fxFill (selectedTabChange)=\"onTabSelectChange($event)\" [color]=\"color\"\n [backgroundColor]=\"backgroundColor\" [headerPosition]=\"headerPosition\" [@.disabled]=\"disableAnimation\" [mat-stretch-tabs]=\"stretchTabs\">\n <mat-tab label=\"{{ mainTabTitle | oTranslate }}\">\n <ng-content></ng-content>\n </mat-tab>\n <mat-tab *ngFor=\"let tabData of data; let i = index\">\n <ng-template mat-tab-label>\n <span class=\"tab-label\" [class.modified]=\"isTabDataModified(tabData)\">\n <ng-container *ngIf=\"icon && isIconPositionLeft\">\n <mat-icon>{{ icon }}</mat-icon>\n </ng-container>\n <ng-container *ngIf=\"templateMatTabLabel && tabData.formDataByLabelColumns && !tabData.insertionMode \">\n <ng-container *ngTemplateOutlet=\"templateMatTabLabel;context:{$implicit:tabData.formDataByLabelColumns}\">\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"!templateMatTabLabel || tabData.insertionMode\">\n {{ tabData.label }}\n </ng-container>\n <ng-container *ngIf=\"icon && !isIconPositionLeft\">\n <mat-icon>{{ icon }}</mat-icon>\n </ng-container>\n <span class=\"gradient-layer\"></span>\n </span>\n <mat-icon (click)=\"closeTab(i)\" svgIcon=\"ontimize:close\"></mat-icon>\n </ng-template>\n <ng-template o-form-layout-manager-content [index]=\"i\"></ng-template>\n </mat-tab>\n</mat-tab-group>\n<div *ngIf=\"showLoading | async\" class=\"spinner-container\" fxLayout=\"column\" fxLayoutAlign=\"center center\">\n <mat-progress-spinner mode=\"indeterminate\" strokeWidth=\"3\"></mat-progress-spinner>\n</div>\n", styles: [".o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.mdc-tab__ripple{display:none}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.tab-label{width:100%;max-width:120px;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.tab-label.modified{font-weight:700}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab span.tab-label.modified:after{content:\"*\"}.o-form-layout-tabgroup .mat-mdc-tab-group .mdc-tab .mat-icon{height:14px;width:14px;min-width:14px;font-size:8px;margin-left:6px;vertical-align:middle}.o-form-layout-tabgroup .mat-mdc-tab-group .mat-mdc-tab-body-wrapper{flex:1 1 auto}.o-form-layout-tabgroup .mat-mdc-tab-group o-form-toolbar{padding:0;top:0px!important}.o-form-layout-tabgroup .mat-mdc-tab-group o-form-toolbar .mat-toolbar{box-shadow:none;border-radius:0}.o-form-layout-tabgroup>.spinner-container{position:absolute;top:0;left:0;right:0;bottom:0;z-index:500;visibility:visible;opacity:1;transition:opacity .25s linear}\n"] }] }], ctorParameters: function () { return [{ type: i0.Injector }, { type: i0.ViewContainerRef }, { type: i0.ElementRef }, { type: i9.OFormLayoutManagerBase, decorators: [{ type: Inject, args: [forwardRef(() => OFormLayoutManagerBase)] }] }]; }, propDecorators: { stretchTabs: [], tabGroup: [{ type: ViewChild, args: ['tabGroup'] }], tabsDirectives: [{ type: ViewChildren, args: [OFormLayoutManagerContentDirective] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiby1mb3JtLWxheW91dC10YWJncm91cC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9vbnRpbWl6ZS13ZWItbmd4L3NyYy9saWIvbGF5b3V0cy9mb3JtLWxheW91dC90YWJncm91cC9vLWZvcm0tbGF5b3V0LXRhYmdyb3VwLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL29udGltaXplLXdlYi1uZ3gvc3JjL2xpYi9sYXlvdXRzL2Zvcm0tbGF5b3V0L3RhYmdyb3VwL28tZm9ybS1sYXlvdXQtdGFiZ3JvdXAuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFFTCxTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsTUFBTSxFQUNOLFFBQVEsRUFDUixNQUFNLEVBRU4sU0FBUyxFQUNULFNBQVMsRUFDVCxZQUFZLEVBQ1osZ0JBQWdCLEVBQ2hCLGlCQUFpQixFQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXFCLFdBQVcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFFLGVBQWUsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUUxRixPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUc1RSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDakUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0saURBQWlELENBQUM7QUFHNUYsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxJQUFJ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S0FBSyxDQUFDLENBQUMsRUFBRTtnQkFDaEIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7YUFDL0I7UUFDSCxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRCxpQkFBaUI7UUFDZixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUM1RyxDQUFDOzswSEFqWFUsNEJBQTRCLG9HQTZCN0IsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLHNCQUFzQixDQUFDOzhHQTdCdkMsNEJBQTRCLG1kQVN6QixrQ0FBa0MsZ0RDaEVsRCxtckRBK0JBO0FEOEJFO0lBQUMscUJBQXFCLEVBQUU7O2lFQUNZOzRGQVB6Qiw0QkFBNEI7a0JBWHhDLFNBQVM7K0JBQ0Usd0JBQXdCLFVBQzFCLHFDQUFxQyxXQUNwQyxzQ0FBc0MsaUJBR2hDLGlCQUFpQixDQUFDLElBQUksUUFDL0I7d0JBQ0osZ0NBQWdDLEVBQUUsTUFBTTtxQkFDekM7OzBCQStCRSxNQUFNOzJCQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQzs0Q0F0QjNDLFdBQVcsTUFDSyxRQUFRO3NCQUE5QixTQUFTO3VCQUFDLFVBQVU7Z0JBQzZCLGNBQWM7c0JBQS9ELFlBQVk7dUJBQUMsa0NBQWtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJWaWV3SW5pdCxcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIEluamVjdCxcbiAgSW5qZWN0b3IsXG4gIE5nWm9uZSxcbiAgT25EZXN0cm95LFxuICBRdWVyeUxpc3QsXG4gIFZpZXdDaGlsZCxcbiAgVmlld0NoaWxkcmVuLFxuICBWaWV3Q29udGFpbmVyUmVmLFxuICBWaWV3RW5jYXBzdWxhdGlvblxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IE1hdFRhYkNoYW5nZUV2ZW50LCBNYXRUYWJHcm91cCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3RhYnMnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUsIFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QsIGNvbmNhdE1hcCwgZGVsYXksIGZyb20sIG9mLCBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgQm9vbGVhbklucHV0Q29udmVydGVyIH0gZnJvbSAnLi4vLi4vLi4vZGVjb3JhdG9ycy9pbnB1dC1jb252ZXJ0ZXInO1xuaW1wb3J0IHsgSUxheW91dE1hbmFnZXJDb21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9pbnRlcmZhY2VzL2xheW91dC1tYW5hZ2VyLWNvbXBvbmVudC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgT0Zvcm1MYXlvdXRNYW5hZ2VyTW9kZSB9IGZyb20gJy4uLy4uLy4uL2ludGVyZmFjZXMvby1mb3JtLWxheW91dC1tYW5hZ2VyLW1vZGUuaW50ZXJmYWNlJztcbmltcG9ydCB7IERpYWxvZ1NlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9kaWFsb2cuc2VydmljZSc7XG5pbXBvcnQgeyBPRm9ybUxheW91dE1hbmFnZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvby1mb3JtLWxheW91dC1tYW5hZ2VyLnNlcnZpY2UnO1xuaW1wb3J0IHsgT0Zvcm1MYXlvdXRNYW5hZ2VyQ29tcG9uZW50U3RhdGVDbGFzcyB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL3N0YXRlL28tZm9ybS1sYXlvdXQtbWFuYWdlci1jb21wb25lbnQtc3RhdGUuY2xhc3MnO1xuaW1wb3J0IHsgRm9ybUxheW91dENsb3NlRGV0YWlsT3B0aW9ucywgRm9ybUxheW91dERldGFpbENvbXBvbmVudERhdGEgfSBmcm9tICcuLi8uLi8uLi90eXBlcy9mb3JtLWxheW91dC1kZXRhaWwtY29tcG9uZW50LWRhdGEudHlwZSc7XG5pbXBvcnQgeyBDb2RlcyB9IGZyb20gJy4uLy4uLy4uL3V0aWwvY29kZXMnO1xuaW1wb3J0IHsgVXRpbCB9IGZyb20gJy4uLy4uLy4uL3V0aWwvdXRpbCc7XG5pbXBvcnQgeyBPRm9ybUxheW91dE1hbmFnZXJDb250ZW50RGlyZWN0aXZlIH0gZnJvbSAnLi4vZGlyZWN0aXZlcy9vLWZvcm0tbGF5b3V0LW1hbmFnZXItY29udGVudC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgT0Zvcm1MYXlvdXRNYW5hZ2VyQmFzZSB9IGZyb20gJy4uL28tZm9ybS1sYXlvdXQtbWFuYWdlci1iYXNlLmNsYXNzJztcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfSU5QVVRTX09fRk9STV9MQVlPVVRfVEFCR1JPVVAgPSBbXG4gICd0aXRsZScsXG4gICdvcHRpb25zJyxcbiAgJ3N0cmV0Y2hUYWJzOiBzdHJldGNoLXRhYnMnXG5dO1xuXG5leHBvcnQgY29uc3QgREVGQVVMVF9PVVRQVVRTX09fRk9STV9MQVlPVVRfVEFCR1JPVVAgPSBbXG4gICdvbk1haW5UYWJTZWxlY3RlZCcsXG4gICdvblNlbGVjdGVkVGFiQ2hhbmdlJyxcbiAgJ29uQ2xvc2VUYWInXG5dO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdvLWZvcm0tbGF5b3V0LXRhYmdyb3VwJyxcbiAgaW5wdXRzOiBERUZBVUxUX0lOUFVUU19PX0ZPUk1fTEFZT1VUX1RBQkdST1VQLFxuICBvdXRwdXRzOiBERUZBVUxUX09VVFBVVFNfT19GT1JNX0xBWU9VVF9UQUJHUk9VUCxcbiAgdGVtcGxhdGVVcmw6ICcuL28tZm9ybS1sYXlvdXQtdGFiZ3JvdXAuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9vLWZvcm0tbGF5b3V0LXRhYmdyb3VwLmNvbXBvbmVudC5zY3NzJ10sXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGhvc3Q6IHtcbiAgICAnW2NsYXNzLm8tZm9ybS1sYXlvdXQtdGFiZ3JvdXBdJzogJ3RydWUnXG4gIH1cbn0pXG5leHBvcnQgY2xhc3MgT0Zvcm1MYXlvdXRUYWJHcm91cENvbXBvbmVudCBpbXBsZW1lbnRzIE9Gb3JtTGF5b3V0TWFuYWdlck1vZGUsIEFmdGVyVmlld0luaXQsIE9uRGVzdHJveSB7XG5cbiAgcHVibGljIGRhdGE6IEZvcm1MYXlvdXREZXRhaWxDb21wb25lbnREYXRhW10gPSBbXTtcbiAgcHVibGljIHRpdGxlOiBzdHJpbmc7XG4gIHB1YmxpYyBvcHRpb25zOiBhbnk7XG4gIHB1YmxpYyBzaG93TG9hZGluZyA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Ym9vbGVhbj4oZmFsc2UpO1xuICBAQm9vbGVhbklucHV0Q29udmVydGVyKClcbiAgcHVibGljIHN0cmV0Y2hUYWJzOiBib29sZWFuID0gZmFsc2U7XG4gIEBWaWV3Q2hpbGQoJ3RhYkdyb3VwJykgdGFiR3JvdXA6IE1hdFRhYkdyb3VwO1xuICBAVmlld0NoaWxkcmVuKE9Gb3JtTGF5b3V0TWFuYWdlckNvbnRlbnREaXJlY3RpdmUpIHRhYnNEaXJlY3RpdmVzOiBRdWVyeUxpc3Q8T0Zvcm1MYXlvdXRNYW5hZ2VyQ29udGVudERpcmVjdGl2ZT47XG5cbiAgcHJvdGVjdGVkIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgcHJvdGVjdGVkIHJvdXRlcjogUm91dGVyO1xuICBwcm90ZWN0ZWQgZGlhbG9nU2VydmljZTogRGlhbG9nU2VydmljZTtcblxuICBwdWJsaWMgb25NYWluVGFiU2VsZWN0ZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIHB1YmxpYyBvblNlbGVjdGVkVGFiQ2hhbmdlOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICBwdWJsaWMgb25DbG9zZVRhYjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBwcm90ZWN0ZWQgcHJldmlvdXNTZWxlY3RlZEluZGV4OiBudW1iZXI7XG5cbiAgcHVibGljIHVwZGF0ZVRhYkNvbXBvbmVudHNTdGF0ZSA9IG5ldyBTdWJqZWN0PGFueT4oKTtcbiAgcHVibGljIHRhYnNNb2RpZmljYXRpb25zQ2FjaGU6IGFueVtdID0gW107XG4gIGFjdFJvdXRlOiBBY3RpdmF0ZWRSb3V0ZTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgaW5qZWN0b3I6IEluamVjdG9yLFxuICAgIHByb3RlY3RlZCBsb2NhdGlvbjogVmlld0NvbnRhaW5lclJlZixcbiAgICBwcm90ZWN0ZWQgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICBASW5qZWN0KGZvcndhcmRSZWYoKCkgPT4gT0Zvcm1MYXlvdXRNYW5hZ2VyQmFzZSkpIHB1YmxpYyBmb3JtTGF5b3V0TWFuYWdlcjogT0Zvcm1MYXlvdXRNYW5hZ2VyQmFzZVxuICApIHtcbiAgICB0aGlzLmRpYWxvZ1NlcnZpY2UgPSBpbmplY3Rvci5nZXQoRGlhbG9nU2VydmljZSk7XG4gICAgdGhpcy5yb3V0ZXIgPSB0aGlzLmluamVjdG9yLmdldChSb3V0ZXIpO1xuICAgIHRoaXMuYWN0Um91dGUgPSB0aGlzLmluamVjdG9yLmdldChBY3RpdmF0ZWRSb3V0ZSk7XG4gIH1cblxuICBnZXQgc3RhdGUoKTogT0Zvcm1MYXlvdXRNYW5hZ2VyQ29tcG9uZW50U3RhdGVDbGFzcyB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybUxheW91dE1hbmFnZXIuc3RhdGU7XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgdGhpcy5pbml0aWFsaXplQ29tcG9uZW50U3RhdGUoKTtcblxuICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5hZGQodGhpcy50YWJzRGlyZWN0aXZlcy5jaGFuZ2VzLnN1YnNjcmliZShjaGFuZ2VzID0+IHtcbiAgICAgIGlmICh0aGlzLnRhYnNEaXJlY3RpdmVzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCB0YWJJdGVtID0gdGhpcy50YWJzRGlyZWN0aXZlcy5sYXN0O1xuICAgICAgICBjb25zdCB0YWJEYXRhID0gdGhpcy5kYXRhW3RhYkl0ZW0uaW5kZXhdO1xuICAgICAgICBpZiAodGFiRGF0YSAmJiAhdGFiRGF0YS5yZW5kZXJlZCkge1xuICAgICAgICAgIHRoaXMuY3JlYXRlVGFiQ29tcG9uZW50KHRhYkRhdGEsIHRhYkl0ZW0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSkpO1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuc3Vic2NyaXB0aW9ucykge1xuICAgICAgdGhpcy5zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCBtYWluVGFiVGl0bGUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gKHRoaXMub3B0aW9ucy50aXRsZSB8fCB0aGlzLnRpdGxlIHx8ICdMQVlPVVRfTUFOQU5HRVIuTUFJTl9UQUJfTEFCRUwnKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgZGlzYWJsZUFuaW1hdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5kaXNhYmxlQW5pbWF0aW9uO1xuICB9XG5cbiAgcHVibGljIGdldCBoZWFkZXJQb3NpdGlvbigpIHtcbiAgICBsZXQgaGVhZGVyUG9zaXRpb247XG4gICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuaGVhZGVyUG9zaXRpb24pIHtcbiAgICAgIGhlYWRlclBvc2l0aW9uID0gdGhpcy5vcHRpb25zLmhlYWRlclBvc2l0aW9uO1xuICAgIH1cbiAgICByZXR1cm4gaGVhZGVyUG9zaXRpb247XG4gIH1cblxuICBwdWJsaWMgZ2V0IGNvbG9yKCkge1xuICAgIGxldCBjb2xvcjtcbiAgICBpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5jb2xvcikge1xuICAgICAgY29sb3IgPSB0aGlzLm9wdGlvbnMuY29sb3I7XG4gICAgfVxuICAgIHJldHVybiBjb2xvcjtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgYmFja2dyb3VuZENvbG9yKCkge1xuICAgIGxldCBiYWNrZ3JvdW5kQ29sb3I7XG4gICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuYmFja2dyb3VuZENvbG9yKSB7XG4gICAgICBiYWNrZ3JvdW5kQ29sb3IgPSB0aGlzLm9wdGlvbnMuYmFja2dyb3VuZENvbG9yO1xuICAgIH1cbiAgICByZXR1cm4gYmFja2dyb3VuZENvbG9yO1xuICB9XG5cbiAgcHVibGljIGdldCB0ZW1wbGF0ZU1hdFRhYkxhYmVsKCkge1xuICAgIGxldCB0ZW1wbGF0ZU1hdFRhYkxhYmVsO1xuICAgIGlmICh0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLnRlbXBsYXRlTWF0VGFiTGFiZWwpIHtcbiAgICAgIHRlbXBsYXRlTWF0VGFiTGFiZWwgPSB0aGlzLm9wdGlvbnMudGVtcGxhdGVNYXRUYWJMYWJlbDtcbiAgICB9XG4gICAgcmV0dXJuIHRlbXBsYXRlTWF0VGFiTGFiZWw7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGljb24oKSB7XG4gICAgbGV0IGljb247XG4gICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMuaWNvbikge1xuICAgICAgaWNvbiA9IHRoaXMub3B0aW9ucy5pY29uO1xuICAgIH1cbiAgICByZXR1cm4gaWNvbjtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgaXNJY29uUG9zaXRpb25MZWZ0KCkge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnMgJiYgdGhpcy5vcHRpb25zLmljb25Qb3NpdGlvbiA9PT0gJ2xlZnQnO1xuICB9XG5cbiAgZ2V0IG1heFRhYnMoKTogbnVtYmVyIHtcbiAgICBsZXQgbWF4VGFicztcbiAgICBpZiAodGhpcy5vcHRpb25zICYmIHRoaXMub3B0aW9ucy5tYXhUYWJzKSB7XG4gICAgICBtYXhUYWJzID0gdGhpcy5vcHRpb25zLm1heFRhYnM7XG4gICAgfVxuICAgIHJldHVybiBtYXhUYWJzO1xuICB9XG5cbiAgYWRkVGFiKGNvbXBEYXRhOiBGb3JtTGF5b3V0RGV0YWlsQ29tcG9uZW50RGF0YSkge1xuICAgIGxldCBhZGROZXdDb21wID0gdHJ1ZTtcbiAgICBpZiAoY29tcERhdGEuaW5zZXJ0aW9uTW9kZSkge1xuICAgICAgY29uc3QgYWxyZWFkeUV4aXN0aW5nSW5zZXJ0aW9uVGFiID0gVXRpbC5pc0RlZmluZWQodGhpcy5kYXRhLmZpbmQoaXRlbSA9PiBpdGVtLmluc2VydGlvbk1vZGUpKTtcbiAgICAgIGFkZE5ld0NvbXAgPSAhYWxyZWFkeUV4aXN0aW5nSW5zZXJ0aW9uVGFiO1xuICAgIH1cbiAgICBjb25zdCBuZXdDb21wUGFyYW1zID0gY29tcERhdGEucGFyYW1zO1xuICAgIGlmIChhZGROZXdDb21wKSB7XG4gICAgICB0aGlzLmRhdGEuZm9yRWFjaChjb21wID0+IHtcbiAgICAgICAgY29uc3QgY3VyclBhcmFtcyA9IGNvbXAucGFyYW1zIHx8IHt9O1xuICAgICAgICBsZXQgc29tZURpZmZQYXJhbXMgPSB0cnVlO1xuICAgICAgICBpZiAoT2JqZWN0LmtleXMoY3VyclBhcmFtcykubGVuZ3RoID4gMCkge1xuICAgICAgICAgI