UNPKG

ng-wizard

Version:

Angular ng-wizard - Angular wizard | stepper

439 lines 65.9 kB
import { Component, ContentChildren, Input, Output, EventEmitter, } from '@angular/core'; import { of, isObservable } from 'rxjs'; import { STEP_STATUS, STEP_STATE, TOOLBAR_POSITION, STEP_DIRECTION, STEP_POSITION, } from '../../utils/enums'; import { merge } from '../../utils/functions'; import { NgWizardStep, } from '../../utils/interfaces'; import * as i0 from "@angular/core"; import * as i1 from "../../services/ng-wizard-data.service"; import * as i2 from "@angular/common"; export class NgWizardComponent { ngWizardDataService; steps; _pConfig; get pConfig() { return this._pConfig || {}; } set pConfig(config) { this._pConfig = config; } config; stepChanged = new EventEmitter(); themeChanged = new EventEmitter(); reset = new EventEmitter(); styles = {}; showToolbarTop = false; showPreviousButton = false; showNextButton = false; showToolbarBottom = false; showExtraButtons = false; currentStepIndex = null; // Active step index currentStep; // Active step resetWizardWatcher; showNextStepWatcher; showPreviousStepWatcher; showStepWatcher; setThemeWatcher; constructor(ngWizardDataService) { this.ngWizardDataService = ngWizardDataService; } 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; } 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(); 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_DIRECTION.forward : STEP_DIRECTION.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; } 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 "reset" event this.reset.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(); } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: NgWizardComponent, deps: [{ token: i1.NgWizardDataService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: NgWizardComponent, selector: "ng-wizard", inputs: { pConfig: ["config", "pConfig"] }, outputs: { stepChanged: "stepChanged", themeChanged: "themeChanged", reset: "reset" }, 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\r\n *ngFor=\"let step of steps; let i = index\"\r\n [ngClass]=\"_getStepCssClass(step)\"\r\n >\r\n <a\r\n href=\"#step-{{ i }}\"\r\n (click)=\"_showSelectedStep($event, step)\"\r\n *ngIf=\"!step.isHidden\"\r\n class=\"nav-link\"\r\n >{{ step.title }}<br /><small>{{ step.description }}</small></a\r\n >\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\r\n *ngIf=\"showPreviousButton\"\r\n [ngClass]=\"styles.previousButton\"\r\n type=\"button\"\r\n (click)=\"_showPreviousStep($event)\"\r\n >\r\n {{ config!.lang!.previous }}\r\n </button>\r\n <button\r\n *ngIf=\"showNextButton\"\r\n [ngClass]=\"styles.nextButton\"\r\n type=\"button\"\r\n (click)=\"_showNextStep($event)\"\r\n >\r\n {{ config!.lang!.next }}\r\n </button>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"showExtraButtons\"\r\n class=\"btn-group mr-2 ng-wizard-btn-group-extra\"\r\n role=\"group\"\r\n >\r\n <button\r\n *ngFor=\"\r\n let button of config!.toolbarSettings!.toolbarExtraButtons;\r\n let j = index\r\n \"\r\n [ngClass]=\"button.class\"\r\n type=\"button\"\r\n (click)=\"_extraButtonClicked(button)\"\r\n >\r\n {{ button.text }}\r\n </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\r\n *ngIf=\"showPreviousButton\"\r\n [ngClass]=\"styles.previousButton\"\r\n type=\"button\"\r\n (click)=\"_showPreviousStep($event)\"\r\n >\r\n {{ config!.lang!.previous }}\r\n </button>\r\n <button\r\n *ngIf=\"showNextButton\"\r\n [ngClass]=\"styles.nextButton\"\r\n type=\"button\"\r\n (click)=\"_showNextStep($event)\"\r\n >\r\n {{ config!.lang!.next }}\r\n </button>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"showExtraButtons\"\r\n class=\"btn-group mr-2 ng-wizard-btn-group-extra\"\r\n role=\"group\"\r\n >\r\n <button\r\n *ngFor=\"\r\n let button of config!.toolbarSettings!.toolbarExtraButtons;\r\n let j = index\r\n \"\r\n [ngClass]=\"button.class\"\r\n type=\"button\"\r\n (click)=\"_extraButtonClicked(button)\"\r\n >\r\n {{ button.text }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n", 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: "18.2.12", 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\r\n *ngFor=\"let step of steps; let i = index\"\r\n [ngClass]=\"_getStepCssClass(step)\"\r\n >\r\n <a\r\n href=\"#step-{{ i }}\"\r\n (click)=\"_showSelectedStep($event, step)\"\r\n *ngIf=\"!step.isHidden\"\r\n class=\"nav-link\"\r\n >{{ step.title }}<br /><small>{{ step.description }}</small></a\r\n >\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\r\n *ngIf=\"showPreviousButton\"\r\n [ngClass]=\"styles.previousButton\"\r\n type=\"button\"\r\n (click)=\"_showPreviousStep($event)\"\r\n >\r\n {{ config!.lang!.previous }}\r\n </button>\r\n <button\r\n *ngIf=\"showNextButton\"\r\n [ngClass]=\"styles.nextButton\"\r\n type=\"button\"\r\n (click)=\"_showNextStep($event)\"\r\n >\r\n {{ config!.lang!.next }}\r\n </button>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"showExtraButtons\"\r\n class=\"btn-group mr-2 ng-wizard-btn-group-extra\"\r\n role=\"group\"\r\n >\r\n <button\r\n *ngFor=\"\r\n let button of config!.toolbarSettings!.toolbarExtraButtons;\r\n let j = index\r\n \"\r\n [ngClass]=\"button.class\"\r\n type=\"button\"\r\n (click)=\"_extraButtonClicked(button)\"\r\n >\r\n {{ button.text }}\r\n </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\r\n *ngIf=\"showPreviousButton\"\r\n [ngClass]=\"styles.previousButton\"\r\n type=\"button\"\r\n (click)=\"_showPreviousStep($event)\"\r\n >\r\n {{ config!.lang!.previous }}\r\n </button>\r\n <button\r\n *ngIf=\"showNextButton\"\r\n [ngClass]=\"styles.nextButton\"\r\n type=\"button\"\r\n (click)=\"_showNextStep($event)\"\r\n >\r\n {{ config!.lang!.next }}\r\n </button>\r\n </div>\r\n\r\n <div\r\n *ngIf=\"showExtraButtons\"\r\n class=\"btn-group mr-2 ng-wizard-btn-group-extra\"\r\n role=\"group\"\r\n >\r\n <button\r\n *ngFor=\"\r\n let button of config!.toolbarSettings!.toolbarExtraButtons;\r\n let j = index\r\n \"\r\n [ngClass]=\"button.class\"\r\n type=\"button\"\r\n (click)=\"_extraButtonClicked(button)\"\r\n >\r\n {{ button.text }}\r\n </button>\r\n </div>\r\n </div>\r\n</div>\r\n" }] }], ctorParameters: () => [{ type: i1.NgWizardDataService }], propDecorators: { steps: [{ type: ContentChildren, args: [NgWizardStep] }], pConfig: [{ type: Input, args: ['config'] }], stepChanged: [{ type: Output }], themeChanged: [{ type: Output }], reset: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmctd2l6YXJkLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25nLXdpemFyZC9zcmMvbGliL2NvbXBvbmVudHMvbmctd2l6YXJkL25nLXdpemFyZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy13aXphcmQvc3JjL2xpYi9jb21wb25lbnRzL25nLXdpemFyZC9uZy13aXphcmQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFHVCxlQUFlLEVBRWYsS0FBSyxFQUNMLE1BQU0sRUFDTixZQUFZLEdBQ2IsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFnQixFQUFFLEVBQWMsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRWxFLE9BQU8sRUFFTCxXQUFXLEVBQ1gsVUFBVSxFQUNWLGdCQUFnQixFQUNoQixjQUFjLEVBQ2QsYUFBYSxHQUNkLE1BQU0sbUJBQW1CLENBQUM7QUFDM0IsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzlDLE9BQU8sRUFHTCxZQUFZLEdBR2IsTUFBTSx3QkFBd0IsQ0FBQzs7OztBQU9oQyxNQUFNLE9BQU8saUJBQWlCO0lBMkNSO0lBekNiLEtBQUssQ0FBMEI7SUFFdEMsUUFBUSxDQUFpQjtJQUN6QixJQUFJLE9BQU87UUFDVCxPQUFPLElBQUksQ0FBQyxRQUFRLElBQUksRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxJQUNJLE9BQU8sQ0FBQyxNQUFzQjtRQUNoQyxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQU0sQ0FBQztJQUN6QixDQUFDO0lBRUQsTUFBTSxDQUFpQjtJQUViLFdBQVcsR0FBRyxJQUFJLFlBQVksRUFBbUIsQ0FBQztJQUNsRCxZQUFZLEdBQUcsSUFBSSxZQUFZLEVBQVMsQ0FBQztJQUN6QyxLQUFLLEdBQUcsSUFBSSxZ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LEVBQUUsQ0FBQztRQUN4QyxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztZQUM3QixJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDekMsQ0FBQztRQUVELElBQUksSUFBSSxDQUFDLHVCQUF1QixFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLHVCQUF1QixDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzdDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3JDLENBQUM7UUFFRCxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUN6QixJQUFJLENBQUMsZUFBZSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQ3JDLENBQUM7SUFDSCxDQUFDO3dHQTdnQlUsaUJBQWlCOzRGQUFqQixpQkFBaUIsME1BQ1gsWUFBWSw2QkNuQy9CLDgwRkFrR0E7OzRGRGhFYSxpQkFBaUI7a0JBTDdCLFNBQVM7K0JBQ0UsV0FBVzt3RkFNZCxLQUFLO3NCQURYLGVBQWU7dUJBQUMsWUFBWTtnQkFTekIsT0FBTztzQkFEVixLQUFLO3VCQUFDLFFBQVE7Z0JBT0wsV0FBVztzQkFBcEIsTUFBTTtnQkFDRyxZQUFZO3NCQUFyQixNQUFNO2dCQUNHLEtBQUs7c0JBQWQsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XHJcbiAgQ29tcG9uZW50LFxyXG4gIE9uRGVzdHJveSxcclxuICBBZnRlckNvbnRlbnRJbml0LFxyXG4gIENvbnRlbnRDaGlsZHJlbixcclxuICBRdWVyeUxpc3QsXHJcbiAgSW5wdXQsXHJcbiAgT3V0cHV0LFxyXG4gIEV2ZW50RW1pdHRlcixcclxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU3Vic2NyaXB0aW9uLCBvZiwgT2JzZXJ2YWJsZSwgaXNPYnNlcnZhYmxlIH0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IE5nV2l6YXJkRGF0YVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9uZy13aXphcmQtZGF0YS5zZXJ2aWNlJztcclxuaW1wb3J0IHtcclxuICBUSEVNRSxcclxuICBTVEVQX1NUQVRVUyxcclxuICBTVEVQX1NUQVRFLFxyXG4gIFRPT0xCQVJfUE9TSVRJT04sXHJcbiAgU1RFUF9ESVJFQ1RJT04sXHJcbiAgU1RFUF9QT1NJVElPTixcclxufSBmcm9tICcuLi8uLi91dGlscy9lbnVtcyc7XHJcbmltcG9ydCB7IG1lcmdlIH0gZnJvbSAnLi4vLi4vdXRpbHMvZnVuY3Rpb25zJztcclxuaW1wb3J0IHtcclxuICBOZ1dpemFyZENvbmZpZyxcclxuICBTdGVwQ2hhbmdlZEFyZ3MsXHJcbiAgTmdXaXphcmRTdGVwLFxyXG4gIFN0ZXBWYWxpZGF0aW9uQXJncyxcclxuICBUb29sYmFyQnV0dG9uLFxyXG59IGZyb20gJy4uLy4uL3V0aWxzL2ludGVyZmFjZXMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICduZy13aXphcmQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9uZy13aXphcmQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL25nLXdpemFyZC5jb21wb25lbnQuc2NzcyddLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgTmdXaXphcmRDb21wb25lbnQgaW1wbGVtZW50cyBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQge1xyXG4gIEBDb250ZW50Q2hpbGRyZW4oTmdXaXphcmRTdGVwKVxyXG4gIHB1YmxpYyBzdGVwczogUXVlcnlMaXN0PE5nV2l6YXJkU3RlcD47XHJcblxyXG4gIF9wQ29uZmlnOiBOZ1dpemFyZENvbmZpZztcclxuICBnZXQgcENvbmZpZygpOiBOZ1dpemFyZENvbmZpZyB7XHJcbiAgICByZXR1cm4gdGhpcy5fcENvbmZpZyB8fCB7fTtcclxuICB9XHJcblxyXG4gIEBJbnB1dCgnY29uZmlnJylcclxuICBzZXQgcENvbmZpZyhjb25maWc6IE5nV2l6YXJkQ29uZmlnKSB7XHJcbiAgICB0aGlzLl9wQ29uZmlnID0gY29uZmlnO1xyXG4gIH1cclxuXHJcbiAgY29uZmlnOiBOZ1dpemFyZENvbmZpZztcclxuXHJcbiAgQE91dHB1dCgpIHN0ZXBDaGFuZ2VkID0gbmV3IEV2ZW50RW1pdHRlcjxTdGVwQ2hhbmdlZEFyZ3M+KCk7XHJcbiAgQE91dHB1dCgpIHRoZW1lQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8VEhFTUU+KCk7XHJcbiAgQE91dHB1dCgpIHJlc2V0ID0gbmV3IEV2ZW50RW1pdHRlcjx2b2lkPigpO1xyXG5cclxuICBzdHlsZXM6IHtcclxuICAgIG1haW4/OiBzdHJpbmc7XHJcbiAgICBzdGVwPzogc3RyaW5nO1xyXG4gICAgcHJldmlvdXNCdXR0b24/OiBzdHJpbmc7XHJcbiAgICBuZXh0QnV0dG9uPzogc3RyaW5nO1xyXG4gICAgdG9vbGJhclRvcD86IHN0cmluZztcclxuICAgIHRvb2xiYXJCb3R0b20/OiBzdHJpbmc7XHJcbiAgfSA9IHt9O1xyXG5cclxuICBzaG93VG9vbGJhclRvcDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHNob3dQcmV2aW91c0J1dHRvbjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHNob3dOZXh0QnV0dG9uOiBib29sZWFuID0gZmFsc2U7XHJcbiAgc2hvd1Rvb2xiYXJCb3R0b206IGJvb2xlYW4gPSBmYWxzZTtcclxuICBzaG93RXh0cmFCdXR0b25zOiBib29sZWFuID0gZmFsc2U7XHJcbiAgY3VycmVudFN0ZXBJbmRleDogbnVtYmVyID0gbnVsbDsgLy8gQWN0aXZlIHN0ZXAgaW5kZXhcclxuICBjdXJyZW50U3RlcDogTmdXaXphcmRTdGVwOyAvLyBBY3RpdmUgc3RlcFxyXG5cclxuICByZXNldFdpemFyZFdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuICBzaG93TmV4dFN0ZXBXYXRjaGVyOiBTdWJzY3JpcHRpb247XHJcbiAgc2hvd1ByZXZpb3VzU3RlcFdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuICBzaG93U3RlcFdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuICBzZXRUaGVtZVdhdGNoZXI6IFN1YnNjcmlwdGlvbjtcclxuXHJcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBuZ1dpemFyZERhdGFTZXJ2aWNlOiBOZ1dpemFyZERhdGFTZXJ2aWNlKSB7fVxyXG5cclxuICBuZ0FmdGVyQ29udGVudEluaXQoKSB7XHJcbiAgICB0aGlzLl9iYWNrdXBTdGVwU3RhdGVzKCk7XHJcblxyXG4gICAgdGhpcy5faW5pdCgpO1xyXG5cclxuICAgIC8vIFNldCB0b29sYmFyXHJcbiAgICB0aGlzLl9zZXRUb29sYmFyKCk7XHJcblxyXG4gICAgLy8gQXNzaWduIHBsdWdpbiBldmVudHNcclxuICAgIHRoaXMuX3NldEV2ZW50cygpO1xyXG5cclxuICAgIHRoaXMucmVzZXRXaXphcmRXYXRjaGVyID0gdGhpcy5uZ1dpemFyZERhdGFTZXJ2aWNlLnJlc2V0V2l6YXJkJC5zdWJzY3JpYmUoXHJcbiAgICAgICgpID0+IHRoaXMuX3Jlc2V0KClcclxuICAgICk7XHJcbiAgICB0aGlzLnNob3dOZXh0U3RlcFdhdGNoZXIgPSB0aGlzLm5nV2l6YXJkRGF0YVNlcnZpY2Uuc2hvd05leHRTdGVwJC5zdWJzY3JpYmUoXHJcbiAgICAgICgpID0+IHRoaXMuX3Nob3dOZXh0U3RlcCgpXHJcbiAgICApO1xyXG4gICAgdGhpcy5zaG93UHJldmlvdXNTdGVwV2F0Y2hlciA9XHJcbiAgICAgIHRoaXMubmdXaXphcmREYXRhU2VydmljZS5zaG93UHJldmlvdXNTdGVwJC5zdWJzY3JpYmUoKCkgPT5cclxuICAgICAgICB0aGlzLl9zaG93UHJldmlvdXNTdGVwKClcclxuICAgICAgKTtcclxuICAgIHRoaXMuc2hvd1N0ZXBXYXRjaGVyID0gdGhpcy5uZ1dpemFyZERhdGFTZXJ2aWNlLnNob3dTdGVwJC5zdWJzY3JpYmUoXHJcbiAgICAgIChpbmRleCkgPT4gdGhpcy5fc2hvd1N0ZXAoaW5kZXgpXHJcbiAgICApO1xyXG4gICAgdGhpcy5zZXRUaGVtZVdhdGNoZXIgPSB0aGlzLm5nV2l6YXJkRGF0YVNlcnZpY2Uuc2V0VGhlbWUkLnN1YnNjcmliZShcclxuICAgICAgKHRoZW1lKSA9PiB0aGlzLl9zZXRUaGVtZSh0aGVtZSlcclxuICAgICk7XHJcbiAgfVxyXG5cclxuICBfaW5pdCgpIHtcclxuICAgIC8vIHNldCBjb25maWdcclxuICAgIGxldCBkZWZhdWx0Q29uZmlnID0gdGhpcy5uZ1dpemFyZERhdGFTZXJ2aWNlLmdldERlZmF1bHRDb25maWcoKTtcclxuICAgIHRoaXMuY29uZmlnID0gbWVyZ2UoZGVmYXVsdENvbmZpZywgdGhpcy5wQ29uZmlnKTtcclxuXHJcbiAgICAvLyBzZXQgc3RlcCBzdGF0ZXNcclxuICAgIHRoaXMuX2luaXRTdGVwcygpO1xyXG5cclxuICAgIC8vIFNldCB0aGUgZWxlbWVudHNcclxuICAgIHRoaXMuX2luaXRTdHlsZXMoKTtcclxuXHJcbiAgICAvLyBTaG93IHRoZSBpbml0aWFsIHN0ZXBcclxuICAgIHRoaXMuX3Nob3dTdGVwKHRoaXMuY29uZmlnLnNlbGVjdGVkKTtcclxuICB9XHJcblxyXG4gIF9pbml0U3RlcHMoKSB7XHJcbiAgICB0aGlzLnN0ZXBzLmZvckVhY2goKHN0ZXAsIGluZGV4KSA9PiB7XHJcbiAgICAgIHN0ZXAuaW5kZXggPSBpbmRleDtcclxuICAgICAgc3RlcC5zdGF0dXMgPSBzdGVwLnN0YXR1cyB8fCBTVEVQX1NUQVRVUy51bnRvdWNoZWQ7XHJcbiAgICAgIHN0ZXAuc3RhdGUgPSBzdGVwLnN0YXRlIHx8IFNURVBfU1RBVEUubm9ybWFsO1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gTWFyayBwcmV2aW91cyBzdGVwcyBvZiB0aGUgYWN0aXZlIHN0ZXAgYXMgZG9uZVxyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLmNvbmZpZy5zZWxlY3RlZCA+IDAgJiZcclxuICAgICAgdGhpcy5jb25maWcuYW5jaG9yU2V0dGluZ3MubWFya0RvbmVTdGVwICYmXHJcbiAgICAgIHRoaXMuY29uZmlnLmFuY2hvclNldHRpbmdzLm1hcmtBbGxQcmV2aW91c1N0ZXBzQXNEb25lXHJcbiAgICApIHtcclxuICAgICAgdGhpcy5zdGVwcy5mb3JFYWNoKChzdGVwKSA9PiB7XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgc3RlcC5zdGF0ZSAhPSBTVEVQX1NUQVRFLmRpc2FibGVkICYmXHJcbiAgICAgICAgICBzdGVwLnN0YXRlICE9IFNURVBfU1RBVEUuaGlkZGVuXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICBzdGVwLnN0YXR1cyA9XHJcbiAgICAgICAgICAgIHN0ZXAuaW5kZXggPCB0aGlzLmNvbmZpZy5zZWxlY3RlZCA/IFNURVBfU1RBVFVTLmRvbmUgOiBzdGVwLnN0YXR1cztcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgX2JhY2t1cFN0ZXBTdGF0ZXMoKSB7XHJcbiAgICB0aGlzLnN0ZXBzLmZvckVhY2goKHN0ZXApID0+IHtcclxuICAgICAgc3RlcC5pbml0aWFsU3RhdHVzID0gc3RlcC5zdGF0dXM7XHJcbiAgICAgIHN0ZXAuaW5pdGlhbFN0YXRlID0gc3RlcC5zdGF0ZTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgX3Jlc3RvcmVTdGVwU3RhdGVzKCkge1xyXG4gICAgdGhpcy5zdGVwcy5mb3JFYWNoKChzdGVwKSA9PiB7XHJcbiAgICAgIHN0ZXAuc3RhdHVzID0gc3RlcC5pbml0aWFsU3RhdHVzO1xyXG4gICAgICBzdGVwLnN0YXRlID0gc3RlcC5pbml0aWFsU3RhdGU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIFBSSVZBVEUgRlVOQ1RJT05TXHJcbiAgX2luaXRTdHlsZXMoKSB7XHJcbiAgICAvLyBTZXQgdGhlIG1haW4gZWxlbWVudFxyXG4gICAgdGhpcy5zdHlsZXMubWFpbiA9ICduZy13aXphcmQtbWFpbiBuZy13aXphcmQtdGhlbWUtJyArIHRoaXMuY29uZmlnLnRoZW1lO1xyXG5cclxuICAgIC8vIFNldCBhbmNob3IgZWxlbWVudHNcclxuICAgIHRoaXMuc3R5bGVzLnN0ZXAgPSAnbmF2LWl0ZW0nOyAvLyBsaVxyXG5cclxuICAgIC8vIE1ha2UgdGhlIGFuY2hvciBjbGlja2FibGVcclxuICAgIGlmIChcclxuICAgICAgdGhpcy5jb25maWcuYW5jaG9yU2V0dGluZ3MuZW5hYmxlQWxsQW5jaG9ycyAmJlxyXG4gICAgICB0aGlzLmNvbmZpZy5hbmNob3JTZXR0aW5ncy5hbmNob3JDbGlja2FibGVcclxuICAgICkge1xyXG4gICAgICB0aGlzLnN0eWxlcy5zdGVwICs9ICcgY2xpY2thYmxlJztcclxuICAgIH1cclxuXHJcbiAgICAvLyBTZXQgdGhlIHRvb2xiYXIgc3R5bGVzXHJcbiAgICB0aGlzLnN0eWxlcy50b29sYmFyVG9wID1cclxuICAgICAgJ2J0bi10b29sYmFyIG5nLXdpemFyZC10b29sYmFyIG5nLXdpemFyZC10b29sYmFyLXRvcCBqdXN0aWZ5LWNvbnRlbnQtJyArXHJcbiAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyQnV0dG9uUG9zaXRpb247XHJcbiAgICB0aGlzLnN0eWxlcy50b29sYmFyQm90dG9tID1cclxuICAgICAgJ2J0bi10b29sYmFyIG5nLXdpemFyZC10b29sYmFyIG5nLXdpemFyZC10b29sYmFyLWJvdHRvbSBqdXN0aWZ5LWNvbnRlbnQtJyArXHJcbiAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyQnV0dG9uUG9zaXRpb247XHJcblxyXG4gICAgLy8gU2V0IHByZXZpb3VzJm5leHQgYnV0dG9uc1xyXG4gICAgdGhpcy5zdHlsZXMucHJldmlvdXNCdXR0b24gPSAnYnRuIGJ0bi1zZWNvbmRhcnkgbmctd2l6YXJkLWJ0bi1wcmV2JztcclxuICAgIHRoaXMuc3R5bGVzLm5leHRCdXR0b24gPSAnYnRuIGJ0bi1zZWNvbmRhcnkgbmctd2l6YXJkLWJ0bi1uZXh0JztcclxuICB9XHJcblxyXG4gIF9zZXRUb29sYmFyKCkge1xyXG4gICAgdGhpcy5zaG93VG9vbGJhclRvcCA9XHJcbiAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyUG9zaXRpb24gPT0gVE9PTEJBUl9QT1NJVElPTi50b3AgfHxcclxuICAgICAgdGhpcy5jb25maWcudG9vbGJhclNldHRpbmdzLnRvb2xiYXJQb3NpdGlvbiA9PSBUT09MQkFSX1BPU0lUSU9OLmJvdGg7XHJcblxyXG4gICAgdGhpcy5zaG93VG9vbGJhckJvdHRvbSA9XHJcbiAgICAgIHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy50b29sYmFyUG9zaXRpb24gPT0gVE9PTEJBUl9QT1NJVElPTi5ib3R0b20gfHxcclxuICAgICAgdGhpcy5jb25maWcudG9vbGJhclNldHRpbmdzLnRvb2xiYXJQb3NpdGlvbiA9PSBUT09MQkFSX1BPU0lUSU9OLmJvdGg7XHJcblxyXG4gICAgdGhpcy5zaG93UHJldmlvdXNCdXR0b24gPSB0aGlzLmNvbmZpZy50b29sYmFyU2V0dGluZ3Muc2hvd1ByZXZpb3VzQnV0dG9uO1xyXG4gICAgdGhpcy5zaG93TmV4dEJ1dHRvbiA9IHRoaXMuY29uZmlnLnRvb2xiYXJTZXR0aW5ncy5zaG93TmV4dEJ1dHRvbjtcclxuXHJcbiAgICB0aGlzLnNob3dFeHRyYUJ1dHRvbnMgPVxyXG4gICAgICB0aGlzLmNvbmZpZy50b29sYmFyU2V0dGluZ3MudG9vbGJhckV4dHJhQnV0dG9ucyAmJlxyXG4gICAgICB0aGlzLmNvbmZpZy50b29sYmFyU2V0dGluZ3MudG9vbGJhckV4dHJhQnV0dG9ucy5sZW5ndGggPiAwO1xyXG4gIH1cclxuXHJcbiAgX3NldEV2ZW50cygpIHtcclxuICAgIC8vVE9ETzoga2V5TmF2aWdhdGlvblxyXG4gICAgLy8gS2V5Ym9hcmQgbmF2aWdhdGlvbiBldmVudFxyXG4gICAgaWYgKHRoaXMuY29uZmlnLmtleU5hdmlnYXRpb24pIHtcclxuICAgICAgLy8gJChkb2N1bWVudCkua2V5dXAoZnVuY3Rpb24gKGUpIHtcclxuICAgICAgLy8gICBtaS5fa2V5TmF2KGUpO1xyXG4gICAgICAvLyB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIF9nZXRTdGVwQ3NzQ2xhc3Moc2VsZWN0ZWRTdGVwOiBOZ1dpemFyZFN0ZXApIHtcclxuICAgIGxldCBzdGVwQ2xhc3MgPSB0aGlzLnN0eWxlcy5zdGVwO1xyXG5cclxuICAgIHN3aXRjaCAoc2VsZWN0ZWRTdGVwLnN0YXRlKSB7XHJcbiAgICAgIGNhc2UgU1RFUF9TVEFURS5kaXNhYmxlZDpcclxuICAgICAgICBzdGVwQ2xhc3MgKz0gJyBkaXNhYmxlZCc7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgU1RFUF9TVEFURS5lcnJvcjpcclxuICAgICAgICBzdGVwQ2xhc3MgKz0gJyBkYW5nZXInO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIFNURVBfU1RBVEUuaGlkZGVuOlxyXG4gICAgICAgIHN0ZXBDbGFzcyArPSAnIGhpZGRlbic7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcblxyXG4gICAgc3dpdGNoIChzZWxlY3RlZFN0ZXAuc3RhdHVzKSB7XHJcbiAgICAgIGNhc2UgU1RFUF9TVEFUVVMuZG9uZTpcclxuICAgICAgICBzdGVwQ2xhc3MgKz0gJyBkb25lJztcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBTVEVQX1NUQVRVUy5hY3RpdmU6XHJcbiAgICAgICAgc3RlcENsYXNzICs9ICcgYWN0aXZlJztcclxuICAgICAgICBicmVhaztcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gc3RlcENsYXNzO1xyXG4gIH1cclxuXHJcbiAgX3Nob3dTZWxlY3RlZFN0ZXAoZ