nr-grid
Version:
NR-Grid is basic a datagrid helper that uses Bootstrap and NgbBootstrap and developed for Angular applications.
425 lines • 56.8 kB
JavaScript
import { __decorate } from "tslib";
import { ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
import * as _ from 'lodash';
import { Subject } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
import { NgbDate, NgbModal } from '@ng-bootstrap/ng-bootstrap';
import { NRGridColumnType } from './model/column/nr-grid-column-type';
import { FilterType } from './model/filter/filter-type';
import format from 'date-fns/format';
let NRGridComponent = class NRGridComponent {
constructor(modalService, cdr) {
this.modalService = modalService;
this.cdr = cdr;
this.onPageChanged = new EventEmitter();
this.onEditClicked = new EventEmitter();
this.onDeleteClicked = new EventEmitter();
this.onFilterChanged = new EventEmitter();
this.onOrderChanged = new EventEmitter();
this.onRowClicked = new EventEmitter();
this.onRowValueChanged = new EventEmitter();
this.onCellLinkClicked = new EventEmitter();
this.onLimitChanged = new EventEmitter();
this.onCustomButtonClicked = new EventEmitter();
this.editingRows = {};
this.limitChangeOptions = {
searchable: false,
valueMember: 'id',
displayMember: 'text',
hideLabel: true
};
this.pages = [
{ id: 10, text: '10' },
{ id: 25, text: '25' },
{ id: 50, text: '50' },
{ id: 100, text: '100' },
];
this.ranges = {};
this.filterChanged = new Subject();
this.rowFilterChange = new EventEmitter();
this.dataLoaded = new EventEmitter();
this.order = {};
this.typeheads = [];
this._rangeValue = '';
this.limit = 10;
this.filterChanged.pipe(debounceTime(500)).subscribe(val => {
if (this.go.dataSource) {
this.go.dataSource.reload();
}
else {
this.onFilterChanged.emit(this.rowFilter);
}
});
}
get rowFilter() {
return this._rowFilter;
}
set rowFilter(value) {
this.changePage(1);
this._rowFilter = value;
this.rowFilterChange.emit(this._rowFilter);
}
changePage(page) {
if (this.options) {
this.options.page = page;
}
}
filteredColumns() {
const f = _.filter(this.go.columns, (x) => {
return !x.denied;
});
return _.filter(f, (x) => {
return !x.hide;
});
}
dataLoad(go) {
go.loading = true;
if (go.dataSource.usePromise) {
go.dataSource.loader(go.dataSource.parent, this.rowFilter)
.then(r => {
go.data = r.data;
go.rowCount = r.rowCount;
go.loading = false;
this.dataLoaded.emit(true);
if (r.summary) {
go.summary = r.summary;
}
})
.catch(e => {
go.loading = false;
console.log('qr-grid-data-load-error', e);
});
}
else {
go.dataSource.loader(this.go.dataSource.parent, this.rowFilter).subscribe(r => {
go.data = r.data;
go.rowCount = r.rowCount;
go.loading = false;
this.dataLoaded.emit(true);
if (r.summary) {
go.summary = r.summary;
}
}, err => {
go.loading = false;
console.log('qr-grid-data-load-error', err);
});
}
}
ngOnInit() {
if (!this.rowFilter) {
this.rowFilter = {};
}
if (this.options && !this.options.limit) {
this.options.limit = 10;
}
if (this.options && !this.options.loading) {
this.options.loading = true;
}
if (this.options && this.options.pager === undefined) {
this.options.pager = true;
}
this.go = this.options;
if (!this.go.data) {
this.go.data = [];
}
if (!this.go.page) {
this.go.page = 1;
}
if (!this.go.limit) {
this.go.limit = 10;
}
if (!this.go.rowCount) {
this.go.rowCount = 0;
}
if (!this.go.bootstrapTableClass) {
this.go.bootstrapTableClass = 'table-bordered';
}
this.columns = this.filteredColumns();
this.loadDropdownData();
if (this.go.dataSource) {
this.go.dataSource.reload = () => {
this.editingRows = {};
return this.dataLoad(this.go);
};
if (!this.go.dataSource.manualLoading) {
this.go.dataSource.reload();
}
else {
this.go.loading = false;
}
}
}
loadDropdownData() {
const my = this;
_.each(this.go.columns, (x) => {
if (x.dropdownDataService) {
my.loadLookupData(x);
}
});
}
filterChange() {
this.changePage(1);
this.filterChanged.next(this.rowFilter);
this.loadDropdownData();
}
pageChange(val) {
if (this.go.dataSource) {
this.go.page = val;
this.go.dataSource.reload();
}
this.onPageChanged.emit(val);
}
editClicked(rowData) {
this.onEditClicked.emit(_.clone(rowData));
}
checkEditButtonOption(rowData) {
if (!this.go.actionButtonsOptions) {
return true;
}
else if (!this.go.actionButtonsOptions.edit) {
return false;
}
if (typeof this.go.actionButtonsOptions.edit == 'boolean') {
return this.go.actionButtonsOptions.edit;
}
else {
return this.go.actionButtonsOptions.edit(rowData);
}
}
checkDeleteButtonOption(rowData) {
if (!this.go.actionButtonsOptions) {
return true;
}
else if (!this.go.actionButtonsOptions.delete) {
return false;
}
if (typeof this.go.actionButtonsOptions.delete == 'boolean') {
return this.go.actionButtonsOptions.delete;
}
else {
return this.go.actionButtonsOptions.delete(rowData);
}
}
deleteClicked(rowData) {
this.activeDeleteModal = this.modalService.open(this.deleteModal, { centered: true });
this.deleteData = rowData;
}
submitDelete() {
this.onDeleteClicked.emit(this.deleteData);
this.activeDeleteModal.close();
}
linkClicked(data) {
this.onCellLinkClicked.emit(data);
}
isDefaultCell(t) {
return !t || (t == NRGridColumnType.default || t == NRGridColumnType.inlineEditor);
}
isLinkCell(t) {
return t === NRGridColumnType.link;
}
toggleOrder(column) {
const columnKey = column.orderKey ? column.orderKey : column.name;
if (this.order.column === columnKey) {
this.order.desc = !this.order.desc;
}
else {
this.order.desc = false;
}
this.order.column = columnKey;
this.onOrderChanged.emit(this.order);
}
rowValueChanged(e) {
this.onRowValueChanged.emit(e);
}
rowClicked(rowData) {
if (this.go.rowClickAction && this.go.rowClickAction.enable) {
this.onRowClicked.emit(rowData);
}
}
isFilterDefault(val) {
return val === FilterType.default;
}
isFilterDateRange(val) {
return val === FilterType.dateRange;
}
isFilterYesNo(val) {
return val == FilterType.yesNoRadio;
}
isFilterTypehead(val) {
return val == FilterType.typeHead;
}
isFilterDropdown(c) {
return c.filterType == FilterType.dropdown;
}
isFilterNumericRange(val) {
return val == FilterType.numericRange;
}
selectTypeheadItem($event, key) {
this.rowFilter[key] = $event.item;
this.filterChange();
}
onDateSelection(date, filterKey) {
if (!this.fromDate && !this.toDate) {
this.fromDate = date;
}
else if (this.fromDate && !this.toDate && date.after(this.fromDate)) {
this.toDate = date;
}
else {
this.toDate = null;
this.fromDate = date;
}
if (this.fromDate && this.toDate) {
let bs = this.fromDate;
let be = this.toDate;
let s = new Date(bs.year, bs.month - 1, bs.day);
let e = new Date(be.year, be.month - 1, be.day);
this._rangeValue = format(s, 'dd/MM/yyyy') + ' - ' + format(e, 'dd/MM/yyyy');
this.rangePicker.toggle();
this.rowFilter[filterKey] = s.toISOString() + ',' + e.toISOString();
this.filterChange();
}
}
rangeValue() {
return this._rangeValue;
}
isHovered(date) {
return this.fromDate && !this.toDate && this.hoveredDate && date.after(this.fromDate) && date.before(this.hoveredDate);
}
isInside(date) {
return date.after(this.fromDate) && date.before(this.toDate);
}
isRange(date) {
return date.equals(this.fromDate) || date.equals(this.toDate) || this.isInside(date) || this.isHovered(date);
}
getFilterKey(c) {
return c.filterKey ? c.filterKey : c.name;
}
rangeChanged(c) {
let key = this.getFilterKey(c);
let startKey = key + '___start';
let endKey = key + '___end';
let start = this.ranges[startKey];
let end = this.ranges[endKey];
this.rowFilter[key] = (start ? start : '') + '___' + (end ? end : '');
this.filterChange();
}
limitChanged(limit) {
this.limit = Number(limit.value ? limit.value : limit);
if (this.options.dataSource) {
this.options.dataSource.reload();
}
this.onLimitChanged.emit(this.limit);
}
loadLookupData(c) {
if (!c.dropdownData) {
c.dropdownDataService.subscribe(result => {
c.dropdownData = _.map(result.data, function (x) {
return {
id: x.id,
text: x.name
};
});
});
}
}
customButtonClick(button, row) {
this.onCustomButtonClicked.emit({
button: button,
data: row
});
}
inlineEditorOn(cr, rowIndex, rowValue) {
if (cr.type == NRGridColumnType.inlineEditor) {
this.editingRows['row-' + rowIndex + '-col-' + cr.name] = {
firstValue: rowValue[cr.name]
};
this.cdr.detectChanges();
let e = document.getElementById('row-' + rowIndex + '-col-' + cr.name);
if (e) {
e.focus();
}
}
}
inlineEditorOff(cr, rowIndex, rowValue = undefined, toggleEvent = false, revert = false) {
if (revert) {
rowValue[cr.name] = this.editingRows['row-' + rowIndex + '-col-' + cr.name].firstValue;
}
this.editingRows['row-' + rowIndex + '-col-' + cr.name] = undefined;
if (!revert && toggleEvent) {
this.rowValueChanged({
column: cr,
row: rowValue
});
}
}
};
NRGridComponent.ctorParameters = () => [
{ type: NgbModal },
{ type: ChangeDetectorRef }
];
__decorate([
Input()
], NRGridComponent.prototype, "options", void 0);
__decorate([
Input()
], NRGridComponent.prototype, "loading", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onPageChanged", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onEditClicked", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onDeleteClicked", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onFilterChanged", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onOrderChanged", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onRowClicked", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onRowValueChanged", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onCellLinkClicked", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onLimitChanged", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "onCustomButtonClicked", void 0);
__decorate([
ViewChild('deleteModal', { static: false })
], NRGridComponent.prototype, "deleteModal", void 0);
__decorate([
ViewChild('rangePicker', { static: false })
], NRGridComponent.prototype, "rangePicker", void 0);
__decorate([
Input()
], NRGridComponent.prototype, "columnHeaderTemplate", void 0);
__decorate([
Input()
], NRGridComponent.prototype, "footerTemplate", void 0);
__decorate([
Input()
], NRGridComponent.prototype, "rowFilter", null);
__decorate([
Output()
], NRGridComponent.prototype, "rowFilterChange", void 0);
__decorate([
Output()
], NRGridComponent.prototype, "dataLoaded", void 0);
NRGridComponent = __decorate([
Component({
selector: 'nr-grid',
template: "<div class=\"nr-grid\">\n <div class=\"table-responsive\">\n <table class=\"table {{options.bootstrapTableClass}} mb-0\">\n <thead>\n <tr>\n <th *ngFor=\"let c of columns\" class=\"nr-order-trigger\" (click)=\"toggleOrder(c)\"\n [ngClass]=\"{'text-right': c.alignment == 'right' }\"\n [ngStyle]=\"{'width': c.width != undefined ? c.width : 'auto' }\">\n\n <ng-container *ngTemplateOutlet=\"columnHeaderTemplate; context: {column: c}\">\n\n </ng-container>\n <ng-container *ngIf=\"!columnHeaderTemplate\">\n {{c.title}}\n </ng-container>\n <span class=\"nr-grid-orderer\"\n *ngIf=\"order.column === (c.orderKey != null ? c.orderKey : c.name)\">\n <i *ngIf=\"!order.desc\" class=\"fa fa-arrow-up\"></i>\n <i *ngIf=\"order.desc\" class=\"fa fa-arrow-down\"></i>\n </span>\n </th>\n <th *ngIf=\"go.actionButtons\"\n [ngStyle]=\"{'width': (90 + ((go.buttons ? go.buttons.length : 0) * 25)) + 'px' }\"></th>\n </tr>\n <tr class=\"filter-row\" *ngIf=\"go.filterRowEnabled\">\n <td *ngFor=\"let c of columns\">\n <ng-container *ngIf=\"!c.filterDisable\">\n <input *ngIf=\"!c.filterType || isFilterDefault(c.filterType)\" type=\"text\" placeholder=\"Filter\"\n class=\"filter-control\" [(ngModel)]=\"rowFilter[getFilterKey(c)]\"\n (ngModelChange)=\"filterChange()\">\n <input *ngIf=\"isFilterDateRange(c.filterType)\" type=\"text\" class=\"btn-light-disable\"\n ngbDatepicker\n #rangePicker=\"ngbDatepicker\"\n (dateSelect)=\"onDateSelection($event, getFilterKey(c))\"\n [dayTemplate]=\"dayTemplate\"\n [displayMonths]=\"2\" outsideDays=\"visible\" (focus)=\"rangePicker.toggle()\"\n [autoClose]=\"false\"\n placeholder=\"Filter\"\n [value]=\"rangeValue()\"\n class=\"filter-control\">\n <div *ngIf=\"isFilterNumericRange(c.filterType)\" class=\"range-selector\">\n <input type=\"text\" class=\"filter-control\" placeholder=\"Grather\"\n [(ngModel)]=\"ranges[getFilterKey(c) + '___start']\" (ngModelChange)=\"rangeChanged(c)\">\n <input type=\"text\" class=\"filter-control\" placeholder=\"Lower\"\n [(ngModel)]=\"ranges[getFilterKey(c) + '___end']\" (ngModelChange)=\"rangeChanged(c)\">\n </div>\n\n <nr-select *ngIf=\"isFilterDropdown(c)\" [(value)]=\"rowFilter[getFilterKey(c)]\" [options]=\"c.selectOptions\"\n label=\"Select\" (valueChange)=\"filterChange()\"></nr-select>\n <div *ngIf=\"isFilterYesNo(c.filterType)\" class=\"btn-group btn-group-toggle\" ngbRadioGroup\n name=\"radioBasic\"\n [(ngModel)]=\"rowFilter[getFilterKey(c)]\" (ngModelChange)=\"filterChange()\">\n <label ngbButtonLabel class=\"btn-primary btn-xs\">\n <input ngbButton type=\"radio\" [value]=\"true\"> Yes\n </label>\n <label ngbButtonLabel class=\"btn-primary btn-xs\">\n <input ngbButton type=\"radio\" [value]=\"false\"> No\n </label>\n </div>\n </ng-container>\n </td>\n <td *ngIf=\"go.actionButtons\"></td>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let r of go.data; let rowIndex=index;\"\n class=\"data-row\"\n [ngClass]=\"{'nr-row-clickable': go.rowClickAction && go.rowClickAction.enable}\"\n (click)=\"rowClicked(r)\">\n <td *ngFor=\"let cr of columns\"\n [ngClass]=\"{'text-right': cr.alignment == 'right', 'padding-none': editingRows['row-' + rowIndex + '-col-' + cr.name]}\">\n\n <div *ngIf=\"cr.formatter && !isLinkCell(cr.type)\">\n {{r[cr.name]|valueFormat: cr.formatter}}\n </div>\n\n <div class=\"default-view\"\n *ngIf=\"!cr.formatter && isDefaultCell(cr.type) && !editingRows['row-' + rowIndex + '-col-' + cr.name]\"\n [innerHTML]=\"cr.format ? cr.format({row: r, value: r[cr.name], parent: go.parent }) : r[cr.name]\"\n (click)=\"inlineEditorOn(cr, rowIndex, r)\"></div>\n\n <div *ngIf=\"isLinkCell(cr.type)\">\n <a href=\"javascript:void(0)\" (click)=\"linkClicked({row: r, column: cr})\"\n class=\"{{cr.link && cr.link.classes ? cr.link.classes : ''}}\"\n [ngbTooltip]=\"cr.link && cr.link.tooltip ? cr.link.tooltip : ''\">\n <i *ngIf=\"cr.link && cr.link.icon\" class=\"{{cr.link.icon}}\"></i>\n\n <span *ngIf=\"!cr.formatter\"\n [innerHTML]=\"cr.format ? cr.format({row: r, value: r[cr.name], parent: go.parent}) : r[cr.name]\"></span>\n <span *ngIf=\"cr.formatter\">{{r[cr.name]|valueFormat: cr.formatter}}</span>\n </a>\n </div>\n <div *ngIf=\"editingRows['row-' + rowIndex + '-col-' + cr.name]\">\n <div class=\"nr-inline-editor\">\n <input [id]=\"'row-' + rowIndex + '-col-' + cr.name\" type=\"text\" [(ngModel)]=\"r[cr.name]\"/>\n <div class=\"nr-inline-editor-buttons\">\n <button class=\"btn btn-sm btn-primary\" type=\"button\" (click)=\"inlineEditorOff(cr, rowIndex, r, true)\">\n Save\n </button>\n <button class=\"btn btn-sm btn-secondary\" type=\"button\"\n (click)=\"inlineEditorOff(cr, rowIndex, r, false, true)\">Cancel\n </button>\n </div>\n </div>\n </div>\n </td>\n <td class=\"action-buttons-container\" *ngIf=\"go.actionButtons\">\n <ng-container *ngFor=\"let b of go.buttons\">\n <a href=\"javascript:void(0);\" (click)=\"customButtonClick(b, r)\" ngbTooltip=\"{{b.tooltip}}\"\n *ngIf=\"!b.visible || (b.visible && b.visible(r))\">\n <i class=\"{{b.icon}}\"></i>\n </a>\n </ng-container>\n <a href=\"javascript:void(0);\" (click)=\"editClicked(r)\" ngbTooltip=\"Edit\"\n *ngIf=\"!go.actionButtonsOptions || checkEditButtonOption(r)\">\n <i class=\"fa fa-pencil\"></i>\n </a>\n <a href=\"javascript:void(0);\" (click)=\"deleteClicked(r)\" ngbTooltip=\"Delete\"\n *ngIf=\"!go.actionButtonsOptions || checkDeleteButtonOption(r)\">\n <i class=\"fa fa-trash\"></i>\n </a>\n </td>\n </tr>\n <tr *ngIf=\"go.data == undefined || go.data.length == 0\">\n <td [colSpan]=\"columns.length + (go.actionButtons ? 1 : 0)\">\n <div style=\"padding: 20px; text-align: center\">\n No data\n </div>\n </td>\n </tr>\n </tbody>\n <tfoot *ngIf=\"go.summary && !go.hideSummary\">\n <tr>\n <th *ngFor=\"let cr of columns\" [ngClass]=\"{'text-right': cr.alignment == 'right' }\">\n <ng-container *ngIf=\"!cr.hideFromSummary\">\n <div *ngIf=\"cr.formatter\">\n {{go.summary[cr.name]|valueFormat: cr.formatter}}\n </div>\n\n <div *ngIf=\"isDefaultCell(cr.type) && (!cr.formatter)\"\n [innerHTML]=\"cr.format ? cr.format({row: go.summary, value: go.summary[cr.name], parent: go.parent}) : go.summary[cr.name]\"></div>\n\n <div *ngIf=\"isLinkCell(cr.type) && (!cr.formatter)\">\n <a href=\"javascript:void(0)\" (click)=\"linkClicked({row: go.summary, column: cr})\"\n class=\"{{cr.link.classes ? cr.link.classes : ''}}\"\n [ngbTooltip]=\"cr.link && cr.link.tooltip ? cr.link.tooltip : ''\">\n <i *ngIf=\"cr.link.icon\" class=\"{{cr.link.icon}}\"></i>\n <span\n [innerHTML]=\"cr.format ? cr.format({row: go.summary, value: go.summary[cr.name], parent: go.parent}) : go.summary[cr.name]\"></span>\n </a>\n </div>\n </ng-container>\n </th>\n </tr>\n </tfoot>\n </table>\n\n </div>\n <ng-container *ngTemplateOutlet=\"footerTemplate;\">\n\n </ng-container>\n <div class=\"nr-grid-footer row\" *ngIf=\"go.pager\">\n <div class=\"col-md-12\">\n <ngb-pagination class=\"float-right\" [collectionSize]=\"go.rowCount\" [(page)]=\"go.page\" [maxSize]=\"10\"\n [pageSize]=\"go.limit\" (pageChange)=\"pageChange($event)\"></ngb-pagination>\n <div class=\"float-right limit-selector\" style=\"min-width: 150px; width: 150px\">\n <nr-select class=\"float-right\" [data]=\"pages\" [(value)]=\"go.limit\" label=\"Limit\" [options]=\"limitChangeOptions\"\n (valueChange)=\"limitChanged($event)\"></nr-select>\n </div>\n </div>\n </div>\n <div class=\"clearfix\"></div>\n</div>\n<ng-template #deleteModal let-modal>\n <div class=\"modal-header\">\n <h4 class=\"modal-title\" id=\"modal-basic-title\">Delete</h4>\n <button type=\"button\" class=\"close\" aria-label=\"Close\" (click)=\"modal.dismiss('Cross click')\">\n <span aria-hidden=\"true\">×</span>\n </button>\n </div>\n <div class=\"modal-body\">\n Data will be deleted, are you sure?\n </div>\n <div class=\"modal-footer\">\n <button type=\"submit\" class=\"btn btn-success\" (click)=\"submitDelete()\">Delete</button>\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"modal.dismiss('Cross click')\">Cancel</button>\n </div>\n</ng-template>\n<ng-template #dayTemplate let-date let-focused=\"focused\">\n <span class=\"custom-day\"\n [class.focused]=\"focused\"\n [class.range]=\"isRange(date)\"\n [class.faded]=\"isHovered(date) || isInside(date)\"\n (mouseenter)=\"hoveredDate = date\"\n (mouseleave)=\"hoveredDate = null\">\n {{ date.day }}\n </span>\n</ng-template>\n"
})
], NRGridComponent);
export { NRGridComponent };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibnItZ3JpZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uci1ncmlkLyIsInNvdXJjZXMiOlsibGliL25yLWdyaWQvbnItZ3JpZC5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBQyxpQkFBaUIsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFHeEgsT0FBTyxLQUFLLENBQUMsTUFBTSxRQUFRLENBQUM7QUFFNUIsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUM3QixPQUFPLEVBQUMsWUFBWSxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUMsT0FBTyxFQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUMsTUFBTSw0QkFBNEIsQ0FBQztBQUM3RCxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxvQ0FBb0MsQ0FBQztBQUNwRSxPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFDdEQsT0FBTyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFPckMsSUFBYSxlQUFlLEdBQTVCLE1BQWEsZUFBZTtJQXFFMUIsWUFBb0IsWUFBc0IsRUFBVSxHQUFzQjtRQUF0RCxpQkFBWSxHQUFaLFlBQVksQ0FBVTtRQUFVLFFBQUcsR0FBSCxHQUFHLENBQW1CO1FBL0RoRSxrQkFBYSxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7UUFDcEMsa0JBQWEsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO1FBQ3hDLG9CQUFlLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUMxQyxvQkFBZSxHQUFzQixJQUFJLFlBQVksRUFBTyxDQUFDO1FBQzdELG1CQUFjLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUN6QyxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7UUFDdkMsc0JBQWlC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QVQsTUFBTSxFQUFFO3dEQUFrRDtBQUNqRDtJQUFULE1BQU0sRUFBRTt3REFBcUU7QUFDcEU7SUFBVCxNQUFNLEVBQUU7dURBQWlEO0FBQ2hEO0lBQVQsTUFBTSxFQUFFO3FEQUErQztBQUM5QztJQUFULE1BQU0sRUFBRTswREFBb0Q7QUFDbkQ7SUFBVCxNQUFNLEVBQUU7MERBQW9EO0FBQ25EO0lBQVQsTUFBTSxFQUFFO3VEQUFpRDtBQUNoRDtJQUFULE1BQU0sRUFBRTs4REFBd0Q7QUFFdEI7SUFBMUMsU0FBUyxDQUFDLGFBQWEsRUFBRSxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUMsQ0FBQztvREFBcUI7QUFDcEI7SUFBMUMsU0FBUyxDQUFDLGFBQWEsRUFBRSxFQUFDLE1BQU0sRUFBRSxLQUFLLEVBQUMsQ0FBQztvREFBcUI7QUFFdEQ7SUFBUixLQUFLLEVBQUU7NkRBQXdDO0FBQ3ZDO0lBQVIsS0FBSyxFQUFFO3VEQUFrQztBQTBCakM7SUFBUixLQUFLLEVBQUU7Z0RBRVA7QUFRUztJQUFULE1BQU0sRUFBRTt3REFBMkM7QUFDMUM7SUFBVCxNQUFNLEVBQUU7bURBQXNDO0FBMURwQyxlQUFlO0lBSjNCLFNBQVMsQ0FBQztRQUNULFFBQVEsRUFBRSxTQUFTO1FBQ25CLG81VEFBdUM7S0FDeEMsQ0FBQztHQUNXLGVBQWUsQ0FzYTNCO1NBdGFZLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge0NoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0LCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7TlJHcmlkQnV0dG9ufSBmcm9tICcuL21vZGVsL2J1dHRvbi9uci1ncmlkLWJ1dHRvbic7XG5pbXBvcnQge05SR3JpZENvbHVtbn0gZnJvbSAnLi9tb2RlbC9jb2x1bW4vbnItZ3JpZC1jb2x1bW4nO1xuaW1wb3J0ICogYXMgXyBmcm9tICdsb2Rhc2gnO1xuaW1wb3J0IHtOUkdyaWRPcHRpb25zfSBmcm9tICcuL21vZGVsL29wdGlvbnMvbnItZ3JpZC1vcHRpb25zJztcbmltcG9ydCB7U3ViamVjdH0gZnJvbSAncnhqcyc7XG5pbXBvcnQge2RlYm91bmNlVGltZX0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHtOZ2JEYXRlLCBOZ2JNb2RhbH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xuaW1wb3J0IHtOUkdyaWRDb2x1bW5UeXBlfSBmcm9tICcuL21vZGVsL2NvbHVtbi9uci1ncmlkLWNvbHVtbi10eXBlJztcbmltcG9ydCB7RmlsdGVyVHlwZX0gZnJvbSAnLi9tb2RlbC9maWx0ZXIvZmlsdGVyLXR5cGUnO1xuaW1wb3J0IGZvcm1hdCBmcm9tICdkYXRlLWZucy9mb3JtYXQnO1xuaW1wb3J0IHtOUlNlbGVjdE9wdGlvbnN9IGZyb20gJ25yLXNlbGVjdCc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ25yLWdyaWQnLFxuICB0ZW1wbGF0ZVVybDogJy4vbnItZ3JpZC5jb21wb25lbnQuaHRtbCdcbn0pXG5leHBvcnQgY2xhc3MgTlJHcmlkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBhY3RpdmVEZWxldGVNb2RhbDtcblxuICBASW5wdXQoKSBvcHRpb25zOiBOUkdyaWRPcHRpb25zO1xuICBASW5wdXQoKSBsb2FkaW5nOiBib29sZWFuO1xuICBAT3V0cHV0KCkgb25QYWdlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9uRWRpdENsaWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvbkRlbGV0ZUNsaWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvbkZpbHRlckNoYW5nZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb25PcmRlckNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvblJvd0NsaWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvblJvd1ZhbHVlQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICBAT3V0cHV0KCkgcHVibGljIG9uQ2VsbExpbmtDbGlja2VkID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBwdWJsaWMgb25MaW1pdENoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIHB1YmxpYyBvbkN1c3RvbUJ1dHRvbkNsaWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcblxuICBAVmlld0NoaWxkKCdkZWxldGVNb2RhbCcsIHtzdGF0aWM6IGZhbHNlfSkgcHJpdmF0ZSBkZWxldGVNb2RhbDtcbiAgQFZpZXdDaGlsZCgncmFuZ2VQaWNrZXInLCB7c3RhdGljOiBmYWxzZX0pIHByaXZhdGUgcmFuZ2VQaWNrZXI7XG5cbiAgQElucHV0KCkgY29sdW1uSGVhZGVyVGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XG4gIEBJbnB1dCgpIGZvb3RlclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+O1xuXG4gIGNvbHVtbnM6IE5SR3JpZENvbHVtbltdO1xuICBlZGl0aW5nUm93czogYW55ID0ge307XG5cbiAgbGltaXRDaGFuZ2VPcHRpb25zOiBOUlNlbGVjdE9wdGlvbnMgPSB7XG4gICAgc2VhcmNoYWJsZTogZmFsc2UsXG4gICAgdmFsdWVNZW1iZXI6ICdpZCcsXG4gICAgZGlzcGxheU1lbWJlcjogJ3RleHQnLFxuICAgIGhpZGVMYWJlbDogdHJ1ZVxuICB9O1xuICBwYWdlcyA9XG4gICAgW1xuICAgICAge2lkOiAxMCwgdGV4dDogJzEwJ30sXG4gICAgICB7aWQ6IDI1LCB0ZXh0OiAnMjUnfSxcbiAgICAgIHtpZDogNTAsIHRleHQ6ICc1MCd9LFxuICAgICAge2lkOiAxMDAsIHRleHQ6ICcxMDAnfSxcbiAgICBdO1xuXG4gIGdvOiBOUkdyaWRPcHRpb25zO1xuXG4gIHJhbmdlczogYW55ID0ge307XG4gIGZpbHRlckNoYW5nZWQ6IFN1YmplY3Q8YW55PiA9IG5ldyBTdWJqZWN0PGFueT4oKTtcblxuICBfcm93RmlsdGVyOiBhbnk7XG5cbiAgQElucHV0KCkgZ2V0IHJvd0ZpbHRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5fcm93RmlsdGVyO1xuICB9XG5cbiAgc2V0IHJvd0ZpbHRlcih2YWx1ZSkge1xuICAgIHRoaXMuY2hhbmdlUGFnZSgxKTtcbiAgICB0aGlzLl9yb3dGaWx0ZXIgPSB2YWx1ZTtcbiAgICB0aGlzLnJvd0ZpbHRlckNoYW5nZS5lbWl0KHRoaXMuX3Jvd0ZpbHRlcik7XG4gIH1cblxuICBAT3V0cHV0KCkgcm93RmlsdGVyQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBkYXRhTG9hZGVkID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgY2hhbmdlUGFnZShwYWdlKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucykge1xuICAgICAgdGhpcy5vcHRpb25zLnBhZ2UgPSBwYWdlO1xuICAgIH1cbiAgfVxuXG4gIG9yZGVyOiBhbnkgPSB7fTtcbiAgZGVsZXRlRGF0YTogYW55O1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCwgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgdGhpcy5maWx0ZXJDaGFuZ2VkLnBpcGUoZGVib3VuY2VUaW1lKDUwMCkpLnN1YnNjcmliZSh2YWwgPT4ge1xuICAgICAgaWYgKHRoaXMuZ28uZGF0YVNvdXJjZSkge1xuICAgICAgICB0aGlzLmdvLmRhdGFTb3VyY2UucmVsb2FkKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9uRmlsdGVyQ2hhbmdlZC5lbWl0KHRoaXMucm93RmlsdGVyKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGZpbHRlcmVkQ29sdW1ucygpOiBOUkdyaWRDb2x1bW5bXSB7XG4gICAgY29uc3QgZiA9IF8uZmlsdGVyKHRoaXMuZ28uY29sdW1ucywgKHgpID0+IHtcbiAgICAgIHJldHVybiAheC5kZW5pZWQ7XG4gICAgfSk7XG4gICAgcmV0dXJuIF8uZmlsdGVyKGYsICh4KSA9PiB7XG4gICAgICByZXR1cm4gIXguaGlkZTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgZGF0YUxvYWQoZ286IE5SR3JpZE9wdGlvbnMpIHtcbiAgICBnby5sb2FkaW5nID0gdHJ1ZTtcbiAgICBpZiAoZ28uZGF0YVNvdXJjZS51c2VQcm9taXNlKSB7XG4gICAgICBnby5kYXRhU291cmNlLmxvYWRlcihnby5kYXRhU291cmNlLnBhcmVudCwgdGhpcy5yb3dGaWx0ZXIpXG4gICAgICAgIC50aGVuKHIgPT4ge1xuICAgICAgICAgIGdvLmRhdGEgPSByLmRhdGE7XG4gICAgICAgICAgZ28ucm93Q291bnQgPSByLnJvd0NvdW50O1xuICAgICAgICAgIGdvLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICB0aGlzLmRhdGFMb2FkZWQuZW1pdCh0cnVlKTtcbiAgICAgICAgICBpZiAoci5zdW1tYXJ5KSB7XG4gICAgICAgICAgICBnby5zdW1tYXJ5ID0gci5zdW1tYXJ5O1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKGUgPT4ge1xuICAgICAgICAgIGdvLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgICBjb25zb2xlLmxvZygncXItZ3JpZC1kYXRhLWxvYWQtZXJyb3InLCBlKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdvLmRhdGFTb3VyY2UubG9hZGVyKHRoaXMuZ28uZGF0YVNvdXJjZS5wYXJlbnQsIHRoaXMucm93RmlsdGVyKS5zdWJzY3JpYmUociA9PiB7XG4gICAgICAgIGdvLmRhdGEgPSByLmRhdGE7XG4gICAgICAgIGdvLnJvd0NvdW50ID0gci5yb3dDb3VudDtcbiAgICAgICAgZ28ubG9hZGluZyA9IGZhbHNlO1xuICAgICAgICB0aGlzLmRhdGFMb2FkZWQuZW1pdCh0cnVlKTtcbiAgICAgICAgaWYgKHIuc3VtbWFyeSkge1xuICAgICAgICAgIGdvLnN1bW1hcnkgPSByLnN1bW1hcnk7XG4gICAgICAgIH1cbiAgICAgIH0sIGVyciA9PiB7XG4gICAgICAgIGdvLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgICAgY29uc29sZS5sb2coJ3FyLWdyaWQtZGF0YS1sb2FkLWVycm9yJywgZXJyKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuXG4gICAgaWYgKCF0aGlzLnJvd0ZpbHRlcikge1xuICAgICAgdGhpcy5yb3dGaWx0ZXIgPSB7fTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zICYmICF0aGlzLm9wdGlvbnMubGltaXQpIHtcbiAgICAgIHRoaXMub3B0aW9ucy5saW1pdCA9IDEwO1xuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMgJiYgIXRoaXMub3B0aW9ucy5sb2FkaW5nKSB7XG4gICAgICB0aGlzLm9wdGlvbnMubG9hZGluZyA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucyAmJiB0aGlzLm9wdGlvbnMucGFnZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5vcHRpb25zLnBhZ2VyID0gdHJ1ZTtcbiAgICB9XG5cbiAgICB0aGlzLmdvID0gdGhpcy5vcHRpb25zO1xuXG4gICAgaWYgKCF0aGlzLmdvLmRhdGEpIHtcbiAgICAgIHRoaXMuZ28uZGF0YSA9IFtdO1xuICAgIH1cbiAgICBpZiAoIXRoaXMuZ28ucGFnZSkge1xuICAgICAgdGhpcy5nby5wYWdlID0gMTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmdvLmxpbWl0KSB7XG4gICAgICB0aGlzLmdvLmxpbWl0ID0gMTA7XG4gICAgfVxuICAgIGlmICghdGhpcy5nby5yb3dDb3VudCkge1xuICAgICAgdGhpcy5nby5yb3dDb3VudCA9IDA7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmdvLmJvb3RzdHJhcFRhYmxlQ2xhc3MpIHtcbiAgICAgIHRoaXMuZ28uYm9vdHN0cmFwVGFibGVDbGFzcyA9ICd0YWJsZS1ib3JkZXJlZCc7XG4gICAgfVxuXG4gICAgdGhpcy5jb2x1bW5zID0gdGhpcy5maWx0ZXJlZENvbHVtbnMoKTtcblxuICAgIHRoaXMubG9hZERyb3Bkb3duRGF0YSgpO1xuICAgIGlmICh0aGlzLmdvLmRhdGFTb3VyY2UpIHtcbiAgICAgIHRoaXMuZ28uZGF0YVNvdXJjZS5yZWxvYWQgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuZWRpdGluZ1Jvd3MgPSB7fTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YUxvYWQodGhpcy5nbyk7XG4gICAgICB9O1xuICAgICAgaWYgKCF0aGlzLmdvLmRhdGFTb3VyY2UubWFudWFsTG9hZGluZykge1xuICAgICAgICB0aGlzLmdvLmRhdGFTb3VyY2UucmVsb2FkKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmdvLmxvYWRpbmcgPSBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBsb2FkRHJvcGRvd25EYXRhKCkge1xuICAgIGNvbnN0IG15ID0gdGhpcztcbiAgICBfLmVhY2godGhpcy5nby5jb2x1bW5zLCAoeCkgPT4ge1xuICAgICAgaWYgKHguZHJvcGRvd25EYXRhU2VydmljZSkge1xuICAgICAgICBteS5sb2FkTG9va3VwRGF0YSh4KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGZpbHRlckNoYW5nZSgpIHtcbiAgICB0aGlzLmNoYW5nZVBhZ2UoMSk7XG4gICAgdGhpcy5maWx0ZXJDaGFuZ2VkLm5leHQodGhpcy5yb3dGaWx0ZXIpO1xuICAgIHRoaXMubG9hZERyb3Bkb3duRGF0YSgpO1xuICB9XG5cbiAgcGFnZUNoYW5nZSh2YWwpIHtcbiAgICBpZiAodGhpcy5nby5kYXRhU291cmNlKSB7XG4gICAgICB0aGlzLmdvLnBhZ2UgPSB2YWw7XG4gICAgICB0aGlzLmdvLmRhdGFTb3VyY2UucmVsb2FkKCk7XG4gICAgfVxuICAgIHRoaXMub25QYWdlQ2hhbmdlZC5lbWl0KHZhbCk7XG4gIH1cblxuICBlZGl0Q2xpY2tlZChyb3dEYXRhKSB7XG4gICAgdGhpcy5vbkVkaXRDbGlja2VkLmVtaXQoXy5jbG9uZShyb3dEYXRhKSk7XG4gIH1cblxuICBjaGVja0VkaXRCdXR0b25PcHRpb24ocm93RGF0YSkge1xuICAgIGlmICghdGhpcy5nby5hY3Rpb25CdXR0b25zT3B0aW9ucykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmICghdGhpcy5nby5hY3Rpb25CdXR0b25zT3B0aW9ucy5lZGl0KSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB0aGlzLmdvLmFjdGlvbkJ1dHRvbnNPcHRpb25zLmVkaXQgPT0gJ2Jvb2xlYW4nKSB7XG4gICAgICByZXR1cm4gdGhpcy5nby5hY3Rpb25CdXR0b25zT3B0aW9ucy5lZGl0O1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdGhpcy5nby5hY3Rpb25CdXR0b25zT3B0aW9ucy5lZGl0KHJvd0RhdGEpO1xuICAgIH1cbiAgfVxuXG4gIGNoZWNrRGVsZXRlQnV0dG9uT3B0aW9uKHJvd0RhdGEpIHtcbiAgICBpZiAoIXRoaXMuZ28uYWN0aW9uQnV0dG9uc09wdGlvbnMpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAoIXRoaXMuZ28uYWN0aW9uQnV0dG9uc09wdGlvbnMuZGVsZXRlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB0aGlzLmdvLmFjdGlvbkJ1dHRvbnNPcHRpb25zLmRlbGV0ZSA9PSAnYm9vbGVhbicpIHtcbiAgICAgIHJldHVybiB0aGlzLmdvLmFjdGlvbkJ1dHRvbnN