UNPKG

@doku-dev/doku-fragment

Version:

A new Angular UI library that moving away from Bootstrap and built from scratch.

212 lines 36.7 kB
import { CommonModule, DOCUMENT, DatePipe } from '@angular/common'; import { ChangeDetectionStrategy, Component, Host, HostBinding, Inject, Injector, Input, LOCALE_ID, Optional, ViewEncapsulation, createComponent, } from '@angular/core'; import { Subject, delay, distinctUntilChanged, filter, fromEvent, map, startWith, takeUntil, } from 'rxjs'; import { getClickType } from '../../../utils/get-click-type'; import { updateFloatingPosition } from '../../../utils/update-floating-position'; import { DOKU_FORM_FIELD_ACCESSOR, } from '../../form-field'; import { DokuDatePickerBase } from '../base/date-picker-base.component'; import { DokuDatePickerRangeProps } from '../common/date-picker-range-props.component'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; import * as i2 from "../../form-field"; export class DokuDateRangePicker extends DokuDatePickerRangeProps { constructor(cdr, appRef, injector, renderer, envInjector, ngZone, datePipe, localeId, document, formField) { super(cdr); this.cdr = cdr; this.appRef = appRef; this.injector = injector; this.renderer = renderer; this.envInjector = envInjector; this.ngZone = ngZone; this.datePipe = datePipe; this.localeId = localeId; this.document = document; this.formField = formField; this.class = ['d-date-picker', 'd-date-range-picker']; /** * Whether to close date range picker dropdown after selecting the end date. * * @default true; */ this.closeOnDateClick = true; /** * Date format that will be used for formatting displayed value (start and end date) in the input field. It follows Angular DatePipe's format options. * * @default 'dd/MM/yyyy' */ this.dateFormat = 'dd/MM/yyyy'; /** * Placeholder of the date range picker input. * * @default 'dd/mm/yyyy - dd/mm/yyyy' */ this.placeholder = 'dd/mm/yyyy - dd/mm/yyyy'; this.isOpen = false; this.destroy$ = new Subject(); this.onClickHandler(); } get formattedStartDate() { return this.formatDisplayedDate(this.value?.start); } get formattedEndDate() { return this.formatDisplayedDate(this.value?.end); } get inputWrapperElement() { return this.formField?.['inputWrapperElement']; } ngAfterViewInit() { this.notifyChange$ .pipe(filter((change) => change === 'disabled' || change === 'readonly'), startWith({ disabled: this.disabled, readonly: this.readonly }), map(() => ({ disabled: this.disabled, readonly: this.readonly })), distinctUntilChanged((prev, current) => JSON.stringify(prev) === JSON.stringify(current)), delay(0), takeUntil(this.destroy$)) .subscribe(({ disabled, readonly }) => { this.onDisable?.(disabled); this.onReadonly?.(readonly); this.setInputWrapperCursorState(this.inputWrapperElement, { disabled, readonly }); }); this.notifyChange$ .pipe(filter((change) => change === 'minDate' || change === 'maxDate'), map(() => ({ minDate: this.minDate, maxDate: this.maxDate })), distinctUntilChanged(), takeUntil(this.destroy$)) .subscribe(({ minDate, maxDate }) => { this.datePickerBaseRef?.setInput('minDate', minDate); this.datePickerBaseRef?.setInput('maxDate', maxDate); }); } ngOnDestroy() { this.close(); this.destroy$.next(true); this.destroy$.complete(); this.cleanup?.(); } registerOnDisable(fn) { this.onDisable = fn; } registerOnValidate(fn) { this.onValidate = fn; } registerOnReadonly(fn) { this.onReadonly = fn; } /** * Open the date range picker dropdown. */ open() { if (this.isOpen || this.disabled || this.readonly) return; this.isOpen = true; this.portalElement = this.createPortalElement(); this.datePickerBaseRef = this.createDatePickerComponent(); this.renderer.appendChild(this.portalElement, this.datePickerBaseRef.location.nativeElement); this.renderer.appendChild(this.document.body, this.portalElement); this.doAutoUpdateDropdownPosition(); } /** * Close the date range picker dropdown. */ close() { if (!this.isOpen) return; this.isOpen = false; if (this.portalElement) this.renderer.removeChild(this.document.body, this.portalElement); this.datePickerBaseRef?.destroy(); } /** * Toggle the date range picker dropdown. */ toggle() { this.isOpen ? this.close() : this.open(); } createPortalElement() { const el = this.renderer.createElement('div'); this.renderer.addClass(el, 'd-date-picker-portal'); return el; } createDatePickerComponent() { const elementInjector = Injector.create({ providers: [], parent: this.injector }); const ref = createComponent(DokuDatePickerBase, { environmentInjector: this.envInjector, elementInjector: elementInjector, }); this.appRef.attachView(ref.hostView); ref.setInput('useDateRange', true); ref.setInput('value', this.value); ref.setInput('minDate', this.minDate); ref.setInput('maxDate', this.maxDate); const valueChangeListener = ref.instance.valueChange.subscribe((value) => { this.dateChangeHandler?.(value); if (this.closeOnDateClick && value?.start && value.end) this.close(); }); ref.onDestroy(() => { valueChangeListener.unsubscribe(); }); ref.changeDetectorRef.detectChanges(); return ref; } onClickHandler() { fromEvent(this.document, 'click') .pipe(takeUntil(this.destroy$)) .subscribe((event) => { const { clickOutside, clickTrigger } = getClickType(event, [this.inputWrapperElement], [this.portalElement]); if (clickTrigger) return this.toggle(); if (clickOutside) return this.close(); }); } doAutoUpdateDropdownPosition() { this.ngZone.runOutsideAngular(() => { if (!this.inputWrapperElement || !this.portalElement) return; this.cleanup = updateFloatingPosition({ triggerElement: this.inputWrapperElement, floatingElement: this.portalElement, placement: 'bottom-start', autoUpdate: true, middleware: { flip: true, shift: true, }, }); }); } setInputWrapperCursorState(inputWrapperElement, props) { if (!inputWrapperElement) return; let cursor = 'pointer'; if (props?.readonly) cursor = 'text'; if (props?.disabled) cursor = 'not-allowed'; inputWrapperElement.style.cursor = cursor; } formatDisplayedDate(date) { if (!date) return null; return this.datePipe.transform(date, this.dateFormat, undefined, this.localeId); } } DokuDateRangePicker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DokuDateRangePicker, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ApplicationRef }, { token: i0.Injector }, { token: i0.Renderer2 }, { token: i0.EnvironmentInjector }, { token: i0.NgZone }, { token: i1.DatePipe }, { token: LOCALE_ID }, { token: DOCUMENT }, { token: i2.DokuFormField, host: true, optional: true }], target: i0.ɵɵFactoryTarget.Component }); DokuDateRangePicker.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: DokuDateRangePicker, isStandalone: true, selector: "doku-date-range-picker", inputs: { closeOnDateClick: "closeOnDateClick", dateFormat: "dateFormat", placeholder: "placeholder" }, host: { properties: { "class": "this.class" } }, providers: [DatePipe, { provide: DOKU_FORM_FIELD_ACCESSOR, useExisting: DokuDateRangePicker }], exportAs: ["dokuDateRangePicker"], usesInheritance: true, ngImport: i0, template: "<span *ngIf=\"!(formattedStartDate || formattedEndDate)\" class=\"d-date-picker-placeholder\">\n {{ placeholder }}\n</span>\n\n<span *ngIf=\"formattedStartDate || formattedEndDate\" class=\"d-date-picker-value\">\n {{ formattedStartDate }} - {{ formattedEndDate }}\n</span>\n\n<span class=\"icon-calendar\">\n <ng-container *ngTemplateOutlet=\"iconCalendar\"></ng-container>\n</span>\n\n<ng-template #iconCalendar>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M19 5H5C4.44772 5 4 5.44772 4 6V17C4 17.5523 4.44772 18 5 18H19C19.5523 18 20 17.5523 20 17V6C20 5.44772 19.5523 5 19 5Z\"\n stroke=\"currentColor\"\n />\n <path d=\"M4 7.94336H20\" stroke=\"currentColor\" />\n <ellipse cx=\"7.69213\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"7.69213\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"10.6462\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"10.6462\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"13.5998\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"13.5998\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"16.554\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"16.554\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n </svg>\n</ng-template>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DokuDateRangePicker, decorators: [{ type: Component, args: [{ selector: 'doku-date-range-picker', exportAs: 'dokuDateRangePicker', standalone: true, imports: [CommonModule], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [DatePipe, { provide: DOKU_FORM_FIELD_ACCESSOR, useExisting: DokuDateRangePicker }], template: "<span *ngIf=\"!(formattedStartDate || formattedEndDate)\" class=\"d-date-picker-placeholder\">\n {{ placeholder }}\n</span>\n\n<span *ngIf=\"formattedStartDate || formattedEndDate\" class=\"d-date-picker-value\">\n {{ formattedStartDate }} - {{ formattedEndDate }}\n</span>\n\n<span class=\"icon-calendar\">\n <ng-container *ngTemplateOutlet=\"iconCalendar\"></ng-container>\n</span>\n\n<ng-template #iconCalendar>\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\">\n <path\n d=\"M19 5H5C4.44772 5 4 5.44772 4 6V17C4 17.5523 4.44772 18 5 18H19C19.5523 18 20 17.5523 20 17V6C20 5.44772 19.5523 5 19 5Z\"\n stroke=\"currentColor\"\n />\n <path d=\"M4 7.94336H20\" stroke=\"currentColor\" />\n <ellipse cx=\"7.69213\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"7.69213\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"10.6462\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"10.6462\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"13.5998\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"13.5998\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"16.554\" cy=\"11.3774\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n <ellipse cx=\"16.554\" cy=\"14.3207\" rx=\"0.984615\" ry=\"0.981132\" fill=\"currentColor\" />\n </svg>\n</ng-template>\n" }] }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ApplicationRef }, { type: i0.Injector }, { type: i0.Renderer2 }, { type: i0.EnvironmentInjector }, { type: i0.NgZone }, { type: i1.DatePipe }, { type: undefined, decorators: [{ type: Inject, args: [LOCALE_ID] }] }, { type: Document, decorators: [{ type: Inject, args: [DOCUMENT] }] }, { type: i2.DokuFormField, decorators: [{ type: Optional }, { type: Host }] }]; }, propDecorators: { class: [{ type: HostBinding, args: ['class'] }], closeOnDateClick: [{ type: Input }], dateFormat: [{ type: Input }], placeholder: [{ type: Input }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1yYW5nZS1waWNrZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZG9rdS1mcmFnbWVudC9zcmMvbGliL2RhdGUtcGlja2VyL2RhdGUtcmFuZ2UtcGlja2VyLWZsb2F0L2RhdGUtcmFuZ2UtcGlja2VyLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2Rva3UtZnJhZ21lbnQvc3JjL2xpYi9kYXRlLXBpY2tlci9kYXRlLXJhbmdlLXBpY2tlci1mbG9hdC9kYXRlLXJhbmdlLXBpY2tlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQVcsTUFBTSxpQkFBaUIsQ0FBQztBQUM1RSxPQUFPLEVBR0wsdUJBQXVCLEVBRXZCLFNBQVMsRUFHVCxJQUFJLEVBQ0osV0FBVyxFQUNYLE1BQU0sRUFDTixRQUFRLEVBQ1IsS0FBSyxFQUNMLFNBQVMsRUFHVCxRQUFRLEVBRVIsaUJBQWlCLEVBQ2pCLGVBQWUsR0FDaEIsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLE9BQU8sRUFDUCxLQUFLLEVBQ0wsb0JBQW9CLEVBQ3BCLE1BQU0sRUFDTixTQUFTLEVBQ1QsR0FBRyxFQUNILFNBQVMsRUFDVCxTQUFTLEdBQ1YsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDN0QsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDakYsT0FBTyxFQUNMLHdCQUF3QixHQUl6QixNQUFNLGtCQUFrQixDQUFDO0FBQzFCLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDZDQUE2QyxDQUFDOzs7O0FB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QkFEdkIsV0FBVzt1QkFBQyxPQUFPO2dCQVFYLGdCQUFnQjtzQkFBeEIsS0FBSztnQkFPRyxVQUFVO3NCQUFsQixLQUFLO2dCQU9HLFdBQVc7c0JBQW5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21tb25Nb2R1bGUsIERPQ1VNRU5ULCBEYXRlUGlwZSwgTmdDbGFzcyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBBcHBsaWNhdGlvblJlZixcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbXBvbmVudFJlZixcbiAgRW52aXJvbm1lbnRJbmplY3RvcixcbiAgSG9zdCxcbiAgSG9zdEJpbmRpbmcsXG4gIEluamVjdCxcbiAgSW5qZWN0b3IsXG4gIElucHV0LFxuICBMT0NBTEVfSUQsXG4gIE5nWm9uZSxcbiAgT25EZXN0cm95LFxuICBPcHRpb25hbCxcbiAgUmVuZGVyZXIyLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgY3JlYXRlQ29tcG9uZW50LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIFN1YmplY3QsXG4gIGRlbGF5LFxuICBkaXN0aW5jdFVudGlsQ2hhbmdlZCxcbiAgZmlsdGVyLFxuICBmcm9tRXZlbnQsXG4gIG1hcCxcbiAgc3RhcnRXaXRoLFxuICB0YWtlVW50aWwsXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgZ2V0Q2xpY2tUeXBlIH0gZnJvbSAnLi4vLi4vLi4vdXRpbHMvZ2V0LWNsaWNrLXR5cGUnO1xuaW1wb3J0IHsgdXBkYXRlRmxvYXRpbmdQb3NpdGlvbiB9IGZyb20gJy4uLy4uLy4uL3V0aWxzL3VwZGF0ZS1mbG9hdGluZy1wb3NpdGlvbic7XG5pbXBvcnQge1xuICBET0tVX0ZPUk1fRklFTERfQUNDRVNTT1IsXG4gIERva3VGb3JtRmllbGQsXG4gIERva3VGb3JtRmllbGRBY2Nlc3NvcixcbiAgRG9rdUZvcm1GaWVsZEFjY2Vzc29yVmFsaWRhdGVWYWx1ZSxcbn0gZnJvbSAnLi4vLi4vZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBEb2t1RGF0ZVBpY2tlckJhc2UgfSBmcm9tICcuLi9iYXNlL2RhdGUtcGlja2VyLWJhc2UuY29tcG9uZW50JztcbmltcG9ydCB7IERva3VEYXRlUGlja2VyUmFuZ2VQcm9wcyB9IGZyb20gJy4uL2NvbW1vbi9kYXRlLXBpY2tlci1yYW5nZS1wcm9wcy5jb21wb25lbnQnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdkb2t1LWRhdGUtcmFuZ2UtcGlja2VyJyxcbiAgZXhwb3J0QXM6ICdkb2t1RGF0ZVJhbmdlUGlja2VyJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZV0sXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRlLXJhbmdlLXBpY2tlci5jb21wb25lbnQuaHRtbCcsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcm92aWRlcnM6IFtEYXRlUGlwZSwgeyBwcm92aWRlOiBET0tVX0ZPUk1fRklFTERfQUNDRVNTT1IsIHVzZUV4aXN0aW5nOiBEb2t1RGF0ZVJhbmdlUGlja2VyIH1dLFxufSlcbmV4cG9ydCBjbGFzcyBEb2t1RGF0ZVJhbmdlUGlja2VyXG4gIGV4dGVuZHMgRG9rdURhdGVQaWNrZXJSYW5nZVByb3BzXG4gIGltcGxlbWVudHMgT25EZXN0cm95LCBBZnRlclZpZXdJbml0LCBEb2t1Rm9ybUZpZWxkQWNjZXNzb3JcbntcbiAgQEhvc3RCaW5kaW5nKCdjbGFzcycpXG4gIHByb3RlY3RlZCByZWFkb25seSBjbGFzczogTmdDbGFzc1snbmdDbGFzcyddID0gWydkLWRhdGUtcGlja2VyJywgJ2QtZGF0ZS1yYW5nZS1waWNrZXInXTtcblxuICAvKipcbiAgICogV2hldGhlciB0byBjbG9zZSBkYXRlIHJhbmdlIHBpY2tlciBkcm9wZG93biBhZnRlciBzZWxlY3RpbmcgdGhlIGVuZCBkYXRlLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlO1xuICAgKi9cbiAgQElucHV0KCkgY2xvc2VPbkRhdGVDbGljayA9IHRydWU7XG5cbiAgLyoqXG4gICAqIERhdGUgZm9ybWF0IHRoYXQgd2lsbCBiZSB1c2VkIGZvciBmb3JtYXR0aW5nIGRpc3BsYXllZCB2YWx1ZSAoc3RhcnQgYW5kIGVuZCBkYXRlKSBpbiB0aGUgaW5wdXQgZmllbGQuIEl0IGZvbGxvd3MgQW5ndWxhciBEYXRlUGlwZSdzIGZvcm1hdCBvcHRpb25zLlxuICAgKlxuICAgKiBAZGVmYXVsdCAnZGQvTU0veXl5eSdcbiAgICovXG4gIEBJbnB1dCgpIGRhdGVGb3JtYXQgPSAnZGQvTU0veXl5eSc7XG5cbiAgLyoqXG4gICAqIFBsYWNlaG9sZGVyIG9mIHRoZSBkYXRlIHJhbmdlIHBpY2tlciBpbnB1dC5cbiAgICpcbiAgICogQGRlZmF1bHQgJ2RkL21tL3l5eXkgLSBkZC9tbS95eXl5J1xuICAgKi9cbiAgQElucHV0KCkgcGxhY2Vob2xkZXIgPSAnZGQvbW0veXl5eSAtIGRkL21tL3l5eXknO1xuXG4gIHByaXZhdGUgaXNPcGVuID0gZmFsc2U7XG5cbiAgcHJpdmF0ZSBwb3J0YWxFbGVtZW50PzogSFRNTERpdkVsZW1lbnQ7XG4gIHByaXZhdGUgZGF0ZVBpY2tlckJhc2VSZWY/OiBDb21wb25lbnRSZWY8RG9rdURhdGVQaWNrZXJCYXNlPjtcblxuICBwcml2YXRlIGRlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcbiAgcHJpdmF0ZSBjbGVhbnVwPzogKCkgPT4gdm9pZDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcml2YXRlIGFwcFJlZjogQXBwbGljYXRpb25SZWYsXG4gICAgcHJpdmF0ZSBpbmplY3RvcjogSW5qZWN0b3IsXG4gICAgcHJpdmF0ZSByZW5kZXJlcjogUmVuZGVyZXIyLFxuICAgIHByaXZhdGUgZW52SW5qZWN0b3I6IEVudmlyb25tZW50SW5qZWN0b3IsXG4gICAgcHJpdmF0ZSBuZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIGRhdGVQaXBlOiBEYXRlUGlwZSxcbiAgICBASW5qZWN0KExPQ0FMRV9JRCkgcHJpdmF0ZSBsb2NhbGVJZDogc3RyaW5nLFxuICAgIEBJbmplY3QoRE9DVU1FTlQpIHByaXZhdGUgZG9jdW1lbnQ6IERvY3VtZW50LFxuICAgIEBPcHRpb25hbCgpIEBIb3N0KCkgcHJpdmF0ZSBmb3JtRmllbGQ/OiBEb2t1Rm9ybUZpZWxkXG4gICkge1xuICAgIHN1cGVyKGNkcik7XG4gICAgdGhpcy5vbkNsaWNrSGFuZGxlcigpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldCBmb3JtYXR0ZWRTdGFydERhdGUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0RGlzcGxheWVkRGF0ZSh0aGlzLnZhbHVlPy5zdGFydCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IGZvcm1hdHRlZEVuZERhdGUoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0RGlzcGxheWVkRGF0ZSh0aGlzLnZhbHVlPy5lbmQpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXQgaW5wdXRXcmFwcGVyRWxlbWVudCgpOiBIVE1MRWxlbWVudCB8IHVuZGVmaW5lZCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybUZpZWxkPy5bJ2lucHV0V3JhcHBlckVsZW1lbnQnXTtcbiAgfVxuXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm5vdGlmeUNoYW5nZSRcbiAgICAgIC5waXBlKFxuICAgICAgICBmaWx0ZXIoKGNoYW5nZSkgPT4gY2hhbmdlID09PSAnZGlzYWJsZWQnIHx8IGNoYW5nZSA9PT0gJ3JlYWRvbmx5JyksXG4gICAgICAgIHN0YXJ0V2l0aCh7IGRpc2FibGVkOiB0aGlzLmRpc2FibGVkLCByZWFkb25seTogdGhpcy5yZWFkb25seSB9KSxcbiAgICAgICAgbWFwKCgpID0+ICh7IGRpc2FibGVkOiB0aGlzLmRpc2FibGVkLCByZWFkb25seTogdGhpcy5yZWFkb25seSB9KSksXG4gICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKChwcmV2LCBjdXJyZW50KSA9PiBKU09OLnN0cmluZ2lmeShwcmV2KSA9PT0gSlNPTi5zdHJpbmdpZnkoY3VycmVudCkpLFxuICAgICAgICBkZWxheSgwKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCh7IGRpc2FibGVkLCByZWFkb25seSB9KSA9PiB7XG4gICAgICAgIHRoaXMub25EaXNhYmxlPy4oZGlzYWJsZWQpO1xuICAgICAgICB0aGlzLm9uUmVhZG9ubHk/LihyZWFkb25seSk7XG4gICAgICAgIHRoaXMuc2V0SW5wdXRXcmFwcGVyQ3Vyc29yU3RhdGUodGhpcy5pbnB1dFdyYXBwZXJFbGVtZW50LCB7IGRpc2FibGVkLCByZWFkb25seSB9KTtcbiAgICAgIH0pO1xuXG4gICAgdGhpcy5ub3RpZnlDaGFuZ2UkXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKChjaGFuZ2UpID0+IGNoYW5nZSA9PT0gJ21pbkRhdGUnIHx8IGNoYW5nZSA9PT0gJ21heERhdGUnKSxcbiAgICAgICAgbWFwKCgpID0+ICh7IG1pbkRhdGU6IHRoaXMubWluRGF0ZSwgbWF4RGF0ZTogdGhpcy5tYXhEYXRlIH0pKSxcbiAgICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCh7IG1pbkRhdGUsIG1heERhdGUgfSkgPT4ge1xuICAgICAgICB0aGlzLmRhdGVQaWNrZXJCYXNlUmVmPy5zZXRJbnB1dCgnbWluRGF0ZScsIG1pbkRhdGUpO1xuICAgICAgICB0aGlzLmRhdGVQaWNrZXJCYXNlUmVmPy5zZXRJbnB1dCgnbWF4RGF0ZScsIG1heERhdGUpO1xuICAgICAgfSk7XG4gIH1cblxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmNsb3NlKCk7XG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcbiAgICB0aGlzLmNsZWFudXA/LigpO1xuICB9XG5cbiAgb25EaXNhYmxlPzogKCh2YWx1ZTogYm9vbGVhbikgPT4gdm9pZCkgfCB1bmRlZmluZWQ7XG4gIG9uUmVhZG9ubHk/OiAoKHZhbHVlOiBib29sZWFuKSA9PiB2b2lkKSB8IHVuZGVmaW5lZDtcbiAgb25WYWxpZGF0ZT86ICgodmFsdWU/OiBEb2t1Rm9ybUZpZWxkQWNjZXNzb3JWYWxpZGF0ZVZhbHVlIHwgdW5kZWZpbmVkKSA9PiB2b2lkKSB8IHVuZGVmaW5lZDtcbiAgcmVnaXN0ZXJPbkRpc2FibGUoZm46ICh2YWx1ZTogYm9vbGVhbikgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25EaXNhYmxlID0gZm47XG4gIH1cbiAgcmVnaXN0ZXJPblZhbGlkYXRlPyhmbjogKHZhbHVlPzogRG9rdUZvcm1GaWVsZEFjY2Vzc29yVmFsaWRhdGVWYWx1ZSB8IHVuZGVmaW5lZCkgPT4gdm9pZCk6IHZvaWQge1xuICAgIHRoaXMub25WYWxpZGF0ZSA9IGZuO1xuICB9XG4gIHJlZ2lzdGVyT25SZWFkb25seShmbjogKHZhbHVlOiBib29sZWFuKSA9PiB2b2lkKTogdm9pZCB7XG4gICAgdGhpcy5vblJlYWRvbmx5ID0gZm47XG4gIH1cblxuICAvKipcbiAgICogT3BlbiB0aGUgZGF0ZSByYW5nZSBwaWNrZXIgZHJvcGRvd24uXG4gICAqL1xuICBvcGVuKCkge1xuICAgIGlmICh0aGlzLmlzT3BlbiB8fCB0aGlzLmRpc2FibGVkIHx8IHRoaXMucmVhZG9ubHkpIHJldHVybjtcbiAgICB0aGlzLmlzT3BlbiA9IHRydWU7XG5cbiAgICB0aGlzLnBvcnRhbEVsZW1lbnQgPSB0aGlzLmNyZWF0ZVBvcnRhbEVsZW1lbnQoKTtcbiAgICB0aGlzLmRhdGVQaWNrZXJCYXNlUmVmID0gdGhpcy5jcmVhdGVEYXRlUGlja2VyQ29tcG9uZW50KCk7XG5cbiAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKHRoaXMucG9ydGFsRWxlbWVudCwgdGhpcy5kYXRlUGlja2VyQmFzZVJlZi5sb2NhdGlvbi5uYXRpdmVFbGVtZW50KTtcbiAgICB0aGlzLnJlbmRlcmVyLmFwcGVuZENoaWxkKHRoaXMuZG9jdW1lbnQuYm9keSwgdGhpcy5wb3J0YWxFbGVtZW50KTtcblxuICAgIHRoaXMuZG9BdXRvVXBkYXRlRHJvcGRvd25Qb3NpdGlvbigpO1xuICB9XG5cbiAgLyoqXG4gICAqIENsb3NlIHRoZSBkYXRlIHJhbmdlIHBpY2tlciBkcm9wZG93bi5cbiAgICovXG4gIGNsb3NlKCkge1xuICAgIGlmICghdGhpcy5pc09wZW4pIHJldHVybjtcbiAgICB0aGlzLmlzT3BlbiA9IGZhbHNlO1xuXG4gICAgaWYgKHRoaXMucG9ydGFsRWxlbWVudCkgdGhpcy5yZW5kZXJlci5yZW1vdmVDaGlsZCh0aGlzLmRvY3VtZW50LmJvZHksIHRoaXMucG9ydGFsRWxlbWVudCk7XG4gICAgdGhpcy5kYXRlUGlja2VyQmFzZVJlZj8uZGVzdHJveSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRvZ2dsZSB0aGUgZGF0ZSByYW5nZSBwaWNrZXIgZHJvcGRvd24uXG4gICAqL1xuICB0b2dnbGUoKSB7XG4gICAgdGhpcy5pc09wZW4gPyB0aGlzLmNsb3NlKCkgOiB0aGlzLm9wZW4oKTtcbiAgfVxuXG4gIHByaXZhdGUgY3JlYXRlUG9ydGFsRWxlbWVudCgpIHtcbiAgICBjb25zdCBlbCA9IHRoaXMucmVuZGVyZXIuY3JlYXRlRWxlbWVudCgnZGl2JykgYXMgSFRNTERpdkVsZW1lbnQ7XG4gICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhlbCwgJ2QtZGF0ZS1waWNrZXItcG9ydGFsJyk7XG4gICAgcmV0dXJuIGVsO1xuICB9XG5cbiAgcHJpdmF0ZSBjcmVhdGVEYXRlUGlja2VyQ29tcG9uZW50KCkge1xuICAgIGNvbnN0IGVsZW1lbnRJbmplY3RvciA9IEluamVjdG9yLmNyZWF0ZSh7IHByb3ZpZGVyczogW10sIHBhcmVudDogdGhpcy5pbmplY3RvciB9KTtcbiAgICBjb25zdCByZWYgPSBjcmVhdGVDb21wb25lbnQoRG9rdURhdGVQaWNrZXJCYXNlLCB7XG4gICAgICBlbnZpcm9ubWVudEluamVjdG9yOiB0aGlzLmVudkluamVjdG9yLFxuICAgICAgZWxlbWVudEluamVjdG9yOiBlbGVtZW50SW5qZWN0b3IsXG4gICAgfSk7XG4gICAgdGhpcy5hcHBSZWYuYXR0YWNoVmlldyhyZWYuaG9zdFZpZXcpO1xuXG4gICAgcmVmLnNldElucHV0KCd1c2VEYXRlUmFuZ2UnLCB0cnVlKTtcbiAgICByZWYuc2V0SW5wdXQoJ3ZhbHVlJywgdGhpcy52YWx1ZSk7XG4gICAgcmVmLnNldElucHV0KCdtaW5EYXRlJywgdGhpcy5taW5EYXRlKTtcbiAgICByZWYuc2V0SW5wdXQoJ21heERhdGUnLCB0aGlzLm1heERhdGUpO1xuXG4gICAgY29uc3QgdmFsdWVDaGFuZ2VMaXN0ZW5lciA9IHJlZi5pbnN0YW5jZS52YWx1ZUNoYW5nZS5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICB0aGlzLmRhdGVDaGFuZ2VIYW5kbGVyPy4odmFsdWUpO1xuICAgICAgaWYgKHRoaXMuY2xvc2VPbkRhdGVDbGljayAmJiB2YWx1ZT8uc3RhcnQgJiYgdmFsdWUuZW5kKSB0aGlzLmNsb3NlKCk7XG4gICAgfSk7XG5cbiAgICByZWYub25EZXN0cm95KCgpID0+IHtcbiAgICAgIHZhbHVlQ2hhbmdlTGlzdGVuZXIudW5zdWJzY3JpYmUoKTtcbiAgICB9KTtcblxuICAgIHJlZi5jaGFuZ2VEZXRlY3RvclJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgcmV0dXJuIHJlZjtcbiAgfVxuXG4gIHByaXZhdGUgb25DbGlja0hhbmRsZXIoKSB7XG4gICAgZnJvbUV2ZW50KHRoaXMuZG9jdW1lbnQsICdjbGljaycpXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXG4gICAgICAuc3Vic2NyaWJlKChldmVudCkgPT4ge1xuICAgICAgICBjb25zdCB7IGNsaWNrT3V0c2lkZSwgY2xpY2tUcmlnZ2VyIH0gPSBnZXRDbGlja1R5cGUoXG4gICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgW3RoaXMuaW5wdXRXcmFwcGVyRWxlbWVudF0sXG4gICAgICAgICAgW3RoaXMucG9ydGFsRWxlbWVudF1cbiAgICAgICAgKTtcbiAgICAgICAgaWYgKGNsaWNrVHJpZ2dlcikgcmV0dXJuIHRoaXMudG9nZ2xlKCk7XG4gICAgICAgIGlmIChjbGlja091dHNpZGUpIHJldHVybiB0aGlzLmNsb3NlKCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZG9BdXRvVXBkYXRlRHJvcGRvd25Qb3NpdGlvbigpIHtcbiAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBpZiAoIXRoaXMuaW5wdXRXcmFwcGVyRWxlbWVudCB8fCAhdGhpcy5wb3J0YWxFbGVtZW50KSByZXR1cm47XG4gICAgICB0aGlzLmNsZWFudXAgPSB1cGRhdGVGbG9hdGluZ1Bvc2l0aW9uKHtcbiAgICAgICAgdHJpZ2dlckVsZW1lbnQ6IHRoaXMuaW5wdXRXcmFwcGVyRWxlbWVudCxcbiAgICAgICAgZmxvYXRpbmdFbGVtZW50OiB0aGlzLnBvcnRhbEVsZW1lbnQsXG4gICAgICAgIHBsYWNlbWVudDogJ2JvdHRvbS1zdGFydCcsXG4gICAgICAgIGF1dG9VcGRhdGU6IHRydWUsXG4gICAgICAgIG1pZGRsZXdhcmU6IHtcbiAgICAgICAgICBmbGlwOiB0cnVlLFxuICAgICAgICAgIHNoaWZ0OiB0cnVlLFxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHNldElucHV0V3JhcHBlckN1cnNvclN0YXRlKFxuICAgIGlucHV0V3JhcHBlckVsZW1lbnQ/OiBIVE1MRWxlbWVudCxcbiAgICBwcm9wcz86IHsgZGlzYWJsZWQ/OiBib29sZWFuOyByZWFkb25seT86IGJvb2xlYW4gfVxuICApOiB2b2lkIHtcbiAgICBpZiAoIWlucHV0V3JhcHBlckVsZW1lbnQpIHJldHVybjtcblxuICAgIGxldCBjdXJzb3IgPSAncG9pbnRlcic7XG4gICAgaWYgKHByb3BzPy5yZWFkb25seSkgY3Vyc29yID0gJ3RleHQnO1xuICAgIGlmIChwcm9wcz8uZGlzYWJsZWQpIGN1cnNvciA9ICdub3QtYWxsb3dlZCc7XG4gICAgaW5wdXRXcmFwcGVyRWxlbWVudC5zdHlsZS5jdXJzb3IgPSBjdXJzb3I7XG4gIH1cblxuICBwcml2YXRlIGZvcm1hdERpc3BsYXllZERhdGUoZGF0ZT86IERhdGUgfCBudWxsKSB7XG4gICAgaWYgKCFkYXRlKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdGhpcy5kYXRlUGlwZS50cmFuc2Zvcm0oZGF0ZSwgdGhpcy5kYXRlRm9ybWF0LCB1bmRlZmluZWQsIHRoaXMubG9jYWxlSWQpO1xuICB9XG59XG4iLCI8c3BhbiAqbmdJZj1cIiEoZm9ybWF0dGVkU3RhcnREYXRlIHx8IGZvcm1hdHRlZEVuZERhdGUpXCIgY2xhc3M9XCJkLWRhdGUtcGlja2VyLXBsYWNlaG9sZGVyXCI+XG4gIHt7IHBsYWNlaG9sZGVyIH19XG48L3NwYW4+XG5cbjxzcGFuICpuZ0lmPVwiZm9ybWF0dGVkU3RhcnREYXRlIHx8IGZvcm1hdHRlZEVuZERhdGVcIiBjbGFzcz1cImQtZGF0ZS1waWNrZXItdmFsdWVcIj5cbiAge3sgZm9ybWF0dGVkU3RhcnREYXRlIH19IC0ge3sgZm9ybWF0dGVkRW5kRGF0ZSB9fVxuPC9zcGFuPlxuXG48c3BhbiBjbGFzcz1cImljb24tY2FsZW5kYXJcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImljb25DYWxlbmRhclwiPjwvbmctY29udGFpbmVyPlxuPC9zcGFuPlxuXG48bmctdGVtcGxhdGUgI2ljb25DYWxlbmRhcj5cbiAgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIyNFwiIGhlaWdodD1cIjI0XCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCI+XG4gICAgPHBhdGhcbiAgICAgIGQ9XCJNMTkgNUg1QzQuNDQ3NzIgNSA0IDUuNDQ3NzIgNCA2VjE3QzQgMTcuNTUyMyA0LjQ0NzcyIDE4IDUgMThIMTlDMTkuNTUyMyAxOCAyMCAxNy41NTIzIDIwIDE3VjZDMjAgNS40NDc3MiAxOS41NTIzIDUgMTkgNVpcIlxuICAgICAgc3Ryb2tlPVwiY3VycmVudENvbG9yXCJcbiAgICAvPlxuICAgIDxwYXRoIGQ9XCJNNCA3Ljk0MzM2SDIwXCIgc3Ryb2tlPVwiY3VycmVudENvbG9yXCIgLz5cbiAgICA8ZWxsaXBzZSBjeD1cIjcuNjkyMTNcIiBjeT1cIjExLjM3NzRcIiByeD1cIjAuOTg0NjE1XCIgcnk9XCIwLjk4MTEzMlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiAvPlxuICAgIDxlbGxpcHNlIGN4PVwiNy42OTIxM1wiIGN5PVwiMTQuMzIwN1wiIHJ4PVwiMC45ODQ2MTVcIiByeT1cIjAuOTgxMTMyXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIC8+XG4gICAgPGVsbGlwc2UgY3g9XCIxMC42NDYyXCIgY3k9XCIxMS4zNzc0XCIgcng9XCIwLjk4NDYxNVwiIHJ5PVwiMC45ODExMzJcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgLz5cbiAgICA8ZWxsaXBzZSBjeD1cIjEwLjY0NjJcIiBjeT1cIjE0LjMyMDdcIiByeD1cIjAuOTg0NjE1XCIgcnk9XCIwLjk4MTEzMlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiAvPlxuICAgIDxlbGxpcHNlIGN4PVwiMTMuNTk5OFwiIGN5PVwiMTEuMzc3NFwiIHJ4PVwiMC45ODQ2MTVcIiByeT1cIjAuOTgxMTMyXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIC8+XG4gICAgPGVsbGlwc2UgY3g9XCIxMy41OTk4XCIgY3k9XCIxNC4zMjA3XCIgcng9XCIwLjk4NDYxNVwiIHJ5PVwiMC45ODExMzJcIiBmaWxsPVwiY3VycmVudENvbG9yXCIgLz5cbiAgICA8ZWxsaXBzZSBjeD1cIjE2LjU1NFwiIGN5PVwiMTEuMzc3NFwiIHJ4PVwiMC45ODQ2MTVcIiByeT1cIjAuOTgxMTMyXCIgZmlsbD1cImN1cnJlbnRDb2xvclwiIC8+XG4gICAgPGVsbGlwc2UgY3g9XCIxNi41NTRcIiBjeT1cIjE0LjMyMDdcIiByeD1cIjAuOTg0NjE1XCIgcnk9XCIwLjk4MTEzMlwiIGZpbGw9XCJjdXJyZW50Q29sb3JcIiAvPlxuICA8L3N2Zz5cbjwvbmctdGVtcGxhdGU+XG4iXX0=