UNPKG

design-angular-kit

Version:

Un toolkit Angular conforme alle linee guida di design per i servizi web della PA

130 lines 32.6 kB
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { debounceTime, distinctUntilChanged, filter } from 'rxjs'; import { LowerCasePipe } from '@angular/common'; import { ItIconComponent } from '../../utils/icon/icon.component'; import { TranslateModule } from '@ngx-translate/core'; import { ItDropdownModule } from '../dropdown/dropdown.module'; import { ItInputComponent } from '../../form/input/input.component'; import { inputToBoolean } from '../../../utils/coercion'; import * as i0 from "@angular/core"; import * as i1 from "@ngx-translate/core"; import * as i2 from "../dropdown/dropdown/dropdown.component"; import * as i3 from "../dropdown/dropdown-item/dropdown-item.component"; import * as i4 from "@angular/forms"; export class ItPaginationComponent { constructor() { /** * Number of pages closest to the current one to display * @default 5 */ this.visiblePages = 5; /** * Available Changer values * @default [10, 25, 50, 100] */ this.changerValues = [10, 25, 50, 100]; /** * Fired when page is changed. Emit the new index of page */ this.pageEvent = new EventEmitter(); /** * Fired when changer is changed. Emit the new changer value */ this.changerEvent = new EventEmitter(); /** * The pages * @protected */ this.pages = []; /** * Jump to page input * @protected */ this.jumpToPage = new FormControl(null); this.jumpToPage.valueChanges .pipe(debounceTime(300), // Delay filter data after time span has passed without another source emission distinctUntilChanged(), filter(value => !!value && this.jumpToPage.valid)) .subscribe(value => { this.pageEvent.emit(value - 1); }); } ngOnChanges(changes) { this.pages = this.calculatePages(); if (changes['currentPage']) { this.jumpToPage.setValue(null, { emitEvent: false }); } } /** * Create array to generate pagination of `visiblePages` element */ calculatePages() { if (this.simpleMode) { return [this.currentPage]; } const length = this.pageNumbers > this.visiblePages ? this.visiblePages : this.pageNumbers; const halfVisiblePages = Math.floor(this.visiblePages / 2); let start = this.currentPage > halfVisiblePages && this.pageNumbers > this.visiblePages ? this.currentPage - halfVisiblePages + 1 : 1; if (this.pageNumbers > this.visiblePages) { if (this.currentPage + 1 >= this.pageNumbers) { start -= halfVisiblePages; } else if (this.currentPage >= this.pageNumbers - halfVisiblePages) { start -= this.pageNumbers - (this.currentPage + 1); } } return Array.from({ length }, (_, i) => i + start); } /** * On click page change * @param event click event * @param newPage the new page of table */ pageChange(event, newPage) { event.preventDefault(); this.pageEvent.emit(newPage - 1); // emit new page index } /** * On click changer * @param event click event * @param value the new changer value */ changerChange(event, value) { event.preventDefault(); this.changerEvent.emit(value); // emit new changer value } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: ItPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.6", type: ItPaginationComponent, isStandalone: true, selector: "it-pagination", inputs: { currentPage: "currentPage", pageNumbers: "pageNumbers", visiblePages: "visiblePages", alignment: "alignment", simpleMode: ["simpleMode", "simpleMode", inputToBoolean], textLinks: ["textLinks", "textLinks", inputToBoolean], currentChanger: "currentChanger", changerValues: "changerValues", showJumpToPage: ["showJumpToPage", "showJumpToPage", inputToBoolean] }, outputs: { pageEvent: "pageEvent", changerEvent: "changerEvent" }, usesOnChanges: true, ngImport: i0, template: "<nav\n class=\"pagination-wrapper\"\n [class.justify-content-center]=\"alignment === 'center'\"\n [class.justify-content-end]=\"alignment === 'end'\"\n [class.pagination-total]=\"totalNumberText.hasChildNodes()\">\n @if (pages.length) {\n <ul class=\"pagination\">\n <li class=\"page-item\" [class.disabled]=\"currentPage < 1\">\n <a class=\"page-link\" [class.text]=\"textLinks\" href=\"#\" (click)=\"pageChange($event, currentPage)\">\n @if (!textLinks) {\n <it-icon name=\"chevron-left\" color=\"primary\"></it-icon>\n }\n <span class=\"visually-hidden\">\n {{ (textLinks ? 'it.core.page' : 'it.core.previous-page') | translate }}\n </span>\n @if (textLinks) {\n {{ 'it.core.previous' | translate }}\n }\n </a>\n </li>\n @if (simpleMode) {\n <li class=\"page-item\">\n <span class=\"page-link\" aria-current=\"page\">{{ currentPage + 1 }}</span>\n </li>\n <li class=\"page-item\"><span class=\"page-link\">/</span></li>\n <li class=\"page-item\">\n <span class=\"page-link\">{{ pageNumbers }}</span>\n </li>\n <li class=\"page-item visually-hidden\">\n <a class=\"page-link\" href=\"#\" aria-current=\"page\">\n {{ 'it.core.page-of-total' | translate: { page: currentPage + 1, total: pageNumbers } }}\n </a>\n </li>\n } @else {\n @if (pageNumbers > visiblePages && pages[0] >= 2) {\n <li class=\"page-item\">\n <a class=\"page-link\" href=\"#\" (click)=\"pageChange($event, 1)\">1</a>\n </li>\n @if (pages[0] >= 3) {\n <li class=\"page-item\">\n <span class=\"page-link\">...</span>\n </li>\n }\n }\n @for (page of pages; track page) {\n <li class=\"page-item\">\n @if (page === currentPage + 1) {\n <a class=\"page-link\" aria-current=\"page\">\n <span class=\"d-inline-block d-sm-none\">{{ 'it.core.page' | translate }}</span> {{ page }}\n </a>\n } @else {\n <a class=\"page-link\" href=\"#\" (click)=\"pageChange($event, page)\">{{ page }}</a>\n }\n </li>\n }\n @if (pageNumbers > visiblePages && pages[pages.length - 1] < pageNumbers) {\n @if (pages[pages.length - 1] < pageNumbers - 1) {\n <li class=\"page-item\">\n <span class=\"page-link\">...</span>\n </li>\n }\n <li class=\"page-item\">\n <a class=\"page-link\" href=\"#\" (click)=\"pageChange($event, pageNumbers)\">{{ pageNumbers }}</a>\n </li>\n }\n }\n <li class=\"page-item\" [class.disabled]=\"currentPage >= pageNumbers - 1\">\n <a class=\"page-link\" [class.text]=\"textLinks\" href=\"#\" (click)=\"pageChange($event, currentPage + 2)\">\n <span class=\"visually-hidden\">\n {{ (textLinks ? 'it.core.page' : 'it.core.next-page') | translate }}\n </span>\n @if (textLinks) {\n {{ 'it.core.next' | translate }}\n } @else {\n <it-icon name=\"chevron-right\" color=\"primary\"></it-icon>\n }\n </a>\n </li>\n </ul>\n }\n\n @if (currentChanger !== undefined) {\n <it-dropdown>\n <span button>{{ currentChanger }} / {{ 'it.core.page' | translate | lowercase }}</span>\n <ng-container list>\n @for (value of changerValues; track value) {\n <it-dropdown-item href=\"#\" externalLink=\"true\" (click)=\"changerChange($event, value)\">\n {{ value }} / {{ 'it.core.page' | translate | lowercase }}\n </it-dropdown-item>\n }\n </ng-container>\n </it-dropdown>\n }\n\n @if (showJumpToPage) {\n <it-input\n type=\"number\"\n [min]=\"1\"\n [max]=\"pageNumbers\"\n [label]=\"('it.core.go-to' | translate) + '...'\"\n [formControl]=\"jumpToPage\"></it-input>\n }\n\n <p [class.d-none]=\"!totalNumberText.hasChildNodes()\" #totalNumberText>\n <ng-content></ng-content>\n </p>\n</nav>\n", dependencies: [{ kind: "component", type: ItIconComponent, selector: "it-icon", inputs: ["name", "size", "color", "padded", "svgClass", "title", "labelWaria"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "pipe", type: LowerCasePipe, name: "lowercase" }, { kind: "ngmodule", type: ItDropdownModule }, { kind: "component", type: i2.ItDropdownComponent, selector: "it-dropdown", inputs: ["mode", "color", "direction", "fullWidth", "megamenu", "dark"], outputs: ["showEvent", "shownEvent", "hideEvent", "hiddenEvent"], exportAs: ["itDropdown"] }, { kind: "component", type: i3.ItDropdownItemComponent, selector: "it-dropdown-item", inputs: ["divider", "active", "large", "iconName", "iconPosition", "mode"] }, { kind: "component", type: ItInputComponent, selector: "it-input", inputs: ["type", "placeholder", "description", "readonly", "maxDate", "minDate", "max", "min", "step", "currency", "percentage", "symbol", "adaptive", "autocomplete"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.6", ngImport: i0, type: ItPaginationComponent, decorators: [{ type: Component, args: [{ standalone: true, selector: 'it-pagination', changeDetection: ChangeDetectionStrategy.OnPush, imports: [ItIconComponent, TranslateModule, LowerCasePipe, ItDropdownModule, ItInputComponent, ReactiveFormsModule], template: "<nav\n class=\"pagination-wrapper\"\n [class.justify-content-center]=\"alignment === 'center'\"\n [class.justify-content-end]=\"alignment === 'end'\"\n [class.pagination-total]=\"totalNumberText.hasChildNodes()\">\n @if (pages.length) {\n <ul class=\"pagination\">\n <li class=\"page-item\" [class.disabled]=\"currentPage < 1\">\n <a class=\"page-link\" [class.text]=\"textLinks\" href=\"#\" (click)=\"pageChange($event, currentPage)\">\n @if (!textLinks) {\n <it-icon name=\"chevron-left\" color=\"primary\"></it-icon>\n }\n <span class=\"visually-hidden\">\n {{ (textLinks ? 'it.core.page' : 'it.core.previous-page') | translate }}\n </span>\n @if (textLinks) {\n {{ 'it.core.previous' | translate }}\n }\n </a>\n </li>\n @if (simpleMode) {\n <li class=\"page-item\">\n <span class=\"page-link\" aria-current=\"page\">{{ currentPage + 1 }}</span>\n </li>\n <li class=\"page-item\"><span class=\"page-link\">/</span></li>\n <li class=\"page-item\">\n <span class=\"page-link\">{{ pageNumbers }}</span>\n </li>\n <li class=\"page-item visually-hidden\">\n <a class=\"page-link\" href=\"#\" aria-current=\"page\">\n {{ 'it.core.page-of-total' | translate: { page: currentPage + 1, total: pageNumbers } }}\n </a>\n </li>\n } @else {\n @if (pageNumbers > visiblePages && pages[0] >= 2) {\n <li class=\"page-item\">\n <a class=\"page-link\" href=\"#\" (click)=\"pageChange($event, 1)\">1</a>\n </li>\n @if (pages[0] >= 3) {\n <li class=\"page-item\">\n <span class=\"page-link\">...</span>\n </li>\n }\n }\n @for (page of pages; track page) {\n <li class=\"page-item\">\n @if (page === currentPage + 1) {\n <a class=\"page-link\" aria-current=\"page\">\n <span class=\"d-inline-block d-sm-none\">{{ 'it.core.page' | translate }}</span> {{ page }}\n </a>\n } @else {\n <a class=\"page-link\" href=\"#\" (click)=\"pageChange($event, page)\">{{ page }}</a>\n }\n </li>\n }\n @if (pageNumbers > visiblePages && pages[pages.length - 1] < pageNumbers) {\n @if (pages[pages.length - 1] < pageNumbers - 1) {\n <li class=\"page-item\">\n <span class=\"page-link\">...</span>\n </li>\n }\n <li class=\"page-item\">\n <a class=\"page-link\" href=\"#\" (click)=\"pageChange($event, pageNumbers)\">{{ pageNumbers }}</a>\n </li>\n }\n }\n <li class=\"page-item\" [class.disabled]=\"currentPage >= pageNumbers - 1\">\n <a class=\"page-link\" [class.text]=\"textLinks\" href=\"#\" (click)=\"pageChange($event, currentPage + 2)\">\n <span class=\"visually-hidden\">\n {{ (textLinks ? 'it.core.page' : 'it.core.next-page') | translate }}\n </span>\n @if (textLinks) {\n {{ 'it.core.next' | translate }}\n } @else {\n <it-icon name=\"chevron-right\" color=\"primary\"></it-icon>\n }\n </a>\n </li>\n </ul>\n }\n\n @if (currentChanger !== undefined) {\n <it-dropdown>\n <span button>{{ currentChanger }} / {{ 'it.core.page' | translate | lowercase }}</span>\n <ng-container list>\n @for (value of changerValues; track value) {\n <it-dropdown-item href=\"#\" externalLink=\"true\" (click)=\"changerChange($event, value)\">\n {{ value }} / {{ 'it.core.page' | translate | lowercase }}\n </it-dropdown-item>\n }\n </ng-container>\n </it-dropdown>\n }\n\n @if (showJumpToPage) {\n <it-input\n type=\"number\"\n [min]=\"1\"\n [max]=\"pageNumbers\"\n [label]=\"('it.core.go-to' | translate) + '...'\"\n [formControl]=\"jumpToPage\"></it-input>\n }\n\n <p [class.d-none]=\"!totalNumberText.hasChildNodes()\" #totalNumberText>\n <ng-content></ng-content>\n </p>\n</nav>\n" }] }], ctorParameters: () => [], propDecorators: { currentPage: [{ type: Input, args: [{ required: true }] }], pageNumbers: [{ type: Input, args: [{ required: true }] }], visiblePages: [{ type: Input }], alignment: [{ type: Input }], simpleMode: [{ type: Input, args: [{ transform: inputToBoolean }] }], textLinks: [{ type: Input, args: [{ transform: inputToBoolean }] }], currentChanger: [{ type: Input }], changerValues: [{ type: Input }], showJumpToPage: [{ type: Input, args: [{ transform: inputToBoolean }] }], pageEvent: [{ type: Output }], changerEvent: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnaW5hdGlvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9kZXNpZ24tYW5ndWxhci1raXQvc3JjL2xpYi9jb21wb25lbnRzL2NvcmUvcGFnaW5hdGlvbi9wYWdpbmF0aW9uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rlc2lnbi1hbmd1bGFyLWtpdC9zcmMvbGliL2NvbXBvbmVudHMvY29yZS9wYWdpbmF0aW9uL3BhZ2luYXRpb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFhLE1BQU0sRUFBaUIsTUFBTSxlQUFlLENBQUM7QUFDMUgsT0FBTyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbEUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQy9ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQzs7Ozs7O0FBU3pELE1BQU0sT0FBTyxxQkFBcUI7SUE2RWhDO1FBbEVBOzs7V0FHRztRQUNNLGlCQUFZLEdBQVcsQ0FBQyxDQUFDO1FBNEJsQzs7O1dBR0c7UUFDTSxrQkFBYSxHQUFrQixDQUFDLEVBQUUsRUFB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c291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgZmlsdGVyIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBMb3dlckNhc2VQaXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEl0SWNvbkNvbXBvbmVudCB9IGZyb20gJy4uLy4uL3V0aWxzL2ljb24vaWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgVHJhbnNsYXRlTW9kdWxlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XG5pbXBvcnQgeyBJdERyb3Bkb3duTW9kdWxlIH0gZnJvbSAnLi4vZHJvcGRvd24vZHJvcGRvd24ubW9kdWxlJztcbmltcG9ydCB7IEl0SW5wdXRDb21wb25lbnQgfSBmcm9tICcuLi8uLi9mb3JtL2lucHV0L2lucHV0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBpbnB1dFRvQm9vbGVhbiB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL2NvZXJjaW9uJztcblxuQENvbXBvbmVudCh7XG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIHNlbGVjdG9yOiAnaXQtcGFnaW5hdGlvbicsXG4gIHRlbXBsYXRlVXJsOiAnLi9wYWdpbmF0aW9uLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGltcG9ydHM6IFtJdEljb25Db21wb25lbnQsIFRyYW5zbGF0ZU1vZHVsZSwgTG93ZXJDYXNlUGlwZSwgSXREcm9wZG93bk1vZHVsZSwgSXRJbnB1dENvbXBvbmVudCwgUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG59KVxuZXhwb3J0IGNsYXNzIEl0UGFnaW5hdGlvbkNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG4gIC8qKlxuICAgKiBJbmRleCBvZiBwYWdlIChzdGFydCAwKVxuICAgKi9cbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgY3VycmVudFBhZ2UhOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIE1heCBudW1iZXIgb2YgcGFnZSAoY291bnRlcilcbiAgICovXG4gIEBJbnB1dCh7IHJlcXVpcmVkOiB0cnVlIH0pIHBhZ2VOdW1iZXJzITogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBOdW1iZXIgb2YgcGFnZXMgY2xvc2VzdCB0byB0aGUgY3VycmVudCBvbmUgdG8gZGlzcGxheVxuICAgKiBAZGVmYXVsdCA1XG4gICAqL1xuICBASW5wdXQoKSB2aXNpYmxlUGFnZXM6IG51bWJlciA9IDU7XG5cbiAgLyoqXG4gICAqIFBhZ2luYXRpb24gYWxpZ25tZW50IChqdXN0aWZ5LWNvbnRlbnQpXG4gICAqL1xuICBASW5wdXQoKSBhbGlnbm1lbnQ6ICdjZW50ZXInIHwgJ2VuZCcgfCB1bmRlZmluZWQ7XG5cbiAgLyoqXG4gICAqIEVuYWJsZS9EaXNhYmxlIHNpbXBsZSBtb2RlXG4gICAqIFBhZ2luYXRpb24gaW4gdGhlIFwiU2ltcGxlIG1vZGVcIiB2ZXJzaW9uIGlzIG9wdGltaXplZCBmb3IgbW9iaWxlIGRldmljZXMuXG4gICAqIEBkZWZhdWx0IGZhbHNlIC0gZGlzYWJsZWRcbiAgICovXG4gIEBJbnB1dCh7IHRyYW5zZm9ybTogaW5wdXRUb0Jvb2xlYW4gfSkgc2ltcGxlTW9kZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEVuYWJsZS9EaXNhYmxlIHRleHQgbGlua3NcbiAgICogQ2hldnJvbiBpY29ucyB1c2VkIGFzIG5hdmlnYXRpb24gbGlua3MgYXJlIHJlcGxhY2VkIGJ5IHRleHQgbGlua3Mgc3VjaCBhcyDigJxwcmV2aW91c+KAnSBhbmQg4oCcbmV4dOKAnS5cbiAgICogQGRlZmF1bHQgZmFsc2UgLSBkaXNhYmxlZFxuICAgKi9cbiAgQElucHV0KHsgdHJhbnNmb3JtOiBpbnB1dFRvQm9vbGVhbiB9KSB0ZXh0TGlua3M/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBDdXJyZW50IHZhbHVlIG9mIENoYW5nZXJcbiAgICogSWYgaXMgc2V0IHNob3cgdGhlIENoYW5nZXJcbiAgICogQGRlZmF1bHQgdW5kZWZpbmVkIC0gaGlkZSB0aGUgQ2hhbmdlclxuICAgKi9cbiAgQElucHV0KCkgY3VycmVudENoYW5nZXI6IG51bWJlciB8IHVuZGVmaW5lZDtcblxuICAvKipcbiAgICogQXZhaWxhYmxlIENoYW5nZXIgdmFsdWVzXG4gICAqIEBkZWZhdWx0IFsxMCwgMjUsIDUwLCAxMDBdXG4gICAqL1xuICBASW5wdXQoKSBjaGFuZ2VyVmFsdWVzOiBBcnJheTxudW1iZXI+ID0gWzEwLCAyNSwgNTAsIDEwMF07XG5cbiAgLyoqXG4gICAqIEhpZGUvU2hvdyBcIkp1bXAgdG8gcGFnZVwiIGlucHV0XG4gICAqIEBkZWZhdWx0IGZhbHNlIC0gaGlkZGVuXG4gICAqL1xuICBASW5wdXQoeyB0cmFuc2Zvcm06IGlucHV0VG9Cb29sZWFuIH0pIHNob3dKdW1wVG9QYWdlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRmlyZWQgd2hlbiBwYWdlIGlzIGNoYW5nZWQuIEVtaXQgdGhlIG5ldyBpbmRleCBvZiBwYWdlXG4gICAqL1xuICBAT3V0cHV0KCkgcGFnZUV2ZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG5cbiAgLyoqXG4gICAqIEZpcmVkIHdoZW4gY2hhbmdlciBpcyBjaGFuZ2VkLiBFbWl0IHRoZSBuZXcgY2hhbmdlciB2YWx1ZVxuICAgKi9cbiAgQE91dHB1dCgpIGNoYW5nZXJFdmVudCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gIC8qKlxuICAgKiBUaGUgcGFnZXNcbiAgICogQHByb3RlY3RlZFxuICAgKi9cbiAgcHJvdGVjdGVkIHBhZ2VzOiBBcnJheTxudW1iZXI+ID0gW107XG5cbiAgLyoqXG4gICAqIEp1bXAgdG8gcGFnZSBpbnB1dFxuICAgKiBAcHJvdGVjdGVkXG4gICAqL1xuICBwcm90ZWN0ZWQganVtcFRvUGFnZTogRm9ybUNvbnRyb2w8bnVtYmVyIHwgbnVsbD4gPSBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyIHwgbnVsbD4obnVsbCk7XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5qdW1wVG9QYWdlLnZhbHVlQ2hhbmdlc1xuICAgICAgLnBpcGUoXG4gICAgICAgIGRlYm91bmNlVGltZSgzMDApLCAvLyBEZWxheSBmaWx0ZXIgZGF0YSBhZnRlciB0aW1lIHNwYW4gaGFzIHBhc3NlZCB3aXRob3V0IGFub3RoZXIgc291cmNlIGVtaXNzaW9uXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICAgIGZpbHRlcih2YWx1ZSA9PiAhIXZhbHVlICYmIHRoaXMuanVtcFRvUGFnZS52YWxpZClcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUodmFsdWUgPT4ge1xuICAgICAgICB0aGlzLnBhZ2VFdmVudC5lbWl0KHZhbHVlISAtIDEpO1xuICAgICAgfSk7XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgdGhpcy5wYWdlcyA9IHRoaXMuY2FsY3VsYXRlUGFnZXMoKTtcbiAgICBpZiAoY2hhbmdlc1snY3VycmVudFBhZ2UnXSkge1xuICAgICAgdGhpcy5qdW1wVG9QYWdlLnNldFZhbHVlKG51bGwsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGFycmF5IHRvIGdlbmVyYXRlIHBhZ2luYXRpb24gb2YgYHZpc2libGVQYWdlc2AgZWxlbWVudFxuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVQYWdlcygpOiBBcnJheTxudW1iZXI+IHtcbiAgICBpZiAodGhpcy5zaW1wbGVNb2RlKSB7XG4gICAgICByZXR1cm4gW3RoaXMuY3VycmVudFBhZ2VdO1xuICAgIH1cblxuICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMucGFnZU51bWJlcnMgPiB0aGlzLnZpc2libGVQYWdlcyA/IHRoaXMudmlzaWJsZVBhZ2VzIDogdGhpcy5wYWdlTnVtYmVycztcblxuICAgIGNvbnN0IGhhbGZWaXNpYmxlUGFnZXMgPSBNYXRoLmZsb29yKHRoaXMudmlzaWJsZVBhZ2VzIC8gMik7XG4gICAgbGV0IHN0YXJ0ID0gdGhpcy5jdXJyZW50UGFnZSA+IGhhbGZWaXNpYmxlUGFnZXMgJiYgdGhpcy5wYWdlTnVtYmVycyA+IHRoaXMudmlzaWJsZVBhZ2VzID8gdGhpcy5jdXJyZW50UGFnZSAtIGhhbGZWaXNpYmxlUGFnZXMgKyAxIDogMTtcblxuICAgIGlmICh0aGlzLnBhZ2VOdW1iZXJzID4gdGhpcy52aXNpYmxlUGFnZXMpIHtcbiAgICAgIGlmICh0aGlzLmN1cnJlbnRQYWdlICsgMSA+PSB0aGlzLnBhZ2VOdW1iZXJzKSB7XG4gICAgICAgIHN0YXJ0IC09IGhhbGZWaXNpYmxlUGFnZXM7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuY3VycmVudFBhZ2UgPj0gdGhpcy5wYWdlTnVtYmVycyAtIGhhbGZWaXNpYmxlUGFnZXMpIHtcbiAgICAgICAgc3RhcnQgLT0gdGhpcy5wYWdlTnVtYmVycyAtICh0aGlzLmN1cnJlbnRQYWdlICsgMSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGggfSwgKF8sIGkpID0+IGkgKyBzdGFydCk7XG4gIH1cblxuICAvKipcbiAgICogT24gY2xpY2sgcGFnZSBjaGFuZ2VcbiAgICogQHBhcmFtIGV2ZW50IGNsaWNrIGV2ZW50XG4gICAqIEBwYXJhbSBuZXdQYWdlIHRoZSBuZXcgcGFnZSBvZiB0YWJsZVxuICAgKi9cbiAgcHJvdGVjdGVkIHBhZ2VDaGFuZ2UoZXZlbnQ6IEV2ZW50LCBuZXdQYWdlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMucGFnZUV2ZW50LmVtaXQobmV3UGFnZSAtIDEpOyAvLyBlbWl0IG5ldyBwYWdlIGluZGV4XG4gIH1cblxuICAvKipcbiAgICogT24gY2xpY2sgY2hhbmdlclxuICAgKiBAcGFyYW0gZXZlbnQgY2xpY2sgZXZlbnRcbiAgICogQHBhcmFtIHZhbHVlIHRoZSBuZXcgY2hhbmdlciB2YWx1ZVxuICAgKi9cbiAgcHJvdGVjdGVkIGNoYW5nZXJDaGFuZ2UoZXZlbnQ6IEV2ZW50LCB2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB0aGlzLmNoYW5nZXJFdmVudC5lbWl0KHZhbHVlKTsgLy8gZW1pdCBuZXcgY2hhbmdlciB2YWx1ZVxuICB9XG59XG4iLCI8bmF2XG4gIGNsYXNzPVwicGFnaW5hdGlvbi13cmFwcGVyXCJcbiAgW2NsYXNzLmp1c3RpZnktY29udGVudC1jZW50ZXJdPVwiYWxpZ25tZW50ID09PSAnY2VudGVyJ1wiXG4gIFtjbGFzcy5qdXN0aWZ5LWNvbnRlbnQtZW5kXT1cImFsaWdubWVudCA9PT0gJ2VuZCdcIlxuICBbY2xhc3MucGFnaW5hdGlvbi10b3RhbF09XCJ0b3RhbE51bWJlclRleHQuaGFzQ2hpbGROb2RlcygpXCI+XG4gIEBpZiAocGFnZXMubGVuZ3RoKSB7XG4gICAgPHVsIGNsYXNzPVwicGFnaW5hdGlvblwiPlxuICAgICAgPGxpIGNsYXNzPVwicGFnZS1pdGVtXCIgW2NsYXNzLmRpc2FibGVkXT1cImN1cnJlbnRQYWdlIDwgMVwiPlxuICAgICAgICA8YSBjbGFzcz1cInBhZ2UtbGlua1wiIFtjbGFzcy50ZXh0XT1cInRleHRMaW5rc1wiIGhyZWY9XCIjXCIgKGNsaWNrKT1cInBhZ2VDaGFuZ2UoJGV2ZW50LCBjdXJyZW50UGFnZSlcIj5cbiAgICAgICAgICBAaWYgKCF0ZXh0TGlua3MpIHtcbiAgICAgICAgICAgIDxpdC1pY29uIG5hbWU9XCJjaGV2cm9uLWxlZnRcIiBjb2xvcj1cInByaW1hcnlcIj48L2l0LWljb24+XG4gICAgICAgICAgfVxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCI+XG4gICAgICAgICAgICB7eyAodGV4dExpbmtzID8gJ2l0LmNvcmUucGFnZScgOiAnaXQuY29yZS5wcmV2aW91cy1wYWdlJykgfCB0cmFuc2xhdGUgfX1cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgQGlmICh0ZXh0TGlua3MpIHtcbiAgICAgICAgICAgIHt7ICdpdC5jb3JlLnByZXZpb3VzJyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH1cbiAgICAgICAgPC9hPlxuICAgICAgPC9saT5cbiAgICAgIEBpZiAoc2ltcGxlTW9kZSkge1xuICAgICAgICA8bGkgY2xhc3M9XCJwYWdlLWl0ZW1cIj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInBhZ2UtbGlua1wiIGFyaWEtY3VycmVudD1cInBhZ2VcIj57eyBjdXJyZW50UGFnZSArIDEgfX08L3NwYW4+XG4gICAgICAgIDwvbGk+XG4gICAgICAgIDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiPjxzcGFuIGNsYXNzPVwicGFnZS1saW5rXCI+Lzwvc3Bhbj48L2xpPlxuICAgICAgICA8bGkgY2xhc3M9XCJwYWdlLWl0ZW1cIj5cbiAgICAgICAgICA8c3BhbiBjbGFzcz1cInBhZ2UtbGlua1wiPnt7IHBhZ2VOdW1iZXJzIH19PC9zcGFuPlxuICAgICAgICA8L2xpPlxuICAgICAgICA8bGkgY2xhc3M9XCJwYWdlLWl0ZW0gdmlzdWFsbHktaGlkZGVuXCI+XG4gICAgICAgICAgPGEgY2xhc3M9XCJwYWdlLWxpbmtcIiBocmVmPVwiI1wiIGFyaWEtY3VycmVudD1cInBhZ2VcIj5cbiAgICAgICAgICAgIHt7ICdpdC5jb3JlLnBhZ2Utb2YtdG90YWwnIHwgdHJhbnNsYXRlOiB7IHBhZ2U6IGN1cnJlbnRQYWdlICsgMSwgdG90YWw6IHBhZ2VOdW1iZXJzIH0gfX1cbiAgICAgICAgICA8L2E+XG4gICAgICAgIDwvbGk+XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgQGlmIChwYWdlTnVtYmVycyA+IHZpc2libGVQYWdlcyAmJiBwYWdlc1swXSA+PSAyKSB7XG4gICAgICAgICAgPGxpIGNsYXNzPVwicGFnZS1pdGVtXCI+XG4gICAgICAgICAgICA8YSBjbGFzcz1cInBhZ2UtbGlua1wiIGhyZWY9XCIjXCIgKGNsaWNrKT1cInBhZ2VDaGFuZ2UoJGV2ZW50LCAxKVwiPjE8L2E+XG4gICAgICAgICAgPC9saT5cbiAgICAgICAgICBAaWYgKHBhZ2VzWzBdID49IDMpIHtcbiAgICAgICAgICAgIDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInBhZ2UtbGlua1wiPi4uLjwvc3Bhbj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIEBmb3IgKHBhZ2Ugb2YgcGFnZXM7IHRyYWNrIHBhZ2UpIHtcbiAgICAgICAgICA8bGkgY2xhc3M9XCJwYWdlLWl0ZW1cIj5cbiAgICAgICAgICAgIEBpZiAocGFnZSA9PT0gY3VycmVudFBhZ2UgKyAxKSB7XG4gICAgICAgICAgICAgIDxhIGNsYXNzPVwicGFnZS1saW5rXCIgYXJpYS1jdXJyZW50PVwicGFnZVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZC1pbmxpbmUtYmxvY2sgZC1zbS1ub25lXCI+e3sgJ2l0LmNvcmUucGFnZScgfCB0cmFuc2xhdGUgfX08L3NwYW4+IHt7IHBhZ2UgfX1cbiAgICAgICAgICAgICAgPC9hPlxuICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgIDxhIGNsYXNzPVwicGFnZS1saW5rXCIgaHJlZj1cIiNcIiAoY2xpY2spPVwicGFnZUNoYW5nZSgkZXZlbnQsIHBhZ2UpXCI+e3sgcGFnZSB9fTwvYT5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L2xpPlxuICAgICAgICB9XG4gICAgICAgIEBpZiAocGFnZU51bWJlcnMgPiB2aXNpYmxlUGFnZXMgJiYgcGFnZXNbcGFnZXMubGVuZ3RoIC0gMV0gPCBwYWdlTnVtYmVycykge1xuICAgICAgICAgIEBpZiAocGFnZXNbcGFnZXMubGVuZ3RoIC0gMV0gPCBwYWdlTnVtYmVycyAtIDEpIHtcbiAgICAgICAgICAgIDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInBhZ2UtbGlua1wiPi4uLjwvc3Bhbj5cbiAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgfVxuICAgICAgICAgIDxsaSBjbGFzcz1cInBhZ2UtaXRlbVwiPlxuICAgICAgICAgICAgPGEgY2xhc3M9XCJwYWdlLWxpbmtcIiBocmVmPVwiI1wiIChjbGljayk9XCJwYWdlQ2hhbmdlKCRldmVudCwgcGFnZU51bWJlcnMpXCI+e3sgcGFnZU51bWJlcnMgfX08L2E+XG4gICAgICAgICAgPC9saT5cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgPGxpIGNsYXNzPVwicGFnZS1pdGVtXCIgW2NsYXNzLmRpc2FibGVkXT1cImN1cnJlbnRQYWdlID49IHBhZ2VOdW1iZXJzIC0gMVwiPlxuICAgICAgICA8YSBjbGFzcz1cInBhZ2UtbGlua1wiIFtjbGFzcy50ZXh0XT1cInRleHRMaW5rc1wiIGhyZWY9XCIjXCIgKGNsaWNrKT1cInBhZ2VDaGFuZ2UoJGV2ZW50LCBjdXJyZW50UGFnZSArIDIpXCI+XG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJ2aXN1YWxseS1oaWRkZW5cIj5cbiAgICAgICAgICAgIHt7ICh0ZXh0TGlua3MgPyAnaXQuY29yZS5wYWdlJyA6ICdpdC5jb3JlLm5leHQtcGFnZScpIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIEBpZiAodGV4dExpbmtzKSB7XG4gICAgICAgICAgICB7eyAnaXQuY29yZS5uZXh0JyB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgPGl0LWljb24gbmFtZT1cImNoZXZyb24tcmlnaHRcIiBjb2xvcj1cInByaW1hcnlcIj48L2l0LWljb24+XG4gICAgICAgICAgfVxuICAgICAgICA8L2E+XG4gICAgICA8L2xpPlxuICAgIDwvdWw+XG4gIH1cblxuICBAaWYgKGN1cnJlbnRDaGFuZ2VyICE9PSB1bmRlZmluZWQpIHtcbiAgICA8aXQtZHJvcGRvd24+XG4gICAgICA8c3BhbiBidXR0b24+e3sgY3VycmVudENoYW5nZXIgfX0gLyB7eyAnaXQuY29yZS5wYWdlJyB8IHRyYW5zbGF0ZSB8IGxvd2VyY2FzZSB9fTwvc3Bhbj5cbiAgICAgIDxuZy1jb250YWluZXIgbGlzdD5cbiAgICAgICAgQGZvciAodmFsdWUgb2YgY2hhbmdlclZhbHVlczsgdHJhY2sgdmFsdWUpIHtcbiAgICAgICAgICA8aXQtZHJvcGRvd24taXRlbSBocmVmPVwiI1wiIGV4dGVybmFsTGluaz1cInRydWVcIiAoY2xpY2spPVwiY2hhbmdlckNoYW5nZSgkZXZlbnQsIHZhbHVlKVwiPlxuICAgICAgICAgICAge3sgdmFsdWUgfX0gLyB7eyAnaXQuY29yZS5wYWdlJyB8IHRyYW5zbGF0ZSB8IGxvd2VyY2FzZSB9fVxuICAgICAgICAgIDwvaXQtZHJvcGRvd24taXRlbT5cbiAgICAgICAgfVxuICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgPC9pdC1kcm9wZG93bj5cbiAgfVxuXG4gIEBpZiAoc2hvd0p1bXBUb1BhZ2UpIHtcbiAgICA8aXQtaW5wdXRcbiAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgW21pbl09XCIxXCJcbiAgICAgIFttYXhdPVwicGFnZU51bWJlcnNcIlxuICAgICAgW2xhYmVsXT1cIignaXQuY29yZS5nby10bycgfCB0cmFuc2xhdGUpICsgJy4uLidcIlxuICAgICAgW2Zvcm1Db250cm9sXT1cImp1bXBUb1BhZ2VcIj48L2l0LWlucHV0PlxuICB9XG5cbiAgPHAgW2NsYXNzLmQtbm9uZV09XCIhdG90YWxOdW1iZXJUZXh0Lmhhc0NoaWxkTm9kZXMoKVwiICN0b3RhbE51bWJlclRleHQ+XG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICA8L3A+XG48L25hdj5cbiJdfQ==