UNPKG

bootstrangular-datatable

Version:

Este es un simple modulo de tabla interactiva al estilo de Angular, Bootstrap y Datatable. Necesita angular/core, bootstrap y sus dependencias (jquery y popper) para funcionar.

148 lines 24.5 kB
import { Component, Input } from '@angular/core'; export class DatatableComponent { constructor() { this.pageSizeOptions = []; this.pageIndex = 1; this.showNumeration = false; this.showSearcher = true; this.showSizeOptions = true; this.showPaginator = true; } ngOnInit() { this.checkPageSize(); } /** Obtener fuente de datos * @description Devuelve los datos filtrados en caso de que `filterText` tenga * valor, de lo contrario devuelve el total de datos. */ getDataSource() { return this.filterText ? this.dataSourceFilter : this.dataSource; } /** Obtener datos por página * @description Devuelve los datos por tamaño de página (número de renglones) * dependiendo del índice de página del que se encuentre. */ getPageData() { return this.getDataSource().slice(this.getPageRowStart() - 1, this.getPageRowEnd()); } /** Obtener el renglón inicial por página * @description Devuelve el numero del renglón inicial de la página actual. */ getPageRowStart() { return (this.pageSize * this.pageIndex) - (this.pageSize - 1); } /** Obtener el renglón final por página * @description Devuelve el numero del renglón final de la página actual. */ getPageRowEnd() { if (this.pageIndex === this.getLastPage()) return this.getPageRowStart() + (this.getDataSource().length - this.getPageRowStart()); else return this.pageSize * this.pageIndex; } /** Ir a la primer página */ goFirstPage() { this.pageIndex = 1; } /** Ir a la página anterior */ goPreviousPage() { this.pageIndex--; } /** Ir a la siguiente página */ goNextPage() { this.pageIndex++; } /** Ir a la ultima página */ goLastPage() { this.pageIndex = this.getLastPage(); } /** Obtener ultima página * @description Devuelve el índice de la ultima página de los datos disponibles * calculado por el tamaño de datos por página. */ getLastPage() { if (this.getDataSource().length % this.pageSize !== 0) return Math.floor(this.getDataSource().length / this.pageSize) + 1; else return Math.floor(this.getDataSource().length / this.pageSize); } /** Cambiar tamaño de página * @description Cambia el tamaño de renglones de la tabla por página vinculado * con el índice de la página actual para no rebasar el total de datos por página. * @param size Valor para el nuevo tamaño de página. */ changePageSize(size) { const isInLastPage = this.pageIndex === this.getLastPage() ? true : false; this.pageSize = size; if (this.pageIndex >= this.getLastPage() || isInLastPage) this.goLastPage(); } /** Revisar tamaño de página * @description Verifica si `pageSize` está vacío, en tal caso se le asignará * el primer valor de la lista de opciones. En caso de que la lista de opciones * también se encuentre vacía, agrega el total de los datos como valor único. */ checkPageSize() { if (!this.pageSize) { if (!this.pageSizeOptions.length) this.pageSizeOptions.push(this.dataSource.length); this.pageSize = this.pageSizeOptions[0]; } else if (!this.pageSizeOptions.find((op) => op === this.pageSize)) { this.addPageSizeToPageSizeOptions(); } } /** Añadir tamaño de página * @description Añade a la lista de opciones de tamaño de pagina el tamaño * de pagina `pageSize` que llegue como parámetro. */ addPageSizeToPageSizeOptions() { this.pageSizeOptions.push(this.pageSize); this.pageSizeOptions.sort((a, b) => a - b); } /** Obtener encabezados * @description Obtiene los encabezados de la tabla, en caso de que no se * definan como parámetro, devolverá una lista de las llaves de la primer fila. */ getHeaders() { if (this.headers) return Object.keys(this.headers).map((item) => { return { id: item, value: this.headers[item] }; }); else return Object.keys(this.dataSource[1]).map((item) => { return { id: item, value: item }; }); } /** Aplicar filtro * @description Guarda en `filterText` lo escrito en la caja de búsqueda y * guarda en `dataSourceFilter` el filtro aplicado en los datos. * @param filter Texto escrito en la caja de búsqueda. */ applyFilter(filter) { if (filter.trim()) { this.filterText = filter.trim().toLowerCase(); this.dataSourceFilter = this.dataSource.filter((item) => { return this.getHeaders().map((head) => item[head.id].trim().toLowerCase().includes(this.filterText)).some((element) => element); }); if (this.pageIndex > this.getLastPage()) this.goLastPage(); } else { this.filterText = undefined; this.goFirstPage(); } } } DatatableComponent.decorators = [ { type: Component, args: [{ selector: 'datatable', template: "<div class=\"row\">\n <div class=\"col-md-6\">\n <div *ngIf=\"tableBtnOptions\" class=\"btn-group btn-group-sm mr-2 mb-2\" role=\"group\">\n <button *ngFor=\"let btnTable of tableBtnOptions\"\n (click)=\"btnTable.action()\"\n type=\"button\"\n class=\"btn btn-secondary\"\n data-toggle=\"tooltip\"\n data-placement=\"bottom\"\n [title]=\"btnTable.title\">\n <div *ngIf=\"btnTable.icon; then btnTableIcon; else btnTableTitle\"></div>\n <ng-template #btnTableIcon>\n <i *ngIf=\"btnTable.icon.origin === 'bootstrap'\" [class]=\"btnTable.icon.icon\"></i>\n <img *ngIf=\"btnTable.icon.origin === 'img'\" [attr.src]=\"btnTable.icon.icon\" class=\"img-icon\">\n </ng-template>\n <ng-template #btnTableTitle>{{btnTable.title}}</ng-template>\n </button>\n </div>\n </div>\n <div class=\"col-md-6\">\n <div *ngIf=\"showSearcher\" class=\"input-group input-group-sm mb-2\">\n <div class=\"input-group-prepend\">\n <div class=\"input-group-text\" id=\"btnGroupAddon\">\uD83D\uDD0E</div>\n </div>\n <input type=\"text\" class=\"form-control\"\n placeholder=\"Buscar en la tabla\" aria-label=\"Buscar en la tabla\"\n (keyup)=\"applyFilter($event.target.value)\">\n </div>\n </div>\n</div>\n\n<div class=\"table-responsive\">\n <table class=\"table table-bordered table-sm table-striped\">\n <thead>\n <tr>\n <th *ngIf=\"showNumeration\">#<!--span class=\"text-muted float-right\">\u2B07\uFE0F\u2B06\uFE0F</span--></th>\n <th *ngFor=\"let head of getHeaders()\">{{head.value}}</th>\n <th *ngIf=\"rowBtnOptions\">\u2699\uFE0F</th>\n </tr>\n </thead>\n <tbody>\n <tr *ngFor=\"let row of getPageData(); let i = index\">\n <td *ngIf=\"showNumeration\">{{i + getPageRowStart()}}</td>\n <td *ngFor=\"let key of getHeaders()\">{{row[key.id]}}</td>\n <th *ngIf=\"rowBtnOptions\">\n <div class=\"row\" style=\"margin: auto;\">\n <div *ngFor=\"let btnRow of rowBtnOptions\"\n (click)=\"btnRow.action(row)\"\n class=\"btn-row\">\n <div *ngIf=\"btnRow.icon; then btnRowIcon; else btnRowTitle\"></div>\n <ng-template #btnRowIcon>\n <i *ngIf=\"btnRow.icon.origin === 'bootstrap'\" [class]=\"btnRow.icon.icon\"\n data-toggle=\"tooltip\" data-placement=\"bottom\" [title]=\"btnRow.title\"></i>\n <img *ngIf=\"btnRow.icon.origin === 'img'\" [attr.src]=\"btnRow.icon.icon\" class=\"img-icon\"\n data-toggle=\"tooltip\" data-placement=\"bottom\" [title]=\"btnRow.title\">\n </ng-template>\n <ng-template #btnRowTitle>\n <small>{{btnRow.title}}</small>\n </ng-template>\n </div>\n </div>\n </th>\n </tr>\n </tbody>\n </table>\n</div>\n\n<div class=\"row\">\n <div class=\"col-sm-6\">\n <div *ngIf=\"showSizeOptions\"\n class=\"input-group input-group-sm mr-2 mb-2 select-page-size\">\n <div class=\"input-group-prepend\">\n <label class=\"input-group-text\" for=\"\">Renglones por p\u00E1gina</label>\n </div>\n <select class=\"custom-select\" (change)=\"changePageSize($event.target.value)\">\n <option *ngFor=\"let option of pageSizeOptions\"\n [value]=\"option\"\n [selected]=\"option === pageSize? 'selected': null\">\n {{option}}\n </option>\n </select>\n </div>\n </div>\n <div class=\"col-sm-6\">\n <nav *ngIf=\"showPaginator\">\n <ul class=\"pagination pagination-sm justify-content-end\">\n <li class=\"page-item\">\n <span class=\"page-link paginator-label\">\n {{getPageRowStart()}} - {{getPageRowEnd()}} de {{this.getDataSource().length}}\n </span>\n </li>\n <li class=\"page-item\" [ngClass]=\"{'disabled': pageIndex === 1}\">\n <a class=\"page-link\" href=\"javascript:void(0);\" (click)=\"goFirstPage()\">\n <span aria-hidden=\"true\">[&laquo;</span>\n </a>\n </li>\n <li class=\"page-item\" [ngClass]=\"{'disabled': pageIndex === 1}\">\n <a class=\"page-link\" href=\"javascript:void(0);\" (click)=\"goPreviousPage()\">\n <span aria-hidden=\"true\">&laquo;</span>\n </a>\n </li>\n <li class=\"page-item\"><span class=\"page-link paginator-label\">{{pageIndex}}</span></li>\n <li class=\"page-item\" [ngClass]=\"{'disabled': pageIndex === getLastPage()}\">\n <a class=\"page-link\" href=\"javascript:void(0);\" (click)=\"goNextPage()\">\n <span aria-hidden=\"true\">&raquo;</span>\n </a>\n </li>\n <li class=\"page-item\" [ngClass]=\"{'disabled': pageIndex === getLastPage()}\">\n <a class=\"page-link\" href=\"javascript:void(0);\" (click)=\"goLastPage()\">\n <span aria-hidden=\"true\">&raquo;]</span>\n </a>\n </li>\n </ul>\n </nav>\n </div>\n</div>", styles: [".select-page-size{width:250px}.paginator-label{background-color:#e9ecef!important;border:1px solid #ced4da!important}.page-link,.paginator-label{color:#495057!important}.img-icon{max-height:14px;max-width:14px}.btn-row>*{color:#535c68;cursor:pointer;margin-inline:4px}.btn-row>i{max-height:14px;max-width:14px}"] },] } ]; DatatableComponent.ctorParameters = () => []; DatatableComponent.propDecorators = { dataSource: [{ type: Input }], headers: [{ type: Input }], pageSize: [{ type: Input }], pageSizeOptions: [{ type: Input }], pageIndex: [{ type: Input }], tableBtnOptions: [{ type: Input }], rowBtnOptions: [{ type: Input }], showNumeration: [{ type: Input }], showSearcher: [{ type: Input }], showSizeOptions: [{ type: Input }], showPaginator: [{ type: Input }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0YXRhYmxlLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2xpYi9zcmMvbGliL2RhdGF0YWJsZS5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBVSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFPekQsTUFBTSxPQUFPLGtCQUFrQjtJQWlCN0I7UUFiZ0Isb0JBQWUsR0FBYSxFQUFFLENBQUM7UUFDL0IsY0FBUyxHQUFXLENBQUMsQ0FBQztRQUl0QixtQkFBYyxHQUFZLEtBQUssQ0FBQztRQUNoQyxpQkFBWSxHQUFZLElBQUksQ0FBQztRQUM3QixvQkFBZSxHQUFZLElBQUksQ0FBQztRQUNoQyxrQkFBYSxHQUFZLElBQUksQ0FBQztJQUsvQixDQUFDO0lBRWhCLFFBQVE7UUFDTixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVEOzs0REFFd0Q7SUFDakQsYUFBYTtRQUNsQixPQUFPLElBQUksQ0FBQyxVQUFVLENBQUEsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQSxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztJQUNqRSxDQUFDO0lBRUQ7O2dFQUU0RDtJQUNyRCxXQUFXO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxDQUFDO0lBQ3RGLENBQUM7SUFFRDtrRkFDOEU7SUFDdkUsZUFBZTtRQUNwQixPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRDtnRkFDNEU7SUFDckUsYUFBYTtRQUNsQixJQUFJ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QUFDLFdBQVcsRUFBRSxDQUFDO1NBQ3BCO0lBQ0gsQ0FBQzs7O1lBakpGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsV0FBVztnQkFDckIsby9KQUF5Qzs7YUFFMUM7Ozs7eUJBRUUsS0FBSztzQkFDTCxLQUFLO3VCQUNMLEtBQUs7OEJBQ0wsS0FBSzt3QkFDTCxLQUFLOzhCQUNMLEtBQUs7NEJBQ0wsS0FBSzs2QkFFTCxLQUFLOzJCQUNMLEtBQUs7OEJBQ0wsS0FBSzs0QkFDTCxLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBPbkluaXQsIElucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2RhdGF0YWJsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRhdGFibGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9kYXRhdGFibGUuY29tcG9uZW50LnNjc3MnXVxufSlcbmV4cG9ydCBjbGFzcyBEYXRhdGFibGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBASW5wdXQoKSBwcml2YXRlIGRhdGFTb3VyY2U6IGFueVtdO1xuICBASW5wdXQoKSBwdWJsaWMgaGVhZGVyczogYW55O1xuICBASW5wdXQoKSBwdWJsaWMgcGFnZVNpemU6IG51bWJlcjtcbiAgQElucHV0KCkgcHVibGljIHBhZ2VTaXplT3B0aW9uczogbnVtYmVyW10gPSBbXTtcbiAgQElucHV0KCkgcHVibGljIHBhZ2VJbmRleDogbnVtYmVyID0gMTtcbiAgQElucHV0KCkgcHVibGljIHRhYmxlQnRuT3B0aW9uczogQnRuT3B0aW9uW107XG4gIEBJbnB1dCgpIHB1YmxpYyByb3dCdG5PcHRpb25zOiBCdG5PcHRpb25bXTtcblxuICBASW5wdXQoKSBwdWJsaWMgc2hvd051bWVyYXRpb246IGJvb2xlYW4gPSBmYWxzZTtcbiAgQElucHV0KCkgcHVibGljIHNob3dTZWFyY2hlcjogYm9vbGVhbiA9IHRydWU7XG4gIEBJbnB1dCgpIHB1YmxpYyBzaG93U2l6ZU9wdGlvbnM6IGJvb2xlYW4gPSB0cnVlO1xuICBASW5wdXQoKSBwdWJsaWMgc2hvd1BhZ2luYXRvcjogYm9vbGVhbiA9IHRydWU7XG5cbiAgcHJpdmF0ZSBmaWx0ZXJUZXh0OiBzdHJpbmc7XG4gIHByaXZhdGUgZGF0YVNvdXJjZUZpbHRlcjogYW55W107XG5cbiAgY29uc3RydWN0b3IoKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuY2hlY2tQYWdlU2l6ZSgpO1xuICB9XG5cbiAgLyoqIE9idGVuZXIgZnVlbnRlIGRlIGRhdG9zXG4gICAqIEBkZXNjcmlwdGlvbiBEZXZ1ZWx2ZSBsb3MgZGF0b3MgZmlsdHJhZG9zIGVuIGNhc28gZGUgcXVlIGBmaWx0ZXJUZXh0YCB0ZW5nYVxuICAgKiB2YWxvciwgZGUgbG8gY29udHJhcmlvIGRldnVlbHZlIGVsIHRvdGFsIGRlIGRhdG9zLiAqL1xuICBwdWJsaWMgZ2V0RGF0YVNvdXJjZSgpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyVGV4dD8gdGhpcy5kYXRhU291cmNlRmlsdGVyOiB0aGlzLmRhdGFTb3VyY2U7XG4gIH0gXG5cbiAgLyoqIE9idGVuZXIgZGF0b3MgcG9yIHDDoWdpbmFcbiAgICogQGRlc2NyaXB0aW9uIERldnVlbHZlIGxvcyBkYXRvcyBwb3IgdGFtYcOxbyBkZSBww6FnaW5hIChuw7ptZXJvIGRlIHJlbmdsb25lcylcbiAgICogZGVwZW5kaWVuZG8gZGVsIMOtbmRpY2UgZGUgcMOhZ2luYSBkZWwgcXVlIHNlIGVuY3VlbnRyZS4gKi9cbiAgcHVibGljIGdldFBhZ2VEYXRhKCk6IGFueVtdIHtcbiAgICByZXR1cm4gdGhpcy5nZXREYXRhU291cmNlKCkuc2xpY2UodGhpcy5nZXRQYWdlUm93U3RhcnQoKSAtIDEsIHRoaXMuZ2V0UGFnZVJvd0VuZCgpKTtcbiAgfVxuXG4gIC8qKiBPYnRlbmVyIGVsIHJlbmdsw7NuIGluaWNpYWwgcG9yIHDDoWdpbmFcbiAgICogQGRlc2NyaXB0aW9uIERldnVlbHZlIGVsIG51bWVybyBkZWwgcmVuZ2zDs24gaW5pY2lhbCBkZSBsYSBww6FnaW5hIGFjdHVhbC4gKi9cbiAgcHVibGljIGdldFBhZ2VSb3dTdGFydCgpOiBudW1iZXIge1xuICAgIHJldHVybiAodGhpcy5wYWdlU2l6ZSAqIHRoaXMucGFnZUluZGV4KSAtICh0aGlzLnBhZ2VTaXplIC0gMSk7XG4gIH1cblxuICAvKiogT2J0ZW5lciBlbCByZW5nbMOzbiBmaW5hbCBwb3IgcMOhZ2luYVxuICAgKiBAZGVzY3JpcHRpb24gRGV2dWVsdmUgZWwgbnVtZXJvIGRlbCByZW5nbMOzbiBmaW5hbCBkZSBsYSBww6FnaW5hIGFjdHVhbC4gKi9cbiAgcHVibGljIGdldFBhZ2VSb3dFbmQoKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5wYWdlSW5kZXggPT09IHRoaXMuZ2V0TGFzdFBhZ2UoKSkgXG4gICAgcmV0dXJuIHRoaXMuZ2V0UGFnZVJvd1N0YXJ0KCkgKyAodGhpcy5nZXREYXRhU291cmNlKCkubGVuZ3RoIC0gdGhpcy5nZXRQYWdlUm93U3RhcnQoKSk7XG4gICAgZWxzZSByZXR1cm4gdGhpcy5wYWdlU2l6ZSAqIHRoaXMucGFnZUluZGV4O1xuICB9XG5cbiAgLyoqIElyIGEgbGEgcHJpbWVyIHDDoWdpbmEgKi9cbiAgcHVibGljIGdvRmlyc3RQYWdlKCk6IHZvaWQge1xuICAgIHRoaXMucGFnZUluZGV4ID0gMTtcbiAgfVxuXG4gIC8qKiBJciBhIGxhIHDDoWdpbmEgYW50ZXJpb3IgKi9cbiAgcHVibGljIGdvUHJldmlvdXNQYWdlKCk6IHZvaWQge1xuICAgIHRoaXMucGFnZUluZGV4LS07XG4gIH1cblxuICAvKiogSXIgYSBsYSBzaWd1aWVudGUgcMOhZ2luYSAqL1xuICBwdWJsaWMgZ29OZXh0UGFnZSgpOiB2b2lkIHtcbiAgICB0aGlzLnBhZ2VJbmRleCsrO1xuICB9XG5cbiAgLyoqIElyIGEgbGEgdWx0aW1hIHDDoWdpbmEgKi9cbiAgcHVibGljIGdvTGFzdFBhZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5wYWdlSW5kZXggPSB0aGlzLmdldExhc3RQYWdlKCk7XG4gIH1cblxuICAvKiogT2J0ZW5lciB1bHRpbWEgcMOhZ2luYVxuICAgKiBAZGVzY3JpcHRpb24gRGV2dWVsdmUgZWwgw61uZGljZSBkZSBsYSB1bHRpbWEgcMOhZ2luYSBkZSBsb3MgZGF0b3MgZGlzcG9uaWJsZXNcbiAgICogY2FsY3VsYWRvIHBvciBlbCB0YW1hw7FvIGRlIGRhdG9zIHBvciBww6FnaW5hLiAqL1xuICBwdWJsaWMgZ2V0TGFzdFBhZ2UoKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5nZXREYXRhU291cmNlKCkubGVuZ3RoICUgdGhpcy5wYWdlU2l6ZSAhPT0gMClcbiAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmdldERhdGFTb3VyY2UoKS5sZW5ndGggLyB0aGlzLnBhZ2VTaXplKSArIDE7XG4gICAgZWxzZSByZXR1cm4gTWF0aC5mbG9vcih0aGlzLmdldERhdGFTb3VyY2UoKS5sZW5ndGggLyB0aGlzLnBhZ2VTaXplKTtcbiAgfVxuXG4gIC8qKiBDYW1iaWFyIHRhbWHDsW8gZGUgcMOhZ2luYVxuICAgKiBAZGVzY3JpcHRpb24gQ2FtYmlhIGVsIHRhbWHDsW8gZGUgcmVuZ2xvbmVzIGRlIGxhIHRhYmxhIHBvciBww6FnaW5hIHZpbmN1bGFkb1xuICAgKiBjb24gZWwgw61uZGljZSBkZSBsYSBww6FnaW5hIGFjdHVhbCBwYXJhIG5vIHJlYmFzYXIgZWwgdG90YWwgZGUgZGF0b3MgcG9yIHDDoWdpbmEuXG4gICAqIEBwYXJhbSBzaXplIFZhbG9yIHBhcmEgZWwgbnVldm8gdGFtYcOxbyBkZSBww6FnaW5hLiAqL1xuICBwdWJsaWMgY2hhbmdlUGFnZVNpemUoc2l6ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgaXNJbkxhc3RQYWdlOiBib29sZWFuID0gdGhpcy5wYWdlSW5kZXggPT09IHRoaXMuZ2V0TGFzdFBhZ2UoKT8gdHJ1ZTogZmFsc2U7XG4gICAgdGhpcy5wYWdlU2l6ZSA9IHNpemU7XG4gICAgaWYgKHRoaXMucGFnZUluZGV4ID49IHRoaXMuZ2V0TGFzdFBhZ2UoKSB8fCBpc0luTGFzdFBhZ2UpIHRoaXMuZ29MYXN0UGFnZSgpO1xuICB9XG5cbiAgLyoqIFJldmlzYXIgdGFtYcOxbyBkZSBww6FnaW5hXG4gICAqIEBkZXNjcmlwdGlvbiBWZXJpZmljYSBzaSBgcGFnZVNpemVgIGVzdMOhIHZhY8OtbywgZW4gdGFsIGNhc28gc2UgbGUgYXNpZ25hcsOhXG4gICAqIGVsIHByaW1lciB2YWxvciBkZSBsYSBsaXN0YSBkZSBvcGNpb25lcy4gRW4gY2FzbyBkZSBxdWUgbGEgbGlzdGEgZGUgb3BjaW9uZXNcbiAgICogdGFtYmnDqW4gc2UgZW5jdWVudHJlIHZhY8OtYSwgYWdyZWdhIGVsIHRvdGFsIGRlIGxvcyBkYXRvcyBjb21vIHZhbG9yIMO6bmljby4gKi9cbiAgcHJpdmF0ZSBjaGVja1BhZ2VTaXplKCkge1xuICAgIGlmICghdGhpcy5wYWdlU2l6ZSkge1xuICAgICAgaWYgKCF0aGlzLnBhZ2VTaXplT3B0aW9ucy5sZW5ndGgpXG4gICAgICB0aGlzLnBhZ2VTaXplT3B0aW9ucy5wdXNoKHRoaXMuZGF0YVNvdXJjZS5sZW5ndGgpO1xuICAgICAgdGhpcy5wYWdlU2l6ZSA9IHRoaXMucGFnZVNpemVPcHRpb25zWzBdO1xuICAgIH0gZWxzZSBpZiAoIXRoaXMucGFnZVNpemVPcHRpb25zLmZpbmQoKG9wOiBudW1iZXIpID0+IG9wID09PSB0aGlzLnBhZ2VTaXplKSkge1xuICAgICAgdGhpcy5hZGRQYWdlU2l6ZVRvUGFnZVNpemVPcHRpb25zKCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEHDsWFkaXIgdGFtYcOxbyBkZSBww6FnaW5hXG4gICAqIEBkZXNjcmlwdGlvbiBBw7FhZGUgYSBsYSBsaXN0YSBkZSBvcGNpb25lcyBkZSB0YW1hw7FvIGRlIHBhZ2luYSBlbCB0YW1hw7FvIFxuICAgKiBkZSBwYWdpbmEgYHBhZ2VTaXplYCBxdWUgbGxlZ3VlIGNvbW8gcGFyw6FtZXRyby4gKi9cbiAgcHJpdmF0ZSBhZGRQYWdlU2l6ZVRvUGFnZVNpemVPcHRpb25zKCk6IHZvaWQge1xuICAgIHRoaXMucGFnZVNpemVPcHRpb25zLnB1c2godGhpcy5wYWdlU2l6ZSk7XG4gICAgdGhpcy5wYWdlU2l6ZU9wdGlvbnMuc29ydCgoYSwgYikgPT4gYS1iKTtcbiAgfVxuXG4gIC8qKiBPYnRlbmVyIGVuY2FiZXphZG9zXG4gICAqIEBkZXNjcmlwdGlvbiBPYnRpZW5lIGxvcyBlbmNhYmV6YWRvcyBkZSBsYSB0YWJsYSwgZW4gY2FzbyBkZSBxdWUgbm8gc2VcbiAgICogZGVmaW5hbiBjb21vIHBhcsOhbWV0cm8sIGRldm9sdmVyw6EgdW5hIGxpc3RhIGRlIGxhcyBsbGF2ZXMgZGUgbGEgcHJpbWVyIGZpbGEuICovXG4gIHB1YmxpYyBnZXRIZWFkZXJzKCk6IG9iamVjdFtdIHtcbiAgICBpZiAodGhpcy5oZWFkZXJzKSByZXR1cm4gT2JqZWN0LmtleXModGhpcy5oZWFkZXJzKS5tYXAoKGl0ZW0pID0+IHtcbiAgICAgIHJldHVybiB7aWQ6IGl0ZW0sIHZhbHVlOiB0aGlzLmhlYWRlcnNbaXRlbV19XG4gICAgfSk7IGVsc2UgcmV0dXJuIE9iamVjdC5rZXlzKHRoaXMuZGF0YVNvdXJjZVsxXSkubWFwKChpdGVtKSA9PiB7XG4gICAgICByZXR1cm4ge2lkOiBpdGVtLCB2YWx1ZTogaXRlbX1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBBcGxpY2FyIGZpbHRyb1xuICAgKiBAZGVzY3JpcHRpb24gR3VhcmRhIGVuIGBmaWx0ZXJUZXh0YCBsbyBlc2NyaXRvIGVuIGxhIGNhamEgZGUgYsO6c3F1ZWRhIHkgXG4gICAqIGd1YXJkYSBlbiBgZGF0YVNvdXJjZUZpbHRlcmAgZWwgZmlsdHJvIGFwbGljYWRvIGVuIGxvcyBkYXRvcy5cbiAgICogQHBhcmFtIGZpbHRlciBUZXh0byBlc2NyaXRvIGVuIGxhIGNhamEgZGUgYsO6c3F1ZWRhLiAqL1xuICBwdWJsaWMgYXBwbHlGaWx0ZXIoZmlsdGVyOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoZmlsdGVyLnRyaW0oKSkge1xuICAgICAgdGhpcy5maWx0ZXJUZXh0ID0gZmlsdGVyLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgdGhpcy5kYXRhU291cmNlRmlsdGVyID0gdGhpcy5kYXRhU291cmNlLmZpbHRlcigoaXRlbTogYW55KSA9PiB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEhlYWRlcnMoKS5tYXAoKGhlYWQ6IGFueSkgPT4gXG4gICAgICAgICAgaXRlbVtoZWFkLmlkXS50cmltKCkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyh0aGlzLmZpbHRlclRleHQpXG4gICAgICAgICkuc29tZSgoZWxlbWVudDogYW55KSA9PiBlbGVtZW50KTtcbiAgICAgIH0pO1xuICAgICAgaWYgKHRoaXMucGFnZUluZGV4ID4gdGhpcy5nZXRMYXN0UGFnZSgpKSB0aGlzLmdvTGFzdFBhZ2UoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5maWx0ZXJUZXh0ID0gdW5kZWZpbmVkO1xuICAgICAgdGhpcy5nb0ZpcnN0UGFnZSgpO1xuICAgIH1cbiAgfVxufVxuXG4vKiogQnV0dG9uIE9wdGlvblxuICogQHBhcmFtIHRpdGxlIFRpdHVsbyBkZWwgYm90b24uXG4gKiBAcGFyYW0gYWN0aW9uIEZ1bmNpb24gZGVsIGJvdG9uLlxuICogQHBhcmFtIGljb24gSW50ZXJmYWNlIEJ1dHRvbiBJY29uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBCdG5PcHRpb24ge1xuICB0aXRsZTogc3RyaW5nLFxuICBhY3Rpb246IEZ1bmN0aW9uLFxuICBpY29uPzogQnRuSWNvblxufVxuXG4vKiogQnV0dG9uIEljb25cbiAqIEBwYXJhbSBvcmlnaW4gT3JpZ2VuIG8gdGlwbyBkZSBpY29uby5cbiAqIEBwYXJhbSBpY29uIERlZmluaWNpb24gZGVsIGljb25vIG8gcmVjdXJzby4gKi9cbmludGVyZmFjZSBCdG5JY29uIHtcbiAgb3JpZ2luOiBTdHJpbmcsXG4gIGljb246IFN0cmluZ1xufSJdfQ==