mat-table-ext 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +16 -0
- package/.vscode/extensions.json +4 -0
- package/.vscode/launch.json +20 -0
- package/.vscode/tasks.json +42 -0
- package/LICENSE +21 -0
- package/angular.json +150 -0
- package/package.json +46 -58
- package/projects/mat-table-ext/.browserslistrc +16 -0
- package/projects/mat-table-ext/README.md +57 -0
- package/projects/mat-table-ext/karma.conf.js +44 -0
- package/projects/mat-table-ext/ng-package.json +9 -0
- package/projects/mat-table-ext/package.json +38 -0
- package/projects/mat-table-ext/src/lib/components/column-pinning/column-pinning.component.html +7 -0
- package/projects/mat-table-ext/src/lib/components/column-pinning/column-pinning.component.scss +9 -0
- package/projects/mat-table-ext/src/lib/components/column-pinning/column-pinning.component.spec.ts +23 -0
- package/projects/mat-table-ext/src/lib/components/column-pinning/column-pinning.component.ts +48 -0
- package/projects/mat-table-ext/src/lib/components/editing/editing.component.html +55 -0
- package/projects/mat-table-ext/src/lib/components/editing/editing.component.scss +19 -0
- package/projects/mat-table-ext/src/lib/components/editing/editing.component.spec.ts +23 -0
- package/projects/mat-table-ext/src/lib/components/editing/editing.component.ts +110 -0
- package/projects/mat-table-ext/src/lib/components/filter-columns-component/filter-columns-component.component.html +26 -0
- package/projects/mat-table-ext/src/lib/components/filter-columns-component/filter-columns-component.component.scss +0 -0
- package/projects/mat-table-ext/src/lib/components/filter-columns-component/filter-columns-component.component.spec.ts +23 -0
- package/projects/mat-table-ext/src/lib/components/filter-columns-component/filter-columns-component.component.ts +54 -0
- package/projects/mat-table-ext/src/lib/directives/resize-column.directive.ts +103 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.component.html +285 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.component.spec.ts +25 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.component.ts +985 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.module.ts +127 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.scss +181 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.service.spec.ts +16 -0
- package/projects/mat-table-ext/src/lib/mat-table-ext.service.ts +12 -0
- package/projects/mat-table-ext/src/lib/models/tableExtModels.ts +85 -0
- package/{public-api.d.ts → projects/mat-table-ext/src/public-api.ts} +5 -1
- package/projects/mat-table-ext/src/test.ts +27 -0
- package/projects/mat-table-ext/tsconfig.lib.json +15 -0
- package/projects/mat-table-ext/tsconfig.lib.prod.json +10 -0
- package/projects/mat-table-ext/tsconfig.spec.json +17 -0
- package/projects/mat-table-ext-example/.browserslistrc +16 -0
- package/projects/mat-table-ext-example/karma.conf.js +44 -0
- package/projects/mat-table-ext-example/src/app/app.component.html +576 -0
- package/projects/mat-table-ext-example/src/app/app.component.scss +0 -0
- package/projects/mat-table-ext-example/src/app/app.component.spec.ts +31 -0
- package/projects/mat-table-ext-example/src/app/app.component.ts +173 -0
- package/projects/mat-table-ext-example/src/app/app.module.ts +40 -0
- package/projects/mat-table-ext-example/src/app/service/custom-table.service.spec.ts +16 -0
- package/projects/mat-table-ext-example/src/app/service/custom-table.service.ts +18 -0
- package/projects/mat-table-ext-example/src/assets/.gitkeep +0 -0
- package/projects/mat-table-ext-example/src/assets/data.json +100003 -0
- package/projects/mat-table-ext-example/src/environments/environment.prod.ts +3 -0
- package/projects/mat-table-ext-example/src/environments/environment.ts +16 -0
- package/projects/mat-table-ext-example/src/favicon.ico +0 -0
- package/projects/mat-table-ext-example/src/index.html +14 -0
- package/projects/mat-table-ext-example/src/main.ts +12 -0
- package/projects/mat-table-ext-example/src/polyfills.ts +53 -0
- package/projects/mat-table-ext-example/src/styles.scss +23 -0
- package/projects/mat-table-ext-example/src/test.ts +26 -0
- package/projects/mat-table-ext-example/tsconfig.app.json +15 -0
- package/projects/mat-table-ext-example/tsconfig.spec.json +18 -0
- package/tsconfig.json +38 -0
- package/esm2020/lib/components/column-pinning/column-pinning.component.mjs +0 -58
- package/esm2020/lib/components/editing/editing.component.mjs +0 -122
- package/esm2020/lib/components/filter-columns-component/filter-columns-component.component.mjs +0 -68
- package/esm2020/lib/directives/resize-column.directive.mjs +0 -99
- package/esm2020/lib/mat-table-ext.component.mjs +0 -1021
- package/esm2020/lib/mat-table-ext.module.mjs +0 -237
- package/esm2020/lib/mat-table-ext.service.mjs +0 -20
- package/esm2020/lib/models/tableExtModels.mjs +0 -2
- package/esm2020/mat-table-ext.mjs +0 -5
- package/esm2020/public-api.mjs +0 -11
- package/fesm2015/mat-table-ext.mjs +0 -1585
- package/fesm2015/mat-table-ext.mjs.map +0 -1
- package/fesm2020/mat-table-ext.mjs +0 -1582
- package/fesm2020/mat-table-ext.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/lib/components/column-pinning/column-pinning.component.d.ts +0 -27
- package/lib/components/editing/editing.component.d.ts +0 -42
- package/lib/components/filter-columns-component/filter-columns-component.component.d.ts +0 -26
- package/lib/directives/resize-column.directive.d.ts +0 -27
- package/lib/mat-table-ext.component.d.ts +0 -348
- package/lib/mat-table-ext.module.d.ts +0 -58
- package/lib/mat-table-ext.service.d.ts +0 -11
- package/lib/models/tableExtModels.d.ts +0 -76
- /package/{assets → projects/mat-table-ext/assets}/_theming.scss +0 -0
- /package/{assets → projects/mat-table-ext/assets}/pinIcon.svg +0 -0
- /package/{assets → projects/mat-table-ext/assets}/pinLeft.svg +0 -0
- /package/{assets → projects/mat-table-ext/assets}/pinNone.svg +0 -0
- /package/{assets → projects/mat-table-ext/assets}/pinRight.svg +0 -0
- /package/{assets → projects/mat-table-ext/assets}/pinned.svg +0 -0
|
@@ -1,1021 +0,0 @@
|
|
|
1
|
-
import { animate, state, style, transition, trigger, } from '@angular/animations';
|
|
2
|
-
import { SelectionModel } from '@angular/cdk/collections';
|
|
3
|
-
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
|
4
|
-
import { EventEmitter, Output, } from '@angular/core';
|
|
5
|
-
import { Component, Input, ViewChild, ViewEncapsulation, } from '@angular/core';
|
|
6
|
-
import { MatDialogConfig } from '@angular/material/dialog';
|
|
7
|
-
import { MatMenuTrigger } from '@angular/material/menu';
|
|
8
|
-
import { MatPaginator } from '@angular/material/paginator';
|
|
9
|
-
import { MatSort } from '@angular/material/sort';
|
|
10
|
-
import { MatTableDataSource } from '@angular/material/table';
|
|
11
|
-
import { EditingComponent } from '../lib/components/editing/editing.component';
|
|
12
|
-
import * as XLSX from 'xlsx';
|
|
13
|
-
import * as i0 from "@angular/core";
|
|
14
|
-
import * as i1 from "@angular/material/dialog";
|
|
15
|
-
import * as i2 from "../lib/mat-table-ext.service";
|
|
16
|
-
import * as i3 from "@angular/forms";
|
|
17
|
-
import * as i4 from "@angular/platform-browser";
|
|
18
|
-
import * as i5 from "@angular/material/icon";
|
|
19
|
-
import * as i6 from "@angular/common";
|
|
20
|
-
import * as i7 from "@angular/material/table";
|
|
21
|
-
import * as i8 from "@angular/cdk/drag-drop";
|
|
22
|
-
import * as i9 from "@angular/material/core";
|
|
23
|
-
import * as i10 from "@angular/material/button";
|
|
24
|
-
import * as i11 from "@angular/material/card";
|
|
25
|
-
import * as i12 from "@angular/material/checkbox";
|
|
26
|
-
import * as i13 from "@angular/material/form-field";
|
|
27
|
-
import * as i14 from "@angular/material/input";
|
|
28
|
-
import * as i15 from "@angular/material/menu";
|
|
29
|
-
import * as i16 from "@angular/material/paginator";
|
|
30
|
-
import * as i17 from "@angular/material/progress-bar";
|
|
31
|
-
import * as i18 from "@angular/material/select";
|
|
32
|
-
import * as i19 from "@angular/material/sort";
|
|
33
|
-
import * as i20 from "@angular/material/toolbar";
|
|
34
|
-
import * as i21 from "@angular/material/tooltip";
|
|
35
|
-
import * as i22 from "./directives/resize-column.directive";
|
|
36
|
-
import * as i23 from "./components/column-pinning/column-pinning.component";
|
|
37
|
-
import * as i24 from "./components/filter-columns-component/filter-columns-component.component";
|
|
38
|
-
export class MatTableExtComponent {
|
|
39
|
-
constructor(dialog, service, formBuildersService, domSanitizer, matIconRegistry, cdr) {
|
|
40
|
-
this.dialog = dialog;
|
|
41
|
-
this.service = service;
|
|
42
|
-
this.formBuildersService = formBuildersService;
|
|
43
|
-
this.domSanitizer = domSanitizer;
|
|
44
|
-
this.matIconRegistry = matIconRegistry;
|
|
45
|
-
this.cdr = cdr;
|
|
46
|
-
this.columns = [];
|
|
47
|
-
this.columnResizable = false;
|
|
48
|
-
this.stripedRows = false;
|
|
49
|
-
this.rowHover = false;
|
|
50
|
-
this.inlineRowEditing = false;
|
|
51
|
-
this.inCellEditing = false;
|
|
52
|
-
this.popupRowEditing = false;
|
|
53
|
-
this.enableDelete = false;
|
|
54
|
-
this.rowSelection = false;
|
|
55
|
-
this.multiRowSelection = false;
|
|
56
|
-
this.stickyFooter = false;
|
|
57
|
-
this.stickyHeader = false;
|
|
58
|
-
this.showFooterRow = false;
|
|
59
|
-
this.columnFilter = false;
|
|
60
|
-
this.loadingIndicator = false;
|
|
61
|
-
this.sorting = false;
|
|
62
|
-
this.showToolbar = false;
|
|
63
|
-
this.toolbarTitle = '';
|
|
64
|
-
this.tableHeight = '';
|
|
65
|
-
this.toolbarHeight = '50px';
|
|
66
|
-
this.tableWidth = '100%';
|
|
67
|
-
this.scrollbarH = false;
|
|
68
|
-
this.columnHidable = false;
|
|
69
|
-
this.columnPinnable = false;
|
|
70
|
-
this.globalSearch = false;
|
|
71
|
-
this.expandRows = false;
|
|
72
|
-
this.dndColumns = false;
|
|
73
|
-
this.showPaginator = true;
|
|
74
|
-
this.showFirstLastButtons = false;
|
|
75
|
-
this.exportButtonEnable = false;
|
|
76
|
-
this.pageSizeOptions = [10, 50, 100];
|
|
77
|
-
this.cellTemplateRefMap = {};
|
|
78
|
-
// Table outputs
|
|
79
|
-
this.inlineChange = new EventEmitter();
|
|
80
|
-
this.cellChange = new EventEmitter();
|
|
81
|
-
this.popupChange = new EventEmitter();
|
|
82
|
-
this.rowDeleted = new EventEmitter();
|
|
83
|
-
this.scroll = new EventEmitter();
|
|
84
|
-
this.selectionChanged = new EventEmitter();
|
|
85
|
-
this.expansionChange = new EventEmitter();
|
|
86
|
-
this.tableID = new Date().getTime();
|
|
87
|
-
this.columnPinningOptions = [];
|
|
88
|
-
this.exportMenuCtrl = false;
|
|
89
|
-
this.columnPinMenuCtrl = false;
|
|
90
|
-
this.hideShowMenuCtrl = false;
|
|
91
|
-
this.columnFilterBySelection = false;
|
|
92
|
-
this.rowDataTemp = {};
|
|
93
|
-
this.inlineEditingTemplateRefData = {};
|
|
94
|
-
this.displayedColumns = [];
|
|
95
|
-
this.showHideColumnsArray = [];
|
|
96
|
-
this.columnsList = [];
|
|
97
|
-
this.columnsArray = [];
|
|
98
|
-
this.headersFiltersIds = [];
|
|
99
|
-
this.columnsToDisplayWithExpand = [];
|
|
100
|
-
this.selection = new SelectionModel(false, []);
|
|
101
|
-
this.hiddenCtrl = new SelectionModel(true, []);
|
|
102
|
-
this.tableData = [];
|
|
103
|
-
this.filterValues = {};
|
|
104
|
-
this.globalFilter = '';
|
|
105
|
-
this.showHideFilter = '';
|
|
106
|
-
this.individualFilter = '';
|
|
107
|
-
this.toggleFilters = false;
|
|
108
|
-
this.hideRows = false;
|
|
109
|
-
this.currentRowIndex = -1;
|
|
110
|
-
this.currentRow = {};
|
|
111
|
-
this.cellEditing = {};
|
|
112
|
-
this.menuX = 0;
|
|
113
|
-
this.menuY = 0;
|
|
114
|
-
this.dynamicDisplayedColumns = [
|
|
115
|
-
{ filter: false, name: 'select', show: false },
|
|
116
|
-
{ filter: false, name: 'edit', show: false },
|
|
117
|
-
{ filter: false, name: 'popup', show: false },
|
|
118
|
-
{ filter: false, name: 'delete', show: false },
|
|
119
|
-
{ filter: false, name: 'expand', show: false },
|
|
120
|
-
];
|
|
121
|
-
this.inputPropertyKeys = [
|
|
122
|
-
'dataSource',
|
|
123
|
-
'columns',
|
|
124
|
-
'inlineRowEditing',
|
|
125
|
-
'popupRowEditing',
|
|
126
|
-
'enableDelete',
|
|
127
|
-
'rowSelection',
|
|
128
|
-
'multiRowSelection',
|
|
129
|
-
'stickyHeader',
|
|
130
|
-
'stickyFooter',
|
|
131
|
-
'columnFilter',
|
|
132
|
-
'globalSearch',
|
|
133
|
-
'expandRows',
|
|
134
|
-
'sorting',
|
|
135
|
-
];
|
|
136
|
-
/**
|
|
137
|
-
* @description This mapping is used to set and update changesin the table.
|
|
138
|
-
*/
|
|
139
|
-
this.setPropertiesMap = {
|
|
140
|
-
dataSource: (value) => this.setTableDataSource(value),
|
|
141
|
-
columns: (value) => this.setColumnsData(value.currentValue),
|
|
142
|
-
inlineRowEditing: (value) => this.showHideColumn('edit', value.currentValue),
|
|
143
|
-
popupRowEditing: (value) => this.showHideColumn('popup', value.currentValue),
|
|
144
|
-
enableDelete: (value) => this.showHideColumn('delete', value.currentValue),
|
|
145
|
-
rowSelection: (value) => this.setRowSelection(value.currentValue),
|
|
146
|
-
multiRowSelection: (value) => {
|
|
147
|
-
this.selection = new SelectionModel(value.currentValue, []);
|
|
148
|
-
},
|
|
149
|
-
stickyHeader: (value) => {
|
|
150
|
-
this.stickyHeader = value.currentValue;
|
|
151
|
-
},
|
|
152
|
-
stickyFooter: (value) => {
|
|
153
|
-
this.stickyFooter = value.currentValue;
|
|
154
|
-
},
|
|
155
|
-
columnFilter: (value) => this.setColumnFilter(value.currentValue),
|
|
156
|
-
globalSearch: (value) => (this.dataSource.filterPredicate = this.createFilter()),
|
|
157
|
-
expandRows: (value) => {
|
|
158
|
-
this.loadingIndicator = true;
|
|
159
|
-
this.dataSource = new MatTableDataSource(this.tableData);
|
|
160
|
-
if (value.currentValue == true) {
|
|
161
|
-
if (!this.displayedColumns.includes('expand')) {
|
|
162
|
-
this.displayedColumns.push('expand');
|
|
163
|
-
this.columnsToDisplayWithExpand = [...this.displayedColumns];
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
this.columnsToDisplayWithExpand = [...this.displayedColumns];
|
|
168
|
-
if (this.displayedColumns.includes('expand')) {
|
|
169
|
-
let index = this.displayedColumns.indexOf('expand');
|
|
170
|
-
this.displayedColumns.splice(index, 1);
|
|
171
|
-
}
|
|
172
|
-
this.expandedElement = null;
|
|
173
|
-
}
|
|
174
|
-
setTimeout(() => {
|
|
175
|
-
this.loadingIndicator = false;
|
|
176
|
-
}, 200);
|
|
177
|
-
},
|
|
178
|
-
sorting: (value) => (this.dataSource.sort = this.sort),
|
|
179
|
-
};
|
|
180
|
-
/**
|
|
181
|
-
* @description This method will take data from inline editing template and update in table data source.
|
|
182
|
-
* @param row updated row from inline editing template.
|
|
183
|
-
*/
|
|
184
|
-
this.updateInlineTemplateData = (row) => {
|
|
185
|
-
this.service.selectedRow.next(row);
|
|
186
|
-
};
|
|
187
|
-
this.addIconsToRegistry();
|
|
188
|
-
if (this.dataSource) {
|
|
189
|
-
this.tableData = this.dataSource.data;
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
/**
|
|
193
|
-
*
|
|
194
|
-
* @param changes changes captured each time user changes property value.
|
|
195
|
-
*/
|
|
196
|
-
ngOnChanges(changes) {
|
|
197
|
-
this.setPropertyValue(changes);
|
|
198
|
-
}
|
|
199
|
-
ngOnInit() {
|
|
200
|
-
if (this.dataSource) {
|
|
201
|
-
this.dataSource.filterPredicate = this.createFilter();
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
ngAfterViewInit() {
|
|
205
|
-
if (this.dataSource) {
|
|
206
|
-
this.dataSource.paginator = this.paginator;
|
|
207
|
-
this.dataSource.sort = this.sort;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
/**
|
|
211
|
-
* @description checks and updates the the column's hide and show properties.
|
|
212
|
-
*/
|
|
213
|
-
setColumnHideShow() {
|
|
214
|
-
if (this.hideShowMenuGroup !== undefined &&
|
|
215
|
-
this.hideShowMenuGroup !== null) {
|
|
216
|
-
this.updateColumnsHideShow(this.hideShowMenuGroup.value);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* @description set the properties of the table.
|
|
221
|
-
* @param changes changes captured each time user changes property value.
|
|
222
|
-
*/
|
|
223
|
-
setPropertyValue(changes) {
|
|
224
|
-
let keys = Object.keys(changes);
|
|
225
|
-
keys.forEach((property) => {
|
|
226
|
-
if (this.inputPropertyKeys.includes(property)) {
|
|
227
|
-
this.setPropertiesMap[property](changes[property]);
|
|
228
|
-
}
|
|
229
|
-
else if (property == 'showToolbar') {
|
|
230
|
-
if (changes['columns']) {
|
|
231
|
-
this.setToolbarMenuControls(changes['columns'].currentValue);
|
|
232
|
-
}
|
|
233
|
-
else {
|
|
234
|
-
this.setToolbarMenuControls(this.columnsArray);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* @description used set data source for table.
|
|
241
|
-
* @param value data source value from user.
|
|
242
|
-
*/
|
|
243
|
-
setTableDataSource(value) {
|
|
244
|
-
if (value.currentValue) {
|
|
245
|
-
this.tableData = value.currentValue.data;
|
|
246
|
-
this.dataSource = value.currentValue;
|
|
247
|
-
this.reCal();
|
|
248
|
-
}
|
|
249
|
-
else {
|
|
250
|
-
this.dataSource = new MatTableDataSource([{}]);
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
/**
|
|
254
|
-
* @description used create seletion model and set selection column visibility.
|
|
255
|
-
* @param value boolean value to show or hide selection Column from table.
|
|
256
|
-
*/
|
|
257
|
-
setRowSelection(value) {
|
|
258
|
-
this.selection = new SelectionModel(true, []);
|
|
259
|
-
this.updateSelectionColumnVisibility(value);
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* @description create filter header row and assigns filter predicate to table data source.
|
|
263
|
-
* @param value boolean value to change visibility of column filter row.
|
|
264
|
-
*/
|
|
265
|
-
setColumnFilter(value) {
|
|
266
|
-
if (value) {
|
|
267
|
-
let array = [];
|
|
268
|
-
this.columnsArray.forEach((column, i) => {
|
|
269
|
-
if (this.dynamicDisplayedColumns.filter((a) => a.name == column?.field)[0]
|
|
270
|
-
.show) {
|
|
271
|
-
array.push(column?.field + '_' + i);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
this.headersFiltersIds = array;
|
|
275
|
-
this.dataSource.filterPredicate = this.createFilter();
|
|
276
|
-
}
|
|
277
|
-
else {
|
|
278
|
-
this.headersFiltersIds = [];
|
|
279
|
-
this.dataSource.filter = '';
|
|
280
|
-
}
|
|
281
|
-
this.toggleFilters = value;
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* @description This method returns the list of visible column names.
|
|
285
|
-
* @returns list of visible column names.
|
|
286
|
-
*/
|
|
287
|
-
getDisplayedColumns() {
|
|
288
|
-
let list = this.dynamicDisplayedColumns
|
|
289
|
-
.filter((cd) => cd.show)
|
|
290
|
-
.map((cd) => cd.name);
|
|
291
|
-
return list;
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* @param menuType type of menu to open from toolbar.
|
|
295
|
-
* @param event mouse event to open menu on that location.
|
|
296
|
-
*/
|
|
297
|
-
openMenu(menuType, event) {
|
|
298
|
-
this.menuX = event.clientX;
|
|
299
|
-
this.menuY = event.clientY;
|
|
300
|
-
switch (menuType) {
|
|
301
|
-
case 'export': {
|
|
302
|
-
this.exportMenuCtrl = true;
|
|
303
|
-
this.menuTrigger.openMenu();
|
|
304
|
-
break;
|
|
305
|
-
}
|
|
306
|
-
case 'hideShow': {
|
|
307
|
-
this.hideShowMenuCtrl = true;
|
|
308
|
-
this.openHideShowMenu(this.columnsArray);
|
|
309
|
-
break;
|
|
310
|
-
}
|
|
311
|
-
case 'columnPin': {
|
|
312
|
-
this.columnPinMenuCtrl = true;
|
|
313
|
-
this.openHideShowMenu(this.columnsArray);
|
|
314
|
-
break;
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* @description triggers when menu is closed and reset the required controls.
|
|
320
|
-
*/
|
|
321
|
-
menuClosed() {
|
|
322
|
-
this.exportMenuCtrl = false;
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* @description set list of columns to display in table.
|
|
326
|
-
* @param columns columns array from user input.
|
|
327
|
-
*/
|
|
328
|
-
setColumnsData(columns) {
|
|
329
|
-
if (columns.length) {
|
|
330
|
-
this.columnsArray = [...columns];
|
|
331
|
-
this.setColumnsList(columns);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
/**
|
|
335
|
-
* @description set list of columns to display in table.
|
|
336
|
-
* @param columns columns array from user input with configurations.
|
|
337
|
-
*/
|
|
338
|
-
setColumnsList(columns) {
|
|
339
|
-
this.columnsList = [];
|
|
340
|
-
this.displayedColumns = ['select', 'edit', 'popup', 'delete'];
|
|
341
|
-
let columnsArray = [];
|
|
342
|
-
columns.forEach((col) => {
|
|
343
|
-
if (typeof col?.header == 'string') {
|
|
344
|
-
this.columnsList.push(col?.header);
|
|
345
|
-
this.displayedColumns.push(col?.field);
|
|
346
|
-
columnsArray.push({ filter: true, name: col?.field, show: !col.hide });
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
this.dynamicDisplayedColumns = [
|
|
350
|
-
{ filter: false, name: 'select', show: false },
|
|
351
|
-
{ filter: false, name: 'edit', show: false },
|
|
352
|
-
{ filter: false, name: 'popup', show: false },
|
|
353
|
-
{ filter: false, name: 'delete', show: false },
|
|
354
|
-
];
|
|
355
|
-
this.dynamicDisplayedColumns = columnsArray.concat(this.dynamicDisplayedColumns);
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* @description Take boolean value and name column and update its visibility status in table.
|
|
359
|
-
* @param name name of the column to set visibility.
|
|
360
|
-
* @param value boolean value to set visibility of the column.
|
|
361
|
-
*/
|
|
362
|
-
showHideColumn(name, value) {
|
|
363
|
-
this.dynamicDisplayedColumns.filter((a) => a.name == name)[0].show = value;
|
|
364
|
-
if (this.columnFilter) {
|
|
365
|
-
this.setColumnFilter(true);
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* @description This method will position the selection column to first and also update its visibility.
|
|
370
|
-
* @param value value used to set visibility of the selection column.
|
|
371
|
-
*/
|
|
372
|
-
updateSelectionColumnVisibility(value) {
|
|
373
|
-
let columnName = 'select';
|
|
374
|
-
let column = this.dynamicDisplayedColumns.filter((a) => a.name == columnName)[0];
|
|
375
|
-
let index = this.dynamicDisplayedColumns.findIndex((column) => column.name == columnName);
|
|
376
|
-
if (index > -1) {
|
|
377
|
-
this.dynamicDisplayedColumns.splice(index, 1);
|
|
378
|
-
this.dynamicDisplayedColumns.unshift(column);
|
|
379
|
-
this.dynamicDisplayedColumns.filter((column) => column.name == columnName)[0].show = value;
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
/**
|
|
383
|
-
* @description This method is used to update the position of column in columns array according to its dropped position.
|
|
384
|
-
* @param event CdkDragDrop used to update column position in columns array.
|
|
385
|
-
*/
|
|
386
|
-
onDrop(event) {
|
|
387
|
-
if (this.dndColumns) {
|
|
388
|
-
let adjustedValue = 0;
|
|
389
|
-
if (this.dynamicDisplayedColumns[0].name == 'select' &&
|
|
390
|
-
this.dynamicDisplayedColumns[0].show == false) {
|
|
391
|
-
adjustedValue = 1;
|
|
392
|
-
}
|
|
393
|
-
moveItemInArray(this.dynamicDisplayedColumns, event.previousIndex + adjustedValue, event.currentIndex + adjustedValue);
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* @description This method create filter predicate function which will set search value to table filters
|
|
398
|
-
* for both global and individual colum filtering.
|
|
399
|
-
* @returns returns boolean value to filter rows in table.
|
|
400
|
-
*/
|
|
401
|
-
createFilter() {
|
|
402
|
-
const tableFilterPredicate = (data, filter) => {
|
|
403
|
-
let result = true;
|
|
404
|
-
// search all column fields
|
|
405
|
-
if (this.globalFilter) {
|
|
406
|
-
let expression = '';
|
|
407
|
-
let keys = Object.keys(data);
|
|
408
|
-
keys.forEach((key) => {
|
|
409
|
-
expression =
|
|
410
|
-
expression +
|
|
411
|
-
`data.${key}.toString().trim().toLowerCase().indexOf(this.globalFilter.toLowerCase()) !== -1 ||`;
|
|
412
|
-
});
|
|
413
|
-
if (expression.charAt(expression.length - 2) +
|
|
414
|
-
expression.charAt(expression.length - 1) ==
|
|
415
|
-
'||') {
|
|
416
|
-
expression = expression.substring(0, expression.length - 2);
|
|
417
|
-
}
|
|
418
|
-
result = eval(expression);
|
|
419
|
-
}
|
|
420
|
-
if (!result) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
let searchString = JSON.parse(filter);
|
|
424
|
-
//search single column field
|
|
425
|
-
if (this.individualFilter) {
|
|
426
|
-
return (data[this.individualFilter]
|
|
427
|
-
.toString()
|
|
428
|
-
.trim()
|
|
429
|
-
.toLowerCase()
|
|
430
|
-
.indexOf(searchString[this.individualFilter].toString().toLowerCase()) !== -1);
|
|
431
|
-
}
|
|
432
|
-
return true;
|
|
433
|
-
};
|
|
434
|
-
return tableFilterPredicate;
|
|
435
|
-
}
|
|
436
|
-
/**
|
|
437
|
-
* @description assigns the search value to mat table data source to apply the filter.
|
|
438
|
-
* @param searchValue value to be searched from table rows.
|
|
439
|
-
*/
|
|
440
|
-
applyGlobalFilter(searchValue) {
|
|
441
|
-
this.globalFilter = searchValue;
|
|
442
|
-
let columns = {};
|
|
443
|
-
this.columnsArray.forEach((column) => {
|
|
444
|
-
if (column.field)
|
|
445
|
-
columns[column.field] = searchValue;
|
|
446
|
-
});
|
|
447
|
-
this.dataSource.filter = JSON.stringify(columns);
|
|
448
|
-
}
|
|
449
|
-
/**
|
|
450
|
-
* @description This method is used to apply column based filtering
|
|
451
|
-
* @param searchValue value to be searched from table rows.
|
|
452
|
-
* @param column filter will be applied based on this column field.
|
|
453
|
-
*/
|
|
454
|
-
applyColumnFilter(searchValue, column) {
|
|
455
|
-
this.individualFilter = column.field;
|
|
456
|
-
this.filterValues[column.field] = searchValue[column.field];
|
|
457
|
-
this.dataSource.filter = JSON.stringify(this.filterValues);
|
|
458
|
-
}
|
|
459
|
-
/**
|
|
460
|
-
* @description This method will take row and its index enable inline editing tools on that row.
|
|
461
|
-
* @param row row on which user wants to do edit.
|
|
462
|
-
* @param index index of the row where inline editing will be enabled.
|
|
463
|
-
*/
|
|
464
|
-
enableInlineEditing(row, index) {
|
|
465
|
-
const rowData = {};
|
|
466
|
-
rowData['e' + index] = { ...row };
|
|
467
|
-
this.rowDataTemp = rowData;
|
|
468
|
-
setTimeout(() => {
|
|
469
|
-
this.tableData[index]['editable'] = !this.tableData[index]['editable'];
|
|
470
|
-
}, 0);
|
|
471
|
-
}
|
|
472
|
-
/**
|
|
473
|
-
* @description This method will create and return data to inline editing template.
|
|
474
|
-
* @param row row on which user wants to do edit.
|
|
475
|
-
* @param index index of the row where inline editing will be enabled.
|
|
476
|
-
* @param column current column of the table.
|
|
477
|
-
*/
|
|
478
|
-
getInlineEditingData(row, index, column) {
|
|
479
|
-
this.inlineEditingTemplateRefData = {
|
|
480
|
-
row: { ...row },
|
|
481
|
-
column: { ...column },
|
|
482
|
-
index: index,
|
|
483
|
-
updateFunc: this.updateInlineTemplateData,
|
|
484
|
-
};
|
|
485
|
-
return this.inlineEditingTemplateRefData;
|
|
486
|
-
}
|
|
487
|
-
/**
|
|
488
|
-
* @description This method set data for in-cell editing.
|
|
489
|
-
* @param row row on which user wants to do edit.
|
|
490
|
-
* @param index index of the row where inline editing will be enabled.
|
|
491
|
-
*/
|
|
492
|
-
setCellData(row, index) {
|
|
493
|
-
this.currentRow = { ...row };
|
|
494
|
-
this.currentRowIndex = index;
|
|
495
|
-
this.rowDataTemp['e' + index] = { ...row };
|
|
496
|
-
}
|
|
497
|
-
/**
|
|
498
|
-
* @description This will restore the data and cencel the inline editing.
|
|
499
|
-
* @param row row on which user wants to do edit.
|
|
500
|
-
* @param index index of the row where inline editing will be enabled.
|
|
501
|
-
*/
|
|
502
|
-
cancelInlineEditing(row, index) {
|
|
503
|
-
this.tableData.filter((a, i) => i == index)[0]['editable'] =
|
|
504
|
-
!this.tableData.filter((a, i) => i == index)[0]['editable'];
|
|
505
|
-
this.dataSource = new MatTableDataSource(this.tableData);
|
|
506
|
-
this.rowDataTemp['e' + index] = {};
|
|
507
|
-
this.service.selectedRow.next(undefined);
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* @description This method will save and update the inline editing data and emit the update row and index.
|
|
511
|
-
* @param row row on which user wants to do edit.
|
|
512
|
-
* @param index index of the row where inline editing will be enabled.
|
|
513
|
-
*/
|
|
514
|
-
saveInlineEditing(row, index) {
|
|
515
|
-
if (!this.inlineEditingTemplateRef) {
|
|
516
|
-
this.tableData[index] = { ...this.rowDataTemp['e' + index] };
|
|
517
|
-
row = { ...this.rowDataTemp['e' + index] };
|
|
518
|
-
}
|
|
519
|
-
else {
|
|
520
|
-
let changedData = this.service.selectedRow.value;
|
|
521
|
-
if (changedData) {
|
|
522
|
-
this.tableData[index] = { ...changedData };
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
this.dataSource = new MatTableDataSource(this.tableData);
|
|
526
|
-
this.rowDataTemp['e' + index] = {};
|
|
527
|
-
let data = {
|
|
528
|
-
row: row,
|
|
529
|
-
index: index,
|
|
530
|
-
};
|
|
531
|
-
this.inlineChange.emit(data);
|
|
532
|
-
this.tableData[index]['editable'] = false;
|
|
533
|
-
}
|
|
534
|
-
/**
|
|
535
|
-
* @description This method will save and update the cell editing data and emit the update row and index.
|
|
536
|
-
*/
|
|
537
|
-
saveCellEditing() {
|
|
538
|
-
this.cellEditing = {};
|
|
539
|
-
let index = this.currentRowIndex;
|
|
540
|
-
if (index > -1) {
|
|
541
|
-
if (this.cellEditingTemplateRef) {
|
|
542
|
-
let changedData = this.service.selectedRow.value;
|
|
543
|
-
if (changedData) {
|
|
544
|
-
this.tableData[index] = { ...changedData };
|
|
545
|
-
}
|
|
546
|
-
}
|
|
547
|
-
else {
|
|
548
|
-
this.tableData[index] = { ...this.rowDataTemp['e' + index] };
|
|
549
|
-
}
|
|
550
|
-
this.dataSource = new MatTableDataSource(this.tableData);
|
|
551
|
-
this.rowDataTemp['e' + index] = {};
|
|
552
|
-
let data = {
|
|
553
|
-
row: { ...this.tableData[index] },
|
|
554
|
-
index: index,
|
|
555
|
-
};
|
|
556
|
-
this.currentRowIndex = -1;
|
|
557
|
-
this.cellChange.emit(data);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
/**
|
|
561
|
-
* @description This method will delete the row from the given index and emit the deleted row and index.
|
|
562
|
-
* @param row row to be deleted.
|
|
563
|
-
* @param index index of the row to be deleted.
|
|
564
|
-
*/
|
|
565
|
-
deleteRow(row, index) {
|
|
566
|
-
this.tableData.splice(index, 1);
|
|
567
|
-
this.dataSource = new MatTableDataSource(this.tableData);
|
|
568
|
-
this.dataSource.paginator = this.paginator;
|
|
569
|
-
this.dataSource.sort = this.sort;
|
|
570
|
-
this.rowDeleted.emit({ removedRow: row, fromIndex: index });
|
|
571
|
-
}
|
|
572
|
-
/**
|
|
573
|
-
* @description This method will expand or collapse the row and emit expand event.
|
|
574
|
-
* @param row row to be expanded or collapsed.
|
|
575
|
-
* @param expand value used to expand or collapse the row.
|
|
576
|
-
* @param index index of the row.
|
|
577
|
-
*/
|
|
578
|
-
expandRow(row, expand, index) {
|
|
579
|
-
if (this.expandRows) {
|
|
580
|
-
this.expansionChange.emit({ data: row, expanded: expand, index: index });
|
|
581
|
-
this.expandedElement = this.expandedElement === row ? null : row;
|
|
582
|
-
}
|
|
583
|
-
}
|
|
584
|
-
/**
|
|
585
|
-
* @description This method is used to set data for popup component and open editing dialog.
|
|
586
|
-
* @param row row which used want to edit.
|
|
587
|
-
*/
|
|
588
|
-
openEditingDialog(row) {
|
|
589
|
-
const dialogConfig = new MatDialogConfig();
|
|
590
|
-
dialogConfig.disableClose = true;
|
|
591
|
-
dialogConfig.width = '40%';
|
|
592
|
-
dialogConfig.height = '70%';
|
|
593
|
-
dialogConfig.maxWidth = '100%';
|
|
594
|
-
let rowData = { ...row };
|
|
595
|
-
dialogConfig.data = {
|
|
596
|
-
row: rowData,
|
|
597
|
-
columns: [...this.columnsArray],
|
|
598
|
-
templateRef: this.popupEditingTemplateRef,
|
|
599
|
-
};
|
|
600
|
-
this.dialog
|
|
601
|
-
.open(EditingComponent, dialogConfig)
|
|
602
|
-
.afterClosed()
|
|
603
|
-
.subscribe((data) => {
|
|
604
|
-
let index = this.tableData.indexOf(row);
|
|
605
|
-
if (data && index > -1) {
|
|
606
|
-
this.tableData[index] = data;
|
|
607
|
-
this.dataSource = new MatTableDataSource(this.tableData);
|
|
608
|
-
let dataChange = {
|
|
609
|
-
row: data,
|
|
610
|
-
index: index,
|
|
611
|
-
};
|
|
612
|
-
this.popupChange.emit(dataChange);
|
|
613
|
-
}
|
|
614
|
-
});
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* @description used to check whether all rows are selected.
|
|
618
|
-
*/
|
|
619
|
-
isAllSelected() {
|
|
620
|
-
const numSelected = this.selection.selected.length;
|
|
621
|
-
const numRows = this.dataSource.data.length;
|
|
622
|
-
return numSelected === numRows;
|
|
623
|
-
}
|
|
624
|
-
/**
|
|
625
|
-
* @description this method is used to toggle the all and no rows selection.
|
|
626
|
-
*/
|
|
627
|
-
toggleAllRows() {
|
|
628
|
-
if (this.isAllSelected()) {
|
|
629
|
-
this.selection.clear();
|
|
630
|
-
return;
|
|
631
|
-
}
|
|
632
|
-
this.selection.select(...this.dataSource.data);
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* @description This method is used return aria-label for selection column checkboxs.
|
|
636
|
-
* @param row row from table.
|
|
637
|
-
* @returns labels for selection column checkboxs.
|
|
638
|
-
*/
|
|
639
|
-
checkboxLabel(row) {
|
|
640
|
-
if (!row) {
|
|
641
|
-
return `${this.isAllSelected() ? 'deselect' : 'select'} all`;
|
|
642
|
-
}
|
|
643
|
-
return `${this.selection.isSelected(row) ? 'deselect' : 'select'} row ${row.position + 1}`;
|
|
644
|
-
}
|
|
645
|
-
/**
|
|
646
|
-
* @description create form control for columns for hiding and and pinning purpose
|
|
647
|
-
* @param columns list of columns to be displayed
|
|
648
|
-
*/
|
|
649
|
-
setToolbarMenuControls(columns) {
|
|
650
|
-
if (columns.length > 0 && this.showToolbar) {
|
|
651
|
-
const group = this.formBuildersService.group({});
|
|
652
|
-
columns.forEach((column) => {
|
|
653
|
-
const control = this.formBuildersService.control(true);
|
|
654
|
-
group.addControl(column.field, control);
|
|
655
|
-
});
|
|
656
|
-
this.hideShowMenuGroup = group;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
/**
|
|
660
|
-
* @param column current column
|
|
661
|
-
* @param event mouse event used to set the menu position
|
|
662
|
-
*/
|
|
663
|
-
openPinnablePropertyMenu(column, event) {
|
|
664
|
-
this.menuX = event.clientX;
|
|
665
|
-
this.menuY = event.clientY;
|
|
666
|
-
let options = [
|
|
667
|
-
{
|
|
668
|
-
label: 'Pin Left',
|
|
669
|
-
value: 'left',
|
|
670
|
-
selected: false,
|
|
671
|
-
field: column.field,
|
|
672
|
-
},
|
|
673
|
-
{
|
|
674
|
-
label: 'Pin Right',
|
|
675
|
-
value: 'right',
|
|
676
|
-
selected: false,
|
|
677
|
-
field: column.field,
|
|
678
|
-
},
|
|
679
|
-
{ label: 'No Pin', value: null, selected: false, field: column.field },
|
|
680
|
-
];
|
|
681
|
-
if (column.pinned && column.pinned !== null) {
|
|
682
|
-
options.forEach((opt) => {
|
|
683
|
-
if (opt.value === column.pinned) {
|
|
684
|
-
opt.selected = true;
|
|
685
|
-
}
|
|
686
|
-
});
|
|
687
|
-
}
|
|
688
|
-
else if (column.pinned == null || column.pinned == 'null') {
|
|
689
|
-
options[2].selected = true;
|
|
690
|
-
}
|
|
691
|
-
this.columnPinningOptions = options;
|
|
692
|
-
this.columnMenuTrigger.openMenu();
|
|
693
|
-
}
|
|
694
|
-
/**
|
|
695
|
-
* @description This method is used to reset menu checks when required.
|
|
696
|
-
*/
|
|
697
|
-
resetMenuChecks() {
|
|
698
|
-
this.hideShowMenuCtrl = false;
|
|
699
|
-
this.showHideColumnsArray = [];
|
|
700
|
-
this.columnPinMenuCtrl = false;
|
|
701
|
-
this.columnPinningOptions = [];
|
|
702
|
-
}
|
|
703
|
-
/**
|
|
704
|
-
* @description This method is used to filter columns for menus like pinning or hide show menu.
|
|
705
|
-
* @param value search value to filter colunms
|
|
706
|
-
*/
|
|
707
|
-
filterColumns(value) {
|
|
708
|
-
if (value !== '') {
|
|
709
|
-
this.showHideColumnsArray = this.columnsArray.filter((col) => {
|
|
710
|
-
return col.header.toLowerCase().includes(value.toLowerCase());
|
|
711
|
-
});
|
|
712
|
-
}
|
|
713
|
-
else {
|
|
714
|
-
this.showHideColumnsArray = this.columnsArray;
|
|
715
|
-
}
|
|
716
|
-
}
|
|
717
|
-
/**
|
|
718
|
-
* @description This method is used to open hide show column menu.
|
|
719
|
-
* @param columns columns array to display in hide show menu.
|
|
720
|
-
*/
|
|
721
|
-
openHideShowMenu(columns) {
|
|
722
|
-
this.showHideColumnsArray = [...columns];
|
|
723
|
-
this.columnMenuTrigger.openMenu();
|
|
724
|
-
}
|
|
725
|
-
/**
|
|
726
|
-
* @param values columns
|
|
727
|
-
*/
|
|
728
|
-
updateColumnsHideShow(values) {
|
|
729
|
-
let keys = Object.keys(values);
|
|
730
|
-
keys.forEach((key) => {
|
|
731
|
-
this.showHideColumn(key, values[key]);
|
|
732
|
-
});
|
|
733
|
-
}
|
|
734
|
-
/**
|
|
735
|
-
* @description This method is called when the table rows are scrolled.
|
|
736
|
-
* @param event scroll event
|
|
737
|
-
*/
|
|
738
|
-
onScroll(event) {
|
|
739
|
-
this.scroll.emit(event);
|
|
740
|
-
}
|
|
741
|
-
/**
|
|
742
|
-
* @param row row to be toggled
|
|
743
|
-
* @param index index of toggled row
|
|
744
|
-
*/
|
|
745
|
-
setSelectedRows(row, index) {
|
|
746
|
-
this.selection.toggle(row);
|
|
747
|
-
if (this.selection.isSelected(row)) {
|
|
748
|
-
this.selectionChanged.emit({ row: row, index: index, isSelected: true });
|
|
749
|
-
}
|
|
750
|
-
else {
|
|
751
|
-
this.selectionChanged.emit({ row: row, index: index, isSelected: false });
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* @description This method is used to display all hidden rows.
|
|
756
|
-
*/
|
|
757
|
-
showHiddenRows() {
|
|
758
|
-
this.hideRows = false;
|
|
759
|
-
this.selection.clear();
|
|
760
|
-
this.hiddenCtrl.clear();
|
|
761
|
-
}
|
|
762
|
-
/**
|
|
763
|
-
* @description This method is used to hide all selected rows.
|
|
764
|
-
*/
|
|
765
|
-
hideSelectedRows() {
|
|
766
|
-
if (!this.selection.isEmpty()) {
|
|
767
|
-
let values = [...this.selection.selected];
|
|
768
|
-
values.forEach((value) => {
|
|
769
|
-
if (!this.hiddenCtrl.isSelected(value)) {
|
|
770
|
-
this.hiddenCtrl.toggle(value);
|
|
771
|
-
}
|
|
772
|
-
});
|
|
773
|
-
this.selection.clear();
|
|
774
|
-
this.hideRows = true;
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
/**
|
|
778
|
-
* @description This method is used to recalculate the required values for table.
|
|
779
|
-
*/
|
|
780
|
-
reCal() {
|
|
781
|
-
if (this.showPaginator) {
|
|
782
|
-
this.dataSource.paginator = this.paginator;
|
|
783
|
-
}
|
|
784
|
-
if (this.sorting) {
|
|
785
|
-
this.dataSource.sort = this.sort;
|
|
786
|
-
}
|
|
787
|
-
if (this.columnFilter) {
|
|
788
|
-
this.dataSource.filterPredicate = this.createFilter();
|
|
789
|
-
}
|
|
790
|
-
}
|
|
791
|
-
/**
|
|
792
|
-
* @description This method is called in constructor method to add SVGs into icon registration.
|
|
793
|
-
*/
|
|
794
|
-
addIconsToRegistry() {
|
|
795
|
-
let y = this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/pinRight.svg`);
|
|
796
|
-
let iconNames = ['pinLeft', 'pinRight', 'pinNone', 'pinned', 'pinIcon'];
|
|
797
|
-
iconNames.forEach((icon) => {
|
|
798
|
-
this.matIconRegistry.addSvgIcon(icon, this.domSanitizer.bypassSecurityTrustResourceUrl(`assets/${icon}.svg`));
|
|
799
|
-
});
|
|
800
|
-
}
|
|
801
|
-
/**
|
|
802
|
-
* @description This method is used to export table data.
|
|
803
|
-
* @param type type of file to be exported.
|
|
804
|
-
*/
|
|
805
|
-
exportTable(type) {
|
|
806
|
-
var element = document.getElementById('matTableExt' + this.tableID);
|
|
807
|
-
var ws = XLSX.utils.table_to_sheet(element);
|
|
808
|
-
ws = this.writeSheetData(ws);
|
|
809
|
-
const wb = XLSX.utils.book_new();
|
|
810
|
-
XLSX.utils.book_append_sheet(wb, ws, 'Sheet1');
|
|
811
|
-
XLSX.writeFile(wb, `tablesheets.${type}`);
|
|
812
|
-
}
|
|
813
|
-
/**
|
|
814
|
-
* @description This method is used to split name of filter row header to get index.
|
|
815
|
-
* @param value value to be splited for index.
|
|
816
|
-
* @returns Will return index of column from value.
|
|
817
|
-
*/
|
|
818
|
-
returnIndex(value) {
|
|
819
|
-
return Number(value.split('_')[1]);
|
|
820
|
-
}
|
|
821
|
-
/**
|
|
822
|
-
* @description This method is used to manage column filtering, expanded data for exporting.
|
|
823
|
-
* @param ws work sheet
|
|
824
|
-
* @returns custom generated worksheet to be used in export.
|
|
825
|
-
*/
|
|
826
|
-
writeSheetData(ws) {
|
|
827
|
-
let displayedColumns = this.getDisplayedColumns();
|
|
828
|
-
var nMerges = this.getMergeIndex(ws['!merges'] || []);
|
|
829
|
-
var merges = ws['!merges'] || [];
|
|
830
|
-
let data = {
|
|
831
|
-
'!cols': [],
|
|
832
|
-
'!rows': [],
|
|
833
|
-
'!merges': nMerges,
|
|
834
|
-
};
|
|
835
|
-
var range = XLSX.utils.decode_range(ws['!ref'] || '');
|
|
836
|
-
let extracolumns = ['popup', 'delete', 'select', 'edit'];
|
|
837
|
-
let keys = Object.keys(ws);
|
|
838
|
-
let nKey = 'A';
|
|
839
|
-
keys.forEach((key, i) => {
|
|
840
|
-
if (ws[key]?.v && typeof ws[key]?.v === 'string') {
|
|
841
|
-
if (!extracolumns.includes(ws[key].v.toLowerCase()) &&
|
|
842
|
-
displayedColumns.includes(ws[key].v.toLowerCase())) {
|
|
843
|
-
let lastRowIndex = range?.e?.r;
|
|
844
|
-
data[key] = ws[key];
|
|
845
|
-
let chr = key.charAt(0);
|
|
846
|
-
for (let j = 2; j <= lastRowIndex; j++) {
|
|
847
|
-
if (ws[chr + (j + 1)] !== undefined &&
|
|
848
|
-
(typeof ws[chr + (j + 1)].v === 'string' ||
|
|
849
|
-
typeof ws[chr + (j + 1)].v === 'number')) {
|
|
850
|
-
data[nKey + j] = ws[chr + (j + 1)];
|
|
851
|
-
}
|
|
852
|
-
}
|
|
853
|
-
nKey = String.fromCharCode(nKey.charCodeAt(0) + 1);
|
|
854
|
-
}
|
|
855
|
-
}
|
|
856
|
-
});
|
|
857
|
-
if (this.rowSelection) {
|
|
858
|
-
let chr = 'A';
|
|
859
|
-
for (let i = 1; i < range.e.c + 1; i++) {
|
|
860
|
-
data[chr + 1] = data[String.fromCharCode(chr.charCodeAt(0) + 1) + 1];
|
|
861
|
-
chr = String.fromCharCode(chr.charCodeAt(0) + 1);
|
|
862
|
-
if (i == range.e.c) {
|
|
863
|
-
data[chr + 1] = undefined;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
if (this.rowSelection && this.expandRows) {
|
|
868
|
-
merges.forEach((merge) => {
|
|
869
|
-
data['A' + merge.s.r] = ws['A' + (merge.s.r + 1)];
|
|
870
|
-
});
|
|
871
|
-
}
|
|
872
|
-
range.e.r--;
|
|
873
|
-
let nRef = XLSX.utils.encode_range(range);
|
|
874
|
-
data['!ref'] = nRef;
|
|
875
|
-
data['!fullref'] = nRef;
|
|
876
|
-
return data;
|
|
877
|
-
}
|
|
878
|
-
getMergeIndex(merges) {
|
|
879
|
-
var arr = [];
|
|
880
|
-
merges.forEach((element) => {
|
|
881
|
-
arr.push({
|
|
882
|
-
e: {
|
|
883
|
-
r: element.e.r == 0 ? element.e.r : element.e.r - 1,
|
|
884
|
-
c: element.e.c,
|
|
885
|
-
},
|
|
886
|
-
s: {
|
|
887
|
-
r: element.s.r == 0 ? element.s.r : element.s.r - 1,
|
|
888
|
-
c: element.s.c,
|
|
889
|
-
},
|
|
890
|
-
});
|
|
891
|
-
});
|
|
892
|
-
return arr;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
MatTableExtComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MatTableExtComponent, deps: [{ token: i1.MatDialog }, { token: i2.MatTableExtService }, { token: i3.FormBuilder }, { token: i4.DomSanitizer }, { token: i5.MatIconRegistry }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
896
|
-
MatTableExtComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: MatTableExtComponent, selector: "mat-table-ext", inputs: { dataSource: "dataSource", columns: "columns", columnResizable: "columnResizable", stripedRows: "stripedRows", rowHover: "rowHover", inlineRowEditing: "inlineRowEditing", inCellEditing: "inCellEditing", popupRowEditing: "popupRowEditing", enableDelete: "enableDelete", rowSelection: "rowSelection", multiRowSelection: "multiRowSelection", stickyFooter: "stickyFooter", stickyHeader: "stickyHeader", showFooterRow: "showFooterRow", columnFilter: "columnFilter", loadingIndicator: "loadingIndicator", sorting: "sorting", showToolbar: "showToolbar", toolbarTitle: "toolbarTitle", tableHeight: "tableHeight", toolbarHeight: "toolbarHeight", tableWidth: "tableWidth", scrollbarH: "scrollbarH", toolbarTemplate: "toolbarTemplate", columnHidable: "columnHidable", columnPinnable: "columnPinnable", globalSearch: "globalSearch", expandRows: "expandRows", dndColumns: "dndColumns", showPaginator: "showPaginator", showFirstLastButtons: "showFirstLastButtons", exportButtonEnable: "exportButtonEnable", pageSizeOptions: "pageSizeOptions", toolbarTemplateRef: "toolbarTemplateRef", headerTemplateRef: "headerTemplateRef", cellTemplateRef: "cellTemplateRef", expansionTemplateRef: "expansionTemplateRef", popupEditingTemplateRef: "popupEditingTemplateRef", inlineEditingTemplateRef: "inlineEditingTemplateRef", cellEditingTemplateRef: "cellEditingTemplateRef", cellTemplateRefMap: "cellTemplateRefMap" }, outputs: { inlineChange: "inlineChange", cellChange: "cellChange", popupChange: "popupChange", rowDeleted: "rowDeleted", scroll: "scroll", selectionChanged: "selectionChanged", expansionChange: "expansionChange" }, viewQueries: [{ propertyName: "menuTrigger", first: true, predicate: MatMenuTrigger, descendants: true }, { propertyName: "columnMenuTrigger", first: true, predicate: ["columnMenuTrigger"], descendants: true }, { propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<mat-card class=\"main-table-ext-container mat-elevation-z8\" [style.width]=\"tableWidth\">\r\n <mat-form-field class=\"global-search-field\" appearance=\"fill\" *ngIf=\"globalSearch\">\r\n <mat-label>Search</mat-label>\r\n <input matInput [ngModel]=\"globalFilter\" (ngModelChange)=\"applyGlobalFilter($event)\" placeholder=\"Ex. Mia\" #input>\r\n </mat-form-field>\r\n <mat-toolbar class=\"toolbar-container\" *ngIf=\"showToolbar\" [style.height]=\"toolbarHeight?toolbarHeight:'50px'\">\r\n <span class=\"toolbar-title\" *ngIf=\"toolbarTitle\">{{toolbarTitle}}</span>\r\n <ng-container *ngIf=\"toolbarTemplateRef\" [ngTemplateOutlet]=\"toolbarTemplateRef\"></ng-container>\r\n <span class=\"example-spacer\"></span>\r\n <ng-container *ngIf=\"rowSelection || multiRowSelection\">\r\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"hideSelectedRows()\">\r\n Hide Rows\r\n </button>\r\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"showHiddenRows()\">\r\n Show All Rows\r\n </button>\r\n </ng-container>\r\n <button *ngIf=\"columnHidable\" class=\"hide-button\" mat-stroked-button color=\"primary\"\r\n (click)=\"openMenu('hideShow',$event)\" matTooltip=\"Column Visibility\" matTooltipPosition=\"above\">\r\n <mat-icon>visibility</mat-icon>\r\n </button>\r\n <button *ngIf=\"columnPinnable\" class=\"pin-button\" mat-stroked-button color=\"primary\"\r\n (click)=\"openMenu('columnPin',$event)\" matTooltip=\"Column Pinning\">\r\n <mat-icon svgIcon=\"pinIcon\"></mat-icon>\r\n </button>\r\n <button *ngIf=\"exportButtonEnable\" class=\"export-button\" mat-stroked-button color=\"primary\"\r\n (click)=\"openMenu('export',$event)\" matTooltip=\"Table Data Export\">\r\n <mat-icon>import_export</mat-icon> <span>Export</span>\r\n <mat-icon>expand_more</mat-icon>\r\n </button>\r\n <div style=\"visibility: hidden; position:fixed\" [matMenuTriggerFor]=\"menu\" [style.left.px]=\"menuX\"\r\n [style.top.px]=\"menuY\"></div>\r\n </mat-toolbar>\r\n <mat-menu #menu=\"matMenu\" (closed)=\"menuClosed()\" id=\"exportMenu\">\r\n <ng-container *ngIf=\"exportMenuCtrl\">\r\n <mat-option (click)=\"exportTable('xlsx')\">Export to Excel</mat-option>\r\n <mat-option (click)=\"exportTable('csv')\">Export to CSV</mat-option>\r\n </ng-container>\r\n </mat-menu>\r\n <div style=\"visibility: hidden; position:fixed\" #columnMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"columnMenu\"\r\n [style.left.px]=\"menuX\" [style.top.px]=\"menuY\">\r\n </div>\r\n <mat-menu #columnMenu=\"matMenu\" (closed)=\"resetMenuChecks()\">\r\n <div class=\"toolbar-menu-container\" *ngIf=\"hideShowMenuCtrl\" [formGroup]=\"hideShowMenuGroup\"\r\n (click)=\"$event.stopPropagation()\">\r\n <h4 class=\"column-headers\">Visible Columns</h4>\r\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\r\n <mat-label>Filter Columns</mat-label>\r\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <div class=\"showHide-menu-columns-list\">\r\n <div class=\"toolbar-menu-item\" *ngFor=\"let column of showHideColumnsArray\">\r\n <mat-checkbox color=\"primary\" class=\"toolbar-menu-checkbox\" style=\"width: max-content;\"\r\n [formControlName]=\"column.field\" (change)=\"setColumnHideShow()\">{{column.header}}</mat-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"toolbar-menu-container\" *ngIf=\"columnPinMenuCtrl\" (click)=\"$event.stopPropagation()\">\r\n <h4 class=\"column-headers\">Pin Columns</h4>\r\n <form class=\"example-form\">\r\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\r\n <mat-label>Filter Columns</mat-label>\r\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n </form>\r\n <div class=\"showHide-menu-columns-list\">\r\n <app-column-pinning [columns]=\"showHideColumnsArray\"></app-column-pinning>\r\n </div>\r\n </div>\r\n </mat-menu>\r\n\r\n <mat-progress-bar *ngIf=\"loadingIndicator\" mode=\"indeterminate\"></mat-progress-bar>\r\n <section id=\"tableContainer\" class=\"mat-table-ext-container\" (scroll)=\"onScroll($event)\"\r\n [style.height]=\"tableHeight ? tableHeight :'max-content'\">\r\n <table mat-table [id]=\"'matTableExt'+tableID\" [dataSource]=\"dataSource\" matSort cdkDropList\r\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\r\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\">\r\n <!-- Row selection column -->\r\n <ng-container matColumnDef=\"select\">\r\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\r\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\r\n [checked]=\"selection.hasValue() && isAllSelected()\"\r\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\r\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\r\n </mat-checkbox>\r\n </td>\r\n <ng-container *ngIf=\"showFooterRow\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n </ng-container>\r\n <!--dynamic columns are being generated here-->\r\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned == 'left' ? true:false\"\r\n [stickyEnd]=\"column.pinned == 'right' ? true:false\" *ngFor=\"let column of columnsArray; let i = index\">\r\n <th mat-header-cell *matHeaderCellDef [style.width]=\"column.width\" [style.maxWidth]=\"column.maxWidth\"\r\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\r\n [columnsResizable]=\"columnResizable\" [index]=\"i\">\r\n <span *ngIf=\"!headerTemplateRef\" matTooltip=\"{{column.headerTooltip?.value}}\"\r\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\" mat-sort-header\r\n [disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\r\n <ng-container *ngIf=\"headerTemplateRef\" [ngTemplateOutlet]=\"headerTemplateRef\"\r\n [ngTemplateOutletContext]=\"{data:column}\"></ng-container>\r\n <ng-container *ngIf=\"column.headerTemplate\" [ngTemplateOutlet]=\"column.headerTemplate\"\r\n [ngTemplateOutletContext]=\"{data:column}\"></ng-container>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\">\r\n <div *ngIf=\"!row.editable && !cellEditing[i +'_'+column.field]\"\r\n (dblclick)=\"cellEditing[i +'_'+column.field] = inCellEditing;setCellData(row,i)\"\r\n matTooltip=\"{{column.cellTooltip?.value}}\"\r\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\r\n <span\r\n *ngIf=\"!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]\">{{row[column.field]}}</span>\r\n <ng-container *ngIf=\"cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"column.cellTemplate\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"column.cellTemplate\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"cellTemplateRef\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n </div>\r\n <div *ngIf=\"row.editable || cellEditing[i +'_'+column.field]\" (click)=\"$event.stopPropagation()\">\r\n <ng-container *ngIf=\"inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]\"\r\n [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\r\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\r\n <ng-container *ngIf=\"cellEditingTemplateRef && !(row.editable)\"\r\n [ngTemplateOutlet]=\"cellEditingTemplateRef\"\r\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\r\n <ng-container *ngIf=\"!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]\">\r\n <mat-form-field *ngIf=\"column.type == 'number'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field style=\"width: 100%;\" *ngIf=\"column.type == 'string'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'date'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'selection'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\r\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\r\n <mat-option *ngFor=\"let option of column.options\" [value]=\"option\">\r\n {{option}}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" *ngIf=\"column.type == 'boolean'\"\r\n color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\r\n </ng-container>\r\n <ng-container *ngIf=\"!cellEditingTemplateRef && cellEditing[i +'_'+column.field]\">\r\n <mat-form-field *ngIf=\"column.type == 'number'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'string'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'date'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'selection'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\r\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\r\n <mat-option *ngFor=\"let option of column.options\" [value]=\"option\">\r\n {{option}}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" *ngIf=\"column.type == 'boolean'\"\r\n color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\r\n </ng-container>\r\n </div>\r\n </td>\r\n <ng-container *ngIf=\"showFooterRow\">\r\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\r\n </ng-container>\r\n </div>\r\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\r\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\r\n class=\"action-column-cells\"> Edit </th>\r\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\r\n <mat-icon class=\"edit-column-icons\" *ngIf=\"!row.editable && !row.editmodal\" aria-hidden=\"false\"\r\n (click)=\"enableInlineEditing(row,i)\" fontIcon=\"edit_note\">\r\n </mat-icon>\r\n <div class=\"inline-editing-controls\" *ngIf=\"row.editable && !row.editmodal\">\r\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"saveInlineEditing(row,i)\"\r\n fontIcon=\"done\"></mat-icon>\r\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"cancelInlineEditing(row,i)\"\r\n fontIcon=\"close\"></mat-icon>\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef> edit </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\r\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\r\n class=\"action-column-cells\"> Popup\r\n </th>\r\n <td mat-cell *matCellDef=\"let row; let i = index\">\r\n <mat-icon aria-hidden=\"false\" (click)=\"openEditingDialog(row)\" fontIcon=\"edit\">\r\n </mat-icon>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"delete\">\r\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\r\n class=\"action-column-cells\"> Delete\r\n </th>\r\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\r\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\r\n fontIcon=\"delete\">\r\n </mat-icon>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\r\n <ng-container *ngIf=\"expandRows\" matColumnDef=\"expandedDetail\">\r\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\r\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\r\n <div class=\"example-element-detail\"\r\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\r\n <ng-container *ngIf=\"expansionTemplateRef\" [ngTemplateOutlet]=\"expansionTemplateRef\"\r\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\r\n </ng-container>\r\n </div>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngFor=\"let ids of headersFiltersIds; let i=index\" [matColumnDef]=\"ids\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <div class=\"filters-container\" [class.animate]=\"toggleFilters\">\r\n <app-filter-columns-component [obj]=\"columnsArray[returnIndex(ids)]\"\r\n (filterOutput)=\"applyColumnFilter($event,columnsArray[returnIndex(ids)])\"></app-filter-columns-component>\r\n </div>\r\n </th>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" class=\"data-row\"\r\n [ngClass]=\"{'data-row':expandRows,'stripedRows':(stripedRows && i % 2 == 1),'hoverClass':rowHover, 'hidden':hiddenCtrl.isSelected(row) && hideRows,'example-expanded-row':expandedElement === row}\"\r\n (click)=\"expandRow(row, row !== expandedElement,i)\">\r\n </tr>\r\n <tr style=\"height: 0px;\" mat-header-row class=\"no-default-height\" *matHeaderRowDef=\"headersFiltersIds\">\r\n </tr>\r\n <ng-container *ngIf=\"expandRows\">\r\n <tr style=\"height: 0px;\" mat-row *matRowDef=\"let row; columns: ['expandedDetail']\"\r\n [ngClass]=\"{'example-detail-row': (expandRows && row === expandedElement),'expand-row':row !== expandedElement}\">\r\n </tr>\r\n </ng-container>\r\n <ng-container *ngIf=\"showFooterRow\">\r\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\r\n </ng-container>\r\n </table>\r\n </section>\r\n <mat-paginator *ngIf=\"showPaginator\" [pageSizeOptions]=\"pageSizeOptions\"\r\n [showFirstLastButtons]=\"showFirstLastButtons\">\r\n </mat-paginator>\r\n</mat-card>", styles: ["table{min-width:100%}.mat-table-sticky-border-elem-right{border-left:1px solid #e0e0e0}.mat-table-sticky-border-elem-left{border-right:1px solid #e0e0e0}tr.example-detail-row{display:table-row!important}.example-element-detail{overflow:hidden;display:flex}.hidden{display:none}.stripedRows{background:#eaeaea!important}.hoverClass:hover{background:#dbdbdb!important}.filters-container{overflow:hidden;max-height:0px;transition:max-height .5s ease-in-out}.animate{max-height:50px!important}.resize-handle{display:inline-block;border-right:2px solid rgb(140,140,140);position:absolute;top:0;right:0;height:100%;cursor:col-resize;opacity:0}.resize-handle:hover{width:20px}table th:hover .resize-handle{opacity:1;transition:.3s ease-in-out}.mat-table.resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}.mat-table .mat-header-cell{position:relative}.mat-table .mat-header-cell:not(:last-child) .resize-holder{cursor:col-resize;width:20px;height:100%;position:absolute;right:-10px;top:0;z-index:1}.toolbar-container{display:flex;padding:0 15px;gap:1rem;grid-auto-rows:10px;justify-content:flex-end;align-items:center}.mat-table-ext-container{width:100%;max-width:100%;overflow:auto}.column-headers{font-family:Roboto,Helvetica Neue,sans-serif}.example-spacer{flex:1 1 auto}.export-button .mat-button-wrapper{display:flex!important;width:8em;justify-content:space-around;align-items:center}.toolbar-menu-container{display:flex;flex-direction:column;margin:auto .8em;width:15em;height:20em}.toolbar-menu-item{display:flex;height:3em}.toolbar-menu-checkbox{margin-left:8%}.toolbar-menu-checkbox.mat-checkbox{width:max-content;display:flex;align-items:center}.hide-button .mat-button-wrapper,.pin-button .mat-button-wrapper{display:flex!important;width:5em;justify-content:space-around;align-items:center}.hide-button,.pin-button,.export-button{height:3em;border:2px solid currentColor!important}.showHide-menu-columns-list{height:10em;max-height:10em;overflow-y:auto}mat-card.main-table-ext-container{padding:0}.main-table-ext-container{margin:10px}.mat-column-select{width:50px!important}.data-row td,.example-expanded-row td{border-bottom-width:0!important}.action-column-cells{width:40px;height:inherit}.inline-editing-controls{display:flex}.global-search-field{width:-webkit-fill-available}\n"], dependencies: [{ kind: "directive", type: i6.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i6.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i7.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i7.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i7.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i7.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i7.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i7.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i7.MatFooterCellDef, selector: "[matFooterCellDef]" }, { kind: "directive", type: i7.MatFooterRowDef, selector: "[matFooterRowDef]", inputs: ["matFooterRowDef", "matFooterRowDefSticky"] }, { kind: "directive", type: i7.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i7.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "directive", type: i7.MatFooterCell, selector: "mat-footer-cell, td[mat-footer-cell]" }, { kind: "component", type: i7.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i7.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i7.MatFooterRow, selector: "mat-footer-row, tr[mat-footer-row]", exportAs: ["matFooterRow"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i3.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i8.CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: i8.CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "component", type: i9.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i10.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i11.MatCard, selector: "mat-card", exportAs: ["matCard"] }, { kind: "component", type: i12.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i13.MatFormField, selector: "mat-form-field", inputs: ["color", "appearance", "hideRequiredMarker", "hintLabel", "floatLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i13.MatLabel, selector: "mat-label" }, { kind: "directive", type: i14.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i15.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "directive", type: i15.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "component", type: i16.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "component", type: i17.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { kind: "component", type: i18.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex"], exportAs: ["matSelect"] }, { kind: "directive", type: i19.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i19.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i20.MatToolbar, selector: "mat-toolbar", inputs: ["color"], exportAs: ["matToolbar"] }, { kind: "directive", type: i21.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i22.ResizeColumnDirective, selector: "[columnsResizable]", inputs: ["columnsResizable", "index"] }, { kind: "component", type: i23.ColumnPinningComponent, selector: "app-column-pinning", inputs: ["columns"], outputs: ["columnsChanged"] }, { kind: "component", type: i24.FilterColumnsComponentComponent, selector: "app-filter-columns-component", inputs: ["obj"], outputs: ["filterOutput"] }], animations: [
|
|
897
|
-
trigger('detailExpand', [
|
|
898
|
-
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
899
|
-
state('expanded', style({ height: '*' })),
|
|
900
|
-
transition('expanded <=> collapsed', animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
901
|
-
]),
|
|
902
|
-
], encapsulation: i0.ViewEncapsulation.None });
|
|
903
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MatTableExtComponent, decorators: [{
|
|
904
|
-
type: Component,
|
|
905
|
-
args: [{ selector: 'mat-table-ext', encapsulation: ViewEncapsulation.None, animations: [
|
|
906
|
-
trigger('detailExpand', [
|
|
907
|
-
state('collapsed', style({ height: '0px', minHeight: '0' })),
|
|
908
|
-
state('expanded', style({ height: '*' })),
|
|
909
|
-
transition('expanded <=> collapsed', animate('300ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
|
|
910
|
-
]),
|
|
911
|
-
], template: "<mat-card class=\"main-table-ext-container mat-elevation-z8\" [style.width]=\"tableWidth\">\r\n <mat-form-field class=\"global-search-field\" appearance=\"fill\" *ngIf=\"globalSearch\">\r\n <mat-label>Search</mat-label>\r\n <input matInput [ngModel]=\"globalFilter\" (ngModelChange)=\"applyGlobalFilter($event)\" placeholder=\"Ex. Mia\" #input>\r\n </mat-form-field>\r\n <mat-toolbar class=\"toolbar-container\" *ngIf=\"showToolbar\" [style.height]=\"toolbarHeight?toolbarHeight:'50px'\">\r\n <span class=\"toolbar-title\" *ngIf=\"toolbarTitle\">{{toolbarTitle}}</span>\r\n <ng-container *ngIf=\"toolbarTemplateRef\" [ngTemplateOutlet]=\"toolbarTemplateRef\"></ng-container>\r\n <span class=\"example-spacer\"></span>\r\n <ng-container *ngIf=\"rowSelection || multiRowSelection\">\r\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"hideSelectedRows()\">\r\n Hide Rows\r\n </button>\r\n <button class=\"hide-button\" mat-stroked-button color=\"primary\" (click)=\"showHiddenRows()\">\r\n Show All Rows\r\n </button>\r\n </ng-container>\r\n <button *ngIf=\"columnHidable\" class=\"hide-button\" mat-stroked-button color=\"primary\"\r\n (click)=\"openMenu('hideShow',$event)\" matTooltip=\"Column Visibility\" matTooltipPosition=\"above\">\r\n <mat-icon>visibility</mat-icon>\r\n </button>\r\n <button *ngIf=\"columnPinnable\" class=\"pin-button\" mat-stroked-button color=\"primary\"\r\n (click)=\"openMenu('columnPin',$event)\" matTooltip=\"Column Pinning\">\r\n <mat-icon svgIcon=\"pinIcon\"></mat-icon>\r\n </button>\r\n <button *ngIf=\"exportButtonEnable\" class=\"export-button\" mat-stroked-button color=\"primary\"\r\n (click)=\"openMenu('export',$event)\" matTooltip=\"Table Data Export\">\r\n <mat-icon>import_export</mat-icon> <span>Export</span>\r\n <mat-icon>expand_more</mat-icon>\r\n </button>\r\n <div style=\"visibility: hidden; position:fixed\" [matMenuTriggerFor]=\"menu\" [style.left.px]=\"menuX\"\r\n [style.top.px]=\"menuY\"></div>\r\n </mat-toolbar>\r\n <mat-menu #menu=\"matMenu\" (closed)=\"menuClosed()\" id=\"exportMenu\">\r\n <ng-container *ngIf=\"exportMenuCtrl\">\r\n <mat-option (click)=\"exportTable('xlsx')\">Export to Excel</mat-option>\r\n <mat-option (click)=\"exportTable('csv')\">Export to CSV</mat-option>\r\n </ng-container>\r\n </mat-menu>\r\n <div style=\"visibility: hidden; position:fixed\" #columnMenuTrigger=\"matMenuTrigger\" [matMenuTriggerFor]=\"columnMenu\"\r\n [style.left.px]=\"menuX\" [style.top.px]=\"menuY\">\r\n </div>\r\n <mat-menu #columnMenu=\"matMenu\" (closed)=\"resetMenuChecks()\">\r\n <div class=\"toolbar-menu-container\" *ngIf=\"hideShowMenuCtrl\" [formGroup]=\"hideShowMenuGroup\"\r\n (click)=\"$event.stopPropagation()\">\r\n <h4 class=\"column-headers\">Visible Columns</h4>\r\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\r\n <mat-label>Filter Columns</mat-label>\r\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <div class=\"showHide-menu-columns-list\">\r\n <div class=\"toolbar-menu-item\" *ngFor=\"let column of showHideColumnsArray\">\r\n <mat-checkbox color=\"primary\" class=\"toolbar-menu-checkbox\" style=\"width: max-content;\"\r\n [formControlName]=\"column.field\" (change)=\"setColumnHideShow()\">{{column.header}}</mat-checkbox>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"toolbar-menu-container\" *ngIf=\"columnPinMenuCtrl\" (click)=\"$event.stopPropagation()\">\r\n <h4 class=\"column-headers\">Pin Columns</h4>\r\n <form class=\"example-form\">\r\n <mat-form-field appearance=\"fill\" style=\"width: -webkit-fill-available;\">\r\n <mat-label>Filter Columns</mat-label>\r\n <input matInput [(ngModel)]=\"showHideFilter\" (ngModelChange)=\"filterColumns($event)\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n </form>\r\n <div class=\"showHide-menu-columns-list\">\r\n <app-column-pinning [columns]=\"showHideColumnsArray\"></app-column-pinning>\r\n </div>\r\n </div>\r\n </mat-menu>\r\n\r\n <mat-progress-bar *ngIf=\"loadingIndicator\" mode=\"indeterminate\"></mat-progress-bar>\r\n <section id=\"tableContainer\" class=\"mat-table-ext-container\" (scroll)=\"onScroll($event)\"\r\n [style.height]=\"tableHeight ? tableHeight :'max-content'\">\r\n <table mat-table [id]=\"'matTableExt'+tableID\" [dataSource]=\"dataSource\" matSort cdkDropList\r\n cdkDropListOrientation=\"horizontal\" multiTemplateDataRows (cdkDropListDropped)=\"onDrop($event)\"\r\n (click)=\"saveCellEditing()\" [style.width]=\"scrollbarH?'max-content':'100%'\">\r\n <!-- Row selection column -->\r\n <ng-container matColumnDef=\"select\">\r\n <th mat-header-cell *matHeaderCellDef cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\">\r\n <mat-checkbox (change)=\"$event ? toggleAllRows() : null\"\r\n [checked]=\"selection.hasValue() && isAllSelected()\"\r\n [indeterminate]=\"selection.hasValue() && !isAllSelected()\" [aria-label]=\"checkboxLabel()\">\r\n </mat-checkbox>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row;let i = dataIndex\">\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" (change)=\"$event ? setSelectedRows(row,i) : null\"\r\n [checked]=\"selection.isSelected(row)\" [aria-label]=\"checkboxLabel(row)\">\r\n </mat-checkbox>\r\n </td>\r\n <ng-container *ngIf=\"showFooterRow\">\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n </ng-container>\r\n <!--dynamic columns are being generated here-->\r\n <div matColumnDef=\"{{column['field']}}\" [sticky]=\"column.pinned == 'left' ? true:false\"\r\n [stickyEnd]=\"column.pinned == 'right' ? true:false\" *ngFor=\"let column of columnsArray; let i = index\">\r\n <th mat-header-cell *matHeaderCellDef [style.width]=\"column.width\" [style.maxWidth]=\"column.maxWidth\"\r\n [style.minWidth]=\"column.minWidth\" cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"!dndColumns\"\r\n [columnsResizable]=\"columnResizable\" [index]=\"i\">\r\n <span *ngIf=\"!headerTemplateRef\" matTooltip=\"{{column.headerTooltip?.value}}\"\r\n [matTooltipPosition]=\"column?.headerTooltip?.tooltipPosition!\" mat-sort-header\r\n [disabled]=\"!sorting || column.disabled === true\">{{column.header}}</span>\r\n <ng-container *ngIf=\"headerTemplateRef\" [ngTemplateOutlet]=\"headerTemplateRef\"\r\n [ngTemplateOutletContext]=\"{data:column}\"></ng-container>\r\n <ng-container *ngIf=\"column.headerTemplate\" [ngTemplateOutlet]=\"column.headerTemplate\"\r\n [ngTemplateOutletContext]=\"{data:column}\"></ng-container>\r\n </th>\r\n <td mat-cell *matCellDef=\"let row ;let i=dataIndex\">\r\n <div *ngIf=\"!row.editable && !cellEditing[i +'_'+column.field]\"\r\n (dblclick)=\"cellEditing[i +'_'+column.field] = inCellEditing;setCellData(row,i)\"\r\n matTooltip=\"{{column.cellTooltip?.value}}\"\r\n [matTooltipPosition]=\"column?.cellTooltip?.tooltipPosition!\">\r\n <span\r\n *ngIf=\"!cellTemplateRef && !column?.cellTemplate && !cellTemplateRefMap[column.field]\">{{row[column.field]}}</span>\r\n <ng-container *ngIf=\"cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"column.cellTemplate\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"!cellTemplateRef && column.cellTemplate && !cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"column.cellTemplate\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n <ng-container\r\n *ngIf=\"cellTemplateRef && !column.cellTemplate && !cellTemplateRefMap[column.field]\"\r\n [ngTemplateOutlet]=\"cellTemplateRef\"\r\n [ngTemplateOutletContext]=\"{row:row,column:column,index:i}\">\r\n </ng-container>\r\n </div>\r\n <div *ngIf=\"row.editable || cellEditing[i +'_'+column.field]\" (click)=\"$event.stopPropagation()\">\r\n <ng-container *ngIf=\"inlineEditingTemplateRef && !cellEditing[i +'_'+column.field]\"\r\n [ngTemplateOutlet]=\"inlineEditingTemplateRef\"\r\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\r\n <ng-container *ngIf=\"cellEditingTemplateRef && !(row.editable)\"\r\n [ngTemplateOutlet]=\"cellEditingTemplateRef\"\r\n [ngTemplateOutletContext]=\"{data:getInlineEditingData(row,i,column)}\"></ng-container>\r\n <ng-container *ngIf=\"!inlineEditingTemplateRef && (row.editable) && rowDataTemp['e'+i]\">\r\n <mat-form-field *ngIf=\"column.type == 'number'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field style=\"width: 100%;\" *ngIf=\"column.type == 'string'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'date'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'selection'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\r\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\r\n <mat-option *ngFor=\"let option of column.options\" [value]=\"option\">\r\n {{option}}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" *ngIf=\"column.type == 'boolean'\"\r\n color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\r\n </ng-container>\r\n <ng-container *ngIf=\"!cellEditingTemplateRef && cellEditing[i +'_'+column.field]\">\r\n <mat-form-field *ngIf=\"column.type == 'number'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"number\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'string'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"text\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'date'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <input matInput type=\"date\" [(ngModel)]=\"rowDataTemp['e'+i][column.field]\"\r\n [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n <mat-form-field *ngIf=\"column.type == 'selection'\" appearance=\"outline\"\r\n class=\"inline-editing-field\">\r\n <mat-select [value]=\"rowDataTemp['e'+i][column.field]\"\r\n [(ngModel)]=\"rowDataTemp['e'+i][column.field]\">\r\n <mat-option *ngFor=\"let option of column.options\" [value]=\"option\">\r\n {{option}}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n <mat-checkbox (click)=\"$event.stopPropagation()\" *ngIf=\"column.type == 'boolean'\"\r\n color=\"primary\" [(ngModel)]=\"row[column.field]\"></mat-checkbox>\r\n </ng-container>\r\n </div>\r\n </td>\r\n <ng-container *ngIf=\"showFooterRow\">\r\n <td mat-footer-cell *matFooterCellDef> {{column.footerText}} </td>\r\n </ng-container>\r\n </div>\r\n <ng-container matColumnDef=\"edit\" stickyEnd=\"false\">\r\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\r\n class=\"action-column-cells\"> Edit </th>\r\n <td mat-cell *matCellDef=\"let row; let i = dataIndex\" class=\"inline-edit-column-cell\">\r\n <mat-icon class=\"edit-column-icons\" *ngIf=\"!row.editable && !row.editmodal\" aria-hidden=\"false\"\r\n (click)=\"enableInlineEditing(row,i)\" fontIcon=\"edit_note\">\r\n </mat-icon>\r\n <div class=\"inline-editing-controls\" *ngIf=\"row.editable && !row.editmodal\">\r\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"saveInlineEditing(row,i)\"\r\n fontIcon=\"done\"></mat-icon>\r\n <mat-icon class=\"edit-column-icons\" aria-hidden=\"false\" (click)=\"cancelInlineEditing(row,i)\"\r\n fontIcon=\"close\"></mat-icon>\r\n </div>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef> edit </td>\r\n </ng-container>\r\n <ng-container matColumnDef=\"popup\" stickyEnd=\"false\">\r\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\r\n class=\"action-column-cells\"> Popup\r\n </th>\r\n <td mat-cell *matCellDef=\"let row; let i = index\">\r\n <mat-icon aria-hidden=\"false\" (click)=\"openEditingDialog(row)\" fontIcon=\"edit\">\r\n </mat-icon>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n\r\n <ng-container matColumnDef=\"delete\">\r\n <th mat-header-cell cdkDragLockAxis=\"x\" cdkDrag [cdkDragDisabled]=\"true\" *matHeaderCellDef\r\n class=\"action-column-cells\"> Delete\r\n </th>\r\n <td mat-cell *matCellDef=\"let row;let i=dataIndex\">\r\n <mat-icon (click)=\"deleteRow(row,i)\" aria-hidden=\"false\" aria-label=\"Example home icon\"\r\n fontIcon=\"delete\">\r\n </mat-icon>\r\n </td>\r\n <td mat-footer-cell *matFooterCellDef></td>\r\n </ng-container>\r\n <!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->\r\n <ng-container *ngIf=\"expandRows\" matColumnDef=\"expandedDetail\">\r\n <td mat-cell *matCellDef=\"let element;let i=dataIndex \"\r\n [attr.colspan]=\"columnsToDisplayWithExpand.length\">\r\n <div class=\"example-element-detail\"\r\n [@detailExpand]=\"element == expandedElement ? 'expanded' : 'collapsed'\">\r\n <ng-container *ngIf=\"expansionTemplateRef\" [ngTemplateOutlet]=\"expansionTemplateRef\"\r\n [ngTemplateOutletContext]=\"{$explicit:element,row:element,index:i}\">\r\n </ng-container>\r\n </div>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngFor=\"let ids of headersFiltersIds; let i=index\" [matColumnDef]=\"ids\">\r\n <th mat-header-cell *matHeaderCellDef>\r\n <div class=\"filters-container\" [class.animate]=\"toggleFilters\">\r\n <app-filter-columns-component [obj]=\"columnsArray[returnIndex(ids)]\"\r\n (filterOutput)=\"applyColumnFilter($event,columnsArray[returnIndex(ids)])\"></app-filter-columns-component>\r\n </div>\r\n </th>\r\n </ng-container>\r\n <tr mat-header-row *matHeaderRowDef=\" getDisplayedColumns(); sticky: stickyHeader\"></tr>\r\n <tr mat-row *matRowDef=\"let row; columns:getDisplayedColumns(); let i=dataIndex;\" class=\"data-row\"\r\n [ngClass]=\"{'data-row':expandRows,'stripedRows':(stripedRows && i % 2 == 1),'hoverClass':rowHover, 'hidden':hiddenCtrl.isSelected(row) && hideRows,'example-expanded-row':expandedElement === row}\"\r\n (click)=\"expandRow(row, row !== expandedElement,i)\">\r\n </tr>\r\n <tr style=\"height: 0px;\" mat-header-row class=\"no-default-height\" *matHeaderRowDef=\"headersFiltersIds\">\r\n </tr>\r\n <ng-container *ngIf=\"expandRows\">\r\n <tr style=\"height: 0px;\" mat-row *matRowDef=\"let row; columns: ['expandedDetail']\"\r\n [ngClass]=\"{'example-detail-row': (expandRows && row === expandedElement),'expand-row':row !== expandedElement}\">\r\n </tr>\r\n </ng-container>\r\n <ng-container *ngIf=\"showFooterRow\">\r\n <tr mat-footer-row *matFooterRowDef=\"getDisplayedColumns(); sticky: stickyFooter\"></tr>\r\n </ng-container>\r\n </table>\r\n </section>\r\n <mat-paginator *ngIf=\"showPaginator\" [pageSizeOptions]=\"pageSizeOptions\"\r\n [showFirstLastButtons]=\"showFirstLastButtons\">\r\n </mat-paginator>\r\n</mat-card>", styles: ["table{min-width:100%}.mat-table-sticky-border-elem-right{border-left:1px solid #e0e0e0}.mat-table-sticky-border-elem-left{border-right:1px solid #e0e0e0}tr.example-detail-row{display:table-row!important}.example-element-detail{overflow:hidden;display:flex}.hidden{display:none}.stripedRows{background:#eaeaea!important}.hoverClass:hover{background:#dbdbdb!important}.filters-container{overflow:hidden;max-height:0px;transition:max-height .5s ease-in-out}.animate{max-height:50px!important}.resize-handle{display:inline-block;border-right:2px solid rgb(140,140,140);position:absolute;top:0;right:0;height:100%;cursor:col-resize;opacity:0}.resize-handle:hover{width:20px}table th:hover .resize-handle{opacity:1;transition:.3s ease-in-out}.mat-table.resizing{-webkit-user-select:none;user-select:none;cursor:col-resize}.mat-table .mat-header-cell{position:relative}.mat-table .mat-header-cell:not(:last-child) .resize-holder{cursor:col-resize;width:20px;height:100%;position:absolute;right:-10px;top:0;z-index:1}.toolbar-container{display:flex;padding:0 15px;gap:1rem;grid-auto-rows:10px;justify-content:flex-end;align-items:center}.mat-table-ext-container{width:100%;max-width:100%;overflow:auto}.column-headers{font-family:Roboto,Helvetica Neue,sans-serif}.example-spacer{flex:1 1 auto}.export-button .mat-button-wrapper{display:flex!important;width:8em;justify-content:space-around;align-items:center}.toolbar-menu-container{display:flex;flex-direction:column;margin:auto .8em;width:15em;height:20em}.toolbar-menu-item{display:flex;height:3em}.toolbar-menu-checkbox{margin-left:8%}.toolbar-menu-checkbox.mat-checkbox{width:max-content;display:flex;align-items:center}.hide-button .mat-button-wrapper,.pin-button .mat-button-wrapper{display:flex!important;width:5em;justify-content:space-around;align-items:center}.hide-button,.pin-button,.export-button{height:3em;border:2px solid currentColor!important}.showHide-menu-columns-list{height:10em;max-height:10em;overflow-y:auto}mat-card.main-table-ext-container{padding:0}.main-table-ext-container{margin:10px}.mat-column-select{width:50px!important}.data-row td,.example-expanded-row td{border-bottom-width:0!important}.action-column-cells{width:40px;height:inherit}.inline-editing-controls{display:flex}.global-search-field{width:-webkit-fill-available}\n"] }]
|
|
912
|
-
}], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.MatTableExtService }, { type: i3.FormBuilder }, { type: i4.DomSanitizer }, { type: i5.MatIconRegistry }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { menuTrigger: [{
|
|
913
|
-
type: ViewChild,
|
|
914
|
-
args: [MatMenuTrigger]
|
|
915
|
-
}], columnMenuTrigger: [{
|
|
916
|
-
type: ViewChild,
|
|
917
|
-
args: ['columnMenuTrigger']
|
|
918
|
-
}], paginator: [{
|
|
919
|
-
type: ViewChild,
|
|
920
|
-
args: [MatPaginator]
|
|
921
|
-
}], sort: [{
|
|
922
|
-
type: ViewChild,
|
|
923
|
-
args: [MatSort]
|
|
924
|
-
}], dataSource: [{
|
|
925
|
-
type: Input
|
|
926
|
-
}], columns: [{
|
|
927
|
-
type: Input
|
|
928
|
-
}], columnResizable: [{
|
|
929
|
-
type: Input
|
|
930
|
-
}], stripedRows: [{
|
|
931
|
-
type: Input
|
|
932
|
-
}], rowHover: [{
|
|
933
|
-
type: Input
|
|
934
|
-
}], inlineRowEditing: [{
|
|
935
|
-
type: Input
|
|
936
|
-
}], inCellEditing: [{
|
|
937
|
-
type: Input
|
|
938
|
-
}], popupRowEditing: [{
|
|
939
|
-
type: Input
|
|
940
|
-
}], enableDelete: [{
|
|
941
|
-
type: Input
|
|
942
|
-
}], rowSelection: [{
|
|
943
|
-
type: Input
|
|
944
|
-
}], multiRowSelection: [{
|
|
945
|
-
type: Input
|
|
946
|
-
}], stickyFooter: [{
|
|
947
|
-
type: Input
|
|
948
|
-
}], stickyHeader: [{
|
|
949
|
-
type: Input
|
|
950
|
-
}], showFooterRow: [{
|
|
951
|
-
type: Input
|
|
952
|
-
}], columnFilter: [{
|
|
953
|
-
type: Input
|
|
954
|
-
}], loadingIndicator: [{
|
|
955
|
-
type: Input
|
|
956
|
-
}], sorting: [{
|
|
957
|
-
type: Input
|
|
958
|
-
}], showToolbar: [{
|
|
959
|
-
type: Input
|
|
960
|
-
}], toolbarTitle: [{
|
|
961
|
-
type: Input
|
|
962
|
-
}], tableHeight: [{
|
|
963
|
-
type: Input
|
|
964
|
-
}], toolbarHeight: [{
|
|
965
|
-
type: Input
|
|
966
|
-
}], tableWidth: [{
|
|
967
|
-
type: Input
|
|
968
|
-
}], scrollbarH: [{
|
|
969
|
-
type: Input
|
|
970
|
-
}], toolbarTemplate: [{
|
|
971
|
-
type: Input
|
|
972
|
-
}], columnHidable: [{
|
|
973
|
-
type: Input
|
|
974
|
-
}], columnPinnable: [{
|
|
975
|
-
type: Input
|
|
976
|
-
}], globalSearch: [{
|
|
977
|
-
type: Input
|
|
978
|
-
}], expandRows: [{
|
|
979
|
-
type: Input
|
|
980
|
-
}], dndColumns: [{
|
|
981
|
-
type: Input
|
|
982
|
-
}], showPaginator: [{
|
|
983
|
-
type: Input
|
|
984
|
-
}], showFirstLastButtons: [{
|
|
985
|
-
type: Input
|
|
986
|
-
}], exportButtonEnable: [{
|
|
987
|
-
type: Input
|
|
988
|
-
}], pageSizeOptions: [{
|
|
989
|
-
type: Input
|
|
990
|
-
}], toolbarTemplateRef: [{
|
|
991
|
-
type: Input
|
|
992
|
-
}], headerTemplateRef: [{
|
|
993
|
-
type: Input
|
|
994
|
-
}], cellTemplateRef: [{
|
|
995
|
-
type: Input
|
|
996
|
-
}], expansionTemplateRef: [{
|
|
997
|
-
type: Input
|
|
998
|
-
}], popupEditingTemplateRef: [{
|
|
999
|
-
type: Input
|
|
1000
|
-
}], inlineEditingTemplateRef: [{
|
|
1001
|
-
type: Input
|
|
1002
|
-
}], cellEditingTemplateRef: [{
|
|
1003
|
-
type: Input
|
|
1004
|
-
}], cellTemplateRefMap: [{
|
|
1005
|
-
type: Input
|
|
1006
|
-
}], inlineChange: [{
|
|
1007
|
-
type: Output
|
|
1008
|
-
}], cellChange: [{
|
|
1009
|
-
type: Output
|
|
1010
|
-
}], popupChange: [{
|
|
1011
|
-
type: Output
|
|
1012
|
-
}], rowDeleted: [{
|
|
1013
|
-
type: Output
|
|
1014
|
-
}], scroll: [{
|
|
1015
|
-
type: Output
|
|
1016
|
-
}], selectionChanged: [{
|
|
1017
|
-
type: Output
|
|
1018
|
-
}], expansionChange: [{
|
|
1019
|
-
type: Output
|
|
1020
|
-
}] } });
|
|
1021
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LXRhYmxlLWV4dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9tYXQtdGFibGUtZXh0L3NyYy9saWIvbWF0LXRhYmxlLWV4dC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9tYXQtdGFibGUtZXh0L3NyYy9saWIvbWF0LXRhYmxlLWV4dC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsT0FBTyxFQUNQLEtBQUssRUFDTCxLQUFLLEVBQ0wsVUFBVSxFQUNWLE9BQU8sR0FDUixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRCxPQUFPLEVBQWUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDdEUsT0FBTyxFQUdMLFlBQVksRUFDWixNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUNMLFNBQVMsRUFDVCxLQUFLLEVBS0wsU0FBUyxFQUNULGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUV2QixPQUFPLEVBQWEsZUFBZSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUMzRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNkNBQTZDLENBQUM7QUFnQi9FLE9BQU8sS0FBSyxJQUFJLE1BQU0sTUFBTSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWlCN0IsTUFBTSxPQUFPLG9CQUFvQjtJQWlIL0IsWUFDUyxN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LEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNHLFdBQVc7c0JBQW5CLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxXQUFXO3NCQUFuQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQUNHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDRyxpQkFBaUI7c0JBQXpCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxvQkFBb0I7c0JBQTVCLEtBQUs7Z0JBQ0csdUJBQXVCO3NCQUEvQixLQUFLO2dCQUNHLHdCQUF3QjtzQkFBaEMsS0FBSztnQkFDRyxzQkFBc0I7c0JBQTlCLEtBQUs7Z0JBQ0csa0JBQWtCO3NCQUExQixLQUFLO2dCQUdJLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxXQUFXO3NCQUFwQixNQUFNO2dCQUNHLFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csTUFBTTtzQkFBZixNQUFNO2dCQUNHLGdCQUFnQjtzQkFBekIsTUFBTTtnQkFFRyxlQUFlO3NCQUF4QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBhbmltYXRlLFxyXG4gIHN0YXRlLFxyXG4gIHN0eWxlLFxyXG4gIHRyYW5zaXRpb24sXHJcbiAgdHJpZ2dlcixcclxufSBmcm9tICdAYW5ndWxhci9hbmltYXRpb25zJztcclxuaW1wb3J0IHsgU2VsZWN0aW9uTW9kZWwgfSBmcm9tICdAYW5ndWxhci9jZGsvY29sbGVjdGlvbnMnO1xyXG5pbXBvcnQgeyBDZGtEcmFnRHJvcCwgbW92ZUl0ZW1JbkFycmF5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL2RyYWctZHJvcCc7XHJcbmltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBFdmVudEVtaXR0ZXIsXHJcbiAgT3V0cHV0LFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIENvbXBvbmVudCxcclxuICBJbnB1dCxcclxuICBPbkNoYW5nZXMsXHJcbiAgT25Jbml0LFxyXG4gIFNpbXBsZUNoYW5nZXMsXHJcbiAgVGVtcGxhdGVSZWYsXHJcbiAgVmlld0NoaWxkLFxyXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBNYXREaWFsb2csIE1hdERpYWxvZ0NvbmZpZyB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XHJcbmltcG9ydCB7IE1hdE1lbnVUcmlnZ2VyIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvbWVudSc7XHJcbmltcG9ydCB7IE1hdFBhZ2luYXRvciB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3BhZ2luYXRvcic7XHJcbmltcG9ydCB7IE1hdFNvcnQgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zb3J0JztcclxuaW1wb3J0IHsgTWF0VGFibGVEYXRhU291cmNlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGUnO1xyXG5pbXBvcnQgeyBFZGl0aW5nQ29tcG9uZW50IH0gZnJvbSAnLi4vbGliL2NvbXBvbmVudHMvZWRpdGluZy9lZGl0aW5nLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7XHJcbiAgUm93Q2hhbmdlLFxyXG4gIERpc3BsYXlDb2x1bW4sXHJcbiAgTVRFeENvbHVtbixcclxuICBNVEV4Q29sdW1uUGluT3B0aW9uLFxyXG4gIFJvd1NlbGVjdGlvbkNoYW5nZSxcclxuICBDZWxsVGVtcGxhdGVSZWZNYXAsXHJcbiAgRXhwYW5zaW9uQ2hhbmdlLFxyXG4gIEZpbHRlclNlYXJjaFZhbHVlLFxyXG4gIE1URXhSb3csXHJcbiAgQ29sdW1uVmlzaWJpbGl0eSxcclxufSBmcm9tICcuLi9saWIvbW9kZWxzL3RhYmxlRXh0TW9kZWxzJztcclxuaW1wb3J0IHsgTWF0VGFibGVFeHRTZXJ2aWNlIH0gZnJvbSAnLi4vbGliL21hdC10YWJsZS1leHQuc2VydmljZSc7XHJcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gJ0Bhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXInO1xyXG5pbXBvcnQgeyBNYXRJY29uUmVnaXN0cnkgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9pY29uJztcclxuaW1wb3J0ICogYXMgWExTWCBmcm9tICd4bHN4JztcclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdtYXQtdGFibGUtZXh0JyxcclxuICB0ZW1wbGF0ZVVybDogJ21hdC10YWJsZS1leHQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWydtYXQtdGFibGUtZXh0LnNjc3MnXSxcclxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxyXG4gIGFuaW1hdGlvbnM6IFtcclxuICAgIHRyaWdnZXIoJ2RldGFpbEV4cGFuZCcsIFtcclxuICAgICAgc3RhdGUoJ2NvbGxhcHNlZCcsIHN0eWxlKHsgaGVpZ2h0OiAnMHB4JywgbWluSGVpZ2h0OiAnMCcgfSkpLFxyXG4gICAgICBzdGF0ZSgnZXhwYW5kZWQnLCBzdHlsZSh7IGhlaWdodDogJyonIH0pKSxcclxuICAgICAgdHJhbnNpdGlvbihcclxuICAgICAgICAnZXhwYW5kZWQgPD0+IGNvbGxhcHNlZCcsXHJcbiAgICAgICAgYW5pbWF0ZSgnMzAwbXMgY3ViaWMtYmV6aWVyKDAuNCwgMC4wLCAwLjIsIDEpJylcclxuICAgICAgKSxcclxuICAgIF0pLFxyXG4gIF0sXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBNYXRUYWJsZUV4dENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBBZnRlclZpZXdJbml0IHtcclxuICBAVmlld0NoaWxkKE1hdE1lbnVUcmlnZ2VyKSBtZW51VHJpZ2dlciE6IE1hdE1lbnVUcmlnZ2VyO1xyXG4gIEBWaWV3Q2hpbGQoJ2NvbHVtbk1lbnVUcmlnZ2VyJykgY29sdW1uTWVudVRyaWdnZXIhOiBNYXRNZW51VHJpZ2dlcjtcclxuICBAVmlld0NoaWxkKE1hdFBhZ2luYXRvcikgcGFnaW5hdG9yITogTWF0UGFnaW5hdG9yO1xyXG4gIEBWaWV3Q2hpbGQoTWF0U29ydCkgc29ydCE6IE1hdFNvcnQ7XHJcblxyXG4gIC8vIFRhYmxlIGlucHV0c1xyXG4gIEBJbnB1dCgpIGRhdGFTb3VyY2UhOiBNYXRUYWJsZURhdGFTb3VyY2U8YW55PjtcclxuICBASW5wdXQoKSBjb2x1bW5zOiBNVEV4Q29sdW1uW10gPSBbXTtcclxuICBASW5wdXQoKSBjb2x1bW5SZXNpemFibGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBzdHJpcGVkUm93czogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHJvd0hvdmVyOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgaW5saW5lUm93RWRpdGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGluQ2VsbEVkaXRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBwb3B1cFJvd0VkaXRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBlbmFibGVEZWxldGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSByb3dTZWxlY3Rpb246IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBtdWx0aVJvd1NlbGVjdGlvbjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHN0aWNreUZvb3RlcjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHN0aWNreUhlYWRlcjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHNob3dGb290ZXJSb3c6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBjb2x1bW5GaWx0ZXI6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBsb2FkaW5nSW5kaWNhdG9yOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgc29ydGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHNob3dUb29sYmFyOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgdG9vbGJhclRpdGxlOiBzdHJpbmcgPSAnJztcclxuICBASW5wdXQoKSB0YWJsZUhlaWdodDogc3RyaW5nID0gJyc7XHJcbiAgQElucHV0KCkgdG9vbGJhckhlaWdodDogc3RyaW5nID0gJzUwcHgnO1xyXG4gIEBJbnB1dCgpIHRhYmxlV2lkdGg6IHN0cmluZyA9ICcxMDAlJztcclxuICBASW5wdXQoKSBzY3JvbGxiYXJIOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgdG9vbGJhclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxhbnk+IHwgdW5kZWZpbmVkO1xyXG4gIEBJbnB1dCgpIGNvbHVtbkhpZGFibGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBjb2x1bW5QaW5uYWJsZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGdsb2JhbFNlYXJjaDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIGV4cGFuZFJvd3M6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBkbmRDb2x1bW5zOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQElucHV0KCkgc2hvd1BhZ2luYXRvcjogYm9vbGVhbiA9IHRydWU7XHJcbiAgQElucHV0KCkgc2hvd0ZpcnN0TGFzdEJ1dHRvbnM6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBleHBvcnRCdXR0b25FbmFibGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBASW5wdXQoKSBwYWdlU2l6ZU9wdGlvbnM6IG51bWJlcltdID0gWzEwLCA1MCwgMTAwXTtcclxuICBASW5wdXQoKSB0b29sYmFyVGVtcGxhdGVSZWYhOiBUZW1wbGF0ZVJlZjxhbnk+IHwgdW5kZWZpbmVkO1xyXG4gIEBJbnB1dCgpIGhlYWRlclRlbXBsYXRlUmVmITogVGVtcGxhdGVSZWY8YW55PiB8IHVuZGVmaW5lZDtcclxuICBASW5wdXQoKSBjZWxsVGVtcGxhdGVSZWYhOiBUZW1wbGF0ZVJlZjxhbnk+IHwgdW5kZWZpbmVkO1xyXG4gIEBJbnB1dCgpIGV4cGFuc2lvblRlbXBsYXRlUmVmITogVGVtcGxhdGVSZWY8YW55PiB8IHVuZGVmaW5lZDtcclxuICBASW5wdXQoKSBwb3B1cEVkaXRpbmdUZW1wbGF0ZVJlZiE6IFRlbXBsYXRlUmVmPGFueT4gfCB1bmRlZmluZWQ7XHJcbiAgQElucHV0KCkgaW5saW5lRWRpdGluZ1RlbXBsYXRlUmVmITogVGVtcGxhdGVSZWY8YW55PiB8IHVuZGVmaW5lZDtcclxuICBASW5wdXQoKSBjZWxsRWRpdGluZ1RlbXBsYXRlUmVmITogVGVtcGxhdGVSZWY8YW55PiB8IHVuZGVmaW5lZDtcclxuICBASW5wdXQoKSBjZWxsVGVtcGxhdGVSZWZNYXA6IENlbGxUZW1wbGF0ZVJlZk1hcCA9IHt9O1xyXG5cclxuICAvLyBUYWJsZSBvdXRwdXRzXHJcbiAgQE91dHB1dCgpIGlubGluZUNoYW5nZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPFJvd0NoYW5nZT4oKTtcclxuICBAT3V0cHV0KCkgY2VsbENoYW5nZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPFJvd0NoYW5nZT4oKTtcclxuICBAT3V0cHV0KCkgcG9wdXBDaGFuZ2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxSb3dDaGFuZ2U+KCk7XHJcbiAgQE91dHB1dCgpIHJvd0RlbGV0ZWQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIHNjcm9sbDogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyPGFueT4oKTtcclxuICBAT3V0cHV0KCkgc2VsZWN0aW9uQ2hhbmdlZDogRXZlbnRFbWl0dGVyPFJvd1NlbGVjdGlvbkNoYW5nZT4gPVxyXG4gICAgbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQE91dHB1dCgpIGV4cGFuc2lvbkNoYW5nZTogRXZlbnRFbWl0dGVyPEV4cGFuc2lvbkNoYW5nZT4gPVxyXG4gICAgbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgdGFibGVJRCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xyXG4gIGNvbHVtblBpbm5pbmdPcHRpb25zOiBNVEV4Q29sdW1uUGluT3B0aW9uW10gPSBbXTtcclxuICBleHBvcnRNZW51Q3RybDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGNvbHVtblBpbk1lbnVDdHJsOiBib29sZWFuID0gZmFsc2U7XHJcbiAgaGlkZVNob3dNZW51Q3RybDogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGNvbHVtbkZpbHRlckJ5U2VsZWN0aW9uOiBhbnkgPSBmYWxzZTtcclxuICByb3dEYXRhVGVtcDogYW55ID0ge307XHJcbiAgaW5saW5lRWRpdGluZ1RlbXBsYXRlUmVmRGF0YTogYW55ID0ge307XHJcbiAgZGlzcGxheWVkQ29sdW1uczogc3RyaW5nW10gPSBbXTtcclxuICBzaG93SGlkZUNvbHVtbnNBcnJheTogTVRFeENvbHVtbltdID0gW107XHJcbiAgY29sdW1uc0xpc3Q6IHN0cmluZ1tdID0gW107XHJcbiAgY29sdW1uc0FycmF5OiBNVEV4Q29sdW1uW10gPSBbXTtcclxuICBoZWFkZXJzRmlsdGVyc0lkczogc3RyaW5nW10gPSBbXTtcclxuICBjb2x1bW5zVG9EaXNwbGF5V2l0aEV4cGFuZDogc3RyaW5nW10gPSBbXTtcclxuICBzZWxlY3Rpb24gPSBuZXcgU2VsZWN0aW9uTW9kZWw8YW55PihmYWxzZSwgW10pO1xyXG4gIGhpZGRlbkN0cmwgPSBuZXcgU2VsZWN0aW9uTW9kZWw8YW55Pih0cnVlLCBbXSk7XHJcbiAgdGFibGVEYXRhOiBhbnkgPSBbXTtcclxuICBmaWx0ZXJWYWx1ZXM6IGFueSA9IHt9O1xyXG4gIGdsb2JhbEZpbHRlciA9ICcnO1xyXG4gIHNob3dIaWRlRmlsdGVyID0gJyc7XHJcbiAgaW5kaXZpZHVhbEZpbHRlciA9ICcnO1xyXG4gIHRvZ2dsZUZpbHRlcnMgPSBmYWxzZTtcclxuICBoaWRlUm93cyA9IGZhbHNlO1xyXG4gIGV4cGFuZGVkRWxlbWVudDogYW55IHwgbnVsbDtcclxuICBjdXJyZW50Um93SW5kZXg6IG51bWJlciA9IC0xO1xyXG4gIGN1cnJlbnRSb3c6IGFueSA9IHt9O1xyXG4gIGNlbGxFZGl0aW5nOiBhbnkgPSB7fTtcclxuICBoaWRlU2hvd01lbnVHcm91cCE6IEZvcm1Hcm91cDtcclxuICBjZWxsVGVtcGxhdGUhOiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIG1lbnVYOiBudW1iZXIgPSAwO1xyXG4gIG1lbnVZOiBudW1iZXIgPSAwO1xyXG4gIGR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zOiBhbnlbXSA9IFtcclxuICAgIHsgZmlsdGVyOiBmYWxzZSwgbmFtZTogJ3NlbGVjdCcsIHNob3c6IGZhbHNlIH0sXHJcbiAgICB7IGZpbHRlcjogZmFsc2UsIG5hbWU6ICdlZGl0Jywgc2hvdzogZmFsc2UgfSxcclxuICAgIHsgZmlsdGVyOiBmYWxzZSwgbmFtZTogJ3BvcHVwJywgc2hvdzogZmFsc2UgfSxcclxuICAgIHsgZmlsdGVyOiBmYWxzZSwgbmFtZTogJ2RlbGV0ZScsIHNob3c6IGZhbHNlIH0sXHJcbiAgICB7IGZpbHRlcjogZmFsc2UsIG5hbWU6ICdleHBhbmQnLCBzaG93OiBmYWxzZSB9LFxyXG4gIF07XHJcbiAgaW5wdXRQcm9wZXJ0eUtleXM6IHN0cmluZ1tdID0gW1xyXG4gICAgJ2RhdGFTb3VyY2UnLFxyXG4gICAgJ2NvbHVtbnMnLFxyXG4gICAgJ2lubGluZVJvd0VkaXRpbmcnLFxyXG4gICAgJ3BvcHVwUm93RWRpdGluZycsXHJcbiAgICAnZW5hYmxlRGVsZXRlJyxcclxuICAgICdyb3dTZWxlY3Rpb24nLFxyXG4gICAgJ211bHRpUm93U2VsZWN0aW9uJyxcclxuICAgICdzdGlja3lIZWFkZXInLFxyXG4gICAgJ3N0aWNreUZvb3RlcicsXHJcbiAgICAnY29sdW1uRmlsdGVyJyxcclxuICAgICdnbG9iYWxTZWFyY2gnLFxyXG4gICAgJ2V4cGFuZFJvd3MnLFxyXG4gICAgJ3NvcnRpbmcnLFxyXG4gIF07XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHVibGljIGRpYWxvZzogTWF0RGlhbG9nLFxyXG4gICAgcHVibGljIHNlcnZpY2U6IE1hdFRhYmxlRXh0U2VydmljZSxcclxuICAgIHB1YmxpYyBmb3JtQnVpbGRlcnNTZXJ2aWNlOiBGb3JtQnVpbGRlcixcclxuICAgIHB1YmxpYyBkb21TYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgIHB1YmxpYyBtYXRJY29uUmVnaXN0cnk6IE1hdEljb25SZWdpc3RyeSxcclxuICAgIHByaXZhdGUgY2RyOiBDaGFuZ2VEZXRlY3RvclJlZlxyXG4gICkge1xyXG4gICAgdGhpcy5hZGRJY29uc1RvUmVnaXN0cnkoKTtcclxuICAgIGlmICh0aGlzLmRhdGFTb3VyY2UpIHtcclxuICAgICAgdGhpcy50YWJsZURhdGEgPSB0aGlzLmRhdGFTb3VyY2UuZGF0YTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICpcclxuICAgKiBAcGFyYW0gY2hhbmdlcyBjaGFuZ2VzIGNhcHR1cmVkIGVhY2ggdGltZSB1c2VyIGNoYW5nZXMgcHJvcGVydHkgdmFsdWUuXHJcbiAgICovXHJcbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xyXG4gICAgdGhpcy5zZXRQcm9wZXJ0eVZhbHVlKGNoYW5nZXMpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcbiAgICBpZiAodGhpcy5kYXRhU291cmNlKSB7XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXJQcmVkaWNhdGUgPSB0aGlzLmNyZWF0ZUZpbHRlcigpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCkge1xyXG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSkge1xyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UucGFnaW5hdG9yID0gdGhpcy5wYWdpbmF0b3I7XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5zb3J0ID0gdGhpcy5zb3J0O1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gY2hlY2tzIGFuZCB1cGRhdGVzIHRoZSB0aGUgY29sdW1uJ3MgaGlkZSBhbmQgc2hvdyBwcm9wZXJ0aWVzLlxyXG4gICAqL1xyXG4gIHNldENvbHVtbkhpZGVTaG93KCkge1xyXG4gICAgaWYgKFxyXG4gICAgICB0aGlzLmhpZGVTaG93TWVudUdyb3VwICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgdGhpcy5oaWRlU2hvd01lbnVHcm91cCAhPT0gbnVsbFxyXG4gICAgKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlQ29sdW1uc0hpZGVTaG93KHRoaXMuaGlkZVNob3dNZW51R3JvdXAudmFsdWUpO1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gc2V0IHRoZSBwcm9wZXJ0aWVzIG9mIHRoZSB0YWJsZS5cclxuICAgKiBAcGFyYW0gY2hhbmdlcyBjaGFuZ2VzIGNhcHR1cmVkIGVhY2ggdGltZSB1c2VyIGNoYW5nZXMgcHJvcGVydHkgdmFsdWUuXHJcbiAgICovXHJcbiAgc2V0UHJvcGVydHlWYWx1ZShjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICBsZXQga2V5cyA9IE9iamVjdC5rZXlzKGNoYW5nZXMpO1xyXG4gICAga2V5cy5mb3JFYWNoKChwcm9wZXJ0eSkgPT4ge1xyXG4gICAgICBpZiAodGhpcy5pbnB1dFByb3BlcnR5S2V5cy5pbmNsdWRlcyhwcm9wZXJ0eSkpIHtcclxuICAgICAgICB0aGlzLnNldFByb3BlcnRpZXNNYXBbcHJvcGVydHldKGNoYW5nZXNbcHJvcGVydHldKTtcclxuICAgICAgfSBlbHNlIGlmIChwcm9wZXJ0eSA9PSAnc2hvd1Rvb2xiYXInKSB7XHJcbiAgICAgICAgaWYgKGNoYW5nZXNbJ2NvbHVtbnMnXSkge1xyXG4gICAgICAgICAgdGhpcy5zZXRUb29sYmFyTWVudUNvbnRyb2xzKGNoYW5nZXNbJ2NvbHVtbnMnXS5jdXJyZW50VmFsdWUpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLnNldFRvb2xiYXJNZW51Q29udHJvbHModGhpcy5jb2x1bW5zQXJyYXkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBUaGlzIG1hcHBpbmcgaXMgdXNlZCB0byBzZXQgYW5kIHVwZGF0ZSBjaGFuZ2VzaW4gdGhlIHRhYmxlLlxyXG4gICAqL1xyXG4gIHNldFByb3BlcnRpZXNNYXA6IGFueSA9IHtcclxuICAgIGRhdGFTb3VyY2U6ICh2YWx1ZTogYW55KSA9PiB0aGlzLnNldFRhYmxlRGF0YVNvdXJjZSh2YWx1ZSksXHJcbiAgICBjb2x1bW5zOiAodmFsdWU6IGFueSkgPT4gdGhpcy5zZXRDb2x1bW5zRGF0YSh2YWx1ZS5jdXJyZW50VmFsdWUpLFxyXG4gICAgaW5saW5lUm93RWRpdGluZzogKHZhbHVlOiBhbnkpID0+XHJcbiAgICAgIHRoaXMuc2hvd0hpZGVDb2x1bW4oJ2VkaXQnLCB2YWx1ZS5jdXJyZW50VmFsdWUpLFxyXG4gICAgcG9wdXBSb3dFZGl0aW5nOiAodmFsdWU6IGFueSkgPT5cclxuICAgICAgdGhpcy5zaG93SGlkZUNvbHVtbigncG9wdXAnLCB2YWx1ZS5jdXJyZW50VmFsdWUpLFxyXG4gICAgZW5hYmxlRGVsZXRlOiAodmFsdWU6IGFueSkgPT5cclxuICAgICAgdGhpcy5zaG93SGlkZUNvbHVtbignZGVsZXRlJywgdmFsdWUuY3VycmVudFZhbHVlKSxcclxuICAgIHJvd1NlbGVjdGlvbjogKHZhbHVlOiBhbnkpID0+IHRoaXMuc2V0Um93U2VsZWN0aW9uKHZhbHVlLmN1cnJlbnRWYWx1ZSksXHJcbiAgICBtdWx0aVJvd1NlbGVjdGlvbjogKHZhbHVlOiBhbnkpID0+IHtcclxuICAgICAgdGhpcy5zZWxlY3Rpb24gPSBuZXcgU2VsZWN0aW9uTW9kZWw8YW55Pih2YWx1ZS5jdXJyZW50VmFsdWUsIFtdKTtcclxuICAgIH0sXHJcbiAgICBzdGlja3lIZWFkZXI6ICh2YWx1ZTogYW55KSA9PiB7XHJcbiAgICAgIHRoaXMuc3RpY2t5SGVhZGVyID0gdmFsdWUuY3VycmVudFZhbHVlO1xyXG4gICAgfSxcclxuICAgIHN0aWNreUZvb3RlcjogKHZhbHVlOiBhbnkpID0+IHtcclxuICAgICAgdGhpcy5zdGlja3lGb290ZXIgPSB2YWx1ZS5jdXJyZW50VmFsdWU7XHJcbiAgICB9LFxyXG4gICAgY29sdW1uRmlsdGVyOiAodmFsdWU6IGFueSkgPT4gdGhpcy5zZXRDb2x1bW5GaWx0ZXIodmFsdWUuY3VycmVudFZhbHVlKSxcclxuICAgIGdsb2JhbFNlYXJjaDogKHZhbHVlOiBhbnkpID0+XHJcbiAgICAgICh0aGlzLmRhdGFTb3VyY2UuZmlsdGVyUHJlZGljYXRlID0gdGhpcy5jcmVhdGVGaWx0ZXIoKSksXHJcbiAgICBleHBhbmRSb3dzOiAodmFsdWU6IGFueSkgPT4ge1xyXG4gICAgICB0aGlzLmxvYWRpbmdJbmRpY2F0b3IgPSB0cnVlO1xyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlKHRoaXMudGFibGVEYXRhKTtcclxuICAgICAgaWYgKHZhbHVlLmN1cnJlbnRWYWx1ZSA9PSB0cnVlKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmRpc3BsYXllZENvbHVtbnMuaW5jbHVkZXMoJ2V4cGFuZCcpKSB7XHJcbiAgICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMucHVzaCgnZXhwYW5kJyk7XHJcbiAgICAgICAgICB0aGlzLmNvbHVtbnNUb0Rpc3BsYXlXaXRoRXhwYW5kID0gWy4uLnRoaXMuZGlzcGxheWVkQ29sdW1uc107XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuY29sdW1uc1RvRGlzcGxheVdpdGhFeHBhbmQgPSBbLi4udGhpcy5kaXNwbGF5ZWRDb2x1bW5zXTtcclxuICAgICAgICBpZiAodGhpcy5kaXNwbGF5ZWRDb2x1bW5zLmluY2x1ZGVzKCdleHBhbmQnKSkge1xyXG4gICAgICAgICAgbGV0IGluZGV4ID0gdGhpcy5kaXNwbGF5ZWRDb2x1bW5zLmluZGV4T2YoJ2V4cGFuZCcpO1xyXG4gICAgICAgICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuZXhwYW5kZWRFbGVtZW50ID0gbnVsbDtcclxuICAgICAgfVxyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICB0aGlzLmxvYWRpbmdJbmRpY2F0b3IgPSBmYWxzZTtcclxuICAgICAgfSwgMjAwKTtcclxuICAgIH0sXHJcbiAgICBzb3J0aW5nOiAodmFsdWU6IGFueSkgPT4gKHRoaXMuZGF0YVNvdXJjZS5zb3J0ID0gdGhpcy5zb3J0KSxcclxuICB9O1xyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiB1c2VkIHNldCBkYXRhIHNvdXJjZSBmb3IgdGFibGUuXHJcbiAgICogQHBhcmFtIHZhbHVlIGRhdGEgc291cmNlIHZhbHVlIGZyb20gdXNlci5cclxuICAgKi9cclxuICBzZXRUYWJsZURhdGFTb3VyY2UodmFsdWU6IGFueSkge1xyXG4gICAgaWYgKHZhbHVlLmN1cnJlbnRWYWx1ZSkge1xyXG4gICAgICB0aGlzLnRhYmxlRGF0YSA9IHZhbHVlLmN1cnJlbnRWYWx1ZS5kYXRhO1xyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UgPSB2YWx1ZS5jdXJyZW50VmFsdWU7XHJcbiAgICAgIHRoaXMucmVDYWwoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBNYXRUYWJsZURhdGFTb3VyY2UoW3t9XSk7XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiB1c2VkIGNyZWF0ZSBzZWxldGlvbiBtb2RlbCBhbmQgc2V0IHNlbGVjdGlvbiBjb2x1bW4gdmlzaWJpbGl0eS5cclxuICAgKiBAcGFyYW0gdmFsdWUgYm9vbGVhbiB2YWx1ZSB0byBzaG93IG9yIGhpZGUgc2VsZWN0aW9uIENvbHVtbiBmcm9tIHRhYmxlLlxyXG4gICAqL1xyXG4gIHNldFJvd1NlbGVjdGlvbih2YWx1ZTogYm9vbGVhbikge1xyXG4gICAgdGhpcy5zZWxlY3Rpb24gPSBuZXcgU2VsZWN0aW9uTW9kZWw8YW55Pih0cnVlLCBbXSk7XHJcbiAgICB0aGlzLnVwZGF0ZVNlbGVjdGlvbkNvbHVtblZpc2liaWxpdHkodmFsdWUpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIGNyZWF0ZSBmaWx0ZXIgaGVhZGVyIHJvdyBhbmQgYXNzaWducyBmaWx0ZXIgcHJlZGljYXRlIHRvIHRhYmxlIGRhdGEgc291cmNlLlxyXG4gICAqIEBwYXJhbSB2YWx1ZSBib29sZWFuIHZhbHVlIHRvIGNoYW5nZSAgdmlzaWJpbGl0eSBvZiBjb2x1bW4gZmlsdGVyIHJvdy5cclxuICAgKi9cclxuICBzZXRDb2x1bW5GaWx0ZXIodmFsdWU6IGJvb2xlYW4pIHtcclxuICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICBsZXQgYXJyYXk6IHN0cmluZ1tdID0gW107XHJcbiAgICAgIHRoaXMuY29sdW1uc0FycmF5LmZvckVhY2goKGNvbHVtbiwgaSkgPT4ge1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgIHRoaXMuZHluYW1pY0Rpc3BsYXllZENvbHVtbnMuZmlsdGVyKChhKSA9PiBhLm5hbWUgPT0gY29sdW1uPy5maWVsZClbMF1cclxuICAgICAgICAgICAgLnNob3dcclxuICAgICAgICApIHtcclxuICAgICAgICAgIGFycmF5LnB1c2goY29sdW1uPy5maWVsZCArICdfJyArIGkpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICAgIHRoaXMuaGVhZGVyc0ZpbHRlcnNJZHMgPSBhcnJheTtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLmZpbHRlclByZWRpY2F0ZSA9IHRoaXMuY3JlYXRlRmlsdGVyKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmhlYWRlcnNGaWx0ZXJzSWRzID0gW107XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIgPSAnJztcclxuICAgIH1cclxuICAgIHRoaXMudG9nZ2xlRmlsdGVycyA9IHZhbHVlO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2QgcmV0dXJucyB0aGUgbGlzdCBvZiB2aXNpYmxlIGNvbHVtbiBuYW1lcy5cclxuICAgKiBAcmV0dXJucyBsaXN0IG9mIHZpc2libGUgY29sdW1uIG5hbWVzLlxyXG4gICAqL1xyXG4gIGdldERpc3BsYXllZENvbHVtbnMoKTogc3RyaW5nW10ge1xyXG4gICAgbGV0IGxpc3QgPSB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zXHJcbiAgICAgIC5maWx0ZXIoKGNkKSA9PiBjZC5zaG93KVxyXG4gICAgICAubWFwKChjZCkgPT4gY2QubmFtZSk7XHJcbiAgICByZXR1cm4gbGlzdDtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQHBhcmFtIG1lbnVUeXBlIHR5cGUgb2YgbWVudSB0byBvcGVuIGZyb20gdG9vbGJhci5cclxuICAgKiBAcGFyYW0gZXZlbnQgbW91c2UgZXZlbnQgdG8gb3BlbiBtZW51IG9uIHRoYXQgbG9jYXRpb24uXHJcbiAgICovXHJcbiAgb3Blbk1lbnUobWVudVR5cGU6IHN0cmluZywgZXZlbnQ6IE1vdXNlRXZlbnQpIHtcclxuICAgIHRoaXMubWVudVggPSBldmVudC5jbGllbnRYO1xyXG4gICAgdGhpcy5tZW51WSA9IGV2ZW50LmNsaWVudFk7XHJcbiAgICBzd2l0Y2ggKG1lbnVUeXBlKSB7XHJcbiAgICAgIGNhc2UgJ2V4cG9ydCc6IHtcclxuICAgICAgICB0aGlzLmV4cG9ydE1lbnVDdHJsID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLm1lbnVUcmlnZ2VyLm9wZW5NZW51KCk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgICAgY2FzZSAnaGlkZVNob3cnOiB7XHJcbiAgICAgICAgdGhpcy5oaWRlU2hvd01lbnVDdHJsID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLm9wZW5IaWRlU2hvd01lbnUodGhpcy5jb2x1bW5zQXJyYXkpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICAgIGNhc2UgJ2NvbHVtblBpbic6IHtcclxuICAgICAgICB0aGlzLmNvbHVtblBpbk1lbnVDdHJsID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLm9wZW5IaWRlU2hvd01lbnUodGhpcy5jb2x1bW5zQXJyYXkpO1xyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiB0cmlnZ2VycyB3aGVuIG1lbnUgaXMgY2xvc2VkIGFuZCByZXNldCB0aGUgcmVxdWlyZWQgY29udHJvbHMuXHJcbiAgICovXHJcbiAgbWVudUNsb3NlZCgpIHtcclxuICAgIHRoaXMuZXhwb3J0TWVudUN0cmwgPSBmYWxzZTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIHNldCBsaXN0IG9mIGNvbHVtbnMgdG8gZGlzcGxheSBpbiB0YWJsZS5cclxuICAgKiBAcGFyYW0gY29sdW1ucyBjb2x1bW5zIGFycmF5IGZyb20gdXNlciBpbnB1dC5cclxuICAgKi9cclxuICBzZXRDb2x1bW5zRGF0YShjb2x1bW5zOiBNVEV4Q29sdW1uW10pIHtcclxuICAgIGlmIChjb2x1bW5zLmxlbmd0aCkge1xyXG4gICAgICB0aGlzLmNvbHVtbnNBcnJheSA9IFsuLi5jb2x1bW5zXTtcclxuICAgICAgdGhpcy5zZXRDb2x1bW5zTGlzdChjb2x1bW5zKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIHNldCBsaXN0IG9mIGNvbHVtbnMgdG8gZGlzcGxheSBpbiB0YWJsZS5cclxuICAgKiBAcGFyYW0gY29sdW1ucyBjb2x1bW5zIGFycmF5IGZyb20gdXNlciBpbnB1dCB3aXRoIGNvbmZpZ3VyYXRpb25zLlxyXG4gICAqL1xyXG4gIHNldENvbHVtbnNMaXN0KGNvbHVtbnM6IE1URXhDb2x1bW5bXSkge1xyXG4gICAgdGhpcy5jb2x1bW5zTGlzdCA9IFtdO1xyXG4gICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zID0gWydzZWxlY3QnLCAnZWRpdCcsICdwb3B1cCcsICdkZWxldGUnXTtcclxuICAgIGxldCBjb2x1bW5zQXJyYXk6IERpc3BsYXlDb2x1bW5bXSA9IFtdO1xyXG4gICAgY29sdW1ucy5mb3JFYWNoKChjb2wpID0+IHtcclxuICAgICAgaWYgKHR5cGVvZiBjb2w/LmhlYWRlciA9PSAnc3RyaW5nJykge1xyXG4gICAgICAgIHRoaXMuY29sdW1uc0xpc3QucHVzaChjb2w/LmhlYWRlcik7XHJcbiAgICAgICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zLnB1c2goY29sPy5maWVsZCk7XHJcbiAgICAgICAgY29sdW1uc0FycmF5LnB1c2goeyBmaWx0ZXI6IHRydWUsIG5hbWU6IGNvbD8uZmllbGQsIHNob3c6ICFjb2wuaGlkZSB9KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zID0gW1xyXG4gICAgICB7IGZpbHRlcjogZmFsc2UsIG5hbWU6ICdzZWxlY3QnLCBzaG93OiBmYWxzZSB9LFxyXG4gICAgICB7IGZpbHRlcjogZmFsc2UsIG5hbWU6ICdlZGl0Jywgc2hvdzogZmFsc2UgfSxcclxuICAgICAgeyBmaWx0ZXI6IGZhbHNlLCBuYW1lOiAncG9wdXAnLCBzaG93OiBmYWxzZSB9LFxyXG4gICAgICB7IGZpbHRlcjogZmFsc2UsIG5hbWU6ICdkZWxldGUnLCBzaG93OiBmYWxzZSB9LFxyXG4gICAgXTtcclxuICAgIHRoaXMuZHluYW1pY0Rpc3BsYXllZENvbHVtbnMgPSBjb2x1bW5zQXJyYXkuY29uY2F0KFxyXG4gICAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zXHJcbiAgICApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGFrZSBib29sZWFuIHZhbHVlIGFuZCBuYW1lIGNvbHVtbiBhbmQgdXBkYXRlIGl0cyB2aXNpYmlsaXR5IHN0YXR1cyBpbiB0YWJsZS5cclxuICAgKiBAcGFyYW0gbmFtZSBuYW1lIG9mIHRoZSBjb2x1bW4gdG8gc2V0IHZpc2liaWxpdHkuXHJcbiAgICogQHBhcmFtIHZhbHVlIGJvb2xlYW4gdmFsdWUgdG8gc2V0IHZpc2liaWxpdHkgb2YgdGhlIGNvbHVtbi5cclxuICAgKi9cclxuICBzaG93SGlkZUNvbHVtbihuYW1lOiBzdHJpbmcsIHZhbHVlOiBib29sZWFuKSB7XHJcbiAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zLmZpbHRlcigoYSkgPT4gYS5uYW1lID09IG5hbWUpWzBdLnNob3cgPSB2YWx1ZTtcclxuICAgIGlmICh0aGlzLmNvbHVtbkZpbHRlcikge1xyXG4gICAgICB0aGlzLnNldENvbHVtbkZpbHRlcih0cnVlKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIHdpbGwgcG9zaXRpb24gdGhlIHNlbGVjdGlvbiBjb2x1bW4gdG8gZmlyc3QgYW5kIGFsc28gdXBkYXRlIGl0cyB2aXNpYmlsaXR5LlxyXG4gICAqIEBwYXJhbSB2YWx1ZSB2YWx1ZSB1c2VkIHRvIHNldCB2aXNpYmlsaXR5IG9mIHRoZSBzZWxlY3Rpb24gY29sdW1uLlxyXG4gICAqL1xyXG4gIHVwZGF0ZVNlbGVjdGlvbkNvbHVtblZpc2liaWxpdHkodmFsdWU6IGJvb2xlYW4pIHtcclxuICAgIGxldCBjb2x1bW5OYW1lID0gJ3NlbGVjdCc7XHJcbiAgICBsZXQgY29sdW1uID0gdGhpcy5keW5hbWljRGlzcGxheWVkQ29sdW1ucy5maWx0ZXIoXHJcbiAgICAgIChhKSA9PiBhLm5hbWUgPT0gY29sdW1uTmFtZVxyXG4gICAgKVswXTtcclxuICAgIGxldCBpbmRleCA9IHRoaXMuZHluYW1pY0Rpc3BsYXllZENvbHVtbnMuZmluZEluZGV4KFxyXG4gICAgICAoY29sdW1uOiBhbnkpID0+IGNvbHVtbi5uYW1lID09IGNvbHVtbk5hbWVcclxuICAgICk7XHJcbiAgICBpZiAoaW5kZXggPiAtMSkge1xyXG4gICAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zLnNwbGljZShpbmRleCwgMSk7XHJcbiAgICAgIHRoaXMuZHluYW1pY0Rpc3BsYXllZENvbHVtbnMudW5zaGlmdChjb2x1bW4pO1xyXG4gICAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zLmZpbHRlcihcclxuICAgICAgICAoY29sdW1uKSA9PiBjb2x1bW4ubmFtZSA9PSBjb2x1bW5OYW1lXHJcbiAgICAgIClbMF0uc2hvdyA9IHZhbHVlO1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2QgaXMgdXNlZCB0byB1cGRhdGUgdGhlIHBvc2l0aW9uIG9mICBjb2x1bW4gaW4gY29sdW1ucyBhcnJheSBhY2NvcmRpbmcgdG8gaXRzIGRyb3BwZWQgcG9zaXRpb24uXHJcbiAgICogQHBhcmFtIGV2ZW50IENka0RyYWdEcm9wIHVzZWQgdG8gdXBkYXRlIGNvbHVtbiBwb3NpdGlvbiBpbiBjb2x1bW5zIGFycmF5LlxyXG4gICAqL1xyXG4gIG9uRHJvcChldmVudDogQ2RrRHJhZ0Ryb3A8YW55Pikge1xyXG4gICAgaWYgKHRoaXMuZG5kQ29sdW1ucykge1xyXG4gICAgICBsZXQgYWRqdXN0ZWRWYWx1ZSA9IDA7XHJcbiAgICAgIGlmIChcclxuICAgICAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zWzBdLm5hbWUgPT0gJ3NlbGVjdCcgJiZcclxuICAgICAgICB0aGlzLmR5bmFtaWNEaXNwbGF5ZWRDb2x1bW5zWzBdLnNob3cgPT0gZmFsc2VcclxuICAgICAgKSB7XHJcbiAgICAgICAgYWRqdXN0ZWRWYWx1ZSA9IDE7XHJcbiAgICAgIH1cclxuICAgICAgbW92ZUl0ZW1JbkFycmF5KFxyXG4gICAgICAgIHRoaXMuZHluYW1pY0Rpc3BsYXllZENvbHVtbnMsXHJcbiAgICAgICAgZXZlbnQucHJldmlvdXNJbmRleCArIGFkanVzdGVkVmFsdWUsXHJcbiAgICAgICAgZXZlbnQuY3VycmVudEluZGV4ICsgYWRqdXN0ZWRWYWx1ZVxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2QgY3JlYXRlIGZpbHRlciBwcmVkaWNhdGUgZnVuY3Rpb24gd2hpY2ggd2lsbCBzZXQgc2VhcmNoIHZhbHVlIHRvIHRhYmxlIGZpbHRlcnNcclxuICAgKiBmb3IgYm90aCBnbG9iYWwgYW5kIGluZGl2aWR1YWwgY29sdW0gZmlsdGVyaW5nLlxyXG4gICAqIEByZXR1cm5zIHJldHVybnMgYm9vbGVhbiB2YWx1ZSB0byBmaWx0ZXIgcm93cyBpbiB0YWJsZS5cclxuICAgKi9cclxuICBjcmVhdGVGaWx0ZXIoKTogKGRhdGE6IGFueSwgZmlsdGVyOiBzdHJpbmcpID0+IGJvb2xlYW4ge1xyXG4gICAgY29uc3QgdGFibGVGaWx0ZXJQcmVkaWNhdGUgPSAoZGF0YTogYW55LCBmaWx0ZXI6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xyXG4gICAgICBsZXQgcmVzdWx0OiBib29sZWFuID0gdHJ1ZTtcclxuICAgICAgLy8gc2VhcmNoIGFsbCBjb2x1bW4gZmllbGRzXHJcbiAgICAgIGlmICh0aGlzLmdsb2JhbEZpbHRlcikge1xyXG4gICAgICAgIGxldCBleHByZXNzaW9uID0gJyc7XHJcbiAgICAgICAgbGV0IGtleXMgPSBPYmplY3Qua2V5cyhkYXRhKTtcclxuICAgICAgICBrZXlzLmZvckVhY2goKGtleSkgPT4ge1xyXG4gICAgICAgICAgZXhwcmVzc2lvbiA9XHJcbiAgICAgICAgICAgIGV4cHJlc3Npb24gK1xyXG4gICAgICAgICAgICBgZGF0YS4ke2tleX0udG9TdHJpbmcoKS50cmltKCkudG9Mb3dlckNhc2UoKS5pbmRleE9mKHRoaXMuZ2xvYmFsRmlsdGVyLnRvTG93ZXJDYXNlKCkpICE9PSAtMSB8fGA7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgZXhwcmVzc2lvbi5jaGFyQXQoZXhwcmVzc2lvbi5sZW5ndGggLSAyKSArXHJcbiAgICAgICAgICAgIGV4cHJlc3Npb24uY2hhckF0KGV4cHJlc3Npb24ubGVuZ3RoIC0gMSkgPT1cclxuICAgICAgICAgICd8fCdcclxuICAgICAgICApIHtcclxuICAgICAgICAgIGV4cHJlc3Npb24gPSBleHByZXNzaW9uLnN1YnN0cmluZygwLCBleHByZXNzaW9uLmxlbmd0aCAtIDIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXN1bHQgPSBldmFsKGV4cHJlc3Npb24pO1xyXG4gICAgICB9XHJcbiAgICAgIGlmICghcmVzdWx0KSB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICAgIGxldCBzZWFyY2hTdHJpbmcgPSBKU09OLnBhcnNlKGZpbHRlcik7XHJcbiAgICAgIC8vc2VhcmNoIHNpbmdsZSBjb2x1bW4gZmllbGRcclxuICAgICAgaWYgKHRoaXMuaW5kaXZpZHVhbEZpbHRlcikge1xyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICBkYXRhW3RoaXMuaW5kaXZpZHVhbEZpbHRlcl1cclxuICAgICAgICAgICAgLnRvU3RyaW5nKClcclxuICAgICAgICAgICAgLnRyaW0oKVxyXG4gICAgICAgICAgICAudG9Mb3dlckNhc2UoKVxyXG4gICAgICAgICAgICAuaW5kZXhPZihcclxuICAgICAgICAgICAgICBzZWFyY2hTdHJpbmdbdGhpcy5pbmRpdmlkdWFsRmlsdGVyXS50b1N0cmluZygpLnRvTG93ZXJDYXNlKClcclxuICAgICAgICAgICAgKSAhPT0gLTFcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfTtcclxuICAgIHJldHVybiB0YWJsZUZpbHRlclByZWRpY2F0ZTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIGFzc2lnbnMgdGhlIHNlYXJjaCB2YWx1ZSB0byBtYXQgdGFibGUgZGF0YSBzb3VyY2UgdG8gYXBwbHkgdGhlIGZpbHRlci5cclxuICAgKiBAcGFyYW0gc2VhcmNoVmFsdWUgdmFsdWUgdG8gYmUgc2VhcmNoZWQgZnJvbSB0YWJsZSByb3dzLlxyXG4gICAqL1xyXG4gIGFwcGx5R2xvYmFsRmlsdGVyKHNlYXJjaFZhbHVlOiBzdHJpbmcpIHtcclxuICAgIHRoaXMuZ2xvYmFsRmlsdGVyID0gc2VhcmNoVmFsdWU7XHJcbiAgICBsZXQgY29sdW1uczogYW55ID0ge307XHJcbiAgICB0aGlzLmNvbHVtbnNBcnJheS5mb3JFYWNoKChjb2x1bW46IE1URXhDb2x1bW4pID0+IHtcclxuICAgICAgaWYgKGNvbHVtbi5maWVsZCkgY29sdW1uc1tjb2x1bW4uZmllbGRdID0gc2VhcmNoVmFsdWU7XHJcbiAgICB9KTtcclxuICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIgPSBKU09OLnN0cmluZ2lmeShjb2x1bW5zKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gYXBwbHkgY29sdW1uIGJhc2VkIGZpbHRlcmluZ1xyXG4gICAqIEBwYXJhbSBzZWFyY2hWYWx1ZSB2YWx1ZSB0byBiZSBzZWFyY2hlZCBmcm9tIHRhYmxlIHJvd3MuXHJcbiAgICogQHBhcmFtIGNvbHVtbiBmaWx0ZXIgd2lsbCBiZSBhcHBsaWVkIGJhc2VkIG9uIHRoaXMgY29sdW1uIGZpZWxkLlxyXG4gICAqL1xyXG4gIGFwcGx5Q29sdW1uRmlsdGVyKHNlYXJjaFZhbHVlOiBGaWx0ZXJTZWFyY2hWYWx1ZSwgY29sdW1uOiBNVEV4Q29sdW1uKSB7XHJcbiAgICB0aGlzLmluZGl2aWR1YWxGaWx0ZXIgPSBjb2x1bW4uZmllbGQ7XHJcbiAgICB0aGlzLmZpbHRlclZhbHVlc1tjb2x1bW4uZmllbGRdID0gc2VhcmNoVmFsdWVbY29sdW1uLmZpZWxkXTtcclxuICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIgPSBKU09OLnN0cmluZ2lmeSh0aGlzLmZpbHRlclZhbHVlcyk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCB3aWxsIHRha2Ugcm93IGFuZCBpdHMgaW5kZXggZW5hYmxlIGlubGluZSBlZGl0aW5nIHRvb2xzIG9uIHRoYXQgcm93LlxyXG4gICAqIEBwYXJhbSByb3cgcm93IG9uIHdoaWNoIHVzZXIgd2FudHMgdG8gZG8gZWRpdC5cclxuICAgKiBAcGFyYW0gaW5kZXggaW5kZXggb2YgdGhlIHJvdyB3aGVyZSBpbmxpbmUgZWRpdGluZyB3aWxsIGJlIGVuYWJsZWQuXHJcbiAgICovXHJcbiAgZW5hYmxlSW5saW5lRWRpdGluZyhyb3c6IGFueSwgaW5kZXg6IG51bWJlcikge1xyXG4gICAgY29uc3Qgcm93RGF0YTogYW55ID0ge307XHJcbiAgICByb3dEYXRhWydlJyArIGluZGV4XSA9IHsgLi4ucm93IH07XHJcbiAgICB0aGlzLnJvd0RhdGFUZW1wID0gcm93RGF0YTtcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLnRhYmxlRGF0YVtpbmRleF1bJ2VkaXRhYmxlJ10gPSAhdGhpcy50YWJsZURhdGFbaW5kZXhdWydlZGl0YWJsZSddO1xyXG4gICAgfSwgMCk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCB3aWxsIGNyZWF0ZSBhbmQgcmV0dXJuIGRhdGEgdG8gaW5saW5lIGVkaXRpbmcgdGVtcGxhdGUuXHJcbiAgICogQHBhcmFtIHJvdyByb3cgb24gd2hpY2ggdXNlciB3YW50cyB0byBkbyBlZGl0LlxyXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiB0aGUgcm93IHdoZXJlIGlubGluZSBlZGl0aW5nIHdpbGwgYmUgZW5hYmxlZC5cclxuICAgKiBAcGFyYW0gY29sdW1uIGN1cnJlbnQgY29sdW1uIG9mIHRoZSB0YWJsZS5cclxuICAgKi9cclxuICBnZXRJbmxpbmVFZGl0aW5nRGF0YShyb3c6IE1URXhSb3csIGluZGV4OiBudW1iZXIsIGNvbHVtbjogTVRFeENvbHVtbikge1xyXG4gICAgdGhpcy5pbmxpbmVFZGl0aW5nVGVtcGxhdGVSZWZEYXRhID0ge1xyXG4gICAgICByb3c6IHsgLi4ucm93IH0sXHJcbiAgICAgIGNvbHVtbjogeyAuLi5jb2x1bW4gfSxcclxuICAgICAgaW5kZXg6IGluZGV4LFxyXG4gICAgICB1cGRhdGVGdW5jOiB0aGlzLnVwZGF0ZUlubGluZVRlbXBsYXRlRGF0YSxcclxuICAgIH07XHJcbiAgICByZXR1cm4gdGhpcy5pbmxpbmVFZGl0aW5nVGVtcGxhdGVSZWZEYXRhO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2Qgd2lsbCB0YWtlIGRhdGEgZnJvbSBpbmxpbmUgZWRpdGluZyB0ZW1wbGF0ZSBhbmQgdXBkYXRlIGluIHRhYmxlIGRhdGEgc291cmNlLlxyXG4gICAqIEBwYXJhbSByb3cgdXBkYXRlZCByb3cgZnJvbSBpbmxpbmUgZWRpdGluZyB0ZW1wbGF0ZS5cclxuICAgKi9cclxuICB1cGRhdGVJbmxpbmVUZW1wbGF0ZURhdGEgPSAocm93OiBNVEV4Um93KSA9PiB7XHJcbiAgICB0aGlzLnNlcnZpY2Uuc2VsZWN0ZWRSb3cubmV4dChyb3cpO1xyXG4gIH07XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIHNldCBkYXRhIGZvciBpbi1jZWxsIGVkaXRpbmcuXHJcbiAgICogQHBhcmFtIHJvdyByb3cgb24gd2hpY2ggdXNlciB3YW50cyB0byBkbyBlZGl0LlxyXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiB0aGUgcm93IHdoZXJlIGlubGluZSBlZGl0aW5nIHdpbGwgYmUgZW5hYmxlZC5cclxuICAgKi9cclxuICBzZXRDZWxsRGF0YShyb3c6IE1URXhSb3csIGluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMuY3VycmVudFJvdyA9IHsgLi4ucm93IH07XHJcbiAgICB0aGlzLmN1cnJlbnRSb3dJbmRleCA9IGluZGV4O1xyXG4gICAgdGhpcy5yb3dEYXRhVGVtcFsnZScgKyBpbmRleF0gPSB7IC4uLnJvdyB9O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyB3aWxsIHJlc3RvcmUgdGhlIGRhdGEgYW5kIGNlbmNlbCB0aGUgaW5saW5lIGVkaXRpbmcuXHJcbiAgICogQHBhcmFtIHJvdyByb3cgb24gd2hpY2ggdXNlciB3YW50cyB0byBkbyBlZGl0LlxyXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiB0aGUgcm93IHdoZXJlIGlubGluZSBlZGl0aW5nIHdpbGwgYmUgZW5hYmxlZC5cclxuICAgKi9cclxuICBjYW5jZWxJbmxpbmVFZGl0aW5nKHJvdzogTVRFeFJvdywgaW5kZXg6IG51bWJlcikge1xyXG4gICAgdGhpcy50YWJsZURhdGEuZmlsdGVyKChhOiBhbnksIGk6IG51bWJlcikgPT4gaSA9PSBpbmRleClbMF1bJ2VkaXRhYmxlJ10gPVxyXG4gICAgICAhdGhpcy50YWJsZURhdGEuZmlsdGVyKChhOiBhbnksIGk6IG51bWJlcikgPT4gaSA9PSBpbmRleClbMF1bJ2VkaXRhYmxlJ107XHJcbiAgICB0aGlzLmRhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlKHRoaXMudGFibGVEYXRhKTtcclxuICAgIHRoaXMucm93RGF0YVRlbXBbJ2UnICsgaW5kZXhdID0ge307XHJcbiAgICB0aGlzLnNlcnZpY2Uuc2VsZWN0ZWRSb3cubmV4dCh1bmRlZmluZWQpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2Qgd2lsbCBzYXZlIGFuZCB1cGRhdGUgdGhlIGlubGluZSBlZGl0aW5nIGRhdGEgYW5kIGVtaXQgdGhlIHVwZGF0ZSByb3cgYW5kIGluZGV4LlxyXG4gICAqIEBwYXJhbSByb3cgcm93IG9uIHdoaWNoIHVzZXIgd2FudHMgdG8gZG8gZWRpdC5cclxuICAgKiBAcGFyYW0gaW5kZXggaW5kZXggb2YgdGhlIHJvdyB3aGVyZSBpbmxpbmUgZWRpdGluZyB3aWxsIGJlIGVuYWJsZWQuXHJcbiAgICovXHJcbiAgc2F2ZUlubGluZUVkaXRpbmcocm93OiBNVEV4Um93LCBpbmRleDogbnVtYmVyKSB7XHJcbiAgICBpZiAoIXRoaXMuaW5saW5lRWRpdGluZ1RlbXBsYXRlUmVmKSB7XHJcbiAgICAgIHRoaXMudGFibGVEYXRhW2luZGV4XSA9IHsgLi4udGhpcy5yb3dEYXRhVGVtcFsnZScgKyBpbmRleF0gfTtcclxuICAgICAgcm93ID0geyAuLi50aGlzLnJvd0RhdGFUZW1wWydlJyArIGluZGV4XSB9O1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgbGV0IGNoYW5nZWREYXRhID0gdGhpcy5zZXJ2aWNlLnNlbGVjdGVkUm93LnZhbHVlO1xyXG4gICAgICBpZiAoY2hhbmdlZERhdGEpIHtcclxuICAgICAgICB0aGlzLnRhYmxlRGF0YVtpbmRleF0gPSB7IC4uLmNoYW5nZWREYXRhIH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBNYXRUYWJsZURhdGFTb3VyY2UodGhpcy50YWJsZURhdGEpO1xyXG4gICAgdGhpcy5yb3dEYXRhVGVtcFsnZScgKyBpbmRleF0gPSB7fTtcclxuICAgIGxldCBkYXRhOiBSb3dDaGFuZ2UgPSB7XHJcbiAgICAgIHJvdzogcm93LFxyXG4gICAgICBpbmRleDogaW5kZXgsXHJcbiAgICB9O1xyXG4gICAgdGhpcy5pbmxpbmVDaGFuZ2UuZW1pdChkYXRhKTtcclxuICAgIHRoaXMudGFibGVEYXRhW2luZGV4XVsnZWRpdGFibGUnXSA9IGZhbHNlO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2Qgd2lsbCBzYXZlIGFuZCB1cGRhdGUgdGhlIGNlbGwgZWRpdGluZyBkYXRhIGFuZCBlbWl0IHRoZSB1cGRhdGUgcm93IGFuZCBpbmRleC5cclxuICAgKi9cclxuICBzYXZlQ2VsbEVkaXRpbmcoKSB7XHJcbiAgICB0aGlzLmNlbGxFZGl0aW5nID0ge307XHJcbiAgICBsZXQgaW5kZXggPSB0aGlzLmN1cnJlbnRSb3dJbmRleDtcclxuICAgIGlmIChpbmRleCA+IC0xKSB7XHJcbiAgICAgIGlmICh0aGlzLmNlbGxFZGl0aW5nVGVtcGxhdGVSZWYpIHtcclxuICAgICAgICBsZXQgY2hhbmdlZERhdGEgPSB0aGlzLnNlcnZpY2Uuc2VsZWN0ZWRSb3cudmFsdWU7XHJcbiAgICAgICAgaWYgKGNoYW5nZWREYXRhKSB7XHJcbiAgICAgICAgICB0aGlzLnRhYmxlRGF0YVtpbmRleF0gPSB7IC4uLmNoYW5nZWREYXRhIH07XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudGFibGVEYXRhW2luZGV4XSA9IHsgLi4udGhpcy5yb3dEYXRhVGVtcFsnZScgKyBpbmRleF0gfTtcclxuICAgICAgfVxyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlKHRoaXMudGFibGVEYXRhKTtcclxuICAgICAgdGhpcy5yb3dEYXRhVGVtcFsnZScgKyBpbmRleF0gPSB7fTtcclxuICAgICAgbGV0IGRhdGE6IFJvd0NoYW5nZSA9IHtcclxuICAgICAgICByb3c6IHsgLi4udGhpcy50YWJsZURhdGFbaW5kZXhdIH0sXHJcbiAgICAgICAgaW5kZXg6IGluZGV4LFxyXG4gICAgICB9O1xyXG4gICAgICB0aGlzLmN1cnJlbnRSb3dJbmRleCA9IC0xO1xyXG4gICAgICB0aGlzLmNlbGxDaGFuZ2UuZW1pdChkYXRhKTtcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIHdpbGwgZGVsZXRlIHRoZSByb3cgZnJvbSB0aGUgZ2l2ZW4gaW5kZXggYW5kIGVtaXQgdGhlIGRlbGV0ZWQgcm93IGFuZCBpbmRleC5cclxuICAgKiBAcGFyYW0gcm93IHJvdyB0byBiZSBkZWxldGVkLlxyXG4gICAqIEBwYXJhbSBpbmRleCBpbmRleCBvZiB0aGUgcm93IHRvIGJlIGRlbGV0ZWQuXHJcbiAgICovXHJcbiAgZGVsZXRlUm93KHJvdzogYW55LCBpbmRleDogbnVtYmVyKSB7XHJcbiAgICB0aGlzLnRhYmxlRGF0YS5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgdGhpcy5kYXRhU291cmNlID0gbmV3IE1hdFRhYmxlRGF0YVNvdXJjZSh0aGlzLnRhYmxlRGF0YSk7XHJcbiAgICB0aGlzLmRhdGFTb3VyY2UucGFnaW5hdG9yID0gdGhpcy5wYWdpbmF0b3I7XHJcbiAgICB0aGlzLmRhdGFTb3VyY2Uuc29ydCA9IHRoaXMuc29ydDtcclxuICAgIHRoaXMucm93RGVsZXRlZC5lbWl0KHsgcmVtb3ZlZFJvdzogcm93LCBmcm9tSW5kZXg6IGluZGV4IH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIHdpbGwgZXhwYW5kIG9yIGNvbGxhcHNlIHRoZSByb3cgYW5kIGVtaXQgZXhwYW5kIGV2ZW50LlxyXG4gICAqIEBwYXJhbSByb3cgcm93IHRvIGJlIGV4cGFuZGVkIG9yIGNvbGxhcHNlZC5cclxuICAgKiBAcGFyYW0gZXhwYW5kIHZhbHVlIHVzZWQgdG8gZXhwYW5kIG9yIGNvbGxhcHNlIHRoZSByb3cuXHJcbiAgICogQHBhcmFtIGluZGV4IGluZGV4IG9mIHRoZSByb3cuXHJcbiAgICovXHJcbiAgZXhwYW5kUm93KHJvdzogTVRFeFJvdywgZXhwYW5kOiBib29sZWFuLCBpbmRleDogbnVtYmVyKSB7XHJcbiAgICBpZiAodGhpcy5leHBhbmRSb3dzKSB7XHJcbiAgICAgIHRoaXMuZXhwYW5zaW9uQ2hhbmdlLmVtaXQoeyBkYXRhOiByb3csIGV4cGFuZGVkOiBleHBhbmQsIGluZGV4OiBpbmRleCB9KTtcclxuICAgICAgdGhpcy5leHBhbmRlZEVsZW1lbnQgPSB0aGlzLmV4cGFuZGVkRWxlbWVudCA9PT0gcm93ID8gbnVsbCA6IHJvdztcclxuICAgIH1cclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gc2V0IGRhdGEgZm9yIHBvcHVwIGNvbXBvbmVudCBhbmQgb3BlbiBlZGl0aW5nIGRpYWxvZy5cclxuICAgKiBAcGFyYW0gcm93IHJvdyB3aGljaCB1c2VkIHdhbnQgdG8gZWRpdC5cclxuICAgKi9cclxuICBvcGVuRWRpdGluZ0RpYWxvZyhyb3c6IE1URXhSb3cpIHtcclxuICAgIGNvbnN0IGRpYWxvZ0NvbmZpZyA9IG5ldyBNYXREaWFsb2dDb25maWcoKTtcclxuICAgIGRpYWxvZ0NvbmZpZy5kaXNhYmxlQ2xvc2UgPSB0cnVlO1xyXG4gICAgZGlhbG9nQ29uZmlnLndpZHRoID0gJzQwJSc7XHJcbiAgICBkaWFsb2dDb25maWcuaGVpZ2h0ID0gJzcwJSc7XHJcbiAgICBkaWFsb2dDb25maWcubWF4V2lkdGggPSAnMTAwJSc7XHJcbiAgICBsZXQgcm93RGF0YSA9IHsgLi4ucm93IH07XHJcbiAgICBkaWFsb2dDb25maWcuZGF0YSA9IHtcclxuICAgICAgcm93OiByb3dEYXRhLFxyXG4gICAgICBjb2x1bW5zOiBbLi4udGhpcy5jb2x1bW5zQXJyYXldLFxyXG4gICAgICB0ZW1wbGF0ZVJlZjogdGhpcy5wb3B1cEVkaXRpbmdUZW1wbGF0ZVJlZixcclxuICAgIH07XHJcbiAgICB0aGlzLmRpYWxvZ1xyXG4gICAgICAub3BlbihFZGl0aW5nQ29tcG9uZW50LCBkaWFsb2dDb25maWcpXHJcbiAgICAgIC5hZnRlckNsb3NlZCgpXHJcbiAgICAgIC5zdWJzY3JpYmUoKGRhdGEpID0+IHtcclxuICAgICAgICBsZXQgaW5kZXggPSB0aGlzLnRhYmxlRGF0YS5pbmRleE9mKHJvdyk7XHJcbiAgICAgICAgaWYgKGRhdGEgJiYgaW5kZXggPiAtMSkge1xyXG4gICAgICAgICAgdGhpcy50YWJsZURhdGFbaW5kZXhdID0gZGF0YTtcclxuICAgICAgICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBNYXRUYWJsZURhdGFTb3VyY2UodGhpcy50YWJsZURhdGEpO1xyXG4gICAgICAgICAgbGV0IGRhdGFDaGFuZ2U6IFJvd0NoYW5nZSA9IHtcclxuICAgICAgICAgICAgcm93OiBkYXRhLFxyXG4gICAgICAgICAgICBpbmRleDogaW5kZXgsXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgICAgdGhpcy5wb3B1cENoYW5nZS5lbWl0KGRhdGFDaGFuZ2UpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiB1c2VkIHRvIGNoZWNrIHdoZXRoZXIgYWxsIHJvd3MgYXJlIHNlbGVjdGVkLlxyXG4gICAqL1xyXG4gIGlzQWxsU2VsZWN0ZWQoKSB7XHJcbiAgICBjb25zdCBudW1TZWxlY3RlZCA9IHRoaXMuc2VsZWN0aW9uLnNlbGVjdGVkLmxlbmd0aDtcclxuICAgIGNvbnN0IG51bVJvd3MgPSB0aGlzLmRhdGFTb3VyY2UuZGF0YS5sZW5ndGg7XHJcbiAgICByZXR1cm4gbnVtU2VsZWN0ZWQgPT09IG51bVJvd3M7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gdGhpcyBtZXRob2QgaXMgdXNlZCB0byB0b2dnbGUgdGhlIGFsbCBhbmQgbm8gcm93cyBzZWxlY3Rpb24uXHJcbiAgICovXHJcbiAgdG9nZ2xlQWxsUm93cygpIHtcclxuICAgIGlmICh0aGlzLmlzQWxsU2VsZWN0ZWQoKSkge1xyXG4gICAgICB0aGlzLnNlbGVjdGlvbi5jbGVhcigpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnNlbGVjdGlvbi5zZWxlY3QoLi4udGhpcy5kYXRhU291cmNlLmRhdGEpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgcmV0dXJuIGFyaWEtbGFiZWwgZm9yIHNlbGVjdGlvbiBjb2x1bW4gY2hlY2tib3hzLlxyXG4gICAqIEBwYXJhbSByb3cgcm93IGZyb20gdGFibGUuXHJcbiAgICogQHJldHVybnMgbGFiZWxzIGZvciBzZWxlY3Rpb24gY29sdW1uIGNoZWNrYm94cy5cclxuICAgKi9cclxuICBjaGVja2JveExhYmVsKHJvdz86IGFueSk6IHN0cmluZyB7XHJcbiAgICBpZiAoIXJvdykge1xyXG4gICAgICByZXR1cm4gYCR7dGhpcy5pc0FsbFNlbGVjdGVkKCkgPyAnZGVzZWxlY3QnIDogJ3NlbGVjdCd9IGFsbGA7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYCR7dGhpcy5zZWxlY3Rpb24uaXNTZWxlY3RlZChyb3cpID8gJ2Rlc2VsZWN0JyA6ICdzZWxlY3QnfSByb3cgJHtcclxuICAgICAgcm93LnBvc2l0aW9uICsgMVxyXG4gICAgfWA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gY3JlYXRlIGZvcm0gY29udHJvbCBmb3IgY29sdW1ucyBmb3IgaGlkaW5nIGFuZCBhbmQgcGlubmluZyBwdXJwb3NlXHJcbiAgICogQHBhcmFtIGNvbHVtbnMgbGlzdCBvZiBjb2x1bW5zIHRvIGJlIGRpc3BsYXllZFxyXG4gICAqL1xyXG4gIHNldFRvb2xiYXJNZW51Q29udHJvbHMoY29sdW1uczogTVRFeENvbHVtbltdKSB7XHJcbiAgICBpZiAoY29sdW1ucy5sZW5ndGggPiAwICYmIHRoaXMuc2hvd1Rvb2xiYXIpIHtcclxuICAgICAgY29uc3QgZ3JvdXAgPSB0aGlzLmZvcm1CdWlsZGVyc1NlcnZpY2UuZ3JvdXAoe30pO1xyXG4gICAgICBjb2x1bW5zLmZvckVhY2goKGNvbHVtbjogTVRFeENvbHVtbikgPT4ge1xyXG4gICAgICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmZvcm1CdWlsZGVyc1NlcnZpY2UuY29udHJvbCh0cnVlKTtcclxuICAgICAgICBncm91cC5hZGRDb250cm9sKGNvbHVtbi5maWVsZCwgY29udHJvbCk7XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLmhpZGVTaG93TWVudUdyb3VwID0gZ3JvdXA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBAcGFyYW0gY29sdW1uIGN1cnJlbnQgY29sdW1uXHJcbiAgICogQHBhcmFtIGV2ZW50IG1vdXNlIGV2ZW50IHVzZWQgdG8gc2V0IHRoZSBtZW51IHBvc2l0aW9uXHJcbiAgICovXHJcbiAgb3BlblBpbm5hYmxlUHJvcGVydHlNZW51KGNvbHVtbjogTVRFeENvbHVtbiwgZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcclxuICAgIHRoaXMubWVudVggPSBldmVudC5jbGllbnRYO1xyXG4gICAgdGhpcy5tZW51WSA9IGV2ZW50LmNsaWVudFk7XHJcbiAgICBsZXQgb3B0aW9uczogTVRFeENvbHVtblBpbk9wdGlvbltdID0gW1xyXG4gICAgICB7XHJcbiAgICAgICAgbGFiZWw6ICdQaW4gTGVmdCcsXHJcbiAgICAgICAgdmFsdWU6ICdsZWZ0JyxcclxuICAgICAgICBzZWxlY3RlZDogZmFsc2UsXHJcbiAgICAgICAgZmllbGQ6IGNvbHVtbi5maWVsZCxcclxuICAgICAgfSxcclxuICAgICAge1xyXG4gICAgICAgIGxhYmVsOiAnUGluIFJpZ2h0JyxcclxuICAgICAgICB2YWx1ZTogJ3JpZ2h0JyxcclxuICAgICAgICBzZWxlY3RlZDogZmFsc2UsXHJcbiAgICAgICAgZmllbGQ6IGNvbHVtbi5maWVsZCxcclxuICAgICAgfSxcclxuICAgICAgeyBsYWJlbDogJ05vIFBpbicsIHZhbHVlOiBudWxsLCBzZWxlY3RlZDogZmFsc2UsIGZpZWxkOiBjb2x1bW4uZmllbGQgfSxcclxuICAgIF07XHJcbiAgICBpZiAoY29sdW1uLnBpbm5lZCAmJiBjb2x1bW4ucGlubmVkICE9PSBudWxsKSB7XHJcbiAgICAgIG9wdGlvbnMuZm9yRWFjaCgob3B0OiBNVEV4Q29sdW1uUGluT3B0aW9uKSA9PiB7XHJcbiAgICAgICAgaWYgKG9wdC52YWx1ZSA9PT0gY29sdW1uLnBpbm5lZCkge1xyXG4gICAgICAgICAgb3B0LnNlbGVjdGVkID0gdHJ1ZTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfSBlbHNlIGlmIChjb2x1bW4ucGlubmVkID09IG51bGwgfHwgY29sdW1uLnBpbm5lZCA9PSAnbnVsbCcpIHtcclxuICAgICAgb3B0aW9uc1syXS5zZWxlY3RlZCA9IHRydWU7XHJcbiAgICB9XHJcbiAgICB0aGlzLmNvbHVtblBpbm5pbmdPcHRpb25zID0gb3B0aW9ucztcclxuICAgIHRoaXMuY29sdW1uTWVudVRyaWdnZXIub3Blbk1lbnUoKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gcmVzZXQgbWVudSBjaGVja3Mgd2hlbiByZXF1aXJlZC5cclxuICAgKi9cclxuICByZXNldE1lbnVDaGVja3MoKSB7XHJcbiAgICB0aGlzLmhpZGVTaG93TWVudUN0cmwgPSBmYWxzZTtcclxuICAgIHRoaXMuc2hvd0hpZGVDb2x1bW5zQXJyYXkgPSBbXTtcclxuICAgIHRoaXMuY29sdW1uUGluTWVudUN0cmwgPSBmYWxzZTtcclxuICAgIHRoaXMuY29sdW1uUGlubmluZ09wdGlvbnMgPSBbXTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gZmlsdGVyIGNvbHVtbnMgZm9yIG1lbnVzIGxpa2UgcGlubmluZyBvciBoaWRlIHNob3cgbWVudS5cclxuICAgKiBAcGFyYW0gdmFsdWUgc2VhcmNoIHZhbHVlIHRvIGZpbHRlciBjb2x1bm1zXHJcbiAgICovXHJcbiAgZmlsdGVyQ29sdW1ucyh2YWx1ZTogc3RyaW5nKSB7XHJcbiAgICBpZiAodmFsdWUgIT09ICcnKSB7XHJcbiAgICAgIHRoaXMuc2hvd0hpZGVDb2x1bW5zQXJyYXkgPSB0aGlzLmNvbHVtbnNBcnJheS5maWx0ZXIoXHJcbiAgICAgICAgKGNvbDogTVRFeENvbHVtbikgPT4ge1xyXG4gICAgICAgICAgcmV0dXJuIGNvbC5oZWFkZXIhLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModmFsdWUudG9Mb3dlckNhc2UoKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICApO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zaG93SGlkZUNvbHVtbnNBcnJheSA9IHRoaXMuY29sdW1uc0FycmF5O1xyXG4gICAgfVxyXG4gIH1cclxuICAvKipcclxuICAgKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2QgaXMgdXNlZCB0byBvcGVuIGhpZGUgc2hvdyBjb2x1bW4gbWVudS5cclxuICAgKiBAcGFyYW0gY29sdW1ucyBjb2x1bW5zIGFycmF5IHRvIGRpc3BsYXkgaW4gaGlkZSBzaG93IG1lbnUuXHJcbiAgICovXHJcbiAgb3BlbkhpZGVTaG93TWVudShjb2x1bW5zOiBNVEV4Q29sdW1uW10pIHtcclxuICAgIHRoaXMuc2hvd0hpZGVDb2x1bW5zQXJyYXkgPSBbLi4uY29sdW1uc107XHJcbiAgICB0aGlzLmNvbHVtbk1lbnVUcmlnZ2VyLm9wZW5NZW51KCk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBwYXJhbSB2YWx1ZXMgY29sdW1uc1xyXG4gICAqL1xyXG4gIHVwZGF0ZUNvbHVtbnNIaWRlU2hvdyh2YWx1ZXM6IENvbHVtblZpc2liaWxpdHkpIHtcclxuICAgIGxldCBrZXlzID0gT2JqZWN0LmtleXModmFsdWVzKTtcclxuICAgIGtleXMuZm9yRWFjaCgoa2V5OiBzdHJpbmcpID0+IHtcclxuICAgICAgdGhpcy5zaG93SGlkZUNvbHVtbihrZXksIHZhbHVlc1trZXldKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCB3aGVuIHRoZSB0YWJsZSByb3dzIGFyZSBzY3JvbGxlZC5cclxuICAgKiBAcGFyYW0gZXZlbnQgc2Nyb2xsIGV2ZW50XHJcbiAgICovXHJcbiAgb25TY3JvbGwoZXZlbnQ6IGFueSkge1xyXG4gICAgdGhpcy5zY3JvbGwuZW1pdChldmVudCk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBwYXJhbSByb3cgcm93IHRvIGJlIHRvZ2dsZWRcclxuICAgKiBAcGFyYW0gaW5kZXggaW5kZXggb2YgdG9nZ2xlZCByb3dcclxuICAgKi9cclxuICBzZXRTZWxlY3RlZFJvd3Mocm93OiBhbnksIGluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMuc2VsZWN0aW9uLnRvZ2dsZShyb3cpO1xyXG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uLmlzU2VsZWN0ZWQocm93KSkge1xyXG4gICAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZWQuZW1pdCh7IHJvdzogcm93LCBpbmRleDogaW5kZXgsIGlzU2VsZWN0ZWQ6IHRydWUgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnNlbGVjdGlvbkNoYW5nZWQuZW1pdCh7IHJvdzogcm93LCBpbmRleDogaW5kZXgsIGlzU2VsZWN0ZWQ6IGZhbHNlIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuLyoqXHJcbiAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCBpcyB1c2VkIHRvIGRpc3BsYXkgYWxsIGhpZGRlbiByb3dzLlxyXG4gKi9cclxuICBzaG93SGlkZGVuUm93cygpIHtcclxuICAgIHRoaXMuaGlkZVJvd3MgPSBmYWxzZTtcclxuICAgIHRoaXMuc2VsZWN0aW9uLmNsZWFyKCk7XHJcbiAgICB0aGlzLmhpZGRlbkN0cmwuY2xlYXIoKTtcclxuICB9XHJcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2QgaXMgdXNlZCB0byBoaWRlIGFsbCBzZWxlY3RlZCByb3dzLlxyXG4gKi9cclxuICBoaWRlU2VsZWN0ZWRSb3dzKCkge1xyXG4gICAgaWYgKCF0aGlzLnNlbGVjdGlvbi5pc0VtcHR5KCkpIHtcclxuICAgICAgbGV0IHZhbHVlcyA9IFsuLi50aGlzLnNlbGVjdGlvbi5zZWxlY3RlZF07XHJcbiAgICAgIHZhbHVlcy5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIGlmICghdGhpcy5oaWRkZW5DdHJsLmlzU2VsZWN0ZWQodmFsdWUpKSB7XHJcbiAgICAgICAgICB0aGlzLmhpZGRlbkN0cmwudG9nZ2xlKHZhbHVlKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICB0aGlzLnNlbGVjdGlvbi5jbGVhcigpO1xyXG4gICAgICB0aGlzLmhpZGVSb3dzID0gdHJ1ZTtcclxuICAgIH1cclxuICB9XHJcbi8qKlxyXG4gKiBAZGVzY3JpcHRpb24gVGhpcyBtZXRob2QgaXMgdXNlZCB0byByZWNhbGN1bGF0ZSB0aGUgcmVxdWlyZWQgdmFsdWVzIGZvciB0YWJsZS5cclxuICovXHJcbiAgcmVDYWwoKSB7XHJcbiAgICBpZiAodGhpcy5zaG93UGFnaW5hdG9yKSB7XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5wYWdpbmF0b3IgPSB0aGlzLnBhZ2luYXRvcjtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLnNvcnRpbmcpIHtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLnNvcnQgPSB0aGlzLnNvcnQ7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5jb2x1bW5GaWx0ZXIpIHtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLmZpbHRlclByZWRpY2F0ZSA9IHRoaXMuY3JlYXRlRmlsdGVyKCk7XHJcbiAgICB9XHJcbiAgfVxyXG4vKipcclxuICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIGNhbGxlZCBpbiBjb25zdHJ1Y3RvciBtZXRob2QgdG8gYWRkIFNWR3MgaW50byBpY29uIHJlZ2lzdHJhdGlvbi5cclxuICovXHJcbiAgYWRkSWNvbnNUb1JlZ2lzdHJ5KCkge1xyXG4gICAgbGV0IHkgPSB0aGlzLmRvbVNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0UmVzb3VyY2VVcmwoXHJcbiAgICAgIGBhc3NldHMvcGluUmlnaHQuc3ZnYFxyXG4gICAgKTtcclxuICAgIGxldCBpY29uTmFtZXMgPSBbJ3BpbkxlZnQnLCAncGluUmlnaHQnLCAncGluTm9uZScsICdwaW5uZWQnLCAncGluSWNvbiddO1xyXG4gICAgaWNvbk5hbWVzLmZvckVhY2goKGljb24pID0+IHtcclxuICAgICAgdGhpcy5tYXRJY29uUmVnaXN0cnkuYWRkU3ZnSWNvbihcclxuICAgICAgICBpY29uLFxyXG4gICAgICAgIHRoaXMuZG9tU2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybChcclxuICAgICAgICAgIGBhc3NldHMvJHtpY29ufS5zdmdgXHJcbiAgICAgICAgKVxyXG4gICAgICApO1xyXG4gICAgfSk7XHJcbiAgfVxyXG4vKipcclxuICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gZXhwb3J0IHRhYmxlIGRhdGEuXHJcbiAqIEBwYXJhbSB0eXBlIHR5cGUgb2YgZmlsZSB0byBiZSBleHBvcnRlZC5cclxuICovXHJcbiAgZXhwb3J0VGFibGUodHlwZTogc3RyaW5nKSB7XHJcbiAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtYXRUYWJsZUV4dCcgKyB0aGlzLnRhYmxlSUQpO1xyXG4gICAgdmFyIHdzOiBYTFNYLldvcmtTaGVldCA9IFhMU1gudXRpbHMudGFibGVfdG9fc2hlZXQoZWxlbWVudCk7XHJcbiAgICB3cyA9IHRoaXMud3JpdGVTaGVldERhdGEod3MpO1xyXG4gICAgY29uc3Qgd2I6IFhMU1guV29ya0Jvb2sgPSBYTFNYLnV0aWxzLmJvb2tfbmV3KCk7XHJcbiAgICBYTFNYLnV0aWxzLmJvb2tfYXBwZW5kX3NoZWV0KHdiLCB3cywgJ1NoZWV0MScpO1xyXG4gICAgWExTWC53cml0ZUZpbGUod2IsIGB0YWJsZXNoZWV0cy4ke3R5cGV9YCk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEBkZXNjcmlwdGlvbiBUaGlzIG1ldGhvZCBpcyB1c2VkIHRvIHNwbGl0IG5hbWUgb2YgZmlsdGVyIHJvdyBoZWFkZXIgdG8gZ2V0IGluZGV4LlxyXG4gICAqIEBwYXJhbSB2YWx1ZSB2YWx1ZSB0byBiZSBzcGxpdGVkIGZvciBpbmRleC5cclxuICAgKiBAcmV0dXJucyBXaWxsIHJldHVybiBpbmRleCBvZiBjb2x1bW4gZnJvbSB2YWx1ZS5cclxuICAgKi9cclxuICByZXR1cm5JbmRleCh2YWx1ZTogc3RyaW5nKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBOdW1iZXIodmFsdWUuc3BsaXQoJ18nKVsxXSk7XHJcbiAgfVxyXG4vKipcclxuICogQGRlc2NyaXB0aW9uIFRoaXMgbWV0aG9kIGlzIHVzZWQgdG8gbWFuYWdlIGNvbHVtbiBmaWx0ZXJpbmcsIGV4cGFuZGVkIGRhdGEgZm9yIGV4cG9ydGluZy5cclxuICogQHBhcmFtIHdzIHdvcmsgc2hlZXRcclxuICogQHJldHVybnMgY3VzdG9tIGdlbmVyYXRlZCB3b3Jrc2hlZXQgdG8gYmUgdXNlZCBpbiBleHBvcnQuXHJcbiAqL1xyXG4gIHdyaXRlU2hlZXREYXRhKHdzOiBYTFNYLldvcmtTaGVldCk6IFhMU1guV29ya1NoZWV0IHtcclxuICAgIGxldCBkaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5nZXREaXNwbGF5ZWRDb2x1bW5zKCk7XHJcbiAgICB2YXIgbk1lcmdlcyA9IHRoaXMuZ2V0TWVyZ2VJbmRleCh3c1snIW1lcmdlcyddIHx8IFtdKTtcclxuICAgIHZhciBtZXJnZXMgPSB3c1snIW1lcmdlcyddIHx8IFtdO1xyXG4gICAgbGV0IGRhdGE6IFhMU1guV29ya1NoZWV0ID0ge1xyXG4gICAgICAnIWNvbHMnOiBbXSxcclxuICAgICAgJyFyb3dzJzogW10sXHJcbiAgICAgICchbWVyZ2VzJzogbk1lcmdlcyxcclxuICAgIH07XHJcbiAgICB2YXIgcmFuZ2UgPSBYTFNYLnV0aWxzLmRlY29kZV9yYW5nZSh3c1snIXJlZiddIHx8ICcnKTtcclxuICAgIGxldCBleHRyYWNvbHVtbnMgPSBbJ3BvcHVwJywgJ2RlbGV0ZScsICdzZWxlY3QnLCAnZWRpdCddO1xyXG4gICAgbGV0IGtleXMgPSBPYmplY3Qua2V5cyh3cyk7XHJcbiAgICBsZXQgbktleSA9ICdBJztcclxuICAgIGtleXMuZm9yRWFjaCgoa2V5LCBpKSA9PiB7XHJcbiAgICAgIGlmICh3c1trZXldPy52ICYmIHR5cGVvZiB3c1trZXldPy52ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgICFleHRyYWNvbHVtbnMuaW5jbHVkZXMod3Nba2V5XS52LnRvTG93ZXJDYXNlKCkpICYmXHJcbiAgICAgICAgICBkaXNwbGF5ZWRDb2x1bW5zLmluY2x1ZGVzKHdzW2tleV0udi50b0xvd2VyQ2FzZSgpKVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgbGV0IGxhc3RSb3dJbmRleCA9IHJhbmdlPy5lPy5yO1xyXG4gICAgICAgICAgZGF0YVtrZXldID0gd3Nba2V5XTtcclxuICAgICAgICAgIGxldCBjaHIgPSBrZXkuY2hhckF0KDApO1xyXG4gICAgICAgICAgZm9yIChsZXQgaiA9IDI7IGogPD0gbGFzdFJvd0luZGV4OyBqKyspIHtcclxuICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgIHdzW2NociArIChqICsgMSldICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgICAgICAgICAodHlwZW9mIHdzW2NociArIChqICsgMSldLnYgPT09ICdzdHJpbmcnIHx8XHJcbiAgICAgICAgICAgICAgICB0eXBlb2Ygd3NbY2hyICsgKGogKyAxKV0udiA9PT0gJ251bWJlcicpXHJcbiAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgIGRhdGFbbktleSArIGpdID0gd3NbY2hyICsgKGogKyAxKV07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIG5LZXkgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKG5LZXkuY2hhckNvZGVBdCgwKSArIDEpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgICBpZiAodGhpcy5yb3dTZWxlY3Rpb24pIHtcclxuICAgICAgbGV0IGNociA9ICdBJztcclxuICAgICAgZm9yIChsZXQgaSA9IDE7IGkgPCByYW5nZS5lLmMgKyAxOyBpKyspIHtcclxuICAgICAgICBkYXRhW2NociArIDFdID0gZGF0YVtTdHJpbmcuZnJvbUNoYXJDb2RlKGNoci5jaGFyQ29kZUF0KDApICsgMSkgKyAxXTtcclxuICAgICAgICBjaHIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGNoci5jaGFyQ29kZUF0KDApICsgMSk7XHJcbiAgICAgICAgaWYgKGkgPT0gcmFuZ2UuZS5jKSB7XHJcbiAgICAgICAgICBkYXRhW2NociArIDFdID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMucm93U2VsZWN0aW9uICYmIHRoaXMuZXhwYW5kUm93cykge1xyXG4gICAgICBtZXJnZXMuZm9yRWFjaCgobWVyZ2UpID0+IHtcclxuICAgICAgICBkYXRhWydBJyArIG1lcmdlLnMucl0gPSB3c1snQScgKyAobWVyZ2Uucy5yICsgMSldO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICAgIHJhbmdlLmUuci0tO1xyXG4gICAgbGV0IG5SZWYgPSBYTFNYLnV0aWxzLmVuY29kZV9yYW5nZShyYW5nZSk7XHJcbiAgICBkYXRhWychcmVmJ10gPSBuUmVmO1xyXG4gICAgZGF0YVsnIWZ1bGxyZWYnXSA9IG5SZWY7XHJcbiAgICByZXR1cm4gZGF0YTtcclxuICB9XHJcbiAgZ2V0TWVyZ2VJbmRleChtZXJnZXM6IGFueVtdKSB7XHJcbiAgICB2YXIgYXJyOiBhbnlbXSA9IFtdO1xyXG4gICAgbWVyZ2VzLmZvckVhY2goKGVsZW1lbnQ6IGFueSkgPT4ge1xyXG4gICAgICBhcnIucHVzaCh7XHJcbiAgICAgICAgZToge1xyXG4gICAgICAgICAgcjogZWxlbWVudC5lLnIgPT0gMCA/IGVsZW1lbnQuZS5yIDogZWxlbWVudC5lLnIgLSAxLFxyXG4gICAgICAgICAgYzogZWxlbWVudC5lLmMsXHJcbiAgICAgICAgfSxcclxuICAgICAgICBzOiB7XHJcbiAgICAgICAgICByOiBlbGVtZW50LnMuciA9PSAwID8gZWxlbWVudC5zLnIgOiBlbGVtZW50LnMuciAtIDEsXHJcbiAgICAgICAgICBjOiBlbGVtZW50LnMuYyxcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGFycjtcclxuICB9XHJcbn1cclxuIiwiPG1hdC1jYXJkIGNsYXNzPVwibWFpbi10YWJsZS1leHQtY29udGFpbmVyIG1hdC1lbGV2YXRpb24tejhcIiBbc3R5bGUud2lkdGhdPVwidGFibGVXaWR0aFwiPlxyXG4gICAgPG1hdC1mb3JtLWZpZWxkIGNsYXNzPVwiZ2xvYmFsLXNlYXJjaC1maWVsZFwiIGFwcGVhcmFuY2U9XCJmaWxsXCIgKm5nSWY9XCJnbG9iYWxTZWFyY2hcIj5cclxuICAgICAgICA8bWF0LWxhYmVsPlNlYXJjaDwvbWF0LWxhYmVsPlxyXG4gICAgICAgIDxpbnB1dCBtYXRJbnB1dCBbbmdNb2RlbF09XCJnbG9iYWxGaWx0ZXJcIiAobmdNb2RlbENoYW5nZSk9XCJhcHBseUdsb2JhbEZpbHRlcigkZXZlbnQpXCIgcGxhY2Vob2xkZXI9XCJFeC4gTWlhXCIgI2lucHV0PlxyXG4gICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgIDxtYXQtdG9vbGJhciBjbGFzcz1cInRvb2xiYXItY29udGFpbmVyXCIgKm5nSWY9XCJzaG93VG9vbGJhclwiIFtzdHlsZS5oZWlnaHRdPVwidG9vbGJhckhlaWdodD90b29sYmFySGVpZ2h0Oic1MHB4J1wiPlxyXG4gICAgICAgIDxzcGFuIGNsYXNzPVwidG9vbGJhci10aXRsZVwiICpuZ0lmPVwidG9vbGJhclRpdGxlXCI+e3t0b29sYmFyVGl0bGV9fTwvc3Bhbj5cclxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidG9vbGJhclRlbXBsYXRlUmVmXCIgW25nVGVtcGxhdGVPdXRsZXRdPVwidG9vbGJhclRlbXBsYXRlUmVmXCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJleGFtcGxlLXNwYWNlclwiPjwvc3Bhbj5cclxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwicm93U2VsZWN0aW9uIHx8IG11bHRpUm93U2VsZWN0aW9uXCI+XHJcbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJoaWRlLWJ1dHRvblwiIG1hdC1zdHJva2VkLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiAoY2xpY2spPVwiaGlkZVNlbGVjdGVkUm93cygpXCI+XHJcbiAgICAgICAgICAgICAgICBIaWRlIFJvd3NcclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJoaWRlLWJ1dHRvblwiIG1hdC1zdHJva2VkLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiAoY2xpY2spPVwic2hvd0hpZGRlblJvd3MoKVwiPlxyXG4gICAgICAgICAgICAgICAgU2hvdyBBbGwgUm93c1xyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiY29sdW1uSGlkYWJsZVwiIGNsYXNzPVwiaGlkZS1idXR0b25cIiBtYXQtc3Ryb2tlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cIm9wZW5NZW51KCdoaWRlU2hvdycsJGV2ZW50KVwiIG1hdFRvb2x0aXA9XCJDb2x1bW4gVmlzaWJpbGl0eVwiIG1hdFRvb2x0aXBQb3NpdGlvbj1cImFib3ZlXCI+XHJcbiAgICAgICAgICAgIDxtYXQtaWNvbj52aXNpYmlsaXR5PC9tYXQtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiY29sdW1uUGlubmFibGVcIiBjbGFzcz1cInBpbi1idXR0b25cIiBtYXQtc3Ryb2tlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cIm9wZW5NZW51KCdjb2x1bW5QaW4nLCRldmVudClcIiBtYXRUb29sdGlwPVwiQ29sdW1uIFBpbm5pbmdcIj5cclxuICAgICAgICAgICAgPG1hdC1pY29uIHN2Z0ljb249XCJwaW5JY29uXCI+PC9tYXQtaWNvbj5cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YnV0dG9uICpuZ0lmPVwiZXhwb3J0QnV0dG9uRW5hYmxlXCIgY2xhc3M9XCJleHBvcnQtYnV0dG9uXCIgbWF0LXN0cm9rZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJvcGVuTWVudSgnZXhwb3J0JywkZXZlbnQpXCIgbWF0VG9vbHRpcD1cIlRhYmxlIERhdGEgRXhwb3J0XCI+XHJcbiAgICAgICAgICAgIDxtYXQtaWNvbj5pbXBvcnRfZXhwb3J0PC9tYXQtaWNvbj4gPHNwYW4+RXhwb3J0PC9zcGFuPlxyXG4gICAgICAgICAgICA8bWF0LWljb24+ZXhwYW5kX21vcmU8L21hdC1pY29uPlxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDxkaXYgc3R5bGU9XCJ2aXNpYmlsaXR5OiBoaWRkZW47IHBvc2l0aW9uOmZpeGVkXCIgW21hdE1lbnVUcmlnZ2VyRm9yXT1cIm1lbnVcIiBbc3R5bGUubGVmdC5weF09XCJtZW51WFwiXHJcbiAgICAgICAgICAgIFtzdHlsZS50b3AucHhdPVwibWVudVlcIj48L2Rpdj5cclxuICAgIDwvbWF0LXRvb2xiYXI+XHJcbiAgICA8bWF0LW1lbnUgI21lbnU9XCJtYXRNZW51XCIgKGNsb3NlZCk9XCJtZW51Q2xvc2VkKClcIiBpZD1cImV4cG9ydE1lbnVcIj5cclxuICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZXhwb3J0TWVudUN0cmxcIj5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gKGNsaWNrKT1cImV4cG9ydFRhYmxlKCd4bHN4JylcIj5FeHBvcnQgdG8gRXhjZWw8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgIDxtYXQtb3B0aW9uIChjbGljayk9XCJleHBvcnRUYWJsZSgnY3N2JylcIj5FeHBvcnQgdG8gQ1NWPC9tYXQtb3B0aW9uPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgPC9tYXQtbWVudT5cclxuICAgIDxkaXYgc3R5bGU9XCJ2aXNpYmlsaXR5OiBoaWRkZW47IHBvc2l0aW9uOmZpeGVkXCIgI2NvbHVtbk1lbnVUcmlnZ2VyPVwibWF0TWVudVRyaWdnZXJcIiBbbWF0TWVudVRyaWdnZXJGb3JdPVwiY29sdW1uTWVudVwiXHJcbiAgICAgICAgW3N0eWxlLmxlZnQucHhdPVwibWVudVhcIiBbc3R5bGUudG9wLnB4XT1cIm1lbnVZXCI+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxtYXQtbWVudSAjY29sdW1uTWVudT1cIm1hdE1lbnVcIiAoY2xvc2VkKT1cInJlc2V0TWVudUNoZWNrcygpXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInRvb2xiYXItbWVudS1jb250YWluZXJcIiAqbmdJZj1cImhpZGVTaG93TWVudUN0cmxcIiBbZm9ybUdyb3VwXT1cImhpZGVTaG93TWVudUdyb3VwXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiPlxyXG4gICAgICAgICAgICA8aDQgY2xhc3M9XCJjb2x1bW4taGVhZGVyc1wiPlZpc2libGUgQ29sdW1uczwvaDQ+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwiZmlsbFwiIHN0eWxlPVwid2lkdGg6IC13ZWJraXQtZmlsbC1hdmFpbGFibGU7XCI+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPkZpbHRlciBDb2x1bW5zPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgWyhuZ01vZGVsKV09XCJzaG93SGlkZUZpbHRlclwiIChuZ01vZGVsQ2hhbmdlKT1cImZpbHRlckNvbHVtbnMoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiPlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2hvd0hpZGUtbWVudS1jb2x1bW5zLWxpc3RcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ0b29sYmFyLW1lbnUtaXRlbVwiICpuZ0Zvcj1cImxldCBjb2x1bW4gb2Ygc2hvd0hpZGVDb2x1bW5zQXJyYXlcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bWF0LWNoZWNrYm94IGNvbG9yPVwicHJpbWFyeVwiIGNsYXNzPVwidG9vbGJhci1tZW51LWNoZWNrYm94XCIgc3R5bGU9XCJ3aWR0aDogbWF4LWNvbnRlbnQ7XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJjb2x1bW4uZmllbGRcIiAoY2hhbmdlKT1cInNldENvbHVtbkhpZGVTaG93KClcIj57e2NvbHVtbi5oZWFkZXJ9fTwvbWF0LWNoZWNrYm94PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0b29sYmFyLW1lbnUtY29udGFpbmVyXCIgKm5nSWY9XCJjb2x1bW5QaW5NZW51Q3RybFwiIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj5cclxuICAgICAgICAgICAgPGg0IGNsYXNzPVwiY29sdW1uLWhlYWRlcnNcIj5QaW4gQ29sdW1uczwvaDQ+XHJcbiAgICAgICAgICAgIDxmb3JtIGNsYXNzPVwiZXhhbXBsZS1mb3JtXCI+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cImZpbGxcIiBzdHlsZT1cIndpZHRoOiAtd2Via2l0LWZpbGwtYXZhaWxhYmxlO1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+RmlsdGVyIENvbHVtbnM8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgWyhuZ01vZGVsKV09XCJzaG93SGlkZUZpbHRlclwiIChuZ01vZGVsQ2hhbmdlKT1cImZpbHRlckNvbHVtbnMoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7c3RhbmRhbG9uZTogdHJ1ZX1cIj5cclxuICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgIDwvZm9ybT5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNob3dIaWRlLW1lbnUtY29sdW1ucy1saXN0XCI+XHJcbiAgICAgICAgICAgICAgICA8YXBwLWNvbHVtbi1waW5uaW5nIFtjb2x1bW5zXT1cInNob3dIaWRlQ29sdW1uc0FycmF5XCI+PC9hcHAtY29sdW1uLXBpbm5pbmc+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9tYXQtbWVudT5cclxuXHJcbiAgICA8bWF0LXByb2dyZXNzLWJhciAqbmdJZj1cImxvYWRpbmdJbmRpY2F0b3JcIiBtb2RlPVwiaW5kZXRlcm1pbmF0ZVwiPjwvbWF0LXByb2dyZXNzLWJhcj5cclxuICAgIDxzZWN0aW9uIGlkPVwidGFibGVDb250YWluZXJcIiBjbGFzcz1cIm1hdC10YWJsZS1leHQtY29udGFpbmVyXCIgKHNjcm9sbCk9XCJvblNjcm9sbCgkZXZlbnQpXCJcclxuICAgICAgICBbc3R5bGUuaGVpZ2h0XT1cInRhYmxlSGVpZ2h0ID8gdGFibGVIZWlnaHQgOidtYXgtY29udGVudCdcIj5cclxuICAgICAgICA8dGFibGUgbWF0LXRhYmxlIFtpZF09XCInbWF0VGFibGVFeHQnK3RhYmxlSURcIiBbZGF0YVNvdXJjZV09XCJkYXRhU291cmNlXCIgbWF0U29ydCBjZGtEcm9wTGlzdFxyXG4gICAgICAgICAgICBjZGtEcm9wTGlzdE9yaWVudGF0aW9uPVwiaG9yaXpvbnRhbFwiIG11bHRpVGVtcGxhdGVEYXRhUm93cyAoY2RrRHJvcExpc3REcm9wcGVkKT1cIm9uRHJvcCgkZXZlbnQpXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cInNhdmVDZWxsRWRpdGluZygpXCIgW3N0eWxlLndpZHRoXT1cInNjcm9sbGJhckg/J21heC1jb250ZW50JzonMTAwJSdcIj5cclxuICAgICAgICAgICAgPCEtLSBSb3cgc2VsZWN0aW9uIGNvbHVtbiAtLT5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJzZWxlY3RcIj5cclxuICAgICAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgY2RrRHJhZ0xvY2tBeGlzPVwieFwiIGNka0RyYWcgW2Nka0RyYWdEaXNhYmxlZF09XCIhZG5kQ29sdW1uc1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXQtY2hlY2tib3ggKGNoYW5nZSk9XCIkZXZlbnQgPyB0b2dnbGVBbGxSb3dzKCkgOiBudWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwic2VsZWN0aW9uLmhhc1ZhbHVlKCkgJiYgaXNBbGxTZWxlY3RlZCgpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2luZGV0ZXJtaW5hdGVdPVwic2VsZWN0aW9uLmhhc1ZhbHVlKCkgJiYgIWlzQWxsU2VsZWN0ZWQoKVwiIFthcmlhLWxhYmVsXT1cImNoZWNrYm94TGFiZWwoKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWNoZWNrYm94PlxyXG4gICAgICAgICAgICAgICAgPC90aD5cclxuICAgICAgICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3c7bGV0IGkgPSBkYXRhSW5kZXhcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bWF0LWNoZWNrYm94IChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIiAoY2hhbmdlKT1cIiRldmVudCA/IHNldFNlbGVjdGVkUm93cyhyb3csaSkgOiBudWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwic2VsZWN0aW9uLmlzU2VsZWN0ZWQocm93KVwiIFthcmlhLWxhYmVsXT1cImNoZWNrYm94TGFiZWwocm93KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWNoZWNrYm94PlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJzaG93Rm9vdGVyUm93XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRkIG1hdC1mb290ZXItY2VsbCAqbWF0Rm9vdGVyQ2VsbERlZj48L3RkPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8IS0tZHluYW1pYyBjb2x1bW5zIGFyZSBiZWluZyBnZW5lcmF0ZWQgaGVyZS0tPlxyXG4gICAgICAgICAgICA8ZGl2IG1hdENvbHVtbkRlZj1cInt7Y29sdW1uWydmaWVsZCddfX1cIiBbc3RpY2t5XT1cImNvbHVtbi5waW5uZWQgPT0gJ2xlZnQnID8gdHJ1ZTpmYWxzZVwiXHJcbiAgICAgICAgICAgICAgICBbc3RpY2t5RW5kXT1cImNvbHVtbi5waW5uZWQgPT0gJ3JpZ2h0JyA/IHRydWU6ZmFsc2VcIiAqbmdGb3I9XCJsZXQgY29sdW1uIG9mIGNvbHVtbnNBcnJheTsgbGV0IGkgPSBpbmRleFwiPlxyXG4gICAgICAgICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCAqbWF0SGVhZGVyQ2VsbERlZiBbc3R5bGUud2lkdGhdPVwiY29sdW1uLndpZHRoXCIgW3N0eWxlLm1heFdpZHRoXT1cImNvbHVtbi5tYXhXaWR0aFwiXHJcbiAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1pbldpZHRoXT1cImNvbHVtbi5taW5XaWR0aFwiIGNka0RyYWdMb2NrQXhpcz1cInhcIiBjZGtEcmFnIFtjZGtEcmFnRGlzYWJsZWRdPVwiIWRuZENvbHVtbnNcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtjb2x1bW5zUmVzaXphYmxlXT1cImNvbHVtblJlc2l6YWJsZVwiIFtpbmRleF09XCJpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIhaGVhZGVyVGVtcGxhdGVSZWZcIiBtYXRUb29sdGlwPVwie3tjb2x1bW4uaGVhZGVyVG9vbHRpcD8udmFsdWV9fVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFttYXRUb29sdGlwUG9zaXRpb25dPVwiY29sdW1uPy5oZWFkZXJUb29sdGlwPy50b29sdGlwUG9zaXRpb24hXCIgbWF0LXNvcnQtaGVhZGVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhc29ydGluZyB8fCBjb2x1bW4uZGlzYWJsZWQgPT09IHRydWVcIj57e2NvbHVtbi5oZWFkZXJ9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaGVhZGVyVGVtcGxhdGVSZWZcIiBbbmdUZW1wbGF0ZU91dGxldF09XCJoZWFkZXJUZW1wbGF0ZVJlZlwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ZGF0YTpjb2x1bW59XCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvbHVtbi5oZWFkZXJUZW1wbGF0ZVwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNvbHVtbi5oZWFkZXJUZW1wbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7ZGF0YTpjb2x1bW59XCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvdyA7bGV0IGk9ZGF0YUluZGV4XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cIiFyb3cuZWRpdGFibGUgJiYgIWNlbGxFZGl0aW5nW2kgKydfJytjb2x1bW4uZmllbGRdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgKGRibGNsaWNrKT1cImNlbGxFZGl0aW5nW2kgKydfJytjb2x1bW4uZmllbGRdID0gaW5DZWxsRWRpdGluZztzZXRDZWxsRGF0YShyb3csaSlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwie3tjb2x1bW4uY2VsbFRvb2x0aXA/LnZhbHVlfX1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcFBvc2l0aW9uXT1cImNvbHVtbj8uY2VsbFRvb2x0aXA/LnRvb2x0aXBQb3NpdGlvbiFcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiIWNlbGxUZW1wbGF0ZVJlZiAmJiAhY29sdW1uPy5jZWxsVGVtcGxhdGUgJiYgIWNlbGxUZW1wbGF0ZVJlZk1hcFtjb2x1bW4uZmllbGRdXCI+e3tyb3dbY29sdW1uLmZpZWxkXX19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY2VsbFRlbXBsYXRlUmVmTWFwW2NvbHVtbi5maWVsZF1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY2VsbFRlbXBsYXRlUmVmTWFwW2NvbHVtbi5maWVsZF1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntyb3c6cm93LGNvbHVtbjpjb2x1bW4saW5kZXg6aX1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiY2VsbFRlbXBsYXRlUmVmICYmIGNvbHVtbi5jZWxsVGVtcGxhdGUgJiYgIWNlbGxUZW1wbGF0ZVJlZk1hcFtjb2x1bW4uZmllbGRdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNvbHVtbi5jZWxsVGVtcGxhdGVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntyb3c6cm93LGNvbHVtbjpjb2x1bW4saW5kZXg6aX1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiIWNlbGxUZW1wbGF0ZVJlZiAmJiBjb2x1bW4uY2VsbFRlbXBsYXRlICYmICFjZWxsVGVtcGxhdGVSZWZNYXBbY29sdW1uLmZpZWxkXVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjb2x1bW4uY2VsbFRlbXBsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7cm93OnJvdyxjb2x1bW46Y29sdW1uLGluZGV4Oml9XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImNlbGxUZW1wbGF0ZVJlZiAmJiAhY29sdW1uLmNlbGxUZW1wbGF0ZSAmJiAhY2VsbFRlbXBsYXRlUmVmTWFwW2NvbHVtbi5maWVsZF1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY2VsbFRlbXBsYXRlUmVmXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7cm93OnJvdyxjb2x1bW46Y29sdW1uLGluZGV4Oml9XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJyb3cuZWRpdGFibGUgfHwgY2VsbEVkaXRpbmdbaSArJ18nK2NvbHVtbi5maWVsZF1cIiAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJpbmxpbmVFZGl0aW5nVGVtcGxhdGVSZWYgJiYgIWNlbGxFZGl0aW5nW2kgKydfJytjb2x1bW4uZmllbGRdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImlubGluZUVkaXRpbmdUZW1wbGF0ZVJlZlwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwie2RhdGE6Z2V0SW5saW5lRWRpdGluZ0RhdGEocm93LGksY29sdW1uKX1cIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNlbGxFZGl0aW5nVGVtcGxhdGVSZWYgJiYgIShyb3cuZWRpdGFibGUpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNlbGxFZGl0aW5nVGVtcGxhdGVSZWZcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cIntkYXRhOmdldElubGluZUVkaXRpbmdEYXRhKHJvdyxpLGNvbHVtbil9XCI+PC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhaW5saW5lRWRpdGluZ1RlbXBsYXRlUmVmICYmIChyb3cuZWRpdGFibGUpICYmIHJvd0RhdGFUZW1wWydlJytpXVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiY29sdW1uLnR5cGUgPT0gJ251bWJlcidcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJpbmxpbmUtZWRpdGluZy1maWVsZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCB0eXBlPVwibnVtYmVyXCIgWyhuZ01vZGVsKV09XCJyb3dEYXRhVGVtcFsnZScraV1bY29sdW1uLmZpZWxkXVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7c3RhbmRhbG9uZTogdHJ1ZX1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgc3R5bGU9XCJ3aWR0aDogMTAwJTtcIiAqbmdJZj1cImNvbHVtbi50eXBlID09ICdzdHJpbmcnXCIgYXBwZWFyYW5jZT1cIm91dGxpbmVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaW5saW5lLWVkaXRpbmctZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgdHlwZT1cInRleHRcIiBbKG5nTW9kZWwpXT1cInJvd0RhdGFUZW1wWydlJytpXVtjb2x1bW4uZmllbGRdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cImNvbHVtbi50eXBlID09ICdkYXRlJ1wiIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImlubGluZS1lZGl0aW5nLWZpZWxkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IHR5cGU9XCJkYXRlXCIgWyhuZ01vZGVsKV09XCJyb3dEYXRhVGVtcFsnZScraV1bY29sdW1uLmZpZWxkXVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ01vZGVsT3B0aW9uc109XCJ7c3RhbmRhbG9uZTogdHJ1ZX1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJjb2x1bW4udHlwZSA9PSAnc2VsZWN0aW9uJ1wiIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImlubGluZS1lZGl0aW5nLWZpZWxkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1zZWxlY3QgW3ZhbHVlXT1cInJvd0RhdGFUZW1wWydlJytpXVtjb2x1bW4uZmllbGRdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJyb3dEYXRhVGVtcFsnZScraV1bY29sdW1uLmZpZWxkXVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgb3B0aW9uIG9mIGNvbHVtbi5vcHRpb25zXCIgW3ZhbHVlXT1cIm9wdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3tvcHRpb259fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtY2hlY2tib3ggKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiICpuZ0lmPVwiY29sdW1uLnR5cGUgPT0gJ2Jvb2xlYW4nXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIiBbKG5nTW9kZWwpXT1cInJvd1tjb2x1bW4uZmllbGRdXCI+PC9tYXQtY2hlY2tib3g+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWNlbGxFZGl0aW5nVGVtcGxhdGVSZWYgJiYgY2VsbEVkaXRpbmdbaSArJ18nK2NvbHVtbi5maWVsZF1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cImNvbHVtbi50eXBlID09ICdudW1iZXInXCIgYXBwZWFyYW5jZT1cIm91dGxpbmVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaW5saW5lLWVkaXRpbmctZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgdHlwZT1cIm51bWJlclwiIFsobmdNb2RlbCldPVwicm93RGF0YVRlbXBbJ2UnK2ldW2NvbHVtbi5maWVsZF1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwie3N0YW5kYWxvbmU6IHRydWV9XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiY29sdW1uLnR5cGUgPT0gJ3N0cmluZydcIiBhcHBlYXJhbmNlPVwib3V0bGluZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJpbmxpbmUtZWRpdGluZy1maWVsZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCB0eXBlPVwidGV4dFwiIFsobmdNb2RlbCldPVwicm93RGF0YVRlbXBbJ2UnK2ldW2NvbHVtbi5maWVsZF1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdNb2RlbE9wdGlvbnNdPVwie3N0YW5kYWxvbmU6IHRydWV9XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiY29sdW1uLnR5cGUgPT0gJ2RhdGUnXCIgYXBwZWFyYW5jZT1cIm91dGxpbmVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaW5saW5lLWVkaXRpbmctZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgbWF0SW5wdXQgdHlwZT1cImRhdGVcIiBbKG5nTW9kZWwpXT1cInJvd0RhdGFUZW1wWydlJytpXVtjb2x1bW4uZmllbGRdXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nTW9kZWxPcHRpb25zXT1cIntzdGFuZGFsb25lOiB0cnVlfVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cImNvbHVtbi50eXBlID09ICdzZWxlY3Rpb24nXCIgYXBwZWFyYW5jZT1cIm91dGxpbmVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiaW5saW5lLWVkaXRpbmctZmllbGRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBbdmFsdWVdPVwicm93RGF0YVRlbXBbJ2UnK2ldW2NvbHVtbi5maWVsZF1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInJvd0RhdGFUZW1wWydlJytpXVtjb2x1bW4uZmllbGRdXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCBvcHRpb24gb2YgY29sdW1uLm9wdGlvbnNcIiBbdmFsdWVdPVwib3B0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e29wdGlvbn19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1jaGVja2JveCAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCIgKm5nSWY9XCJjb2x1bW4udHlwZSA9PSAnYm9vbGVhbidcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiIFsobmdNb2RlbCldPVwicm93W2NvbHVtbi5maWVsZF1cIj48L21hdC1jaGVja2JveD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInNob3dGb290ZXJSb3dcIj5cclxuICAgICAgICAgICAgICAgICAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPiB7e2NvbHVtbi5mb290ZXJUZXh0fX0gPC90ZD5cclxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJlZGl0XCIgc3RpY2t5RW5kPVwiZmFsc2VcIj5cclxuICAgICAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgY2RrRHJhZ0xvY2tBeGlzPVwieFwiIGNka0RyYWcgW2Nka0RyYWdEaXNhYmxlZF09XCJ0cnVlXCIgKm1hdEhlYWRlckNlbGxEZWZcclxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImFjdGlvbi1jb2x1bW4tY2VsbHNcIj4gRWRpdCA8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvdzsgbGV0IGkgPSBkYXRhSW5kZXhcIiBjbGFzcz1cImlubGluZS1lZGl0LWNvbHVtbi1jZWxsXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiZWRpdC1jb2x1bW4taWNvbnNcIiAqbmdJZj1cIiFyb3cuZWRpdGFibGUgJiYgIXJvdy5lZGl0bW9kYWxcIiBhcmlhLWhpZGRlbj1cImZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImVuYWJsZUlubGluZUVkaXRpbmcocm93LGkpXCIgZm9udEljb249XCJlZGl0X25vdGVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbmxpbmUtZWRpdGluZy1jb250cm9sc1wiICpuZ0lmPVwicm93LmVkaXRhYmxlICYmICFyb3cuZWRpdG1vZGFsXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxtYXQtaWNvbiBjbGFzcz1cImVkaXQtY29sdW1uLWljb25zXCIgYXJpYS1oaWRkZW49XCJmYWxzZVwiIChjbGljayk9XCJzYXZlSW5saW5lRWRpdGluZyhyb3csaSlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9udEljb249XCJkb25lXCI+PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG1hdC1pY29uIGNsYXNzPVwiZWRpdC1jb2x1bW4taWNvbnNcIiBhcmlhLWhpZGRlbj1cImZhbHNlXCIgKGNsaWNrKT1cImNhbmNlbElubGluZUVkaXRpbmcocm93LGkpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvbnRJY29uPVwiY2xvc2VcIj48L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZCBtYXQtZm9vdGVyLWNlbGwgKm1hdEZvb3RlckNlbGxEZWY+IGVkaXQgPC90ZD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwicG9wdXBcIiBzdGlja3lFbmQ9XCJmYWxzZVwiPlxyXG4gICAgICAgICAgICAgICAgPHRoIG1hdC1oZWFkZXItY2VsbCBjZGtEcmFnTG9ja0F4aXM9XCJ4XCIgY2RrRHJhZyBbY2RrRHJhZ0Rpc2FibGVkXT1cInRydWVcIiAqbWF0SGVhZGVyQ2VsbERlZlxyXG4gICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYWN0aW9uLWNvbHVtbi1jZWxsc1wiPiBQb3B1cFxyXG4gICAgICAgICAgICAgICAgPC90aD5cclxuICAgICAgICAgICAgICAgIDx0ZCBtYXQtY2VsbCAqbWF0Q2VsbERlZj1cImxldCByb3c7IGxldCBpID0gaW5kZXhcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gYXJpYS1oaWRkZW49XCJmYWxzZVwiIChjbGljayk9XCJvcGVuRWRpdGluZ0RpYWxvZyhyb3cpXCIgZm9udEljb249XCJlZGl0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8dGQgbWF0LWZvb3Rlci1jZWxsICptYXRGb290ZXJDZWxsRGVmPjwvdGQ+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJkZWxldGVcIj5cclxuICAgICAgICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgY2RrRHJhZ0xvY2tBeGlzPVwieFwiIGNka0RyYWcgW2Nka0RyYWdEaXNhYmxlZF09XCJ0cnVlXCIgKm1hdEhlYWRlckNlbGxEZWZcclxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImFjdGlvbi1jb2x1bW4tY2VsbHNcIj4gRGVsZXRlXHJcbiAgICAgICAgICAgICAgICA8L3RoPlxyXG4gICAgICAgICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IHJvdztsZXQgaT1kYXRhSW5kZXhcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bWF0LWljb24gKGNsaWNrKT1cImRlbGV0ZVJvdyhyb3csaSlcIiBhcmlhLWhpZGRlbj1cImZhbHNlXCIgYXJpYS1sYWJlbD1cIkV4YW1wbGUgaG9tZSBpY29uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9udEljb249XCJkZWxldGVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgIDx0ZCBtYXQtZm9vdGVyLWNlbGwgKm1hdEZvb3RlckNlbGxEZWY+PC90ZD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDwhLS0gRXhwYW5kZWQgQ29udGVudCBDb2x1bW4gLSBUaGUgZGV0YWlsIHJvdyBpcyBtYWRlIHVwIG9mIHRoaXMgb25lIGNvbHVtbiB0aGF0IHNwYW5zIGFjcm9zcyBhbGwgY29sdW1ucyAtLT5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImV4cGFuZFJvd3NcIiBtYXRDb2x1bW5EZWY9XCJleHBhbmRlZERldGFpbFwiPlxyXG4gICAgICAgICAgICAgICAgPHRkIG1hdC1jZWxsICptYXRDZWxsRGVmPVwibGV0IGVsZW1lbnQ7bGV0IGk9ZGF0YUluZGV4IFwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2F0dHIuY29sc3Bhbl09XCJjb2x1bW5zVG9EaXNwbGF5V2l0aEV4cGFuZC5sZW5ndGhcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZXhhbXBsZS1lbGVtZW50LWRldGFpbFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtAZGV0YWlsRXhwYW5kXT1cImVsZW1lbnQgPT0gZXhwYW5kZWRFbGVtZW50ID8gJ2V4cGFuZGVkJyA6ICdjb2xsYXBzZWQnXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJleHBhbnNpb25UZW1wbGF0ZVJlZlwiIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImV4cGFuc2lvblRlbXBsYXRlUmVmXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7JGV4cGxpY2l0OmVsZW1lbnQscm93OmVsZW1lbnQsaW5kZXg6aX1cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgaWRzIG9mIGhlYWRlcnNGaWx0ZXJzSWRzOyBsZXQgaT1pbmRleFwiIFttYXRDb2x1bW5EZWZdPVwiaWRzXCI+XHJcbiAgICAgICAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXJzLWNvbnRhaW5lclwiIFtjbGFzcy5hbmltYXRlXT1cInRvZ2dsZUZpbHRlcnNcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGFwcC1maWx0ZXItY29sdW1ucy1jb21wb25lbnQgW29ial09XCJjb2x1bW5zQXJyYXlbcmV0dXJuSW5kZXgoaWRzKV1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZpbHRlck91dHB1dCk9XCJhcHBseUNvbHVtbkZpbHRlcigkZXZlbnQsY29sdW1uc0FycmF5W3JldHVybkluZGV4KGlkcyldKVwiPjwvYXBwLWZpbHRlci1jb2x1bW5zLWNvbXBvbmVudD5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvdGg+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cIiBnZXREaXNwbGF5ZWRDb2x1bW5zKCk7IHN0aWNreTogc3RpY2t5SGVhZGVyXCI+PC90cj5cclxuICAgICAgICAgICAgPHRyIG1hdC1yb3cgKm1hdFJvd0RlZj1cImxldCByb3c7IGNvbHVtbnM6Z2V0RGlzcGxheWVkQ29sdW1ucygpOyBsZXQgaT1kYXRhSW5kZXg7XCIgY2xhc3M9XCJkYXRhLXJvd1wiXHJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJ7J2RhdGEtcm93JzpleHBhbmRSb3dzLCdzdHJpcGVkUm93cyc6KHN0cmlwZWRSb3dzICYmICBpICUgMiA9PSAxKSwnaG92ZXJDbGFzcyc6cm93SG92ZXIsICdoaWRkZW4nOmhpZGRlbkN0cmwuaXNTZWxlY3RlZChyb3cpICYmIGhpZGVSb3dzLCdleGFtcGxlLWV4cGFuZGVkLXJvdyc6ZXhwYW5kZWRFbGVtZW50ID09PSByb3d9XCJcclxuICAgICAgICAgICAgICAgIChjbGljayk9XCJleHBhbmRSb3cocm93LCByb3cgIT09IGV4cGFuZGVkRWxlbWVudCxpKVwiPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICA8dHIgc3R5bGU9XCJoZWlnaHQ6IDBweDtcIiBtYXQtaGVhZGVyLXJvdyBjbGFzcz1cIm5vLWRlZmF1bHQtaGVpZ2h0XCIgKm1hdEhlYWRlclJvd0RlZj1cImhlYWRlcnNGaWx0ZXJzSWRzXCI+XHJcbiAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJleHBhbmRSb3dzXCI+XHJcbiAgICAgICAgICAgICAgICA8dHIgc3R5bGU9XCJoZWlnaHQ6IDBweDtcIiBtYXQtcm93ICptYXRSb3dEZWY9XCJsZXQgcm93OyBjb2x1bW5zOiBbJ2V4cGFuZGVkRGV0YWlsJ11cIlxyXG4gICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsnZXhhbXBsZS1kZXRhaWwtcm93JzogKGV4cGFuZFJvd3MgJiYgcm93ID09PSBleHBhbmRlZEVsZW1lbnQpLCdleHBhbmQtcm93Jzpyb3cgIT09IGV4cGFuZGVkRWxlbWVudH1cIj5cclxuICAgICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwic2hvd0Zvb3RlclJvd1wiPlxyXG4gICAgICAgICAgICAgICAgPHRyIG1hdC1mb290ZXItcm93ICptYXRGb290ZXJSb3dEZWY9XCJnZXREaXNwbGF5ZWRDb2x1bW5zKCk7IHN0aWNreTogc3RpY2t5Rm9vdGVyXCI+PC90cj5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgPC90YWJsZT5cclxuICAgIDwvc2VjdGlvbj5cclxuICAgIDxtYXQtcGFnaW5hdG9yICpuZ0lmPVwic2hvd1BhZ2luYXRvclwiIFtwYWdlU2l6ZU9wdGlvbnNdPVwicGFnZVNpemVPcHRpb25zXCJcclxuICAgICAgICBbc2hvd0ZpcnN0TGFzdEJ1dHRvbnNdPVwic2hvd0ZpcnN0TGFzdEJ1dHRvbnNcIj5cclxuICAgIDwvbWF0LXBhZ2luYXRvcj5cclxuPC9tYXQtY2FyZD4iXX0=
|