UNPKG

ngx-ui-hero

Version:

Simple, fast and reliable utilities for Angular.

199 lines 60.3 kB
import * as momentImported from 'moment';
import { Component, ContentChild, EventEmitter, Inject, Input, Optional, Output, TemplateRef } from '@angular/core';
import { CHARTS_CONFIG } from '../../config/charts-config.contants';
import { GanttSeriesTooltipTemplateDirective } from '../../directives/gantt-templates.directive';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
import * as i2 from "ngx-bootstrap/tooltip";
const moment = momentImported;
let identifier = 0;
export class GanttChartComponent {
    constructor(config) {
        this.tooltipPlacement = 'left';
        this.maxHeight = 0;
        this.showFooter = false;
        this.showTodayIndicator = true;
        this.onSelect = new EventEmitter();
        this.identifier = `gantt-chart-${identifier++}`;
        this.locale = 'en-us';
        this.emptyMessage = 'No results found at this moment.';
        this.showingMouseIndicator = false;
        this.mouseMovingLastMonth = false;
        this.colors = [
            '#8270fa',
            '#4d5b66',
            '#4fd1a1',
            '#fe3cae',
            '#ffca22',
            '#ff9f41',
            '#5aaaff',
            '#498acb',
            '#27cfc2',
            '#ff6982',
            '#f44336',
            '#cddc39',
            '#607d8b',
            '#795548'
        ];
        Object.assign(this, config);
    }
    ngOnInit() {
        this.initData();
        this.initMonths();
        this.initTimelineSizes();
        this.initTodayIndicator();
    }
    onResize() {
        this.handleTimelineSizes();
        this.initTodayIndicator();
    }
    onSerieSelected(item, serie) {
        this.onSelect.emit({
            item,
            serie
        });
    }
    onTimelineMouseMove(event) {
        if (!this.showingMouseIndicator)
            return;
        let offset = $(`#${this.identifier} .gantt-timeline .timeline`).offset();
        this.mouseIndicatorCoordinateX = event.pageX - offset.left;
        let monthWidth = $(`#${this.identifier} .gantt-timeline .timeline .item:first-child`).children('.box:first-child').width();
        let monthIndexBeingHovered = Math.floor(this.mouseIndicatorCoordinateX / (monthWidth + 2));
        let date = new Date(this.currentYear, monthIndexBeingHovered, 1);
        let daysInMonth = moment(date).daysInMonth();
        let dayWidth = monthWidth / daysInMonth;
        let dayBeignHovered = Math.floor((this.mouseIndicatorCoordinateX - ((monthWidth + 2) * monthIndexBeingHovered)) / dayWidth) + 1;
        if (dayBeignHovered <= 0 || dayBeignHovered > daysInMonth)
            return;
        this.dateIndicator = new Date(this.currentYear, monthIndexBeingHovered, dayBeignHovered);
        this.mouseMovingLastMonth = monthIndexBeingHovered == 11;
    }
    onTimelineMouseEnter() {
        this.showingMouseIndicator = true;
    }
    onTimelineMouseLeave() {
        this.showingMouseIndicator = false;
    }
    initData() {
        if (!this.externalData || this.externalData.length == 0)
            return;
        this.internalData = new Array();
        for (let i = 0; i < this.externalData.length; i++) {
            let colorIndex = Math.round(Math.random() * (this.colors.length - 1));
            this.internalData.push({
                label: this.externalData[i].label,
                series: this.externalData[i].series.map(s => {
                    return {
                        color: s.color || this.colors[colorIndex],
                        startDate: s.startDate,
                        endDate: s.endDate,
                        data: s.data,
                        left: 0,
                        width: 0,
                        daysDiff: this.daysDiffFromSerie(s),
                        label: s.label
                    };
                })
            });
        }
    }
    daysDiffFromSerie(serie) {
        var start = moment(serie.startDate);
        var end = moment(serie.endDate);
        return end.diff(start, 'days') + 1;
    }
    monthsDiffFromSerie(serie) {
        var start = moment(serie.startDate);
        var end = moment(serie.endDate);
        return end.diff(start, 'months');
    }
    initMonths() {
        moment.locale(this.locale);
        let today = new Date();
        if (!this.currentYear) {
            this.currentYear = today.getFullYear();
        }
        let referenceDate = new Date(this.currentYear, today.getMonth(), today.getDay());
        this.dayLabel = moment.localeData().relativeTime(1, false, 'd', false).split(' ')[1];
        this.monthLabel = moment.localeData().relativeTime(1, false, 'M', false).split(' ')[1];
        this.yearLabel = moment.localeData().relativeTime(1, false, 'y', false).split(' ')[1];
        this.currentMonth = referenceDate.getMonth();
        this.months = moment.monthsShort('-MMM-');
    }
    initTimelineSizes() {
        setTimeout(() => {
            this.handleTimelineSizes();
        }, 0);
    }
    initTodayIndicator() {
        setTimeout(() => {
            let monthWidth = $(`#${this.identifier} .gantt-timeline .timeline .item:first-child`).children('.box:first-child').width();
            let referenceDate = new Date();
            let day = referenceDate.getDate();
            let month = referenceDate.getMonth() + 1;
            let firstDayWidth = monthWidth / moment(referenceDate).daysInMonth();
            this.todayIndicatorCoordinateX = ((month - 1) * monthWidth) + ((day - 1) * firstDayWidth) + ((month - 1) * 2);
        }, 0);
    }
    handleTimelineSizes() {
        if (!this.internalData || this.internalData.length == 0)
            return;
        let monthWidth = $(`#${this.identifier} .gantt-timeline .timeline .item:first-child`).children('.box:first-child').width();
        for (let i = 0; i < this.internalData.length; i++) {
            if (!this.internalData[i].series || this.internalData[i].series.length == 0)
                continue;
            for (let s = 0; s < this.internalData[i].series.length; s++) {
                let serieTotalWidth = 0;
                let day = this.internalData[i].series[s].startDate.getDate();
                let month = this.internalData[i].series[s].startDate.getMonth() + 1;
                let daysDiff = this.internalData[i].series[s].daysDiff;
                let startDate = this.internalData[i].series[s].startDate;
                let firstDayWidth = monthWidth / moment(startDate).daysInMonth();
                let monthsDiff = this.monthsDiffFromSerie(this.internalData[i].series[s]);
                for (let d = 0; d < daysDiff; d++) {
                    let date = moment(startDate).add({ days: d }).toDate();
                    let daysInMonth = moment(date).daysInMonth();
                    let dayWidth = monthWidth / daysInMonth;
                    serieTotalWidth += dayWidth;
                }
                this.internalData[i].series[s].left = ((month - 1) * monthWidth) + ((day - 1) * firstDayWidth) + ((month - 1) * 2);
                this.internalData[i].series[s].width = serieTotalWidth + (monthsDiff * 2);
            }
        }
    }
}
GanttChartComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GanttChartComponent, deps: [{ token: CHARTS_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component });
GanttChartComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: GanttChartComponent, selector: "gantt-chart", inputs: { externalData: ["data", "externalData"], caption: "caption", tooltipPlacement: "tooltipPlacement", maxHeight: "maxHeight", showFooter: "showFooter", showTodayIndicator: "showTodayIndicator", currentYear: "currentYear" }, outputs: { onSelect: "onSelect" }, host: { listeners: { "window:resize": "onResize()" } }, queries: [{ propertyName: "seriesTooltipTemplate", first: true, predicate: GanttSeriesTooltipTemplateDirective, descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: "<div id=\"{{identifier}}\" class=\"ui-gantt-chart\">\n    <div class=\"gantt-container\" *ngIf=\"internalData?.length > 0\" [ngStyle]=\"{'maxHeight.px': maxHeight > 0 ? maxHeight : 'auto'}\">\n        <div class=\"gantt-labels\">\n            <div class=\"header\">\n                <div class=\"title\">{{caption}}</div>\n                <div class=\"legends\">\n                    <span class=\"year\">{{yearLabel}}</span>\n                    <span class=\"month\">{{monthLabel}}</span>\n                </div>\n            </div>\n            <div class=\"labels\">\n                <div class=\"label\" *ngFor=\"let item of internalData\">\n                    {{item.label}}\n                </div>\n            </div>\n            <div class=\"footer\" *ngIf=\"showFooter\">\n                <div class=\"title\">{{caption}}</div>\n                <div class=\"legends\">\n                    <span class=\"month\">{{monthLabel}}</span>\n                    <span class=\"year\">{{yearLabel}}</span>\n                </div>\n            </div>\n        </div>\n        <div class=\"gantt-timeline\">\n            <div class=\"header\">\n                <div class=\"year\">{{currentYear}}</div>\n                <div class=\"months\">\n                    <div class=\"month\" *ngFor=\"let item of months\">{{item | uppercase}}</div>\n                </div>\n                <div class=\"date-indicator\" *ngIf=\"showingMouseIndicator\" [ngStyle]=\"{\n                    'left.px': mouseIndicatorCoordinateX - (mouseMovingLastMonth ? 150 : 75)\n                }\">\n                    <i class=\"fa fa-calendar\"></i> {{dateIndicator | date}}\n                </div>\n            </div>\n            <div class=\"timeline\" (mouseenter)=\"onTimelineMouseEnter()\" (mouseleave)=\"onTimelineMouseLeave()\" (mousemove)=\"onTimelineMouseMove($event)\">\n                <div class=\"item\" *ngFor=\"let item of internalData\">\n                    <div class=\"box\" *ngFor=\"let month of months\"></div>\n\n                    <div class=\"serie-container\"  *ngFor=\"let serie of item.series\">\n                        <ng-template #tooltipTemplate>\n                            <ng-container \n                                [ngTemplateOutlet]=\"seriesTooltipTemplate\"\n                                [ngTemplateOutletContext]=\"{\n                                    serie: serie,\n                                    item: item\n                                }\">\n                            </ng-container>\n                        </ng-template>\n\n                        <div class=\"serie\" \n                            [placement]=\"tooltipPlacement\"\n                            [tooltip]=\"seriesTooltipTemplate ? tooltipTemplate : null\"\n                            container=\"body\"\n                            (click)=\"onSerieSelected(item, serie)\"\n                            [ngClass]=\"{\n                                'highlighted': showingMouseIndicator && mouseIndicatorCoordinateX >= serie.left && mouseIndicatorCoordinateX <= (serie.left + serie.width)\n                            }\"\n                            [ngStyle]=\"{\n                                'backgroundColor': serie.color,\n                                'left.px': serie.left,\n                                'width.px': serie.width\n                            }\">\n                            <span class=\"text-truncate\">{{serie.label || serie.daysDiff}}</span>\n                            <div class=\"left-border\"></div>\n                            <div class=\"top-border\"></div>\n                            <div class=\"right-border\"></div>\n                            <div class=\"bottom-border\"></div>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"mouse-indicator\" *ngIf=\"showingMouseIndicator\" [ngStyle]=\"{'left.px': mouseIndicatorCoordinateX}\"></div>\n                <div class=\"mouse-indicator today\" *ngIf=\"showTodayIndicator\" [ngStyle]=\"{'left.px': todayIndicatorCoordinateX}\"></div>\n            </div>\n            <div class=\"footer\" *ngIf=\"showFooter\">\n                <div class=\"months\">\n                    <div class=\"month\" *ngFor=\"let item of months\">{{item | uppercase}}</div>\n                </div>\n                <div class=\"year\">{{currentYear}}</div>\n                <div class=\"date-indicator\" *ngIf=\"showingMouseIndicator\" [ngStyle]=\"{\n                    'left.px': mouseIndicatorCoordinateX - (mouseMovingLastMonth ? 150 : 75)\n                }\">\n                    <i class=\"fa fa-calendar\"></i> {{dateIndicator | date}}\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <p *ngIf=\"!internalData || internalData.length == 0\">{{emptyMessage}}</p>\n</div>\n", styles: ["@keyframes pulse{0%{opacity:.7}50%{opacity:1}to{opacity:.7}}.ui-gantt-chart{width:100%;border:1px solid #eeeeee}.ui-gantt-chart .gantt-container{display:flex;overflow-y:auto}.ui-gantt-chart .gantt-container .gantt-labels .header,.ui-gantt-chart .gantt-container .gantt-labels .footer,.ui-gantt-chart .gantt-container .gantt-timeline .header,.ui-gantt-chart .gantt-container .gantt-timeline .footer{display:flex;height:70px;box-shadow:0 .125rem .25rem #00000013}.ui-gantt-chart .gantt-container .gantt-labels .footer,.ui-gantt-chart .gantt-container .gantt-timeline .footer{box-shadow:0 -.125rem .25rem #00000013}.ui-gantt-chart .gantt-container .gantt-labels{width:300px;flex-shrink:0;position:relative}.ui-gantt-chart .gantt-container .gantt-labels .header,.ui-gantt-chart .gantt-container .gantt-labels .footer{justify-content:space-between;align-items:center;border-right:2px solid #eeeeee;padding:0 20px;background-color:#fff;position:sticky;top:0;z-index:10}.ui-gantt-chart .gantt-container .gantt-labels .header .title,.ui-gantt-chart .gantt-container .gantt-labels .footer .title{color:#717274;font-weight:600;font-size:18px}.ui-gantt-chart .gantt-container .gantt-labels .header .legends,.ui-gantt-chart .gantt-container .gantt-labels .footer .legends{text-align:right}.ui-gantt-chart .gantt-container .gantt-labels .header .legends span,.ui-gantt-chart .gantt-container .gantt-labels .footer .legends span{color:#717274;display:block;font-size:13px;font-weight:700;padding:4px 0;text-transform:capitalize}.ui-gantt-chart .gantt-container .gantt-labels .footer{top:inherit;bottom:0}.ui-gantt-chart .gantt-container .gantt-labels .labels .label{display:flex;align-items:center;font-weight:600;line-height:1.2;background-color:#f1f5f8;border-bottom:1px solid #dfe8ef;border-right:2px solid #dfe8ef;padding:0 20px;height:50px}.ui-gantt-chart .gantt-container .gantt-timeline{flex-grow:1;position:relative}.ui-gantt-chart .gantt-container .gantt-timeline .header,.ui-gantt-chart .gantt-container .gantt-timeline .footer{display:flex;flex-direction:column;justify-content:center;min-width:700px;background-color:#fff;position:sticky;top:0;z-index:10}.ui-gantt-chart .gantt-container .gantt-timeline .header .year,.ui-gantt-chart .gantt-container .gantt-timeline .footer .year{text-align:center;color:#717274;font-size:13px;font-weight:700;padding:4px 0}.ui-gantt-chart .gantt-container .gantt-timeline .header .months,.ui-gantt-chart .gantt-container .gantt-timeline .footer .months{display:flex;padding:4px 0}.ui-gantt-chart .gantt-container .gantt-timeline .header .months .month,.ui-gantt-chart .gantt-container .gantt-timeline .footer .months .month{color:#717274;text-align:center;flex-grow:1;font-size:13px;font-weight:600}.ui-gantt-chart .gantt-container .gantt-timeline .header .date-indicator,.ui-gantt-chart .gantt-container .gantt-timeline .footer .date-indicator{position:absolute;bottom:8px;background-color:#327ace;color:#fff;padding:3px 10px;border-radius:10px;border:1px solid #00559A;font-size:13px;width:150px;text-align:center;transition:left .2s ease-out}.ui-gantt-chart .gantt-container .gantt-timeline .footer{top:inherit;bottom:0}.ui-gantt-chart .gantt-container .gantt-timeline .footer .date-indicator{bottom:35px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline{position:relative;min-width:700px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item{display:flex;position:relative;transition:background-color .2s ease-in-out}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .box{flex-grow:1;transition:background-color .2s ease-in-out;border-bottom:1px solid #eeeeee;border-right:2px solid #eeeeee;height:50px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .box:last-child{border-right:0}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .box:hover{background-color:#f0f0f0}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie{cursor:pointer;position:absolute;display:flex;align-items:center;color:#fff;font-size:13px;font-weight:600;top:5px;bottom:6px;padding:0 5px;transition:opacity .3s ease-in-out,width .8s ease-out;z-index:9}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie:hover{opacity:.8}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .left-border,.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .top-border,.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .right-border,.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .bottom-border{position:absolute;background-color:#333;opacity:.5;z-index:11}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .left-border{top:2px;left:0;bottom:2px;width:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .top-border{top:0;right:0;left:0;height:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .right-border{top:2px;right:0;bottom:2px;width:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .bottom-border{bottom:0;right:0;left:0;height:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie.highlighted{animation:pulse 1s infinite ease-in-out}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item:hover{background-color:#f9f9f9}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator{position:absolute;top:0;bottom:0;width:0;border-right:1px dashed #327ACE;z-index:8;-webkit-user-select:none;user-select:none;outline:none}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator.today{border-right:1px dashed #327ACE;z-index:10}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator.today:before{content:\"\";position:absolute;top:0;left:-4.5px;width:0;height:0;z-index:8;border-top:5px solid #327ACE;border-right:5px solid transparent;border-left:5px solid transparent}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator.today:after{content:\"\";position:absolute;bottom:0;left:-4.5px;width:0;height:0;z-index:8;border-bottom:5px solid #327ACE;border-right:5px solid transparent;border-left:5px solid transparent}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.TooltipDirective, selector: "[tooltip], [tooltipHtml]", inputs: ["containerClass", "tooltipAnimation", "tooltipFadeDuration", "isOpen", "tooltipHtml", "tooltip", "tooltipPlacement", "placement", "tooltipIsOpen", "tooltipEnable", "isDisabled", "tooltipAppendToBody", "container", "tooltipClass", "tooltipContext", "tooltipPopupDelay", "delay", "tooltipTrigger", "triggers", "adaptivePosition"], outputs: ["tooltipChange", "tooltipStateChanged", "onShown", "onHidden"], exportAs: ["bs-tooltip"] }, { kind: "pipe", type: i1.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i1.DatePipe, name: "date" }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: GanttChartComponent, decorators: [{
            type: Component,
            args: [{ selector: 'gantt-chart', host: {
                        '(window:resize)': 'onResize()'
                    }, template: "<div id=\"{{identifier}}\" class=\"ui-gantt-chart\">\n    <div class=\"gantt-container\" *ngIf=\"internalData?.length > 0\" [ngStyle]=\"{'maxHeight.px': maxHeight > 0 ? maxHeight : 'auto'}\">\n        <div class=\"gantt-labels\">\n            <div class=\"header\">\n                <div class=\"title\">{{caption}}</div>\n                <div class=\"legends\">\n                    <span class=\"year\">{{yearLabel}}</span>\n                    <span class=\"month\">{{monthLabel}}</span>\n                </div>\n            </div>\n            <div class=\"labels\">\n                <div class=\"label\" *ngFor=\"let item of internalData\">\n                    {{item.label}}\n                </div>\n            </div>\n            <div class=\"footer\" *ngIf=\"showFooter\">\n                <div class=\"title\">{{caption}}</div>\n                <div class=\"legends\">\n                    <span class=\"month\">{{monthLabel}}</span>\n                    <span class=\"year\">{{yearLabel}}</span>\n                </div>\n            </div>\n        </div>\n        <div class=\"gantt-timeline\">\n            <div class=\"header\">\n                <div class=\"year\">{{currentYear}}</div>\n                <div class=\"months\">\n                    <div class=\"month\" *ngFor=\"let item of months\">{{item | uppercase}}</div>\n                </div>\n                <div class=\"date-indicator\" *ngIf=\"showingMouseIndicator\" [ngStyle]=\"{\n                    'left.px': mouseIndicatorCoordinateX - (mouseMovingLastMonth ? 150 : 75)\n                }\">\n                    <i class=\"fa fa-calendar\"></i> {{dateIndicator | date}}\n                </div>\n            </div>\n            <div class=\"timeline\" (mouseenter)=\"onTimelineMouseEnter()\" (mouseleave)=\"onTimelineMouseLeave()\" (mousemove)=\"onTimelineMouseMove($event)\">\n                <div class=\"item\" *ngFor=\"let item of internalData\">\n                    <div class=\"box\" *ngFor=\"let month of months\"></div>\n\n                    <div class=\"serie-container\"  *ngFor=\"let serie of item.series\">\n                        <ng-template #tooltipTemplate>\n                            <ng-container \n                                [ngTemplateOutlet]=\"seriesTooltipTemplate\"\n                                [ngTemplateOutletContext]=\"{\n                                    serie: serie,\n                                    item: item\n                                }\">\n                            </ng-container>\n                        </ng-template>\n\n                        <div class=\"serie\" \n                            [placement]=\"tooltipPlacement\"\n                            [tooltip]=\"seriesTooltipTemplate ? tooltipTemplate : null\"\n                            container=\"body\"\n                            (click)=\"onSerieSelected(item, serie)\"\n                            [ngClass]=\"{\n                                'highlighted': showingMouseIndicator && mouseIndicatorCoordinateX >= serie.left && mouseIndicatorCoordinateX <= (serie.left + serie.width)\n                            }\"\n                            [ngStyle]=\"{\n                                'backgroundColor': serie.color,\n                                'left.px': serie.left,\n                                'width.px': serie.width\n                            }\">\n                            <span class=\"text-truncate\">{{serie.label || serie.daysDiff}}</span>\n                            <div class=\"left-border\"></div>\n                            <div class=\"top-border\"></div>\n                            <div class=\"right-border\"></div>\n                            <div class=\"bottom-border\"></div>\n                        </div>\n                    </div>\n                </div>\n                <div class=\"mouse-indicator\" *ngIf=\"showingMouseIndicator\" [ngStyle]=\"{'left.px': mouseIndicatorCoordinateX}\"></div>\n                <div class=\"mouse-indicator today\" *ngIf=\"showTodayIndicator\" [ngStyle]=\"{'left.px': todayIndicatorCoordinateX}\"></div>\n            </div>\n            <div class=\"footer\" *ngIf=\"showFooter\">\n                <div class=\"months\">\n                    <div class=\"month\" *ngFor=\"let item of months\">{{item | uppercase}}</div>\n                </div>\n                <div class=\"year\">{{currentYear}}</div>\n                <div class=\"date-indicator\" *ngIf=\"showingMouseIndicator\" [ngStyle]=\"{\n                    'left.px': mouseIndicatorCoordinateX - (mouseMovingLastMonth ? 150 : 75)\n                }\">\n                    <i class=\"fa fa-calendar\"></i> {{dateIndicator | date}}\n                </div>\n            </div>\n        </div>\n    </div>\n\n    <p *ngIf=\"!internalData || internalData.length == 0\">{{emptyMessage}}</p>\n</div>\n", styles: ["@keyframes pulse{0%{opacity:.7}50%{opacity:1}to{opacity:.7}}.ui-gantt-chart{width:100%;border:1px solid #eeeeee}.ui-gantt-chart .gantt-container{display:flex;overflow-y:auto}.ui-gantt-chart .gantt-container .gantt-labels .header,.ui-gantt-chart .gantt-container .gantt-labels .footer,.ui-gantt-chart .gantt-container .gantt-timeline .header,.ui-gantt-chart .gantt-container .gantt-timeline .footer{display:flex;height:70px;box-shadow:0 .125rem .25rem #00000013}.ui-gantt-chart .gantt-container .gantt-labels .footer,.ui-gantt-chart .gantt-container .gantt-timeline .footer{box-shadow:0 -.125rem .25rem #00000013}.ui-gantt-chart .gantt-container .gantt-labels{width:300px;flex-shrink:0;position:relative}.ui-gantt-chart .gantt-container .gantt-labels .header,.ui-gantt-chart .gantt-container .gantt-labels .footer{justify-content:space-between;align-items:center;border-right:2px solid #eeeeee;padding:0 20px;background-color:#fff;position:sticky;top:0;z-index:10}.ui-gantt-chart .gantt-container .gantt-labels .header .title,.ui-gantt-chart .gantt-container .gantt-labels .footer .title{color:#717274;font-weight:600;font-size:18px}.ui-gantt-chart .gantt-container .gantt-labels .header .legends,.ui-gantt-chart .gantt-container .gantt-labels .footer .legends{text-align:right}.ui-gantt-chart .gantt-container .gantt-labels .header .legends span,.ui-gantt-chart .gantt-container .gantt-labels .footer .legends span{color:#717274;display:block;font-size:13px;font-weight:700;padding:4px 0;text-transform:capitalize}.ui-gantt-chart .gantt-container .gantt-labels .footer{top:inherit;bottom:0}.ui-gantt-chart .gantt-container .gantt-labels .labels .label{display:flex;align-items:center;font-weight:600;line-height:1.2;background-color:#f1f5f8;border-bottom:1px solid #dfe8ef;border-right:2px solid #dfe8ef;padding:0 20px;height:50px}.ui-gantt-chart .gantt-container .gantt-timeline{flex-grow:1;position:relative}.ui-gantt-chart .gantt-container .gantt-timeline .header,.ui-gantt-chart .gantt-container .gantt-timeline .footer{display:flex;flex-direction:column;justify-content:center;min-width:700px;background-color:#fff;position:sticky;top:0;z-index:10}.ui-gantt-chart .gantt-container .gantt-timeline .header .year,.ui-gantt-chart .gantt-container .gantt-timeline .footer .year{text-align:center;color:#717274;font-size:13px;font-weight:700;padding:4px 0}.ui-gantt-chart .gantt-container .gantt-timeline .header .months,.ui-gantt-chart .gantt-container .gantt-timeline .footer .months{display:flex;padding:4px 0}.ui-gantt-chart .gantt-container .gantt-timeline .header .months .month,.ui-gantt-chart .gantt-container .gantt-timeline .footer .months .month{color:#717274;text-align:center;flex-grow:1;font-size:13px;font-weight:600}.ui-gantt-chart .gantt-container .gantt-timeline .header .date-indicator,.ui-gantt-chart .gantt-container .gantt-timeline .footer .date-indicator{position:absolute;bottom:8px;background-color:#327ace;color:#fff;padding:3px 10px;border-radius:10px;border:1px solid #00559A;font-size:13px;width:150px;text-align:center;transition:left .2s ease-out}.ui-gantt-chart .gantt-container .gantt-timeline .footer{top:inherit;bottom:0}.ui-gantt-chart .gantt-container .gantt-timeline .footer .date-indicator{bottom:35px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline{position:relative;min-width:700px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item{display:flex;position:relative;transition:background-color .2s ease-in-out}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .box{flex-grow:1;transition:background-color .2s ease-in-out;border-bottom:1px solid #eeeeee;border-right:2px solid #eeeeee;height:50px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .box:last-child{border-right:0}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .box:hover{background-color:#f0f0f0}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie{cursor:pointer;position:absolute;display:flex;align-items:center;color:#fff;font-size:13px;font-weight:600;top:5px;bottom:6px;padding:0 5px;transition:opacity .3s ease-in-out,width .8s ease-out;z-index:9}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie:hover{opacity:.8}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .left-border,.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .top-border,.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .right-border,.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .bottom-border{position:absolute;background-color:#333;opacity:.5;z-index:11}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .left-border{top:2px;left:0;bottom:2px;width:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .top-border{top:0;right:0;left:0;height:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .right-border{top:2px;right:0;bottom:2px;width:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie .bottom-border{bottom:0;right:0;left:0;height:2px}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item .serie.highlighted{animation:pulse 1s infinite ease-in-out}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .item:hover{background-color:#f9f9f9}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator{position:absolute;top:0;bottom:0;width:0;border-right:1px dashed #327ACE;z-index:8;-webkit-user-select:none;user-select:none;outline:none}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator.today{border-right:1px dashed #327ACE;z-index:10}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator.today:before{content:\"\";position:absolute;top:0;left:-4.5px;width:0;height:0;z-index:8;border-top:5px solid #327ACE;border-right:5px solid transparent;border-left:5px solid transparent}.ui-gantt-chart .gantt-container .gantt-timeline .timeline .mouse-indicator.today:after{content:\"\";position:absolute;bottom:0;left:-4.5px;width:0;height:0;z-index:8;border-bottom:5px solid #327ACE;border-right:5px solid transparent;border-left:5px solid transparent}\n"] }]
        }], ctorParameters: function () { return [{ type: undefined, decorators: [{
                    type: Inject,
                    args: [CHARTS_CONFIG]
                }, {
                    type: Optional
                }] }]; }, propDecorators: { externalData: [{
                type: Input,
                args: ['data']
            }], caption: [{
                type: Input
            }], tooltipPlacement: [{
                type: Input
            }], maxHeight: [{
                type: Input
            }], showFooter: [{
                type: Input
            }], showTodayIndicator: [{
                type: Input
            }], currentYear: [{
                type: Input
            }], onSelect: [{
                type: Output
            }], seriesTooltipTemplate: [{
                type: ContentChild,
                args: [GanttSeriesTooltipTemplateDirective, { read: TemplateRef, static: true }]
            }] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FudHQtY2hhcnQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXVpLWhlcm8vc3JjL2xpYi9jaGFydHMvY29tcG9uZW50cy9nYW50dC1jaGFydC9nYW50dC1jaGFydC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtdWktaGVyby9zcmMvbGliL2NoYXJ0cy9jb21wb25lbnRzL2dhbnR0LWNoYXJ0L2dhbnR0LWNoYXJ0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxjQUFjLE1BQU0sUUFBUSxDQUFDO0FBRXpDLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFVLFFBQVEsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRzVILE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUNwRSxPQUFPLEVBQUUsbUNBQW1DLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQzs7OztBQUlqRyxNQUFNLE1BQU0sR0FBRyxjQUFjLENBQUM7QUFFOUIsSUFBSSxVQUFVLEdBQUcsQ0FBQyxDQUFDO0FBVW5CLE1BQU0sT0FBTyxtQkFBbUI7SUEwQzlCLFlBQ3FDLE1BQW9CO1FBeENoRCxxQkFBZ0IsR0FBVyxNQUFNLENBQUM7UUFDbEMsY0FBUyxHQUFXLENBQUMsQ0FBQztRQUN0QixlQUFVLEdBQVksS0FBSyxDQUFDO1FBQzVCLHVCQUFrQixHQUFZLElBQUksQ0FBQztRQUVsQyxhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUd0QyxlQUFVLEdBQUcsZUFBZSxVQUFVLEVBQUUsRUFBRSxDQUFDO1FBRWxELFdBQU0sR0FBWSxPQUFPLENBQUM7UUFDMUIsaUJBQVksR0FBWSxrQ0FBa0MsQ0FBQztRQU8z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QUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsZUFBZSxHQUFHLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxDQUFDO2FBQzNFO1NBQ0Y7SUFDSCxDQUFDOztpSEE3TFUsbUJBQW1CLGtCQTJDcEIsYUFBYTtxR0EzQ1osbUJBQW1CLHVhQVNoQixtQ0FBbUMsMkJBQVMsV0FBVywyQ0MvQnZFLCt2SkEwRkE7NEZEcEVhLG1CQUFtQjtrQkFSL0IsU0FBUzsrQkFDRSxhQUFhLFFBR2pCO3dCQUNKLGlCQUFpQixFQUFFLFlBQVk7cUJBQ2hDOzswQkE2Q0UsTUFBTTsyQkFBQyxhQUFhOzswQkFBRyxRQUFROzRDQTFDbkIsWUFBWTtzQkFBMUIsS0FBSzt1QkFBQyxNQUFNO2dCQUNKLE9BQU87c0JBQWYsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNJLFFBQVE7c0JBQWpCLE1BQU07Z0JBQytFLHFCQUFxQjtzQkFBMUcsWUFBWTt1QkFBQyxtQ0FBbUMsRUFBRSxFQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIG1vbWVudEltcG9ydGVkIGZyb20gJ21vbWVudCc7XG5cbmltcG9ydCB7IENvbXBvbmVudCwgQ29udGVudENoaWxkLCBFdmVudEVtaXR0ZXIsIEluamVjdCwgSW5wdXQsIE9uSW5pdCwgT3B0aW9uYWwsIE91dHB1dCwgVGVtcGxhdGVSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgQ2hhcnRzQ29uZmlnIH0gZnJvbSAnLi4vLi4vY29uZmlnL2NoYXJ0cy1jb25maWcnO1xuaW1wb3J0IHsgQ0hBUlRTX0NPTkZJRyB9IGZyb20gJy4uLy4uL2NvbmZpZy9jaGFydHMtY29uZmlnLmNvbnRhbnRzJztcbmltcG9ydCB7IEdhbnR0U2VyaWVzVG9vbHRpcFRlbXBsYXRlRGlyZWN0aXZlIH0gZnJvbSAnLi4vLi4vZGlyZWN0aXZlcy9nYW50dC10ZW1wbGF0ZXMuZGlyZWN0aXZlJztcbmltcG9ydCB7IEdhbnR0SW50ZXJuYWxJdGVtTW9kZWwsIEdhbnR0SW50ZXJuYWxTZXJpZU1vZGVsLCBHYW50dEl0ZW1Nb2RlbCwgR2FudHRTZXJpZU1vZGVsIH0gZnJvbSAnLi9tb2RlbHMvZ2FudHQtaXRlbS5tb2RlbCc7XG5cbmRlY2xhcmUgdmFyICQ6IGFueTtcbmNvbnN0IG1vbWVudCA9IG1vbWVudEltcG9ydGVkO1xuXG5sZXQgaWRlbnRpZmllciA9IDA7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2dhbnR0LWNoYXJ0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2dhbnR0LWNoYXJ0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZ2FudHQtY2hhcnQuY29tcG9uZW50LnNjc3MnXSxcbiAgaG9zdDoge1xuICAgICcod2luZG93OnJlc2l6ZSknOiAnb25SZXNpemUoKSdcbiAgfVxufSlcbmV4cG9ydCBjbGFzcyBHYW50dENoYXJ0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KCdkYXRhJykgZXh0ZXJuYWxEYXRhOiBBcnJheTxHYW50dEl0ZW1Nb2RlbD47XG4gIEBJbnB1dCgpIGNhcHRpb246IHN0cmluZztcbiAgQElucHV0KCkgdG9vbHRpcFBsYWNlbWVudDogc3RyaW5nID0gJ2xlZnQnO1xuICBASW5wdXQoKSBtYXhIZWlnaHQ6IG51bWJlciA9IDA7XG4gIEBJbnB1dCgpIHNob3dGb290ZXI6IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgc2hvd1RvZGF5SW5kaWNhdG9yOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgY3VycmVudFllYXI6IG51bWJlcjtcbiAgQE91dHB1dCgpIG9uU2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBDb250ZW50Q2hpbGQoR2FudHRTZXJpZXNUb29sdGlwVGVtcGxhdGVEaXJlY3RpdmUsIHtyZWFkOiBUZW1wbGF0ZVJlZiwgc3RhdGljOiB0cnVlfSkgc2VyaWVzVG9vbHRpcFRlbXBsYXRlOiBHYW50dFNlcmllc1Rvb2x0aXBUZW1wbGF0ZURpcmVjdGl2ZTtcblxuICBwdWJsaWMgaWRlbnRpZmllciA9IGBnYW50dC1jaGFydC0ke2lkZW50aWZpZXIrK31gOyAgXG4gIFxuICBsb2NhbGU/OiBzdHJpbmcgPSAnZW4tdXMnO1xuICBlbXB0eU1lc3NhZ2U/OiBzdHJpbmcgPSAnTm8gcmVzdWx0cyBmb3VuZCBhdCB0aGlzIG1vbWVudC4nO1xuICBpbnRlcm5hbERhdGE6IEFycmF5PEdhbnR0SW50ZXJuYWxJdGVtTW9kZWw+O1xuICBtb250aHM6IEFycmF5PHN0cmluZz47XG4gIGRheUxhYmVsOiBzdHJpbmc7XG4gIG1vbnRoTGFiZWw6IHN0cmluZztcbiAgeWVhckxhYmVsOiBzdHJpbmc7ICBcbiAgY3VycmVudE1vbnRoOiBudW1iZXI7XG4gIHNob3dpbmdNb3VzZUluZGljYXRvcjogYm9vbGVhbiA9IGZhbHNlO1xuICBtb3VzZU1vdmluZ0xhc3RNb250aDogYm9vbGVhbiA9IGZhbHNlO1xuICBtb3VzZUluZGljYXRvckNvb3JkaW5hdGVYOiBudW1iZXI7XG4gIHRvZGF5SW5kaWNhdG9yQ29vcmRpbmF0ZVg6IG51bWJlcjtcbiAgZGF0ZUluZGljYXRvcjogRGF0ZTtcbiAgY29sb3JzOiBBcnJheTxzdHJpbmc+ID0gW1xuICAgICcjODI3MGZhJywgXG4gICAgJyM0ZDViNjYnLCBcbiAgICAnIzRmZDFhMScsIFxuICAgICcjZmUzY2FlJywgXG4gICAgJyNmZmNhMjInLCBcbiAgICAnI2ZmOWY0MScsIFxuICAgICcjNWFhYWZmJywgXG4gICAgJyM0OThhY2InLCBcbiAgICAnIzI3Y2ZjMicsIFxuICAgICcjZmY2OTgyJywgXG4gICAgJyNmNDQzMzYnLCBcbiAgICAnI2NkZGMzOScsIFxuICAgICcjNjA3ZDhiJywgXG4gICAgJyM3OTU1NDgnXTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KENIQVJUU19DT05GSUcpIEBPcHRpb25hbCgpIGNvbmZpZzogQ2hhcnRzQ29uZmlnLFxuICApIHtcbiAgICBPYmplY3QuYXNzaWduKHRoaXMsIGNvbmZpZyk7XG4gIH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLmluaXREYXRhKCk7XG4gICAgdGhpcy5pbml0TW9udGhzKCk7XG4gICAgdGhpcy5pbml0VGltZWxpbmVTaXplcygpO1xuICAgIHRoaXMuaW5pdFRvZGF5SW5kaWNhdG9yKCk7XG4gIH1cblxuICBvblJlc2l6ZSgpe1xuICAgIHRoaXMuaGFuZGxlVGltZWxpbmVTaXplcygpO1xuICAgIHRoaXMuaW5pdFRvZGF5SW5kaWNhdG9yKCk7XG4gIH1cbiAgb25TZXJpZVNlbGVjdGVkKGl0ZW06IEdhbnR0SW50ZXJuYWxJdGVtTW9kZWwsIHNlcmllOiBHYW50dEludGVybmFsU2VyaWVNb2RlbCk6IHZvaWQge1xuICAgIHRoaXMub25TZWxlY3QuZW1pdCh7XG4gICAgICBpdGVtLFxuICAgICAgc2VyaWVcbiAgICB9KTtcbiAgfVxuICBvblRpbWVsaW5lTW91c2VNb3ZlKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNob3dpbmdNb3VzZUluZGljYXRvcikgcmV0dXJuO1xuXG4gICAgbGV0IG9mZnNldCA9ICQoYCMke3RoaXMuaWRlbnRpZmllcn0gLmdhbnR0LXRpbWVsaW5lIC50aW1lbGluZWApLm9mZnNldCgpO1xuICAgIHRoaXMubW91c2VJbmRpY2F0b3JDb29yZGluYXRlWCA9IGV2ZW50LnBhZ2VYIC0gb2Zmc2V0LmxlZnQ7XG5cbiAgICBsZXQgbW9udGhXaWR0aDogbnVtYmVyID0gJChgIyR7dGhpcy5pZGVudGlmaWVyfSAuZ2FudHQtdGltZWxpbmUgLnRpbWVsaW5lIC5pdGVtOmZpcnN0LWNoaWxkYCkuY2hpbGRyZW4oJy5ib3g6Zmlyc3QtY2hpbGQnKS53aWR0aCgpO1xuICAgIGxldCBtb250aEluZGV4QmVpbmdIb3ZlcmVkOiBudW1iZXIgPSBNYXRoLmZsb29yKHRoaXMubW91c2VJbmRpY2F0b3JDb29yZGluYXRlWCAvIChtb250aFdpZHRoICsgMikpO1xuXG4gICAgbGV0IGRhdGUgPSBuZXcgRGF0ZSh0aGlzLmN1cnJlbnRZZWFyLCBtb250aEluZGV4QmVpbmdIb3ZlcmVkLCAxKTtcbiAgICBsZXQgZGF5c0luTW9udGg6IG51bWJlciA9IG1vbWVudChkYXRlKS5kYXlzSW5Nb250aCgpO1xuICAgIGxldCBkYXlXaWR0aDogbnVtYmVyID0gbW9udGhXaWR0aCAvIGRheXNJbk1vbnRoO1xuICAgIGxldCBkYXlCZWlnbkhvdmVyZWQ6IG51bWJlciA9IE1hdGguZmxvb3IoKHRoaXMubW91c2VJbmRpY2F0b3JDb29yZGluYXRlWCAtICgobW9udGhXaWR0aCArIDIpICogbW9udGhJbmRleEJlaW5nSG92ZXJlZCkpIC8gZGF5V2lkdGgpICsgMTtcblxuICAgIGlmIChkYXlCZWlnbkhvdmVyZWQgPD0gMCB8fCBkYXlCZWlnbkhvdmVyZWQgPiBkYXlzSW5Nb250aCkgcmV0dXJuO1xuICAgIFxuICAgIHRoaXMuZGF0ZUluZGljYXRvciA9IG5ldyBEYXRlKHRoaXMuY3VycmVudFllYXIsIG1vbnRoSW5kZXhCZWluZ0hvdmVyZWQsIGRheUJlaWduSG92ZXJlZCk7XG4gICAgdGhpcy5tb3VzZU1vdmluZ0xhc3RNb250aCA9IG1vbnRoSW5kZXhCZWluZ0hvdmVyZWQgPT0gMTE7XG4gIH1cbiAgb25UaW1lbGluZU1vdXNlRW50ZXIoKTogdm9pZCB7XG4gICAgdGhpcy5zaG93aW5nTW91c2VJbmRpY2F0b3IgPSB0cnVlO1xuICB9XG4gIG9uVGltZWxpbmVNb3VzZUxlYXZlKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd2luZ01vdXNlSW5kaWNhdG9yID0gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGluaXREYXRhKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5leHRlcm5hbERhdGEgfHwgdGhpcy5leHRlcm5hbERhdGEubGVuZ3RoID09IDApIHJldHVybjtcbiAgICB0aGlzLmludGVybmFsRGF0YSA9IG5ldyBBcnJheTxHYW50dEludGVybmFsSXRlbU1vZGVsPigpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLmV4dGVybmFsRGF0YS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGNvbG9ySW5kZXggPSBNYXRoLnJvdW5kKE1hdGgucmFuZG9tKCkgKiAodGhpcy5jb2xvcnMubGVuZ3RoIC0gMSkpO1xuXG4gICAgICB0aGlzLmludGVybmFsRGF0YS5wdXNoKHtcbiAgICAgICAgbGFiZWw6IHRoaXMuZXh0ZXJuYWxEYXRhW2ldLmxhYmVsLFxuICAgICAgICBzZXJpZXM6IHRoaXMuZXh0ZXJuYWxEYXRhW2ldLnNlcmllcy5tYXAocyA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGNvbG9yOiBzLmNvbG9yIHx8IHRoaXMuY29sb3JzW2NvbG9ySW5kZXhdLFxuICAgICAgICAgICAgc3RhcnREYXRlOiBzLnN0YXJ0RGF0ZSxcbiAgICAgICAgICAgIGVuZERhdGU6IHMuZW5kRGF0ZSxcbiAgICAgICAgICAgIGRhdGE6IHMuZGF0YSxcbiAgICAgICAgICAgIGxlZnQ6IDAsXG4gICAgICAgICAgICB3aWR0aDogMCxcbiAgICAgICAgICAgIGRheXNEaWZmOiB0aGlzLmRheXNEaWZmRnJvbVNlcmllKHMpLFxuICAgICAgICAgICAgbGFiZWw6IHMubGFiZWxcbiAgICAgICAgICB9O1xuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHByaXZhdGUgZGF5c0RpZmZGcm9tU2VyaWUoc2VyaWU6IEdhbnR0U2VyaWVNb2RlbCk6IG51bWJlciB7XG4gICAgdmFyIHN0YXJ0ID0gbW9tZW50KHNlcmllLnN0YXJ0RGF0ZSk7XG4gICAgdmFyIGVuZCA9IG1vbWVudChzZXJpZS5lbmREYXRlKTtcblxuICAgIHJldHVybiBlbmQuZGlmZihzdGFydCwgJ2RheXMnKSArIDE7XG4gIH1cbiAgcHJpdmF0ZSBtb250aHNEaWZmRnJvbVNlcmllKHNlcmllOiBHYW50dFNlcmllTW9kZWwpOiBudW1iZXIge1xuICAgIHZhciBzdGFydCA9IG1vbWVudChzZXJpZS5zdGFydERhdGUpO1xuICAgIHZhciBlbmQgPSBtb21lbnQoc2VyaWUuZW5kRGF0ZSk7XG5cbiAgICByZXR1cm4gZW5kLmRpZmYoc3RhcnQsICdtb250aHMnKTtcbiAgfVxuICBwcml2YXRlIGluaXRNb250aHMoKTogdm9pZCB7XG4gICAgbW9tZW50LmxvY2FsZSh0aGlzLmxvY2FsZSk7XG5cbiAgICBsZXQgdG9kYXkgPSBuZXcgRGF0ZSgpO1xuXG4gICAgaWYgKCF0aGlzLmN1cnJlbnRZZWFyKSB7XG4gICAgICB0aGlzLmN1cnJlbnRZZWFyID0gdG9kYXkuZ2V0RnVsbFllYXIoKTtcbiAgICB9XG5cbiAgICBsZXQgcmVmZXJlbmNlRGF0ZSA9IG5ldyBEYXRlKHRoaXMuY3VycmVudFllYXIsIHRvZGF5LmdldE1vbnRoKCksIHRvZGF5LmdldERheSgpKTtcbiAgICBcbiAgICB0aGlzLmRheUxhYmVsID0gbW9tZW50LmxvY2FsZURhdGEoKS5yZWxhdGl2ZVRpbWUoMSwgZmFsc2UsICdkJywgZmFsc2UpLnNwbGl0KCcgJylbMV07XG4gICAgdGhpcy5tb250aExhYmVsID0gbW9tZW50LmxvY2FsZURhdGEoKS5yZWxhdGl2ZVRpbWUoMSwgZmFsc2UsICdNJywgZmFsc2UpLnNwbGl0KCcgJylbMV07XG4gICAgdGhpcy55ZWFyTGFiZWwgPSBtb21lbnQubG9jYWxlRGF0YSgpLnJlbGF0aXZlVGltZSgxLCBmYWxzZSwgJ3knLCBmYWxzZSkuc3BsaXQoJyAnKVsxXTsgICAgXG4gICAgdGhpcy5jdXJyZW50TW9udGggPSByZWZlcmVuY2VEYXRlLmdldE1vbnRoKCk7XG5cbiAgICB0aGlzLm1vbnRocyA9IG1vbWVudC5tb250aHNTaG9ydCgnLU1NTS0nKTtcbiAgfVxuICBwcml2YXRlIGluaXRUaW1lbGluZVNpemVzKCk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5oYW5kbGVUaW1lbGluZVNpemVzKCk7XG4gICAgfSwgMCk7XG4gIH1cbiAgcHJpdmF0ZSBpbml0VG9kYXlJbmRpY2F0b3IoKTogdm9pZCB7XG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBsZXQgbW9udGhXaWR0aDogbnVtYmVyID0gJChgIyR7dGhpcy5pZGVudGlmaWVyfSAuZ2FudHQtdGltZWxpbmUgLnRpbWVsaW5lIC5pdGVtOmZpcnN0LWNoaWxkYCkuY2hpbGRyZW4oJy5ib3g6Zmlyc3QtY2hpbGQnKS53aWR0aCgpO1xuICAgICAgbGV0IHJlZmVyZW5jZURhdGUgPSBuZXcgRGF0ZSgpO1xuICAgICAgbGV0IGRheSA9IHJlZmVyZW5jZURhdGUuZ2V0RGF0ZSgpO1xuICAgICAgbGV0IG1vbnRoID0gcmVmZXJlbmNlRGF0ZS5nZXRNb250aCgpICsgMTtcbiAgICAgIGxldCBmaXJzdERheVdpZHRoOiBudW1iZXIgPSBtb250aFdpZHRoIC8gbW9tZW50KHJlZmVyZW5jZURhdGUpLmRheXNJbk1vbnRoKCk7XG4gICAgICB0aGlzLnRvZGF5SW5kaWNhdG9yQ29vcmRpbmF0ZVggPSAoKG1vbnRoIC0gMSkgKiBtb250aFdpZHRoKSArICgoZGF5IC0gMSkgKiBmaXJzdERheVdpZHRoKSArICgobW9udGggLSAxKSAqIDIpO1xuICAgIH0sIDApO1xuICB9XG4gIHByaXZhdGUgaGFuZGxlVGltZWxpbmVTaXplcygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaW50ZXJuYWxEYXRhIHx8IHRoaXMuaW50ZXJuYWxEYXRhLmxlbmd0aCA9PSAwKSByZXR1cm47XG4gICAgXG4gICAgbGV0IG1vbnRoV2lkdGg6IG51bWJlciA9ICQoYCMke3RoaXMuaWRlbnRpZmllcn0gLmdhbnR0LXRpbWVsaW5lIC50aW1lbGluZSAuaXRlbTpmaXJzdC1jaGlsZGApLmNoaWxkcmVuKCcuYm94OmZpcnN0LWNoaWxkJykud2lkdGgoKTtcbiAgICBcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaW50ZXJuYWxEYXRhLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoIXRoaXMuaW50ZXJuYWxEYXRhW2ldLnNlcmllcyB8fCB0aGlzLmludGVybmFsRGF0YVtpXS5zZXJpZXMubGVuZ3RoID09IDApIGNvbnRpbnVlO1xuXG4gICAgICBmb3IgKGxldCBzID0gMDsgcyA8IHRoaXMuaW50ZXJuYWxEYXRhW2ldLnNlcmllcy5sZW5ndGg7IHMrKykge1xuICAgICAgICBsZXQgc2VyaWVUb3RhbFdpZHRoID0gMDtcbiAgICAgICAgbGV0IGRheSA9IHRoaXMuaW50ZXJuYWxEYXRhW2ldLnNlcmllc1tzXS5zdGFydERhdGUuZ2V0RGF0ZSgpO1xuICAgICAgICBsZXQgbW9udGggPSB0aGlzLmludGVybmFsRGF0YVtpXS5zZXJpZXNbc10uc3RhcnREYXRlLmdldE1vbnRoKCkgKyAxO1xuICAgICAgICBsZXQgZGF5c0RpZmYgPSB0aGlzLmludGVybmFsRGF0YVtpXS5zZXJpZXNbc10uZGF5c0RpZmY7XG4gICAgICAgIGxldCBzdGFydERhdGUgPSB0aGlzLmludGVybmFsRGF0YVtpXS5zZXJpZXNbc10uc3RhcnREYXRlO1xuICAgICAgICBsZXQgZmlyc3REYXlXaWR0aDogbnVtYmVyID0gbW9udGhXaWR0aCAvIG1vbWVudChzdGFydERhdGUpLmRheXNJbk1vbnRoKCk7XG4gICAgICAgIGxldCBtb250aHNEaWZmID0gdGhpcy5tb250aHNEaWZmRnJvbVNlcmllKHRoaXMuaW50ZXJuYWxEYXRhW2ldLnNlcmllc1tzXSk7XG5cbiAgICAgICAgZm9yIChsZXQgZCA9IDA7IGQgPCBkYXlzRGlmZjsgZCsrKSB7XG4gICAgICAgICAgbGV0IGRhdGUgPSBtb21lbnQoc3RhcnREYXRlKS5hZGQoe2RheXM6IGR9KS50b0RhdGUoKTtcbiAgICAgICAgICBsZXQgZGF5c0luTW9udGggPSBtb21lbnQoZGF0ZSkuZGF5c0luTW9udGgoKTtcbiAgICAgICAgICBsZXQgZGF5V2lkdGg6IG51bWJlciA9IG1vbnRoV2lkdGggLyBkYXlzSW5Nb250aDtcblxuICAgICAgICAgIHNlcmllVG90YWxXaWR0aCArPSBkYXlXaWR0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuaW50ZXJuYWxEYXRhW2ldLnNlcmllc1tzXS5sZWZ0ID0gKChtb250aCAtIDEpICogbW9udGhXaWR0aCkgKyAoKGRheSAtIDEpICogZmlyc3REYXlXaWR0aCkgKyAoKG1vbnRoIC0gMSkgKiAyKTtcbiAgICAgICAgdGhpcy5pbnRlcm5hbERhdGFbaV0uc2VyaWVzW3NdLndpZHRoID0gc2VyaWVUb3RhbFdpZHRoICsgKG1vbnRoc0RpZmYgKiAyKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxufVxuIiwiPGRpdiBpZD1cInt7aWRlbnRpZmllcn19XCIgY2xhc3M9XCJ1aS1nYW50dC1jaGFydFwiPlxuICAgIDxkaXYgY2xhc3M9XCJnYW50dC1jb250YWluZXJcIiAqbmdJZj1cImludGVybmFsRGF0YT8ubGVuZ3RoID4gMFwiIFtuZ1N0eWxlXT1cInsnbWF4SGVpZ2h0LnB4JzogbWF4SGVpZ2h0ID4gMCA/IG1heEhlaWdodCA6ICdhdXRvJ31cIj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdhbnR0LWxhYmVsc1wiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlclwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aXRsZVwiPnt7Y2FwdGlvbn19PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxlZ2VuZHNcIj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ5ZWFyXCI+e3t5ZWFyTGFiZWx9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJtb250aFwiPnt7bW9udGhMYWJlbH19PC9zcGFuPlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGFiZWxzXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxhYmVsXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgaW50ZXJuYWxEYXRhXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7aXRlbS5sYWJlbH19XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmb290ZXJcIiAqbmdJZj1cInNob3dGb290ZXJcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGVcIj57e2NhcHRpb259fTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsZWdlbmRzXCI+XG4gICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibW9udGhcIj57e21vbnRoTGFiZWx9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ5ZWFyXCI+e3t5ZWFyTGFiZWx9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImdhbnR0LXRpbWVsaW5lXCI+XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyXCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInllYXJcIj57e2N1cnJlbnRZZWFyfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibW9udGhzXCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtb250aFwiICpuZ0Zvcj1cImxldCBpdGVtIG9mIG1vbnRoc1wiPnt7aXRlbSB8IHVwcGVyY2FzZX19PC9kaXY+XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRhdGUtaW5kaWNhdG9yXCIgKm5nSWY9XCJzaG93aW5nTW91c2VJbmRpY2F0b3JcIiBbbmdTdHlsZV09XCJ7XG4gICAgICAgICAgICAgICAgICAgICdsZWZ0LnB4JzogbW91c2VJbmRpY2F0b3JDb29yZGluYXRlWCAtIChtb3VzZU1vdmluZ0xhc3RNb250aCA/IDE1MCA6IDc1KVxuICAgICAgICAgICAgICAgIH1cIj5cbiAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1jYWxlbmRhclwiPjwvaT4ge3tkYXRlSW5kaWNhdG9yIHwgZGF0ZX19XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0aW1lbGluZVwiIChtb3VzZWVudGVyKT1cIm9uVGltZWxpbmVNb3VzZUVudGVyKClcIiAobW91c2VsZWF2ZSk9XCJvblRpbWVsaW5lTW91c2VMZWF2ZSgpXCIgKG1vdXNlbW92ZSk9XCJvblRpbWVsaW5lTW91c2VNb3ZlKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaXRlbVwiICpuZ0Zvcj1cImxldCBpdGVtIG9mIGludGVybmFsRGF0YVwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYm94XCIgKm5nRm9yPVwibGV0IG1vbnRoIG9mIG1vbnRoc1wiPjwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZXJpZS1jb250YWluZXJcIiAgKm5nRm9yPVwibGV0IHNlcmllIG9mIGl0ZW0uc2VyaWVzXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI3Rvb2x0aXBUZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJzZXJpZXNUb29sdGlwVGVtcGxhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VyaWU6IHNlcmllLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXRlbTogaXRlbVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VyaWVcIiBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcGxhY2VtZW50XT1cInRvb2x0aXBQbGFjZW1lbnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0b29sdGlwXT1cInNlcmllc1Rvb2x0aXBUZW1wbGF0ZSA/IHRvb2x0aXBUZW1wbGF0ZSA6IG51bGxcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lcj1cImJvZHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvblNlcmllU2VsZWN0ZWQoaXRlbSwgc2VyaWUpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdoaWdobGlnaHRlZCc6IHNob3dpbmdNb3VzZUluZGljYXRvciAmJiBtb3VzZUluZGljYXRvckNvb3JkaW5hdGVYID49IHNlcmllLmxlZnQgJiYgbW91c2VJbmRpY2F0b3JDb29yZGluYXRlWCA8PSAoc2VyaWUubGVmdCArIHNlcmllLndpZHRoKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2JhY2tncm91bmRDb2xvcic6IHNlcmllLmNvbG9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbGVmdC5weCc6IHNlcmllLmxlZnQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICd3aWR0aC5weCc6IHNlcmllLndpZHRoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC10cnVuY2F0ZVwiPnt7c2VyaWUubGFiZWwgfHwgc2VyaWUuZGF5c0RpZmZ9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGVmdC1ib3JkZXJcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwidG9wLWJvcmRlclwiPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyaWdodC1ib3JkZXJcIj48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYm90dG9tLWJvcmRlclwiPjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtb3VzZS1pbmRpY2F0b3JcIiAqbmdJZj1cInNob3dpbmdNb3VzZUluZGljYXRvclwiIFtuZ1N0eWxlXT1cInsnbGVmdC5weCc6IG1vdXNlSW5kaWNhdG9yQ29vcmRpbmF0ZVh9XCI+PC9kaXY+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1vdXNlLWluZGljYXRvciB0b2RheVwiICpuZ0lmPVwic2hvd1RvZGF5SW5kaWNhdG9yXCIgW25nU3R5bGVdPVwieydsZWZ0LnB4JzogdG9kYXlJbmRpY2F0b3JDb29yZGluYXRlWH1cIj48L2Rpdj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZvb3RlclwiICpuZ0lmPVwic2hvd0Zvb3RlclwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtb250aHNcIj5cbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1vbnRoXCIgKm5nRm9yPVwibGV0IGl0ZW0gb2YgbW9udGhzXCI+e3tpdGVtIHwgdXBwZXJjYXNlfX08L2Rpdj5cbiAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwieWVhclwiPnt7Y3VycmVudFllYXJ9fTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkYXRlLWluZGljYXRvclwiICpuZ0lmPVwic2hvd2luZ01vdXNlSW5kaWNhdG9yXCIgW25nU3R5bGVdPVwie1xuICAgICAgICAgICAgICAgICAgICAnbGVmdC5weCc6IG1vdXNlSW5kaWNhdG9yQ29vcmRpbmF0ZVggLSAobW91c2VNb3ZpbmdMYXN0TW9udGggPyAxNTAgOiA3NSlcbiAgICAgICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtY2FsZW5kYXJcIj48L2k+IHt7ZGF0ZUluZGljYXRvciB8IGRhdGV9fVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuXG4gICAgPHAgKm5nSWY9XCIhaW50ZXJuYWxEYXRhIHx8IGludGVybmFsRGF0YS5sZW5ndGggPT0gMFwiPnt7ZW1wdHlNZXNzYWdlfX08L3A+XG48L2Rpdj5cbiJdfQ==