@c8y/ngx-components
Version:
Angular modules for Cumulocity IoT applications
209 lines • 28.8 kB
JavaScript
import { Directionality } from '@angular/cdk/bidi';
import { CdkStepper, STEP_STATE } from '@angular/cdk/stepper';
import { ChangeDetectorRef, Component, ContentChildren, ElementRef, EventEmitter, forwardRef, Input, Output, QueryList } from '@angular/core';
import { Subject } from 'rxjs';
import { PRODUCT_EXPERIENCE_EVENT_SOURCE } from '../product-experience/product-experience.model';
import { C8yStepperIcon } from './stepper-icon.directive';
import * as i0 from "@angular/core";
import * as i1 from "@angular/cdk/bidi";
import * as i2 from "@angular/common";
import * as i3 from "./stepper-progress.component";
import * as i4 from "../i18n/c8y-translate.pipe";
/**
* `C8yStepper` extends the `CdkStepper`. You can use cdk based functionality and inputs.
* Additional to that you are able to modify the behavior and also the look and feel when
* using the `C8yStepper`.
*
* The `C8yStepper` is used to present any step-based process to the user.
* A stepper, `C8yStepper` and/or `CdkStepper` is the parent of cdk-steps.
* Each cdk-step represents one step in the whole process that you want to provide to the user.
*
* The `C8yStepper` will create, based on the given `cdk-steps`, a kind of stepper-progress which looks like this:
* `(1)---(2)---(3)---(n)`
* The stepper will handle the state of each step and provides styles for active steps, done-steps or in edit-mode.
* You are able to override icons for each step in the stepper-progress with a template. You are also able to activate
* default-icons for states like 'edit' and 'done'.
*
* To force users through every provided step, set the stepper to 'linear'.
* This will disable the possibility to move for example from step one to step three.
*
* Whenever it comes to validation try to use formGroups. It is possible to
* assign a `formGroup` to a `cdk-step` input called `[stepControl]`, which automatically respects the
* validation-rules that you created for this `formGroup`. If fields are required but not filled or
* any other validation, like a pattern, is not matched the `formGroup` will be invalid. In this case
* stepping in a linear stepper to the next step gets impossible.
*
* If there is the need to execute asynchronous code you have at least two possibilities.
* First: As you learned, a cdk-step works with `formGroups` and `Validators`, so you are able to use
* asyncValidators as well.
* Second: The `C8yStepper` provides an event-emitter `onStepChange` which is called whenever a step-button `(1)--(2)--(n)`
* in the stepper-progress is clicked. The event of this emitter holds the index of the step as number. You can
* use this `EventEmitter` to call for example a custom navigate-method which performs first any async-call and then moves
* on to the given step.
*
* ```typescript
* <c8y-stepper
* (onStepChange)="navigate($event)"
* [disableDefaultIcons]="{ edit: true, done: false }"
* [customClasses]="['m-l-40', 'm-r-40', 'm-t-32']"
* linear
* >
* <!-- override icons -->
* <ng-template c8yStepperIcon="final">
* <span [c8yIcon]="'hand-peace-o'"></span>
* </ng-template>
*
* <cdk-step [stepControl]="formGroupStepOne" label="Name of the hero">
* <div class="m-l-40 m-r-40 m-t-32">
* <h4 class="p-b-8" translate>What is the name of your hero?</h4>
* <c8y-form-group>
* <div [formGroup]="formGroupStepOne">
* <input
* class="form-control"
* type="text"
* formControlName="name"
* placeholder="Mister X"
* #nameRef
* required
* />
* <c8y-messages>
* <c8y-message *ngIf="!formGroupStepOne.untouched && !nameRef.value" translate
* >Enter the name of the Superhero</c8y-message
* >
* </c8y-messages>
* </div>
* </c8y-form-group>
* </div>
* <c8y-stepper-buttons></c8y-stepper-buttons>
* </cdk-step>
* <cdk-step>
* ...
* </cdk-step state="final">
* </c8y-stepper>
* ```
*/
export class C8yStepper extends CdkStepper {
/**
* @ignore
*/
constructor(dir, changeDetectorRef, elementRef) {
super(dir, changeDetectorRef, elementRef);
this.dir = dir;
this.changeDetectorRef = changeDetectorRef;
this.elementRef = elementRef;
/**
* Optional
* Indicator if icons for edit and done state should be shown in step-header buttons
*/
this.disableDefaultIcons = { edit: true, done: true };
/**
* Optional
* Disable/enable navigation by stepper progress buttons
* default: false
*/
this.disableProgressButtons = false;
/**
* Optional
* Possibility to hide the stepper progress completely.
*/
this.hideStepProgress = false;
/**
* Optional
* If `true`, the label defined on a cdk-step won't get rendered below each step-header button.
* Instead, it will be used as a title only.
*/
this.useStepLabelsAsTitlesOnly = false;
/**
* Will emit the step index number whenever a step-header button was clicked
* It listens to the stepIndex Subject.
* @deprecated: Use the default `selectionChange` event emitter.
*/
this.onStepChange = new EventEmitter();
/** Consumer-specified template-refs to be used to override the header icons. */
this._iconOverrides = {};
this._stepIndex = new Subject();
}
/**
* @ignore
*/
ngAfterContentInit() {
super.ngAfterContentInit();
this._icons.forEach(({ name, templateRef }) => (this._iconOverrides[name] = templateRef));
this._stepIndexSubscription = this.selectionChange.subscribe(event => this.onStepChange.emit(event.selectedIndex));
}
/**
* @ignore
*/
ngOnDestroy() {
if (this._stepIndexSubscription && !this._stepIndexSubscription.closed) {
this._stepIndexSubscription.unsubscribe();
}
}
/**
* Manipulates the state based on the disabledDefaultIcons Input()
* Changing edit or done to false will change the icons within step-header buttons
* @param index step index
* @param state step state, like 'done', 'edit', 'error'
*/
getIndicatorType(index, state) {
const stepState = this._getIndicatorType(index, state);
let _state = state;
switch (stepState) {
case STEP_STATE.EDIT:
if (!this.disableDefaultIcons.edit) {
_state = STEP_STATE.EDIT;
}
break;
case STEP_STATE.DONE:
if (!this.disableDefaultIcons.done) {
_state = STEP_STATE.DONE;
}
else {
_state = '_done';
}
break;
case STEP_STATE.ERROR:
_state = STEP_STATE.ERROR;
break;
}
return _state;
}
/**
* Pushes the step index to the subject
* @param index step index
*/
setIndex(index) {
const steps = this.steps.toArray();
if (!steps[this.selectedIndex]?.stepControl?.invalid || index < this.selectedIndex) {
this.selectedIndex = index;
}
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C8yStepper, deps: [{ token: i1.Directionality }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: C8yStepper, selector: "c8y-stepper", inputs: { disableDefaultIcons: "disableDefaultIcons", disableProgressButtons: "disableProgressButtons", customClasses: "customClasses", hideStepProgress: "hideStepProgress", useStepLabelsAsTitlesOnly: "useStepLabelsAsTitlesOnly" }, outputs: { onStepChange: "onStepChange" }, providers: [
{ provide: CdkStepper, useExisting: C8yStepper },
{ provide: PRODUCT_EXPERIENCE_EVENT_SOURCE, useExisting: forwardRef(() => C8yStepper) }
], queries: [{ propertyName: "_icons", predicate: C8yStepperIcon, descendants: true }], usesInheritance: true, ngImport: i0, template: "<ul *ngIf=\"!hideStepProgress\" class=\"c8y-stepper\" [ngClass]=\"customClasses\">\n <li *ngFor=\"let step of steps; let i = index\">\n <c8y-stepper-progress\n [iconOverrides]=\"_iconOverrides\"\n [state]=\"getIndicatorType(i, step.state)\"\n [index]=\"i\"\n [selected]=\"selectedIndex === i\"\n [disabled]=\"disableProgressButtons\"\n (onStepClicked)=\"setIndex($event)\"\n title=\"{{ step.label | translate }}\"\n [ngClass]=\"{'active': selectedIndex === i}\"\n >\n </c8y-stepper-progress>\n <div *ngIf=\"!useStepLabelsAsTitlesOnly\" class=\"c8y-step__label\" title=\"{{ step.label | translate }}\">\n {{ step.label | translate }}\n </div>\n </li>\n</ul>\n<ng-container [ngTemplateOutlet]=\"selected.content\"></ng-container>\n", 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"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.C8yStepperProgress, selector: "c8y-stepper-progress", inputs: ["iconOverrides", "index", "selected", "state", "disabled"], outputs: ["onStepClicked"] }, { kind: "pipe", type: i4.C8yTranslatePipe, name: "translate" }] }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C8yStepper, decorators: [{
type: Component,
args: [{ selector: 'c8y-stepper', providers: [
{ provide: CdkStepper, useExisting: C8yStepper },
{ provide: PRODUCT_EXPERIENCE_EVENT_SOURCE, useExisting: forwardRef(() => C8yStepper) }
], template: "<ul *ngIf=\"!hideStepProgress\" class=\"c8y-stepper\" [ngClass]=\"customClasses\">\n <li *ngFor=\"let step of steps; let i = index\">\n <c8y-stepper-progress\n [iconOverrides]=\"_iconOverrides\"\n [state]=\"getIndicatorType(i, step.state)\"\n [index]=\"i\"\n [selected]=\"selectedIndex === i\"\n [disabled]=\"disableProgressButtons\"\n (onStepClicked)=\"setIndex($event)\"\n title=\"{{ step.label | translate }}\"\n [ngClass]=\"{'active': selectedIndex === i}\"\n >\n </c8y-stepper-progress>\n <div *ngIf=\"!useStepLabelsAsTitlesOnly\" class=\"c8y-step__label\" title=\"{{ step.label | translate }}\">\n {{ step.label | translate }}\n </div>\n </li>\n</ul>\n<ng-container [ngTemplateOutlet]=\"selected.content\"></ng-container>\n" }]
}], ctorParameters: () => [{ type: i1.Directionality }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }], propDecorators: { disableDefaultIcons: [{
type: Input
}], disableProgressButtons: [{
type: Input
}], customClasses: [{
type: Input
}], hideStepProgress: [{
type: Input
}], useStepLabelsAsTitlesOnly: [{
type: Input
}], onStepChange: [{
type: Output
}], _icons: [{
type: ContentChildren,
args: [C8yStepperIcon, { descendants: true }]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcHBlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9jb3JlL3N0ZXBwZXIvc3RlcHBlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9jb3JlL3N0ZXBwZXIvc3RlcHBlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDbkQsT0FBTyxFQUFFLFVBQVUsRUFBYSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RSxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxlQUFlLEVBQ2YsVUFBVSxFQUNWLFlBQVksRUFDWixVQUFVLEVBQ1YsS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEVBRVYsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLE9BQU8sRUFBZ0IsTUFBTSxNQUFNLENBQUM7QUFDN0MsT0FBTyxFQUdMLCtCQUErQixFQUNoQyxNQUFNLGdEQUFnRCxDQUFDO0FBQ3hELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7O0FBRTFEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F3RUc7QUFTSCxNQUFNLE9BQU8sVUFDWCxTQUFRLFVBQVU7SUF3RWxCOztPQUVHO0lBQ0gsWUFDVSxHQUFtQixFQUNuQixpQkFBb0MsRUFDcEMsVUFBb0M7UUFFNUMsS0FBSyxDQUFDLEdBQUcsRUFBRSxpQkFBaUIsRUFBRSxVQUFVLENBQUMsQ0FBQztRQUpsQyxRQUFHLEdBQUgsR0FBRyxDQUFnQjtRQUNuQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ3BDLGVBQVUsR0FBVixVQUFVLENBQTBCO1FBM0U5Qzs7O1dBR0c7UUFDTSx3QkFBbUIsR0FBc0MsRUFBRSxJQUFJLEVBQUUs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LEdBQUcsRUFBRSxDQUFDLFVBQVUsQ0FBQyxFQUFFO1NBQ3hGLGlEQWlFZ0IsY0FBYyx1RUN4S2pDLDB4QkFtQkE7OzRGRHNGYSxVQUFVO2tCQVJ0QixTQUFTOytCQUNFLGFBQWEsYUFFWjt3QkFDVCxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsV0FBVyxZQUFZLEVBQUU7d0JBQ2hELEVBQUUsT0FBTyxFQUFFLCtCQUErQixFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxFQUFFO3FCQUN4Rjs0SUFVUSxtQkFBbUI7c0JBQTNCLEtBQUs7Z0JBTUcsc0JBQXNCO3NCQUE5QixLQUFLO2dCQUtHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBS0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQU1HLHlCQUF5QjtzQkFBakMsS0FBSztnQkFNSSxZQUFZO3NCQUFyQixNQUFNO2dCQTJCaUQsTUFBTTtzQkFBN0QsZUFBZTt1QkFBQyxjQUFjLEVBQUUsRUFBRSxXQUFXLEVBQUUsSUFBSSxFQUFFIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGlyZWN0aW9uYWxpdHkgfSBmcm9tICdAYW5ndWxhci9jZGsvYmlkaSc7XG5pbXBvcnQgeyBDZGtTdGVwcGVyLCBTdGVwU3RhdGUsIFNURVBfU1RBVEUgfSBmcm9tICdAYW5ndWxhci9jZGsvc3RlcHBlcic7XG5pbXBvcnQge1xuICBBZnRlckNvbnRlbnRJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgZm9yd2FyZFJlZixcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT3V0cHV0LFxuICBRdWVyeUxpc3QsXG4gIFRlbXBsYXRlUmVmXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgU3ViamVjdCwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1xuICBQcm9kdWN0RXhwZXJpZW5jZUV2ZW50LFxuICBQcm9kdWN0RXhwZXJpZW5jZUV2ZW50U291cmNlLFxuICBQUk9EVUNUX0VYUEVSSUVOQ0VfRVZFTlRfU09VUkNFXG59IGZyb20gJy4uL3Byb2R1Y3QtZXhwZXJpZW5jZS9wcm9kdWN0LWV4cGVyaWVuY2UubW9kZWwnO1xuaW1wb3J0IHsgQzh5U3RlcHBlckljb24gfSBmcm9tICcuL3N0ZXBwZXItaWNvbi5kaXJlY3RpdmUnO1xuXG4vKipcbiAqIGBDOHlTdGVwcGVyYCBleHRlbmRzIHRoZSBgQ2RrU3RlcHBlcmAuIFlvdSBjYW4gdXNlIGNkayBiYXNlZCBmdW5jdGlvbmFsaXR5IGFuZCBpbnB1dHMuXG4gKiBBZGRpdGlvbmFsIHRvIHRoYXQgeW91IGFyZSBhYmxlIHRvIG1vZGlmeSB0aGUgYmVoYXZpb3IgYW5kIGFsc28gdGhlIGxvb2sgYW5kIGZlZWwgd2hlblxuICogdXNpbmcgdGhlIGBDOHlTdGVwcGVyYC5cbiAqXG4gKiBUaGUgYEM4eVN0ZXBwZXJgIGlzIHVzZWQgdG8gcHJlc2VudCBhbnkgc3RlcC1iYXNlZCBwcm9jZXNzIHRvIHRoZSB1c2VyLlxuICogQSBzdGVwcGVyLCBgQzh5U3RlcHBlcmAgYW5kL29yIGBDZGtTdGVwcGVyYCBpcyB0aGUgcGFyZW50IG9mIGNkay1zdGVwcy5cbiAqIEVhY2ggY2RrLXN0ZXAgcmVwcmVzZW50cyBvbmUgc3RlcCBpbiB0aGUgd2hvbGUgcHJvY2VzcyB0aGF0IHlvdSB3YW50IHRvIHByb3ZpZGUgdG8gdGhlIHVzZXIuXG4gKlxuICogVGhlIGBDOHlTdGVwcGVyYCB3aWxsIGNyZWF0ZSwgYmFzZWQgb24gdGhlIGdpdmVuIGBjZGstc3RlcHNgLCBhIGtpbmQgb2Ygc3RlcHBlci1wcm9ncmVzcyB3aGljaCBsb29rcyBsaWtlIHRoaXM6XG4gKiBgKDEpLS0tKDIpLS0tKDMpLS0tKG4pYFxuICogVGhlIHN0ZXBwZXIgd2lsbCBoYW5kbGUgdGhlIHN0YXRlIG9mIGVhY2ggc3RlcCBhbmQgcHJvdmlkZXMgc3R5bGVzIGZvciBhY3RpdmUgc3RlcHMsIGRvbmUtc3RlcHMgb3IgaW4gZWRpdC1tb2RlLlxuICogWW91IGFyZSBhYmxlIHRvIG92ZXJyaWRlIGljb25zIGZvciBlYWNoIHN0ZXAgaW4gdGhlIHN0ZXBwZXItcHJvZ3Jlc3Mgd2l0aCBhIHRlbXBsYXRlLiBZb3UgYXJlIGFsc28gYWJsZSB0byBhY3RpdmF0ZVxuICogZGVmYXVsdC1pY29ucyBmb3Igc3RhdGVzIGxpa2UgJ2VkaXQnIGFuZCAnZG9uZScuXG4gKlxuICogVG8gZm9yY2UgdXNlcnMgdGhyb3VnaCBldmVyeSBwcm92aWRlZCBzdGVwLCBzZXQgdGhlIHN0ZXBwZXIgdG8gJ2xpbmVhcicuXG4gKiBUaGlzIHdpbGwgZGlzYWJsZSB0aGUgcG9zc2liaWxpdHkgdG8gbW92ZSBmb3IgZXhhbXBsZSBmcm9tIHN0ZXAgb25lIHRvIHN0ZXAgdGhyZWUuXG4gKlxuICogV2hlbmV2ZXIgaXQgY29tZXMgdG8gdmFsaWRhdGlvbiB0cnkgdG8gdXNlIGZvcm1Hcm91cHMuIEl0IGlzIHBvc3NpYmxlIHRvXG4gKiBhc3NpZ24gYSBgZm9ybUdyb3VwYCB0byBhIGBjZGstc3RlcGAgaW5wdXQgY2FsbGVkIGBbc3RlcENvbnRyb2xdYCwgd2hpY2ggYXV0b21hdGljYWxseSByZXNwZWN0cyB0aGVcbiAqIHZhbGlkYXRpb24tcnVsZXMgdGhhdCB5b3UgY3JlYXRlZCBmb3IgdGhpcyBgZm9ybUdyb3VwYC4gSWYgZmllbGRzIGFyZSByZXF1aXJlZCBidXQgbm90IGZpbGxlZCBvclxuICogYW55IG90aGVyIHZhbGlkYXRpb24sIGxpa2UgYSBwYXR0ZXJuLCBpcyBub3QgbWF0Y2hlZCB0aGUgYGZvcm1Hcm91cGAgd2lsbCBiZSBpbnZhbGlkLiBJbiB0aGlzIGNhc2VcbiAqIHN0ZXBwaW5nIGluIGEgbGluZWFyIHN0ZXBwZXIgdG8gdGhlIG5leHQgc3RlcCBnZXRzIGltcG9zc2libGUuXG4gKlxuICogSWYgdGhlcmUgaXMgdGhlIG5lZWQgdG8gZXhlY3V0ZSBhc3luY2hyb25vdXMgY29kZSB5b3UgaGF2ZSBhdCBsZWFzdCB0d28gcG9zc2liaWxpdGllcy5cbiAqIEZpcnN0OiBBcyB5b3UgbGVhcm5lZCwgYSBjZGstc3RlcCB3b3JrcyB3aXRoIGBmb3JtR3JvdXBzYCBhbmQgYFZhbGlkYXRvcnNgLCBzbyB5b3UgYXJlIGFibGUgdG8gdXNlXG4gKiBhc3luY1ZhbGlkYXRvcnMgYXMgd2VsbC5cbiAqIFNlY29uZDogVGhlIGBDOHlTdGVwcGVyYCBwcm92aWRlcyBhbiBldmVudC1lbWl0dGVyIGBvblN0ZXBDaGFuZ2VgIHdoaWNoIGlzIGNhbGxlZCB3aGVuZXZlciBhIHN0ZXAtYnV0dG9uIGAoMSktLSgyKS0tKG4pYFxuICogaW4gdGhlIHN0ZXBwZXItcHJvZ3Jlc3MgaXMgY2xpY2tlZC4gVGhlIGV2ZW50IG9mIHRoaXMgZW1pdHRlciBob2xkcyB0aGUgaW5kZXggb2YgdGhlIHN0ZXAgYXMgbnVtYmVyLiBZb3UgY2FuXG4gKiB1c2UgdGhpcyBgRXZlbnRFbWl0dGVyYCB0byBjYWxsIGZvciBleGFtcGxlIGEgY3VzdG9tIG5hdmlnYXRlLW1ldGhvZCB3aGljaCBwZXJmb3JtcyBmaXJzdCBhbnkgYXN5bmMtY2FsbCBhbmQgdGhlbiBtb3Zlc1xuICogb24gdG8gdGhlIGdpdmVuIHN0ZXAuXG4gKlxuICogYGBgdHlwZXNjcmlwdFxuICogPGM4eS1zdGVwcGVyXG4gKiAob25TdGVwQ2hhbmdlKT1cIm5hdmlnYXRlKCRldmVudClcIlxuICogW2Rpc2FibGVEZWZhdWx0SWNvbnNdPVwieyBlZGl0OiB0cnVlLCBkb25lOiBmYWxzZSB9XCJcbiAqIFtjdXN0b21DbGFzc2VzXT1cIlsnbS1sLTQwJywgJ20tci00MCcsICdtLXQtMzInXVwiXG4gKiBsaW5lYXJcbiAqID5cbiAqIDwhLS0gb3ZlcnJpZGUgaWNvbnMgLS0+XG4gKiA8bmctdGVtcGxhdGUgYzh5U3RlcHBlckljb249XCJmaW5hbFwiPlxuICogICA8c3BhbiBbYzh5SWNvbl09XCInaGFuZC1wZWFjZS1vJ1wiPjwvc3Bhbj5cbiAqIDwvbmctdGVtcGxhdGU+XG4gKlxuICogPGNkay1zdGVwIFtzdGVwQ29udHJvbF09XCJmb3JtR3JvdXBTdGVwT25lXCIgbGFiZWw9XCJOYW1lIG9mIHRoZSBoZXJvXCI+XG4gKiAgIDxkaXYgY2xhc3M9XCJtLWwtNDAgbS1yLTQwIG0tdC0zMlwiPlxuICogICAgIDxoNCBjbGFzcz1cInAtYi04XCIgdHJhbnNsYXRlPldoYXQgaXMgdGhlIG5hbWUgb2YgeW91ciBoZXJvPzwvaDQ+XG4gKiAgICAgPGM4eS1mb3JtLWdyb3VwPlxuICogICAgICA8ZGl2IFtmb3JtR3JvdXBdPVwiZm9ybUdyb3VwU3RlcE9uZVwiPlxuICogICAgICAgPGlucHV0XG4gKiAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAqICAgICAgICAgdHlwZT1cInRleHRcIlxuICogICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCJcbiAqICAgICAgICAgcGxhY2Vob2xkZXI9XCJNaXN0ZXIgWFwiXG4gKiAgICAgICAgICNuYW1lUmVmXG4gKiAgICAgICAgIHJlcXVpcmVkXG4gKiAgICAgICAvPlxuICogICAgICAgPGM4eS1tZXNzYWdlcz5cbiAqICAgICAgICAgPGM4eS1tZXNzYWdlICpuZ0lmPVwiIWZvcm1Hcm91cFN0ZXBPbmUudW50b3VjaGVkICYmICFuYW1lUmVmLnZhbHVlXCIgdHJhbnNsYXRlXG4gKiAgICAgICAgICAgPkVudGVyIHRoZSBuYW1lIG9mIHRoZSBTdXBlcmhlcm88L2M4eS1tZXNzYWdlXG4gKiAgICAgICAgID5cbiAqICAgICAgIDwvYzh5LW1lc3NhZ2VzPlxuICogICAgICA8L2Rpdj5cbiAqICAgICA8L2M4eS1mb3JtLWdyb3VwPlxuICogICA8L2Rpdj5cbiAqICAgPGM4eS1zdGVwcGVyLWJ1dHRvbnM+PC9jOHktc3RlcHBlci1idXR0b25zPlxuICogPC9jZGstc3RlcD5cbiAqIDxjZGstc3RlcD5cbiAqICAuLi5cbiAqIDwvY2RrLXN0ZXAgc3RhdGU9XCJmaW5hbFwiPlxuICogPC9jOHktc3RlcHBlcj5cbiAqIGBgYFxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjOHktc3RlcHBlcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9zdGVwcGVyLmNvbXBvbmVudC5odG1sJyxcbiAgcHJvdmlkZXJzOiBbXG4gICAgeyBwcm92aWRlOiBDZGtTdGVwcGVyLCB1c2VFeGlzdGluZzogQzh5U3RlcHBlciB9LFxuICAgIHsgcHJvdmlkZTogUFJPRFVDVF9FWFBFUklFTkNFX0VWRU5UX1NPVVJDRSwgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gQzh5U3RlcHBlcikgfVxuICBdXG59KVxuZXhwb3J0IGNsYXNzIEM4eVN0ZXBwZXJcbiAgZXh0ZW5kcyBDZGtTdGVwcGVyXG4gIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgT25EZXN0cm95LCBQcm9kdWN0RXhwZXJpZW5jZUV2ZW50U291cmNlXG57XG4gIC8qKlxuICAgKiBPcHRpb25hbFxuICAgKiBJbmRpY2F0b3IgaWYgaWNvbnMgZm9yIGVkaXQgYW5kIGRvbmUgc3RhdGUgc2hvdWxkIGJlIHNob3duIGluIHN0ZXAtaGVhZGVyIGJ1dHRvbnNcbiAgICovXG4gIEBJbnB1dCgpIGRpc2FibGVEZWZhdWx0SWNvbnM/OiB7IGVkaXQ6IGJvb2xlYW47IGRvbmU6IGJvb2xlYW4gfSA9IHsgZWRpdDogdHJ1ZSwgZG9uZTogdHJ1ZSB9O1xuICAvKipcbiAgICogT3B0aW9uYWxcbiAgICogRGlzYWJsZS9lbmFibGUgbmF2aWdhdGlvbiBieSBzdGVwcGVyIHByb2dyZXNzIGJ1dHRvbnNcbiAgICogZGVmYXVsdDogZmFsc2VcbiAgICovXG4gIEBJbnB1dCgpIGRpc2FibGVQcm9ncmVzc0J1dHRvbnM/OiBib29sZWFuID0gZmFsc2U7XG4gIC8qKlxuICAgKiBPcHRpb25hbFxuICAgKiBQb3NzaWJpbGl0eSB0byBhZGQgYW55IGtpbmQgb2YgY3VzdG9tIGNzcyBjbGFzc2VzIHRvIHRoZSBzdGVwLWhlYWRlclxuICAgKi9cbiAgQElucHV0KCkgY3VzdG9tQ2xhc3Nlcz86IHN0cmluZ1tdO1xuICAvKipcbiAgICogT3B0aW9uYWxcbiAgICogUG9zc2liaWxpdHkgdG8gaGlkZSB0aGUgc3RlcHBlciBwcm9ncmVzcyBjb21wbGV0ZWx5LlxuICAgKi9cbiAgQElucHV0KCkgaGlkZVN0ZXBQcm9ncmVzcz86IGJvb2xlYW4gPSBmYWxzZTtcbiAgLyoqXG4gICAqIE9wdGlvbmFsXG4gICAqIElmIGB0cnVlYCwgdGhlIGxhYmVsIGRlZmluZWQgb24gYSBjZGstc3RlcCB3b24ndCBnZXQgcmVuZGVyZWQgYmVsb3cgZWFjaCBzdGVwLWhlYWRlciBidXR0b24uXG4gICAqIEluc3RlYWQsIGl0IHdpbGwgYmUgdXNlZCBhcyBhIHRpdGxlIG9ubHkuXG4gICAqL1xuICBASW5wdXQoKSB1c2VTdGVwTGFiZWxzQXNUaXRsZXNPbmx5PzogYm9vbGVhbiA9IGZhbHNlO1xuICAvKipcbiAgICogV2lsbCBlbWl0IHRoZSBzdGVwIGluZGV4IG51bWJlciB3aGVuZXZlciBhIHN0ZXAtaGVhZGVyIGJ1dHRvbiB3YXMgY2xpY2tlZFxuICAgKiBJdCBsaXN0ZW5zIHRvIHRoZSBzdGVwSW5kZXggU3ViamVjdC5cbiAgICogQGRlcHJlY2F0ZWQ6IFVzZSB0aGUgZGVmYXVsdCBgc2VsZWN0aW9uQ2hhbmdlYCBldmVudCBlbWl0dGVyLlxuICAgKi9cbiAgQE91dHB1dCgpIG9uU3RlcENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gIC8qKlxuICAgKiBIb2xkaW5nIGEgUXVlcnlMaXN0IG9mIEM4eVN0ZXBwZXJJY29uc1xuICAgKiBUaGVzZSBhcmUgdGVtcGxhdGVSZWZzIHdoaWNoIG92ZXJyaWRlcyBhbnkgc3RlcC1oZWFkZXIgYnV0dG9uIGljb24gd2l0aCBtYXRjaGluZyBzdGF0ZSBvZiBjZGstc3RlcFxuICAgKlxuICAgKiBgYGB0eXBlc2NyaXB0XG4gICAqIDwhLS0gb3ZlcnJpZGUgaWNvbnMgLS0+XG4gICAqICA8bmctdGVtcGxhdGUgYzh5U3RlcHBlckljb249XCJmaW5hbFwiPlxuICAgKiAgIDxzcGFuIFtjOHlJY29uXT1cIidoYW5kLXBlYWNlLW8nXCI+PC9zcGFuPlxuICAgKiAgPC9uZy10ZW1wbGF0ZT5cbiAgICpcbiAgICogPGNkay1zdGVwIHN0YXRlPVwiZmluYWxcIiBsYWJlbD1cIkpvYiBkb25lIVwiPlxuICAgKiAgPGRpdiBjbGFzcz1cIm0tbC00MCBtLXItNDAgbS10LTMyXCI+XG4gICAqICAgIDxoNCBjbGFzcz1cInAtYi0zMlwiIHN0eWxlPVwidGV4dC1hbGlnbjogY2VudGVyO1wiIHRyYW5zbGF0ZT5cbiAgICogICAgIFlvdXIgU3VwZXJoZXJvIGlzIG5vdyByZWFkeSB0byBzYXZlIHRoZSB3b3JsZCFcbiAgICogICA8L2g0PlxuICAgKiAgPC9kaXY+XG4gICAqICA8Yzh5LXN0ZXBwZXItYnV0dG9uc1xuICAgKiAgICBbaGlkZGVuXT1cIiFpc01vZGFsXCJcbiAgICogICAgKG9uQmFjayk9XCJjbG9zZSgpXCJcbiAgICogICAgW2xhYmVsc109XCJ7IGJhY2s6ICdHb3QgaXQhJyB9XCJcbiAgICogID48L2M4eS1zdGVwcGVyLWJ1dHRvbnM+XG4gICAqICA8Yzh5LXN0ZXBwZXItYnV0dG9ucyBbaGlkZGVuXT1cImlzTW9kYWxcIj48L2M4eS1zdGVwcGVyLWJ1dHRvbnM+XG4gICAqIDwvY2RrLXN0ZXA+XG4gICAqIGBgYFxuICAgKi9cbiAgQENvbnRlbnRDaGlsZHJlbihDOHlTdGVwcGVySWNvbiwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KSBfaWNvbnM6IFF1ZXJ5TGlzdDxDOHlTdGVwcGVySWNvbj47XG5cbiAgLyoqIENvbnN1bWVyLXNwZWNpZmllZCB0ZW1wbGF0ZS1yZWZzIHRvIGJlIHVzZWQgdG8gb3ZlcnJpZGUgdGhlIGhlYWRlciBpY29ucy4gKi9cbiAgX2ljb25PdmVycmlkZXM6IHsgW2tleTogc3RyaW5nXTogVGVtcGxhdGVSZWY8YW55PiB9ID0ge307XG5cbiAgcHJvZHVjdEV4cGVyaWVuY2VFdmVudDogUHJvZHVjdEV4cGVyaWVuY2VFdmVudDtcblxuICBwcml2YXRlIF9zdGVwSW5kZXg6IFN1YmplY3Q8bnVtYmVyPiA9IG5ldyBTdWJqZWN0KCk7XG4gIHByaXZhdGUgX3N0ZXBJbmRleFN1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuXG4gIC8qKlxuICAgKiBAaWdub3JlXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGRpcjogRGlyZWN0aW9uYWxpdHksXG4gICAgcHJpdmF0ZSBjaGFuZ2VEZXRlY3RvclJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gICAgcHJpdmF0ZSBlbGVtZW50UmVmPzogRWxlbWVudFJlZjxIVE1MRWxlbWVudD5cbiAgKSB7XG4gICAgc3VwZXIoZGlyLCBjaGFuZ2VEZXRlY3RvclJlZiwgZWxlbWVudFJlZik7XG4gIH1cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgIHN1cGVyLm5nQWZ0ZXJDb250ZW50SW5pdCgpO1xuICAgIHRoaXMuX2ljb25zLmZvckVhY2goKHsgbmFtZSwgdGVtcGxhdGVSZWYgfSkgPT4gKHRoaXMuX2ljb25PdmVycmlkZXNbbmFtZV0gPSB0ZW1wbGF0ZVJlZikpO1xuICAgIHRoaXMuX3N0ZXBJbmRleFN1YnNjcmlwdGlvbiA9IHRoaXMuc2VsZWN0aW9uQ2hhbmdlLnN1YnNjcmliZShldmVudCA9PlxuICAgICAgdGhpcy5vblN0ZXBDaGFuZ2UuZW1pdChldmVudC5zZWxlY3RlZEluZGV4KVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQGlnbm9yZVxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgaWYgKHRoaXMuX3N0ZXBJbmRleFN1YnNjcmlwdGlvbiAmJiAhdGhpcy5fc3RlcEluZGV4U3Vic2NyaXB0aW9uLmNsb3NlZCkge1xuICAgICAgdGhpcy5fc3RlcEluZGV4U3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hbmlwdWxhdGVzIHRoZSBzdGF0ZSBiYXNlZCBvbiB0aGUgZGlzYWJsZWREZWZhdWx0SWNvbnMgSW5wdXQoKVxuICAgKiBDaGFuZ2luZyBlZGl0IG9yIGRvbmUgdG8gZmFsc2Ugd2lsbCBjaGFuZ2UgdGhlIGljb25zIHdpdGhpbiBzdGVwLWhlYWRlciBidXR0b25zXG4gICAqIEBwYXJhbSBpbmRleCBzdGVwIGluZGV4XG4gICAqIEBwYXJhbSBzdGF0ZSBzdGVwIHN0YXRlLCBsaWtlICdkb25lJywgJ2VkaXQnLCAnZXJyb3InXG4gICAqL1xuICBnZXRJbmRpY2F0b3JUeXBlKGluZGV4OiBudW1iZXIsIHN0YXRlOiBTdGVwU3RhdGUpIHtcbiAgICBjb25zdCBzdGVwU3RhdGUgPSB0aGlzLl9nZXRJbmRpY2F0b3JUeXBlKGluZGV4LCBzdGF0ZSk7XG4gICAgbGV0IF9zdGF0ZSA9IHN0YXRlO1xuICAgIHN3aXRjaCAoc3RlcFN0YXRlKSB7XG4gICAgICBjYXNlIFNURVBfU1RBVEUuRURJVDpcbiAgICAgICAgaWYgKCF0aGlzLmRpc2FibGVEZWZhdWx0SWNvbnMuZWRpdCkge1xuICAgICAgICAgIF9zdGF0ZSA9IFNURVBfU1RBVEUuRURJVDtcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBTVEVQX1NUQVRFLkRPTkU6XG4gICAgICAgIGlmICghdGhpcy5kaXNhYmxlRGVmYXVsdEljb25zLmRvbmUpIHtcbiAgICAgICAgICBfc3RhdGUgPSBTVEVQX1NUQVRFLkRPTkU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgX3N0YXRlID0gJ19kb25lJztcbiAgICAgICAgfVxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSBTVEVQX1NUQVRFLkVSUk9SOlxuICAgICAgICBfc3RhdGUgPSBTVEVQX1NUQVRFLkVSUk9SO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmV0dXJuIF9zdGF0ZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdXNoZXMgdGhlIHN0ZXAgaW5kZXggdG8gdGhlIHN1YmplY3RcbiAgICogQHBhcmFtIGluZGV4IHN0ZXAgaW5kZXhcbiAgICovXG4gIHNldEluZGV4KGluZGV4OiBudW1iZXIpIHtcbiAgICBjb25zdCBzdGVwcyA9IHRoaXMuc3RlcHMudG9BcnJheSgpO1xuICAgIGlmICghc3RlcHNbdGhpcy5zZWxlY3RlZEluZGV4XT8uc3RlcENvbnRyb2w/LmludmFsaWQgfHwgaW5kZXggPCB0aGlzLnNlbGVjdGVkSW5kZXgpIHtcbiAgICAgIHRoaXMuc2VsZWN0ZWRJbmRleCA9IGluZGV4O1xuICAgIH1cbiAgfVxufVxuIiwiPHVsICpuZ0lmPVwiIWhpZGVTdGVwUHJvZ3Jlc3NcIiBjbGFzcz1cImM4eS1zdGVwcGVyXCIgW25nQ2xhc3NdPVwiY3VzdG9tQ2xhc3Nlc1wiPlxuICA8bGkgKm5nRm9yPVwibGV0IHN0ZXAgb2Ygc3RlcHM7IGxldCBpID0gaW5kZXhcIj5cbiAgICA8Yzh5LXN0ZXBwZXItcHJvZ3Jlc3NcbiAgICAgIFtpY29uT3ZlcnJpZGVzXT1cIl9pY29uT3ZlcnJpZGVzXCJcbiAgICAgIFtzdGF0ZV09XCJnZXRJbmRpY2F0b3JUeXBlKGksIHN0ZXAuc3RhdGUpXCJcbiAgICAgIFtpbmRleF09XCJpXCJcbiAgICAgIFtzZWxlY3RlZF09XCJzZWxlY3RlZEluZGV4ID09PSBpXCJcbiAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlUHJvZ3Jlc3NCdXR0b25zXCJcbiAgICAgIChvblN0ZXBDbGlja2VkKT1cInNldEluZGV4KCRldmVudClcIlxuICAgICAgdGl0bGU9XCJ7eyBzdGVwLmxhYmVsIHwgdHJhbnNsYXRlIH19XCJcbiAgICAgIFtuZ0NsYXNzXT1cInsnYWN0aXZlJzogc2VsZWN0ZWRJbmRleCA9PT0gaX1cIlxuICAgID5cbiAgICA8L2M4eS1zdGVwcGVyLXByb2dyZXNzPlxuICAgIDxkaXYgKm5nSWY9XCIhdXNlU3RlcExhYmVsc0FzVGl0bGVzT25seVwiIGNsYXNzPVwiYzh5LXN0ZXBfX2xhYmVsXCIgIHRpdGxlPVwie3sgc3RlcC5sYWJlbCB8IHRyYW5zbGF0ZSB9fVwiPlxuICAgICAge3sgc3RlcC5sYWJlbCB8IHRyYW5zbGF0ZSB9fVxuICAgIDwvZGl2PlxuICA8L2xpPlxuPC91bD5cbjxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwic2VsZWN0ZWQuY29udGVudFwiPjwvbmctY29udGFpbmVyPlxuIl19