UNPKG

@kronscht/ng-wizard

Version:

Angular ng-wizard - Angular wizard | stepper

393 lines 62.2 kB
import { Component, Input, EventEmitter, Output, ContentChildren, QueryList } from '@angular/core'; import { isObservable, of } from 'rxjs'; import { NgWizardDataService } from '../ng-wizard-data.service'; import { NgWizardStep } from '../../utils/interfaces'; import { TOOLBAR_POSITION, STEP_STATE, STEP_STATUS, STEP_DIRECTIN, STEP_POSITION } from '../../utils/enums'; import { merge } from '../../utils/functions'; import * as i0 from "@angular/core"; import * as i1 from "../ng-wizard-data.service"; import * as i2 from "@angular/common"; export class NgWizardComponent { constructor(ngWizardDataService) { this.ngWizardDataService = ngWizardDataService; this.stepChanged = new EventEmitter(); this.themeChanged = new EventEmitter(); this.reseted = new EventEmitter(); this.styles = {}; this.showToolbarTop = false; this.showPreviousButton = false; this.showNextButton = false; this.showToolbarBottom = false; this.showExtraButtons = false; this.currentStepIndex = null; // Active step index } get pConfig() { return this._pConfig || {}; } set pConfig(config) { this._pConfig = config; } ngAfterContentInit() { this._backupStepStates(); this._init(); // Set toolbar this._setToolbar(); // Assign plugin events this._setEvents(); this.resetWizardWatcher = this.ngWizardDataService.resetWizard$.subscribe(() => this._reset()); this.showNextStepWatcher = this.ngWizardDataService.showNextStep$.subscribe(() => this._showNextStep()); this.showPreviousStepWatcher = this.ngWizardDataService.showPreviousStep$.subscribe(() => this._showPreviousStep()); this.showStepWatcher = this.ngWizardDataService.showStep$.subscribe(index => this._showStep(index)); this.setThemeWatcher = this.ngWizardDataService.setTheme$.subscribe(theme => this._setTheme(theme)); } _init() { // set config let defaultConfig = this.ngWizardDataService.getDefaultConfig(); this.config = merge(defaultConfig, this.pConfig); // set step states this._initSteps(); // Set the elements this._initStyles(); // Show the initial step this._showStep(this.config.selected); } _initSteps() { this.steps.forEach((step, index) => { step.index = index; step.status = step.status || STEP_STATUS.untouched; step.state = step.state || STEP_STATE.normal; }); // Mark previous steps of the active step as done if (this.config.selected > 0 && this.config.anchorSettings.markDoneStep && this.config.anchorSettings.markAllPreviousStepsAsDone) { this.steps.forEach(step => { if (step.state != STEP_STATE.disabled && step.state != STEP_STATE.hidden) { step.status = step.index < this.config.selected ? STEP_STATUS.done : step.status; } }); } } _backupStepStates() { this.steps.forEach(step => { step.initialStatus = step.status; step.initialState = step.state; }); } _restoreStepStates() { this.steps.forEach(step => { step.status = step.initialStatus; step.state = step.initialState; }); } // PRIVATE FUNCTIONS _initStyles() { // Set the main element this.styles.main = 'ng-wizard-main ng-wizard-theme-' + this.config.theme; // Set anchor elements this.styles.step = 'nav-item'; // li // Make the anchor clickable if (this.config.anchorSettings.enableAllAnchors && this.config.anchorSettings.anchorClickable) { this.styles.step += ' clickable'; } // Set the toolbar styles this.styles.toolbarTop = 'btn-toolbar ng-wizard-toolbar ng-wizard-toolbar-top justify-content-' + this.config.toolbarSettings.toolbarButtonPosition; this.styles.toolbarBottom = 'btn-toolbar ng-wizard-toolbar ng-wizard-toolbar-bottom justify-content-' + this.config.toolbarSettings.toolbarButtonPosition; // Set previous&next buttons this.styles.previousButton = 'btn btn-secondary ng-wizard-btn-prev'; this.styles.nextButton = 'btn btn-secondary ng-wizard-btn-next'; } _setToolbar() { this.showToolbarTop = this.config.toolbarSettings.toolbarPosition == TOOLBAR_POSITION.top || this.config.toolbarSettings.toolbarPosition == TOOLBAR_POSITION.both; this.showToolbarBottom = this.config.toolbarSettings.toolbarPosition == TOOLBAR_POSITION.bottom || this.config.toolbarSettings.toolbarPosition == TOOLBAR_POSITION.both; this.showPreviousButton = this.config.toolbarSettings.showPreviousButton; this.showNextButton = this.config.toolbarSettings.showNextButton; this.showExtraButtons = this.config.toolbarSettings.toolbarExtraButtons && this.config.toolbarSettings.toolbarExtraButtons.length > 0; } _setEvents() { //TODO: keyNavigation // Keyboard navigation event if (this.config.keyNavigation) { // $(document).keyup(function (e) { // mi._keyNav(e); // }); } } _getStepCssClass(selectedStep) { let stepClass = this.styles.step; switch (selectedStep.state) { case STEP_STATE.disabled: stepClass += ' disabled'; break; case STEP_STATE.error: stepClass += ' danger'; break; case STEP_STATE.hidden: stepClass += ' hidden'; break; } switch (selectedStep.status) { case STEP_STATUS.done: stepClass += ' done'; break; case STEP_STATUS.active: stepClass += ' active'; break; } return stepClass; } _showSelectedStep(event, selectedStep) { event.preventDefault(); if (!this.config.anchorSettings.anchorClickable) { return; } if (!this.config.anchorSettings.enableAnchorOnDoneStep && selectedStep.status == STEP_STATUS.done) { return true; } if (selectedStep.index != this.currentStepIndex) { if (this.config.anchorSettings.enableAllAnchors && this.config.anchorSettings.anchorClickable) { this._showStep(selectedStep.index); } else { if (selectedStep.status == STEP_STATUS.done) { this._showStep(selectedStep.index); } } } } _showNextStep(event) { if (event) { event.preventDefault(); } // Find the next not disabled & hidden step let filteredSteps = this.steps.filter(step => { return step.index > (this.currentStepIndex == null ? -1 : this.currentStepIndex) && step.state != STEP_STATE.disabled && step.state != STEP_STATE.hidden; }); if (filteredSteps.length == 0) { if (!this.config.cycleSteps) { return; } this._showStep(0); } else { this._showStep(filteredSteps.shift().index); } } _showPreviousStep(event) { if (event) { event.preventDefault(); } // Find the previous not disabled & hidden step let filteredSteps = this.steps.filter(step => { return step.index < (this.currentStepIndex == null && this.config.cycleSteps ? this.steps.length : this.currentStepIndex) && step.state != STEP_STATE.disabled && step.state != STEP_STATE.hidden; }); if (filteredSteps.length == 0) { if (!this.config.cycleSteps) { return; } this._showStep(this.steps.length - 1); } else { this._showStep(filteredSteps.pop().index); } } _showStep(selectedStepIndex) { // If step not found, skip if (selectedStepIndex >= this.steps.length || selectedStepIndex < 0) { return; } // If current step is requested again, skip if (selectedStepIndex == this.currentStepIndex) { return; } let selectedStep = this.steps.toArray()[selectedStepIndex]; // If it is a disabled or hidden step, skip if (selectedStep.state == STEP_STATE.disabled || selectedStep.state == STEP_STATE.hidden) { return; } this._showLoader(); return this._isStepChangeValid(selectedStep, this.currentStep && this.currentStep.canExit).toPromise() .then(isValid => { if (isValid) { return this._isStepChangeValid(selectedStep, selectedStep.canEnter).toPromise(); } return of(isValid).toPromise(); }) .then(isValid => { if (isValid) { // Load step content this._loadStepContent(selectedStep); } }) .finally(() => this._hideLoader()); } _isStepChangeValid(selectedStep, condition) { if (typeof condition === typeof true) { return of(condition); } else if (condition instanceof Function) { let direction = this._getStepDirection(selectedStep.index); let result = condition({ direction: direction, fromStep: this.currentStep, toStep: selectedStep }); if (isObservable(result)) { return result; } else if (typeof result === typeof true) { return of(result); } else { return of(false); } } return of(true); } _loadStepContent(selectedStep) { // Update controls this._setAnchor(selectedStep); // Set the buttons based on the step this._setButtons(selectedStep.index); // Trigger "stepChanged" event const args = { step: selectedStep, previousStep: this.currentStep, direction: this._getStepDirection(selectedStep.index), position: this._getStepPosition(selectedStep.index) }; this.stepChanged.emit(args); this.ngWizardDataService.stepChanged(args); // Update the current index this.currentStepIndex = selectedStep.index; this.currentStep = selectedStep; } _setAnchor(selectedStep) { // Current step anchor > Remove other classes and add done class if (this.currentStep) { this.currentStep.status = STEP_STATUS.untouched; if (this.config.anchorSettings.markDoneStep) { this.currentStep.status = STEP_STATUS.done; if (this.config.anchorSettings.removeDoneStepOnNavigateBack) { this.steps.forEach(step => { if (step.index > selectedStep.index) { step.status = STEP_STATUS.untouched; } }); } } } // Next step anchor > Remove other classes and add active class selectedStep.status = STEP_STATUS.active; } _setButtons(index) { // Previous/Next Button enable/disable based on step if (!this.config.cycleSteps) { if (0 >= index) { this.styles.previousButton = 'btn btn-secondary ng-wizard-btn-prev disabled'; } else { this.styles.previousButton = 'btn btn-secondary ng-wizard-btn-prev'; } if (this.steps.length - 1 <= index) { this.styles.nextButton = 'btn btn-secondary ng-wizard-btn-next disabled'; } else { this.styles.nextButton = 'btn btn-secondary ng-wizard-btn-next'; } } } _extraButtonClicked(button) { if (button.event) { button.event(); } } // HELPER FUNCTIONS _keyNav(event) { // Keyboard navigation switch (event.which) { case 37: // left this._showPreviousStep(event); event.preventDefault(); break; case 39: // right this._showNextStep(event); event.preventDefault(); break; default: return; // exit this handler for other keys } } _showLoader() { this.styles.main = 'ng-wizard-main ng-wizard-theme-' + this.config.theme + ' ng-wizard-loading'; } _hideLoader() { this.styles.main = 'ng-wizard-main ng-wizard-theme-' + this.config.theme; } _getStepDirection(selectedStepIndex) { return (this.currentStepIndex != null && this.currentStepIndex != selectedStepIndex) ? (this.currentStepIndex < selectedStepIndex ? STEP_DIRECTIN.forward : STEP_DIRECTIN.backward) : null; } _getStepPosition(selectedStepIndex) { return (selectedStepIndex == 0) ? STEP_POSITION.first : (selectedStepIndex == this.steps.length - 1 ? STEP_POSITION.final : STEP_POSITION.middle); } // PUBLIC FUNCTIONS _setTheme(theme) { if (this.config.theme == theme) { return false; } this.config.theme = theme; this.styles.main = 'ng-wizard-main ng-wizard-theme-' + this.config.theme; // Trigger "themeChanged" event this.themeChanged.emit(this.config.theme); } _reset() { // Reset all elements and classes this.currentStepIndex = null; this.currentStep = null; this._restoreStepStates(); this._init(); // Trigger "reseted" event this.reseted.emit(); } ngOnDestroy() { if (this.resetWizardWatcher) { this.resetWizardWatcher.unsubscribe(); } if (this.showNextStepWatcher) { this.showNextStepWatcher.unsubscribe(); } if (this.showPreviousStepWatcher) { this.showPreviousStepWatcher.unsubscribe(); } if (this.showStepWatcher) { this.showStepWatcher.unsubscribe(); } if (this.setThemeWatcher) { this.setThemeWatcher.unsubscribe(); } } } NgWizardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: NgWizardComponent, deps: [{ token: i1.NgWizardDataService }], target: i0.ɵɵFactoryTarget.Component }); NgWizardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.2", type: NgWizardComponent, selector: "ng-wizard", inputs: { pConfig: ["config", "pConfig"] }, outputs: { stepChanged: "stepChanged", themeChanged: "themeChanged", reseted: "reseted" }, queries: [{ propertyName: "steps", predicate: NgWizardStep }], ngImport: i0, template: "<div id=\"ngwizard\" [ngClass]=\"styles.main\">\r\n <ul class=\"nav nav-tabs step-anchor\">\r\n <li *ngFor=\"let step of steps; let i = index\" [ngClass]=\"_getStepCssClass(step)\">\r\n <a href=\"#step-{{ i }}\" (click)=\"_showSelectedStep($event, step)\" *ngIf=\"!step.isHidden\"\r\n class=\"nav-link\">{{ step.title }}<br /><small>{{ step.description }}</small></a>\r\n </li>\r\n </ul>\r\n\r\n <div *ngIf=\"showToolbarTop\" [ngClass]=\"styles.toolbarTop\">\r\n <div class=\"btn-group mr-2 ng-wizard-btn-group\" role=\"group\">\r\n <button *ngIf=\"showPreviousButton\" [ngClass]=\"styles.previousButton\" type=\"button\"\r\n (click)=\"_showPreviousStep($event)\">{{ config!.lang!.previous }}</button>\r\n <button *ngIf=\"showNextButton\" [ngClass]=\"styles.nextButton\" type=\"button\"\r\n (click)=\"_showNextStep($event)\">{{ config!.lang!.next }}</button>\r\n </div>\r\n\r\n <div *ngIf=\"showExtraButtons\" class=\"btn-group mr-2 ng-wizard-btn-group-extra\" role=\"group\">\r\n <button *ngFor=\"let button of config!.toolbarSettings!.toolbarExtraButtons; let j = index\"\r\n [ngClass]=\"button.class\" type=\"button\" (click)=\"_extraButtonClicked(button)\">{{ button.text }}</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"ng-wizard-container tab-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <div *ngIf=\"showToolbarBottom\" [ngClass]=\"styles.toolbarBottom\">\r\n <div class=\"btn-group mr-2 ng-wizard-btn-group\" role=\"group\">\r\n <button *ngIf=\"showPreviousButton\" [ngClass]=\"styles.previousButton\" type=\"button\"\r\n (click)=\"_showPreviousStep($event)\">{{ config!.lang!.previous }}</button>\r\n <button *ngIf=\"showNextButton\" [ngClass]=\"styles.nextButton\" type=\"button\"\r\n (click)=\"_showNextStep($event)\">{{ config!.lang!.next }}</button>\r\n </div>\r\n\r\n <div *ngIf=\"showExtraButtons\" class=\"btn-group mr-2 ng-wizard-btn-group-extra\" role=\"group\">\r\n <button *ngFor=\"let button of config!.toolbarSettings!.toolbarExtraButtons; let j = index\"\r\n [ngClass]=\"button.class\" type=\"button\" (click)=\"_extraButtonClicked(button)\">{{ button.text }}</button>\r\n </div>\r\n </div>\r\n</div>", styles: [""], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.2", ngImport: i0, type: NgWizardComponent, decorators: [{ type: Component, args: [{ selector: 'ng-wizard', template: "<div id=\"ngwizard\" [ngClass]=\"styles.main\">\r\n <ul class=\"nav nav-tabs step-anchor\">\r\n <li *ngFor=\"let step of steps; let i = index\" [ngClass]=\"_getStepCssClass(step)\">\r\n <a href=\"#step-{{ i }}\" (click)=\"_showSelectedStep($event, step)\" *ngIf=\"!step.isHidden\"\r\n class=\"nav-link\">{{ step.title }}<br /><small>{{ step.description }}</small></a>\r\n </li>\r\n </ul>\r\n\r\n <div *ngIf=\"showToolbarTop\" [ngClass]=\"styles.toolbarTop\">\r\n <div class=\"btn-group mr-2 ng-wizard-btn-group\" role=\"group\">\r\n <button *ngIf=\"showPreviousButton\" [ngClass]=\"styles.previousButton\" type=\"button\"\r\n (click)=\"_showPreviousStep($event)\">{{ config!.lang!.previous }}</button>\r\n <button *ngIf=\"showNextButton\" [ngClass]=\"styles.nextButton\" type=\"button\"\r\n (click)=\"_showNextStep($event)\">{{ config!.lang!.next }}</button>\r\n </div>\r\n\r\n <div *ngIf=\"showExtraButtons\" class=\"btn-group mr-2 ng-wizard-btn-group-extra\" role=\"group\">\r\n <button *ngFor=\"let button of config!.toolbarSettings!.toolbarExtraButtons; let j = index\"\r\n [ngClass]=\"button.class\" type=\"button\" (click)=\"_extraButtonClicked(button)\">{{ button.text }}</button>\r\n </div>\r\n </div>\r\n\r\n <div class=\"ng-wizard-container tab-content\">\r\n <ng-content></ng-content>\r\n </div>\r\n\r\n <div *ngIf=\"showToolbarBottom\" [ngClass]=\"styles.toolbarBottom\">\r\n <div class=\"btn-group mr-2 ng-wizard-btn-group\" role=\"group\">\r\n <button *ngIf=\"showPreviousButton\" [ngClass]=\"styles.previousButton\" type=\"button\"\r\n (click)=\"_showPreviousStep($event)\">{{ config!.lang!.previous }}</button>\r\n <button *ngIf=\"showNextButton\" [ngClass]=\"styles.nextButton\" type=\"button\"\r\n (click)=\"_showNextStep($event)\">{{ config!.lang!.next }}</button>\r\n </div>\r\n\r\n <div *ngIf=\"showExtraButtons\" class=\"btn-group mr-2 ng-wizard-btn-group-extra\" role=\"group\">\r\n <button *ngFor=\"let button of config!.toolbarSettings!.toolbarExtraButtons; let j = index\"\r\n [ngClass]=\"button.class\" type=\"button\" (click)=\"_extraButtonClicked(button)\">{{ button.text }}</button>\r\n </div>\r\n </div>\r\n</div>" }] }], ctorParameters: function () { return [{ type: i1.NgWizardDataService }]; }, propDecorators: { steps: [{ type: ContentChildren, args: [NgWizardStep] }], pConfig: [{ type: Input, args: ['config'] }], stepChanged: [{ type: Output }], themeChanged: [{ type: Output }], reseted: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctd2l6YXJkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9uZy13aXphcmQvbGliL2NvcmUvd2l6YXJkL25nLXdpemFyZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvbmctd2l6YXJkL2xpYi9jb3JlL3dpemFyZC9uZy13aXphcmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBb0IsS0FBSyxFQUFhLFlBQVksRUFBRSxNQUFNLEVBQUUsZUFBZSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNoSSxPQUFPLEVBQUUsWUFBWSxFQUEwQixFQUFFLEVBQWdCLE1BQU0sTUFBTSxDQUFDO0FBRTlFLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2hFLE9BQU8sRUFBa0IsWUFBWSxFQUFzRCxNQUFNLHdCQUF3QixDQUFDO0FBQzFILE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUFTLGFBQWEsRUFBRSxhQUFhLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUNuSCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7Ozs7QUFPOUMsTUFBTSxPQUFPLGlCQUFpQjtJQTRDNUIsWUFBb0IsbUJBQXdDO1FBQXhDLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBcUI7UUEzQmxELGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQW1CLENBQUM7UUFDbEQsaUJBQVksR0FBRyxJQUFJLFlBQVksRUFBUyxDQUFDO1FBQ3pDLFlBQU8sR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBRTdDLFdBQU0sR0FPRixFQUFFLENBQUM7UUFFUCxtQkFBYyxHQUFZLEtBQUssQ0FBQztRQUNoQyx1QkFBa0IsR0FBWSxLQUFLLENBQUM7UUFDcEMsbUJBQWMsR0FBWSxLQUFLLENB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IE9uRGVzdHJveSwgRXZlbnRFbWl0dGVyLCBPdXRwdXQsIENvbnRlbnRDaGlsZHJlbiwgUXVlcnlMaXN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IGlzT2JzZXJ2YWJsZSwgb2JzZXJ2YWJsZSwgT2JzZXJ2YWJsZSwgb2YsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5cclxuaW1wb3J0IHsgTmdXaXphcmREYXRhU2VydmljZSB9IGZyb20gJy4uL25nLXdpemFyZC1kYXRhLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBOZ1dpemFyZENvbmZpZywgTmdXaXphcmRTdGVwLCBUb29sYmFyQnV0dG9uLCBTdGVwQ2hhbmdlZEFyZ3MsIFN0ZXBWYWxpZGF0aW9uQXJncyB9IGZyb20gJy4uLy4uL3V0aWxzL2ludGVyZmFjZXMnO1xyXG5pbXBvcnQgeyBUT09MQkFSX1BPU0lUSU9OLCBTVEVQX1NUQVRFLCBTVEVQX1NUQVRVUywgVEhFTUUsIFNURVBfRElSRUNUSU4sIFNURVBfUE9TSVRJT04gfSBmcm9tICcuLi8uLi91dGlscy9lbnVtcyc7XHJcbmltcG9ydCB7IG1lcmdlIH0gZnJvbSAnLi4vLi4vdXRpbHMvZnVuY3Rpb25zJztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbmctd2l6YXJkJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vbmctd2l6YXJkLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9uZy13aXphcmQuY29tcG9uZW50LmNzcyddLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmdXaXphcmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQge1xyXG5cclxuICBAQ29udGVudENoaWxkcmVuKE5nV2l6YXJkU3RlcClcclxuICBwdWJsaWMgc3RlcHM6IFF1ZXJ5TGlzdDxOZ1dpemFyZFN0ZXA+O1xyXG5cclxuICBfcENvbmZpZzogTmdXaXphcmRDb25maWc7XHJcbiAgZ2V0IHBDb25maWcoKTogTmdXaXphcmRDb25maWcge1xyXG4gICAgcmV0dXJuIHRoaXMuX3BDb25maWcgfHwge307XHJcbiAgfVxyXG5cclxuICBASW5wdXQoJ2NvbmZpZycpXHJcbiAgc2V0IHBDb25maWcoY29uZmlnOiBOZ1dpemFyZENvbmZpZykge1xyXG4gICAgdGhpcy5fcENvbmZpZyA9IGNvbmZpZztcclxuICB9XHJcblxyXG4gIGNvbmZpZzogTmdXaXphcmRDb25maWc7XHJcblxyXG4gIEBPdXRwdXQoKSBzdGVwQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8U3RlcENoYW5nZWRBcmdzPigpO1xyXG4gIEBPdXRwdXQoKSB0aGVtZUNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPFRIRU1FPigpO1xyXG4gIEBPdXRwdXQoKSByZXNldGVkID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICBzdHlsZXM6IHtcclxuICAgIG1haW4/OiBzdHJpbmc7XHJcbiAgICBzdGVwPzogc3RyaW5nO1xyXG4gICAgcHJldmlvdXNCdXR0b24/OiBzdHJpbmc7XHJcbiAgICBuZXh0QnV0dG9uPzogc3RyaW5nO1xyXG4gICAgdG9vbGJhclRvcD86IHN0cmluZztcclxuICAgIHRvb2xiYXJCb3R0b20/OiBzdHJpbmc7XHJcbiAgfSA9IHt9O1xyXG5cclxuICBzaG93VG9vbGJhclRvcDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHNob3dQcmV2aW91c0J1dHRvbjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHNob3dOZXh0QnV0dG9uOiBib29sZWFuID0gZmFsc2U7XHJcbiAgc2hvd1Rvb2xiYXJCb3R0b206IGJvb2xlYW4gPSBmYWxzZTtcclxuICBzaG93RXh0cmFCdXR0b25zOiBib29sZWFuID0gZmFsc2U7XHJcbiAgY3VycmVudFN0ZXBJbmRleDogbnVtYmVyID0gbnVsbDsgLy8gQWN0aXZlIHN0ZXAgaW5kZXhcclxuICBjdXJyZW50U3RlcDogTmdXaXphcmRTdGVwOyAvLyBBY3RpdmUgc3RlcFxyXG5cclxuICByZXNldFdpemFyZFdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuICBzaG93TmV4dFN0ZXBXYXRjaGVyOiBTdWJzY3JpcHRpb247XHJcbiAgc2hvd1ByZXZpb3VzU3RlcFdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuICBzaG93U3RlcFdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuICBzZXRUaGVtZVdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBuZ1dpemFyZERhdGFTZXJ2aWNlOiBOZ1dpemFyZERhdGFTZXJ2aWNlKSB7XHJcbiAgfVxyXG5cclxuICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XHJcbiAgICB0aGlzLl9iYWNrdXBTdGVwU3RhdGVzKCk7XHJcblxyXG4gICAgdGhpcy5faW5pdCgpO1xyXG5cclxuICAgIC8vIFNldCB0b29sYmFyXHJcbiAgICB0aGlzLl9zZXRUb29sYmFyKCk7XHJcblxyXG4gICAgLy8gQXNzaWduIHBsdWdpbiBldmVudHNcclxuICAgIHRoaXMuX3NldEV2ZW50cygpO1xyXG5cclxuICAgIHRoaXMucmVzZXRXaXphcmRXYXRjaGVyID0gdGhpcy5uZ1dpemFyZERhdGFTZXJ2aWNlLnJlc2V0V2l6YXJkJC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fcmVzZXQoKSk7XHJcbiAgICB0aGlzLnNob3dOZXh0U3RlcFdhdGNoZXIgPSB0aGlzLm5nV2l6YXJkRGF0YVNlcnZpY2Uuc2hvd05leHRTdGVwJC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fc2hvd05leHRTdGVwKCkpO1xyXG4gICAgdGhpcy5zaG93UHJldmlvdXNTdGVwV2F0Y2hlciA9IHRoaXMubmdXaXphcmREYXRhU2VydmljZS5zaG93UHJldmlvdXNTdGVwJC5zdWJzY3JpYmUoKCkgPT4gdGhpcy5fc2hvd1ByZXZpb3VzU3RlcCgpKTtcclxuICAgIHRoaXMuc2hvd1N0ZXBXYXRjaGVyID0gdGhpcy5uZ1dpemFyZERhdGFTZXJ2aWNlLnNob3dTdGVwJC5zdWJzY3JpYmUoaW5kZXggPT4gdGhpcy5fc2hvd1N0ZXAoaW5kZXgpKTtcclxuICAgIHRoaXMuc2V0VGhlbWVXYXRjaGVyID0gdGhpcy5uZ1dpemFyZERhdGFTZXJ2aWNlLnNldFRoZW1lJC5zdWJzY3JpYmUodGhlbWUgPT4gdGhpcy5fc2V0VGhlbWUodGhlbWUpKTtcclxuICB9XHJcblxyXG4gIF9pbml0KCkge1xyXG4gICAgLy8gc2V0IGNvbmZpZ1xyXG4gICAgbGV0IGRlZmF1bHRDb25maWcgPSB0aGlzLm5nV2l6YXJkRGF0YVNlcnZpY2UuZ2V0RGVmYXVsdENvbmZpZygpO1xyXG4gICAgdGhpcy5jb25maWcgPSBtZXJnZShkZWZhdWx0Q29uZmlnLCB0aGlzLnBDb25maWcpO1xyXG5cclxuICAgIC8vIHNldCBzdGVwIHN0YXRlc1xyXG4gICAgdGhpcy5faW5pdFN0ZXBzKCk7XHJcblxyXG4gICAgLy8gU2V0IHRoZSBlbGVtZW50c1xyXG4gICAgdGhpcy5faW5pdFN0eWxlcygpO1xyXG5cclxuICAgIC8vIFNob3cgdGhlIGluaXRpYWwgc3RlcFxyXG4gICAgdGhpcy5fc2hvd1N0ZXAodGhpcy5jb25maWcuc2VsZWN0ZWQpO1xyXG4gIH1cclxuXHJcbiAgX2luaXRTdGVwcygpIHtcclxuICAgIHRoaXMuc3RlcHMuZm9yRWFjaCgoc3RlcCwgaW5kZXgpID0+IHtcclxuICAgICAgc3RlcC5pbmRleCA9IGluZGV4O1xyXG4gICAgICBzdGVwLnN0YXR1cyA9IHN0ZXAuc3RhdHVzIHx8IFNURVBfU1RBVFVTLnVudG91Y2hlZDtcclxuICAgICAgc3RlcC5zdGF0ZSA9IHN0ZXAuc3RhdGUgfHwgU1RFUF9TVEFURS5ub3JtYWw7XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBNYXJrIHByZXZpb3VzIHN0ZXBzIG9mIHRoZSBhY3RpdmUgc3RlcCBhcyBkb25lXHJcbiAgICBpZiAodGhpcy5jb25maWcuc2VsZWN0ZWQgPiAwXHJcbiAgICAgICYmIHRoaXMuY29uZmlnLmFuY2hvclNldHRpbmdzLm1hcmtEb25lU3RlcFxyXG4gICAgICAmJiB0aGlzLmNvbmZpZy5hbmNob3JTZXR0aW5ncy5tYXJrQWxsUHJldmlvdXNTdGVwc0FzRG9uZSkge1xyXG5cclxuICAgICAgdGhpcy5zdGVwcy5mb3JFYWNoKHN0ZXAgPT4ge1xyXG4gICAgICAgIGlmIChzdGVwLnN0YXRlICE9IFNURVBfU1RBVEUuZGlzYWJsZWQgJiYgc3RlcC5zdGF0ZSAhPSBTVEVQX1NUQVRFLmhpZGRlbikge1xyXG4gICAgICAgICAgc3RlcC5zdGF0dXMgPSBzdGVwLmluZGV4IDwgdGhpcy5jb25maWcuc2VsZWN0ZWQgPyBTVEVQX1NUQVRVUy5kb25lIDogc3RlcC5zdGF0dXM7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIF9iYWNrdXBTdGVwU3RhdGVzKCkge1xyXG4gICAgdGhpcy5zdGVwcy5mb3JFYWNoKHN0ZXAgPT4ge1xyXG4gICAgICBzdGVwLmluaXRpYWxTdGF0dXMgPSBzdGVwLnN0YXR1cztcclxuICAgICAgc3RlcC5pbml0aWFsU3RhdGUgPSBzdGVwLnN0YXRlO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBfcmVzdG9yZVN0ZXBTdGF0ZXMoKSB7XHJcbiAgICB0aGlzLnN0ZXBzLmZvckVhY2goc3RlcCA9PiB7XHJcbiAgICAgIHN0ZXAuc3RhdHVzID0gc3RlcC5pbml0aWFsU3RhdHVzO1xyXG4gICAgICBzdGVwLnN0YXRlID0gc3RlcC5pbml0aWFsU3RhdGU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIFBSSVZBVEUgRlVOQ1RJT05TXHJcbiAgX2luaXRTdHlsZXMoKSB7XHJcbiAgICAvLyBTZXQgdGhlIG1haW4gZWxlbWVudFxyXG4gICAgdGhpcy5zdHlsZXMubWFpbiA9ICduZy13aXphcmQtbWFpbiBuZy13aXphcmQtdGhlbWUtJyArIHRoaXMuY29uZmlnLnRoZW1lO1xyXG5cclxuICAgIC8vIFNldCBhbmNob3IgZWxlbWVudHNcclxuICAgIHRoaXMuc3R5bGVzLnN0ZXAgPSAnbmF2LWl0ZW0nOyAvLyBsaVxyXG5cclxuICAgIC8vIE1ha2UgdGhlIGFuY2hvciBjbGlja2FibGVcclxuICAgIGlmICh0aGlzLmNvbmZpZy5hbmNob3JTZXR0aW5ncy5lbmFibGVBbGxBbmNob3JzICYmIHRoaXMuY29uZmlnLmFuY2hvclNldHRpbmdzLmFuY2hvckNsaWNrYWJsZSkge1xyXG4gICAgICB0aGlzLnN0eWxlcy5zdGVwICs9ICcgY2xpY2thYmxlJztcclxuICAgIH1cclxuXHJcbiAgICAvLyBTZXQgdGhlIHRvb2xiYXIgc3R5bGVzXHJcbiAgICB0aGlzLnN0eWxlcy50b29sYmFyVG9wID0gJ2J0bi10b29sYmFyIG5nLXdpemFyZC10b29sYmFyIG5nLXdpemFyZC10b29sYmFyLXRvcCBqdXN0aWZ5LWNvbnRlbnQtJyArIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyQnV0dG9uUG9zaXRpb247XHJcbiAgICB0aGlzLnN0eWxlcy50b29sYmFyQm90dG9tID0gJ2J0bi10b29sYmFyIG5nLXdpemFyZC10b29sYmFyIG5nLXdpemFyZC10b29sYmFyLWJvdHRvbSBqdXN0aWZ5LWNvbnRlbnQtJyArIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyQnV0dG9uUG9zaXRpb247XHJcblxyXG4gICAgLy8gU2V0IHByZXZpb3VzJm5leHQgYnV0dG9ucyBcclxuICAgIHRoaXMuc3R5bGVzLnByZXZpb3VzQnV0dG9uID0gJ2J0biBidG4tc2Vjb25kYXJ5IG5nLXdpemFyZC1idG4tcHJldic7XHJcbiAgICB0aGlzLnN0eWxlcy5uZXh0QnV0dG9uID0gJ2J0biBidG4tc2Vjb25kYXJ5IG5nLXdpemFyZC1idG4tbmV4dCc7XHJcbiAgfVxyXG5cclxuICBfc2V0VG9vbGJhcigpIHtcclxuICAgIHRoaXMuc2hvd1Rvb2xiYXJUb3AgPSB0aGlzLmNvbmZpZy50b29sYmFyU2V0dGluZ3MudG9vbGJhclBvc2l0aW9uID09IFRPT0xCQVJfUE9TSVRJT04udG9wIHx8XHJcbiAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyUG9zaXRpb24gPT0gVE9PTEJBUl9QT1NJVElPTi5ib3RoO1xyXG5cclxuICAgIHRoaXMuc2hvd1Rvb2xiYXJCb3R0b20gPSB0aGlzLmNvbmZpZy50b29sYmFyU2V0dGluZ3MudG9vbGJhclBvc2l0aW9uID09IFRPT0xCQVJfUE9TSVRJT04uYm90dG9tIHx8XHJcbiAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyUG9zaXRpb24gPT0gVE9PTEJBUl9QT1NJVElPTi5ib3RoO1xyXG5cclxuICAgIHRoaXMuc2hvd1ByZXZpb3VzQnV0dG9uID0gdGhpcy5jb25maWcudG9vbGJhclNldHRpbmdzLnNob3dQcmV2aW91c0J1dHRvbjtcclxuICAgIHRoaXMuc2hvd05leHRCdXR0b24gPSB0aGlzLmNvbmZpZy50b29sYmFyU2V0dGluZ3Muc2hvd05leHRCdXR0b247XHJcblxyXG4gICAgdGhpcy5zaG93RXh0cmFCdXR0b25zID0gdGhpcy5jb25maWcudG9vbGJhclNldHRpbmdzLnRvb2xiYXJFeHRyYUJ1dHRvbnMgJiYgdGhpcy5jb25maWcudG9vbGJhclNldHRpbmdzLnRvb2xiYXJFeHRyYUJ1dHRvbnMubGVuZ3RoID4gMDtcclxuICB9XHJcblxyXG4gIF9zZXRFdmVudHMoKSB7XHJcbiAgICAvL1RPRE86IGtleU5hdmlnYXRpb25cclxuICAgIC8vIEtleWJvYXJkIG5hdmlnYXRpb24gZXZlbnRcclxuICAgIGlmICh0aGlzLmNvbmZpZy5rZXlOYXZpZ2F0aW9uKSB7XHJcbiAgICAgIC8vICQoZG9jdW1lbnQpLmtleXVwKGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgIC8vICAgbWkuX2tleU5hdihlKTtcclxuICAgICAgLy8gfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBfZ2V0U3RlcENzc0NsYXNzKHNlbGVjdGVkU3RlcDogTmdXaXphcmRTdGVwKSB7XHJcbiAgICBsZXQgc3RlcENsYXNzID0gdGhpcy5zdHlsZXMuc3RlcDtcclxuXHJcbiAgICBzd2l0Y2ggKHNlbGVjdGVkU3RlcC5zdGF0ZSkge1xyXG4gICAgICBjYXNlIFNURVBfU1RBVEUuZGlzYWJsZWQ6XHJcbiAgICAgICAgc3RlcENsYXNzICs9ICcgZGlzYWJsZWQnO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIFNURVBfU1RBVEUuZXJyb3I6XHJcbiAgICAgICAgc3RlcENsYXNzICs9ICcgZGFuZ2VyJztcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBTVEVQX1NUQVRFLmhpZGRlbjpcclxuICAgICAgICBzdGVwQ2xhc3MgKz0gJyBoaWRkZW4nO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgfVxyXG5cclxuICAgIHN3aXRjaCAoc2VsZWN0ZWRTdGVwLnN0YXR1cykge1xyXG4gICAgICBjYXNlIFNURVBfU1RBVFVTLmRvbmU6XHJcbiAgICAgICAgc3RlcENsYXNzICs9ICcgZG9uZSc7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgU1RFUF9TVEFUVVMuYWN0aXZlOlxyXG4gICAgICAgIHN0ZXBDbGFzcyArPSAnIGFjdGl2ZSc7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHN0ZXBDbGFzcztcclxuICB9XHJcblxyXG4gIF9zaG93U2VsZWN0ZWRTdGVwKGV2ZW50OiBFdmVudCwgc2VsZWN0ZWRTdGVwOiBOZ1dpemFyZFN0ZXApIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcblxyXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5hbmNob3JTZXR0aW5ncy5hbmNob3JDbGlja2FibGUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghdGhpcy5jb25maWcuYW5jaG9yU2V0dGluZ3MuZW5hYmxlQW5jaG9yT25Eb25lU3RlcCAmJiBzZWxlY3RlZFN0ZXAuc3RhdHVzID09IFNURVBfU1RBVFVTLmRvbmUpIHtcclxuICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHNlbGVjdGVkU3RlcC5pbmRleCAhPSB0aGlzLmN1cnJlbnRTdGVwSW5kZXgpIHtcclxuICAgICAgaWYgKHRoaXMuY29uZmlnLmFuY2hvclNldHRpbmdzLmVuYWJsZUFsbEFuY2hvcnMgJiYgdGhpcy5jb25maWcuYW5jaG9yU2V0dGluZ3MuYW5jaG9yQ2xpY2thYmxlKSB7XHJcbiAgICAgICAgdGhpcy5fc2hvd1N0ZXAoc2VsZWN0ZWRTdGVwLmluZGV4KTtcclxuICAgICAgfVxyXG4gICAgICBlbHNlIHtcclxuICAgICAgICBpZiAoc2VsZWN0ZWRTdGVwLnN0YXR1cyA9PSBTVEVQX1NUQVRVUy5kb25lKSB7XHJcbiAgICAgICAgICB0aGlzLl9zaG93U3RlcChzZWxlY3RlZFN0ZXAuaW5kZXgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgX3Nob3dOZXh0U3RlcChldmVudD86IEV2ZW50KSB7XHJcbiAgICBpZiAoZXZlbnQpIHtcclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIH1cclxuICAgIC8vIEZpbmQgdGhlIG5leHQgbm90IGRpc2FibGVkICYgaGlkZGVuIHN0ZXBcclxuICAgIGxldCBmaWx0ZXJlZFN0ZXBzID0gdGhpcy5zdGVwcy5maWx0ZXIoc3RlcCA9PiB7XHJcbiAgICAgIHJldHVybiBzdGVwLmluZGV4ID4gKHRoaXMuY3VycmVudFN0ZXBJbmRleCA9PSBudWxsID8gLTEgOiB0aGlzLmN1cnJlbnRTdGVwSW5kZXgpXHJcbiAgICAgICAgJiYgc3RlcC5zdGF0ZSAhPSBTVEVQX1NUQVRFLmRpc2FibGVkXHJcbiAgICAgICAgJiYgc3RlcC5zdGF0ZSAhPSBTVEVQX1NUQVRFLmhpZGRlbjtcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChmaWx0ZXJlZFN0ZXBzLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgIGlmICghdGhpcy5jb25maWcuY3ljbGVTdGVwcykge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgdGhpcy5fc2hvd1N0ZXAoMClcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICB0aGlzLl9zaG93U3RlcChmaWx0ZXJlZFN0ZXBzLnNoaWZ0KCkuaW5kZXgpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBfc2hvd1ByZXZpb3VzU3RlcChldmVudD86IEV2ZW50KSB7XHJcbiAgICBpZiAoZXZlbnQpIHtcclxuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIH1cclxuICAgIC8vIEZpbmQgdGhlIHByZXZpb3VzIG5vdCBkaXNhYmxlZCAmIGhpZGRlbiBzdGVwXHJcbiAgICBsZXQgZmlsdGVyZWRTdGVwcyA9IHRoaXMuc3RlcHMuZmlsdGVyKHN0ZXAgPT4ge1xyXG4gICAgICByZXR1cm4gc3RlcC5pbmRleCA8ICh0aGlzLmN1cnJlbnRTdGVwSW5kZXggPT0gbnVsbCAmJiB0aGlzLmNvbmZpZy5jeWNsZVN0ZXBzID8gdGhpcy5zdGVwcy5sZW5ndGggOiB0aGlzLmN1cnJlbnRTdGVwSW5kZXgpXHJcbiAgICAgICAgJiYgc3RlcC5zdGF0ZSAhPSBTVEVQX1NUQVRFLmRpc2FibGVkXHJcbiAgICAgICAgJiYgc3RlcC5zdGF0ZSAhPSBTVEVQX1NUQVRFLmhpZGRlbjtcclxuICAgIH0pO1xyXG5cclxuICAgIGlmIChmaWx0ZXJlZFN0ZXBzLmxlbmd0aCA9PSAwKSB7XHJcbiAgICAgIGlmICghdGhpcy5jb25maWcuY3ljbGVTdGVwcykge1xyXG4gICAgICAgIHJldHVybjtcclxuICAg