UNPKG

juvo-rafa-library

Version:

A comprehensive Angular component library featuring real-world components and validators extracted from the Juvo Rafa backoffice application. Now with improved select components and bug fixes.

282 lines 48.6 kB
import { Component, Input, Output, EventEmitter } from '@angular/core'; import { CommonModule } from '@angular/common'; import { of } from 'rxjs'; import * as i0 from "@angular/core"; import * as i1 from "@angular/common"; /** * Table Component * * @description * A comprehensive table component for displaying and managing tabular data. * Originally designed for backoffice applications with data management needs. * Supports pagination, sorting, selection, and custom actions. * * @example * ```html * <!-- Basic table --> * <juvo-table * [data$]="tableData$" * [columns]="[ * { key: 'id', label: 'ID', width: '80px' }, * { key: 'name', label: 'Name', sortable: true }, * { key: 'email', label: 'Email', sortable: true }, * { key: 'actions', label: 'Actions', type: 'actions' } * ]" * [paginator]="true" * [rows]="10" * (rowSelected)="onRowSelected($event)" * (actionTriggered)="onActionTriggered($event)"> * </juvo-table> * * <!-- Table with selection --> * <juvo-table * [data$]="userData$" * [columns]="userColumns" * [loading$]="userLoading$" * [selectionMode]="'multiple'" * [paginator]="true" * [sortMode]="'single'" * (selectionChange)="onSelectionChange($event)"> * </juvo-table> * ``` * * @selector juvo-table * @since 2.1.0 * @author Juvo Rafa Team */ export class JuvoTableComponent { constructor() { /** Observable data source */ this.data$ = of([]); /** Column configuration */ this.columns = []; /** Loading state observable */ this.loading$ = of(false); /** Selection mode @default "none" */ this.selectionMode = 'none'; /** Whether to show paginator @default false */ this.paginator = false; /** Number of rows per page @default 10 */ this.rows = 10; /** Sort mode @default "single" */ this.sortMode = 'single'; /** Whether to show grid lines @default true */ this.showGridlines = true; /** Whether to show striped rows @default true */ this.striped = true; /** Whether to show hover effect @default true */ this.hoverable = true; /** Table size variant @default "medium" */ this.size = 'medium'; /** Empty state message */ this.emptyMessage = 'No records found'; /** Loading message */ this.loadingMessage = 'Loading data...'; /** Emitted when a row is selected */ this.rowSelected = new EventEmitter(); /** Emitted when selection changes */ this.selectionChange = new EventEmitter(); /** Emitted when a row is clicked */ this.rowClicked = new EventEmitter(); /** Emitted when column is sorted */ this.sortChange = new EventEmitter(); /** Emitted when page changes */ this.pageChange = new EventEmitter(); /** Emitted when an action is triggered */ this.actionTriggered = new EventEmitter(); this.selectedRows = []; this.currentPage = 0; this.sortOrder = 'asc'; this.paginatedData = []; this.totalRecords = 0; // Expose Math for template this.Math = Math; } /** * Gets CSS classes for the table container * @returns Combined CSS classes */ get containerClasses() { let classes = `juvo-table juvo-table-${this.size}`; if (this.showGridlines) classes += ' gridlines'; if (this.striped) classes += ' striped'; if (this.hoverable) classes += ' hoverable'; return classes; } /** * Handles row selection */ onRowSelect(row, event) { if (this.selectionMode === 'none') return; if (event) { event.stopPropagation(); } const index = this.selectedRows.findIndex(selected => selected === row); if (this.selectionMode === 'single') { this.selectedRows = index > -1 ? [] : [row]; } else if (this.selectionMode === 'multiple') { if (index > -1) { this.selectedRows.splice(index, 1); } else { this.selectedRows.push(row); } } this.rowSelected.emit(row); this.selectionChange.emit(this.selectedRows); } /** * Handles row click */ onRowClick(row) { this.rowClicked.emit(row); } /** * Handles column sort */ onSort(column) { if (!column.sortable || this.sortMode === 'none') return; if (this.sortField === column.key) { this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc'; } else { this.sortField = column.key; this.sortOrder = 'asc'; } this.sortChange.emit({ field: column.key, order: this.sortOrder }); } /** * Handles select all checkbox */ selectAll(event) { const checkbox = event.target; // This would need to be implemented based on current data // For now, just emit the selection change this.selectionChange.emit(this.selectedRows); } /** * Handles previous page navigation */ previousPage() { if (this.currentPage > 0) { this.currentPage--; this.pageChange.emit({ first: this.currentPage * this.rows, rows: this.rows }); } } /** * Handles next page navigation */ nextPage() { this.currentPage++; this.pageChange.emit({ first: this.currentPage * this.rows, rows: this.rows }); } /** * Checks if a row is selected */ isSelected(row) { return this.selectedRows.includes(row); } /** * Gets the display value for a cell */ getCellValue(item, column) { const value = item[column.key]; switch (column.type) { case 'boolean': return value ? '' : ''; case 'date': return value ? new Date(value).toLocaleDateString() : ''; case 'number': return typeof value === 'number' ? value.toLocaleString() : ''; case 'actions': return ''; // Actions are handled separately default: return value?.toString() || ''; } } /** * Gets CSS classes for column header */ getHeaderClasses(column) { let classes = 'table-header-cell'; if (column.sortable) classes += ' sortable'; if (this.sortField === column.key) classes += ` sorted-${this.sortOrder}`; if (column.align) classes += ` text-${column.align}`; return classes; } /** * Gets CSS classes for table cell */ getCellClasses(column) { let classes = 'table-cell'; if (column.align) classes += ` text-${column.align}`; return classes; } /** * Handles action button click */ onAction(action, item) { this.actionTriggered.emit({ action, item }); } /** * Track by function for ngFor */ trackByFn(index, item) { return item.id || index; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: JuvoTableComponent, isStandalone: true, selector: "juvo-table", inputs: { data$: "data$", columns: "columns", loading$: "loading$", selectionMode: "selectionMode", paginator: "paginator", rows: "rows", sortMode: "sortMode", showGridlines: "showGridlines", striped: "striped", hoverable: "hoverable", size: "size", emptyMessage: "emptyMessage", loadingMessage: "loadingMessage" }, outputs: { rowSelected: "rowSelected", selectionChange: "selectionChange", rowClicked: "rowClicked", sortChange: "sortChange", pageChange: "pageChange", actionTriggered: "actionTriggered" }, ngImport: i0, template: "<div [class]=\"containerClasses\">\n <!-- Loading State -->\n <div class=\"table-loading\" *ngIf=\"loading$ | async\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">{{ loadingMessage }}</div>\n </div>\n\n <!-- Table Content -->\n <div class=\"table-wrapper\" *ngIf=\"!(loading$ | async)\">\n <table class=\"table\">\n <!-- Header -->\n <thead>\n <tr>\n <!-- Selection column -->\n <th *ngIf=\"selectionMode !== 'none'\" class=\"selection-column\">\n <input \n *ngIf=\"selectionMode === 'multiple'\"\n type=\"checkbox\" \n (change)=\"selectAll($event)\">\n </th>\n \n <!-- Data columns -->\n <th \n *ngFor=\"let column of columns\"\n [class]=\"getHeaderClasses(column)\"\n [style.width]=\"column.width\"\n (click)=\"onSort(column)\">\n {{ column.label }}\n <span class=\"sort-indicator\" *ngIf=\"column.sortable && sortField === column.key\">\n {{ sortOrder === 'asc' ? '\u2191' : '\u2193' }}\n </span>\n </th>\n </tr>\n </thead>\n\n <!-- Body -->\n <tbody>\n <!-- Data rows -->\n <tr \n *ngFor=\"let row of data$ | async; trackBy: trackByFn\"\n class=\"table-row\"\n [class.selected]=\"isSelected(row)\"\n (click)=\"onRowClick(row)\">\n \n <!-- Selection cell -->\n <td *ngIf=\"selectionMode !== 'none'\" class=\"selection-cell\">\n <input \n type=\"checkbox\" \n [checked]=\"isSelected(row)\"\n (change)=\"onRowSelect(row, $event)\"\n (click)=\"$event.stopPropagation()\">\n </td>\n\n <!-- Data cells -->\n <td \n *ngFor=\"let column of columns\"\n [class]=\"getCellClasses(column)\"\n [style.width]=\"column.width\">\n \n <!-- Regular content -->\n <span *ngIf=\"column.type !== 'actions'\">\n {{ getCellValue(row, column) }}\n </span>\n \n <!-- Actions column -->\n <div *ngIf=\"column.type === 'actions'\" class=\"action-buttons\">\n <button \n type=\"button\" \n class=\"action-btn edit-btn\"\n (click)=\"onAction('edit', row); $event.stopPropagation()\"\n title=\"Edit\">\n \u270F\uFE0F\n </button>\n <button \n type=\"button\" \n class=\"action-btn delete-btn\"\n (click)=\"onAction('delete', row); $event.stopPropagation()\"\n title=\"Delete\">\n \uD83D\uDDD1\uFE0F\n </button>\n </div>\n </td>\n </tr>\n\n <!-- Empty state -->\n <tr *ngIf=\"(data$ | async)?.length === 0\" class=\"empty-row\">\n <td [attr.colspan]=\"columns.length + (selectionMode !== 'none' ? 1 : 0)\">\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\uD83D\uDCC4</div>\n <div class=\"empty-text\">{{ emptyMessage }}</div>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"table-pagination\" *ngIf=\"paginator && ((data$ | async)?.length || 0) > 0\">\n <div class=\"pagination-info\">\n Showing {{ currentPage * rows + 1 }} to {{ Math.min((currentPage + 1) * rows, totalRecords) }} of {{ totalRecords }} entries\n </div>\n <div class=\"pagination-controls\">\n <button \n type=\"button\" \n class=\"page-btn\"\n [disabled]=\"currentPage === 0\"\n (click)=\"previousPage()\">\n Previous\n </button>\n <span class=\"page-info\">Page {{ currentPage + 1 }}</span>\n <button \n type=\"button\" \n class=\"page-btn\"\n [disabled]=\"(currentPage + 1) * rows >= totalRecords\"\n (click)=\"nextPage()\">\n Next\n </button>\n </div>\n </div>\n</div> ", styles: [".juvo-table{width:100%;background:#fff;border-radius:.5rem;overflow:hidden;border:1px solid #e5e7eb}.table-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem 2rem;gap:1rem}.loading-spinner{width:2rem;height:2rem;border:2px solid #f3f4f6;border-top:2px solid #3b82f6;border-radius:50%;animation:spin 1s linear infinite}.loading-text{color:#6b7280;font-size:.875rem}@keyframes spin{to{transform:rotate(360deg)}}.table-wrapper{overflow-x:auto}.table{width:100%;border-collapse:collapse}.table thead{background:#f9fafb}.table-header-cell{text-align:left;font-weight:600;color:#374151;font-size:.875rem;border-bottom:1px solid #e5e7eb;position:relative}.table-header-cell.sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .15s}.table-header-cell.sortable:hover{background:#f3f4f6}.sort-indicator{margin-left:.5rem;font-size:.75rem;color:#3b82f6}.table-row{transition:all .15s;cursor:pointer}.juvo-table.hoverable .table-row:hover{background:#f9fafb}.table-row.selected{background:#eff6ff}.juvo-table.striped .table-row:nth-child(2n){background:#fafafa}.juvo-table.striped .table-row:nth-child(2n):hover{background:#f3f4f6}.table-cell{color:#374151;font-size:.875rem;border-bottom:1px solid #f3f4f6;vertical-align:middle}.juvo-table.gridlines .table-cell{border-right:1px solid #f3f4f6}.juvo-table.gridlines .table-cell:last-child{border-right:none}.selection-column,.selection-cell{width:3rem;text-align:center}.selection-cell input[type=checkbox]{margin:0}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.juvo-table-small .table-header-cell,.juvo-table-small .table-cell{padding:.5rem;font-size:.8125rem}.juvo-table-medium .table-header-cell,.juvo-table-medium .table-cell{padding:.75rem;font-size:.875rem}.juvo-table-large .table-header-cell,.juvo-table-large .table-cell{padding:1rem;font-size:1rem}.action-buttons{display:flex;gap:.5rem;justify-content:center}.action-btn{background:none;border:none;cursor:pointer;padding:.25rem;border-radius:.25rem;font-size:1rem;transition:all .15s}.action-btn:hover{background:#f3f4f6}.edit-btn:hover{background:#fef3c7}.delete-btn:hover{background:#fee2e2}.empty-row .table-cell{border-bottom:none}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem 2rem;gap:1rem}.empty-icon{font-size:3rem;opacity:.4}.empty-text{color:#9ca3af;font-size:.875rem;text-align:center}.table-pagination{display:flex;justify-content:between;align-items:center;padding:1rem;border-top:1px solid #e5e7eb;background:#fafafa}.pagination-info{color:#6b7280;font-size:.875rem;flex:1}.pagination-controls{display:flex;align-items:center;gap:1rem}.page-btn{background:#fff;border:1px solid #d1d5db;color:#374151;padding:.5rem 1rem;border-radius:.375rem;font-size:.875rem;cursor:pointer;transition:all .15s}.page-btn:hover:not(:disabled){background:#f9fafb;border-color:#9ca3af}.page-btn:disabled{opacity:.5;cursor:not-allowed}.page-info{color:#374151;font-size:.875rem;font-weight:500}@media (max-width: 768px){.table-pagination{flex-direction:column;gap:1rem}.pagination-info{text-align:center}.juvo-table-large .table-header-cell,.juvo-table-large .table-cell{padding:.75rem .5rem;font-size:.875rem}}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: JuvoTableComponent, decorators: [{ type: Component, args: [{ selector: 'juvo-table', standalone: true, imports: [CommonModule], template: "<div [class]=\"containerClasses\">\n <!-- Loading State -->\n <div class=\"table-loading\" *ngIf=\"loading$ | async\">\n <div class=\"loading-spinner\"></div>\n <div class=\"loading-text\">{{ loadingMessage }}</div>\n </div>\n\n <!-- Table Content -->\n <div class=\"table-wrapper\" *ngIf=\"!(loading$ | async)\">\n <table class=\"table\">\n <!-- Header -->\n <thead>\n <tr>\n <!-- Selection column -->\n <th *ngIf=\"selectionMode !== 'none'\" class=\"selection-column\">\n <input \n *ngIf=\"selectionMode === 'multiple'\"\n type=\"checkbox\" \n (change)=\"selectAll($event)\">\n </th>\n \n <!-- Data columns -->\n <th \n *ngFor=\"let column of columns\"\n [class]=\"getHeaderClasses(column)\"\n [style.width]=\"column.width\"\n (click)=\"onSort(column)\">\n {{ column.label }}\n <span class=\"sort-indicator\" *ngIf=\"column.sortable && sortField === column.key\">\n {{ sortOrder === 'asc' ? '\u2191' : '\u2193' }}\n </span>\n </th>\n </tr>\n </thead>\n\n <!-- Body -->\n <tbody>\n <!-- Data rows -->\n <tr \n *ngFor=\"let row of data$ | async; trackBy: trackByFn\"\n class=\"table-row\"\n [class.selected]=\"isSelected(row)\"\n (click)=\"onRowClick(row)\">\n \n <!-- Selection cell -->\n <td *ngIf=\"selectionMode !== 'none'\" class=\"selection-cell\">\n <input \n type=\"checkbox\" \n [checked]=\"isSelected(row)\"\n (change)=\"onRowSelect(row, $event)\"\n (click)=\"$event.stopPropagation()\">\n </td>\n\n <!-- Data cells -->\n <td \n *ngFor=\"let column of columns\"\n [class]=\"getCellClasses(column)\"\n [style.width]=\"column.width\">\n \n <!-- Regular content -->\n <span *ngIf=\"column.type !== 'actions'\">\n {{ getCellValue(row, column) }}\n </span>\n \n <!-- Actions column -->\n <div *ngIf=\"column.type === 'actions'\" class=\"action-buttons\">\n <button \n type=\"button\" \n class=\"action-btn edit-btn\"\n (click)=\"onAction('edit', row); $event.stopPropagation()\"\n title=\"Edit\">\n \u270F\uFE0F\n </button>\n <button \n type=\"button\" \n class=\"action-btn delete-btn\"\n (click)=\"onAction('delete', row); $event.stopPropagation()\"\n title=\"Delete\">\n \uD83D\uDDD1\uFE0F\n </button>\n </div>\n </td>\n </tr>\n\n <!-- Empty state -->\n <tr *ngIf=\"(data$ | async)?.length === 0\" class=\"empty-row\">\n <td [attr.colspan]=\"columns.length + (selectionMode !== 'none' ? 1 : 0)\">\n <div class=\"empty-state\">\n <div class=\"empty-icon\">\uD83D\uDCC4</div>\n <div class=\"empty-text\">{{ emptyMessage }}</div>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"table-pagination\" *ngIf=\"paginator && ((data$ | async)?.length || 0) > 0\">\n <div class=\"pagination-info\">\n Showing {{ currentPage * rows + 1 }} to {{ Math.min((currentPage + 1) * rows, totalRecords) }} of {{ totalRecords }} entries\n </div>\n <div class=\"pagination-controls\">\n <button \n type=\"button\" \n class=\"page-btn\"\n [disabled]=\"currentPage === 0\"\n (click)=\"previousPage()\">\n Previous\n </button>\n <span class=\"page-info\">Page {{ currentPage + 1 }}</span>\n <button \n type=\"button\" \n class=\"page-btn\"\n [disabled]=\"(currentPage + 1) * rows >= totalRecords\"\n (click)=\"nextPage()\">\n Next\n </button>\n </div>\n </div>\n</div> ", styles: [".juvo-table{width:100%;background:#fff;border-radius:.5rem;overflow:hidden;border:1px solid #e5e7eb}.table-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:4rem 2rem;gap:1rem}.loading-spinner{width:2rem;height:2rem;border:2px solid #f3f4f6;border-top:2px solid #3b82f6;border-radius:50%;animation:spin 1s linear infinite}.loading-text{color:#6b7280;font-size:.875rem}@keyframes spin{to{transform:rotate(360deg)}}.table-wrapper{overflow-x:auto}.table{width:100%;border-collapse:collapse}.table thead{background:#f9fafb}.table-header-cell{text-align:left;font-weight:600;color:#374151;font-size:.875rem;border-bottom:1px solid #e5e7eb;position:relative}.table-header-cell.sortable{cursor:pointer;-webkit-user-select:none;user-select:none;transition:background-color .15s}.table-header-cell.sortable:hover{background:#f3f4f6}.sort-indicator{margin-left:.5rem;font-size:.75rem;color:#3b82f6}.table-row{transition:all .15s;cursor:pointer}.juvo-table.hoverable .table-row:hover{background:#f9fafb}.table-row.selected{background:#eff6ff}.juvo-table.striped .table-row:nth-child(2n){background:#fafafa}.juvo-table.striped .table-row:nth-child(2n):hover{background:#f3f4f6}.table-cell{color:#374151;font-size:.875rem;border-bottom:1px solid #f3f4f6;vertical-align:middle}.juvo-table.gridlines .table-cell{border-right:1px solid #f3f4f6}.juvo-table.gridlines .table-cell:last-child{border-right:none}.selection-column,.selection-cell{width:3rem;text-align:center}.selection-cell input[type=checkbox]{margin:0}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.juvo-table-small .table-header-cell,.juvo-table-small .table-cell{padding:.5rem;font-size:.8125rem}.juvo-table-medium .table-header-cell,.juvo-table-medium .table-cell{padding:.75rem;font-size:.875rem}.juvo-table-large .table-header-cell,.juvo-table-large .table-cell{padding:1rem;font-size:1rem}.action-buttons{display:flex;gap:.5rem;justify-content:center}.action-btn{background:none;border:none;cursor:pointer;padding:.25rem;border-radius:.25rem;font-size:1rem;transition:all .15s}.action-btn:hover{background:#f3f4f6}.edit-btn:hover{background:#fef3c7}.delete-btn:hover{background:#fee2e2}.empty-row .table-cell{border-bottom:none}.empty-state{display:flex;flex-direction:column;align-items:center;justify-content:center;padding:3rem 2rem;gap:1rem}.empty-icon{font-size:3rem;opacity:.4}.empty-text{color:#9ca3af;font-size:.875rem;text-align:center}.table-pagination{display:flex;justify-content:between;align-items:center;padding:1rem;border-top:1px solid #e5e7eb;background:#fafafa}.pagination-info{color:#6b7280;font-size:.875rem;flex:1}.pagination-controls{display:flex;align-items:center;gap:1rem}.page-btn{background:#fff;border:1px solid #d1d5db;color:#374151;padding:.5rem 1rem;border-radius:.375rem;font-size:.875rem;cursor:pointer;transition:all .15s}.page-btn:hover:not(:disabled){background:#f9fafb;border-color:#9ca3af}.page-btn:disabled{opacity:.5;cursor:not-allowed}.page-info{color:#374151;font-size:.875rem;font-weight:500}@media (max-width: 768px){.table-pagination{flex-direction:column;gap:1rem}.pagination-info{text-align:center}.juvo-table-large .table-header-cell,.juvo-table-large .table-cell{padding:.75rem .5rem;font-size:.875rem}}\n"] }] }], propDecorators: { data$: [{ type: Input }], columns: [{ type: Input }], loading$: [{ type: Input }], selectionMode: [{ type: Input }], paginator: [{ type: Input }], rows: [{ type: Input }], sortMode: [{ type: Input }], showGridlines: [{ type: Input }], striped: [{ type: Input }], hoverable: [{ type: Input }], size: [{ type: Input }], emptyMessage: [{ type: Input }], loadingMessage: [{ type: Input }], rowSelected: [{ type: Output }], selectionChange: [{ type: Output }], rowClicked: [{ type: Output }], sortChange: [{ type: Output }], pageChange: [{ type: Output }], actionTriggered: [{ type: Output }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoianV2by10YWJsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy91aS1jb21wb25lbnRzL3NyYy9saWIvanV2by10YWJsZS9qdXZvLXRhYmxlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3VpLWNvbXBvbmVudHMvc3JjL2xpYi9qdXZvLXRhYmxlL2p1dm8tdGFibGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDL0MsT0FBTyxFQUFjLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7O0FBZ0J0Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdDRztBQVFILE1BQU0sT0FBTyxrQkFBa0I7SUFQL0I7UUFRRSw2QkFBNkI7UUFDcEIsVUFBSyxHQUFzQixFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFM0MsMkJBQTJCO1FBQ2xCLFlBQU8sR0FBa0IsRUFBRSxDQUFDO1FBRXJDLCtCQUErQjtRQUN0QixhQUFRLEdBQXdCLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUVuRCxxQ0FBcUM7UUFDNUIsa0JBQWEsR0FBbUMsTUFBTSxDQUFDO1FBRWhFLCtDQUErQztRQUN0QyxjQUFTLEdBQVksS0FBSyxDQUFDO1FBRXBDLDBDQUEwQztRQUNqQyxTQUFJLEdBQVcsRUFBRSxDQUFDO1FBRTNCLGtDQUFrQztRQUN6QixhQUFRLEdBQW1DLFFBQVEsQ0FBQztRQUU3RCwrQ0FBK0M7UUFDdEMsa0JBQWEsR0FBWSxJQUFJLENBQUM7UUFFdkMsaURBQWlEO1FBQ3hDLFlBQU8sR0FBWSxJQUFJLENBQUM7UUFFakMsaURBQWlE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QWE7c0JBQXJCLEtBQUs7Z0JBR0csT0FBTztzQkFBZixLQUFLO2dCQUdHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBR0csSUFBSTtzQkFBWixLQUFLO2dCQUdHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBR0csY0FBYztzQkFBdEIsS0FBSztnQkFHSSxXQUFXO3NCQUFwQixNQUFNO2dCQUdHLGVBQWU7c0JBQXhCLE1BQU07Z0JBR0csVUFBVTtzQkFBbkIsTUFBTTtnQkFHRyxVQUFVO3NCQUFuQixNQUFNO2dCQUdHLFVBQVU7c0JBQW5CLE1BQU07Z0JBR0csZUFBZTtzQkFBeEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgb2YgfSBmcm9tICdyeGpzJztcblxuLyoqXG4gKiBUYWJsZSBjb2x1bW4gY29uZmlndXJhdGlvbiBpbnRlcmZhY2VcbiAqIEBpbnRlcmZhY2UgVGFibGVDb2x1bW5cbiAqIEBzaW5jZSAyLjEuMFxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhYmxlQ29sdW1uIHtcbiAga2V5OiBzdHJpbmc7XG4gIGxhYmVsOiBzdHJpbmc7XG4gIHNvcnRhYmxlPzogYm9vbGVhbjtcbiAgd2lkdGg/OiBzdHJpbmc7XG4gIHR5cGU/OiAndGV4dCcgfCAnbnVtYmVyJyB8ICdkYXRlJyB8ICdib29sZWFuJyB8ICdhY3Rpb25zJztcbiAgYWxpZ24/OiAnbGVmdCcgfCAnY2VudGVyJyB8ICdyaWdodCc7XG59XG5cbi8qKlxuICogVGFibGUgQ29tcG9uZW50XG4gKiBcbiAqIEBkZXNjcmlwdGlvblxuICogQSBjb21wcmVoZW5zaXZlIHRhYmxlIGNvbXBvbmVudCBmb3IgZGlzcGxheWluZyBhbmQgbWFuYWdpbmcgdGFidWxhciBkYXRhLlxuICogT3JpZ2luYWxseSBkZXNpZ25lZCBmb3IgYmFja29mZmljZSBhcHBsaWNhdGlvbnMgd2l0aCBkYXRhIG1hbmFnZW1lbnQgbmVlZHMuXG4gKiBTdXBwb3J0cyBwYWdpbmF0aW9uLCBzb3J0aW5nLCBzZWxlY3Rpb24sIGFuZCBjdXN0b20gYWN0aW9ucy5cbiAqIFxuICogQGV4YW1wbGVcbiAqIGBgYGh0bWxcbiAqIDwhLS0gQmFzaWMgdGFibGUgLS0+XG4gKiA8anV2by10YWJsZVxuICogICBbZGF0YSRdPVwidGFibGVEYXRhJFwiXG4gKiAgIFtjb2x1bW5zXT1cIltcbiAqICAgICB7IGtleTogJ2lkJywgbGFiZWw6ICdJRCcsIHdpZHRoOiAnODBweCcgfSxcbiAqICAgICB7IGtleTogJ25hbWUnLCBsYWJlbDogJ05hbWUnLCBzb3J0YWJsZTogdHJ1ZSB9LFxuICogICAgIHsga2V5OiAnZW1haWwnLCBsYWJlbDogJ0VtYWlsJywgc29ydGFibGU6IHRydWUgfSxcbiAqICAgICB7IGtleTogJ2FjdGlvbnMnLCBsYWJlbDogJ0FjdGlvbnMnLCB0eXBlOiAnYWN0aW9ucycgfVxuICogICBdXCJcbiAqICAgW3BhZ2luYXRvcl09XCJ0cnVlXCJcbiAqICAgW3Jvd3NdPVwiMTBcIlxuICogICAocm93U2VsZWN0ZWQpPVwib25Sb3dTZWxlY3RlZCgkZXZlbnQpXCJcbiAqICAgKGFjdGlvblRyaWdnZXJlZCk9XCJvbkFjdGlvblRyaWdnZXJlZCgkZXZlbnQpXCI+XG4gKiA8L2p1dm8tdGFibGU+XG4gKiBcbiAqIDwhLS0gVGFibGUgd2l0aCBzZWxlY3Rpb24gLS0+XG4gKiA8anV2by10YWJsZVxuICogICBbZGF0YSRdPVwidXNlckRhdGEkXCJcbiAqICAgW2NvbHVtbnNdPVwidXNlckNvbHVtbnNcIlxuICogICBbbG9hZGluZyRdPVwidXNlckxvYWRpbmckXCJcbiAqICAgW3NlbGVjdGlvbk1vZGVdPVwiJ211bHRpcGxlJ1wiXG4gKiAgIFtwYWdpbmF0b3JdPVwidHJ1ZVwiXG4gKiAgIFtzb3J0TW9kZV09XCInc2luZ2xlJ1wiXG4gKiAgIChzZWxlY3Rpb25DaGFuZ2UpPVwib25TZWxlY3Rpb25DaGFuZ2UoJGV2ZW50KVwiPlxuICogPC9qdXZvLXRhYmxlPlxuICogYGBgXG4gKiBcbiAqIEBzZWxlY3RvciBqdXZvLXRhYmxlXG4gKiBAc2luY2UgMi4xLjBcbiAqIEBhdXRob3IgSnV2byBSYWZhIFRlYW1cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnanV2by10YWJsZScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vanV2by10YWJsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9qdXZvLXRhYmxlLmNvbXBvbmVudC5jc3MnXG59KVxuZXhwb3J0IGNsYXNzIEp1dm9UYWJsZUNvbXBvbmVudCB7XG4gIC8qKiBPYnNlcnZhYmxlIGRhdGEgc291cmNlICovXG4gIEBJbnB1dCgpIGRhdGEkOiBPYnNlcnZhYmxlPGFueVtdPiA9IG9mKFtdKTtcbiAgXG4gIC8qKiBDb2x1bW4gY29uZmlndXJhdGlvbiAqL1xuICBASW5wdXQoKSBjb2x1bW5zOiBUYWJsZUNvbHVtbltdID0gW107XG4gIFxuICAvKiogTG9hZGluZyBzdGF0ZSBvYnNlcnZhYmxlICovXG4gIEBJbnB1dCgpIGxvYWRpbmckOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gb2YoZmFsc2UpO1xuICBcbiAgLyoqIFNlbGVjdGlvbiBtb2RlIEBkZWZhdWx0IFwibm9uZVwiICovXG4gIEBJbnB1dCgpIHNlbGVjdGlvbk1vZGU6ICdub25lJyB8ICdzaW5nbGUnIHwgJ211bHRpcGxlJyA9ICdub25lJztcbiAgXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgcGFnaW5hdG9yIEBkZWZhdWx0IGZhbHNlICovXG4gIEBJbnB1dCgpIHBhZ2luYXRvcjogYm9vbGVhbiA9IGZhbHNlO1xuICBcbiAgLyoqIE51bWJlciBvZiByb3dzIHBlciBwYWdlIEBkZWZhdWx0IDEwICovXG4gIEBJbnB1dCgpIHJvd3M6IG51bWJlciA9IDEwO1xuICBcbiAgLyoqIFNvcnQgbW9kZSBAZGVmYXVsdCBcInNpbmdsZVwiICovXG4gIEBJbnB1dCgpIHNvcnRNb2RlOiAnbm9uZScgfCAnc2luZ2xlJyB8ICdtdWx0aXBsZScgPSAnc2luZ2xlJztcbiAgXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgZ3JpZCBsaW5lcyBAZGVmYXVsdCB0cnVlICovXG4gIEBJbnB1dCgpIHNob3dHcmlkbGluZXM6IGJvb2xlYW4gPSB0cnVlO1xuICBcbiAgLyoqIFdoZXRoZXIgdG8gc2hvdyBzdHJpcGVkIHJvd3MgQGRlZmF1bHQgdHJ1ZSAqL1xuICBASW5wdXQoKSBzdHJpcGVkOiBib29sZWFuID0gdHJ1ZTtcbiAgXG4gIC8qKiBXaGV0aGVyIHRvIHNob3cgaG92ZXIgZWZmZWN0IEBkZWZhdWx0IHRydWUgKi9cbiAgQElucHV0KCkgaG92ZXJhYmxlOiBib29sZWFuID0gdHJ1ZTtcbiAgXG4gIC8qKiBUYWJsZSBzaXplIHZhcmlhbnQgQGRlZmF1bHQgXCJtZWRpdW1cIiAqL1xuICBASW5wdXQoKSBzaXplOiAnc21hbGwnIHwgJ21lZGl1bScgfCAnbGFyZ2UnID0gJ21lZGl1bSc7XG4gIFxuICAvKiogRW1wdHkgc3RhdGUgbWVzc2FnZSAqL1xuICBASW5wdXQoKSBlbXB0eU1lc3NhZ2U6IHN0cmluZyA9ICdObyByZWNvcmRzIGZvdW5kJztcbiAgXG4gIC8qKiBMb2FkaW5nIG1lc3NhZ2UgKi9cbiAgQElucHV0KCkgbG9hZGluZ01lc3NhZ2U6IHN0cmluZyA9ICdMb2FkaW5nIGRhdGEuLi4nO1xuICBcbiAgLyoqIEVtaXR0ZWQgd2hlbiBhIHJvdyBpcyBzZWxlY3RlZCAqL1xuICBAT3V0cHV0KCkgcm93U2VsZWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgXG4gIC8qKiBFbWl0dGVkIHdoZW4gc2VsZWN0aW9uIGNoYW5nZXMgKi9cbiAgQE91dHB1dCgpIHNlbGVjdGlvbkNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55W10+KCk7XG4gIFxuICAvKiogRW1pdHRlZCB3aGVuIGEgcm93IGlzIGNsaWNrZWQgKi9cbiAgQE91dHB1dCgpIHJvd0NsaWNrZWQgPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcbiAgXG4gIC8qKiBFbWl0dGVkIHdoZW4gY29sdW1uIGlzIHNvcnRlZCAqL1xuICBAT3V0cHV0KCkgc29ydENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8eyBmaWVsZDogc3RyaW5nLCBvcmRlcjogJ2FzYycgfCAnZGVzYycgfT4oKTtcbiAgXG4gIC8qKiBFbWl0dGVkIHdoZW4gcGFnZSBjaGFuZ2VzICovXG4gIEBPdXRwdXQoKSBwYWdlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjx7IGZpcnN0OiBudW1iZXIsIHJvd3M6IG51bWJlciB9PigpO1xuICBcbiAgLyoqIEVtaXR0ZWQgd2hlbiBhbiBhY3Rpb24gaXMgdHJpZ2dlcmVkICovXG4gIEBPdXRwdXQoKSBhY3Rpb25UcmlnZ2VyZWQgPSBuZXcgRXZlbnRFbWl0dGVyPHsgYWN0aW9uOiBzdHJpbmcsIGl0ZW06IGFueSB9PigpO1xuXG4gIHNlbGVjdGVkUm93czogYW55W10gPSBbXTtcbiAgY3VycmVudFBhZ2UgPSAwO1xuICBzb3J0RmllbGQ/OiBzdHJpbmc7XG4gIHNvcnRPcmRlcjogJ2FzYycgfCAnZGVzYycgPSAnYXNjJztcbiAgcGFnaW5hdGVkRGF0YTogYW55W10gPSBbXTtcbiAgdG90YWxSZWNvcmRzID0gMDtcblxuICAvLyBFeHBvc2UgTWF0aCBmb3IgdGVtcGxhdGVcbiAgTWF0aCA9IE1hdGg7XG5cbiAgLyoqXG4gICAqIEdldHMgQ1NTIGNsYXNzZXMgZm9yIHRoZSB0YWJsZSBjb250YWluZXJcbiAgICogQHJldHVybnMgQ29tYmluZWQgQ1NTIGNsYXNzZXNcbiAgICovXG4gIGdldCBjb250YWluZXJDbGFzc2VzKCk6IHN0cmluZyB7XG4gICAgbGV0IGNsYXNzZXMgPSBganV2by10YWJsZSBqdXZvLXRhYmxlLSR7dGhpcy5zaXplfWA7XG4gICAgaWYgKHRoaXMuc2hvd0dyaWRsaW5lcykgY2xhc3NlcyArPSAnIGdyaWRsaW5lcyc7XG4gICAgaWYgKHRoaXMuc3RyaXBlZCkgY2xhc3NlcyArPSAnIHN0cmlwZWQnO1xuICAgIGlmICh0aGlzLmhvdmVyYWJsZSkgY2xhc3NlcyArPSAnIGhvdmVyYWJsZSc7XG4gICAgcmV0dXJuIGNsYXNzZXM7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyByb3cgc2VsZWN0aW9uXG4gICAqL1xuICBvblJvd1NlbGVjdChyb3c6IGFueSwgZXZlbnQ/OiBFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICdub25lJykgcmV0dXJuO1xuICAgIFxuICAgIGlmIChldmVudCkge1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgfVxuICAgIFxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5zZWxlY3RlZFJvd3MuZmluZEluZGV4KHNlbGVjdGVkID0+IHNlbGVjdGVkID09PSByb3cpO1xuICAgIFxuICAgIGlmICh0aGlzLnNlbGVjdGlvbk1vZGUgPT09ICdzaW5nbGUnKSB7XG4gICAgICB0aGlzLnNlbGVjdGVkUm93cyA9IGluZGV4ID4gLTEgPyBbXSA6IFtyb3ddO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zZWxlY3Rpb25Nb2RlID09PSAnbXVsdGlwbGUnKSB7XG4gICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICB0aGlzLnNlbGVjdGVkUm93cy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5zZWxlY3RlZFJvd3MucHVzaChyb3cpO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICB0aGlzLnJvd1NlbGVjdGVkLmVtaXQocm93KTtcbiAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWRSb3dzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHJvdyBjbGlja1xuICAgKi9cbiAgb25Sb3dDbGljayhyb3c6IGFueSk6IHZvaWQge1xuICAgIHRoaXMucm93Q2xpY2tlZC5lbWl0KHJvdyk7XG4gIH1cblxuICAvKipcbiAgICogSGFuZGxlcyBjb2x1bW4gc29ydFxuICAgKi9cbiAgb25Tb3J0KGNvbHVtbjogVGFibGVDb2x1bW4pOiB2b2lkIHtcbiAgICBpZiAoIWNvbHVtbi5zb3J0YWJsZSB8fCB0aGlzLnNvcnRNb2RlID09PSAnbm9uZScpIHJldHVybjtcbiAgICBcbiAgICBpZiAodGhpcy5zb3J0RmllbGQgPT09IGNvbHVtbi5rZXkpIHtcbiAgICAgIHRoaXMuc29ydE9yZGVyID0gdGhpcy5zb3J0T3JkZXIgPT09ICdhc2MnID8gJ2Rlc2MnIDogJ2FzYyc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc29ydEZpZWxkID0gY29sdW1uLmtleTtcbiAgICAgIHRoaXMuc29ydE9yZGVyID0gJ2FzYyc7XG4gICAgfVxuICAgIFxuICAgIHRoaXMuc29ydENoYW5nZS5lbWl0KHsgZmllbGQ6IGNvbHVtbi5rZXksIG9yZGVyOiB0aGlzLnNvcnRPcmRlciB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHNlbGVjdCBhbGwgY2hlY2tib3hcbiAgICovXG4gIHNlbGVjdEFsbChldmVudDogRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBjaGVja2JveCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xuICAgIC8vIFRoaXMgd291bGQgbmVlZCB0byBiZSBpbXBsZW1lbnRlZCBiYXNlZCBvbiBjdXJyZW50IGRhdGFcbiAgICAvLyBGb3Igbm93LCBqdXN0IGVtaXQgdGhlIHNlbGVjdGlvbiBjaGFuZ2VcbiAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZS5lbWl0KHRoaXMuc2VsZWN0ZWRSb3dzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIHByZXZpb3VzIHBhZ2UgbmF2aWdhdGlvblxuICAgKi9cbiAgcHJldmlvdXNQYWdlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmN1cnJlbnRQYWdlID4gMCkge1xuICAgICAgdGhpcy5jdXJyZW50UGFnZS0tO1xuICAgICAgdGhpcy5wYWdlQ2hhbmdlLmVtaXQoeyBmaXJzdDogdGhpcy5jdXJyZW50UGFnZSAqIHRoaXMucm93cywgcm93czogdGhpcy5yb3dzIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIG5leHQgcGFnZSBuYXZpZ2F0aW9uXG4gICAqL1xuICBuZXh0UGFnZSgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRQYWdlKys7XG4gICAgdGhpcy5wYWdlQ2hhbmdlLmVtaXQoeyBmaXJzdDogdGhpcy5jdXJyZW50UGFnZSAqIHRoaXMucm93cywgcm93czogdGhpcy5yb3dzIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBpZiBhIHJvdyBpcyBzZWxlY3RlZFxuICAgKi9cbiAgaXNTZWxlY3RlZChyb3c6IGFueSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkUm93cy5pbmNsdWRlcyhyb3cpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGRpc3BsYXkgdmFsdWUgZm9yIGEgY2VsbFxuICAgKi9cbiAgZ2V0Q2VsbFZhbHVlKGl0ZW06IGFueSwgY29sdW1uOiBUYWJsZUNvbHVtbik6IHN0cmluZyB7XG4gICAgY29uc3QgdmFsdWUgPSBpdGVtW2NvbHVtbi5rZXldO1xuICAgIFxuICAgIHN3aXRjaCAoY29sdW1uLnR5cGUpIHtcbiAgICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgICByZXR1cm4gdmFsdWUgPyAn4pyFJyA6ICfinYwnO1xuICAgICAgY2FzZSAnZGF0ZSc6XG4gICAgICAgIHJldHVybiB2YWx1ZSA/IG5ldyBEYXRlKHZhbHVlKS50b0xvY2FsZURhdGVTdHJpbmcoKSA6ICcnO1xuICAgICAgY2FzZSAnbnVtYmVyJzpcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgPyB2YWx1ZS50b0xvY2FsZVN0cmluZygpIDogJyc7XG4gICAgICBjYXNlICdhY3Rpb25zJzpcbiAgICAgICAgcmV0dXJuICcnOyAvLyBBY3Rpb25zIGFyZSBoYW5kbGVkIHNlcGFyYXRlbHlcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiB2YWx1ZT8udG9TdHJpbmcoKSB8fCAnJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBDU1MgY2xhc3NlcyBmb3IgY29sdW1uIGhlYWRlclxuICAgKi9cbiAgZ2V0SGVhZGVyQ2xhc3Nlcyhjb2x1bW46IFRhYmxlQ29sdW1uKTogc3RyaW5nIHtcbiAgICBsZXQgY2xhc3NlcyA9ICd0YWJsZS1oZWFkZXItY2VsbCc7XG4gICAgaWYgKGNvbHVtbi5zb3J0YWJsZSkgY2xhc3NlcyArPSAnIHNvcnRhYmxlJztcbiAgICBpZiAodGhpcy5zb3J0RmllbGQgPT09IGNvbHVtbi5rZXkpIGNsYXNzZXMgKz0gYCBzb3J0ZWQtJHt0aGlzLnNvcnRPcmRlcn1gO1xuICAgIGlmIChjb2x1bW4uYWxpZ24pIGNsYXNzZXMgKz0gYCB0ZXh0LSR7Y29sdW1uLmFsaWdufWA7XG4gICAgcmV0dXJuIGNsYXNzZXM7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyBDU1MgY2xhc3NlcyBmb3IgdGFibGUgY2VsbFxuICAgKi9cbiAgZ2V0Q2VsbENsYXNzZXMoY29sdW1uOiBUYWJsZUNvbHVtbik6IHN0cmluZyB7XG4gICAgbGV0IGNsYXNzZXMgPSAndGFibGUtY2VsbCc7XG4gICAgaWYgKGNvbHVtbi5hbGlnbikgY2xhc3NlcyArPSBgIHRleHQtJHtjb2x1bW4uYWxpZ259YDtcbiAgICByZXR1cm4gY2xhc3NlcztcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGVzIGFjdGlvbiBidXR0b24gY2xpY2tcbiAgICovXG4gIG9uQWN0aW9uKGFjdGlvbjogc3RyaW5nLCBpdGVtOiBhbnkpOiB2b2lkIHtcbiAgICB0aGlzLmFjdGlvblRyaWdnZXJlZC5lbWl0KHsgYWN0aW9uLCBpdGVtIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYWNrIGJ5IGZ1bmN0aW9uIGZvciBuZ0ZvclxuICAgKi9cbiAgdHJhY2tCeUZuKGluZGV4OiBudW1iZXIsIGl0ZW06IGFueSk6IGFueSB7XG4gICAgcmV0dXJuIGl0ZW0uaWQgfHwgaW5kZXg7XG4gIH1cbn0gIiwiPGRpdiBbY2xhc3NdPVwiY29udGFpbmVyQ2xhc3Nlc1wiPlxuICA8IS0tIExvYWRpbmcgU3RhdGUgLS0+XG4gIDxkaXYgY2xhc3M9XCJ0YWJsZS1sb2FkaW5nXCIgKm5nSWY9XCJsb2FkaW5nJCB8IGFzeW5jXCI+XG4gICAgPGRpdiBjbGFzcz1cImxvYWRpbmctc3Bpbm5lclwiPjwvZGl2PlxuICAgIDxkaXYgY2xhc3M9XCJsb2FkaW5nLXRleHRcIj57eyBsb2FkaW5nTWVzc2FnZSB9fTwvZGl2PlxuICA8L2Rpdj5cblxuICA8IS0tIFRhYmxlIENvbnRlbnQgLS0+XG4gIDxkaXYgY2xhc3M9XCJ0YWJsZS13cmFwcGVyXCIgKm5nSWY9XCIhKGxvYWRpbmckIHwgYXN5bmMpXCI+XG4gICAgPHRhYmxlIGNsYXNzPVwidGFibGVcIj5cbiAgICAgIDwhLS0gSGVhZGVyIC0tPlxuICAgICAgPHRoZWFkPlxuICAgICAgICA8dHI+XG4gICAgICAgICAgPCEtLSBTZWxlY3Rpb24gY29sdW1uIC0tPlxuICAgICAgICAgIDx0aCAqbmdJZj1cInNlbGVjdGlvbk1vZGUgIT09ICdub25lJ1wiIGNsYXNzPVwic2VsZWN0aW9uLWNvbHVtblwiPlxuICAgICAgICAgICAgPGlucHV0IFxuICAgICAgICAgICAgICAqbmdJZj1cInNlbGVjdGlvbk1vZGUgPT09ICdtdWx0aXBsZSdcIlxuICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIiBcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJzZWxlY3RBbGwoJGV2ZW50KVwiPlxuICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgXG4gICAgICAgICAgPCEtLSBEYXRhIGNvbHVtbnMgLS0+XG4gICAgICAgICAgPHRoIFxuICAgICAgICAgICAgKm5nRm9yPVwibGV0IGNvbHVtbiBvZiBjb2x1bW5zXCJcbiAgICAgICAgICAgIFtjbGFzc109XCJnZXRIZWFkZXJDbGFzc2VzKGNvbHVtbilcIlxuICAgICAgICAgICAgW3N0eWxlLndpZHRoXT1cImNvbHVtbi53aWR0aFwiXG4gICAgICAgICAgICAoY2xpY2spPVwib25Tb3J0KGNvbHVtbilcIj5cbiAgICAgICAgICAgIHt7IGNvbHVtbi5sYWJlbCB9fVxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzb3J0LWluZGljYXRvclwiICpuZ0lmPVwiY29sdW1uLnNvcnRhYmxlICYmIHNvcnRGaWVsZCA9PT0gY29sdW1uLmtleVwiPlxuICAgICAgICAgICAgICB7eyBzb3J0T3JkZXIgPT09ICdhc2MnID8gJ+KGkScgOiAn4oaTJyB9fVxuICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgIDwvdGg+XG4gICAgICAgIDwvdHI+XG4gICAgICA8L3RoZWFkPlxuXG4gICAgICA8IS0tIEJvZHkgLS0+XG4gICAgICA8dGJvZHk+XG4gICAgICAgIDwhLS0gRGF0YSByb3dzIC0tPlxuICAgICAgICA8dHIgXG4gICAgICAgICAgKm5nRm9yPVwibGV0IHJvdyBvZiBkYXRhJCB8IGFzeW5jOyB0cmFja0J5OiB0cmFja0J5Rm5cIlxuICAgICAgICAgIGNsYXNzPVwidGFibGUtcm93XCJcbiAgICAgICAgICBbY2xhc3Muc2VsZWN0ZWRdPVwiaXNTZWxlY3RlZChyb3cpXCJcbiAgICAgICAgICAoY2xpY2spPVwib25Sb3dDbGljayhyb3cpXCI+XG4gICAgICAgICAgXG4gICAgICAgICAgPCEtLSBTZWxlY3Rpb24gY2VsbCAtLT5cbiAgICAgICAgICA8dGQgKm5nSWY9XCJzZWxlY3Rpb25Nb2RlICE9PSAnbm9uZSdcIiBjbGFzcz1cInNlbGVjdGlvbi1jZWxsXCI+XG4gICAgICAgICAgICA8aW5wdXQgXG4gICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiIFxuICAgICAgICAgICAgICBbY2hlY2tlZF09XCJpc1NlbGVjdGVkKHJvdylcIlxuICAgICAgICAgICAgICAoY2hhbmdlKT1cIm9uUm93U2VsZWN0KHJvdywgJGV2ZW50KVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj5cbiAgICAgICAgICA8L3RkPlxuXG4gICAgICAgICAgPCEtLSBEYXRhIGNlbGxzIC0tPlxuICAgICAgICAgIDx0ZCBcbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29sdW1uc1wiXG4gICAgICAgICAgICBbY2xhc3NdPVwiZ2V0Q2VsbENsYXNzZXMoY29sdW1uKVwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGhdPVwiY29sdW1uLndpZHRoXCI+XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIDwhLS0gUmVndWxhciBjb250ZW50IC0tPlxuICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJjb2x1bW4udHlwZSAhPT0gJ2FjdGlvbnMnXCI+XG4gICAgICAgICAgICAgIHt7IGdldENlbGxWYWx1ZShyb3csIGNvbHVtbikgfX1cbiAgICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICAgIFxuICAgICAgICAgICAgPCEtLSBBY3Rpb25zIGNvbHVtbiAtLT5cbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJjb2x1bW4udHlwZSA9PT0gJ2FjdGlvbnMnXCIgY2xhc3M9XCJhY3Rpb24tYnV0dG9uc1wiPlxuICAgICAgICAgICAgICA8YnV0dG9uIFxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIiBcbiAgICAgICAgICAgICAgICBjbGFzcz1cImFjdGlvbi1idG4gZWRpdC1idG5cIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkFjdGlvbignZWRpdCcsIHJvdyk7ICRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAgICAgdGl0bGU9XCJFZGl0XCI+XG4gICAgICAgICAgICAgICAg4pyP77iPXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICA8YnV0dG9uIFxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIiBcbiAgICAgICAgICAgICAgICBjbGFzcz1cImFjdGlvbi1idG4gZGVsZXRlLWJ0blwiXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQWN0aW9uKCdkZWxldGUnLCByb3cpOyAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxuICAgICAgICAgICAgICAgIHRpdGxlPVwiRGVsZXRlXCI+XG4gICAgICAgICAgICAgICAg8J+Xke+4j1xuICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvdGQ+XG4gICAgICAgIDwvdHI+XG5cbiAgICAgICAgPCEtLSBFbXB0eSBzdGF0ZSAtLT5cbiAgICAgICAgPHRyICpuZ0lmPVwiKGRhdGEkIHwgYXN5bmMpPy5sZW5ndGggPT09IDBcIiBjbGFzcz1cImVtcHR5LXJvd1wiPlxuICAgICAgICAgIDx0ZCBbYXR0ci5jb2xzcGFuXT1cImNvbHVtbnMubGVuZ3RoICsgKHNlbGVjdGlvbk1vZGUgIT09ICdub25lJyA/IDEgOiAwKVwiPlxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCI+XG4gICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJlbXB0eS1pY29uXCI+8J+ThDwvZGl2PlxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZW1wdHktdGV4dFwiPnt7IGVtcHR5TWVzc2FnZSB9fTwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC90ZD5cbiAgICAgICAgPC90cj5cbiAgICAgIDwvdGJvZHk+XG4gICAgPC90YWJsZT5cbiAgPC9kaXY+XG5cbiAgPCEtLSBQYWdpbmF0aW9uIC0tPlxuICA8ZGl2IGNsYXNzPVwidGFibGUtcGFnaW5hdGlvblwiICpuZ0lmPVwicGFnaW5hdG9yICYmICgoZGF0YSQgfCBhc3luYyk/Lmxlbmd0aCB8fCAwKSA+IDBcIj5cbiAgICA8ZGl2IGNsYXNzPVwicGFnaW5hdGlvbi1pbmZvXCI+XG4gICAgICBTaG93aW5nIHt7IGN1cnJlbnRQYWdlICogcm93cyArIDEgfX0gdG8ge3sgTWF0aC5taW4oKGN1cnJlbnRQYWdlICsgMSkgKiByb3dzLCB0b3RhbFJlY29yZHMpIH19IG9mIHt7IHRvdGFsUmVjb3JkcyB9fSBlbnRyaWVzXG4gICAgPC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInBhZ2luYXRpb24tY29udHJvbHNcIj5cbiAgICAgIDxidXR0b24gXG4gICAgICAgIHR5cGU9XCJidXR0b25cIiBcbiAgICAgICAgY2xhc3M9XCJwYWdlLWJ0blwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJjdXJyZW50UGFnZSA9PT0gMFwiXG4gICAgICAgIChjbGljayk9XCJwcmV2aW91c1BhZ2UoKVwiPlxuICAgICAgICBQcmV2aW91c1xuICAgICAgPC9idXR0b24+XG4gICAgICA8c3BhbiBjbGFzcz1cInBhZ2UtaW5mb1wiPlBhZ2Uge3sgY3VycmVudFBhZ2UgKyAxIH19PC9zcGFuPlxuICAgICAgPGJ1dHRvbiBcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiIFxuICAgICAgICBjbGFzcz1cInBhZ2UtYnRuXCJcbiAgICAgICAgW2Rpc2FibGVkXT1cIihjdXJyZW50UGFnZSArIDEpICogcm93cyA+PSB0b3RhbFJlY29yZHNcIlxuICAgICAgICAoY2xpY2spPVwibmV4dFBhZ2UoKVwiPlxuICAgICAgICBOZXh0XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L2Rpdj4gIl19