ngx-excel-viewer
Version:
Ngx-excel-viewer is an angular library to view/edit excel data in the angular application where data is in the form of matrix of string.
211 lines • 41.3 kB
JavaScript
import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
import * as i0 from "@angular/core";
import * as i1 from "@angular/common";
export class NgxExcelViewerComponent {
constructor() {
this.id = "";
this.sheetNames = [];
this.editable = false;
this.events = null;
this.saveDataOutput = "complete";
this.onDataSave = new EventEmitter();
this.onScrollEnd = new EventEmitter();
this.currentSheetName = "";
this.maxOfColumns = 0;
this.selectedCellIndices = [-1, -1];
this.isEditingTheSelectedCell = false;
this.headers = [];
this.sheetData = [];
this.isSheetDataChanged = false;
this.backupSheetData = [];
this.modifiedRows = [];
this.renderedPages = 1;
this.lastScrollTop = 0;
this.loading = false;
}
ngOnInit() {
if (this.data != null) {
this.currentSheetName = this.sheetNames[0];
if (this.data[this.currentSheetName]) {
this.run();
}
}
if (this.events != null) {
this.events.subscribe(event => {
if (event.id == this.id) {
if (event.type == "cancel") {
this.sheetData = JSON.parse(JSON.stringify(this.backupSheetData));
this.isSheetDataChanged = false;
this.modifiedRows = [];
}
else if (event.type == "save") {
if (this.saveDataOutput == "complete") {
this.onDataSave.emit({ id: this.id, sheet: this.currentSheetName, data: this.sheetData.map((row) => row['value']) });
return;
}
let payload = {};
for (let rowIndex of this.modifiedRows) {
payload[`${rowIndex + 1}`] = this.sheetData[rowIndex].map((row) => row['value']);
}
this.onDataSave.emit({ id: this.id, sheet: this.currentSheetName, data: payload });
}
else if (event.type == "saved") {
for (let rowIndex of this.modifiedRows) {
this.data[rowIndex] = this.sheetData[rowIndex].map((row) => row['value']);
this.backupSheetData[rowIndex] = this.sheetData[rowIndex];
}
}
else if (event.type == "new_data") {
this.run();
}
}
});
}
}
run() {
this.loading = true;
setTimeout(() => {
this.calculateMaxColumns();
this.generateHeaders();
this.generateSheetData();
setTimeout(() => {
this.loading = false;
}, 100);
}, 100);
}
ngOnChanges(changes) {
if (changes['data'] && changes['data'].previousValue != changes['data'].currentValue) {
this.run();
}
}
calculateMaxColumns() {
this.maxOfColumns = 0;
if (this.data[this.currentSheetName]) {
for (let row of this.data[this.currentSheetName]) {
if (row.length > this.maxOfColumns) {
this.maxOfColumns = row.length;
}
}
}
}
generateHeaders() {
let headers = [];
for (let i = 0; i < this.maxOfColumns; i++) {
let header = "";
let num = i;
while (num >= 0) {
let remainder = num % 26;
header = String.fromCharCode(65 + remainder) + header;
num = Math.floor(num / 26) - 1;
}
headers.push(header);
}
this.headers = headers;
}
generateSheetData() {
if (this.data[this.currentSheetName]) {
this.sheetData = JSON.parse(JSON.stringify(this.data[this.currentSheetName].map((row) => row.map((r) => ({ "value": r })))));
this.backupSheetData = JSON.parse(JSON.stringify(this.sheetData));
}
else {
this.sheetData = [];
this.backupSheetData = [];
}
}
setSelectedSheetName(sheet) {
if (this.isSheetDataChanged) {
alert("Save sheet before switching");
return;
}
this.currentSheetName = sheet;
this.run();
}
selectCell(i, j) {
if ((this.selectedCellIndices[0] == i && this.selectedCellIndices[1] == j) || (i > this.sheetData.length - 1 || j > this.maxOfColumns - 1)) {
document.querySelector(`#input-${this.selectedCellIndices[0]}-${this.selectedCellIndices[1]}`).focus();
return;
}
i = i >= 0 ? i : 0;
j = j >= 0 ? j : 0;
this.selectedCellIndices = [i, j];
document.querySelector(`#input-${i}-${j}`).focus();
}
onDataChanges(event, i, j) {
if (!this.editable)
return;
if (this.backupSheetData[i][j]["value"] != event.target.innerText) {
this.sheetData[i][j]["value"] = event.target.innerText;
if (!this.modifiedRows.includes(i)) {
this.modifiedRows.push(i);
}
if (!this.isSheetDataChanged) {
this.isSheetDataChanged = true;
}
}
}
onKeyPress(event) {
if (event.which == 13) {
event.preventDefault();
}
}
onScroll(event) {
if (event.target.scrollTop > this.lastScrollTop) {
if ((event.target.offsetHeight + event.target.scrollTop) >= event.target.scrollHeight) {
this.onScrollEnd.emit({ id: this.id, pageNo: this.renderedPages++, sheet: this.currentSheetName });
}
}
this.lastScrollTop = event.target.scrollTop;
}
onKeyDown(event) {
if (event.key?.includes("Arrow")) {
const key = event.key;
let i = this.selectedCellIndices[0];
let j = this.selectedCellIndices[1];
event.target.blur();
if (key == "ArrowUp") {
i--;
}
else if (key == "ArrowDown") {
i++;
}
else if (key == "ArrowLeft") {
if (window.getSelection()?.anchorOffset == 0)
j--;
}
else if (key == "ArrowRight") {
if ((window.getSelection()?.anchorOffset ?? 0) >= event.target.innerText.length)
j++;
}
this.selectCell(i, j);
}
}
}
NgxExcelViewerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: NgxExcelViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
NgxExcelViewerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.8", type: NgxExcelViewerComponent, selector: "ngx-excel-viewer", inputs: { id: "id", data: "data", sheetNames: "sheetNames", editable: "editable", events: "events", saveDataOutput: "saveDataOutput" }, outputs: { onDataSave: "onDataSave", onScrollEnd: "onScrollEnd" }, host: { listeners: { "keypress": "onKeyPress($event)", "keydown": "onKeyDown($event)" } }, usesOnChanges: true, ngImport: i0, template: "<div class=\"excel-file\">\r\n <div class=\"scrollable\" (scroll)=\"onScroll($event)\">\r\n <table *ngIf=\"sheetData.length != 0\">\r\n <thead>\r\n <tr>\r\n <th class=\"header s-no\"></th>\r\n <th class=\"header\" *ngFor=\"let header of headers\">{{header}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <ng-container *ngIf=\"currentSheetName && data\">\r\n <tr *ngFor=\"let data of sheetData; let i=index\">\r\n <td class=\"s-no\">{{i+1}}</td>\r\n <td *ngFor=\"let cell of data; let j=index\"\r\n [ngClass]=\"{'main-selected': selectedCellIndices[0] == i && selectedCellIndices[1] == j}\"\r\n (click)=\"selectCell(i,j)\">\r\n <div [id]=\"'input-'+i+'-'+j\" (blur)=\"onDataChanges($event, i, j)\" (focus)=\"selectCell(i,j)\"\r\n [contentEditable]=\"editable\" [innerHTML]=\"cell['value']\"></div>\r\n </td>\r\n </tr>\r\n </ng-container>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div class=\"empty-data\" *ngIf=\"sheetData.length == 0\">\r\n Empty Sheet\r\n </div>\r\n <div class=\"footer\">\r\n Sheets: <div *ngFor=\"let sheet of sheetNames\" class=\"sheet\" [ngClass]=\"{'active': currentSheetName == sheet}\"\r\n (click)=\"setSelectedSheetName(sheet)\">{{sheet}}</div>\r\n </div>\r\n <div class=\"loading\" *ngIf=\"loading\">\r\n <div class=\"spinner\">\r\n <div class=\"lds-spinner\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: ["*{margin:0;padding:0}.excel-file{border:1px solid lightgrey;width:100%;min-height:20vh;height:100%;border-radius:5px;position:relative;font-family:sans-serif;-webkit-user-select:none;user-select:none;overflow:hidden}.excel-file .loading{position:absolute;inset:0;background-color:#0003;z-index:5}.excel-file .loading .spinner{position:absolute;top:50%;left:47%;transform:translate(-50%,-50%) scale(.7)}.excel-file .scrollable{width:100%;height:calc(100% - 50px);overflow:auto}.excel-file td,.excel-file th{padding:0;white-space:nowrap}.excel-file .s-no{min-width:25px;background-color:#efefef;position:sticky;left:-1.5px;text-align:center;z-index:1}.excel-file table{table-layout:fixed}.excel-file .main-selected{background-color:#87ceeb33;border:2px solid skyblue}.excel-file td div{outline:none;border:none;width:auto;padding:5px;background-color:transparent;min-height:10px}.excel-file table,.excel-file td,.excel-file th{border:1.5px solid #d9d9d9;border-collapse:collapse}.excel-file table .header,.excel-file td .header,.excel-file th .header{background-color:#efefef;position:sticky;top:-1.5px;z-index:2;padding:2px}.excel-file .empty-data{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.excel-file .footer{position:absolute;bottom:0;left:0;right:0;min-height:30px;z-index:5;padding:5px;background-color:#efefef;border-top:1.5px solid lightgray;overflow-x:auto;display:flex;align-items:center}.excel-file .footer .sheet{display:inline-block;position:relative;padding:5px;margin:5px 2px;border-radius:3px;cursor:pointer;transition:all .3s ease;white-space:nowrap}.excel-file .footer .sheet.active,.excel-file .footer .sheet:hover{margin:5px;background-color:#fff;box-shadow:0 0 5px #0003}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#888;border-radius:5px}::-webkit-scrollbar-thumb:hover{background:#555}.lds-spinner{color:official;display:inline-block;position:relative;width:80px;height:80px}.lds-spinner div{transform-origin:40px 40px;animation:lds-spinner 1.2s linear infinite}.lds-spinner div:after{content:\" \";display:block;position:absolute;top:3px;left:37px;width:6px;height:18px;border-radius:20%;background:#fff}.lds-spinner div:nth-child(1){transform:rotate(0);animation-delay:-1.1s}.lds-spinner div:nth-child(2){transform:rotate(30deg);animation-delay:-1s}.lds-spinner div:nth-child(3){transform:rotate(60deg);animation-delay:-.9s}.lds-spinner div:nth-child(4){transform:rotate(90deg);animation-delay:-.8s}.lds-spinner div:nth-child(5){transform:rotate(120deg);animation-delay:-.7s}.lds-spinner div:nth-child(6){transform:rotate(150deg);animation-delay:-.6s}.lds-spinner div:nth-child(7){transform:rotate(180deg);animation-delay:-.5s}.lds-spinner div:nth-child(8){transform:rotate(210deg);animation-delay:-.4s}.lds-spinner div:nth-child(9){transform:rotate(240deg);animation-delay:-.3s}.lds-spinner div:nth-child(10){transform:rotate(270deg);animation-delay:-.2s}.lds-spinner div:nth-child(11){transform:rotate(300deg);animation-delay:-.1s}.lds-spinner div:nth-child(12){transform:rotate(330deg);animation-delay:0s}@keyframes lds-spinner{0%{opacity:1}to{opacity:0}}\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"] }] });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.8", ngImport: i0, type: NgxExcelViewerComponent, decorators: [{
type: Component,
args: [{ selector: 'ngx-excel-viewer', template: "<div class=\"excel-file\">\r\n <div class=\"scrollable\" (scroll)=\"onScroll($event)\">\r\n <table *ngIf=\"sheetData.length != 0\">\r\n <thead>\r\n <tr>\r\n <th class=\"header s-no\"></th>\r\n <th class=\"header\" *ngFor=\"let header of headers\">{{header}}</th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <ng-container *ngIf=\"currentSheetName && data\">\r\n <tr *ngFor=\"let data of sheetData; let i=index\">\r\n <td class=\"s-no\">{{i+1}}</td>\r\n <td *ngFor=\"let cell of data; let j=index\"\r\n [ngClass]=\"{'main-selected': selectedCellIndices[0] == i && selectedCellIndices[1] == j}\"\r\n (click)=\"selectCell(i,j)\">\r\n <div [id]=\"'input-'+i+'-'+j\" (blur)=\"onDataChanges($event, i, j)\" (focus)=\"selectCell(i,j)\"\r\n [contentEditable]=\"editable\" [innerHTML]=\"cell['value']\"></div>\r\n </td>\r\n </tr>\r\n </ng-container>\r\n </tbody>\r\n </table>\r\n </div>\r\n <div class=\"empty-data\" *ngIf=\"sheetData.length == 0\">\r\n Empty Sheet\r\n </div>\r\n <div class=\"footer\">\r\n Sheets: <div *ngFor=\"let sheet of sheetNames\" class=\"sheet\" [ngClass]=\"{'active': currentSheetName == sheet}\"\r\n (click)=\"setSelectedSheetName(sheet)\">{{sheet}}</div>\r\n </div>\r\n <div class=\"loading\" *ngIf=\"loading\">\r\n <div class=\"spinner\">\r\n <div class=\"lds-spinner\">\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n <div></div>\r\n </div>\r\n </div>\r\n </div>\r\n</div>", styles: ["*{margin:0;padding:0}.excel-file{border:1px solid lightgrey;width:100%;min-height:20vh;height:100%;border-radius:5px;position:relative;font-family:sans-serif;-webkit-user-select:none;user-select:none;overflow:hidden}.excel-file .loading{position:absolute;inset:0;background-color:#0003;z-index:5}.excel-file .loading .spinner{position:absolute;top:50%;left:47%;transform:translate(-50%,-50%) scale(.7)}.excel-file .scrollable{width:100%;height:calc(100% - 50px);overflow:auto}.excel-file td,.excel-file th{padding:0;white-space:nowrap}.excel-file .s-no{min-width:25px;background-color:#efefef;position:sticky;left:-1.5px;text-align:center;z-index:1}.excel-file table{table-layout:fixed}.excel-file .main-selected{background-color:#87ceeb33;border:2px solid skyblue}.excel-file td div{outline:none;border:none;width:auto;padding:5px;background-color:transparent;min-height:10px}.excel-file table,.excel-file td,.excel-file th{border:1.5px solid #d9d9d9;border-collapse:collapse}.excel-file table .header,.excel-file td .header,.excel-file th .header{background-color:#efefef;position:sticky;top:-1.5px;z-index:2;padding:2px}.excel-file .empty-data{width:100%;height:100%;display:flex;justify-content:center;align-items:center}.excel-file .footer{position:absolute;bottom:0;left:0;right:0;min-height:30px;z-index:5;padding:5px;background-color:#efefef;border-top:1.5px solid lightgray;overflow-x:auto;display:flex;align-items:center}.excel-file .footer .sheet{display:inline-block;position:relative;padding:5px;margin:5px 2px;border-radius:3px;cursor:pointer;transition:all .3s ease;white-space:nowrap}.excel-file .footer .sheet.active,.excel-file .footer .sheet:hover{margin:5px;background-color:#fff;box-shadow:0 0 5px #0003}::-webkit-scrollbar{width:8px;height:8px}::-webkit-scrollbar-track{background:#f1f1f1}::-webkit-scrollbar-thumb{background:#888;border-radius:5px}::-webkit-scrollbar-thumb:hover{background:#555}.lds-spinner{color:official;display:inline-block;position:relative;width:80px;height:80px}.lds-spinner div{transform-origin:40px 40px;animation:lds-spinner 1.2s linear infinite}.lds-spinner div:after{content:\" \";display:block;position:absolute;top:3px;left:37px;width:6px;height:18px;border-radius:20%;background:#fff}.lds-spinner div:nth-child(1){transform:rotate(0);animation-delay:-1.1s}.lds-spinner div:nth-child(2){transform:rotate(30deg);animation-delay:-1s}.lds-spinner div:nth-child(3){transform:rotate(60deg);animation-delay:-.9s}.lds-spinner div:nth-child(4){transform:rotate(90deg);animation-delay:-.8s}.lds-spinner div:nth-child(5){transform:rotate(120deg);animation-delay:-.7s}.lds-spinner div:nth-child(6){transform:rotate(150deg);animation-delay:-.6s}.lds-spinner div:nth-child(7){transform:rotate(180deg);animation-delay:-.5s}.lds-spinner div:nth-child(8){transform:rotate(210deg);animation-delay:-.4s}.lds-spinner div:nth-child(9){transform:rotate(240deg);animation-delay:-.3s}.lds-spinner div:nth-child(10){transform:rotate(270deg);animation-delay:-.2s}.lds-spinner div:nth-child(11){transform:rotate(300deg);animation-delay:-.1s}.lds-spinner div:nth-child(12){transform:rotate(330deg);animation-delay:0s}@keyframes lds-spinner{0%{opacity:1}to{opacity:0}}\n"] }]
}], ctorParameters: function () { return []; }, propDecorators: { id: [{
type: Input
}], data: [{
type: Input
}], sheetNames: [{
type: Input
}], editable: [{
type: Input
}], events: [{
type: Input
}], saveDataOutput: [{
type: Input
}], onDataSave: [{
type: Output
}], onScrollEnd: [{
type: Output
}], onKeyPress: [{
type: HostListener,
args: ['keypress', ['$event']]
}], onKeyDown: [{
type: HostListener,
args: ['keydown', ['$event']]
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWV4Y2VsLXZpZXdlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZXhjZWwtdmlld2VyL3NyYy9saWIvbmd4LWV4Y2VsLXZpZXdlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtZXhjZWwtdmlld2VyL3NyYy9saWIvbmd4LWV4Y2VsLXZpZXdlci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFxQixNQUFNLEVBQWlCLE1BQU0sZUFBZSxDQUFDOzs7QUFRdkgsTUFBTSxPQUFPLHVCQUF1QjtJQXFCbEM7UUFwQlMsT0FBRSxHQUFXLEVBQUUsQ0FBQztRQUVoQixlQUFVLEdBQWEsRUFBRSxDQUFDO1FBQzFCLGFBQVEsR0FBWSxLQUFLLENBQUM7UUFDMUIsV0FBTSxHQUFnQyxJQUFJLENBQUM7UUFDM0MsbUJBQWMsR0FBK0IsVUFBVSxDQUFDO1FBQ3ZELGVBQVUsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO1FBQ3JDLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztRQUN6QyxxQkFBZ0IsR0FBRyxFQUFFLENBQUM7UUFDdEIsaUJBQVksR0FBRyxDQUFDLENBQUM7UUFDakIsd0JBQW1CLEdBQXFCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCw2QkFBd0IsR0FBRyxLQUFLLENBQUM7UUFDakMsWUFBTyxHQUFhLEVBQUUsQ0FBQztRQUN2QixjQUFTLEdBQVUsRUFBRSxDQUFDO1FBQ3RCLHVCQUFrQixHQUFHLEtBQUssQ0FBQztRQUMxQixvQkFBZSxHQUFVLEVBQUUsQ0FBQztRQUM3QixpQkFBWSxHQUFhLEVBQUUsQ0FBQztRQUMzQixrQkFBYSxHQUFHLENBQUMsQ0FBQztRQUNsQixrQkFBYSxHQUFH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RyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBQ0ksVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxXQUFXO3NCQUFwQixNQUFNO2dCQTZJUCxVQUFVO3NCQURULFlBQVk7dUJBQUMsVUFBVSxFQUFFLENBQUMsUUFBUSxDQUFDO2dCQWtCcEMsU0FBUztzQkFEUixZQUFZO3VCQUFDLFNBQVMsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkNoYW5nZXMsIE9uSW5pdCwgT3V0cHV0LCBTaW1wbGVDaGFuZ2VzIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBCZWhhdmlvclN1YmplY3QgfSBmcm9tICdyeGpzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbmd4LWV4Y2VsLXZpZXdlcicsXG4gIHRlbXBsYXRlVXJsOiAnbmd4LWV4Y2VsLXZpZXdlci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWyduZ3gtZXhjZWwtdmlld2VyLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgTmd4RXhjZWxWaWV3ZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcyB7XG4gIEBJbnB1dCgpIGlkOiBzdHJpbmcgPSBcIlwiO1xuICBASW5wdXQoKSBkYXRhOiBhbnk7XG4gIEBJbnB1dCgpIHNoZWV0TmFtZXM6IHN0cmluZ1tdID0gW107XG4gIEBJbnB1dCgpIGVkaXRhYmxlOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpIGV2ZW50czogQmVoYXZpb3JTdWJqZWN0PGFueT4gfCBudWxsID0gbnVsbDtcbiAgQElucHV0KCkgc2F2ZURhdGFPdXRwdXQ6IFwiY29tcGxldGVcIiB8IFwiZWRpdGVkLW9ubHlcIiA9IFwiY29tcGxldGVcIjtcbiAgQE91dHB1dCgpIG9uRGF0YVNhdmUgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgQE91dHB1dCgpIG9uU2Nyb2xsRW5kID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIHB1YmxpYyBjdXJyZW50U2hlZXROYW1lID0gXCJcIjtcbiAgcHVibGljIG1heE9mQ29sdW1ucyA9IDA7XG4gIHB1YmxpYyBzZWxlY3RlZENlbGxJbmRpY2VzOiBbbnVtYmVyLCBudW1iZXJdID0gWy0xLCAtMV07XG4gIHB1YmxpYyBpc0VkaXRpbmdUaGVTZWxlY3RlZENlbGwgPSBmYWxzZTtcbiAgcHVibGljIGhlYWRlcnM6IHN0cmluZ1tdID0gW107XG4gIHB1YmxpYyBzaGVldERhdGE6IGFueVtdID0gW107XG4gIHB1YmxpYyBpc1NoZWV0RGF0YUNoYW5nZWQgPSBmYWxzZTtcbiAgcHJpdmF0ZSBiYWNrdXBTaGVldERhdGE6IGFueVtdID0gW107XG4gIHB1YmxpYyBtb2RpZmllZFJvd3M6IG51bWJlcltdID0gW107XG4gIHByaXZhdGUgcmVuZGVyZWRQYWdlcyA9IDE7XG4gIHByaXZhdGUgbGFzdFNjcm9sbFRvcCA9IDA7XG4gIHB1YmxpYyBsb2FkaW5nID0gZmFsc2U7XG4gIGNvbnN0cnVjdG9yKCkgeyB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGF0YSAhPSBudWxsKSB7XG4gICAgICB0aGlzLmN1cnJlbnRTaGVldE5hbWUgPSB0aGlzLnNoZWV0TmFtZXNbMF07XG4gICAgICBpZiAodGhpcy5kYXRhW3RoaXMuY3VycmVudFNoZWV0TmFtZV0pIHtcbiAgICAgICAgdGhpcy5ydW4oKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKHRoaXMuZXZlbnRzICE9IG51bGwpIHtcbiAgICAgIHRoaXMuZXZlbnRzLnN1YnNjcmliZShldmVudCA9PiB7XG4gICAgICAgIGlmIChldmVudC5pZCA9PSB0aGlzLmlkKSB7XG4gICAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT0gXCJjYW5jZWxcIikge1xuICAgICAgICAgICAgdGhpcy5zaGVldERhdGEgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHRoaXMuYmFja3VwU2hlZXREYXRhKSk7XG4gICAgICAgICAgICB0aGlzLmlzU2hlZXREYXRhQ2hhbmdlZCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5tb2RpZmllZFJvd3MgPSBbXTtcbiAgICAgICAgICB9IGVsc2UgaWYgKGV2ZW50LnR5cGUgPT0gXCJzYXZlXCIpIHtcbiAgICAgICAgICAgIGlmKHRoaXMuc2F2ZURhdGFPdXRwdXQgPT0gXCJjb21wbGV0ZVwiKXtcbiAgICAgICAgICAgICAgdGhpcy5vbkRhdGFTYXZlLmVtaXQoe2lkOiB0aGlzLmlkLCBzaGVldDogdGhpcy5jdXJyZW50U2hlZXROYW1lLCBkYXRhOiB0aGlzLnNoZWV0RGF0YS5tYXAoKHJvdzogYW55KSA9PiByb3dbJ3ZhbHVlJ10pfSk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxldCBwYXlsb2FkOiBhbnkgPSB7fTtcbiAgICAgICAgICAgIGZvciAobGV0IHJvd0luZGV4IG9mIHRoaXMubW9kaWZpZWRSb3dzKSB7XG4gICAgICAgICAgICAgIHBheWxvYWRbYCR7cm93SW5kZXggKyAxfWBdID0gdGhpcy5zaGVldERhdGFbcm93SW5kZXhdLm1hcCgocm93OiBhbnkpID0+IHJvd1sndmFsdWUnXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm9uRGF0YVNhdmUuZW1pdCh7IGlkOiB0aGlzLmlkLCBzaGVldDogdGhpcy5jdXJyZW50U2hlZXROYW1lLCBkYXRhOiBwYXlsb2FkIH0pO1xuICAgICAgICAgIH0gZWxzZSBpZiAoZXZlbnQudHlwZSA9PSBcInNhdmVkXCIpIHtcbiAgICAgICAgICAgIGZvciAobGV0IHJvd0luZGV4IG9mIHRoaXMubW9kaWZpZWRSb3dzKSB7XG4gICAgICAgICAgICAgIHRoaXMuZGF0YVtyb3dJbmRleF0gPSB0aGlzLnNoZWV0RGF0YVtyb3dJbmRleF0ubWFwKChyb3c6IGFueSkgPT4gcm93Wyd2YWx1ZSddKTtcbiAgICAgICAgICAgICAgdGhpcy5iYWNrdXBTaGVldERhdGFbcm93SW5kZXhdID0gdGhpcy5zaGVldERhdGFbcm93SW5kZXhdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAoZXZlbnQudHlwZSA9PSBcIm5ld19kYXRhXCIpIHtcbiAgICAgICAgICAgIHRoaXMucnVuKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIHJ1bigpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5jYWxjdWxhdGVNYXhDb2x1bW5zKCk7XG4gICAgICB0aGlzLmdlbmVyYXRlSGVhZGVycygpO1xuICAgICAgdGhpcy5nZW5lcmF0ZVNoZWV0RGF0YSgpO1xuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xuICAgICAgfSwgMTAwKVxuICAgIH0sIDEwMCk7XG5cbiAgfVxuXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcbiAgICBpZiAoY2hhbmdlc1snZGF0YSddICYmIGNoYW5nZXNbJ2RhdGEnXS5wcmV2aW91c1ZhbHVlICE9IGNoYW5nZXNbJ2RhdGEnXS5jdXJyZW50VmFsdWUpIHtcbiAgICAgIHRoaXMucnVuKCk7XG4gICAgfVxuICB9XG5cbiAgY2FsY3VsYXRlTWF4Q29sdW1ucygpIHtcbiAgICB0aGlzLm1heE9mQ29sdW1ucyA9IDA7XG4gICAgaWYgKHRoaXMuZGF0YVt0aGlzLmN1cnJlbnRTaGVldE5hbWVdKSB7XG4gICAgICBmb3IgKGxldCByb3cgb2YgdGhpcy5kYXRhW3RoaXMuY3VycmVudFNoZWV0TmFtZV0pIHtcbiAgICAgICAgaWYgKHJvdy5sZW5ndGggPiB0aGlzLm1heE9mQ29sdW1ucykge1xuICAgICAgICAgIHRoaXMubWF4T2ZDb2x1bW5zID0gcm93Lmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdlbmVyYXRlSGVhZGVycygpIHtcbiAgICBsZXQgaGVhZGVyczogc3RyaW5nW10gPSBbXTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubWF4T2ZDb2x1bW5zOyBpKyspIHtcbiAgICAgIGxldCBoZWFkZXIgPSBcIlwiO1xuICAgICAgbGV0IG51bSA9IGk7XG4gICAgICB3aGlsZSAobnVtID49IDApIHtcbiAgICAgICAgbGV0IHJlbWFpbmRlciA9IG51bSAlIDI2O1xuICAgICAgICBoZWFkZXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKDY1ICsgcmVtYWluZGVyKSArIGhlYWRlcjtcbiAgICAgICAgbnVtID0gTWF0aC5mbG9vcihudW0gLyAyNikgLSAxO1xuICAgICAgfVxuICAgICAgaGVhZGVycy5wdXNoKGhlYWRlcik7XG4gICAgfVxuICAgIHRoaXMuaGVhZGVycyA9IGhlYWRlcnM7XG4gIH1cblxuICBnZW5lcmF0ZVNoZWV0RGF0YSgpIHtcbiAgICBpZih0aGlzLmRhdGFbdGhpcy5jdXJyZW50U2hlZXROYW1lXSl7XG4gICAgICB0aGlzLnNoZWV0RGF0YSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkodGhpcy5kYXRhW3RoaXMuY3VycmVudFNoZWV0TmFtZV0ubWFwKChyb3c6IGFueSkgPT4gcm93Lm1hcCgocjogYW55KSA9PiAoe1widmFsdWVcIjogcn0pKSkpKTtcbiAgICAgIHRoaXMuYmFja3VwU2hlZXREYXRhID0gSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSh0aGlzLnNoZWV0RGF0YSkpO1xuICAgIH1lbHNle1xuICAgICAgdGhpcy5zaGVldERhdGEgPSBbXTtcbiAgICAgIHRoaXMuYmFja3VwU2hlZXREYXRhID0gW107XG4gICAgfVxuICB9XG5cbiAgc2V0U2VsZWN0ZWRTaGVldE5hbWUoc2hlZXQ6IHN0cmluZykge1xuICAgIGlmICh0aGlzLmlzU2hlZXREYXRhQ2hhbmdlZCkge1xuICAgICAgYWxlcnQoXCJTYXZlIHNoZWV0IGJlZm9yZSBzd2l0Y2hpbmdcIik7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuY3VycmVudFNoZWV0TmFtZSA9IHNoZWV0O1xuICAgIHRoaXMucnVuKCk7XG4gIH1cblxuICBzZWxlY3RDZWxsKGk6IG51bWJlciwgajogbnVtYmVyKSB7XG4gICAgaWYgKCh0aGlzLnNlbGVjdGVkQ2VsbEluZGljZXNbMF0gPT0gaSAmJiB0aGlzLnNlbGVjdGVkQ2VsbEluZGljZXNbMV0gPT0gaikgfHwgKGkgPiB0aGlzLnNoZWV0RGF0YS5sZW5ndGggLSAxIHx8IGogPiB0aGlzLm1heE9mQ29sdW1ucyAtIDEpKSB7XG4gICAgICAoZG9jdW1lbnQucXVlcnlTZWxlY3RvcihgI2lucHV0LSR7dGhpcy5zZWxlY3RlZENlbGxJbmRpY2VzWzBdfS0ke3RoaXMuc2VsZWN0ZWRDZWxsSW5kaWNlc1sxXX1gKSBhcyBhbnkpLmZvY3VzKClcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaSA9IGkgPj0gMCA/IGkgOiAwO1xuICAgIGogPSBqID49IDAgPyBqIDogMDtcbiAgICB0aGlzLnNlbGVjdGVkQ2VsbEluZGljZXMgPSBbaSwgal07XG4gICAgKGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYCNpbnB1dC0ke2l9LSR7an1gKSBhcyBhbnkpLmZvY3VzKClcbiAgfVxuXG4gIG9uRGF0YUNoYW5nZXMoZXZlbnQ6IGFueSwgaTogbnVtYmVyLCBqOiBudW1iZXIpIHtcbiAgICBpZiAoIXRoaXMuZWRpdGFibGUpIHJldHVybjtcbiAgICBpZiAodGhpcy5iYWNrdXBTaGVldERhdGFbaV1bal1bXCJ2YWx1ZVwiXSAhPSBldmVudC50YXJnZXQuaW5uZXJUZXh0KSB7XG4gICAgICB0aGlzLnNoZWV0RGF0YVtpXVtqXVtcInZhbHVlXCJdID0gZXZlbnQudGFyZ2V0LmlubmVyVGV4dDtcbiAgICAgIGlmICghdGhpcy5tb2RpZmllZFJvd3MuaW5jbHVkZXMoaSkpIHtcbiAgICAgICAgdGhpcy5tb2RpZmllZFJvd3MucHVzaChpKTtcbiAgICAgIH1cbiAgICAgIGlmICghdGhpcy5pc1NoZWV0RGF0YUNoYW5nZWQpIHtcbiAgICAgICAgdGhpcy5pc1NoZWV0RGF0YUNoYW5nZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2tleXByZXNzJywgWyckZXZlbnQnXSlcbiAgb25LZXlQcmVzcyhldmVudDogYW55KSB7XG4gICAgaWYgKGV2ZW50LndoaWNoID09IDEzKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cbiAgfVxuXG4gIG9uU2Nyb2xsKGV2ZW50OiBhbnkpIHtcbiAgICBpZiAoZXZlbnQudGFyZ2V0LnNjcm9sbFRvcCA+IHRoaXMubGFzdFNjcm9sbFRvcCkge1xuICAgICAgaWYgKChldmVudC50YXJnZXQub2Zmc2V0SGVpZ2h0ICsgZXZlbnQudGFyZ2V0LnNjcm9sbFRvcCkgPj0gZXZlbnQudGFyZ2V0LnNjcm9sbEhlaWdodCkge1xuICAgICAgICB0aGlzLm9uU2Nyb2xsRW5kLmVtaXQoeyBpZDogdGhpcy5pZCwgcGFnZU5vOiB0aGlzLnJlbmRlcmVkUGFnZXMrKywgc2hlZXQ6IHRoaXMuY3VycmVudFNoZWV0TmFtZSB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5sYXN0U2Nyb2xsVG9wID0gZXZlbnQudGFyZ2V0LnNjcm9sbFRvcDtcbiAgfVxuXG5cbiAgQEhvc3RMaXN0ZW5lcigna2V5ZG93bicsIFsnJGV2ZW50J10pXG4gIG9uS2V5RG93bihldmVudDogYW55KSB7XG4gICAgaWYgKGV2ZW50LmtleT8uaW5jbHVkZXMoXCJBcnJvd1wiKSkge1xuICAgICAgY29uc3Qga2V5ID0gZXZlbnQua2V5O1xuICAgICAgbGV0IGkgPSB0aGlzLnNlbGVjdGVkQ2VsbEluZGljZXNbMF07XG4gICAgICBsZXQgaiA9IHRoaXMuc2VsZWN0ZWRDZWxsSW5kaWNlc1sxXTtcbiAgICAgIGV2ZW50LnRhcmdldC5ibHVyKCk7XG4gICAgICBpZiAoa2V5ID09IFwiQXJyb3dVcFwiKSB7XG4gICAgICAgIGktLTtcbiAgICAgIH0gZWxzZSBpZiAoa2V5ID09IFwiQXJyb3dEb3duXCIpIHtcbiAgICAgICAgaSsrO1xuICAgICAgfSBlbHNlIGlmIChrZXkgPT0gXCJBcnJvd0xlZnRcIikge1xuICAgICAgICBpZiAod2luZG93LmdldFNlbGVjdGlvbigpPy5hbmNob3JPZmZzZXQgPT0gMCkgai0tO1xuICAgICAgfSBlbHNlIGlmIChrZXkgPT0gXCJBcnJvd1JpZ2h0XCIpIHtcbiAgICAgICAgaWYgKCh3aW5kb3cuZ2V0U2VsZWN0aW9uKCk/LmFuY2hvck9mZnNldCA/PyAwKSA+PSBldmVudC50YXJnZXQuaW5uZXJUZXh0Lmxlbmd0aCkgaisrO1xuICAgICAgfVxuICAgICAgdGhpcy5zZWxlY3RDZWxsKGksIGopO1xuICAgIH1cbiAgfVxuXG5cbn1cbiIsIjxkaXYgY2xhc3M9XCJleGNlbC1maWxlXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwic2Nyb2xsYWJsZVwiIChzY3JvbGwpPVwib25TY3JvbGwoJGV2ZW50KVwiPlxyXG4gICAgICAgIDx0YWJsZSAqbmdJZj1cInNoZWV0RGF0YS5sZW5ndGggIT0gMFwiPlxyXG4gICAgICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICAgICAgICA8dHI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRoIGNsYXNzPVwiaGVhZGVyIHMtbm9cIj48L3RoPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0aCBjbGFzcz1cImhlYWRlclwiICpuZ0Zvcj1cImxldCBoZWFkZXIgb2YgaGVhZGVyc1wiPnt7aGVhZGVyfX08L3RoPlxyXG4gICAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgPC90aGVhZD5cclxuICAgICAgICAgICAgPHRib2R5PlxyXG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImN1cnJlbnRTaGVldE5hbWUgJiYgZGF0YVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0ciAqbmdGb3I9XCJsZXQgZGF0YSBvZiBzaGVldERhdGE7IGxldCBpPWluZGV4XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBjbGFzcz1cInMtbm9cIj57e2krMX19PC90ZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkICpuZ0Zvcj1cImxldCBjZWxsIG9mIGRhdGE7IGxldCBqPWluZGV4XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsnbWFpbi1zZWxlY3RlZCc6IHNlbGVjdGVkQ2VsbEluZGljZXNbMF0gPT0gaSAmJiBzZWxlY3RlZENlbGxJbmRpY2VzWzFdID09IGp9XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RDZWxsKGksailcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgW2lkXT1cIidpbnB1dC0nK2krJy0nK2pcIiAoYmx1cik9XCJvbkRhdGFDaGFuZ2VzKCRldmVudCwgaSwgailcIiAoZm9jdXMpPVwic2VsZWN0Q2VsbChpLGopXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY29udGVudEVkaXRhYmxlXT1cImVkaXRhYmxlXCIgW2lubmVySFRNTF09XCJjZWxsWyd2YWx1ZSddXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8L3Rib2R5PlxyXG4gICAgICAgIDwvdGFibGU+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJlbXB0eS1kYXRhXCIgKm5nSWY9XCJzaGVldERhdGEubGVuZ3RoID09IDBcIj5cclxuICAgICAgICBFbXB0eSBTaGVldFxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiZm9vdGVyXCI+XHJcbiAgICAgICAgU2hlZXRzOiA8ZGl2ICpuZ0Zvcj1cImxldCBzaGVldCBvZiBzaGVldE5hbWVzXCIgY2xhc3M9XCJzaGVldFwiIFtuZ0NsYXNzXT1cInsnYWN0aXZlJzogY3VycmVudFNoZWV0TmFtZSA9PSBzaGVldH1cIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwic2V0U2VsZWN0ZWRTaGVldE5hbWUoc2hlZXQpXCI+e3tzaGVldH19PC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nXCIgKm5nSWY9XCJsb2FkaW5nXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNwaW5uZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxkcy1zcGlubmVyXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2PjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXY+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2PjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXY+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2PjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXY+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2PjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXY+PC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PiJdfQ==