UNPKG

ngx-nested-data-table

Version:
317 lines (308 loc) 34.1 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('tslib'), require('@angular/cdk/collections'), require('rxjs/operators'), require('rxjs'), require('@angular/core'), require('@angular/material'), require('@angular/animations'), require('@angular/common')) : typeof define === 'function' && define.amd ? define('ngx-nested-data-table', ['exports', 'tslib', '@angular/cdk/collections', 'rxjs/operators', 'rxjs', '@angular/core', '@angular/material', '@angular/animations', '@angular/common'], factory) : (factory((global['ngx-nested-data-table'] = {}),global.tslib,global.ng.cdk.collections,global.Rx.Observable.prototype,null,global.ng.core,global.ng.material,global.ng.animations,global.ng.common)); }(this, (function (exports,tslib_1,collections,operators,rxjs,core,material,animations,common) { 'use strict'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Data source for the NgxDataTable view. This class should * encapsulate all logic for fetching and manipulating the displayed data * (including sorting, pagination, and filtering). */ var /** * Data source for the NgxDataTable view. This class should * encapsulate all logic for fetching and manipulating the displayed data * (including sorting, pagination, and filtering). */ NgxDataTableDataSource = (function (_super) { tslib_1.__extends(NgxDataTableDataSource, _super); function NgxDataTableDataSource(paginator, _data, sort) { var _this = _super.call(this) || this; _this.paginator = paginator; _this._data = _data; _this.sort = sort; _this._filterChange = new rxjs.BehaviorSubject(''); _this.data = _data; // Master detail table var /** @type {?} */ rows = []; _data.forEach(function (element) { return element.details ? rows.push(element, { detailRow: true, element: element }) : rows.push(element); }); _this.data = rows; return _this; } Object.defineProperty(NgxDataTableDataSource.prototype, "filter", { get: /** * @return {?} */ function () { return this._filterChange.value; }, set: /** * @param {?} filter * @return {?} */ function (filter) { this._filterChange.next(filter); }, enumerable: true, configurable: true }); /** * Connect this data source to the table. The table will only update when * the returned stream emits new items. * @returns A stream of the items to be rendered. */ /** * Connect this data source to the table. The table will only update when * the returned stream emits new items. * @return {?} A stream of the items to be rendered. */ NgxDataTableDataSource.prototype.connect = /** * Connect this data source to the table. The table will only update when * the returned stream emits new items. * @return {?} A stream of the items to be rendered. */ function () { var _this = this; // Combine everything that affects the rendered data into one update // stream for the data-table to consume. var /** @type {?} */ dataMutations = [ rxjs.of(this.data), this.paginator.page, this.sort.sortChange, this._filterChange, ]; // Set the paginator length this.paginator.length = this.data.length; return rxjs.merge.apply(void 0, tslib_1.__spread(dataMutations)).pipe(operators.map(function () { var /** @type {?} */ filtered = _this._filterData(_this._data); _this.data = _this._enrichData(filtered); return _this.getPagedData(_this.getSortedData(tslib_1.__spread(_this.data))); })); }; /** * @param {?} filtered * @return {?} */ NgxDataTableDataSource.prototype._enrichData = /** * @param {?} filtered * @return {?} */ function (filtered) { var /** @type {?} */ rows = []; filtered.forEach(function (element) { return element.details ? rows.push(element, { detailRow: true, element: element }) : rows.push(element); }); return rows; }; /** * @param {?} data * @return {?} */ NgxDataTableDataSource.prototype._filterData = /** * @param {?} data * @return {?} */ function (data) { var _this = this; this.filteredData = !this.filter ? data : data.filter(function (obj) { // Transform the data into a lowercase string of all property values. var /** @type {?} */ accumulator = function (currentTerm, key) { return currentTerm + obj[key]; }; var /** @type {?} */ dataStr = Object.keys(obj).reduce(accumulator, '').toLowerCase(); // Transform the filter by converting it to lowercase and removing whitespace. var /** @type {?} */ transformedFilter = _this.filter.trim().toLowerCase(); return dataStr.indexOf(transformedFilter) !== -1; }); return this.filteredData; }; /** * Called when the table is being destroyed. Use this function, to clean up * any open connections or free any held resources that were set up during connect. */ /** * Called when the table is being destroyed. Use this function, to clean up * any open connections or free any held resources that were set up during connect. * @return {?} */ NgxDataTableDataSource.prototype.disconnect = /** * Called when the table is being destroyed. Use this function, to clean up * any open connections or free any held resources that were set up during connect. * @return {?} */ function () { }; /** * Paginate the data (client-side). If you're using server-side pagination, * this would be replaced by requesting the appropriate data from the server. * @param {?} data * @return {?} */ NgxDataTableDataSource.prototype.getPagedData = /** * Paginate the data (client-side). If you're using server-side pagination, * this would be replaced by requesting the appropriate data from the server. * @param {?} data * @return {?} */ function (data) { var /** @type {?} */ startIndex = this.paginator.pageIndex * this.paginator.pageSize; return data.splice(startIndex, this.paginator.pageSize); }; /** * Sort the data (client-side). If you're using server-side sorting, * this would be replaced by requesting the appropriate data from the server. * @param {?} data * @return {?} */ NgxDataTableDataSource.prototype.getSortedData = /** * Sort the data (client-side). If you're using server-side sorting, * this would be replaced by requesting the appropriate data from the server. * @param {?} data * @return {?} */ function (data) { var _this = this; if (!this.sort.active || this.sort.direction === '') { return data; } return data.sort(function (a, b) { var /** @type {?} */ isAsc = _this.sort.direction === 'asc'; if (isNaN(a[_this.sort.active])) { return compare(a[_this.sort.active], b[_this.sort.active], isAsc); } else { return compare(+a[_this.sort.active], +b[_this.sort.active], isAsc); } }); }; return NgxDataTableDataSource; }(collections.DataSource)); /** * Simple sort comparator for example ID/Name columns (for client-side sorting). * @param {?} a * @param {?} b * @param {?} isAsc * @return {?} */ function compare(a, b, isAsc) { return (a < b ? -1 : 1) * (isAsc ? 1 : -1); } /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var NgxDataTableComponent = (function () { function NgxDataTableComponent() { this.isExpansionDetailRow = function (i, row) { return row.hasOwnProperty('detailRow'); }; } Object.defineProperty(NgxDataTableComponent.prototype, "data", { set: /** * @param {?} _data * @return {?} */ function (_data) { if (_data) { this.dataSource = new NgxDataTableDataSource(this.paginator, _data, this.sort); this.displayedColumns = Object.keys(_data[0]).filter(function (key) { return key !== 'details'; }); } }, enumerable: true, configurable: true }); /** * expand collapse a row * @param row */ /** * expand collapse a row * @param {?} row * @return {?} */ NgxDataTableComponent.prototype.toggleRow = /** * expand collapse a row * @param {?} row * @return {?} */ function (row) { if (this.expandedElement === row) { this.expandedElement = null; } else { this.expandedElement = row; } }; /** * @param {?} filterValue * @return {?} */ NgxDataTableComponent.prototype.applyFilter = /** * @param {?} filterValue * @return {?} */ function (filterValue) { this.dataSource.filter = filterValue; }; NgxDataTableComponent.decorators = [ { type: core.Component, args: [{ selector: 'ngx-data-table', template: "<div class=\"mat-elevation-z8\">\n <mat-form-field>\n <input matInput (keyup)=\"applyFilter($event.target.value)\" placeholder=\"Filter\" class=\"filter\">\n </mat-form-field>\n <mat-table #table [dataSource]=\"dataSource\" matSort aria-label=\"Elements\">\n <ng-container [matColumnDef]=\"cols\" *ngFor=\"let cols of displayedColumns; let i = index\">\n <mat-header-cell *matHeaderCellDef mat-sort-header>{{cols}}</mat-header-cell>\n <mat-cell *matCellDef=\"let element\" [ngClass]=\"{'col-value': element.details === undefined}\">\n <!-- expand caret -->\n <span *ngIf=\"i === 0 && element.details\">\n <span *ngIf=\"expandedElement && expandedElement[cols] === element[cols]; else plusIcon\" class=\"expand-icon\">&#9650;</span>\n <ng-template #plusIcon><span class=\"expand-icon\">&#9660;</span></ng-template>\n </span>\n <span>{{element[cols]}}</span>\n </mat-cell>\n </ng-container>\n\n <!-- Expanded Content Column - The detail row is made up of this one column -->\n <ng-container matColumnDef=\"expandedDetail\">\n <mat-cell *matCellDef=\"let detail\">\n <ngx-data-table [data]=\"detail.element.details\" class=\"detail-table\"></ngx-data-table>\n </mat-cell>\n </ng-container>\n\n <mat-header-row *matHeaderRowDef=\"displayedColumns\"></mat-header-row>\n <mat-row *matRowDef=\"let row; columns: displayedColumns;\"\n [class.expanded]=\"expandedElement == row\"\n (click)=\"toggleRow(row)\"></mat-row>\n <mat-row *matRowDef=\"let row; columns: ['expandedDetail']; when: isExpansionDetailRow\"\n [@detailExpand]=\"row.element == expandedElement ? 'expanded' : 'collapsed'\"\n style=\"overflow: hidden\"></mat-row>\n </mat-table>\n\n <mat-paginator #paginator\n\n [length]=\"dataSource?.data?.length\"\n [pageIndex]=\"0\"\n [pageSize]=\"25\"\n [pageSizeOptions]=\"[25, 50, 100, 250]\">\n </mat-paginator>\n</div>\n", styles: [ ".detail-table {display: flex;flex-direction: column;display: block;margin: 10px;width: 100%;}\n .expand-icon {color: rgba(0,0,0,.44);font-size: 12px; margin-right: 5px; cursor: pointer;}\n .col-value:first-child span{margin-left: 15px;}\n .mat-form-field {padding: 10px 10px 0 10px;width: calc(100% - 20px);}" ], animations: [ animations.trigger('detailExpand', [ animations.state('collapsed', animations.style({ height: '0px', minHeight: '0', visibility: 'hidden' })), animations.state('expanded', animations.style({ height: '*', visibility: 'visible' })), animations.transition('expanded <=> collapsed', animations.animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')), ]), ], },] }, ]; NgxDataTableComponent.propDecorators = { data: [{ type: core.Input }], paginator: [{ type: core.ViewChild, args: [material.MatPaginator,] }], sort: [{ type: core.ViewChild, args: [material.MatSort,] }] }; return NgxDataTableComponent; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ var NgxDataTableModule = (function () { function NgxDataTableModule() { } NgxDataTableModule.decorators = [ { type: core.NgModule, args: [{ imports: [ common.CommonModule, material.MatTableModule, material.MatPaginatorModule, material.MatSortModule, material.MatInputModule, ], declarations: [NgxDataTableComponent], exports: [NgxDataTableComponent], },] }, ]; return NgxDataTableModule; }()); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ exports.NgxDataTableDataSource = NgxDataTableDataSource; exports.NgxDataTableComponent = NgxDataTableComponent; exports.NgxDataTableModule = NgxDataTableModule; Object.defineProperty(exports, '__esModule', { value: true }); }))); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW5lc3RlZC1kYXRhLXRhYmxlLnVtZC5qcy5tYXAiLCJzb3VyY2VzIjpbIm5nOi8vbmd4LW5lc3RlZC1kYXRhLXRhYmxlL2xpYi9uZ3gtZGF0YS10YWJsZS9uZ3gtZGF0YS10YWJsZS1kYXRhc291cmNlLnRzIiwibmc6Ly9uZ3gtbmVzdGVkLWRhdGEtdGFibGUvbGliL25neC1kYXRhLXRhYmxlL25neC1kYXRhLXRhYmxlLmNvbXBvbmVudC50cyIsIm5nOi8vbmd4LW5lc3RlZC1kYXRhLXRhYmxlL2xpYi9uZ3gtZGF0YS10YWJsZS9uZ3gtZGF0YS10YWJsZS5tb2R1bGUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRGF0YVNvdXJjZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9jb2xsZWN0aW9ucyc7XG5pbXBvcnQgeyBNYXRQYWdpbmF0b3IsIE1hdFNvcnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbCc7XG5pbXBvcnQgeyBtYXAgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge09ic2VydmFibGUsIG9mIGFzIG9ic2VydmFibGVPZiwgbWVyZ2UsIEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdH0gZnJvbSAncnhqcyc7XG5cbi8qKlxuICogRGF0YSBzb3VyY2UgZm9yIHRoZSBOZ3hEYXRhVGFibGUgdmlldy4gVGhpcyBjbGFzcyBzaG91bGRcbiAqIGVuY2Fwc3VsYXRlIGFsbCBsb2dpYyBmb3IgZmV0Y2hpbmcgYW5kIG1hbmlwdWxhdGluZyB0aGUgZGlzcGxheWVkIGRhdGFcbiAqIChpbmNsdWRpbmcgc29ydGluZywgcGFnaW5hdGlvbiwgYW5kIGZpbHRlcmluZykuXG4gKi9cbmV4cG9ydCBjbGFzcyBOZ3hEYXRhVGFibGVEYXRhU291cmNlIGV4dGVuZHMgRGF0YVNvdXJjZTxhbnk+IHtcbiAgcHVibGljIGRhdGE6IGFueVtdO1xuICBfZmlsdGVyQ2hhbmdlID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmc+KCcnKTtcbiAgZmlsdGVyZWREYXRhOiBhbnlbXTtcblxuICBnZXQgZmlsdGVyKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2ZpbHRlckNoYW5nZS52YWx1ZTtcbiAgfVxuICBzZXQgZmlsdGVyKGZpbHRlcjogc3RyaW5nKSB7XG4gICAgdGhpcy5fZmlsdGVyQ2hhbmdlLm5leHQoZmlsdGVyKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcGFnaW5hdG9yOiBNYXRQYWdpbmF0b3IsXG4gICAgcHJpdmF0ZSBfZGF0YTogYW55W10sXG4gICAgcHJpdmF0ZSBzb3J0OiBNYXRTb3J0XG4gICkge1xuICAgIHN1cGVyKCk7XG4gICAgdGhpcy5kYXRhID0gX2RhdGE7XG4gICAgLy8gTWFzdGVyIGRldGFpbCB0YWJsZVxuICAgIGNvbnN0IHJvd3MgPSBbXTtcbiAgICBfZGF0YS5mb3JFYWNoKFxuICAgICAgZWxlbWVudCA9PlxuICAgICAgICBlbGVtZW50LmRldGFpbHNcbiAgICAgICAgICA/IHJvd3MucHVzaChlbGVtZW50LCB7IGRldGFpbFJvdzogdHJ1ZSwgZWxlbWVudCB9KVxuICAgICAgICAgIDogcm93cy5wdXNoKGVsZW1lbnQpXG4gICAgKTtcbiAgICB0aGlzLmRhdGEgPSByb3dzO1xuICB9XG5cbiAgLyoqXG4gICAqIENvbm5lY3QgdGhpcyBkYXRhIHNvdXJjZSB0byB0aGUgdGFibGUuIFRoZSB0YWJsZSB3aWxsIG9ubHkgdXBkYXRlIHdoZW5cbiAgICogdGhlIHJldHVybmVkIHN0cmVhbSBlbWl0cyBuZXcgaXRlbXMuXG4gICAqIEByZXR1cm5zIEEgc3RyZWFtIG9mIHRoZSBpdGVtcyB0byBiZSByZW5kZXJlZC5cbiAgICovXG4gIGNvbm5lY3QoKTogT2JzZXJ2YWJsZTxhbnlbXT4ge1xuICAgIC8vIENvbWJpbmUgZXZlcnl0aGluZyB0aGF0IGFmZmVjdHMgdGhlIHJlbmRlcmVkIGRhdGEgaW50byBvbmUgdXBkYXRlXG4gICAgLy8gc3RyZWFtIGZvciB0aGUgZGF0YS10YWJsZSB0byBjb25zdW1lLlxuICAgIGNvbnN0IGRhdGFNdXRhdGlvbnMgPSBbXG4gICAgICBvYnNlcnZhYmxlT2YodGhpcy5kYXRhKSxcbiAgICAgIHRoaXMucGFnaW5hdG9yLnBhZ2UsXG4gICAgICB0aGlzLnNvcnQuc29ydENoYW5nZSxcbiAgICAgIHRoaXMuX2ZpbHRlckNoYW5nZSxcbiAgICBdO1xuXG4gICAgLy8gU2V0IHRoZSBwYWdpbmF0b3IgbGVuZ3RoXG4gICAgdGhpcy5wYWdpbmF0b3IubGVuZ3RoID0gdGhpcy5kYXRhLmxlbmd0aDtcblxuICAgIHJldHVybiBtZXJnZSguLi5kYXRhTXV0YXRpb25zKS5waXBlKFxuICAgICAgbWFwKCgpID0+IHtcbiAgICAgICAgY29uc3QgZmlsdGVyZWQgPSB0aGlzLl9maWx0ZXJEYXRhKHRoaXMuX2RhdGEpO1xuICAgICAgICB0aGlzLmRhdGEgPSB0aGlzLl9lbnJpY2hEYXRhKGZpbHRlcmVkKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UGFnZWREYXRhKHRoaXMuZ2V0U29ydGVkRGF0YShbLi4udGhpcy5kYXRhXSkpO1xuICAgICAgfSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBfZW5yaWNoRGF0YShmaWx0ZXJlZCkge1xuICAgIGNvbnN0IHJvd3MgPSBbXTtcbiAgICBmaWx0ZXJlZC5mb3JFYWNoKFxuICAgICAgZWxlbWVudCA9PlxuICAgICAgICBlbGVtZW50LmRldGFpbHNcbiAgICAgICAgICA/IHJvd3MucHVzaChlbGVtZW50LCB7ZGV0YWlsUm93OiB0cnVlLCBlbGVtZW50fSlcbiAgICAgICAgICA6IHJvd3MucHVzaChlbGVtZW50KVxuICAgICk7XG4gICAgcmV0dXJuIHJvd3M7XG4gIH1cblxuICBwcml2YXRlIF9maWx0ZXJEYXRhKGRhdGE6IGFueVtdKSB7XG4gICAgdGhpcy5maWx0ZXJlZERhdGEgPVxuICAgICAgIXRoaXMuZmlsdGVyID8gZGF0YSA6IGRhdGEuZmlsdGVyKG9iaiA9PiB7XG4gICAgICAvLyBUcmFuc2Zvcm0gdGhlIGRhdGEgaW50byBhIGxvd2VyY2FzZSBzdHJpbmcgb2YgYWxsIHByb3BlcnR5IHZhbHVlcy5cbiAgICAgIGNvbnN0IGFjY3VtdWxhdG9yID0gKGN1cnJlbnRUZXJtLCBrZXkpID0+IGN1cnJlbnRUZXJtICsgb2JqW2tleV07XG4gICAgICBjb25zdCBkYXRhU3RyID0gT2JqZWN0LmtleXMob2JqKS5yZWR1Y2UoYWNjdW11bGF0b3IsICcnKS50b0xvd2VyQ2FzZSgpO1xuXG4gICAgICAvLyBUcmFuc2Zvcm0gdGhlIGZpbHRlciBieSBjb252ZXJ0aW5nIGl0IHRvIGxvd2VyY2FzZSBhbmQgcmVtb3Zpbmcgd2hpdGVzcGFjZS5cbiAgICAgIGNvbnN0IHRyYW5zZm9ybWVkRmlsdGVyID0gdGhpcy5maWx0ZXIudHJpbSgpLnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgIHJldHVybiBkYXRhU3RyLmluZGV4T2YodHJhbnNmb3JtZWRGaWx0ZXIpICE9PSAtMTtcbiAgICB9KTtcbiAgICByZXR1cm4gdGhpcy5maWx0ZXJlZERhdGE7XG4gIH1cblxuICAvKipcbiAgICogIENhbGxlZCB3aGVuIHRoZSB0YWJsZSBpcyBiZWluZyBkZXN0cm95ZWQuIFVzZSB0aGlzIGZ1bmN0aW9uLCB0byBjbGVhbiB1cFxuICAgKiBhbnkgb3BlbiBjb25uZWN0aW9ucyBvciBmcmVlIGFueSBoZWxkIHJlc291cmNlcyB0aGF0IHdlcmUgc2V0IHVwIGR1cmluZyBjb25uZWN0LlxuICAgKi9cbiAgZGlzY29ubmVjdCgpIHt9XG5cbiAgLyoqXG4gICAqIFBhZ2luYXRlIHRoZSBkYXRhIChjbGllbnQtc2lkZSkuIElmIHlvdSdyZSB1c2luZyBzZXJ2ZXItc2lkZSBwYWdpbmF0aW9uLFxuICAgKiB0aGlzIHdvdWxkIGJlIHJlcGxhY2VkIGJ5IHJlcXVlc3RpbmcgdGhlIGFwcHJvcHJpYXRlIGRhdGEgZnJvbSB0aGUgc2VydmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRQYWdlZERhdGEoZGF0YTogYW55W10pIHtcbiAgICBjb25zdCBzdGFydEluZGV4ID0gdGhpcy5wYWdpbmF0b3IucGFnZUluZGV4ICogdGhpcy5wYWdpbmF0b3IucGFnZVNpemU7XG4gICAgcmV0dXJuIGRhdGEuc3BsaWNlKHN0YXJ0SW5kZXgsIHRoaXMucGFnaW5hdG9yLnBhZ2VTaXplKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTb3J0IHRoZSBkYXRhIChjbGllbnQtc2lkZSkuIElmIHlvdSdyZSB1c2luZyBzZXJ2ZXItc2lkZSBzb3J0aW5nLFxuICAgKiB0aGlzIHdvdWxkIGJlIHJlcGxhY2VkIGJ5IHJlcXVlc3RpbmcgdGhlIGFwcHJvcHJpYXRlIGRhdGEgZnJvbSB0aGUgc2VydmVyLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRTb3J0ZWREYXRhKGRhdGE6IGFueVtdKSB7XG4gICAgaWYgKCF0aGlzLnNvcnQuYWN0aXZlIHx8IHRoaXMuc29ydC5kaXJlY3Rpb24gPT09ICcnKSB7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICByZXR1cm4gZGF0YS5zb3J0KChhLCBiKSA9PiB7XG4gICAgICBjb25zdCBpc0FzYyA9IHRoaXMuc29ydC5kaXJlY3Rpb24gPT09ICdhc2MnO1xuICAgICAgaWYgKGlzTmFOKGFbdGhpcy5zb3J0LmFjdGl2ZV0pKSB7XG4gICAgICAgIHJldHVybiBjb21wYXJlKGFbdGhpcy5zb3J0LmFjdGl2ZV0sIGJbdGhpcy5zb3J0LmFjdGl2ZV0sIGlzQXNjKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBjb21wYXJlKCthW3RoaXMuc29ydC5hY3RpdmVdLCArYlt0aGlzLnNvcnQuYWN0aXZlXSwgaXNBc2MpO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG59XG5cbi8qKiBTaW1wbGUgc29ydCBjb21wYXJhdG9yIGZvciBleGFtcGxlIElEL05hbWUgY29sdW1ucyAoZm9yIGNsaWVudC1zaWRlIHNvcnRpbmcpLiAqL1xuZnVuY3Rpb24gY29tcGFyZShhLCBiLCBpc0FzYykge1xuICByZXR1cm4gKGEgPCBiID8gLTEgOiAxKSAqIChpc0FzYyA/IDEgOiAtMSk7XG59XG4iLCJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgVmlld0NoaWxkLCBJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTWF0UGFnaW5hdG9yLCBNYXRTb3J0IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwnO1xuaW1wb3J0IHsgTmd4RGF0YVRhYmxlRGF0YVNvdXJjZSB9IGZyb20gJy4vbmd4LWRhdGEtdGFibGUtZGF0YXNvdXJjZSc7XG5pbXBvcnQge1xuICB0cmlnZ2VyLFxuICBzdGF0ZSxcbiAgc3R5bGUsXG4gIHRyYW5zaXRpb24sXG4gIGFuaW1hdGUsXG59IGZyb20gJ0Bhbmd1bGFyL2FuaW1hdGlvbnMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ3gtZGF0YS10YWJsZScsXG4gIHRlbXBsYXRlOiBgPGRpdiBjbGFzcz1cIm1hdC1lbGV2YXRpb24tejhcIj5cbiAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICA8aW5wdXQgbWF0SW5wdXQgKGtleXVwKT1cImFwcGx5RmlsdGVyKCRldmVudC50YXJnZXQudmFsdWUpXCIgcGxhY2Vob2xkZXI9XCJGaWx0ZXJcIiBjbGFzcz1cImZpbHRlclwiPlxuICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gIDxtYXQtdGFibGUgI3RhYmxlIFtkYXRhU291cmNlXT1cImRhdGFTb3VyY2VcIiBtYXRTb3J0IGFyaWEtbGFiZWw9XCJFbGVtZW50c1wiPlxuICAgIDxuZy1jb250YWluZXIgW21hdENvbHVtbkRlZl09XCJjb2xzXCIgKm5nRm9yPVwibGV0IGNvbHMgb2YgZGlzcGxheWVkQ29sdW1uczsgbGV0IGkgPSBpbmRleFwiPlxuICAgICAgPG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBtYXQtc29ydC1oZWFkZXI+e3tjb2xzfX08L21hdC1oZWFkZXItY2VsbD5cbiAgICAgIDxtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBlbGVtZW50XCIgW25nQ2xhc3NdPVwieydjb2wtdmFsdWUnOiBlbGVtZW50LmRldGFpbHMgPT09IHVuZGVmaW5lZH1cIj5cbiAgICAgICAgPCEtLSBleHBhbmQgY2FyZXQgLS0+XG4gICAgICAgIDxzcGFuICpuZ0lmPVwiaSA9PT0gMCAmJiBlbGVtZW50LmRldGFpbHNcIj5cbiAgICAgICAgICA8c3BhbiAqbmdJZj1cImV4cGFuZGVkRWxlbWVudCAmJiBleHBhbmRlZEVsZW1lbnRbY29sc10gPT09IGVsZW1lbnRbY29sc107IGVsc2UgcGx1c0ljb25cIiBjbGFzcz1cImV4cGFuZC1pY29uXCI+JiM5NjUwOzwvc3Bhbj5cbiAgICAgICAgICA8bmctdGVtcGxhdGUgI3BsdXNJY29uPjxzcGFuIGNsYXNzPVwiZXhwYW5kLWljb25cIj4mIzk2NjA7PC9zcGFuPjwvbmctdGVtcGxhdGU+XG4gICAgICAgIDwvc3Bhbj5cbiAgICAgICAgPHNwYW4+e3tlbGVtZW50W2NvbHNdfX08L3NwYW4+XG4gICAgICA8L21hdC1jZWxsPlxuICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgPCEtLSBFeHBhbmRlZCBDb250ZW50IENvbHVtbiAtIFRoZSBkZXRhaWwgcm93IGlzIG1hZGUgdXAgb2YgdGhpcyBvbmUgY29sdW1uIC0tPlxuICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiZXhwYW5kZWREZXRhaWxcIj5cbiAgICAgIDxtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCBkZXRhaWxcIj5cbiAgICAgICAgPG5neC1kYXRhLXRhYmxlIFtkYXRhXT1cImRldGFpbC5lbGVtZW50LmRldGFpbHNcIiBjbGFzcz1cImRldGFpbC10YWJsZVwiPjwvbmd4LWRhdGEtdGFibGU+XG4gICAgICA8L21hdC1jZWxsPlxuICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgPG1hdC1oZWFkZXItcm93ICptYXRIZWFkZXJSb3dEZWY9XCJkaXNwbGF5ZWRDb2x1bW5zXCI+PC9tYXQtaGVhZGVyLXJvdz5cbiAgICA8bWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1ucztcIlxuICAgICAgICAgICAgICBbY2xhc3MuZXhwYW5kZWRdPVwiZXhwYW5kZWRFbGVtZW50ID09IHJvd1wiXG4gICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGVSb3cocm93KVwiPjwvbWF0LXJvdz5cbiAgICA8bWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogWydleHBhbmRlZERldGFpbCddOyB3aGVuOiBpc0V4cGFuc2lvbkRldGFpbFJvd1wiXG4gICAgW0BkZXRhaWxFeHBhbmRdPVwicm93LmVsZW1lbnQgPT0gZXhwYW5kZWRFbGVtZW50ID8gJ2V4cGFuZGVkJyA6ICdjb2xsYXBzZWQnXCJcbiAgICBzdHlsZT1cIm92ZXJmbG93OiBoaWRkZW5cIj48L21hdC1yb3c+XG4gIDwvbWF0LXRhYmxlPlxuXG4gIDxtYXQtcGFnaW5hdG9yICNwYWdpbmF0b3JcblxuICAgIFtsZW5ndGhdPVwiZGF0YVNvdXJjZT8uZGF0YT8ubGVuZ3RoXCJcbiAgICBbcGFnZUluZGV4XT1cIjBcIlxuICAgIFtwYWdlU2l6ZV09XCIyNVwiXG4gICAgW3BhZ2VTaXplT3B0aW9uc109XCJbMjUsIDUwLCAxMDAsIDI1MF1cIj5cbiAgPC9tYXQtcGFnaW5hdG9yPlxuPC9kaXY+XG5gLFxuICBzdHlsZXM6IFtcbiAgICBgLmRldGFpbC10YWJsZSB7ZGlzcGxheTogZmxleDtmbGV4LWRpcmVjdGlvbjogY29sdW1uO2Rpc3BsYXk6IGJsb2NrO21hcmdpbjogMTBweDt3aWR0aDogMTAwJTt9XG4gICAgLmV4cGFuZC1pY29uIHtjb2xvcjogcmdiYSgwLDAsMCwuNDQpO2ZvbnQtc2l6ZTogMTJweDsgbWFyZ2luLXJpZ2h0OiA1cHg7IGN1cnNvcjogcG9pbnRlcjt9XG4gICAgLmNvbC12YWx1ZTpmaXJzdC1jaGlsZCBzcGFue21hcmdpbi1sZWZ0OiAxNXB4O31cbiAgICAubWF0LWZvcm0tZmllbGQge3BhZGRpbmc6IDEwcHggMTBweCAwIDEwcHg7d2lkdGg6IGNhbGMoMTAwJSAtIDIwcHgpO31gXG4gIF0sXG4gIGFuaW1hdGlvbnM6IFtcbiAgICB0cmlnZ2VyKCdkZXRhaWxFeHBhbmQnLCBbXG4gICAgICBzdGF0ZShcbiAgICAgICAgJ2NvbGxhcHNlZCcsXG4gICAgICAgIHN0eWxlKHsgaGVpZ2h0OiAnMHB4JywgbWluSGVpZ2h0OiAnMCcsIHZpc2liaWxpdHk6ICdoaWRkZW4nIH0pXG4gICAgICApLFxuICAgICAgc3RhdGUoJ2V4cGFuZGVkJywgc3R5bGUoeyBoZWlnaHQ6ICcqJywgdmlzaWJpbGl0eTogJ3Zpc2libGUnIH0pKSxcbiAgICAgIHRyYW5zaXRpb24oXG4gICAgICAgICdleHBhbmRlZCA8PT4gY29sbGFwc2VkJyxcbiAgICAgICAgYW5pbWF0ZSgnMjI1bXMgY3ViaWMtYmV6aWVyKDAuNCwgMC4wLCAwLjIsIDEpJylcbiAgICAgICksXG4gICAgXSksXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIE5neERhdGFUYWJsZUNvbXBvbmVudCB7XG4gIEBJbnB1dCgpXG4gIHNldCBkYXRhKF9kYXRhOiBhbnlbXSkge1xuICAgIGlmIChfZGF0YSkge1xuICAgICAgdGhpcy5kYXRhU291cmNlID0gbmV3IE5neERhdGFUYWJsZURhdGFTb3VyY2UoXG4gICAgICAgIHRoaXMucGFnaW5hdG9yLFxuICAgICAgICBfZGF0YSxcbiAgICAgICAgdGhpcy5zb3J0XG4gICAgICApO1xuICAgICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zID0gT2JqZWN0LmtleXMoX2RhdGFbMF0pLmZpbHRlcihcbiAgICAgICAga2V5ID0+IGtleSAhPT0gJ2RldGFpbHMnXG4gICAgICApO1xuICAgIH1cbiAgfVxuICBAVmlld0NoaWxkKE1hdFBhZ2luYXRvcikgcGFnaW5hdG9yOiBNYXRQYWdpbmF0b3I7XG4gIEBWaWV3Q2hpbGQoTWF0U29ydCkgc29ydDogTWF0U29ydDtcbiAgZGF0YVNvdXJjZTogTmd4RGF0YVRhYmxlRGF0YVNvdXJjZTtcblxuICAvKiogQ29sdW1ucyBkaXNwbGF5ZWQgaW4gdGhlIHRhYmxlLiBDb2x1bW5zIElEcyBjYW4gYmUgYWRkZWQsIHJlbW92ZWQsIG9yIHJlb3JkZXJlZC4gKi9cbiAgZGlzcGxheWVkQ29sdW1uczogQXJyYXk8c3RyaW5nPjtcbiAgZXhwYW5kZWRFbGVtZW50OiBBcnJheTxzdHJpbmc+O1xuICBpc0V4cGFuc2lvbkRldGFpbFJvdyA9IChpOiBudW1iZXIsIHJvdzogT2JqZWN0KSA9PlxuICAgIHJvdy5oYXNPd25Qcm9wZXJ0eSgnZGV0YWlsUm93Jyk7XG5cbiAgLyoqXG4gICAqIGV4cGFuZCBjb2xsYXBzZSBhIHJvd1xuICAgKiBAcGFyYW0gcm93XG4gICAqL1xuICB0b2dnbGVSb3cocm93KSB7XG4gICAgaWYgKHRoaXMuZXhwYW5kZWRFbGVtZW50ID09PSByb3cpIHtcbiAgICAgIHRoaXMuZXhwYW5kZWRFbGVtZW50ID0gbnVsbDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5leHBhbmRlZEVsZW1lbnQgPSByb3c7XG4gICAgfVxuICB9XG5cbiAgYXBwbHlGaWx0ZXIoZmlsdGVyVmFsdWU6IHN0cmluZykge1xuICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIgPSBmaWx0ZXJWYWx1ZTtcbiAgfVxufVxuIiwiaW1wb3J0IHsgTmdNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBOZ3hEYXRhVGFibGVDb21wb25lbnQgfSBmcm9tICcuL25neC1kYXRhLXRhYmxlLmNvbXBvbmVudCc7XG5pbXBvcnQge1xuICBNYXRUYWJsZU1vZHVsZSxcbiAgTWF0UGFnaW5hdG9yTW9kdWxlLFxuICBNYXRTb3J0TW9kdWxlLFxuICBNYXRJbnB1dE1vZHVsZSxcbn0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwnO1xuXG5ATmdNb2R1bGUoe1xuICBpbXBvcnRzOiBbXG4gICAgQ29tbW9uTW9kdWxlLFxuICAgIE1hdFRhYmxlTW9kdWxlLFxuICAgIE1hdFBhZ2luYXRvck1vZHVsZSxcbiAgICBNYXRTb3J0TW9kdWxlLFxuICAgIE1hdElucHV0TW9kdWxlLFxuICBdLFxuICBkZWNsYXJhdGlvbnM6IFtOZ3hEYXRhVGFibGVDb21wb25lbnRdLFxuICBleHBvcnRzOiBbTmd4RGF0YVRhYmxlQ29tcG9uZW50XSxcbn0pXG5leHBvcnQgY2xhc3MgTmd4RGF0YVRhYmxlTW9kdWxlIHt9XG4iXSwibmFtZXMiOlsidHNsaWJfMS5fX2V4dGVuZHMiLCJCZWhhdmlvclN1YmplY3QiLCJvYnNlcnZhYmxlT2YiLCJtZXJnZSIsIm1hcCIsIkRhdGFTb3VyY2UiLCJDb21wb25lbnQiLCJ0cmlnZ2VyIiwic3RhdGUiLCJzdHlsZSIsInRyYW5zaXRpb24iLCJhbmltYXRlIiwiSW5wdXQiLCJWaWV3Q2hpbGQiLCJNYXRQYWdpbmF0b3IiLCJNYXRTb3J0IiwiTmdNb2R1bGUiLCJDb21tb25Nb2R1bGUiLCJNYXRUYWJsZU1vZHVsZSIsIk1hdFBhZ2luYXRvck1vZHVsZSIsIk1hdFNvcnRNb2R1bGUiLCJNYXRJbnB1dE1vZHVsZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7O0FBVUE7Ozs7UUFBQTtRQUE0Q0Esa0RBQWU7UUFZekQsZ0NBQ1UsV0FDQSxPQUNBO1lBSFYsWUFLRSxpQkFBTyxTQVdSO1lBZlMsZUFBUyxHQUFULFNBQVM7WUFDVCxXQUFLLEdBQUwsS0FBSztZQUNMLFVBQUksR0FBSixJQUFJO2tDQWJFLElBQUlDLG9CQUFlLENBQVMsRUFBRSxDQUFDO1lBZ0I3QyxLQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQzs7WUFFbEIscUJBQU0sSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNoQixLQUFLLENBQUMsT0FBTyxDQUNYLFVBQUEsT0FBTztnQkFDTCxPQUFBLE9BQU8sQ0FBQyxPQUFPO3NCQUNYLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxPQUFPLFNBQUEsRUFBRSxDQUFDO3NCQUNoRCxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQzthQUFBLENBQ3pCLENB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