UNPKG

@eduardsson/ngx-daterange

Version:
158 lines 29.8 kB
import { Component, Input, Output, EventEmitter, ViewEncapsulation, ChangeDetectionStrategy } from "@angular/core"; import * as momentNs from "moment"; const moment = momentNs; import { extendMoment } from "moment-range"; const { range } = extendMoment(moment); export class CalendarComponent { constructor() { this.singleCalendar = false; this.dateChanged = new EventEmitter(); this.monthChanged = new EventEmitter(); this.yearChanged = new EventEmitter(); } get monthText() { return moment.monthsShort()[this.month]; } ngOnChanges() { this.createCalendarGridData(); } getWeekDays() { return moment.weekdaysShort(true); } getWeekNumbers(monthRange) { const weekNumbers = []; const weeks = Array.from(monthRange.by("weeks")); for (let i = 0; i < weeks.length; i++) { const week = weeks[i]; if (i < 6) { weekNumbers.push(week.week()); } else { break; } } return weekNumbers; } getWeeksRange(weeks) { const weeksRange = []; for (let i = 0; i < weeks.length; i++) { const week = weeks[i]; let firstWeekDay = moment([this.year, this.month]) .week(week) .startOf("week"); let lastWeekDay = moment([this.year, this.month]) .week(week) .endOf("week"); if (i > 0 && week < weeks[i - 1]) { firstWeekDay.add(1, "year"); lastWeekDay.add(1, "year"); } weeksRange.push(range(firstWeekDay.week(week).startOf("week"), lastWeekDay.week(week).endOf("week"))); } return weeksRange; } createCalendarGridData() { const firstDay = moment([this.year, this.month]).startOf("month"); const endDay = moment([this.year, this.month]) .endOf("month") .endOf("week"); const monthRange = range(firstDay, endDay); const weeksRange = this.getWeeksRange(this.getWeekNumbers(monthRange)); const weekList = []; weeksRange.map(week => { const daysList = []; Array.from(week.by("days")).forEach((day) => { if (day.isSame(this.minDate, "date")) { day = this.minDate; } else if (day.isSame(this.maxDate, "date")) { day = this.maxDate; } daysList.push(day); }); weekList.push(daysList); }); this.weekList = weekList; } isDisabled(day) { return (day.isBefore(this.minDate) || day.isAfter(this.maxDate) || (day.isBefore(this.selectedFromDate) && !this.isLeft)); } isDateAvailable(day) { if (this.isLeft) { return (day.isSameOrBefore(this.selectedToDate, "date") && !day.isSameOrBefore(this.minDate, "date")); } return (day.isSameOrAfter(this.selectedFromDate, "date") && !day.isSameOrAfter(this.maxDate, "date")); } isSelectedDate(day) { const date = this.isLeft ? this.selectedFromDate : this.selectedToDate; return date && day.get("month") === this.month && day.isSame(date, "date"); } isDateInRange(day) { if (this.isLeft) { if (!this.selectedToDate) { return (this.selectedFromDate && day.get("month") === this.month && day.isSameOrAfter(this.selectedFromDate, "date")); } } if (this.selectedFromDate) { return (this.selectedToDate && day.get("month") === this.month && day.isSameOrBefore(this.selectedToDate, "date") && day.isSameOrAfter(this.selectedFromDate, "date")); } } isDifferentMonth(day) { return day.get("month") !== this.month; } dateSelected(event, data) { this.dateChanged.emit({ day: data.day, isLeft: this.isLeft }); event.stopPropagation(); } monthSelected(event, data) { this.monthChanged.emit({ value: data.value, isLeft: this.isLeft }); event.stopPropagation(); } yearSelected(event, data) { this.yearChanged.emit({ value: data.value, isLeft: this.isLeft }); event.stopPropagation(); } } CalendarComponent.decorators = [ { type: Component, args: [{ changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, selector: "calendar", template: "<div class=\"row\">\n <div class=\"col text-center\">\n <div\n class=\"d-flex align-items-center calendar-pagination {{\n icons === 'material' ? 'material' : ''\n }}\"\n >\n <div>\n <button\n type=\"button\"\n class=\"btn btn-link btn-previous-year\"\n (click)=\"yearSelected($event, { value: -1 })\"\n >\n <i *ngIf=\"icons === 'material'\" class=\"material-icons\">first_page</i>\n <i\n *ngIf=\"icons === 'font-awesome'\"\n class=\"fas fa-angle-double-left\"\n ></i>\n <img\n *ngIf=\"icons === 'default'\"\n src=\"data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTkuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA0MDcuNDM2IDQwNy40MzYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQwNy40MzYgNDA3LjQzNjsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHdpZHRoPSIxNnB4IiBoZWlnaHQ9IjE2cHgiPgo8Zz4KCTxwb2x5Z29uIHBvaW50cz0iMjY2LjQ1MiwyMS4xNzggMjQ1LjIwNCwwIDQyLjE0OSwyMDMuNzE4IDI0NS4yMDQsNDA3LjQzNiAyNjYuNDUyLDM4Ni4yNTggODQuNTA3LDIwMy43MTggICIgZmlsbD0iIzAwMDAwMCIvPgoJPHBvbHlnb24gcG9pbnRzPSIzNjUuMjg2LDIxLjE3OCAzNDQuMDM4LDAgMTQwLjk4MywyMDMuNzE4IDM0NC4wMzgsNDA3LjQzNiAzNjUuMjg2LDM4Ni4yNTggMTgzLjM0MSwyMDMuNzE4ICAiIGZpbGw9IiMwMDAwMDAiLz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8Zz4KPC9nPgo8L3N2Zz4K\"\n />\n </button>\n </div>\n <div>\n <button\n type=\"button\"\n class=\"btn btn-link btn-previous-month\"\n (click)=\"monthSelected($event, { value: -1 })\"\n >\n <i *ngIf=\"icons === 'material'\" class=\"material-icons\"\n >chevron_left</i\n >\n <i *ngIf=\"icons === 'font-awesome'\" class=\"fas fa-angle-left\"></i>\n <img\n *ngIf=\"icons === 'default'\"\n src=\"data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCIgdmlld0JveD0iMCAwIDQ0NC41MzEgNDQ0LjUzMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDQ0LjUzMSA0NDQuNTMxOyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPHBhdGggZD0iTTIxMy4xMywyMjIuNDA5TDM1MS44OCw4My42NTNjNy4wNS03LjA0MywxMC41NjctMTUuNjU3LDEwLjU2Ny0yNS44NDFjMC0xMC4xODMtMy41MTgtMTguNzkzLTEwLjU2Ny0yNS44MzUgICBsLTIxLjQwOS0yMS40MTZDMzIzLjQzMiwzLjUyMSwzMTQuODE3LDAsMzA0LjYzNywwcy0xOC43OTEsMy41MjEtMjUuODQxLDEwLjU2MUw5Mi42NDksMTk2LjQyNSAgIGMtNy4wNDQsNy4wNDMtMTAuNTY2LDE1LjY1Ni0xMC41NjYsMjUuODQxczMuNTIxLDE4Ljc5MSwxMC41NjYsMjUuODM3bDE4Ni4xNDYsMTg1Ljg2NGM3LjA1LDcuMDQzLDE1LjY2LDEwLjU2NCwyNS44NDEsMTAuNTY0ICAgczE4Ljc5NS0zLjUyMSwyNS44MzQtMTAuNTY0bDIxLjQwOS0yMS40MTJjNy4wNS03LjAzOSwxMC41NjctMTUuNjA0LDEwLjU2Ny0yNS42OTdjMC0xMC4wODUtMy41MTgtMTguNzQ2LTEwLjU2Ny0yNS45NzggICBMMjEzLjEzLDIyMi40MDl6IiBmaWxsPSIjMDAwMDAwIi8+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==\"\n />\n </button>\n </div>\n <div class=\"flex-grow-1 month-year\">{{ monthText }} {{ year }}</div>\n <div>\n <button\n type=\"button\"\n class=\"btn btn-link btn-next-month\"\n (click)=\"monthSelected($event, { value: 1 })\"\n >\n <i *ngIf=\"icons === 'material'\" class=\"material-icons\"\n >chevron_right</i\n >\n <i *ngIf=\"icons === 'font-awesome'\" class=\"fas fa-angle-right\"></i>\n <img\n *ngIf=\"icons === 'default'\"\n src=\"data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTYuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4PSIwcHgiIHk9IjBweCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCIgdmlld0JveD0iMCAwIDQ0NC44MTkgNDQ0LjgxOSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDQ0LjgxOSA0NDQuODE5OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+CjxnPgoJPHBhdGggZD0iTTM1Mi4wMjUsMTk2LjcxMkwxNjUuODg0LDEwLjg0OEMxNTkuMDI5LDMuNjE1LDE1MC40NjksMCwxNDAuMTg3LDBjLTEwLjI4MiwwLTE4Ljg0MiwzLjYxOS0yNS42OTcsMTAuODQ4TDkyLjc5MiwzMi4yNjQgICBjLTcuMDQ0LDcuMDQzLTEwLjU2NiwxNS42MDQtMTAuNTY2LDI1LjY5MmMwLDkuODk3LDMuNTIxLDE4LjU2LDEwLjU2NiwyNS45ODFsMTM4Ljc1MywxMzguNDczTDkyLjc4NiwzNjEuMTY4ICAgYy03LjA0Miw3LjA0My0xMC41NjQsMTUuNjA0LTEwLjU2NCwyNS42OTNjMCw5Ljg5NiwzLjUyMSwxOC41NjIsMTAuNTY0LDI1Ljk4bDIxLjcsMjEuNDEzICAgYzcuMDQzLDcuMDQzLDE1LjYxMiwxMC41NjQsMjUuNjk3LDEwLjU2NGMxMC4wODksMCwxOC42NTYtMy41MjEsMjUuNjk3LTEwLjU2NGwxODYuMTQ1LTE4NS44NjQgICBjNy4wNDYtNy40MjMsMTAuNTcxLTE2LjA4NCwxMC41NzEtMjUuOTgxQzM2Mi41OTcsMjEyLjMyMSwzNTkuMDcxLDIwMy43NTUsMzUyLjAyNSwxOTYuNzEyeiIgZmlsbD0iIzAwMDAwMCIvPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+CjxnPgo8L2c+Cjwvc3ZnPgo=\"\n />\n </button>\n </div>\n <div>\n <button\n type=\"button\"\n class=\"btn btn-link btn-next-year\"\n (click)=\"yearSelected($event, { value: 1 })\"\n >\n <i *ngIf=\"icons === 'material'\" class=\"material-icons\">last_page</i>\n <i\n *ngIf=\"icons === 'font-awesome'\"\n class=\"fas fa-angle-double-right\"\n ></i>\n <img\n *ngIf=\"icons === 'default'\"\n src=\"data:image/svg+xml;utf8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pgo8IS0tIEdlbmVyYXRvcjogQWRvYmUgSWxsdXN0cmF0b3IgMTkuMC4wLCBTVkcgRXhwb3J0IFBsdWctSW4gLiBTVkcgVmVyc2lvbjogNi4wMCBCdWlsZCAwKSAgLS0+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgdmVyc2lvbj0iMS4xIiBpZD0iTGF5ZXJfMSIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCA0MDcuNDM2IDQwNy40MzYiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQwNy40MzYgNDA3LjQzNjsiIHhtbDpzcGFjZT0icHJlc2VydmUiIHdpZHRoPSIxNnB4IiBoZWlnaHQ9IjE2cHgiPgo8Zz4KCTxwb2x5Z29uIHBvaW50cz0iMTYyLjIzMSwwIDE0MC45ODMsMjEuMTc4IDMyMi45MjksMjAzLjcxOCAxNDAuOTgzLDM4Ni4yNTggMTYyLjIzMSw0MDcuNDM2IDM2NS4yODYsMjAzLjcxOCAgIiBmaWxsPSIjMDAwMDAwIi8+Cgk8cG9seWdvbiBwb2ludHM9IjYzLjM5NywwIDQyLjE0OSwyMS4xNzggMjI0LjA5NSwyMDMuNzE4IDQyLjE0OSwzODYuMjU4IDYzLjM5Nyw0MDcuNDM2IDI2Ni40NTIsMjAzLjcxOCAgIiBmaWxsPSIjMDAwMDAwIi8+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPGc+CjwvZz4KPC9zdmc+Cg==\"\n />\n </button>\n </div>\n </div>\n </div>\n</div>\n\n<div class=\"row\">\n <div class=\"col\">\n <table class=\"table table-borderless mb-0\">\n <thead>\n <tr class=\"week-days\">\n <th *ngFor=\"let day of getWeekDays()\">{{ day }}</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let week of weekList; let i = index\">\n <td\n *ngFor=\"let day of weekList[i]\"\n (click)=\"dateSelected($event, { day: day })\"\n [ngClass]=\"{\n selected: isSelectedDate(day),\n 'in-selected-range': isDateInRange(day),\n disabled: isDisabled(day),\n 'different-month': isDifferentMonth(day)\n }\"\n >\n {{ day.format(\"D\") }}\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n</div>\n", styles: [".calendar.calendar-single .table td.in-selected-range{background-color:transparent}.calendar .calendar-pagination{font-size:16px;margin:.5rem -15px 0}.calendar .calendar-pagination.material .btn.btn-previous-year{padding-right:3px}.calendar .calendar-pagination.material .btn.btn-previous-month{padding-left:0}.calendar .calendar-pagination.material .btn.btn-next-month{padding-right:0}.calendar .calendar-pagination.material .btn.btn-next-year{padding-left:3px}.calendar .calendar-pagination .month-year{font-weight:600}.calendar .week-days{text-transform:uppercase}.calendar .table th,.calendar .table td{border-radius:0;color:#333;font-size:12px;height:36px;line-height:1;padding:0;text-align:center;vertical-align:middle}.calendar .table th{font-weight:400}.calendar .table td{border-radius:5px;cursor:pointer;font-weight:900;width:32px;max-width:32px}.calendar .table td:not(.disabled):not(.selected):hover{background-color:#eee;color:#333}.calendar .table td.selected{background-color:#003d79;border-radius:5px;color:#fff;font-size:12px}.calendar .table td.selected.in-selected-range{background-color:#003d79;border-radius:5px}.calendar .table td.selected:hover{background-color:#003d79}.calendar .table td.in-selected-range{background-color:#dfefff;border-radius:0;font-size:12px}.calendar .table td.disabled{background-color:transparent;color:#666;cursor:not-allowed;font-weight:400}.calendar .table td.different-month{color:#888;font-weight:500}.calendar .table td.different-month.disabled{color:#ccc}\n"] },] } ]; CalendarComponent.propDecorators = { month: [{ type: Input }], year: [{ type: Input }], selectedFromDate: [{ type: Input }], selectedToDate: [{ type: Input }], isLeft: [{ type: Input }], format: [{ type: Input }], minDate: [{ type: Input }], maxDate: [{ type: Input }], singleCalendar: [{ type: Input }], icons: [{ type: Input }], dateChanged: [{ type: Output }], monthChanged: [{ type: Output }], yearChanged: [{ type: Output }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsZW5kYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL21vZHVsZXMvbmd4LWRhdGVyYW5nZS9zcmMvY29tcG9uZW50cy9jYWxlbmRhci9jYWxlbmRhci5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBQ0wsTUFBTSxFQUNOLFlBQVksRUFFWixpQkFBaUIsRUFDakIsdUJBQXVCLEVBQ3hCLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sS0FBSyxRQUFRLE1BQU0sUUFBUSxDQUFDO0FBQ25DLE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQztBQUV4QixPQUFPLEVBQUUsWUFBWSxFQUFhLE1BQU0sY0FBYyxDQUFDO0FBR3ZELE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxZQUFZLENBQUMsTUFBTSxDQUFDLENBQUM7QUFTdkMsTUFBTSxPQUFPLGlCQUFpQjtJQVA5QjtRQWlDRSxtQkFBYyxHQUFHLEtBQUssQ0FBQztRQU12QixnQkFBVyxHQUFHLElBQUksWUFBWSxFQUFnQixDQUFDO1FBRy9DLGlCQUFZLEdBQUcsSUFBSSxZQUFZLEVBQWdCLENBQUM7UUFHaEQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBZ0IsQ0FBQztJQXlLakQsQ0FBQztJQXJLQyxJQUFJLFNBQVM7UUFDWCxPQUFPLE1BQU0sQ0FBQyxXQUFXLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDMUMsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQsV0FBVztRQUNULE9BQU8sTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBRUQsY0FBYyxDQUFDLFVBQXFCO1FBQ2xDLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztRQUN2QixNQUFNLEtBQUss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bnB1dCxcbiAgT3V0cHV0LFxuICBFdmVudEVtaXR0ZXIsXG4gIE9uQ2hhbmdlcyxcbiAgVmlld0VuY2Fwc3VsYXRpb24sXG4gIENoYW5nZURldGVjdGlvblN0cmF0ZWd5XG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5cbmltcG9ydCAqIGFzIG1vbWVudE5zIGZyb20gXCJtb21lbnRcIjtcbmNvbnN0IG1vbWVudCA9IG1vbWVudE5zO1xuXG5pbXBvcnQgeyBleHRlbmRNb21lbnQsIERhdGVSYW5nZSB9IGZyb20gXCJtb21lbnQtcmFuZ2VcIjtcbmltcG9ydCB7IElDaGFuZ2VkRGF0YSwgSURhdGVSYW5nZSB9IGZyb20gXCIuLi8uLi9pbnRlcmZhY2VzXCI7XG5cbmNvbnN0IHsgcmFuZ2UgfSA9IGV4dGVuZE1vbWVudChtb21lbnQpO1xuXG5AQ29tcG9uZW50KHtcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIHNlbGVjdG9yOiBcImNhbGVuZGFyXCIsXG4gIHN0eWxlVXJsczogW1wiLi9jYWxlbmRhci5jb21wb25lbnQuc2Nzc1wiXSxcbiAgdGVtcGxhdGVVcmw6IFwiLi9jYWxlbmRhci5jb21wb25lbnQuaHRtbFwiXG59KVxuZXhwb3J0IGNsYXNzIENhbGVuZGFyQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzIHtcbiAgQElucHV0KClcbiAgbW9udGg6IG51bWJlcjtcblxuICBASW5wdXQoKVxuICB5ZWFyOiBudW1iZXI7XG5cbiAgQElucHV0KClcbiAgc2VsZWN0ZWRGcm9tRGF0ZTogbW9tZW50TnMuTW9tZW50O1xuXG4gIEBJbnB1dCgpXG4gIHNlbGVjdGVkVG9EYXRlOiBtb21lbnROcy5Nb21lbnQ7XG5cbiAgQElucHV0KClcbiAgaXNMZWZ0OiBib29sZWFuO1xuXG4gIEBJbnB1dCgpXG4gIGZvcm1hdDogc3RyaW5nO1xuXG4gIEBJbnB1dCgpXG4gIG1pbkRhdGU6IG1vbWVudE5zLk1vbWVudDtcblxuICBASW5wdXQoKVxuICBtYXhEYXRlOiBtb21lbnROcy5Nb21lbnQ7XG5cbiAgQElucHV0KClcbiAgc2luZ2xlQ2FsZW5kYXIgPSBmYWxzZTtcblxuICBASW5wdXQoKVxuICBpY29uczogc3RyaW5nO1xuXG4gIEBPdXRwdXQoKVxuICBkYXRlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8SUNoYW5nZWREYXRhPigpO1xuXG4gIEBPdXRwdXQoKVxuICBtb250aENoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPElDaGFuZ2VkRGF0YT4oKTtcblxuICBAT3V0cHV0KClcbiAgeWVhckNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPElDaGFuZ2VkRGF0YT4oKTtcblxuICB3ZWVrTGlzdDogYW55IC8vSURhdGVSYW5nZVtdO1xuXG4gIGdldCBtb250aFRleHQoKSB7XG4gICAgcmV0dXJuIG1vbWVudC5tb250aHNTaG9ydCgpW3RoaXMubW9udGhdO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5jcmVhdGVDYWxlbmRhckdyaWREYXRhKCk7XG4gIH1cblxuICBnZXRXZWVrRGF5cygpIHtcbiAgICByZXR1cm4gbW9tZW50LndlZWtkYXlzU2hvcnQodHJ1ZSk7XG4gIH1cblxuICBnZXRXZWVrTnVtYmVycyhtb250aFJhbmdlOiBEYXRlUmFuZ2UpOiBudW1iZXJbXSB7XG4gICAgY29uc3Qgd2Vla051bWJlcnMgPSBbXTtcbiAgICBjb25zdCB3ZWVrcyA9IEFycmF5LmZyb20obW9udGhSYW5nZS5ieShcIndlZWtzXCIpKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgd2Vla3MubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IHdlZWsgPSB3ZWVrc1tpXTtcblxuICAgICAgaWYgKGkgPCA2KSB7XG4gICAgICAgIHdlZWtOdW1iZXJzLnB1c2god2Vlay53ZWVrKCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHdlZWtOdW1iZXJzO1xuICB9XG5cbiAgZ2V0V2Vla3NSYW5nZSh3ZWVrczogbnVtYmVyW10pOiBEYXRlUmFuZ2VbXSB7XG4gICAgY29uc3Qgd2Vla3NSYW5nZSA9IFtdO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB3ZWVrcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgd2VlayA9IHdlZWtzW2ldO1xuXG4gICAgICBsZXQgZmlyc3RXZWVrRGF5ID0gbW9tZW50KFt0aGlzLnllYXIsIHRoaXMubW9udGhdKVxuICAgICAgICAud2Vlayh3ZWVrKVxuICAgICAgICAuc3RhcnRPZihcIndlZWtcIik7XG4gICAgICBsZXQgbGFzdFdlZWtEYXkgPSBtb21lbnQoW3RoaXMueWVhciwgdGhpcy5tb250aF0pXG4gICAgICAgIC53ZWVrKHdlZWspXG4gICAgICAgIC5lbmRPZihcIndlZWtcIik7XG5cbiAgICAgIGlmIChpID4gMCAmJiB3ZWVrIDwgd2Vla3NbaSAtIDFdKSB7XG4gICAgICAgIGZpcnN0V2Vla0RheS5hZGQoMSwgXCJ5ZWFyXCIpO1xuICAgICAgICBsYXN0V2Vla0RheS5hZGQoMSwgXCJ5ZWFyXCIpO1xuICAgICAgfVxuXG4gICAgICB3ZWVrc1JhbmdlLnB1c2goXG4gICAgICAgIHJhbmdlKFxuICAgICAgICAgIGZpcnN0V2Vla0RheS53ZWVrKHdlZWspLnN0YXJ0T2YoXCJ3ZWVrXCIpLFxuICAgICAgICAgIGxhc3RXZWVrRGF5LndlZWsod2VlaykuZW5kT2YoXCJ3ZWVrXCIpXG4gICAgICAgIClcbiAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHdlZWtzUmFuZ2U7XG4gIH1cblxuICBjcmVhdGVDYWxlbmRhckdyaWREYXRhKCk6IHZvaWQge1xuICAgIGNvbnN0IGZpcnN0RGF5ID0gbW9tZW50KFt0aGlzLnllYXIsIHRoaXMubW9udGhdKS5zdGFydE9mKFwibW9udGhcIik7XG4gICAgY29uc3QgZW5kRGF5ID0gbW9tZW50KFt0aGlzLnllYXIsIHRoaXMubW9udGhdKVxuICAgICAgLmVuZE9mKFwibW9udGhcIilcbiAgICAgIC5lbmRPZihcIndlZWtcIik7XG4gICAgY29uc3QgbW9udGhSYW5nZSA9IHJhbmdlKGZpcnN0RGF5LCBlbmREYXkpO1xuICAgIGNvbnN0IHdlZWtzUmFuZ2UgPSB0aGlzLmdldFdlZWtzUmFuZ2UodGhpcy5nZXRXZWVrTnVtYmVycyhtb250aFJhbmdlKSk7XG4gICAgY29uc3Qgd2Vla0xpc3QgPSBbXTtcblxuICAgIHdlZWtzUmFuZ2UubWFwKHdlZWsgPT4ge1xuICAgICAgY29uc3QgZGF5c0xpc3QgPSBbXTtcblxuICAgICAgQXJyYXkuZnJvbSh3ZWVrLmJ5KFwiZGF5c1wiKSkuZm9yRWFjaCgoZGF5OiBtb21lbnROcy5Nb21lbnQpID0+IHtcbiAgICAgICAgaWYgKGRheS5pc1NhbWUodGhpcy5taW5EYXRlLCBcImRhdGVcIikpIHtcbiAgICAgICAgICBkYXkgPSB0aGlzLm1pbkRhdGU7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF5LmlzU2FtZSh0aGlzLm1heERhdGUsIFwiZGF0ZVwiKSkge1xuICAgICAgICAgIGRheSA9IHRoaXMubWF4RGF0ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRheXNMaXN0LnB1c2goZGF5KTtcbiAgICAgIH0pO1xuXG4gICAgICB3ZWVrTGlzdC5wdXNoKGRheXNMaXN0KTtcbiAgICB9KTtcblxuICAgIHRoaXMud2Vla0xpc3QgPSB3ZWVrTGlzdDtcbiAgfVxuXG4gIGlzRGlzYWJsZWQoZGF5OiBtb21lbnROcy5Nb21lbnQpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKFxuICAgICAgZGF5LmlzQmVmb3JlKHRoaXMubWluRGF0ZSkgfHxcbiAgICAgIGRheS5pc0FmdGVyKHRoaXMubWF4RGF0ZSkgfHxcbiAgICAgIChkYXkuaXNCZWZvcmUodGhpcy5zZWxlY3RlZEZyb21EYXRlKSAmJiAhdGhpcy5pc0xlZnQpXG4gICAgKTtcbiAgfVxuXG4gIGlzRGF0ZUF2YWlsYWJsZShkYXk6IG1vbWVudE5zLk1vbWVudCk6IGJvb2xlYW4ge1xuICAgIGlmICh0aGlzLmlzTGVmdCkge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgZGF5LmlzU2FtZU9yQmVmb3JlKHRoaXMuc2VsZWN0ZWRUb0RhdGUsIFwiZGF0ZVwiKSAmJlxuICAgICAgICAhZGF5LmlzU2FtZU9yQmVmb3JlKHRoaXMubWluRGF0ZSwgXCJkYXRlXCIpXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiAoXG4gICAgICBkYXkuaXNTYW1lT3JBZnRlcih0aGlzLnNlbGVjdGVkRnJvbURhdGUsIFwiZGF0ZVwiKSAmJlxuICAgICAgIWRheS5pc1NhbWVPckFmdGVyKHRoaXMubWF4RGF0ZSwgXCJkYXRlXCIpXG4gICAgKTtcbiAgfVxuXG4gIGlzU2VsZWN0ZWREYXRlKGRheTogbW9tZW50TnMuTW9tZW50KTogYm9vbGVhbiB7XG4gICAgY29uc3QgZGF0ZSA9IHRoaXMuaXNMZWZ0ID8gdGhpcy5zZWxlY3RlZEZyb21EYXRlIDogdGhpcy5zZWxlY3RlZFRvRGF0ZTtcblxuICAgIHJldHVybiBkYXRlICYmIGRheS5nZXQoXCJtb250aFwiKSA9PT0gdGhpcy5tb250aCAmJiBkYXkuaXNTYW1lKGRhdGUsIFwiZGF0ZVwiKTtcbiAgfVxuXG4gIGlzRGF0ZUluUmFuZ2UoZGF5OiBtb21lbnROcy5Nb21lbnQpOiBib29sZWFuIHtcbiAgICBpZiAodGhpcy5pc0xlZnQpIHtcbiAgICAgIGlmICghdGhpcy5zZWxlY3RlZFRvRGF0ZSkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGcm9tRGF0ZSAmJlxuICAgICAgICAgIGRheS5nZXQoXCJtb250aFwiKSA9PT0gdGhpcy5tb250aCAmJlxuICAgICAgICAgIGRheS5pc1NhbWVPckFmdGVyKHRoaXMuc2VsZWN0ZWRGcm9tRGF0ZSwgXCJkYXRlXCIpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRGcm9tRGF0ZSkge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgdGhpcy5zZWxlY3RlZFRvRGF0ZSAmJlxuICAgICAgICBkYXkuZ2V0KFwibW9udGhcIikgPT09IHRoaXMubW9udGggJiZcbiAgICAgICAgZGF5LmlzU2FtZU9yQmVmb3JlKHRoaXMuc2VsZWN0ZWRUb0RhdGUsIFwiZGF0ZVwiKSAmJlxuICAgICAgICBkYXkuaXNTYW1lT3JBZnRlcih0aGlzLnNlbGVjdGVkRnJvbURhdGUsIFwiZGF0ZVwiKVxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBpc0RpZmZlcmVudE1vbnRoKGRheTogbW9tZW50TnMuTW9tZW50KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIGRheS5nZXQoXCJtb250aFwiKSAhPT0gdGhpcy5tb250aDtcbiAgfVxuXG4gIGRhdGVTZWxlY3RlZChldmVudDogRXZlbnQsIGRhdGE6IElDaGFuZ2VkRGF0YSk6IHZvaWQge1xuICAgIHRoaXMuZGF0ZUNoYW5nZWQuZW1pdCh7XG4gICAgICBkYXk6IGRhdGEuZGF5LFxuICAgICAgaXNMZWZ0OiB0aGlzLmlzTGVmdFxuICAgIH0pO1xuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cblxuICBtb250aFNlbGVjdGVkKGV2ZW50OiBFdmVudCwgZGF0YTogSUNoYW5nZWREYXRhKTogdm9pZCB7XG4gICAgdGhpcy5tb250aENoYW5nZWQuZW1pdCh7XG4gICAgICB2YWx1ZTogZGF0YS52YWx1ZSxcbiAgICAgIGlzTGVmdDogdGhpcy5pc0xlZnRcbiAgICB9KTtcblxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICB9XG5cbiAgeWVhclNlbGVjdGVkKGV2ZW50OiBFdmVudCwgZGF0YTogSUNoYW5nZWREYXRhKTogdm9pZCB7XG4gICAgdGhpcy55ZWFyQ2hhbmdlZC5lbWl0KHtcbiAgICAgIHZhbHVlOiBkYXRhLnZhbHVlLFxuICAgICAgaXNMZWZ0OiB0aGlzLmlzTGVmdFxuICAgIH0pO1xuXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH1cbn1cbiJdfQ==