ng-firebase-table-kxp 1.2.0 → 1.2.2

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.
Files changed (48) hide show
  1. package/{fesm2020 → fesm2022}/ng-firebase-table-kxp.mjs +2762 -2744
  2. package/fesm2022/ng-firebase-table-kxp.mjs.map +1 -0
  3. package/index.d.ts +665 -5
  4. package/package.json +3 -11
  5. package/esm2020/lib/components/table/table.component.mjs +0 -710
  6. package/esm2020/lib/components/table-tabs/table-tabs.component.mjs +0 -73
  7. package/esm2020/lib/components/table-tooltip/table-tooltip.component.mjs +0 -34
  8. package/esm2020/lib/ng-firebase-table-kxp.component.mjs +0 -11
  9. package/esm2020/lib/ng-firebase-table-kxp.module.mjs +0 -98
  10. package/esm2020/lib/ng-firebase-table-kxp.service.mjs +0 -14
  11. package/esm2020/lib/services/filter.service.mjs +0 -416
  12. package/esm2020/lib/services/pagination.service.mjs +0 -115
  13. package/esm2020/lib/services/table.service.mjs +0 -1140
  14. package/esm2020/lib/services/tooltip.service.mjs +0 -141
  15. package/esm2020/lib/types/Table.mjs +0 -9
  16. package/esm2020/lib/utils/table.utils.mjs +0 -75
  17. package/esm2020/ng-firebase-table-kxp.mjs +0 -5
  18. package/esm2020/public-api.mjs +0 -22
  19. package/fesm2015/ng-firebase-table-kxp.mjs +0 -2869
  20. package/fesm2015/ng-firebase-table-kxp.mjs.map +0 -1
  21. package/fesm2020/ng-firebase-table-kxp.mjs.map +0 -1
  22. package/lib/components/table/table.component.d.ts +0 -132
  23. package/lib/components/table/table.component.d.ts.map +0 -1
  24. package/lib/components/table-tabs/table-tabs.component.d.ts +0 -34
  25. package/lib/components/table-tabs/table-tabs.component.d.ts.map +0 -1
  26. package/lib/components/table-tooltip/table-tooltip.component.d.ts +0 -18
  27. package/lib/components/table-tooltip/table-tooltip.component.d.ts.map +0 -1
  28. package/lib/ng-firebase-table-kxp.component.d.ts +0 -5
  29. package/lib/ng-firebase-table-kxp.component.d.ts.map +0 -1
  30. package/lib/ng-firebase-table-kxp.module.d.ts +0 -23
  31. package/lib/ng-firebase-table-kxp.module.d.ts.map +0 -1
  32. package/lib/ng-firebase-table-kxp.service.d.ts +0 -6
  33. package/lib/ng-firebase-table-kxp.service.d.ts.map +0 -1
  34. package/lib/services/filter.service.d.ts +0 -88
  35. package/lib/services/filter.service.d.ts.map +0 -1
  36. package/lib/services/pagination.service.d.ts +0 -34
  37. package/lib/services/pagination.service.d.ts.map +0 -1
  38. package/lib/services/table.service.d.ts +0 -80
  39. package/lib/services/table.service.d.ts.map +0 -1
  40. package/lib/services/tooltip.service.d.ts +0 -73
  41. package/lib/services/tooltip.service.d.ts.map +0 -1
  42. package/lib/types/Table.d.ts +0 -162
  43. package/lib/types/Table.d.ts.map +0 -1
  44. package/lib/utils/table.utils.d.ts +0 -25
  45. package/lib/utils/table.utils.d.ts.map +0 -1
  46. package/ng-firebase-table-kxp.d.ts.map +0 -1
  47. package/public-api.d.ts +0 -12
  48. package/public-api.d.ts.map +0 -1
@@ -1,710 +0,0 @@
1
- import { TABLE_DEFAULTS, } from '../../types/Table';
2
- import { Component, Input, ViewChild, ChangeDetectionStrategy, } from '@angular/core';
3
- import { MatPaginator } from '@angular/material/paginator';
4
- import { MatSort } from '@angular/material/sort';
5
- import { MatTableDataSource } from '@angular/material/table';
6
- import { getDisplayValue, getNestedValue, isString, trackByProperty, getImageKey, } from '../../utils/table.utils';
7
- import { debounceTime, firstValueFrom, Subject, takeUntil, BehaviorSubject, } from 'rxjs';
8
- import { FormControl, FormArray } from '@angular/forms';
9
- import * as i0 from "@angular/core";
10
- import * as i1 from "@angular/router";
11
- import * as i2 from "../../services/table.service";
12
- import * as i3 from "../../services/filter.service";
13
- import * as i4 from "../../services/tooltip.service";
14
- import * as i5 from "../../services/pagination.service";
15
- import * as i6 from "@angular/fire/compat/firestore";
16
- import * as i7 from "@angular/common";
17
- import * as i8 from "@angular/forms";
18
- import * as i9 from "@angular/material/table";
19
- import * as i10 from "@angular/material/paginator";
20
- import * as i11 from "@angular/material/sort";
21
- import * as i12 from "@angular/material/form-field";
22
- import * as i13 from "@angular/material/input";
23
- import * as i14 from "@angular/material/select";
24
- import * as i15 from "@angular/material/core";
25
- import * as i16 from "@angular/material/tooltip";
26
- import * as i17 from "@angular/material/progress-spinner";
27
- import * as i18 from "@angular/material/icon";
28
- import * as i19 from "../table-tabs/table-tabs.component";
29
- import * as i20 from "../table-tooltip/table-tooltip.component";
30
- export class TableComponent {
31
- // CONSTRUCTOR
32
- constructor(router, tableService, filterService, tooltipService, paginationService, firestore, el, cdr) {
33
- this.router = router;
34
- this.tableService = tableService;
35
- this.filterService = filterService;
36
- this.tooltipService = tooltipService;
37
- this.paginationService = paginationService;
38
- this.firestore = firestore;
39
- this.el = el;
40
- this.cdr = cdr;
41
- this.arrange = null;
42
- this.currentPageNumber = 1;
43
- this.currentClientPageIndex = 0;
44
- this.isLoading$ = new BehaviorSubject(false);
45
- this.items = [];
46
- this.filteredItems = [];
47
- this.lastDoc = null;
48
- this.firstDoc = null;
49
- this.sortBy = {
50
- field: TABLE_DEFAULTS.SORT_FIELD,
51
- order: TABLE_DEFAULTS.SORT_ORDER,
52
- };
53
- this.columnProperties = [];
54
- this.selectSort = new FormControl('');
55
- this.currentArrange = '';
56
- this.hasNextPage = false;
57
- this.dropdownItems = [];
58
- this.sortableDropdownItems = [];
59
- this.pageSize = TABLE_DEFAULTS.PAGE_SIZE;
60
- this.totalItems = 0;
61
- this.filterValue = null;
62
- this.hasFilterableColumn = false;
63
- this.hasSortableColumn = false;
64
- this.filterSubject = new Subject();
65
- this.debounceTimeMs = TABLE_DEFAULTS.DEBOUNCE_TIME_MS;
66
- this.selectedTab = 0;
67
- // Controle de loading de imagens
68
- this.imageLoadingState = new Map();
69
- this.destroy$ = new Subject();
70
- this.filtersForm = new FormArray([this.filterService.createFilterGroup()]);
71
- this.tooltipState = this.tooltipService.createInitialState();
72
- }
73
- // FILTER METHODS (delegados ao FilterService)
74
- createFilterGroup() {
75
- return this.filterService.createFilterGroup();
76
- }
77
- addFilter(filterData) {
78
- this.filterService.addFilter(this.filtersForm, this.data.pagination === true, filterData);
79
- }
80
- hasActiveDateFilter() {
81
- return this.filterService.hasActiveDateFilter(this.filtersForm);
82
- }
83
- getAvailableFilterOptions() {
84
- return this.filterService.getAvailableFilterOptions(this.dropdownItems, this.data.pagination === true, this.filtersForm);
85
- }
86
- onSelectFilterChange() {
87
- const lastIndex = this.filtersForm.length - 1;
88
- const lastFilter = this.filtersForm.at(lastIndex);
89
- const selectedFilter = lastFilter.get('selectFilter')?.value;
90
- if (selectedFilter) {
91
- if (selectedFilter.arrange === 'filterByDate' &&
92
- this.data.pagination === true) {
93
- return;
94
- }
95
- this.addFilter();
96
- }
97
- }
98
- removeFilter(index) {
99
- this.filterService.removeFilter(this.filtersForm, index);
100
- }
101
- removeAllFilters() {
102
- this.filterService.removeAllFilters(this.filtersForm);
103
- this.resetFilter();
104
- }
105
- onDateInput(event, controlName, filterIndex) {
106
- const filterGroup = this.filtersForm.at(filterIndex);
107
- this.filterService.applyDateMask(event, controlName, filterGroup);
108
- }
109
- onDateFilterChange() {
110
- if (this.data.pagination === false) {
111
- this.arrange = this.filterService.buildArrangeFromFilters(this.filtersForm, this.sortBy);
112
- this.applyFiltersToDataSource();
113
- this.cdr.markForCheck();
114
- }
115
- }
116
- applyFiltersToDataSource() {
117
- if (!this.dataSource)
118
- return;
119
- let filteredItems = this.filterService.applyClientSideFilters([...this.items], this.filtersForm, this.sortBy);
120
- this.dataSource.data = filteredItems;
121
- this.filteredItems = filteredItems;
122
- this.totalItems = filteredItems.length;
123
- this.cdr.markForCheck();
124
- }
125
- applyClientSideFilters(items) {
126
- return this.filterService.applyClientSideFilters(items, this.filtersForm, this.sortBy);
127
- }
128
- buildArrangeFromFilters() {
129
- return this.filterService.buildArrangeFromFilters(this.filtersForm, this.sortBy);
130
- }
131
- // TOOLTIP METHODS (delegados ao TooltipService)
132
- getTooltipStyles() {
133
- return this.tooltipService.getTooltipStyles(this.tooltipState);
134
- }
135
- onCellMouseEnter(event, row, col) {
136
- this.tooltipService.handleMouseEnter(event, row, col, (c, r, w) => this.getDisplayValue(c, r, w), (state) => {
137
- this.tooltipState = { ...this.tooltipState, ...state };
138
- this.cdr.markForCheck();
139
- });
140
- }
141
- onCellMouseLeave() {
142
- this.tooltipService.handleMouseLeave((state) => {
143
- this.tooltipState = state;
144
- this.cdr.markForCheck();
145
- });
146
- }
147
- onCellMouseMove(event) {
148
- this.tooltipService.handleMouseMove(event, this.tooltipState.showTooltip, (position) => {
149
- this.tooltipState = { ...this.tooltipState, tooltipPosition: position };
150
- this.cdr.markForCheck();
151
- });
152
- }
153
- // TAB METHODS
154
- onTabSelected(event) {
155
- if (!this.data.tabs?.method)
156
- return;
157
- this.selectedTab = event.index;
158
- this.data.tabs.method(event.tab, event.index);
159
- this.cdr.markForCheck();
160
- }
161
- // UTILITY METHODS (delegados aos utils)
162
- getDisplayValue(col, row, withinLimit = false) {
163
- return getDisplayValue(col, row, withinLimit);
164
- }
165
- getNestedValue(obj, path) {
166
- return getNestedValue(obj, path);
167
- }
168
- isString(value) {
169
- return isString(value);
170
- }
171
- trackByProperty(_index, col) {
172
- return trackByProperty(_index, col);
173
- }
174
- // IMAGE LOADING METHODS
175
- getImageKey(row, col) {
176
- return getImageKey(row, col);
177
- }
178
- isImageLoading(row, col) {
179
- const key = this.getImageKey(row, col);
180
- return !this.imageLoadingState.has(key);
181
- }
182
- onImageLoad(row, col) {
183
- const key = this.getImageKey(row, col);
184
- this.imageLoadingState.set(key, true);
185
- this.cdr.markForCheck();
186
- }
187
- onImageError(event, row, col, defaultImage) {
188
- const key = this.getImageKey(row, col);
189
- this.imageLoadingState.set(key, true);
190
- const target = event.target;
191
- if (target) {
192
- if (defaultImage) {
193
- target.src = defaultImage;
194
- target.onerror = null;
195
- }
196
- else {
197
- target.style.display = 'none';
198
- }
199
- }
200
- this.cdr.markForCheck();
201
- }
202
- // LIFECYCLE METHODS
203
- ngOnChanges(changes) {
204
- if (changes['data']) {
205
- setTimeout(() => this.applyCustomColors(), 0);
206
- }
207
- }
208
- ngAfterViewInit() {
209
- this.applyCustomColors();
210
- }
211
- ngOnDestroy() {
212
- this.tooltipService.destroy();
213
- this.destroy$.next();
214
- this.destroy$.complete();
215
- }
216
- applyCustomColors() {
217
- const hostElement = this.el?.nativeElement;
218
- if (!hostElement || !this.data)
219
- return;
220
- if (this.data.color?.bg) {
221
- hostElement.style.setProperty('--table-color', this.data.color.bg);
222
- hostElement.style.setProperty('--table-header-bg', this.data.color.bg);
223
- }
224
- if (this.data.color?.text) {
225
- hostElement.style.setProperty('--table-text-color', this.data.color.text);
226
- hostElement.style.setProperty('--table-header-text', this.data.color.text);
227
- }
228
- setTimeout(() => {
229
- const headerCells = hostElement.querySelectorAll('.mat-header-cell, .mat-mdc-header-cell, th.mat-header-cell, th.mat-mdc-header-cell');
230
- headerCells.forEach((cell) => {
231
- if (this.data.color?.bg) {
232
- cell.style.backgroundColor = this.data.color.bg;
233
- }
234
- if (this.data.color?.text) {
235
- cell.style.color = this.data.color.text;
236
- }
237
- });
238
- }, 100);
239
- }
240
- async ngOnInit() {
241
- if (!this.data.color) {
242
- this.data.color = {
243
- bg: TABLE_DEFAULTS.DEFAULT_BG_COLOR,
244
- text: TABLE_DEFAULTS.DEFAULT_TEXT_COLOR,
245
- };
246
- }
247
- if (this.data.showSimpleSearch === undefined) {
248
- this.data.showSimpleSearch = true;
249
- }
250
- this.columnProperties = this.data.displayedColumns.map((column) => column.property);
251
- this.cdr.markForCheck();
252
- if (this.data.actionButton && !this.data.actionButton.condition) {
253
- this.data.actionButton.condition = (_row) => true;
254
- }
255
- // Inicializar dropdownItems usando FilterService
256
- const filterConfig = this.filterService.initializeDropdownItems(this.data.displayedColumns);
257
- this.dropdownItems = filterConfig.dropdownItems;
258
- this.sortableDropdownItems = filterConfig.sortableDropdownItems;
259
- this.hasFilterableColumn = filterConfig.hasFilterableColumn;
260
- this.hasSortableColumn = filterConfig.hasSortableColumn;
261
- if (this.data.filterableOptions) {
262
- this.dropdownItems = this.filterService.addFilterableOptions(this.dropdownItems, this.data.filterableOptions);
263
- }
264
- // Sem paginação
265
- if (this.data.pagination === false) {
266
- await this.loadItems();
267
- this.cdr.markForCheck();
268
- }
269
- // Com paginação
270
- if (this.data.pagination === true) {
271
- if (this.data.sortBy) {
272
- this.sortBy = {
273
- field: this.data.sortBy.field,
274
- order: this.data.sortBy.order,
275
- };
276
- }
277
- this.filterSubject
278
- .pipe(debounceTime(this.debounceTimeMs), takeUntil(this.destroy$))
279
- .subscribe(() => {
280
- this.loadItemsPaginated('reload', true);
281
- });
282
- this.isLoading$.next(true);
283
- this.cdr.markForCheck();
284
- await this.loadItemsPaginated('reload', true);
285
- this.sort.active = 'createdAt';
286
- this.sort.direction = 'desc';
287
- this.dataSource.paginator = this.paginator;
288
- this.dataSource.sort = this.sort;
289
- this.totalItems = 0;
290
- if (this.data.totalRef) {
291
- for (const totalRef of this.data.totalRef) {
292
- const totalRefDoc = await totalRef.ref.get();
293
- const docData = totalRefDoc.data();
294
- if (docData && docData[totalRef.field]) {
295
- const fieldValue = docData[totalRef.field];
296
- this.totalItems = (this.totalItems +
297
- (typeof fieldValue === 'number' ? fieldValue : 0));
298
- }
299
- }
300
- }
301
- this.isLoading$.next(false);
302
- this.cdr.markForCheck();
303
- }
304
- }
305
- // DATA LOADING METHODS
306
- async loadItems() {
307
- this.imageLoadingState.clear();
308
- this.items = (await this.tableService.getItems(this.data.collectionRef));
309
- if (this.data.conditions) {
310
- this.filterItems();
311
- }
312
- await this.loadRelations();
313
- await this.loadQueryLengths();
314
- this.totalItems = this.items.length;
315
- this.arrange = {
316
- filters: [],
317
- sortBy: this.data.sortBy || {
318
- field: TABLE_DEFAULTS.SORT_FIELD,
319
- order: TABLE_DEFAULTS.SORT_ORDER,
320
- },
321
- };
322
- this.sortBy = this.data.sortBy || {
323
- field: TABLE_DEFAULTS.SORT_FIELD,
324
- order: TABLE_DEFAULTS.SORT_ORDER,
325
- };
326
- let itemsToDisplay = [...this.items];
327
- itemsToDisplay = this.applyClientSideFilters(itemsToDisplay);
328
- this.filteredItems = itemsToDisplay;
329
- this.dataSource = new MatTableDataSource(itemsToDisplay);
330
- this.dataSource.paginator = this.paginator;
331
- this.dataSource.sort = this.sort;
332
- if (this.data.sortBy) {
333
- this.dataSource.sort.active = this.data.sortBy.field;
334
- this.dataSource.sort.direction = this.data.sortBy.order;
335
- this.dataSource.sort.sortChange.emit();
336
- }
337
- this.dataSource.filterPredicate = (data, filter) => {
338
- const item = data;
339
- return this.data.displayedColumns.some((col) => {
340
- if (col.filterPredicates) {
341
- return col.filterPredicates.some((predicate) => {
342
- const propertyValue = item[col.property];
343
- if (!propertyValue || typeof propertyValue !== 'object') {
344
- return false;
345
- }
346
- const propertyRecord = propertyValue;
347
- const predicateValue = propertyRecord[predicate];
348
- if (predicateValue === null || predicateValue === undefined) {
349
- return false;
350
- }
351
- return String(predicateValue)
352
- .trim()
353
- .toLocaleLowerCase()
354
- .includes(filter);
355
- });
356
- }
357
- if (col.property && col.isFilterable) {
358
- const propertyValue = item[col.property];
359
- if (propertyValue === null || propertyValue === undefined) {
360
- return false;
361
- }
362
- return String(propertyValue)
363
- .trim()
364
- .toLocaleLowerCase()
365
- .includes(filter);
366
- }
367
- return false;
368
- });
369
- };
370
- this.filterPredicate = this.dataSource.filterPredicate;
371
- this.cdr.markForCheck();
372
- }
373
- async loadItemsPaginated(navigation = 'reload', reset = false) {
374
- this.imageLoadingState.clear();
375
- if (reset && ['forward', 'reload'].includes(navigation)) {
376
- this.lastDoc = null;
377
- this.currentClientPageIndex = 0;
378
- }
379
- if (reset && ['backward', 'reload'].includes(navigation)) {
380
- this.firstDoc = null;
381
- this.currentClientPageIndex = 0;
382
- }
383
- const activeFilters = this.filterService.extractActiveFilters(this.filtersForm);
384
- this.arrange = {
385
- filters: activeFilters,
386
- sortBy: this.sortBy,
387
- };
388
- const paginated = {
389
- batchSize: this.pageSize,
390
- collection: this.data.collection,
391
- doc: { lastDoc: this.lastDoc, firstDoc: this.firstDoc },
392
- navigation,
393
- arrange: this.arrange,
394
- conditions: this.data.conditions,
395
- size: this.totalItems,
396
- filterFn: this.data.filterFn,
397
- clientPageIndex: this.currentClientPageIndex,
398
- };
399
- const result = await this.tableService.getPaginated(paginated);
400
- this.items = result.items;
401
- await this.loadRelations();
402
- await this.loadQueryLengths();
403
- this.lastDoc = result.lastDoc;
404
- this.firstDoc = result.firstDoc;
405
- if (result.currentClientPageIndex !== undefined) {
406
- this.currentClientPageIndex = result.currentClientPageIndex;
407
- }
408
- let sum = 0;
409
- if (this.data.totalRef) {
410
- for (const totalRef of this.data.totalRef) {
411
- const totalRefDoc = await totalRef.ref.get();
412
- const docData = totalRefDoc.data();
413
- if (docData || result.filterLength) {
414
- const fieldValue = docData ? docData[totalRef.field] : undefined;
415
- const numericValue = typeof fieldValue === 'number' ? fieldValue : 0;
416
- sum = result.filterLength ?? (sum + numericValue);
417
- }
418
- }
419
- this.totalItems = sum;
420
- }
421
- this.hasNextPage = result.hasNextPage;
422
- this.dataSource = new MatTableDataSource(this.items);
423
- this.filterPredicate = this.dataSource.filterPredicate;
424
- this.cdr.markForCheck();
425
- }
426
- // PAGINATION METHODS
427
- async onPageChange(event) {
428
- if (this.data.pagination !== true || !event)
429
- return;
430
- this.isLoading$.next(true);
431
- const currentState = {
432
- currentPageNumber: this.currentPageNumber,
433
- currentClientPageIndex: this.currentClientPageIndex,
434
- pageSize: this.pageSize,
435
- totalItems: this.totalItems,
436
- hasNextPage: this.hasNextPage,
437
- };
438
- const navigation = this.paginationService.calculateNavigation(event, currentState);
439
- if (!navigation.shouldNavigate) {
440
- this.isLoading$.next(false);
441
- this.pageEvent = event;
442
- return;
443
- }
444
- // Atualizar estado local
445
- this.currentClientPageIndex = navigation.newClientPageIndex;
446
- this.currentPageNumber = navigation.newPageNumber;
447
- // Atualizar pageSize se mudou
448
- if (event.pageSize !== this.pageSize) {
449
- this.pageSize = event.pageSize;
450
- }
451
- // Ajustar pageSize temporariamente para última página se necessário
452
- const lastPageIndex = this.paginationService.calculateLastPageIndex(this.totalItems, event.pageSize);
453
- let originalPageSize = null;
454
- if (event.pageIndex === lastPageIndex &&
455
- navigation.direction === 'backward' &&
456
- navigation.resetDocs) {
457
- const itemsExpectedInLastPage = this.paginationService.calculateLastPageItemCount(this.totalItems, event.pageSize);
458
- if (itemsExpectedInLastPage > 0 &&
459
- itemsExpectedInLastPage < event.pageSize) {
460
- originalPageSize = this.pageSize;
461
- this.pageSize = itemsExpectedInLastPage;
462
- }
463
- }
464
- try {
465
- await this.loadItemsPaginated(navigation.direction, navigation.resetDocs);
466
- }
467
- catch (error) {
468
- console.error('Erro ao carregar itens paginados:', error);
469
- }
470
- finally {
471
- if (originalPageSize !== null) {
472
- this.pageSize = originalPageSize;
473
- }
474
- }
475
- this.pageEvent = event;
476
- this.isLoading$.next(false);
477
- this.cdr.markForCheck();
478
- }
479
- // FILTER/SEARCH METHODS
480
- applyFilter(value) {
481
- if (this.data.pagination === false) {
482
- this.dataSource.filter = String(value).trim().toLowerCase();
483
- }
484
- if (this.data.pagination === true) {
485
- this.filterValue = value;
486
- this.filterSubject.next(this.filterValue);
487
- }
488
- }
489
- async search(event) {
490
- if (event) {
491
- event.preventDefault();
492
- event.stopPropagation();
493
- }
494
- if (this.selectSort.value) {
495
- if (this.selectSort.value.arrange === 'ascending') {
496
- this.sortBy = {
497
- field: this.selectSort.value.property,
498
- order: 'asc',
499
- };
500
- }
501
- if (this.selectSort.value.arrange === 'descending') {
502
- this.sortBy = {
503
- field: this.selectSort.value.property,
504
- order: 'desc',
505
- };
506
- }
507
- }
508
- if (this.data.pagination === false) {
509
- this.arrange = this.buildArrangeFromFilters();
510
- this.applyFiltersToDataSource();
511
- this.currentArrange =
512
- this.filtersForm.length > 0
513
- ? (this.filtersForm.at(0).get('selectFilter')?.value?.arrange ?? '')
514
- : '';
515
- this.cdr.markForCheck();
516
- }
517
- else {
518
- await this.loadItemsPaginated('reload', true);
519
- this.currentArrange =
520
- this.filtersForm.length > 0
521
- ? (this.filtersForm.at(0).get('selectFilter')?.value?.arrange ?? '')
522
- : '';
523
- this.paginator.firstPage();
524
- this.cdr.markForCheck();
525
- }
526
- }
527
- async resetFilter() {
528
- this.dataSource.filter = '';
529
- if (this.filterPredicate) {
530
- this.dataSource.filterPredicate = this.filterPredicate;
531
- }
532
- this.filtersForm.clear();
533
- this.addFilter();
534
- this.selectSort.patchValue('');
535
- this.sortBy = {
536
- order: this.data.sortBy ? this.data.sortBy.order : 'desc',
537
- field: this.data.sortBy ? this.data.sortBy.field : 'createdAt',
538
- };
539
- if (this.data.pagination === false) {
540
- this.arrange = {
541
- filters: [],
542
- sortBy: this.sortBy,
543
- };
544
- this.dataSource.data = [...this.items];
545
- this.totalItems = this.items.length;
546
- this.currentArrange = '';
547
- this.cdr.markForCheck();
548
- }
549
- else {
550
- await this.loadItemsPaginated('reload', true);
551
- this.currentArrange = '';
552
- this.paginator.firstPage();
553
- this.cdr.markForCheck();
554
- }
555
- }
556
- // NAVIGATION METHODS
557
- goToDetails(row) {
558
- if (this.data.isNotClickable) {
559
- return;
560
- }
561
- const urlPath = this.data.url || this.data.name;
562
- const rowWithId = row;
563
- const url = this.router.serializeUrl(this.router.createUrlTree([`/${urlPath}`, rowWithId.id]));
564
- window.open(url, '_blank');
565
- }
566
- // RELATION METHODS
567
- async getRelation(params) {
568
- try {
569
- let snapshot;
570
- if (params.id !== '' &&
571
- params.id !== undefined &&
572
- params.collection !== undefined &&
573
- params.collection !== '') {
574
- snapshot = await firstValueFrom(this.firestore.collection(params.collection).doc(params.id).get());
575
- }
576
- if (snapshot && snapshot.exists) {
577
- const data = snapshot.data();
578
- const value = data?.[params.newProperty];
579
- return typeof value === 'string' ? value : '';
580
- }
581
- return '';
582
- }
583
- catch (e) {
584
- console.error(e);
585
- return '';
586
- }
587
- }
588
- async loadRelations() {
589
- const relationPromises = this.data.displayedColumns
590
- .filter((col) => col.relation)
591
- .flatMap((col) => this.items.map(async (item) => {
592
- if (col.relation) {
593
- const itemRecord = item;
594
- itemRecord[col.property] = await this.getRelation({
595
- id: String(itemRecord[col.relation.sourceProperty] ?? ''),
596
- collection: col.relation.targetedCollection,
597
- newProperty: col.relation.targetedProperty || col.property,
598
- });
599
- }
600
- }));
601
- await Promise.all(relationPromises);
602
- }
603
- async getQueryLength(params) {
604
- const itemRecord = params.item;
605
- const snapshot = await this.firestore
606
- .collection(params.relation.collection)
607
- .ref.where(params.relation.property, params.relation.operator, itemRecord[params.relation.value])
608
- .get();
609
- return snapshot.size;
610
- }
611
- async loadQueryLengths() {
612
- const lengthPromises = this.data.displayedColumns
613
- .filter((col) => col.queryLength)
614
- .flatMap((col) => this.items.map(async (item) => {
615
- if (col.queryLength) {
616
- const itemRecord = item;
617
- itemRecord[col.property] = await this.getQueryLength({
618
- item: item,
619
- relation: col.queryLength,
620
- });
621
- }
622
- }));
623
- await Promise.all(lengthPromises);
624
- }
625
- filterItems() {
626
- if (this.data.conditions) {
627
- this.data.conditions.forEach((cond) => {
628
- this.items = this.items.filter((item) => {
629
- const operatorFunction = this.tableService.operators[cond.operator];
630
- if (operatorFunction) {
631
- const itemRecord = item;
632
- return operatorFunction(itemRecord[cond.firestoreProperty], cond.dashProperty);
633
- }
634
- return false;
635
- });
636
- });
637
- }
638
- }
639
- // PUBLIC METHODS
640
- async reloadTable() {
641
- if (this.data.pagination) {
642
- await this.loadItemsPaginated('reload', true);
643
- this.paginator.firstPage();
644
- this.cdr.markForCheck();
645
- }
646
- else {
647
- await this.loadItems();
648
- }
649
- }
650
- updateDisplayedColumns() {
651
- if (this.dataSource) {
652
- this.dataSource = new MatTableDataSource([]);
653
- }
654
- this.columnProperties = this.data.displayedColumns.map((column) => column.property);
655
- const filterConfig = this.filterService.initializeDropdownItems(this.data.displayedColumns);
656
- this.dropdownItems = filterConfig.dropdownItems;
657
- this.sortableDropdownItems = filterConfig.sortableDropdownItems;
658
- if (this.data.filterableOptions) {
659
- this.dropdownItems = this.filterService.addFilterableOptions(this.dropdownItems, this.data.filterableOptions);
660
- }
661
- this.cdr.markForCheck();
662
- }
663
- shouldShowActionButton() {
664
- if (!this.data?.actionButton) {
665
- return false;
666
- }
667
- if (!this.data.actionButton.condition) {
668
- return true;
669
- }
670
- try {
671
- return this.data.actionButton.condition(null) ?? true;
672
- }
673
- catch {
674
- return true;
675
- }
676
- }
677
- handleDownload() {
678
- if (!this.downloadTable)
679
- return;
680
- if (this.data.pagination === false) {
681
- if (this.dataSource && this.dataSource.filteredData) {
682
- this.filteredItems = [...this.dataSource.filteredData];
683
- }
684
- const arrange = this.buildArrangeFromFilters();
685
- this.downloadTable(arrange, this.data.conditions || []);
686
- }
687
- else {
688
- if (this.arrange) {
689
- this.downloadTable(this.arrange, this.data.conditions || []);
690
- }
691
- }
692
- }
693
- }
694
- TableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableComponent, deps: [{ token: i1.Router }, { token: i2.TableService }, { token: i3.FilterService }, { token: i4.TooltipService }, { token: i5.PaginationService }, { token: i6.AngularFirestore }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
695
- TableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: TableComponent, selector: "lib-table", inputs: { data: "data", downloadTable: "downloadTable" }, viewQueries: [{ propertyName: "paginator", first: true, predicate: MatPaginator, descendants: true }, { propertyName: "sort", first: true, predicate: MatSort, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div *ngIf=\"data\" class=\"card-body\">\r\n <div class=\"flex flex-col justify-between gap-6\">\r\n <!-- UNIFIED CONTROL PANEL: FILTERS, SORT & ACTIONS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === true &&\r\n (dropdownItems.length > 0 ||\r\n sortableDropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title and Custom Action -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- SORT FIELD (Integrated with filters) -->\r\n <div class=\"mb-4\" *ngIf=\"sortableDropdownItems.length > 0\">\r\n <div class=\"flex flex-wrap items-center gap-3 p-2\">\r\n <div class=\"min-w-[200px] flex-1\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>Ordenar por</span>\r\n </mat-label>\r\n <mat-select placeholder=\"Selecione...\" [formControl]=\"selectSort\">\r\n <mat-option\r\n *ngFor=\"let item of sortableDropdownItems\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- FILTERS CONTENT (WITH REFINEMENTS) -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option\r\n *ngFor=\"let item of getAvailableFilterOptions()\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search($event)\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n matInput\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'initialDate', i)\"\r\n formControlName=\"initialDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'finalDate', i)\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Action Buttons -->\r\n <div\r\n class=\"-mb-2 flex items-start justify-between gap-4 border-t border-gray-200 pt-4\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Right Side: Search, Reset, Export -->\r\n <div\r\n class=\"flex flex-wrap gap-3 self-start sm:self-auto\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true || this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"\r\n $any(arrange) && downloadTable !== undefined\r\n ? downloadTable($any(arrange), data.conditions || [])\r\n : null\r\n \"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- UNIFIED CONTROL PANEL (for non-paginated tables): SEARCH, SORT & FILTERS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === false &&\r\n (hasFilterableColumn === true ||\r\n dropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title and Custom Action -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- SIMPLE SEARCH -->\r\n <div\r\n class=\"mb-4\"\r\n *ngIf=\"hasFilterableColumn === true && data.showSimpleSearch !== false\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-blue-500\"></i>\r\n Buscar\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search($event)\"\r\n (keyup)=\"applyFilter(filterInput.value)\"\r\n placeholder=\"Digite para filtrar...\"\r\n #filterInput\r\n />\r\n <mat-icon matSuffix class=\"text-gray-500\">search</mat-icon>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- FILTERS PANEL -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <!-- FILTERS CONTENT -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option\r\n *ngFor=\"let item of getAvailableFilterOptions()\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search($event)\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n matInput\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'initialDate', i)\"\r\n (blur)=\"onDateFilterChange()\"\r\n formControlName=\"initialDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'finalDate', i)\"\r\n (blur)=\"onDateFilterChange()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Actions -->\r\n <div\r\n class=\"-mb-2 flex items-start justify-between gap-4 border-t border-gray-200 pt-4\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div\r\n class=\"flex flex-wrap gap-3 self-start sm:self-auto\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true ||\r\n this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"handleDownload()\"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"flex flex-col\">\r\n <!-- TABS COMPONENT -->\r\n <lib-table-tabs\r\n *ngIf=\"data.tabs && data.tabs.tabsData && data.tabs.tabsData.length > 0\"\r\n [tabsData]=\"data.tabs.tabsData\"\r\n [selectedTab]=\"selectedTab\"\r\n (tabSelected)=\"onTabSelected($event)\"\r\n ></lib-table-tabs>\r\n <div\r\n class=\"mat-elevation-z8 w-full overflow-x-auto rounded-xl table-container\"\r\n >\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n #sort=\"matSort\"\r\n matSortActive=\"createdAt\"\r\n matSortDirection=\"desc\"\r\n >\r\n <ng-container\r\n *ngFor=\"let col of data.displayedColumns; trackBy: trackByProperty\"\r\n matColumnDef=\"{{ col.property }}\"\r\n >\r\n <ng-container *matHeaderCellDef>\r\n <!-- IF THE COLUMN IS NOT SORTABLE, THEN DON'T SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"!col.isSortable || data.pagination === true\"\r\n mat-header-cell\r\n >\r\n {{ col.title }}\r\n </th>\r\n <!-- IF THE COLUMN IS SORTABLE, THEN SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"col.isSortable && data.pagination === false\"\r\n mat-header-cell\r\n mat-sort-header\r\n >\r\n {{ col.title }}\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let row\"\r\n (click)=\"col.method ? col.method(row) : null\"\r\n (mouseenter)=\"onCellMouseEnter($event, row, col)\"\r\n (mouseleave)=\"onCellMouseLeave()\"\r\n (mousemove)=\"onCellMouseMove($event)\"\r\n >\r\n <!-- CHECK IF THE COLUMN MUST BE DISPLAYED -->\r\n <span *ngIf=\"!col.image && !col.iconClass && !col.method\">\r\n <ng-container>\r\n <span\r\n *ngIf=\"\r\n col.charLimit &&\r\n row[col.property] &&\r\n row[col.property].length > col.charLimit;\r\n else withinLimit\r\n \"\r\n >\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </span>\r\n </span>\r\n </ng-container>\r\n <ng-template #withinLimit>\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n <!------------------- IMAGE ------------------>\r\n <!-- Imagem com loading -->\r\n <div\r\n *ngIf=\"\r\n col.image && col.image.path && !col.iconClass && !col.method\r\n \"\r\n class=\"relative inline-block\"\r\n >\r\n <mat-spinner\r\n *ngIf=\"isImageLoading(row, col)\"\r\n [diameter]=\"32\"\r\n class=\"absolute inset-0 m-auto\"\r\n ></mat-spinner>\r\n <img\r\n [src]=\"col.image.path + '/' + row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n [class.opacity-0]=\"isImageLoading(row, col)\"\r\n alt=\"\"\r\n (load)=\"onImageLoad(row, col)\"\r\n (error)=\"onImageError($event, row, col, col.image.default)\"\r\n />\r\n </div>\r\n\r\n <!-- Imagem com URL completa e loading -->\r\n <div\r\n *ngIf=\"\r\n col.image && col.image.url && !col.iconClass && !col.method\r\n \"\r\n class=\"relative inline-block\"\r\n >\r\n <mat-spinner\r\n *ngIf=\"isImageLoading(row, col)\"\r\n [diameter]=\"32\"\r\n class=\"absolute inset-0 m-auto\"\r\n ></mat-spinner>\r\n <img\r\n [src]=\"row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n [class.opacity-0]=\"isImageLoading(row, col)\"\r\n alt=\"\"\r\n (load)=\"onImageLoad(row, col)\"\r\n (error)=\"onImageError($event, row, col, col.image.default)\"\r\n />\r\n </div>\r\n <ng-container *ngIf=\"col.iconClass\">\r\n <button\r\n *ngFor=\"let iconClass of col.iconClass\"\r\n (click)=\"\r\n iconClass.buttonMethod\r\n ? iconClass.buttonMethod(row, $event)\r\n : $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [ngClass]=\"iconClass.class\"\r\n *ngIf=\"\r\n iconClass.condition === undefined ||\r\n (iconClass.condition !== undefined &&\r\n $any(iconClass.condition)(row))\r\n \"\r\n >{{ iconClass.text }}</span\r\n >\r\n </button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"columnProperties\"></tr>\r\n <tr\r\n [ngClass]=\"{\r\n 'example-element-row': data.isNotClickable === true,\r\n 'example-element-row cursor-pointer': !data.isNotClickable,\r\n }\"\r\n mat-row\r\n *matRowDef=\"let row; columns: columnProperties\"\r\n (click)=\"goToDetails(row)\"\r\n ></tr>\r\n\r\n <!-- ROW SHOWN WHEN THERE IS NO MATCHING DATA. -->\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td *ngIf=\"!(isLoading$ | async)\" class=\"mat-cell p-4\" colspan=\"4\">\r\n Nenhum resultado encontrado para a busca\r\n </td>\r\n </tr>\r\n </table>\r\n\r\n <div class=\"flex justify-center\" *ngIf=\"isLoading$ | async\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <div class=\"paginator-container\">\r\n <mat-paginator\r\n #paginator\r\n [pageSizeOptions]=\"[25, 50, 100]\"\r\n [pageSize]=\"pageSize\"\r\n [length]=\"totalItems\"\r\n showFirstLastButtons\r\n aria-label=\"Select page of periodic elements\"\r\n (page)=\"onPageChange($event)\"\r\n [ngClass]=\"{\r\n 'hide-length':\r\n ['filter', 'filterByDate', 'equals'].includes(\r\n this.currentArrange\r\n ) || this.data.filterFn,\r\n 'hide-next-button': !hasNextPage && data.pagination === true,\r\n 'hide-last-button':\r\n (!hasNextPage && data.pagination === true) ||\r\n this.data.filterFn,\r\n }\"\r\n >\r\n </mat-paginator>\r\n <div\r\n *ngIf=\"\r\n !(isLoading$ | async) &&\r\n dataSource?.data &&\r\n dataSource.data.length > 0 &&\r\n data?.filterFn\r\n \"\r\n class=\"page-number-display\"\r\n >\r\n {{ currentPageNumber }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- TOOLTIP PERSONALIZADO -->\r\n <lib-table-tooltip\r\n [state]=\"tooltipState\"\r\n [styles]=\"getTooltipStyles()\"\r\n ></lib-table-tooltip>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{--table-color: #1976d2;--table-text-color: white;--table-header-bg: #1976d2;--table-header-text: white;--table-scrollbar-bg: #f5f5f5;--table-scrollbar-thumb: var(--table-color)}.table-container::-webkit-scrollbar{width:10px;height:10px;background-color:var(--table-scrollbar-bg, #f5f5f5)}.table-container::-webkit-scrollbar-thumb{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));border-radius:5px}.table-container::-webkit-scrollbar-thumb:hover{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));opacity:.8}.overflow-x-auto::-webkit-scrollbar,.overflow-y-auto::-webkit-scrollbar,.overflow-auto::-webkit-scrollbar{width:10px;height:10px;background-color:var(--table-scrollbar-bg, #f5f5f5)}.overflow-x-auto::-webkit-scrollbar-thumb,.overflow-y-auto::-webkit-scrollbar-thumb,.overflow-auto::-webkit-scrollbar-thumb{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));border-radius:5px}.overflow-x-auto::-webkit-scrollbar-thumb:hover,.overflow-y-auto::-webkit-scrollbar-thumb:hover,.overflow-auto::-webkit-scrollbar-thumb:hover{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));opacity:.8}:host ::ng-deep .mat-table .mat-header-cell,:host ::ng-deep .mat-header-cell,:host ::ng-deep th.mat-header-cell,:host ::ng-deep .mat-mdc-table .mat-mdc-header-cell,:host ::ng-deep .mat-mdc-header-cell,:host ::ng-deep th.mat-mdc-header-cell{background-color:var(--table-header-bg, #1976d2)!important;color:var(--table-header-text, white)!important;font-weight:600}::ng-deep .fa-filter,::ng-deep i.fa-filter{color:var(--table-color, #1976d2)!important}::ng-deep .rounded-xl.border{border-color:var(--table-color, #1976d2)!important}::ng-deep .border-gray-200.rounded-xl{border-color:var(--table-color, #1976d2)!important}::ng-deep .mdc-notched-outline__notch{border-right:none!important}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-bottom:0}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-bottom:0}.mat-mdc-text-field-wrapper.mdc-text-field--outlined.mdc-text-field--disabled{background:rgba(0,0,0,.15);background-size:1px 100%!important;background-repeat:repeat-x!important}.mdc-text-field--disabled .mdc-text-field__input{color:#525252}button:not([matTooltip=\"Adicionar novo filtro\"]):not([matTooltip=\"Aplicar filtros\"]):not([matTooltip=\"Limpar filtros\"]):not([matTooltip=\"Exportar Tabela\"]):not(:has(i.fa-plus)):not(:has(i.fa-search)):not(:has(i.fas.fa-redo-alt)):not(:has(i.fa-download)){transition:all .2s ease;cursor:pointer}button:not([matTooltip=\"Adicionar novo filtro\"]):not([matTooltip=\"Aplicar filtros\"]):not([matTooltip=\"Limpar filtros\"]):not([matTooltip=\"Exportar Tabela\"]):not(:has(i.fa-plus)):not(:has(i.fa-search)):not(:has(i.fas.fa-redo-alt)):not(:has(i.fa-download)):hover:not(:disabled){opacity:.9;transform:scale(1.02)}button:not([matTooltip=\"Adicionar novo filtro\"]):not([matTooltip=\"Aplicar filtros\"]):not([matTooltip=\"Limpar filtros\"]):not([matTooltip=\"Exportar Tabela\"]):not(:has(i.fa-plus)):not(:has(i.fa-search)):not(:has(i.fas.fa-redo-alt)):not(:has(i.fa-download)):disabled{opacity:.5;cursor:not-allowed;transform:none}::ng-deep .hide-length .mat-mdc-paginator-range-label{display:none}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-next.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base{visibility:hidden}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-last.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base.ng-star-inserted{visibility:hidden}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field.ng-tns-c162-1.mdc-text-field--filled{width:25dvw}::ng-deep .custom-filter .mat-mdc-text-field-wrapper{width:20dvw;max-width:300px}button[matTooltip=\"Adicionar novo filtro\"],button:has(i.fa-plus){display:inline-flex;align-items:center;gap:.5rem;border-radius:9999px;border:2px solid #93c5fd;background-color:#dbeafe;padding:.5rem 1.5rem;font-size:.875rem;font-weight:500;color:#2563eb;transition:all .3s;cursor:pointer;transform:translateY(0)}button[matTooltip=\"Adicionar novo filtro\"]:hover,button:has(i.fa-plus):hover{transform:translateY(-2px);border-color:#60a5fa;background-color:#bfdbfe;box-shadow:0 4px 6px #0000001a}button[matTooltip=\"Aplicar filtros\"],button:has(i.fa-search){display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;background-color:#16a34a;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;color:#fff;transition:background-color .2s;cursor:pointer;border:none}button[matTooltip=\"Aplicar filtros\"]:hover,button:has(i.fa-search):hover{background-color:#15803d}button[matTooltip=\"Aplicar filtros\"]:disabled,button:has(i.fa-search):disabled{opacity:.5;cursor:not-allowed}button[matTooltip=\"Limpar filtros\"],button:has(i.fas.fa-redo-alt){display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;background-color:#ef4444;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;color:#fff;transition:background-color .2s;cursor:pointer;border:none}button[matTooltip=\"Limpar filtros\"]:hover,button:has(i.fas.fa-redo-alt):hover{background-color:#dc2626}button[matTooltip=\"Exportar Tabela\"],button:has(i.fa-download){display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;background-color:#f97316;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;color:#fff;transition:background-color .2s;cursor:pointer;border:none}button[matTooltip=\"Exportar Tabela\"]:hover:not(:disabled),button:has(i.fa-download):hover:not(:disabled){background-color:#ea580c}button[matTooltip=\"Exportar Tabela\"]:disabled,button:has(i.fa-download):disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i7.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i8.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: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i8.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i8.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i8.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i8.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: i9.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i9.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i9.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i9.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i9.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i9.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i9.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i9.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i9.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i9.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i9.MatNoDataRow, selector: "ng-template[matNoDataRow]" }, { kind: "component", type: i10.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "directive", type: i11.MatSort, selector: "[matSort]", inputs: ["matSortDisabled", "matSortActive", "matSortStart", "matSortDirection", "matSortDisableClear"], outputs: ["matSortChange"], exportAs: ["matSort"] }, { kind: "component", type: i11.MatSortHeader, selector: "[mat-sort-header]", inputs: ["disabled", "mat-sort-header", "arrowPosition", "start", "sortActionDescription", "disableClear"], exportAs: ["matSortHeader"] }, { kind: "component", type: i12.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i12.MatLabel, selector: "mat-label" }, { kind: "directive", type: i12.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: i13.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: i14.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i15.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "directive", type: i16.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i17.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i18.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i19.TableTabsComponent, selector: "lib-table-tabs", inputs: ["tabsData", "selectedTab"], outputs: ["tabSelected"] }, { kind: "component", type: i20.TableTooltipComponent, selector: "lib-table-tooltip", inputs: ["state", "styles"] }, { kind: "pipe", type: i7.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
696
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: TableComponent, decorators: [{
697
- type: Component,
698
- args: [{ selector: 'lib-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"data\" class=\"card-body\">\r\n <div class=\"flex flex-col justify-between gap-6\">\r\n <!-- UNIFIED CONTROL PANEL: FILTERS, SORT & ACTIONS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === true &&\r\n (dropdownItems.length > 0 ||\r\n sortableDropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title and Custom Action -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- SORT FIELD (Integrated with filters) -->\r\n <div class=\"mb-4\" *ngIf=\"sortableDropdownItems.length > 0\">\r\n <div class=\"flex flex-wrap items-center gap-3 p-2\">\r\n <div class=\"min-w-[200px] flex-1\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>Ordenar por</span>\r\n </mat-label>\r\n <mat-select placeholder=\"Selecione...\" [formControl]=\"selectSort\">\r\n <mat-option\r\n *ngFor=\"let item of sortableDropdownItems\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-sort-alpha-down text-cyan-600\"></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- FILTERS CONTENT (WITH REFINEMENTS) -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3 p-2\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option\r\n *ngFor=\"let item of getAvailableFilterOptions()\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange === 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search($event)\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n matInput\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'initialDate', i)\"\r\n formControlName=\"initialDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'finalDate', i)\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Action Buttons -->\r\n <div\r\n class=\"-mb-2 flex items-start justify-between gap-4 border-t border-gray-200 pt-4\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Right Side: Search, Reset, Export -->\r\n <div\r\n class=\"flex flex-wrap gap-3 self-start sm:self-auto\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true || this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"\r\n $any(arrange) && downloadTable !== undefined\r\n ? downloadTable($any(arrange), data.conditions || [])\r\n : null\r\n \"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- UNIFIED CONTROL PANEL (for non-paginated tables): SEARCH, SORT & FILTERS -->\r\n <div\r\n class=\"rounded-xl border border-gray-200 bg-white p-4 shadow-lg\"\r\n *ngIf=\"\r\n data.pagination === false &&\r\n (hasFilterableColumn === true ||\r\n dropdownItems.length > 0 ||\r\n data.actionButton)\r\n \"\r\n >\r\n <!-- PANEL HEADER: Title and Custom Action -->\r\n <div\r\n class=\"mb-4 flex flex-col items-start justify-between gap-4 border-b-2 border-gray-200 pb-4 md:flex-row md:items-center\"\r\n >\r\n <!-- Left Side: Title & Main Action Button -->\r\n <div class=\"flex flex-wrap items-center gap-4\">\r\n <div class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-filter text-xl text-blue-500\"></i>\r\n <span class=\"text-lg font-semibold text-gray-700\"\r\n >Filtros e A\u00E7\u00F5es</span\r\n >\r\n </div>\r\n <button\r\n *ngIf=\"data.actionButton && data.actionButton.condition\"\r\n [ngClass]=\"\r\n (data.actionButton.colorClass || 'bg-blue-500') +\r\n ' flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium text-white hover:opacity-70'\r\n \"\r\n [routerLink]=\"data.actionButton.routerLink\"\r\n (click)=\"\r\n data.actionButton.method ? data.actionButton.method($event) : null\r\n \"\r\n >\r\n <i\r\n *ngIf=\"data.actionButton.icon\"\r\n [class]=\"data.actionButton.icon\"\r\n ></i>\r\n {{ data.actionButton.label }}\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <!-- SIMPLE SEARCH -->\r\n <div\r\n class=\"mb-4\"\r\n *ngIf=\"hasFilterableColumn === true && data.showSimpleSearch !== false\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-blue-500\"></i>\r\n Buscar\r\n </mat-label>\r\n <input\r\n matInput\r\n (keyup.enter)=\"search($event)\"\r\n (keyup)=\"applyFilter(filterInput.value)\"\r\n placeholder=\"Digite para filtrar...\"\r\n #filterInput\r\n />\r\n <mat-icon matSuffix class=\"text-gray-500\">search</mat-icon>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- FILTERS PANEL -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <!-- FILTERS CONTENT -->\r\n <div class=\"mb-4 space-y-3\" *ngIf=\"filtersForm.controls.length > 0\">\r\n <div\r\n [formGroup]=\"$any(filterGroup)\"\r\n *ngFor=\"let filterGroup of filtersForm.controls; let i = index\"\r\n class=\"flex flex-wrap items-center gap-3\"\r\n >\r\n <!-- FILTER TYPE SELECTOR -->\r\n <div class=\"min-w-[200px] flex-1\" *ngIf=\"dropdownItems.length > 0\">\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>Tipo de filtro</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione o tipo...\"\r\n formControlName=\"selectFilter\"\r\n (selectionChange)=\"onSelectFilterChange()\"\r\n >\r\n <mat-option\r\n *ngFor=\"let item of getAvailableFilterOptions()\"\r\n [value]=\"item\"\r\n >\r\n <div class=\"flex items-center gap-2\">\r\n <i\r\n [class]=\"item.icon || 'fa fa-filter'\"\r\n class=\"text-sm text-blue-500\"\r\n ></i>\r\n <span>{{ item.title }}</span>\r\n </div>\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- TEXT FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filter'\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-search text-gray-400\"></i>\r\n <span>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Filtrar\"\r\n }}</span>\r\n </mat-label>\r\n <input\r\n (keyup.enter)=\"search($event)\"\r\n formControlName=\"typeFilter\"\r\n matInput\r\n placeholder=\"Digite para filtrar...\"\r\n #input\r\n />\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DROPDOWN FILTER -->\r\n <div\r\n class=\"min-w-[200px] flex-1\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value &&\r\n $any(filterGroup)\r\n .get('selectFilter')\r\n ?.value.hasOwnProperty('items')\r\n \"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"w-full\">\r\n <mat-label>{{\r\n $any(filterGroup).get(\"selectFilter\")?.value?.title ||\r\n \"Selecione\"\r\n }}</mat-label>\r\n <mat-select\r\n placeholder=\"Selecione...\"\r\n formControlName=\"selectItem\"\r\n multiple\r\n >\r\n <mat-option\r\n *ngFor=\"\r\n let item of $any(filterGroup).get('selectFilter')?.value\r\n .items\r\n \"\r\n [value]=\"item\"\r\n >\r\n {{ item.label }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- DATE FILTER -->\r\n <div\r\n class=\"min-w-[340px] flex-auto\"\r\n *ngIf=\"\r\n $any(filterGroup).get('selectFilter')?.value?.arrange ===\r\n 'filterByDate'\r\n \"\r\n >\r\n <div\r\n class=\"flex flex-col items-stretch gap-3 sm:flex-row sm:items-center\"\r\n >\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Inicial</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n matInput\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'initialDate', i)\"\r\n (blur)=\"onDateFilterChange()\"\r\n formControlName=\"initialDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"flex-1\">\r\n <mat-label class=\"flex items-center gap-2\">\r\n <i class=\"fa fa-calendar text-gray-400\"></i>\r\n <span>Data Final</span>\r\n </mat-label>\r\n <input\r\n type=\"text\"\r\n (keydown.enter)=\"search($event)\"\r\n (input)=\"onDateInput($event, 'finalDate', i)\"\r\n (blur)=\"onDateFilterChange()\"\r\n matInput\r\n formControlName=\"finalDate\"\r\n placeholder=\"DD/MM/AAAA\"\r\n maxlength=\"10\"\r\n />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- REMOVE FILTER BUTTON -->\r\n <div *ngIf=\"filtersForm.length > 1\" class=\"ml-auto flex-shrink-0\">\r\n <button\r\n (click)=\"removeFilter(i)\"\r\n class=\"flex h-10 w-10 items-center justify-center rounded-full transition-colors duration-300 hover:bg-red-100\"\r\n matTooltip=\"Remover filtro\"\r\n >\r\n <i class=\"fa fa-trash text-red-500 hover:text-red-600\"></i>\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- PANEL FOOTER: Add Filter & Actions -->\r\n <div\r\n class=\"-mb-2 flex items-start justify-between gap-4 border-t border-gray-200 pt-4\"\r\n >\r\n <!-- Add Filter Button -->\r\n <div *ngIf=\"dropdownItems.length > 0\">\r\n <button\r\n (click)=\"addFilter()\"\r\n class=\"transform rounded-full border-2 border-blue-300 bg-blue-50 px-6 py-2 text-sm font-medium text-blue-600 transition-all duration-300 hover:-translate-y-0.5 hover:border-blue-400 hover:bg-blue-100 hover:shadow-md\"\r\n matTooltip=\"Adicionar novo filtro\"\r\n >\r\n <i class=\"fa fa-plus mr-2\"></i>\r\n Adicionar Filtro\r\n </button>\r\n </div>\r\n\r\n <!-- Action Buttons -->\r\n <div\r\n class=\"flex flex-wrap gap-3 self-start sm:self-auto\"\r\n *ngIf=\"\r\n this.hasFilterableColumn === true ||\r\n this.hasSortableColumn === true\r\n \"\r\n >\r\n <button\r\n (click)=\"search()\"\r\n type=\"button\"\r\n class=\"flex items-center gap-2 rounded-lg bg-green-600 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-green-700\"\r\n matTooltip=\"Aplicar filtros\"\r\n >\r\n <i class=\"fa fa-search\"></i>\r\n Pesquisar\r\n </button>\r\n\r\n <button\r\n (click)=\"resetFilter()\"\r\n class=\"flex items-center gap-2 rounded-lg bg-red-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-red-600\"\r\n matTooltip=\"Limpar filtros\"\r\n >\r\n <i class=\"fas fa-redo-alt\"></i>\r\n Resetar\r\n </button>\r\n\r\n <button\r\n *ngIf=\"data.download !== false && downloadTable\"\r\n class=\"flex items-center gap-2 rounded-lg bg-orange-500 px-5 py-2 text-sm font-medium text-white transition-colors hover:bg-orange-600\"\r\n matTooltipPosition=\"above\"\r\n matTooltip=\"Exportar Tabela\"\r\n [disabled]=\"\r\n this.dataSource && this.dataSource.filteredData.length <= 0\r\n \"\r\n (click)=\"handleDownload()\"\r\n >\r\n <i class=\"fa fa-download\"></i>\r\n Exportar\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"flex flex-col\">\r\n <!-- TABS COMPONENT -->\r\n <lib-table-tabs\r\n *ngIf=\"data.tabs && data.tabs.tabsData && data.tabs.tabsData.length > 0\"\r\n [tabsData]=\"data.tabs.tabsData\"\r\n [selectedTab]=\"selectedTab\"\r\n (tabSelected)=\"onTabSelected($event)\"\r\n ></lib-table-tabs>\r\n <div\r\n class=\"mat-elevation-z8 w-full overflow-x-auto rounded-xl table-container\"\r\n >\r\n <table\r\n mat-table\r\n [dataSource]=\"dataSource\"\r\n matSort\r\n #sort=\"matSort\"\r\n matSortActive=\"createdAt\"\r\n matSortDirection=\"desc\"\r\n >\r\n <ng-container\r\n *ngFor=\"let col of data.displayedColumns; trackBy: trackByProperty\"\r\n matColumnDef=\"{{ col.property }}\"\r\n >\r\n <ng-container *matHeaderCellDef>\r\n <!-- IF THE COLUMN IS NOT SORTABLE, THEN DON'T SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"!col.isSortable || data.pagination === true\"\r\n mat-header-cell\r\n >\r\n {{ col.title }}\r\n </th>\r\n <!-- IF THE COLUMN IS SORTABLE, THEN SHOW THE SORT BUTTONS -->\r\n <th\r\n *ngIf=\"col.isSortable && data.pagination === false\"\r\n mat-header-cell\r\n mat-sort-header\r\n >\r\n {{ col.title }}\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let row\"\r\n (click)=\"col.method ? col.method(row) : null\"\r\n (mouseenter)=\"onCellMouseEnter($event, row, col)\"\r\n (mouseleave)=\"onCellMouseLeave()\"\r\n (mousemove)=\"onCellMouseMove($event)\"\r\n >\r\n <!-- CHECK IF THE COLUMN MUST BE DISPLAYED -->\r\n <span *ngIf=\"!col.image && !col.iconClass && !col.method\">\r\n <ng-container>\r\n <span\r\n *ngIf=\"\r\n col.charLimit &&\r\n row[col.property] &&\r\n row[col.property].length > col.charLimit;\r\n else withinLimit\r\n \"\r\n >\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row) }}\r\n </span>\r\n </span>\r\n </ng-container>\r\n <ng-template #withinLimit>\r\n <a\r\n *ngIf=\"col.hasLink === true\"\r\n [href]=\"row[col.property]\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <a\r\n *ngIf=\"col.hasLink && isString(col.hasLink)\"\r\n [href]=\"col.hasLink\"\r\n target=\"_blank\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </a>\r\n <span\r\n *ngIf=\"col.hasLink !== true && !isString(col.hasLink)\"\r\n >\r\n {{ getDisplayValue(col, row, true) }}\r\n </span>\r\n </ng-template>\r\n </span>\r\n <!------------------- IMAGE ------------------>\r\n <!-- Imagem com loading -->\r\n <div\r\n *ngIf=\"\r\n col.image && col.image.path && !col.iconClass && !col.method\r\n \"\r\n class=\"relative inline-block\"\r\n >\r\n <mat-spinner\r\n *ngIf=\"isImageLoading(row, col)\"\r\n [diameter]=\"32\"\r\n class=\"absolute inset-0 m-auto\"\r\n ></mat-spinner>\r\n <img\r\n [src]=\"col.image.path + '/' + row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n [class.opacity-0]=\"isImageLoading(row, col)\"\r\n alt=\"\"\r\n (load)=\"onImageLoad(row, col)\"\r\n (error)=\"onImageError($event, row, col, col.image.default)\"\r\n />\r\n </div>\r\n\r\n <!-- Imagem com URL completa e loading -->\r\n <div\r\n *ngIf=\"\r\n col.image && col.image.url && !col.iconClass && !col.method\r\n \"\r\n class=\"relative inline-block\"\r\n >\r\n <mat-spinner\r\n *ngIf=\"isImageLoading(row, col)\"\r\n [diameter]=\"32\"\r\n class=\"absolute inset-0 m-auto\"\r\n ></mat-spinner>\r\n <img\r\n [src]=\"row[col.property]\"\r\n [ngClass]=\"col.image.class\"\r\n [class.opacity-0]=\"isImageLoading(row, col)\"\r\n alt=\"\"\r\n (load)=\"onImageLoad(row, col)\"\r\n (error)=\"onImageError($event, row, col, col.image.default)\"\r\n />\r\n </div>\r\n <ng-container *ngIf=\"col.iconClass\">\r\n <button\r\n *ngFor=\"let iconClass of col.iconClass\"\r\n (click)=\"\r\n iconClass.buttonMethod\r\n ? iconClass.buttonMethod(row, $event)\r\n : $event.stopPropagation()\r\n \"\r\n >\r\n <span\r\n [ngClass]=\"iconClass.class\"\r\n *ngIf=\"\r\n iconClass.condition === undefined ||\r\n (iconClass.condition !== undefined &&\r\n $any(iconClass.condition)(row))\r\n \"\r\n >{{ iconClass.text }}</span\r\n >\r\n </button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <tr mat-header-row *matHeaderRowDef=\"columnProperties\"></tr>\r\n <tr\r\n [ngClass]=\"{\r\n 'example-element-row': data.isNotClickable === true,\r\n 'example-element-row cursor-pointer': !data.isNotClickable,\r\n }\"\r\n mat-row\r\n *matRowDef=\"let row; columns: columnProperties\"\r\n (click)=\"goToDetails(row)\"\r\n ></tr>\r\n\r\n <!-- ROW SHOWN WHEN THERE IS NO MATCHING DATA. -->\r\n <tr class=\"mat-row\" *matNoDataRow>\r\n <td *ngIf=\"!(isLoading$ | async)\" class=\"mat-cell p-4\" colspan=\"4\">\r\n Nenhum resultado encontrado para a busca\r\n </td>\r\n </tr>\r\n </table>\r\n\r\n <div class=\"flex justify-center\" *ngIf=\"isLoading$ | async\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <div class=\"paginator-container\">\r\n <mat-paginator\r\n #paginator\r\n [pageSizeOptions]=\"[25, 50, 100]\"\r\n [pageSize]=\"pageSize\"\r\n [length]=\"totalItems\"\r\n showFirstLastButtons\r\n aria-label=\"Select page of periodic elements\"\r\n (page)=\"onPageChange($event)\"\r\n [ngClass]=\"{\r\n 'hide-length':\r\n ['filter', 'filterByDate', 'equals'].includes(\r\n this.currentArrange\r\n ) || this.data.filterFn,\r\n 'hide-next-button': !hasNextPage && data.pagination === true,\r\n 'hide-last-button':\r\n (!hasNextPage && data.pagination === true) ||\r\n this.data.filterFn,\r\n }\"\r\n >\r\n </mat-paginator>\r\n <div\r\n *ngIf=\"\r\n !(isLoading$ | async) &&\r\n dataSource?.data &&\r\n dataSource.data.length > 0 &&\r\n data?.filterFn\r\n \"\r\n class=\"page-number-display\"\r\n >\r\n {{ currentPageNumber }}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- TOOLTIP PERSONALIZADO -->\r\n <lib-table-tooltip\r\n [state]=\"tooltipState\"\r\n [styles]=\"getTooltipStyles()\"\r\n ></lib-table-tooltip>\r\n</div>\r\n", styles: ["@charset \"UTF-8\";:host{--table-color: #1976d2;--table-text-color: white;--table-header-bg: #1976d2;--table-header-text: white;--table-scrollbar-bg: #f5f5f5;--table-scrollbar-thumb: var(--table-color)}.table-container::-webkit-scrollbar{width:10px;height:10px;background-color:var(--table-scrollbar-bg, #f5f5f5)}.table-container::-webkit-scrollbar-thumb{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));border-radius:5px}.table-container::-webkit-scrollbar-thumb:hover{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));opacity:.8}.overflow-x-auto::-webkit-scrollbar,.overflow-y-auto::-webkit-scrollbar,.overflow-auto::-webkit-scrollbar{width:10px;height:10px;background-color:var(--table-scrollbar-bg, #f5f5f5)}.overflow-x-auto::-webkit-scrollbar-thumb,.overflow-y-auto::-webkit-scrollbar-thumb,.overflow-auto::-webkit-scrollbar-thumb{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));border-radius:5px}.overflow-x-auto::-webkit-scrollbar-thumb:hover,.overflow-y-auto::-webkit-scrollbar-thumb:hover,.overflow-auto::-webkit-scrollbar-thumb:hover{background-color:var(--table-scrollbar-thumb, var(--table-color, #1976d2));opacity:.8}:host ::ng-deep .mat-table .mat-header-cell,:host ::ng-deep .mat-header-cell,:host ::ng-deep th.mat-header-cell,:host ::ng-deep .mat-mdc-table .mat-mdc-header-cell,:host ::ng-deep .mat-mdc-header-cell,:host ::ng-deep th.mat-mdc-header-cell{background-color:var(--table-header-bg, #1976d2)!important;color:var(--table-header-text, white)!important;font-weight:600}::ng-deep .fa-filter,::ng-deep i.fa-filter{color:var(--table-color, #1976d2)!important}::ng-deep .rounded-xl.border{border-color:var(--table-color, #1976d2)!important}::ng-deep .border-gray-200.rounded-xl{border-color:var(--table-color, #1976d2)!important}::ng-deep .mdc-notched-outline__notch{border-right:none!important}.mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-bottom:0}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field--outlined .mat-mdc-form-field-infix{padding-bottom:0}.mat-mdc-text-field-wrapper.mdc-text-field--outlined.mdc-text-field--disabled{background:rgba(0,0,0,.15);background-size:1px 100%!important;background-repeat:repeat-x!important}.mdc-text-field--disabled .mdc-text-field__input{color:#525252}button:not([matTooltip=\"Adicionar novo filtro\"]):not([matTooltip=\"Aplicar filtros\"]):not([matTooltip=\"Limpar filtros\"]):not([matTooltip=\"Exportar Tabela\"]):not(:has(i.fa-plus)):not(:has(i.fa-search)):not(:has(i.fas.fa-redo-alt)):not(:has(i.fa-download)){transition:all .2s ease;cursor:pointer}button:not([matTooltip=\"Adicionar novo filtro\"]):not([matTooltip=\"Aplicar filtros\"]):not([matTooltip=\"Limpar filtros\"]):not([matTooltip=\"Exportar Tabela\"]):not(:has(i.fa-plus)):not(:has(i.fa-search)):not(:has(i.fas.fa-redo-alt)):not(:has(i.fa-download)):hover:not(:disabled){opacity:.9;transform:scale(1.02)}button:not([matTooltip=\"Adicionar novo filtro\"]):not([matTooltip=\"Aplicar filtros\"]):not([matTooltip=\"Limpar filtros\"]):not([matTooltip=\"Exportar Tabela\"]):not(:has(i.fa-plus)):not(:has(i.fa-search)):not(:has(i.fas.fa-redo-alt)):not(:has(i.fa-download)):disabled{opacity:.5;cursor:not-allowed;transform:none}::ng-deep .hide-length .mat-mdc-paginator-range-label{display:none}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-next.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base{visibility:hidden}::ng-deep .hide-next-button .mat-mdc-tooltip-trigger.mat-mdc-paginator-navigation-last.mdc-icon-button.mat-mdc-icon-button.mat-unthemed.mat-mdc-button-base.ng-star-inserted{visibility:hidden}::ng-deep .mat-mdc-text-field-wrapper.mdc-text-field.ng-tns-c162-1.mdc-text-field--filled{width:25dvw}::ng-deep .custom-filter .mat-mdc-text-field-wrapper{width:20dvw;max-width:300px}button[matTooltip=\"Adicionar novo filtro\"],button:has(i.fa-plus){display:inline-flex;align-items:center;gap:.5rem;border-radius:9999px;border:2px solid #93c5fd;background-color:#dbeafe;padding:.5rem 1.5rem;font-size:.875rem;font-weight:500;color:#2563eb;transition:all .3s;cursor:pointer;transform:translateY(0)}button[matTooltip=\"Adicionar novo filtro\"]:hover,button:has(i.fa-plus):hover{transform:translateY(-2px);border-color:#60a5fa;background-color:#bfdbfe;box-shadow:0 4px 6px #0000001a}button[matTooltip=\"Aplicar filtros\"],button:has(i.fa-search){display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;background-color:#16a34a;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;color:#fff;transition:background-color .2s;cursor:pointer;border:none}button[matTooltip=\"Aplicar filtros\"]:hover,button:has(i.fa-search):hover{background-color:#15803d}button[matTooltip=\"Aplicar filtros\"]:disabled,button:has(i.fa-search):disabled{opacity:.5;cursor:not-allowed}button[matTooltip=\"Limpar filtros\"],button:has(i.fas.fa-redo-alt){display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;background-color:#ef4444;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;color:#fff;transition:background-color .2s;cursor:pointer;border:none}button[matTooltip=\"Limpar filtros\"]:hover,button:has(i.fas.fa-redo-alt):hover{background-color:#dc2626}button[matTooltip=\"Exportar Tabela\"],button:has(i.fa-download){display:inline-flex;align-items:center;gap:.5rem;border-radius:.5rem;background-color:#f97316;padding:.5rem 1.25rem;font-size:.875rem;font-weight:500;color:#fff;transition:background-color .2s;cursor:pointer;border:none}button[matTooltip=\"Exportar Tabela\"]:hover:not(:disabled),button:has(i.fa-download):hover:not(:disabled){background-color:#ea580c}button[matTooltip=\"Exportar Tabela\"]:disabled,button:has(i.fa-download):disabled{opacity:.5;cursor:not-allowed}\n"] }]
699
- }], ctorParameters: function () { return [{ type: i1.Router }, { type: i2.TableService }, { type: i3.FilterService }, { type: i4.TooltipService }, { type: i5.PaginationService }, { type: i6.AngularFirestore }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { data: [{
700
- type: Input
701
- }], downloadTable: [{
702
- type: Input
703
- }], paginator: [{
704
- type: ViewChild,
705
- args: [MatPaginator]
706
- }], sort: [{
707
- type: ViewChild,
708
- args: [MatSort]
709
- }] } });
710
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmctZmlyZWJhc2UtdGFibGUta3hwL3NyYy9saWIvY29tcG9uZW50cy90YWJsZS90YWJsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZy1maXJlYmFzZS10YWJsZS1reHAvc3JjL2xpYi9jb21wb25lbnRzL3RhYmxlL3RhYmxlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFNTCxjQUFjLEdBSWYsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQ0wsU0FBUyxFQUNULEtBQUssRUFFTCxTQUFTLEVBS1QsdUJBQXVCLEdBR3hCLE1BQU0sZUFBZSxDQUFDO0FBS3ZCLE9BQU8sRUFBRSxZQUFZLEVBQWEsTUFBTSw2QkFBNkIsQ0FBQztBQUN0RSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDakQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFNN0QsT0FBTyxFQUNMLGVBQWUsRUFDZixjQUFjLEVBQ2QsUUFBUSxFQUNSLGVBQWUsRUFDZixXQUFXLEdBQ1osTUFBTSx5QkFBeUIsQ0FBQztBQUNqQyxPQUFPLEVBQ0wsWUFBWSxFQUNaLGNBQWMsRUFDZCxPQUFPLEVBQ1AsU0FBUyxFQUNULGVBQWUsR0FDaEIsTUFBTSxNQUFNLENBQUM7QUFLZCxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBYSxNQUFNLGdCQUFnQixDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBUW5FLE1BQU0sT0FBTyxjQUFjO0lBd0R6QixjQUFjO0lBQ2QsWUFDVSxNQUFjLEVBQ2QsWUFBMEIsRUFDMUIsYUFBNEIsRUFDNUIsY0FBOEIsRUFDOUIsaUJBQW9DLEVBQ3BDLFNBQTJCLEVBQzNCLEVBQWMsRUFDZCxHQUFzQjtR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QVUsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLFlBQVksRUFBRTtnQkFDbkQsSUFBSSxDQUFDLGFBQWEsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxZQUFZLENBQUMsQ0FBQzthQUN4RDtZQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1lBQy9DLElBQUksQ0FBQyxhQUFhLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1NBQ3pEO2FBQU07WUFDTCxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUU7Z0JBQ2hCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQzthQUM5RDtTQUNGO0lBQ0gsQ0FBQzs7NEdBMTRCVSxjQUFjO2dHQUFkLGNBQWMsc0pBNkNkLFlBQVksdUVBQ1osT0FBTyxxRUM1R3BCLGszL0JBd3hCQTs0RkQxdEJhLGNBQWM7a0JBTjFCLFNBQVM7K0JBQ0UsV0FBVyxtQkFHSix1QkFBdUIsQ0FBQyxNQUFNO3lTQU10QyxJQUFJO3NCQUFaLEtBQUs7Z0JBQ0csYUFBYTtzQkFBckIsS0FBSztnQkF3Q21CLFNBQVM7c0JBQWpDLFNBQVM7dUJBQUMsWUFBWTtnQkFDSCxJQUFJO3NCQUF2QixTQUFTO3VCQUFDLE9BQU8iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIEFycmFuZ2UsXHJcbiAgQ29uZGl0aW9uLFxyXG4gIFRhYkRhdGEsXHJcbiAgVGFibGVEYXRhLFxyXG4gIENvbHVtbixcclxuICBUQUJMRV9ERUZBVUxUUyxcclxuICBEcm9wZG93bkl0ZW0sXHJcbiAgRmlsdGVyU2VsZWN0SXRlbSxcclxuICBQYWdpbmF0aW9uLFxyXG59IGZyb20gJy4uLy4uL3R5cGVzL1RhYmxlJztcclxuaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgSW5wdXQsXHJcbiAgT25Jbml0LFxyXG4gIFZpZXdDaGlsZCxcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIEVsZW1lbnRSZWYsXHJcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgT25EZXN0cm95LFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIEFuZ3VsYXJGaXJlc3RvcmUsXHJcbiAgUXVlcnlEb2N1bWVudFNuYXBzaG90LFxyXG59IGZyb20gJ0Bhbmd1bGFyL2ZpcmUvY29tcGF0L2ZpcmVzdG9yZSc7XHJcbmltcG9ydCB7IE1hdFBhZ2luYXRvciwgUGFnZUV2ZW50IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvcGFnaW5hdG9yJztcclxuaW1wb3J0IHsgTWF0U29ydCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL3NvcnQnO1xyXG5pbXBvcnQgeyBNYXRUYWJsZURhdGFTb3VyY2UgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJsZSc7XHJcbmltcG9ydCB7IFJvdXRlciB9IGZyb20gJ0Bhbmd1bGFyL3JvdXRlcic7XHJcbmltcG9ydCB7IFRhYmxlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3RhYmxlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBGaWx0ZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZmlsdGVyLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBUb29sdGlwU2VydmljZSwgVG9vbHRpcFN0YXRlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdG9vbHRpcC5zZXJ2aWNlJztcclxuaW1wb3J0IHsgUGFnaW5hdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9wYWdpbmF0aW9uLnNlcnZpY2UnO1xyXG5pbXBvcnQge1xyXG4gIGdldERpc3BsYXlWYWx1ZSxcclxuICBnZXROZXN0ZWRWYWx1ZSxcclxuICBpc1N0cmluZyxcclxuICB0cmFja0J5UHJvcGVydHksXHJcbiAgZ2V0SW1hZ2VLZXksXHJcbn0gZnJvbSAnLi4vLi4vdXRpbHMvdGFibGUudXRpbHMnO1xyXG5pbXBvcnQge1xyXG4gIGRlYm91bmNlVGltZSxcclxuICBmaXJzdFZhbHVlRnJvbSxcclxuICBTdWJqZWN0LFxyXG4gIHRha2VVbnRpbCxcclxuICBCZWhhdmlvclN1YmplY3QsXHJcbn0gZnJvbSAncnhqcyc7XHJcbmltcG9ydCB7IE9yZGVyQnlEaXJlY3Rpb24gfSBmcm9tICdmaXJlYmFzZS9maXJlc3RvcmUnO1xyXG5pbXBvcnQgZmlyZWJhc2UgZnJvbSAnZmlyZWJhc2UvY29tcGF0JztcclxuaW1wb3J0IFdoZXJlRmlsdGVyT3AgPSBmaXJlYmFzZS5maXJlc3RvcmUuV2hlcmVGaWx0ZXJPcDtcclxuaW1wb3J0IGZpcmVzdG9yZSA9IGZpcmViYXNlLmZpcmVzdG9yZTtcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1BcnJheSwgRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdsaWItdGFibGUnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi90YWJsZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vdGFibGUuY29tcG9uZW50LnNjc3MnXSxcclxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxufSlcclxuZXhwb3J0IGNsYXNzIFRhYmxlQ29tcG9uZW50PFQgPSBhbnk+XHJcbiAgaW1wbGVtZW50cyBPbkluaXQsIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95XHJcbntcclxuICAvLyBJTlBVVFNcclxuICBASW5wdXQoKSBkYXRhITogVGFibGVEYXRhO1xyXG4gIEBJbnB1dCgpIGRvd25sb2FkVGFibGU/OiAoYXJyYW5nZTogQXJyYW5nZSwgY29uZGl0aW9uczogQ29uZGl0aW9uW10pID0+IHZvaWQ7XHJcbiAgYXJyYW5nZTogQXJyYW5nZSB8IG51bGwgPSBudWxsO1xyXG5cclxuICAvLyBWQVJJQUJMRVNcclxuICBkYXRhU291cmNlITogTWF0VGFibGVEYXRhU291cmNlPFQ+O1xyXG4gIGN1cnJlbnRQYWdlTnVtYmVyID0gMTtcclxuICBjdXJyZW50Q2xpZW50UGFnZUluZGV4ID0gMDtcclxuXHJcbiAgcHVibGljIGlzTG9hZGluZyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PGJvb2xlYW4+KGZhbHNlKTtcclxuXHJcbiAgcHVibGljIGl0ZW1zOiBUW10gPSBbXTtcclxuICBwdWJsaWMgZmlsdGVyZWRJdGVtczogVFtdID0gW107XHJcbiAgcHJpdmF0ZSBsYXN0RG9jOiBRdWVyeURvY3VtZW50U25hcHNob3Q8VD4gfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIGZpcnN0RG9jOiBRdWVyeURvY3VtZW50U25hcHNob3Q8VD4gfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIHNvcnRCeTogeyBmaWVsZDogc3RyaW5nOyBvcmRlcjogT3JkZXJCeURpcmVjdGlvbiB9ID0ge1xyXG4gICAgZmllbGQ6IFRBQkxFX0RFRkFVTFRTLlNPUlRfRklFTEQsXHJcbiAgICBvcmRlcjogVEFCTEVfREVGQVVMVFMuU09SVF9PUkRFUixcclxuICB9O1xyXG4gIHB1YmxpYyBjb2x1bW5Qcm9wZXJ0aWVzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICBmaWx0ZXJzRm9ybTogRm9ybUFycmF5O1xyXG4gIHNlbGVjdFNvcnQ6IEZvcm1Db250cm9sID0gbmV3IEZvcm1Db250cm9sKCcnKTtcclxuICBjdXJyZW50QXJyYW5nZSA9ICcnO1xyXG5cclxuICBoYXNOZXh0UGFnZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGRyb3Bkb3duSXRlbXM6IERyb3Bkb3duSXRlbVtdID0gW107XHJcbiAgc29ydGFibGVEcm9wZG93bkl0ZW1zOiBEcm9wZG93bkl0ZW1bXSA9IFtdO1xyXG4gIHBhZ2VTaXplID0gVEFCTEVfREVGQVVMVFMuUEFHRV9TSVpFO1xyXG4gIHRvdGFsSXRlbXMgPSAwO1xyXG4gIHBhZ2VFdmVudD86IFBhZ2VFdmVudDtcclxuICBmaWx0ZXJWYWx1ZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIGhhc0ZpbHRlcmFibGVDb2x1bW46IGJvb2xlYW4gPSBmYWxzZTtcclxuICBoYXNTb3J0YWJsZUNvbHVtbjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGZpbHRlclByZWRpY2F0ZTogKChkYXRhOiBULCBmaWx0ZXI6IHN0cmluZykgPT4gYm9vbGVhbikgfCB1bmRlZmluZWQ7XHJcbiAgcHJpdmF0ZSBmaWx0ZXJTdWJqZWN0ID0gbmV3IFN1YmplY3Q8c3RyaW5nPigpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVib3VuY2VUaW1lTXMgPSBUQUJMRV9ERUZBVUxUUy5ERUJPVU5DRV9USU1FX01TO1xyXG5cclxuICBzZWxlY3RlZFRhYjogbnVtYmVyID0gMDtcclxuXHJcbiAgQFZpZXdDaGlsZChNYXRQYWdpbmF0b3IpIHBhZ2luYXRvciE6IE1hdFBhZ2luYXRvcjtcclxuICBAVmlld0NoaWxkKE1hdFNvcnQpIHNvcnQhOiBNYXRTb3J0O1xyXG5cclxuICAvLyBQcm9wcmllZGFkZXMgcGFyYSBjb250cm9sZSBkbyB0b29sdGlwXHJcbiAgdG9vbHRpcFN0YXRlOiBUb29sdGlwU3RhdGU7XHJcblxyXG4gIC8vIENvbnRyb2xlIGRlIGxvYWRpbmcgZGUgaW1hZ2Vuc1xyXG4gIGltYWdlTG9hZGluZ1N0YXRlID0gbmV3IE1hcDxzdHJpbmcsIGJvb2xlYW4+KCk7XHJcblxyXG4gIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG5cclxuICAvLyBDT05TVFJVQ1RPUlxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcclxuICAgIHByaXZhdGUgdGFibGVTZXJ2aWNlOiBUYWJsZVNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGZpbHRlclNlcnZpY2U6IEZpbHRlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIHRvb2x0aXBTZXJ2aWNlOiBUb29sdGlwU2VydmljZSxcclxuICAgIHByaXZhdGUgcGFnaW5hdGlvblNlcnZpY2U6IFBhZ2luYXRpb25TZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBmaXJlc3RvcmU6IEFuZ3VsYXJGaXJlc3RvcmUsXHJcbiAgICBwcml2YXRlIGVsOiBFbGVtZW50UmVmLFxyXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICkge1xyXG4gICAgdGhpcy5maWx0ZXJzRm9ybSA9IG5ldyBGb3JtQXJyYXkoW3RoaXMuZmlsdGVyU2VydmljZS5jcmVhdGVGaWx0ZXJHcm91cCgpXSk7XHJcbiAgICB0aGlzLnRvb2x0aXBTdGF0ZSA9IHRoaXMudG9vbHRpcFNlcnZpY2UuY3JlYXRlSW5pdGlhbFN0YXRlKCk7XHJcbiAgfVxyXG5cclxuICAvLyBGSUxURVIgTUVUSE9EUyAoZGVsZWdhZG9zIGFvIEZpbHRlclNlcnZpY2UpXHJcblxyXG4gIGNyZWF0ZUZpbHRlckdyb3VwKCk6IEZvcm1Hcm91cCB7XHJcbiAgICByZXR1cm4gdGhpcy5maWx0ZXJTZXJ2aWNlLmNyZWF0ZUZpbHRlckdyb3VwKCk7XHJcbiAgfVxyXG5cclxuICBhZGRGaWx0ZXIoZmlsdGVyRGF0YT86IHtcclxuICAgIHNlbGVjdEZpbHRlcjogRHJvcGRvd25JdGVtIHwgbnVsbDtcclxuICAgIHR5cGVGaWx0ZXI/OiBzdHJpbmc7XHJcbiAgICBzZWxlY3RJdGVtPzogRmlsdGVyU2VsZWN0SXRlbVtdO1xyXG4gICAgaW5pdGlhbERhdGU/OiBzdHJpbmc7XHJcbiAgICBmaW5hbERhdGU/OiBzdHJpbmc7XHJcbiAgfSk6IHZvaWQge1xyXG4gICAgdGhpcy5maWx0ZXJTZXJ2aWNlLmFkZEZpbHRlcihcclxuICAgICAgdGhpcy5maWx0ZXJzRm9ybSxcclxuICAgICAgdGhpcy5kYXRhLnBhZ2luYXRpb24gPT09IHRydWUsXHJcbiAgICAgIGZpbHRlckRhdGEsXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgaGFzQWN0aXZlRGF0ZUZpbHRlcigpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlclNlcnZpY2UuaGFzQWN0aXZlRGF0ZUZpbHRlcih0aGlzLmZpbHRlcnNGb3JtKTtcclxuICB9XHJcblxyXG4gIGdldEF2YWlsYWJsZUZpbHRlck9wdGlvbnMoKTogRHJvcGRvd25JdGVtW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyU2VydmljZS5nZXRBdmFpbGFibGVGaWx0ZXJPcHRpb25zKFxyXG4gICAgICB0aGlzLmRyb3Bkb3duSXRlbXMsXHJcbiAgICAgIHRoaXMuZGF0YS5wYWdpbmF0aW9uID09PSB0cnVlLFxyXG4gICAgICB0aGlzLmZpbHRlcnNGb3JtLFxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIG9uU2VsZWN0RmlsdGVyQ2hhbmdlKCk6IHZvaWQge1xyXG4gICAgY29uc3QgbGFzdEluZGV4ID0gdGhpcy5maWx0ZXJzRm9ybS5sZW5ndGggLSAxO1xyXG4gICAgY29uc3QgbGFzdEZpbHRlciA9IHRoaXMuZmlsdGVyc0Zvcm0uYXQobGFzdEluZGV4KTtcclxuICAgIGNvbnN0IHNlbGVjdGVkRmlsdGVyID0gbGFzdEZpbHRlci5nZXQoJ3NlbGVjdEZpbHRlcicpPy52YWx1ZTtcclxuXHJcbiAgICBpZiAoc2VsZWN0ZWRGaWx0ZXIpIHtcclxuICAgICAgaWYgKFxyXG4gICAgICAgIHNlbGVjdGVkRmlsdGVyLmFycmFuZ2UgPT09ICdmaWx0ZXJCeURhdGUnICYmXHJcbiAgICAgICAgdGhpcy5kYXRhLnBhZ2luYXRpb24gPT09IHRydWVcclxuICAgICAgKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuYWRkRmlsdGVyKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZW1vdmVGaWx0ZXIoaW5kZXg6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5maWx0ZXJTZXJ2aWNlLnJlbW92ZUZpbHRlcih0aGlzLmZpbHRlcnNGb3JtLCBpbmRleCk7XHJcbiAgfVxyXG5cclxuICByZW1vdmVBbGxGaWx0ZXJzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5maWx0ZXJTZXJ2aWNlLnJlbW92ZUFsbEZpbHRlcnModGhpcy5maWx0ZXJzRm9ybSk7XHJcbiAgICB0aGlzLnJlc2V0RmlsdGVyKCk7XHJcbiAgfVxyXG5cclxuICBvbkRhdGVJbnB1dChcclxuICAgIGV2ZW50OiBFdmVudCxcclxuICAgIGNvbnRyb2xOYW1lOiAnaW5pdGlhbERhdGUnIHwgJ2ZpbmFsRGF0ZScsXHJcbiAgICBmaWx0ZXJJbmRleDogbnVtYmVyLFxyXG4gICk6IHZvaWQge1xyXG4gICAgY29uc3QgZmlsdGVyR3JvdXAgPSB0aGlzLmZpbHRlcnNGb3JtLmF0KGZpbHRlckluZGV4KSBhcyBGb3JtR3JvdXA7XHJcbiAgICB0aGlzLmZpbHRlclNlcnZpY2UuYXBwbHlEYXRlTWFzayhldmVudCwgY29udHJvbE5hbWUsIGZpbHRlckdyb3VwKTtcclxuICB9XHJcblxyXG4gIG9uRGF0ZUZpbHRlckNoYW5nZSgpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmRhdGEucGFnaW5hdGlvbiA9PT0gZmFsc2UpIHtcclxuICAgICAgdGhpcy5hcnJhbmdlID0gdGhpcy5maWx0ZXJTZXJ2aWNlLmJ1aWxkQXJyYW5nZUZyb21GaWx0ZXJzKFxyXG4gICAgICAgIHRoaXMuZmlsdGVyc0Zvcm0sXHJcbiAgICAgICAgdGhpcy5zb3J0QnksXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuYXBwbHlGaWx0ZXJzVG9EYXRhU291cmNlKCk7XHJcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhcHBseUZpbHRlcnNUb0RhdGFTb3VyY2UoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuZGF0YVNvdXJjZSkgcmV0dXJuO1xyXG5cclxuICAgIGxldCBmaWx0ZXJlZEl0ZW1zID0gdGhpcy5maWx0ZXJTZXJ2aWNlLmFwcGx5Q2xpZW50U2lkZUZpbHRlcnM8VD4oXHJcbiAgICAgIFsuLi50aGlzLml0ZW1zXSxcclxuICAgICAgdGhpcy5maWx0ZXJzRm9ybSxcclxuICAgICAgdGhpcy5zb3J0QnksXHJcbiAgICApO1xyXG4gICAgdGhpcy5kYXRhU291cmNlLmRhdGEgPSBmaWx0ZXJlZEl0ZW1zO1xyXG4gICAgdGhpcy5maWx0ZXJlZEl0ZW1zID0gZmlsdGVyZWRJdGVtcztcclxuICAgIHRoaXMudG90YWxJdGVtcyA9IGZpbHRlcmVkSXRlbXMubGVuZ3RoO1xyXG5cclxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhcHBseUNsaWVudFNpZGVGaWx0ZXJzKGl0ZW1zOiBUW10pOiBUW10ge1xyXG4gICAgcmV0dXJuIHRoaXMuZmlsdGVyU2VydmljZS5hcHBseUNsaWVudFNpZGVGaWx0ZXJzPFQ+KFxyXG4gICAgICBpdGVtcyxcclxuICAgICAgdGhpcy5maWx0ZXJzRm9ybSxcclxuICAgICAgdGhpcy5zb3J0QnksXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBidWlsZEFycmFuZ2VGcm9tRmlsdGVycygpOiBBcnJhbmdlIHtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlclNlcnZpY2UuYnVpbGRBcnJhbmdlRnJvbUZpbHRlcnMoXHJcbiAgICAgIHRoaXMuZmlsdGVyc0Zvcm0sXHJcbiAgICAgIHRoaXMuc29ydEJ5LFxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIC8vIFRPT0xUSVAgTUVUSE9EUyAoZGVsZWdhZG9zIGFvIFRvb2x0aXBTZXJ2aWNlKVxyXG5cclxuICBnZXRUb29sdGlwU3R5bGVzKCk6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0ge1xyXG4gICAgcmV0dXJuIHRoaXMudG9vbHRpcFNlcnZpY2UuZ2V0VG9vbHRpcFN0eWxlcyh0aGlzLnRvb2x0aXBTdGF0ZSk7XHJcbiAgfVxyXG5cclxuICBvbkNlbGxNb3VzZUVudGVyKGV2ZW50OiBNb3VzZUV2ZW50LCByb3c6IFQsIGNvbDogQ29sdW1uKTogdm9pZCB7XHJcbiAgICB0aGlzLnRvb2x0aXBTZXJ2aWNlLmhhbmRsZU1vdXNlRW50ZXIoXHJcbiAgICAgIGV2ZW50LFxyXG4gICAgICByb3csXHJcbiAgICAgIGNvbCxcclxuICAgICAgKGMsIHIsIHcpID0+IHRoaXMuZ2V0RGlzcGxheVZhbHVlKGMsIHIsIHcpLFxyXG4gICAgICAoc3RhdGUpID0+IHtcclxuICAgICAgICB0aGlzLnRvb2x0aXBTdGF0ZSA9IHsgLi4udGhpcy50b29sdGlwU3RhdGUsIC4uLnN0YXRlIH07XHJcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgIH0sXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgb25DZWxsTW91c2VMZWF2ZSgpOiB2b2lkIHtcclxuICAgIHRoaXMudG9vbHRpcFNlcnZpY2UuaGFuZGxlTW91c2VMZWF2ZSgoc3RhdGUpID0+IHtcclxuICAgICAgdGhpcy50b29sdGlwU3RhdGUgPSBzdGF0ZTtcclxuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uQ2VsbE1vdXNlTW92ZShldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xyXG4gICAgdGhpcy50b29sdGlwU2VydmljZS5oYW5kbGVNb3VzZU1vdmUoXHJcbiAgICAgIGV2ZW50LFxyXG4gICAgICB0aGlzLnRvb2x0aXBTdGF0ZS5zaG93VG9vbHRpcCxcclxuICAgICAgKHBvc2l0aW9uKSA9PiB7XHJcbiAgICAgICAgdGhpcy50b29sdGlwU3RhdGUgPSB7IC4uLnRoaXMudG9vbHRpcFN0YXRlLCB0b29sdGlwUG9zaXRpb246IHBvc2l0aW9uIH07XHJcbiAgICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICAgIH0sXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLy8gVEFCIE1FVEhPRFNcclxuXHJcbiAgb25UYWJTZWxlY3RlZChldmVudDogeyB0YWI6IFRhYkRhdGE7IGluZGV4OiBudW1iZXIgfSk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmRhdGEudGFicz8ubWV0aG9kKSByZXR1cm47XHJcbiAgICB0aGlzLnNlbGVjdGVkVGFiID0gZXZlbnQuaW5kZXg7XHJcbiAgICB0aGlzLmRhdGEudGFicy5tZXRob2QoZXZlbnQudGFiLCBldmVudC5pbmRleCk7XHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIC8vIFVUSUxJVFkgTUVUSE9EUyAoZGVsZWdhZG9zIGFvcyB1dGlscylcclxuXHJcbiAgZ2V0RGlzcGxheVZhbHVlKGNvbDogQ29sdW1uLCByb3c6IFQsIHdpdGhpbkxpbWl0OiBib29sZWFuID0gZmFsc2UpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGdldERpc3BsYXlWYWx1ZShjb2wsIHJvdywgd2l0aGluTGltaXQpO1xyXG4gIH1cclxuXHJcbiAgZ2V0TmVzdGVkVmFsdWUob2JqOiB1bmtub3duLCBwYXRoOiBzdHJpbmcpOiB1bmtub3duIHtcclxuICAgIHJldHVybiBnZXROZXN0ZWRWYWx1ZShvYmosIHBhdGgpO1xyXG4gIH1cclxuXHJcbiAgaXNTdHJpbmcodmFsdWU6IHVua25vd24pOiBib29sZWFuIHtcclxuICAgIHJldHVybiBpc1N0cmluZyh2YWx1ZSk7XHJcbiAgfVxyXG5cclxuICB0cmFja0J5UHJvcGVydHkoX2luZGV4OiBudW1iZXIsIGNvbDogQ29sdW1uKTogc3RyaW5nIHtcclxuICAgIHJldHVybiB0cmFja0J5UHJvcGVydHkoX2luZGV4LCBjb2wpO1xyXG4gIH1cclxuXHJcbiAgLy8gSU1BR0UgTE9BRElORyBNRVRIT0RTXHJcblxyXG4gIHByaXZhdGUgZ2V0SW1hZ2VLZXkocm93OiBULCBjb2w6IENvbHVtbik6IHN0cmluZyB7XHJcbiAgICByZXR1cm4gZ2V0SW1hZ2VLZXkocm93LCBjb2wpO1xyXG4gIH1cclxuXHJcbiAgaXNJbWFnZUxvYWRpbmcocm93OiBULCBjb2w6IENvbHVtbik6IGJvb2xlYW4ge1xyXG4gICAgY29uc3Qga2V5ID0gdGhpcy5nZXRJbWFnZUtleShyb3csIGNvbCk7XHJcbiAgICByZXR1cm4gIXRoaXMuaW1hZ2VMb2FkaW5nU3RhdGUuaGFzKGtleSk7XHJcbiAgfVxyXG5cclxuICBvbkltYWdlTG9hZChyb3c6IFQsIGNvbDogQ29sdW1uKTogdm9pZCB7XHJcbiAgICBjb25zdCBrZXkgPSB0aGlzLmdldEltYWdlS2V5KHJvdywgY29sKTtcclxuICAgIHRoaXMuaW1hZ2VMb2FkaW5nU3RhdGUuc2V0KGtleSwgdHJ1ZSk7XHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIG9uSW1hZ2VFcnJvcihldmVudDogRXZlbnQsIHJvdzogVCwgY29sOiBDb2x1bW4sIGRlZmF1bHRJbWFnZT86IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3Qga2V5ID0gdGhpcy5nZXRJbWFnZUtleShyb3csIGNvbCk7XHJcbiAgICB0aGlzLmltYWdlTG9hZGluZ1N0YXRlLnNldChrZXksIHRydWUpO1xyXG5cclxuICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW1hZ2VFbGVtZW50O1xyXG4gICAgaWYgKHRhcmdldCkge1xyXG4gICAgICBpZiAoZGVmYXVsdEltYWdlKSB7XHJcbiAgICAgICAgdGFyZ2V0LnNyYyA9IGRlZmF1bHRJbWFnZTtcclxuICAgICAgICB0YXJnZXQub25lcnJvciA9IG51bGw7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGFyZ2V0LnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIC8vIExJRkVDWUNMRSBNRVRIT0RTXHJcblxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgIGlmIChjaGFuZ2VzWydkYXRhJ10pIHtcclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmFwcGx5Q3VzdG9tQ29sb3JzKCksIDApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5hcHBseUN1c3RvbUNvbG9ycygpO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICB0aGlzLnRvb2x0aXBTZXJ2aWNlLmRlc3Ryb3koKTtcclxuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xyXG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhcHBseUN1c3RvbUNvbG9ycygpOiB2b2lkIHtcclxuICAgIGNvbnN0IGhvc3RFbGVtZW50ID0gdGhpcy5lbD8ubmF0aXZlRWxlbWVudDtcclxuICAgIGlmICghaG9zdEVsZW1lbnQgfHwgIXRoaXMuZGF0YSkgcmV0dXJuO1xyXG5cclxuICAgIGlmICh0aGlzLmRhdGEuY29sb3I/LmJnKSB7XHJcbiAgICAgIGhvc3RFbGVtZW50LnN0eWxlLnNldFByb3BlcnR5KCctLXRhYmxlLWNvbG9yJywgdGhpcy5kYXRhLmNvbG9yLmJnKTtcclxuICAgICAgaG9zdEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoJy0tdGFibGUtaGVhZGVyLWJnJywgdGhpcy5kYXRhLmNvbG9yLmJnKTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmRhdGEuY29sb3I/LnRleHQpIHtcclxuICAgICAgaG9zdEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoJy0tdGFibGUtdGV4dC1jb2xvcicsIHRoaXMuZGF0YS5jb2xvci50ZXh0KTtcclxuICAgICAgaG9zdEVsZW1lbnQuc3R5bGUuc2V0UHJvcGVydHkoXHJcbiAgICAgICAgJy0tdGFibGUtaGVhZGVyLXRleHQnLFxyXG4gICAgICAgIHRoaXMuZGF0YS5jb2xvci50ZXh0LFxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICBjb25zdCBoZWFkZXJDZWxscyA9IGhvc3RFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoXHJcbiAgICAgICAgJy5tYXQtaGVhZGVyLWNlbGwsIC5tYXQtbWRjLWhlYWRlci1jZWxsLCB0aC5tYXQtaGVhZGVyLWNlbGwsIHRoLm1hdC1tZGMtaGVhZGVyLWNlbGwnLFxyXG4gICAgICApO1xyXG4gICAgICBoZWFkZXJDZWxscy5mb3JFYWNoKChjZWxsOiBIVE1MRWxlbWVudCkgPT4ge1xyXG4gICAgICAgIGlmICh0aGlzLmRhdGEuY29sb3I/LmJnKSB7XHJcbiAgICAgICAgICBjZWxsLnN0eWxlLmJhY2tncm91bmRDb2xvciA9IHRoaXMuZGF0YS5jb2xvci5iZztcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHRoaXMuZGF0YS5jb2xvcj8udGV4dCkge1xyXG4gICAgICAgICAgY2VsbC5zdHlsZS5jb2xvciA9IHRoaXMuZGF0YS5jb2xvci50ZXh0O1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9LCAxMDApO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIGFzeW5jIG5nT25Jbml0KCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgaWYgKCF0aGlzLmRhdGEuY29sb3IpIHtcclxuICAgICAgdGhpcy5kYXRhLmNvbG9yID0ge1xyXG4gICAgICAgIGJnOiBUQUJMRV9ERUZBVUxUUy5ERUZBVUxUX0JHX0NPTE9SLFxyXG4gICAgICAgIHRleHQ6IFRBQkxFX0RFRkFVTFRTLkRFRkFVTFRfVEVYVF9DT0xPUixcclxuICAgICAgfTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmRhdGEuc2hvd1NpbXBsZVNlYXJjaCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgIHRoaXMuZGF0YS5zaG93U2ltcGxlU2VhcmNoID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNvbHVtblByb3BlcnRpZXMgPSB0aGlzLmRhdGEuZGlzcGxheWVkQ29sdW1ucy5tYXAoXHJcbiAgICAgIChjb2x1bW4pID0+IGNvbHVtbi5wcm9wZXJ0eSxcclxuICAgICk7XHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuXHJcbiAgICBpZiAodGhpcy5kYXRhLmFjdGlvbkJ1dHRvbiAmJiAhdGhpcy5kYXRhLmFjdGlvbkJ1dHRvbi5jb25kaXRpb24pIHtcclxuICAgICAgdGhpcy5kYXRhLmFjdGlvbkJ1dHRvbi5jb25kaXRpb24gPSAoX3Jvdz86IFQpID0+IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gSW5pY2lhbGl6YXIgZHJvcGRvd25JdGVtcyB1c2FuZG8gRmlsdGVyU2VydmljZVxyXG4gICAgY29uc3QgZmlsdGVyQ29uZmlnID0gdGhpcy5maWx0ZXJTZXJ2aWNlLmluaXRpYWxpemVEcm9wZG93bkl0ZW1zKFxyXG4gICAgICB0aGlzLmRhdGEuZGlzcGxheWVkQ29sdW1ucyxcclxuICAgICk7XHJcbiAgICB0aGlzLmRyb3Bkb3duSXRlbXMgPSBmaWx0ZXJDb25maWcuZHJvcGRvd25JdGVtcztcclxuICAgIHRoaXMuc29ydGFibGVEcm9wZG93bkl0ZW1zID0gZmlsdGVyQ29uZmlnLnNvcnRhYmxlRHJvcGRvd25JdGVtcztcclxuICAgIHRoaXMuaGFzRmlsdGVyYWJsZUNvbHVtbiA9IGZpbHRlckNvbmZpZy5oYXNGaWx0ZXJhYmxlQ29sdW1uO1xyXG4gICAgdGhpcy5oYXNTb3J0YWJsZUNvbHVtbiA9IGZpbHRlckNvbmZpZy5oYXNTb3J0YWJsZUNvbHVtbjtcclxuXHJcbiAgICBpZiAodGhpcy5kYXRhLmZpbHRlcmFibGVPcHRpb25zKSB7XHJcbiAgICAgIHRoaXMuZHJvcGRvd25JdGVtcyA9IHRoaXMuZmlsdGVyU2VydmljZS5hZGRGaWx0ZXJhYmxlT3B0aW9ucyhcclxuICAgICAgICB0aGlzLmRyb3Bkb3duSXRlbXMsXHJcbiAgICAgICAgdGhpcy5kYXRhLmZpbHRlcmFibGVPcHRpb25zLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFNlbSBwYWdpbmHDp8Ojb1xyXG4gICAgaWYgKHRoaXMuZGF0YS5wYWdpbmF0aW9uID09PSBmYWxzZSkge1xyXG4gICAgICBhd2FpdCB0aGlzLmxvYWRJdGVtcygpO1xyXG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDb20gcGFnaW5hw6fDo29cclxuICAgIGlmICh0aGlzLmRhdGEucGFnaW5hdGlvbiA9PT0gdHJ1ZSkge1xyXG4gICAgICBpZiAodGhpcy5kYXRhLnNvcnRCeSkge1xyXG4gICAgICAgIHRoaXMuc29ydEJ5ID0ge1xyXG4gICAgICAgICAgZmllbGQ6IHRoaXMuZGF0YS5zb3J0QnkuZmllbGQsXHJcbiAgICAgICAgICBvcmRlcjogdGhpcy5kYXRhLnNvcnRCeS5vcmRlcixcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICAgIHRoaXMuZmlsdGVyU3ViamVjdFxyXG4gICAgICAgIC5waXBlKGRlYm91bmNlVGltZSh0aGlzLmRlYm91bmNlVGltZU1zKSwgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxyXG4gICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5sb2FkSXRlbXNQYWdpbmF0ZWQoJ3JlbG9hZCcsIHRydWUpO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgdGhpcy5pc0xvYWRpbmckLm5leHQodHJ1ZSk7XHJcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgICBhd2FpdCB0aGlzLmxvYWRJdGVtc1BhZ2luYXRlZCgncmVsb2FkJywgdHJ1ZSk7XHJcblxyXG4gICAgICB0aGlzLnNvcnQuYWN0aXZlID0gJ2NyZWF0ZWRBdCc7XHJcbiAgICAgIHRoaXMuc29ydC5kaXJlY3Rpb24gPSAnZGVzYyc7XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5wYWdpbmF0b3IgPSB0aGlzLnBhZ2luYXRvcjtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLnNvcnQgPSB0aGlzLnNvcnQ7XHJcbiAgICAgIHRoaXMudG90YWxJdGVtcyA9IDA7XHJcbiAgICAgIGlmICh0aGlzLmRhdGEudG90YWxSZWYpIHtcclxuICAgICAgICBmb3IgKGNvbnN0IHRvdGFsUmVmIG9mIHRoaXMuZGF0YS50b3RhbFJlZikge1xyXG4gICAgICAgICAgY29uc3QgdG90YWxSZWZEb2MgPSBhd2FpdCB0b3RhbFJlZi5yZWYuZ2V0KCk7XHJcbiAgICAgICAgICBjb25zdCBkb2NEYXRhID0gdG90YWxSZWZEb2MuZGF0YSgpIGFzXHJcbiAgICAgICAgICAgIHwgUmVjb3JkPHN0cmluZywgdW5rbm93bj5cclxuICAgICAgICAgICAgfCB1bmRlZmluZWQ7XHJcbiAgICAgICAgICBpZiAoZG9jRGF0YSAmJiBkb2NEYXRhW3RvdGFsUmVmLmZpZWxkXSkge1xyXG4gICAgICAgICAgICBjb25zdCBmaWVsZFZhbHVlID0gZG9jRGF0YVt0b3RhbFJlZi5maWVsZF07XHJcbiAgICAgICAgICAgIHRoaXMudG90YWxJdGVtcyA9ICh0aGlzLnRvdGFsSXRlbXMgK1xyXG4gICAgICAgICAgICAgICh0eXBlb2YgZmllbGRWYWx1ZSA9PT0gJ251bWJlcicgPyBmaWVsZFZhbHVlIDogMCkpIGFzIG51bWJlcjtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5pc0xvYWRpbmckLm5leHQoZmFsc2UpO1xyXG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIERBVEEgTE9BRElORyBNRVRIT0RTXHJcblxyXG4gIHByaXZhdGUgYXN5bmMgbG9hZEl0ZW1zKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgdGhpcy5pbWFnZUxvYWRpbmdTdGF0ZS5jbGVhcigpO1xyXG4gICAgdGhpcy5pdGVtcyA9IChhd2FpdCB0aGlzLnRhYmxlU2VydmljZS5nZXRJdGVtcyhcclxuICAgICAgdGhpcy5kYXRhLmNvbGxlY3Rpb25SZWYsXHJcbiAgICApKSBhcyBUW107XHJcbiAgICBpZiAodGhpcy5kYXRhLmNvbmRpdGlvbnMpIHtcclxuICAgICAgdGhpcy5maWx0ZXJJdGVtcygpO1xyXG4gICAgfVxyXG4gICAgYXdhaXQgdGhpcy5sb2FkUmVsYXRpb25zKCk7XHJcbiAgICBhd2FpdCB0aGlzLmxvYWRRdWVyeUxlbmd0aHMoKTtcclxuICAgIHRoaXMudG90YWxJdGVtcyA9IHRoaXMuaXRlbXMubGVuZ3RoO1xyXG5cclxuICAgIHRoaXMuYXJyYW5nZSA9IHtcclxuICAgICAgZmlsdGVyczogW10sXHJcbiAgICAgIHNvcnRCeTogdGhpcy5kYXRhLnNvcnRCeSB8fCB7XHJcbiAgICAgICAgZmllbGQ6IFRBQkxFX0RFRkFVTFRTLlNPUlRfRklFTEQsXHJcbiAgICAgICAgb3JkZXI6IFRBQkxFX0RFRkFVTFRTLlNPUlRfT1JERVIsXHJcbiAgICAgIH0sXHJcbiAgICB9O1xyXG4gICAgdGhpcy5zb3J0QnkgPSB0aGlzLmRhdGEuc29ydEJ5IHx8IHtcclxuICAgICAgZmllbGQ6IFRBQkxFX0RFRkFVTFRTLlNPUlRfRklFTEQsXHJcbiAgICAgIG9yZGVyOiBUQUJMRV9ERUZBVUxUUy5TT1JUX09SREVSLFxyXG4gICAgfTtcclxuXHJcbiAgICBsZXQgaXRlbXNUb0Rpc3BsYXkgPSBbLi4udGhpcy5pdGVtc107XHJcbiAgICBpdGVtc1RvRGlzcGxheSA9IHRoaXMuYXBwbHlDbGllbnRTaWRlRmlsdGVycyhpdGVtc1RvRGlzcGxheSk7XHJcbiAgICB0aGlzLmZpbHRlcmVkSXRlbXMgPSBpdGVtc1RvRGlzcGxheTtcclxuXHJcbiAgICB0aGlzLmRhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlKGl0ZW1zVG9EaXNwbGF5KTtcclxuICAgIHRoaXMuZGF0YVNvdXJjZS5wYWdpbmF0b3IgPSB0aGlzLnBhZ2luYXRvcjtcclxuICAgIHRoaXMuZGF0YVNvdXJjZS5zb3J0ID0gdGhpcy5zb3J0O1xyXG4gICAgaWYgKHRoaXMuZGF0YS5zb3J0QnkpIHtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLnNvcnQuYWN0aXZlID0gdGhpcy5kYXRhLnNvcnRCeS5maWVsZDtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLnNvcnQuZGlyZWN0aW9uID0gdGhpcy5kYXRhLnNvcnRCeS5vcmRlcjtcclxuICAgICAgdGhpcy5kYXRhU291cmNlLnNvcnQuc29ydENoYW5nZS5lbWl0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5kYXRhU291cmNlLmZpbHRlclByZWRpY2F0ZSA9IChkYXRhLCBmaWx0ZXI6IHN0cmluZykgPT4ge1xyXG4gICAgICBjb25zdCBpdGVtID0gZGF0YSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcclxuICAgICAgcmV0dXJuIHRoaXMuZGF0YS5kaXNwbGF5ZWRDb2x1bW5zLnNvbWUoKGNvbCk6IGJvb2xlYW4gPT4ge1xyXG4gICAgICAgIGlmIChjb2wuZmlsdGVyUHJlZGljYXRlcykge1xyXG4gICAgICAgICAgcmV0dXJuIGNvbC5maWx0ZXJQcmVkaWNhdGVzLnNvbWUoKHByZWRpY2F0ZSk6IGJvb2xlYW4gPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9wZXJ0eVZhbHVlID0gaXRlbVtjb2wucHJvcGVydHldO1xyXG4gICAgICAgICAgICBpZiAoIXByb3BlcnR5VmFsdWUgfHwgdHlwZW9mIHByb3BlcnR5VmFsdWUgIT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBwcm9wZXJ0eVJlY29yZCA9IHByb3BlcnR5VmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XHJcbiAgICAgICAgICAgIGNvbnN0IHByZWRpY2F0ZVZhbHVlID0gcHJvcGVydHlSZWNvcmRbcHJlZGljYXRlXTtcclxuICAgICAgICAgICAgaWYgKHByZWRpY2F0ZVZhbHVlID09PSBudWxsIHx8IHByZWRpY2F0ZVZhbHVlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiBTdHJpbmcocHJlZGljYXRlVmFsdWUpXHJcbiAgICAgICAgICAgICAgLnRyaW0oKVxyXG4gICAgICAgICAgICAgIC50b0xvY2FsZUxvd2VyQ2FzZSgpXHJcbiAgICAgICAgICAgICAgLmluY2x1ZGVzKGZpbHRlcik7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChjb2wucHJvcGVydHkgJiYgY29sLmlzRmlsdGVyYWJsZSkge1xyXG4gICAgICAgICAgY29uc3QgcHJvcGVydHlWYWx1ZSA9IGl0ZW1bY29sLnByb3BlcnR5XTtcclxuICAgICAgICAgIGlmIChwcm9wZXJ0eVZhbHVlID09PSBudWxsIHx8IHByb3BlcnR5VmFsdWUgPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgcmV0dXJuIFN0cmluZyhwcm9wZXJ0eVZhbHVlKVxyXG4gICAgICAgICAgICAudHJpbSgpXHJcbiAgICAgICAgICAgIC50b0xvY2FsZUxvd2VyQ2FzZSgpXHJcbiAgICAgICAgICAgIC5pbmNsdWRlcyhmaWx0ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgIH0pO1xyXG4gICAgfTtcclxuICAgIHRoaXMuZmlsdGVyUHJlZGljYXRlID0gdGhpcy5kYXRhU291cmNlLmZpbHRlclByZWRpY2F0ZTtcclxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBsb2FkSXRlbXNQYWdpbmF0ZWQoXHJcbiAgICBuYXZpZ2F0aW9uOiAncmVsb2FkJyB8ICdmb3J3YXJkJyB8ICdiYWNrd2FyZCcgPSAncmVsb2FkJyxcclxuICAgIHJlc2V0OiBib29sZWFuID0gZmFsc2UsXHJcbiAgKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICB0aGlzLmltYWdlTG9hZGluZ1N0YXRlLmNsZWFyKCk7XHJcbiAgICBpZiAocmVzZXQgJiYgWydmb3J3YXJkJywgJ3JlbG9hZCddLmluY2x1ZGVzKG5hdmlnYXRpb24pKSB7XHJcbiAgICAgIHRoaXMubGFzdERvYyA9IG51bGw7XHJcbiAgICAgIHRoaXMuY3VycmVudENsaWVudFBhZ2VJbmRleCA9IDA7XHJcbiAgICB9XHJcbiAgICBpZiAocmVzZXQgJiYgWydiYWNrd2FyZCcsICdyZWxvYWQnXS5pbmNsdWRlcyhuYXZpZ2F0aW9uKSkge1xyXG4gICAgICB0aGlzLmZpcnN0RG9jID0gbnVsbDtcclxuICAgICAgdGhpcy5jdXJyZW50Q2xpZW50UGFnZUluZGV4ID0gMDtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBhY3RpdmVGaWx0ZXJzID0gdGhpcy5maWx0ZXJTZXJ2aWNlLmV4dHJhY3RBY3RpdmVGaWx0ZXJzKFxyXG4gICAgICB0aGlzLmZpbHRlcnNGb3JtLFxyXG4gICAgKTtcclxuXHJcbiAgICB0aGlzLmFycmFuZ2UgPSB7XHJcbiAgICAgIGZpbHRlcnM6IGFjdGl2ZUZpbHRlcnMsXHJcbiAgICAgIHNvcnRCeTogdGhpcy5zb3J0QnksXHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IHBhZ2luYXRlZDogUGFnaW5hdGlvbiA9IHtcclxuICAgICAgYmF0Y2hTaXplOiB0aGlzLnBhZ2VTaXplLFxyXG4gICAgICBjb2xsZWN0aW9uOiB0aGlzLmRhdGEuY29sbGVjdGlvbixcclxuICAgICAgZG9jOiB7IGxhc3REb2M6IHRoaXMubGFzdERvYywgZmlyc3REb2M6IHRoaXMuZmlyc3REb2MgfSxcclxuICAgICAgbmF2aWdhdGlvbixcclxuICAgICAgYXJyYW5nZTogdGhpcy5hcnJhbmdlISxcclxuICAgICAgY29uZGl0aW9uczogdGhpcy5kYXRhLmNvbmRpdGlvbnMsXHJcbiAgICAgIHNpemU6IHRoaXMudG90YWxJdGVtcyxcclxuICAgICAgZmlsdGVyRm46IHRoaXMuZGF0YS5maWx0ZXJGbixcclxuICAgICAgY2xpZW50UGFnZUluZGV4OiB0aGlzLmN1cnJlbnRDbGllbnRQYWdlSW5kZXgsXHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMudGFibGVTZXJ2aWNlLmdldFBhZ2luYXRlZChwYWdpbmF0ZWQpO1xyXG4gICAgdGhpcy5pdGVtcyA9IHJlc3VsdC5pdGVtcyBhcyBUW107XHJcbiAgICBhd2FpdCB0aGlzLmxvYWRSZWxhdGlvbnMoKTtcclxuICAgIGF3YWl0IHRoaXMubG9hZFF1ZXJ5TGVuZ3RocygpO1xyXG4gICAgdGhpcy5sYXN0RG9jID0gcmVzdWx0Lmxhc3REb2MgYXMgUXVlcnlEb2N1bWVudFNuYXBzaG90PFQ+IHwgbnVsbDtcclxuICAgIHRoaXMuZmlyc3REb2MgPSByZXN1bHQuZmlyc3REb2MgYXMgUXVlcnlEb2N1bWVudFNuYXBzaG90PFQ+IHwgbnVsbDtcclxuXHJcbiAgICBpZiAocmVzdWx0LmN1cnJlbnRDbGllbnRQYWdlSW5kZXggIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLmN1cnJlbnRDbGllbnRQYWdlSW5kZXggPSByZXN1bHQuY3VycmVudENsaWVudFBhZ2VJbmRleDtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgc3VtID0gMDtcclxuICAgIGlmICh0aGlzLmRhdGEudG90YWxSZWYpIHtcclxuICAgICAgZm9yIChjb25zdCB0b3RhbFJlZiBvZiB0aGlzLmRhdGEudG90YWxSZWYpIHtcclxuICAgICAgICBjb25zdCB0b3RhbFJlZkRvYyA9IGF3YWl0IHRvdGFsUmVmLnJlZi5nZXQoKTtcclxuICAgICAgICBjb25zdCBkb2NEYXRhID0gdG90YWxSZWZEb2MuZGF0YSgpIGFzXHJcbiAgICAgICAgICB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+XHJcbiAgICAgICAgICB8IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAoZG9jRGF0YSB8fCByZXN1bHQuZmlsdGVyTGVuZ3RoKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWVsZFZhbHVlID0gZG9jRGF0YSA/IGRvY0RhdGFbdG90YWxSZWYuZmllbGRdIDogdW5kZWZpbmVkO1xyXG4gICAgICAgICAgY29uc3QgbnVtZXJpY1ZhbHVlID0gdHlwZW9mIGZpZWxkVmFsdWUgPT09ICdudW1iZXInID8gZmllbGRWYWx1ZSA6IDA7XHJcbiAgICAgICAgICBzdW0gPSByZXN1bHQuZmlsdGVyTGVuZ3RoID8/ICgoc3VtICsgbnVtZXJpY1ZhbHVlKSBhcyBudW1iZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICB0aGlzLnRvdGFsSXRlbXMgPSBzdW07XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5oYXNOZXh0UGFnZSA9IHJlc3VsdC5oYXNOZXh0UGFnZTtcclxuICAgIHRoaXMuZGF0YVNvdXJjZSA9IG5ldyBNYXRUYWJsZURhdGFTb3VyY2UodGhpcy5pdGVtcyk7XHJcbiAgICB0aGlzLmZpbHRlclByZWRpY2F0ZSA9IHRoaXMuZGF0YVNvdXJjZS5maWx0ZXJQcmVkaWNhdGU7XHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIC8vIFBBR0lOQVRJT04gTUVUSE9EU1xyXG5cclxuICBhc3luYyBvblBhZ2VDaGFuZ2UoZXZlbnQ/OiBQYWdlRXZlbnQpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICh0aGlzLmRhdGEucGFnaW5hdGlvbiAhPT0gdHJ1ZSB8fCAhZXZlbnQpIHJldHVybjtcclxuXHJcbiAgICB0aGlzLmlzTG9hZGluZyQubmV4dCh0cnVlKTtcclxuXHJcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB7XHJcbiAgICAgIGN1cnJlbnRQYWdlTnVtYmVyOiB0aGlzLmN1cnJlbnRQYWdlTnVtYmVyLFxyXG4gICAgICBjdXJyZW50Q2xpZW50UGFnZUluZGV4OiB0aGlzLmN1cnJlbnRDbGllbnRQYWdlSW5kZXgsXHJcbiAgICAgIHBhZ2VTaXplOiB0aGlzLnBhZ2VTaXplLFxyXG4gICAgICB0b3RhbEl0ZW1zOiB0aGlzLnRvdGFsSXRlbXMsXHJcbiAgICAgIGhhc05leHRQYWdlOiB0aGlzLmhhc05leHRQYWdlLFxyXG4gICAgfTtcclxuXHJcbiAgICBjb25zdCBuYXZpZ2F0aW9uID0gdGhpcy5wYWdpbmF0aW9uU2VydmljZS5jYWxjdWxhdGVOYXZpZ2F0aW9uKFxyXG4gICAgICBldmVudCxcclxuICAgICAgY3VycmVudFN0YXRlLFxyXG4gICAgKTtcclxuXHJcbiAgICBpZiAoIW5hdmlnYXRpb24uc2hvdWxkTmF2aWdhdGUpIHtcclxuICAgICAgdGhpcy5pc0xvYWRpbmckLm5leHQoZmFsc2UpO1xyXG4gICAgICB0aGlzLnBhZ2VFdmVudCA9IGV2ZW50O1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQXR1YWxpemFyIGVzdGFkbyBsb2NhbFxyXG4gICAgdGhpcy5jdXJyZW50Q2xpZW50UGFnZUluZGV4ID0gbmF2aWdhdGlvbi5uZXdDbGllbnRQYWdlSW5kZXg7XHJcbiAgICB0aGlzLmN1cnJlbnRQYWdlTnVtYmVyID0gbmF2aWdhdGlvbi5uZXdQYWdlTnVtYmVyO1xyXG5cclxuICAgIC8vIEF0dWFsaXphciBwYWdlU2l6ZSBzZSBtdWRvdVxyXG4gICAgaWYgKGV2ZW50LnBhZ2VTaXplICE9PSB0aGlzLnBhZ2VTaXplKSB7XHJcbiAgICAgIHRoaXMucGFnZVNpemUgPSBldmVudC5wYWdlU2l6ZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBanVzdGFyIHBhZ2VTaXplIHRlbXBvcmFyaWFtZW50ZSBwYXJhIMO6bHRpbWEgcMOhZ2luYSBzZSBuZWNlc3PDoXJpb1xyXG4gICAgY29uc3QgbGFzdFBhZ2VJbmRleCA9IHRoaXMucGFnaW5hdGlvblNlcnZpY2UuY2FsY3VsYXRlTGFzdFBhZ2VJbmRleChcclxuICAgICAgdGhpcy50b3RhbEl0ZW1zLFxyXG4gICAgICBldmVudC5wYWdlU2l6ZSxcclxuICAgICk7XHJcbiAgICBsZXQgb3JpZ2luYWxQYWdlU2l6ZTogbnVtYmVyIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gICAgaWYgKFxyXG4gICAgICBldmVudC5wYWdlSW5kZXggPT09IGxhc3RQYWdlSW5kZXggJiZcclxuICAgICAgbmF2aWdhdGlvbi5kaXJlY3Rpb24gPT09ICdiYWNrd2FyZCcgJiZcclxuICAgICAgbmF2aWdhdGlvbi5yZXNldERvY3NcclxuICAgICkge1xyXG4gICAgICBjb25zdCBpdGVtc0V4cGVjdGVkSW5MYXN0UGFnZSA9XHJcbiAgICAgICAgdGhpcy5wYWdpbmF0aW9uU2VydmljZS5jYWxjdWxhdGVMYXN0UGFnZUl0ZW1Db3VudChcclxuICAgICAgICAgIHRoaXMudG90YWxJdGVtcyxcclxuICAgICAgICAgIGV2ZW50LnBhZ2VTaXplLFxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgaXRlbXNFeHBlY3RlZEluTGFzdFBhZ2UgPiAwICYmXHJcbiAgICAgICAgaXRlbXNFeHBlY3RlZEluTGFzdFBhZ2UgPCBldmVudC5wYWdlU2l6ZVxyXG4gICAgICApIHtcclxuICAgICAgICBvcmlnaW5hbFBhZ2VTaXplID0gdGhpcy5wYWdlU2l6ZTtcclxuICAgICAgICB0aGlzLnBhZ2VTaXplID0gaXRlbXNFeHBlY3RlZEluTGFzdFBhZ2U7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0cnkge1xyXG4gICAgICBhd2FpdCB0aGlzLmxvYWRJdGVtc1BhZ2luYXRlZChuYXZpZ2F0aW9uLmRpcmVjdGlvbiwgbmF2aWdhdGlvbi5yZXNldERvY3MpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignRXJybyBhbyBjYXJyZWdhciBpdGVucyBwYWdpbmFkb3M6JywgZXJyb3IpO1xyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgaWYgKG9yaWdpbmFsUGFnZVNpemUgIT09IG51bGwpIHtcclxuICAgICAgICB0aGlzLnBhZ2VTaXplID0gb3JpZ2luYWxQYWdlU2l6ZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMucGFnZUV2ZW50ID0gZXZlbnQ7XHJcbiAgICB0aGlzLmlzTG9hZGluZyQubmV4dChmYWxzZSk7XHJcbiAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIC8vIEZJTFRFUi9TRUFSQ0ggTUVUSE9EU1xyXG5cclxuICBhcHBseUZpbHRlcih2YWx1ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5kYXRhLnBhZ2luYXRpb24gPT09IGZhbHNlKSB7XHJcbiAgICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIgPSBTdHJpbmcodmFsdWUpLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuZGF0YS5wYWdpbmF0aW9uID09PSB0cnVlKSB7XHJcbiAgICAgIHRoaXMuZmlsdGVyVmFsdWUgPSB2YWx1ZTtcclxuICAgICAgdGhpcy5maWx0ZXJTdWJqZWN0Lm5leHQodGhpcy5maWx0ZXJWYWx1ZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBzZWFyY2goZXZlbnQ/OiBFdmVudCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgaWYgKGV2ZW50KSB7XHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnNlbGVjdFNvcnQudmFsdWUpIHtcclxuICAgICAgaWYgKHRoaXMuc2VsZWN0U29ydC52YWx1ZS5hcnJhbmdlID09PSAnYXNjZW5kaW5nJykge1xyXG4gICAgICAgIHRoaXMuc29ydEJ5ID0ge1xyXG4gICAgICAgICAgZmllbGQ6IHRoaXMuc2VsZWN0U29ydC52YWx1ZS5wcm9wZXJ0eSxcclxuICAgICAgICAgIG9yZGVyOiAnYXNjJyxcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICAgIGlmICh0aGlzLnNlbGVjdFNvcnQudmFsdWUuYXJyYW5nZSA9PT0gJ2Rlc2NlbmRpbmcnKSB7XHJcbiAgICAgICAgdGhpcy5zb3J0QnkgPSB7XHJcbiAgICAgICAgICBmaWVsZDogdGhpcy5zZWxlY3RTb3J0LnZhbHVlLnByb3BlcnR5LFxyXG4gICAgICAgICAgb3JkZXI6ICdkZXNjJyxcclxuICAgICAgICB9O1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuZGF0YS5wYWdpbmF0aW9uID09PSBmYWxzZSkge1xyXG4gICAgICB0aGlzLmFycmFuZ2UgPSB0aGlzLmJ1aWxkQXJyYW5nZUZyb21GaWx0ZXJzKCk7XHJcbiAgICAgIHRoaXMuYXBwbHlGaWx0ZXJzVG9EYXRhU291cmNlKCk7XHJcbiAgICAgIHRoaXMuY3VycmVudEFycmFuZ2UgPVxyXG4gICAgICAgIHRoaXMuZmlsdGVyc0Zvcm0ubGVuZ3RoID4gMFxyXG4gICAgICAgICAgPyAodGhpcy5maWx0ZXJzRm9ybS5hdCgwKS5nZXQoJ3NlbGVjdEZpbHRlcicpPy52YWx1ZT8uYXJyYW5nZSA/PyAnJylcclxuICAgICAgICAgIDogJyc7XHJcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgYXdhaXQgdGhpcy5sb2FkSXRlbXNQYWdpbmF0ZWQoJ3JlbG9hZCcsIHRydWUpO1xyXG4gICAgICB0aGlzLmN1cnJlbnRBcnJhbmdlID1cclxuICAgICAgICB0aGlzLmZpbHRlcnNGb3JtLmxlbmd0aCA+IDBcclxuICAgICAgICAgID8gKHRoaXMuZmlsdGVyc0Zvcm0uYXQoMCkuZ2V0KCdzZWxlY3RGaWx0ZXInKT8udmFsdWU/LmFycmFuZ2UgPz8gJycpXHJcbiAgICAgICAgICA6ICcnO1xyXG4gICAgICB0aGlzLnBhZ2luYXRvci5maXJzdFBhZ2UoKTtcclxuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyByZXNldEZpbHRlcigpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXIgPSAnJztcclxuICAgIGlmICh0aGlzLmZpbHRlclByZWRpY2F0ZSkge1xyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UuZmlsdGVyUHJlZGljYXRlID0gdGhpcy5maWx0ZXJQcmVkaWNhdGU7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5maWx0ZXJzRm9ybS5jbGVhcigpO1xyXG4gICAgdGhpcy5hZGRGaWx0ZXIoKTtcclxuICAgIHRoaXMuc2VsZWN0U29ydC5wYXRjaFZhbHVlKCcnKTtcclxuICAgIHRoaXMuc29ydEJ5ID0ge1xyXG4gICAgICBvcmRlcjogdGhpcy5kYXRhLnNvcnRCeSA/IHRoaXMuZGF0YS5zb3J0Qnkub3JkZXIgOiAnZGVzYycsXHJcbiAgICAgIGZpZWxkOiB0aGlzLmRhdGEuc29ydEJ5ID8gdGhpcy5kYXRhLnNvcnRCeS5maWVsZCA6ICdjcmVhdGVkQXQnLFxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAodGhpcy5kYXRhLnBhZ2luYXRpb24gPT09IGZhbHNlKSB7XHJcbiAgICAgIHRoaXMuYXJyYW5nZSA9IHtcclxuICAgICAgICBmaWx0ZXJzOiBbXSxcclxuICAgICAgICBzb3J0Qnk6IHRoaXMuc29ydEJ5LFxyXG4gICAgICB9O1xyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UuZGF0YSA9IFsuLi50aGlzLml0ZW1zXTtcclxuICAgICAgdGhpcy50b3RhbEl0ZW1zID0gdGhpcy5pdGVtcy5sZW5ndGg7XHJcbiAgICAgIHRoaXMuY3VycmVudEFycmFuZ2UgPSAnJztcclxuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBhd2FpdCB0aGlzLmxvYWRJdGVtc1BhZ2luYXRlZCgncmVsb2FkJywgdHJ1ZSk7XHJcbiAgICAgIHRoaXMuY3VycmVudEFycmFuZ2UgPSAnJztcclxuICAgICAgdGhpcy5wYWdpbmF0b3IuZmlyc3RQYWdlKCk7XHJcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gTkFWSUdBVElPTiBNRVRIT0RTXHJcblxyXG4gIGdvVG9EZXRhaWxzKHJvdzogVCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZGF0YS5pc05vdENsaWNrYWJsZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBjb25zdCB1cmxQYXRoID0gdGhpcy5kYXRhLnVybCB8fCB0aGlzLmRhdGEubmFtZTtcclxuICAgIGNvbnN0IHJvd1dpdGhJZCA9IHJvdyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiAmIHsgaWQ6IHN0cmluZyB9O1xyXG4gICAgY29uc3QgdXJsID0gdGhpcy5yb3V0ZXIuc2VyaWFsaXplVXJsKFxyXG4gICAgICB0aGlzLnJvdXRlci5jcmVhdGVVcmxUcmVlKFtgLyR7dXJsUGF0aH1gLCByb3dXaXRoSWQuaWRdKSxcclxuICAgICk7XHJcbiAgICB3aW5kb3cub3Blbih1cmwsICdfYmxhbmsnKTtcclxuICB9XHJcblxyXG4gIC8vIFJFTEFUSU9OIE1FVEhPRFNcclxuXHJcbiAgYXN5bmMgZ2V0UmVsYXRpb24ocGFyYW1zOiB7XHJcbiAgICBpZDogc3RyaW5nO1xyXG4gICAgY29sbGVjdGlvbjogc3RyaW5nO1xyXG4gICAgbmV3UHJvcGVydHk6IHN0cmluZztcclxuICB9KTogUHJvbWlzZTxzdHJpbmc+IHtcclxuICAgIHRyeSB7XHJcbiAgICAgIGxldCBzbmFwc2hvdDogZmlyZXN0b3JlLkRvY3VtZW50U25hcHNob3Q8dW5rbm93bj4gfCB1bmRlZmluZWQ7XHJcbiAgICAgIGlmIChcclxuICAgICAgICBwYXJhbXMuaWQgIT09ICcnICYmXHJcbiAgICAgICAgcGFyYW1zLmlkICE9PSB1bmRlZmluZWQgJiZcclxuICAgICAgICBwYXJhbXMuY29sbGVjdGlvbiAhPT0gdW5kZWZpbmVkICYmXHJcbiAgICAgICAgcGFyYW1zLmNvbGxlY3Rpb24gIT09ICcnXHJcbiAgICAgICkge1xyXG4gICAgICAgIHNuYXBzaG90ID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20oXHJcbiAgICAgICAgICB0aGlzLmZpcmVzdG9yZS5jb2xsZWN0aW9uKHBhcmFtcy5jb2xsZWN0aW9uKS5kb2MocGFyYW1zLmlkKS5nZXQoKSxcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcbiAgICAgIGlmIChzbmFwc2hvdCAmJiBzbmFwc2hvdC5leGlzdHMpIHtcclxuICAgICAgICBjb25zdCBkYXRhID0gc25hcHNob3QuZGF0YSgpIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gZGF0YT8uW3BhcmFtcy5uZXdQcm9wZXJ0eV07XHJcbiAgICAgICAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgPyB2YWx1ZSA6ICcnO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiAnJztcclxuICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgY29uc29sZS5lcnJvcihlKTtcclxuICAgICAgcmV0dXJuICcnO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBhc3luYyBsb2FkUmVsYXRpb25zKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgY29uc3QgcmVsYXRpb25Qcm9taXNlcyA9IHRoaXMuZGF0YS5kaXNwbGF5ZWRDb2x1bW5zXHJcbiAgICAgIC5maWx0ZXIoKGNvbCkgPT4gY29sLnJlbGF0aW9uKVxyXG4gICAgICAuZmxhdE1hcCgoY29sKSA9PlxyXG4gICAgICAgIHRoaXMuaXRlbXMubWFwKGFzeW5jIChpdGVtKSA9PiB7XHJcbiAgICAgICAgICBpZiAoY29sLnJlbGF0aW9uKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGl0ZW1SZWNvcmQgPSBpdGVtIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xyXG4gICAgICAgICAgICBpdGVtUmVjb3JkW2NvbC5wcm9wZXJ0eV0gPSBhd2FpdCB0aGlzLmdldFJlbGF0aW9uKHtcclxuICAgICAgICAgICAgICBpZDogU3RyaW5nKGl0ZW1SZWNvcmRbY29sLnJlbGF0aW9uLnNvdXJjZVByb3BlcnR5XSA/PyAnJyksXHJcbiAgICAgICAgICAgICAgY29sbGVjdGlvbjogY29sLnJlbGF0aW9uLnRhcmdldGVkQ29sbGVjdGlvbixcclxuICAgICAgICAgICAgICBuZXdQcm9wZXJ0eTogY29sLnJlbGF0aW9uLnRhcmdldGVkUHJvcGVydHkgfHwgY29sLnByb3BlcnR5LFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9KSxcclxuICAgICAgKTtcclxuXHJcbiAgICBhd2FpdCBQcm9taXNlLmFsbChyZWxhdGlvblByb21pc2VzKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGdldFF1ZXJ5TGVuZ3RoKHBhcmFtczoge1xyXG4gICAgaXRlbTogVDtcclxuICAgIHJlbGF0aW9uOiB7XHJcbiAgICAgIGNvbGxlY3Rpb246IHN0cmluZztcclxuICAgICAgcHJvcGVydHk6IHN0cmluZztcclxuICAgICAgb3BlcmF0b3I6IFdoZXJlRmlsdGVyT3A7XHJcbiAgICAgIHZhbHVlOiBzdHJpbmc7XHJcbiAgICB9O1xyXG4gIH0pOiBQcm9taXNlPG51bWJlcj4ge1xyXG4gICAgY29uc3QgaXRlbVJlY29yZCA9IHBhcmFtcy5pdGVtIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xyXG4gICAgY29uc3Qgc25hcHNob3QgPSBhd2FpdCB0aGlzLmZpcmVzdG9yZVxyXG4gICAgICAuY29sbGVjdGlvbihwYXJhbXMucmVsYXRpb24uY29sbGVjdGlvbilcclxuICAgICAgLnJlZi53aGVyZShcclxuICAgICAgICBwYXJhbXMucmVsYXRpb24ucHJvcGVydHksXHJcbiAgICAgICAgcGFyYW1zLnJlbGF0aW9uLm9wZXJhdG9yLFxyXG4gICAgICAgIGl0ZW1SZWNvcmRbcGFyYW1zLnJlbGF0aW9uLnZhbHVlXSxcclxuICAgICAgKVxyXG4gICAgICAuZ2V0KCk7XHJcbiAgICByZXR1cm4gc25hcHNob3Quc2l6ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXN5bmMgbG9hZFF1ZXJ5TGVuZ3RocygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGNvbnN0IGxlbmd0aFByb21pc2VzID0gdGhpcy5kYXRhLmRpc3BsYXllZENvbHVtbnNcclxuICAgICAgLmZpbHRlcigoY29sKSA9PiBjb2wucXVlcnlMZW5ndGgpXHJcbiAgICAgIC5mbGF0TWFwKChjb2wpID0+XHJcbiAgICAgICAgdGhpcy5pdGVtcy5tYXAoYXN5bmMgKGl0ZW0pID0+IHtcclxuICAgICAgICAgIGlmIChjb2wucXVlcnlMZW5ndGgpIHtcclxuICAgICAgICAgICAgY29uc3QgaXRlbVJlY29yZCA9IGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XHJcbiAgICAgICAgICAgIGl0ZW1SZWNvcmRbY29sLnByb3BlcnR5XSA9IGF3YWl0IHRoaXMuZ2V0UXVlcnlMZW5ndGgoe1xyXG4gICAgICAgICAgICAgIGl0ZW06IGl0ZW0sXHJcbiAgICAgICAgICAgICAgcmVsYXRpb246IGNvbC5xdWVyeUxlbmd0aCxcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSksXHJcbiAgICAgICk7XHJcbiAgICBhd2FpdCBQcm9taXNlLmFsbChsZW5ndGhQcm9taXNlcyk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZpbHRlckl0ZW1zKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZGF0YS5jb25kaXRpb25zKSB7XHJcbiAgICAgIHRoaXMuZGF0YS5jb25kaXRpb25zLmZvckVhY2goKGNvbmQpID0+IHtcclxuICAgICAgICB0aGlzLml0ZW1zID0gdGhpcy5pdGVtcy5maWx0ZXIoKGl0ZW0pID0+IHtcclxuICAgICAgICAgIGNvbnN0IG9wZXJhdG9yRnVuY3Rpb24gPVxyXG4gICAgICAgICAgICB0aGlzLnRhYmxlU2VydmljZS5vcGVyYXRvcnNbXHJcbiAgICAgICAgICAgICAgY29uZC5vcGVyYXRvciBhcyBrZXlvZiB0eXBlb2YgdGhpcy50YWJsZVNlcnZpY2Uub3BlcmF0b3JzXHJcbiAgICAgICAgICAgIF07XHJcbiAgICAgICAgICBpZiAob3BlcmF0b3JGdW5jdGlvbikge1xyXG4gICAgICAgICAgICBjb25zdCBpdGVtUmVjb3JkID0gaXRlbSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcclxuICAgICAgICAgICAgcmV0dXJuIG9wZXJhdG9yRnVuY3Rpb24oXHJcbiAgICAgICAgICAgICAgaXRlbVJlY29yZFtjb25kLmZpcmVzdG9yZVByb3BlcnR5XSxcclxuICAgICAgICAgICAgICBjb25kLmRhc2hQcm9wZXJ0eSxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9KTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBQVUJMSUMgTUVUSE9EU1xyXG5cclxuICBhc3luYyByZWxvYWRUYWJsZSgpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICh0aGlzLmRhdGEucGFnaW5hdGlvbikge1xyXG4gICAgICBhd2FpdCB0aGlzLmxvYWRJdGVtc1BhZ2luYXRlZCgncmVsb2FkJywgdHJ1ZSk7XHJcbiAgICAgIHRoaXMucGFnaW5hdG9yLmZpcnN0UGFnZSgpO1xyXG4gICAgICB0aGlzLmNkci5tYXJrRm9yQ2hlY2soKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGF3YWl0IHRoaXMubG9hZEl0ZW1zKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICB1cGRhdGVEaXNwbGF5ZWRDb2x1bW5zKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuZGF0YVNvdXJjZSkge1xyXG4gICAgICB0aGlzLmRhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlPFQ+KFtdKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNvbHVtblByb3BlcnRpZXMgPSB0aGlzLmRhdGEuZGlzcGxheWVkQ29sdW1ucy5tYXAoXHJcbiAgICAgIChjb2x1bW4pID0+IGNvbHVtbi5wcm9wZXJ0eSxcclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgZmlsdGVyQ29uZmlnID0gdGhpcy5maWx0ZXJTZXJ2aWNlLmluaXRpYWxpemVEcm9wZG93bkl0ZW1zKFxyXG4gICAgICB0aGlzLmRhdGEuZGlzcGxheWVkQ29sdW1ucyxcclxuICAgICk7XHJcbiAgICB0aGlzLmRyb3Bkb3duSXRlbXMgPSBmaWx0ZXJDb25maWcuZHJvcGRvd25JdGVtcztcclxuICAgIHRoaXMuc29ydGFibGVEcm9wZG93bkl0ZW1zID0gZmlsdGVyQ29uZmlnLnNvcnRhYmxlRHJvcGRvd25JdGVtcztcclxuXHJcbiAgICBpZiAodGhpcy5kYXRhLmZpbHRlcmFibGVPcHRpb25zKSB7XHJcbiAgICAgIHRoaXMuZHJvcGRvd25JdGVtcyA9IHRoaXMuZmlsdGVyU2VydmljZS5hZGRGaWx0ZXJhYmxlT3B0aW9ucyhcclxuICAgICAgICB0aGlzLmRyb3Bkb3duSXRlbXMsXHJcbiAgICAgICAgdGhpcy5kYXRhLmZpbHRlcmFibGVPcHRpb25zLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XHJcbiAgfVxyXG5cclxuICBzaG91bGRTaG93QWN0aW9uQnV0dG9uKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCF0aGlzLmRhdGE/LmFjdGlvbkJ1dHRvbikge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0aGlzLmRhdGEuYWN0aW9uQnV0dG9uLmNvbmRpdGlvbikge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICB0cnkge1xyXG4gICAgICByZXR1cm4gdGhpcy5kYXRhLmFjdGlvbkJ1dHRvbi5jb25kaXRpb24obnVsbCkgPz8gdHJ1ZTtcclxuICAgIH0gY2F0Y2gge1xyXG4gICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGhhbmRsZURvd25sb2FkKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmRvd25sb2FkVGFibGUpIHJldHVybjtcclxuXHJcbiAgICBpZiAodGhpcy5kYXRhLnBhZ2luYXRpb24gPT09IGZhbHNlKSB7XHJcbiAgICAgIGlmICh0aGlzLmRhdGFTb3VyY2UgJiYgdGhpcy5kYXRhU291cmNlLmZpbHRlcmVkRGF0YSkge1xyXG4gICAgICAgIHRoaXMuZmlsdGVyZWRJdGVtcyA9IFsuLi50aGlzLmRhdGFTb3VyY2UuZmlsdGVyZWREYXRhXTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgYXJyYW5nZSA9IHRoaXMuYnVpbGRBcnJhbmdlRnJvbUZpbHRlcnMoKTtcclxuICAgICAgdGhpcy5kb3dubG9hZFRhYmxlKGFycmFuZ2UsIHRoaXMuZGF0YS5jb25kaXRpb25zIHx8IFtdKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0aGlzLmFycmFuZ2UpIHtcclxuICAgICAgICB0aGlzLmRvd25sb2FkVGFibGUodGhpcy5hcnJhbmdlLCB0aGlzLmRhdGEuY29uZGl0aW9ucyB8fCBbXSk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiPGRpdiAqbmdJZj1cImRhdGFcIiBjbGFzcz1cImNhcmQtYm9keVwiPlxyXG4gIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGp1c3RpZnktYmV0d2VlbiBnYXAtNlwiPlxyXG4gICAgPCEtLSBVTklGSUVEIENPTlRST0wgUEFORUw6IEZJTFRFUlMsIFNPUlQgJiBBQ1RJT05TIC0tPlxyXG4gICAgPGRpdlxyXG4gICAgICBjbGFzcz1cInJvdW5kZWQteGwgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCBiZy13aGl0ZSBwLTQgc2hhZG93LWxnXCJcclxuICAgICAgKm5nSWY9XCJcclxuICAgICAgICBkYXRhLnBhZ2luYXRpb24gPT09IHRydWUgJiZcclxuICAgICAgICAoZHJvcGRvd25JdGVtcy5sZW5ndGggPiAwIHx8XHJcbiAgICAgICAgICBzb3J0YWJsZURyb3Bkb3duSXRlbXMubGVuZ3RoID4gMCB8fFxyXG4gICAgICAgICAgZGF0YS5hY3Rpb25CdXR0b24pXHJcbiAgICAgIFwiXHJcbiAgICA+XHJcbiAgICAgIDwhLS0gUEFORUwgSEVBREVSOiBUaXRsZSBhbmQgQ3VzdG9tIEFjdGlvbiAtLT5cclxuICAgICAgPGRpdlxyXG4gICAgICAgIGNsYXNzPVwibWItNCBmbGV4IGZsZXgtY29sIGl0ZW1zLXN0YXJ0IGp1c3RpZnktYmV0d2VlbiBnYXAtNCBib3JkZXItYi0yIGJvcmRlci1ncmF5LTIwMCBwYi00IG1kOmZsZXgtcm93IG1kOml0ZW1zLWNlbnRlclwiXHJcbiAgICAgID5cclxuICAgICAgICA8IS0tIExlZnQgU2lkZTogVGl0bGUgJiBNYWluIEFjdGlvbiBCdXR0b24gLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC13cmFwIGl0ZW1zLWNlbnRlciBnYXAtNFwiPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XHJcbiAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtZmlsdGVyIHRleHQteGwgdGV4dC1ibHVlLTUwMFwiPjwvaT5cclxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTcwMFwiXHJcbiAgICAgICAgICAgICAgPkZpbHRyb3MgZSBBw6fDtWVzPC9zcGFuXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cImRhdGEuYWN0aW9uQnV0dG9uICYmIGRhdGEuYWN0aW9uQnV0dG9uLmNvbmRpdGlvblwiXHJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cIlxyXG4gICAgICAgICAgICAgIChkYXRhLmFjdGlvbkJ1dHRvbi5jb2xvckNsYXNzIHx8ICdiZy1ibHVlLTUwMCcpICtcclxuICAgICAgICAgICAgICAnIGZsZXggaXRlbXMtY2VudGVyIGdhcC0yIHJvdW5kZWQtbGcgcHgtNCBweS0yIHRleHQtc20gZm9udC1tZWRpdW0gdGV4dC13aGl0ZSBob3ZlcjpvcGFjaXR5LTcwJ1xyXG4gICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICBbcm91dGVyTGlua109XCJkYXRhLmFjdGlvbkJ1dHRvbi5yb3V0ZXJMaW5rXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cIlxyXG4gICAgICAgICAgICAgIGRhdGEuYWN0aW9uQnV0dG9uLm1ldGhvZCA/IGRhdGEuYWN0aW9uQnV0dG9uLm1ldGhvZCgkZXZlbnQpIDogbnVsbFxyXG4gICAgICAgICAgICBcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8aVxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiZGF0YS5hY3Rpb25CdXR0b24uaWNvblwiXHJcbiAgICAgICAgICAgICAgW2NsYXNzXT1cImRhdGEuYWN0aW9uQnV0dG9uLmljb25cIlxyXG4gICAgICAgICAgICA+PC9pPlxyXG4gICAgICAgICAgICB7eyBkYXRhLmFjdGlvbkJ1dHRvbi5sYWJlbCB9fVxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBTT1JUIEZJRUxEIChJbnRlZ3JhdGVkIHdpdGggZmlsdGVycykgLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJtYi00XCIgKm5nSWY9XCJzb3J0YWJsZURyb3Bkb3duSXRlbXMubGVuZ3RoID4gMFwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtd3JhcCBpdGVtcy1jZW50ZXIgZ2FwLTMgcC0yXCI+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluLXctWzIwMHB4XSBmbGV4LTFcIj5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgY2xhc3M9XCJ3LWZ1bGxcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cclxuICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtc29ydC1hbHBoYS1kb3duIHRleHQtY3lhbi02MDBcIj48L2k+XHJcbiAgICAgICAgICAgICAgICA8c3Bhbj5PcmRlbmFyIHBvcjwvc3Bhbj5cclxuICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBwbGFjZWhvbGRlcj1cIlNlbGVjaW9uZS4uLlwiIFtmb3JtQ29udHJvbF09XCJzZWxlY3RTb3J0XCI+XHJcbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvblxyXG4gICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBzb3J0YWJsZURyb3Bkb3duSXRlbXNcIlxyXG4gICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiaXRlbVwiXHJcbiAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtc29ydC1hbHBoYS1kb3duIHRleHQtY3lhbi02MDBcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgaXRlbS50aXRsZSB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBGSUxURVJTIENPTlRFTlQgKFdJVEggUkVGSU5FTUVOVFMpIC0tPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwibWItNCBzcGFjZS15LTNcIiAqbmdJZj1cImZpbHRlcnNGb3JtLmNvbnRyb2xzLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICA8ZGl2XHJcbiAgICAgICAgICBbZm9ybUdyb3VwXT1cIiRhbnkoZmlsdGVyR3JvdXApXCJcclxuICAgICAgICAgICpuZ0Zvcj1cImxldCBmaWx0ZXJHcm91cCBvZiBmaWx0ZXJzRm9ybS5jb250cm9sczsgbGV0IGkgPSBpbmRleFwiXHJcbiAgICAgICAgICBjbGFzcz1cImZsZXggZmxleC13cmFwIGl0ZW1zLWNlbnRlciBnYXAtMyBwLTJcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDwhLS0gRklMVEVSIFRZUEUgU0VMRUNUT1IgLS0+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluLXctWzIwMHB4XSBmbGV4LTFcIiAqbmdJZj1cImRyb3Bkb3duSXRlbXMubGVuZ3RoID4gMFwiPlxyXG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBjbGFzcz1cInctZnVsbFwiPlxyXG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+VGlwbyBkZSBmaWx0cm88L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWxlY2lvbmUgbyB0aXBvLi4uXCJcclxuICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInNlbGVjdEZpbHRlclwiXHJcbiAgICAgICAgICAgICAgICAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uU2VsZWN0RmlsdGVyQ2hhbmdlKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXHJcbiAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBpdGVtIG9mIGdldEF2YWlsYWJsZUZpbHRlck9wdGlvbnMoKVwiXHJcbiAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJpdGVtXCJcclxuICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGlcclxuICAgICAgICAgICAgICAgICAgICAgIFtjbGFzc109XCJpdGVtLmljb24gfHwgJ2ZhIGZhLWZpbHRlcidcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXNtIHRleHQtYmx1ZS01MDBcIlxyXG4gICAgICAgICAgICAgICAgICAgID48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgaXRlbS50aXRsZSB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgPCEtLSBURVhUIEZJTFRFUiAtLT5cclxuICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgY2xhc3M9XCJtaW4tdy1bMjAwcHhdIGZsZXgtMVwiXHJcbiAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgJGFueShmaWx0ZXJHcm91cCkuZ2V0KCdzZWxlY3RGaWx0ZXInKT8udmFsdWU/LmFycmFuZ2UgPT09ICdmaWx0ZXInXHJcbiAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIGNsYXNzPVwidy1mdWxsXCI+XHJcbiAgICAgICAgICAgICAgPG1hdC1sYWJlbCBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXNlYXJjaCB0ZXh0LWdyYXktNDAwXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4+e3tcclxuICAgICAgICAgICAgICAgICAgJGFueShmaWx0ZXJHcm91cCkuZ2V0KFwic2VsZWN0RmlsdGVyXCIpPy52YWx1ZT8udGl0bGUgfHxcclxuICAgICAgICAgICAgICAgICAgICBcIkZpbHRyYXJcIlxyXG4gICAgICAgICAgICAgICAgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICAoa2V5dXAuZW50ZXIpPVwic2VhcmNoKCRldmVudClcIlxyXG4gICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidHlwZUZpbHRlclwiXHJcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJEaWdpdGUgcGFyYSBmaWx0cmFyLi4uXCJcclxuICAgICAgICAgICAgICAgICNpbnB1dFxyXG4gICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIERST1BET1dOIEZJTFRFUiAtLT5cclxuICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgY2xhc3M9XCJtaW4tdy1bMjAwcHhdIGZsZXgtMVwiXHJcbiAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgJGFueShmaWx0ZXJHcm91cCkuZ2V0KCdzZWxlY3RGaWx0ZXInKT8udmFsdWUgJiZcclxuICAgICAgICAgICAgICAkYW55KGZpbHRlckdyb3VwKVxyXG4gICAgICAgICAgICAgICAgLmdldCgnc2VsZWN0RmlsdGVyJylcclxuICAgICAgICAgICAgICAgID8udmFsdWUuaGFzT3duUHJvcGVydHkoJ2l0ZW1zJylcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgY2xhc3M9XCJ3LWZ1bGxcIj5cclxuICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7XHJcbiAgICAgICAgICAgICAgICAkYW55KGZpbHRlckdyb3VwKS5nZXQoXCJzZWxlY3RGaWx0ZXJcIik/LnZhbHVlPy50aXRsZSB8fFxyXG4gICAgICAgICAgICAgICAgICBcIlNlbGVjaW9uZVwiXHJcbiAgICAgICAgICAgICAgfX08L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxyXG4gICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWxlY2lvbmUuLi5cIlxyXG4gICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwic2VsZWN0SXRlbVwiXHJcbiAgICAgICAgICAgICAgICBtdWx0aXBsZVxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uXHJcbiAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cIlxyXG4gICAgICAgICAgICAgICAgICAgIGxldCBpdGVtIG9mICRhbnkoZmlsdGVyR3JvdXApLmdldCgnc2VsZWN0RmlsdGVyJyk/LnZhbHVlXHJcbiAgICAgICAgICAgICAgICAgICAgICAuaXRlbXNcclxuICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cIml0ZW1cIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIH19XHJcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxyXG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgPCEtLSBEQVRFIEZJTFRFUiAtLT5cclxuICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgY2xhc3M9XCJtaW4tdy1bMzQwcHhdIGZsZXgtYXV0b1wiXHJcbiAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgJGFueShmaWx0ZXJHcm91cCkuZ2V0KCdzZWxlY3RGaWx0ZXInKT8udmFsdWU/LmFycmFuZ2UgPT09XHJcbiAgICAgICAgICAgICAgJ2ZpbHRlckJ5RGF0ZSdcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPGRpdlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBmbGV4LWNvbCBpdGVtcy1zdHJldGNoIGdhcC0zIHNtOmZsZXgtcm93IHNtOml0ZW1zLWNlbnRlclwiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBjbGFzcz1cImZsZXgtMVwiPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbCBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XHJcbiAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtY2FsZW5kYXIgdGV4dC1ncmF5LTQwMFwiPjwvaT5cclxuICAgICAgICAgICAgICAgICAgPHNwYW4+RGF0YSBJbmljaWFsPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJzZWFyY2goJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJvbkRhdGVJbnB1dCgkZXZlbnQsICdpbml0aWFsRGF0ZScsIGkpXCJcclxuICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiaW5pdGlhbERhdGVcIlxyXG4gICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkREL01NL0FBQUFcIlxyXG4gICAgICAgICAgICAgICAgICBtYXhsZW5ndGg9XCIxMFwiXHJcbiAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcblxyXG4gICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIGNsYXNzPVwiZmxleC0xXCI+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWxhYmVsIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cclxuICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1jYWxlbmRhciB0ZXh0LWdyYXktNDAwXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICA8c3Bhbj5EYXRhIEZpbmFsPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJzZWFyY2goJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJvbkRhdGVJbnB1dCgkZXZlbnQsICdmaW5hbERhdGUnLCBpKVwiXHJcbiAgICAgICAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImZpbmFsRGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiREQvTU0vQUFBQVwiXHJcbiAgICAgICAgICAgICAgICAgIG1heGxlbmd0aD1cIjEwXCJcclxuICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICA8IS0tIFJFTU9WRSBGSUxURVIgQlVUVE9OIC0tPlxyXG4gICAgICAgICAgPGRpdiAqbmdJZj1cImZpbHRlcnNGb3JtLmxlbmd0aCA+IDFcIiBjbGFzcz1cIm1sLWF1dG8gZmxleC1zaHJpbmstMFwiPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUZpbHRlcihpKVwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGgtMTAgdy0xMCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgcm91bmRlZC1mdWxsIHRyYW5zaXRpb24tY29sb3JzIGR1cmF0aW9uLTMwMCBob3ZlcjpiZy1yZWQtMTAwXCJcclxuICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiUmVtb3ZlciBmaWx0cm9cIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS10cmFzaCB0ZXh0LXJlZC01MDAgaG92ZXI6dGV4dC1yZWQtNjAwXCI+PC9pPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gUEFORUwgRk9PVEVSOiBBZGQgRmlsdGVyICYgQWN0aW9uIEJ1dHRvbnMgLS0+XHJcbiAgICAgIDxkaXZcclxuICAgICAgICBjbGFzcz1cIi1tYi0yIGZsZXggaXRlbXMtc3RhcnQganVzdGlmeS1iZXR3ZWVuIGdhcC00IGJvcmRlci10IGJvcmRlci1ncmF5LTIwMCBwdC00XCJcclxuICAgICAgPlxyXG4gICAgICAgIDwhLS0gQWRkIEZpbHRlciBCdXR0b24gLS0+XHJcbiAgICAgICAgPGRpdiAqbmdJZj1cImRyb3Bkb3duSXRlbXMubGVuZ3RoID4gMFwiPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAoY2xpY2spPVwiYWRkRmlsdGVyKClcIlxyXG4gICAgICAgICAgICBjbGFzcz1cInRyYW5zZm9ybSByb3VuZGVkLWZ1bGwgYm9yZGVyLTIgYm9yZGVyLWJsdWUtMzAwIGJnLWJsdWUtNTAgcHgtNiBweS0yIHRleHQtc20gZm9udC1tZWRpdW0gdGV4dC1ibHVlLTYwMCB0cmFuc2l0aW9uLWFsbCBkdXJhdGlvbi0zMDAgaG92ZXI6LXRyYW5zbGF0ZS15LTAuNSBob3Zlcjpib3JkZXItYmx1ZS00MDAgaG92ZXI6YmctYmx1ZS0xMDAgaG92ZXI6c2hhZG93LW1kXCJcclxuICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkFkaWNpb25hciBub3ZvIGZpbHRyb1wiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtcGx1cyBtci0yXCI+PC9pPlxyXG4gICAgICAgICAgICBBZGljaW9uYXIgRmlsdHJvXHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPCEtLSBSaWdodCBTaWRlOiBTZWFyY2gsIFJlc2V0LCBFeHBvcnQgLS0+XHJcbiAgICAgICAgPGRpdlxyXG4gICAgICAgICAgY2xhc3M9XCJmbGV4IGZsZXgtd3JhcCBnYXAtMyBzZWxmLXN0YXJ0IHNtOnNlbGYtYXV0b1wiXHJcbiAgICAgICAgICAqbmdJZj1cIlxyXG4gICAgICAgICAgICB0aGlzLmhhc0ZpbHRlcmFibGVDb2x1bW4gPT09IHRydWUgfHwgdGhpcy5oYXNTb3J0YWJsZUNvbHVtbiA9PT0gdHJ1ZVxyXG4gICAgICAgICAgXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgIChjbGljayk9XCJzZWFyY2goKVwiXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yIHJvdW5kZWQtbGcgYmctZ3JlZW4tNjAwIHB4LTUgcHktMiB0ZXh0LXNtIGZvbnQtbWVkaXVtIHRleHQtd2hpdGUgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctZ3JlZW4tNzAwXCJcclxuICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkFwbGljYXIgZmlsdHJvc1wiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtc2VhcmNoXCI+PC9pPlxyXG4gICAgICAgICAgICBQZXNxdWlzYXJcclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgKGNsaWNrKT1cInJlc2V0RmlsdGVyKClcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yIHJvdW5kZWQtbGcgYmctcmVkLTUwMCBweC01IHB5LTIgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LXdoaXRlIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLXJlZC02MDBcIlxyXG4gICAgICAgICAgICBtYXRUb29sdGlwPVwiTGltcGFyIGZpbHRyb3NcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1yZWRvLWFsdFwiPjwvaT5cclxuICAgICAgICAgICAgUmVzZXRhclxyXG4gICAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cImRhdGEuZG93bmxvYWQgIT09IGZhbHNlICYmIGRvd25sb2FkVGFibGVcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yIHJvdW5kZWQtbGcgYmctb3JhbmdlLTUwMCBweC01IHB5LTIgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LXdoaXRlIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLW9yYW5nZS02MDBcIlxyXG4gICAgICAgICAgICBtYXRUb29sdGlwUG9zaXRpb249XCJhYm92ZVwiXHJcbiAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJFeHBvcnRhciBUYWJlbGFcIlxyXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiXHJcbiAgICAgICAgICAgICAgdGhpcy5kYXRhU291cmNlICYmIHRoaXMuZGF0YVNvdXJjZS5maWx0ZXJlZERhdGEubGVuZ3RoIDw9IDBcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cIlxyXG4gICAgICAgICAgICAgICRhbnkoYXJyYW5nZSkgJiYgZG93bmxvYWRUYWJsZSAhPT0gdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICA/IGRvd25sb2FkVGFibGUoJGFueShhcnJhbmdlKSwgZGF0YS5jb25kaXRpb25zIHx8IFtdKVxyXG4gICAgICAgICAgICAgICAgOiBudWxsXHJcbiAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtZG93bmxvYWRcIj48L2k+XHJcbiAgICAgICAgICAgIEV4cG9ydGFyXHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIFVOSUZJRUQgQ09OVFJPTCBQQU5FTCAoZm9yIG5vbi1wYWdpbmF0ZWQgdGFibGVzKTogU0VBUkNILCBTT1JUICYgRklMVEVSUyAtLT5cclxuICAgIDxkaXZcclxuICAgICAgY2xhc3M9XCJyb3VuZGVkLXhsIGJvcmRlciBib3JkZXItZ3JheS0yMDAgYmctd2hpdGUgcC00IHNoYWRvdy1sZ1wiXHJcbiAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgZGF0YS5wYWdpbmF0aW9uID09PSBmYWxzZSAmJlxyXG4gICAgICAgIChoYXNGaWx0ZXJhYmxlQ29sdW1uID09PSB0cnVlIHx8XHJcbiAgICAgICAgICBkcm9wZG93bkl0ZW1zLmxlbmd0aCA+IDAgfHxcclxuICAgICAgICAgIGRhdGEuYWN0aW9uQnV0dG9uKVxyXG4gICAgICBcIlxyXG4gICAgPlxyXG4gICAgICA8IS0tIFBBTkVMIEhFQURFUjogVGl0bGUgYW5kIEN1c3RvbSBBY3Rpb24gLS0+XHJcbiAgICAgIDxkaXZcclxuICAgICAgICBjbGFzcz1cIm1iLTQgZmxleCBmbGV4LWNvbCBpdGVtcy1zdGFydCBqdXN0aWZ5LWJldHdlZW4gZ2FwLTQgYm9yZGVyLWItMiBib3JkZXItZ3JheS0yMDAgcGItNCBtZDpmbGV4LXJvdyBtZDppdGVtcy1jZW50ZXJcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPCEtLSBMZWZ0IFNpZGU6IFRpdGxlICYgTWFpbiBBY3Rpb24gQnV0dG9uIC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtd3JhcCBpdGVtcy1jZW50ZXIgZ2FwLTRcIj5cclxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLWZpbHRlciB0ZXh0LXhsIHRleHQtYmx1ZS01MDBcIj48L2k+XHJcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1sZyBmb250LXNlbWlib2xkIHRleHQtZ3JheS03MDBcIlxyXG4gICAgICAgICAgICAgID5GaWx0cm9zIGUgQcOnw7Vlczwvc3BhblxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgKm5nSWY9XCJkYXRhLmFjdGlvbkJ1dHRvbiAmJiBkYXRhLmFjdGlvbkJ1dHRvbi5jb25kaXRpb25cIlxyXG4gICAgICAgICAgICBbbmdDbGFzc109XCJcclxuICAgICAgICAgICAgICAoZGF0YS5hY3Rpb25CdXR0b24uY29sb3JDbGFzcyB8fCAnYmctYmx1ZS01MDAnKSArXHJcbiAgICAgICAgICAgICAgJyBmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMiByb3VuZGVkLWxnIHB4LTQgcHktMiB0ZXh0LXNtIGZvbnQtbWVkaXVtIHRleHQtd2hpdGUgaG92ZXI6b3BhY2l0eS03MCdcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgW3JvdXRlckxpbmtdPVwiZGF0YS5hY3Rpb25CdXR0b24ucm91dGVyTGlua1wiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJcclxuICAgICAgICAgICAgICBkYXRhLmFjdGlvbkJ1dHRvbi5tZXRob2QgPyBkYXRhLmFjdGlvbkJ1dHRvbi5tZXRob2QoJGV2ZW50KSA6IG51bGxcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPGlcclxuICAgICAgICAgICAgICAqbmdJZj1cImRhdGEuYWN0aW9uQnV0dG9uLmljb25cIlxyXG4gICAgICAgICAgICAgIFtjbGFzc109XCJkYXRhLmFjdGlvbkJ1dHRvbi5pY29uXCJcclxuICAgICAgICAgICAgPjwvaT5cclxuICAgICAgICAgICAge3sgZGF0YS5hY3Rpb25CdXR0b24ubGFiZWwgfX1cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDwhLS0gU0lNUExFIFNFQVJDSCAtLT5cclxuICAgICAgPGRpdlxyXG4gICAgICAgIGNsYXNzPVwibWItNFwiXHJcbiAgICAgICAgKm5nSWY9XCJoYXNGaWx0ZXJhYmxlQ29sdW1uID09PSB0cnVlICYmIGRhdGEuc2hvd1NpbXBsZVNlYXJjaCAhPT0gZmFsc2VcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgY2xhc3M9XCJ3LWZ1bGxcIj5cclxuICAgICAgICAgIDxtYXQtbGFiZWwgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXNlYXJjaCB0ZXh0LWJsdWUtNTAwXCI+PC9pPlxyXG4gICAgICAgICAgICBCdXNjYXJcclxuICAgICAgICAgIDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgIG1hdElucHV0XHJcbiAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJzZWFyY2goJGV2ZW50KVwiXHJcbiAgICAgICAgICAgIChrZXl1cCk9XCJhcHBseUZpbHRlcihmaWx0ZXJJbnB1dC52YWx1ZSlcIlxyXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkRpZ2l0ZSBwYXJhIGZpbHRyYXIuLi5cIlxyXG4gICAgICAgICAgICAjZmlsdGVySW5wdXRcclxuICAgICAgICAgIC8+XHJcbiAgICAgICAgICA8bWF0LWljb24gbWF0U3VmZml4IGNsYXNzPVwidGV4dC1ncmF5LTUwMFwiPnNlYXJjaDwvbWF0LWljb24+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgPC9kaXY+XHJcblxyXG4gICAgICA8IS0tIEZJTFRFUlMgUEFORUwgLS0+XHJcbiAgICAgIDxkaXYgKm5nSWY9XCJkcm9wZG93bkl0ZW1zLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICA8IS0tIEZJTFRFUlMgQ09OVEVOVCAtLT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibWItNCBzcGFjZS15LTNcIiAqbmdJZj1cImZpbHRlcnNGb3JtLmNvbnRyb2xzLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgW2Zvcm1Hcm91cF09XCIkYW55KGZpbHRlckdyb3VwKVwiXHJcbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBmaWx0ZXJHcm91cCBvZiBmaWx0ZXJzRm9ybS5jb250cm9sczsgbGV0IGkgPSBpbmRleFwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiZmxleCBmbGV4LXdyYXAgaXRlbXMtY2VudGVyIGdhcC0zXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPCEtLSBGSUxURVIgVFlQRSBTRUxFQ1RPUiAtLT5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1pbi13LVsyMDBweF0gZmxleC0xXCIgKm5nSWY9XCJkcm9wZG93bkl0ZW1zLmxlbmd0aCA+IDBcIj5cclxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBjbGFzcz1cInctZnVsbFwiPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD5UaXBvIGRlIGZpbHRybzwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1zZWxlY3RcclxuICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWxlY2lvbmUgbyB0aXBvLi4uXCJcclxuICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwic2VsZWN0RmlsdGVyXCJcclxuICAgICAgICAgICAgICAgICAgKHNlbGVjdGlvbkNoYW5nZSk9XCJvblNlbGVjdEZpbHRlckNoYW5nZSgpXCJcclxuICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgPG1hdC1vcHRpb25cclxuICAgICAgICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgaXRlbSBvZiBnZXRBdmFpbGFibGVGaWx0ZXJPcHRpb25zKClcIlxyXG4gICAgICAgICAgICAgICAgICAgIFt2YWx1ZV09XCJpdGVtXCJcclxuICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGlcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzXT1cIml0ZW0uaWNvbiB8fCAnZmEgZmEtZmlsdGVyJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1zbSB0ZXh0LWJsdWUtNTAwXCJcclxuICAgICAgICAgICAgICAgICAgICAgID48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj57eyBpdGVtLnRpdGxlIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1zZWxlY3Q+XHJcbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICA8IS0tIFRFWFQgRklMVEVSIC0tPlxyXG4gICAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJtaW4tdy1bMjAwcHhdIGZsZXgtMVwiXHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJcclxuICAgICAgICAgICAgICAgICRhbnkoZmlsdGVyR3JvdXApLmdldCgnc2VsZWN0RmlsdGVyJyk/LnZhbHVlPy5hcnJhbmdlID09PVxyXG4gICAgICAgICAgICAgICAgJ2ZpbHRlcidcclxuICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgY2xhc3M9XCJ3LWZ1bGxcIj5cclxuICAgICAgICAgICAgICAgIDxtYXQtbGFiZWwgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXNlYXJjaCB0ZXh0LWdyYXktNDAwXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICA8c3Bhbj57e1xyXG4gICAgICAgICAgICAgICAgICAgICRhbnkoZmlsdGVyR3JvdXApLmdldChcInNlbGVjdEZpbHRlclwiKT8udmFsdWU/LnRpdGxlIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgICBcIkZpbHRyYXJcIlxyXG4gICAgICAgICAgICAgICAgICB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICAgIChrZXl1cC5lbnRlcik9XCJzZWFyY2goJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInR5cGVGaWx0ZXJcIlxyXG4gICAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkRpZ2l0ZSBwYXJhIGZpbHRyYXIuLi5cIlxyXG4gICAgICAgICAgICAgICAgICAjaW5wdXRcclxuICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICA8IS0tIERST1BET1dOIEZJTFRFUiAtLT5cclxuICAgICAgICAgICAgPGRpdlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwibWluLXctWzIwMHB4XSBmbGV4LTFcIlxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgICAkYW55KGZpbHRlckdyb3VwKS5nZXQoJ3NlbGVjdEZpbHRlcicpPy52YWx1ZSAmJlxyXG4gICAgICAgICAgICAgICAgJGFueShmaWx0ZXJHcm91cClcclxuICAgICAgICAgICAgICAgICAgLmdldCgnc2VsZWN0RmlsdGVyJylcclxuICAgICAgICAgICAgICAgICAgPy52YWx1ZS5oYXNPd25Qcm9wZXJ0eSgnaXRlbXMnKVxyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQgYXBwZWFyYW5jZT1cIm91dGxpbmVcIiBjbGFzcz1cInctZnVsbFwiPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1sYWJlbD57e1xyXG4gICAgICAgICAgICAgICAgICAkYW55KGZpbHRlckdyb3VwKS5nZXQoXCJzZWxlY3RGaWx0ZXJcIik/LnZhbHVlPy50aXRsZSB8fFxyXG4gICAgICAgICAgICAgICAgICAgIFwiU2VsZWNpb25lXCJcclxuICAgICAgICAgICAgICAgIH19PC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8bWF0LXNlbGVjdFxyXG4gICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNlbGVjaW9uZS4uLlwiXHJcbiAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInNlbGVjdEl0ZW1cIlxyXG4gICAgICAgICAgICAgICAgICBtdWx0aXBsZVxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICA8bWF0LW9wdGlvblxyXG4gICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgbGV0IGl0ZW0gb2YgJGFueShmaWx0ZXJHcm91cCkuZ2V0KCdzZWxlY3RGaWx0ZXInKT8udmFsdWVcclxuICAgICAgICAgICAgICAgICAgICAgICAgLml0ZW1zXHJcbiAgICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiaXRlbVwiXHJcbiAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICB7eyBpdGVtLmxhYmVsIH19XHJcbiAgICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gREFURSBGSUxURVIgLS0+XHJcbiAgICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgICBjbGFzcz1cIm1pbi13LVszNDBweF0gZmxleC1hdXRvXCJcclxuICAgICAgICAgICAgICAqbmdJZj1cIlxyXG4gICAgICAgICAgICAgICAgJGFueShmaWx0ZXJHcm91cCkuZ2V0KCdzZWxlY3RGaWx0ZXInKT8udmFsdWU/LmFycmFuZ2UgPT09XHJcbiAgICAgICAgICAgICAgICAnZmlsdGVyQnlEYXRlJ1xyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggZmxleC1jb2wgaXRlbXMtc3RyZXRjaCBnYXAtMyBzbTpmbGV4LXJvdyBzbTppdGVtcy1jZW50ZXJcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIGNsYXNzPVwiZmxleC0xXCI+XHJcbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWwgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtY2FsZW5kYXIgdGV4dC1ncmF5LTQwMFwiPjwvaT5cclxuICAgICAgICAgICAgICAgICAgICA8c3Bhbj5EYXRhIEluaWNpYWw8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICAgICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcclxuICAgICAgICAgICAgICAgICAgICAoa2V5ZG93bi5lbnRlcik9XCJzZWFyY2goJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGlucHV0KT1cIm9uRGF0ZUlucHV0KCRldmVudCwgJ2luaXRpYWxEYXRlJywgaSlcIlxyXG4gICAgICAgICAgICAgICAgICAgIChibHVyKT1cIm9uRGF0ZUZpbHRlckNoYW5nZSgpXCJcclxuICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJpbml0aWFsRGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJERC9NTS9BQUFBXCJcclxuICAgICAgICAgICAgICAgICAgICBtYXhsZW5ndGg9XCIxMFwiXHJcbiAgICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG5cclxuICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIGNsYXNzPVwiZmxleC0xXCI+XHJcbiAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWwgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtY2FsZW5kYXIgdGV4dC1ncmF5LTQwMFwiPjwvaT5cclxuICAgICAgICAgICAgICAgICAgICA8c3Bhbj5EYXRhIEZpbmFsPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICAgICAgICAgIChrZXlkb3duLmVudGVyKT1cInNlYXJjaCgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICAgICAgICAoaW5wdXQpPVwib25EYXRlSW5wdXQoJGV2ZW50LCAnZmluYWxEYXRlJywgaSlcIlxyXG4gICAgICAgICAgICAgICAgICAgIChibHVyKT1cIm9uRGF0ZUZpbHRlckNoYW5nZSgpXCJcclxuICAgICAgICAgICAgICAgICAgICBtYXRJbnB1dFxyXG4gICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImZpbmFsRGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJERC9NTS9BQUFBXCJcclxuICAgICAgICAgICAgICAgICAgICBtYXhsZW5ndGg9XCIxMFwiXHJcbiAgICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gUkVNT1ZFIEZJTFRFUiBCVVRUT04gLS0+XHJcbiAgICAgICAgICAgIDxkaXYgKm5nSWY9XCJmaWx0ZXJzRm9ybS5sZW5ndGggPiAxXCIgY2xhc3M9XCJtbC1hdXRvIGZsZXgtc2hyaW5rLTBcIj5cclxuICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVtb3ZlRmlsdGVyKGkpXCJcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBoLTEwIHctMTAgaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHJvdW5kZWQtZnVsbCB0cmFuc2l0aW9uLWNvbG9ycyBkdXJhdGlvbi0zMDAgaG92ZXI6YmctcmVkLTEwMFwiXHJcbiAgICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiUmVtb3ZlciBmaWx0cm9cIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEgZmEtdHJhc2ggdGV4dC1yZWQtNTAwIGhvdmVyOnRleHQtcmVkLTYwMFwiPjwvaT5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPCEtLSBQQU5FTCBGT09URVI6IEFkZCBGaWx0ZXIgJiBBY3Rpb25zIC0tPlxyXG4gICAgICAgIDxkaXZcclxuICAgICAgICAgIGNsYXNzPVwiLW1iLTIgZmxleCBpdGVtcy1zdGFydCBqdXN0aWZ5LWJldHdlZW4gZ2FwLTQgYm9yZGVyLXQgYm9yZGVyLWdyYXktMjAwIHB0LTRcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIDwhLS0gQWRkIEZpbHRlciBCdXR0b24gLS0+XHJcbiAgICAgICAgICA8ZGl2ICpuZ0lmPVwiZHJvcGRvd25JdGVtcy5sZW5ndGggPiAwXCI+XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAoY2xpY2spPVwiYWRkRmlsdGVyKClcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwidHJhbnNmb3JtIHJvdW5kZWQtZnVsbCBib3JkZXItMiBib3JkZXItYmx1ZS0zMDAgYmctYmx1ZS01MCBweC02IHB5LTIgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LWJsdWUtNjAwIHRyYW5zaXRpb24tYWxsIGR1cmF0aW9uLTMwMCBob3ZlcjotdHJhbnNsYXRlLXktMC41IGhvdmVyOmJvcmRlci1ibHVlLTQwMCBob3ZlcjpiZy1ibHVlLTEwMCBob3ZlcjpzaGFkb3ctbWRcIlxyXG4gICAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJBZGljaW9uYXIgbm92byBmaWx0cm9cIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1wbHVzIG1yLTJcIj48L2k+XHJcbiAgICAgICAgICAgICAgQWRpY2lvbmFyIEZpbHRyb1xyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgIDwhLS0gQWN0aW9uIEJ1dHRvbnMgLS0+XHJcbiAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgIGNsYXNzPVwiZmxleCBmbGV4LXdyYXAgZ2FwLTMgc2VsZi1zdGFydCBzbTpzZWxmLWF1dG9cIlxyXG4gICAgICAgICAgICAqbmdJZj1cIlxyXG4gICAgICAgICAgICAgIHRoaXMuaGFzRmlsdGVyYWJsZUNvbHVtbiA9PT0gdHJ1ZSB8fFxyXG4gICAgICAgICAgICAgIHRoaXMuaGFzU29ydGFibGVDb2x1bW4gPT09IHRydWVcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJzZWFyY2goKVwiXHJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMiByb3VuZGVkLWxnIGJnLWdyZWVuLTYwMCBweC01IHB5LTIgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LXdoaXRlIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLWdyZWVuLTcwMFwiXHJcbiAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkFwbGljYXIgZmlsdHJvc1wiXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhIGZhLXNlYXJjaFwiPjwvaT5cclxuICAgICAgICAgICAgICBQZXNxdWlzYXJcclxuICAgICAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInJlc2V0RmlsdGVyKClcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTIgcm91bmRlZC1sZyBiZy1yZWQtNTAwIHB4LTUgcHktMiB0ZXh0LXNtIGZvbnQtbWVkaXVtIHRleHQtd2hpdGUgdHJhbnNpdGlvbi1jb2xvcnMgaG92ZXI6YmctcmVkLTYwMFwiXHJcbiAgICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkxpbXBhciBmaWx0cm9zXCJcclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLXJlZG8tYWx0XCI+PC9pPlxyXG4gICAgICAgICAgICAgIFJlc2V0YXJcclxuICAgICAgICAgICAgPC9idXR0b24+XHJcblxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJkYXRhLmRvd25sb2FkICE9PSBmYWxzZSAmJiBkb3dubG9hZFRhYmxlXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yIHJvdW5kZWQtbGcgYmctb3JhbmdlLTUwMCBweC01IHB5LTIgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LXdoaXRlIHRyYW5zaXRpb24tY29sb3JzIGhvdmVyOmJnLW9yYW5nZS02MDBcIlxyXG4gICAgICAgICAgICAgIG1hdFRvb2x0aXBQb3NpdGlvbj1cImFib3ZlXCJcclxuICAgICAgICAgICAgICBtYXRUb29sdGlwPVwiRXhwb3J0YXIgVGFiZWxhXCJcclxuICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiXHJcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGFTb3VyY2UgJiYgdGhpcy5kYXRhU291cmNlLmZpbHRlcmVkRGF0YS5sZW5ndGggPD0gMFxyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImhhbmRsZURvd25sb2FkKClcIlxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYSBmYS1kb3dubG9hZFwiPjwvaT5cclxuICAgICAgICAgICAgICBFeHBvcnRhclxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sXCI+XHJcbiAgICAgIDwhLS0gVEFCUyBDT01QT05FTlQgLS0+XHJcbiAgICAgIDxsaWItdGFibGUtdGFic1xyXG4gICAgICAgICpuZ0lmPVwiZGF0YS50YWJzICYmIGRhdGEudGFicy50YWJzRGF0YSAmJiBkYXRhLnRhYnMudGFic0RhdGEubGVuZ3RoID4gMFwiXHJcbiAgICAgICAgW3RhYnNEYXRhXT1cImRhdGEudGFicy50YWJzRGF0YVwiXHJcbiAgICAgICAgW3NlbGVjdGVkVGFiXT1cInNlbGVjdGVkVGFiXCJcclxuICAgICAgICAodGFiU2VsZWN0ZWQpPVwib25UYWJTZWxlY3RlZCgkZXZlbnQpXCJcclxuICAgICAgPjwvbGliLXRhYmxlLXRhYnM+XHJcbiAgICAgIDxkaXZcclxuICAgICAgICBjbGFzcz1cIm1hdC1lbGV2YXRpb24tejggdy1mdWxsIG92ZXJmbG93LXgtYXV0byByb3VuZGVkLXhsIHRhYmxlLWNvbnRhaW5lclwiXHJcbiAgICAgID5cclxuICAgICAgICA8dGFibGVcclxuICAgICAgICAgIG1hdC10YWJsZVxyXG4gICAgICAgICAgW2RhdGFTb3VyY2VdPVwiZGF0YVNvdXJjZVwiXHJcbiAgICAgICAgICBtYXRTb3J0XHJcbiAgICAgICAgICAjc29ydD1cIm1hdFNvcnRcIlxyXG4gICAgICAgICAgbWF0U29ydEFjdGl2ZT1cImNyZWF0ZWRBdFwiXHJcbiAgICAgICAgICBtYXRTb3J0RGlyZWN0aW9uPVwiZGVzY1wiXHJcbiAgICAgICAgPlxyXG4gICAgICAgICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICAgICAgICAqbmdGb3I9XCJsZXQgY29sIG9mIGRhdGEuZGlzcGxheWVkQ29sdW1uczsgdHJhY2tCeTogdHJhY2tCeVByb3BlcnR5XCJcclxuICAgICAgICAgICAgbWF0Q29sdW1uRGVmPVwie3sgY29sLnByb3BlcnR5IH19XCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbWF0SGVhZGVyQ2VsbERlZj5cclxuICAgICAgICAgICAgICA8IS0tIElGIFRIRSBDT0xVTU4gSVMgTk9UIFNPUlRBQkxFLCBUSEVOIERPTidUIFNIT1cgVEhFIFNPUlQgQlVUVE9OUyAtLT5cclxuICAgICAgICAgICAgICA8dGhcclxuICAgICAgICAgICAgICAgICpuZ0lmPVwiIWNvbC5pc1NvcnRhYmxlIHx8IGRhdGEucGFnaW5hdGlvbiA9PT0gdHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaGVhZGVyLWNlbGxcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICB7eyBjb2wudGl0bGUgfX1cclxuICAgICAgICAgICAgICA8L3RoPlxyXG4gICAgICAgICAgICAgIDwhLS0gSUYgVEhFIENPTFVNTiBJUyBTT1JUQUJMRSwgVEhFTiBTSE9XIFRIRSBTT1JUIEJVVFRPTlMgLS0+XHJcbiAgICAgICAgICAgICAgPHRoXHJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImNvbC5pc1NvcnRhYmxlICYmIGRhdGEucGFnaW5hdGlvbiA9PT0gZmFsc2VcIlxyXG4gICAgICAgICAgICAgICAgbWF0LWhlYWRlci1jZWxsXHJcbiAgICAgICAgICAgICAgICBtYXQtc29ydC1oZWFkZXJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICB7eyBjb2wudGl0bGUgfX1cclxuICAgICAgICAgICAgICA8L3RoPlxyXG4gICAgICAgICAgICAgIDx0ZFxyXG4gICAgICAgICAgICAgICAgbWF0LWNlbGxcclxuICAgICAgICAgICAgICAgICptYXRDZWxsRGVmPVwibGV0IHJvd1wiXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiY29sLm1ldGhvZCA/IGNvbC5tZXRob2Qocm93KSA6IG51bGxcIlxyXG4gICAgICAgICAgICAgICAgKG1vdXNlZW50ZXIpPVwib25DZWxsTW91c2VFbnRlcigkZXZlbnQsIHJvdywgY29sKVwiXHJcbiAgICAgICAgICAgICAgICAobW91c2VsZWF2ZSk9XCJvbkNlbGxNb3VzZUxlYXZlKClcIlxyXG4gICAgICAgICAgICAgICAgKG1vdXNlbW92ZSk9XCJvbkNlbGxNb3VzZU1vdmUoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPCEtLSBDSEVDSyBJRiBUSEUgQ09MVU1OIE1VU1QgQkUgRElTUExBWUVEIC0tPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCIhY29sLmltYWdlICYmICFjb2wuaWNvbkNsYXNzICYmICFjb2wubWV0aG9kXCI+XHJcbiAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbC5jaGFyTGltaXQgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgICByb3dbY29sLnByb3BlcnR5XSAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJvd1tjb2wucHJvcGVydHldLmxlbmd0aCA+IGNvbC5jaGFyTGltaXQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2Ugd2l0aGluTGltaXRcclxuICAgICAgICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGFcclxuICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJjb2wuaGFzTGluayA9PT0gdHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtocmVmXT1cInJvd1tjb2wucHJvcGVydHldXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcclxuICAgICAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICAgICAge3sgZ2V0RGlzcGxheVZhbHVlKGNvbCwgcm93KSB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGFcclxuICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJjb2wuaGFzTGluayAmJiBpc1N0cmluZyhjb2wuaGFzTGluaylcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbaHJlZl09XCJjb2wuaGFzTGlua1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldD1cIl9ibGFua1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IGdldERpc3BsYXlWYWx1ZShjb2wsIHJvdykgfX1cclxuICAgICAgICAgICAgICAgICAgICAgIDwvYT5cclxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiY29sLmhhc0xpbmsgIT09IHRydWUgJiYgIWlzU3RyaW5nKGNvbC5oYXNMaW5rKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IGdldERpc3BsYXlWYWx1ZShjb2wsIHJvdykgfX1cclxuICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgI3dpdGhpbkxpbWl0PlxyXG4gICAgICAgICAgICAgICAgICAgIDxhXHJcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImNvbC5oYXNMaW5rID09PSB0cnVlXCJcclxuICAgICAgICAgICAgICAgICAgICAgIFtocmVmXT1cInJvd1tjb2wucHJvcGVydHldXCJcclxuICAgICAgICAgICAgICAgICAgICAgIHRhcmdldD1cIl9ibGFua1wiXHJcbiAgICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgICAge3sgZ2V0RGlzcGxheVZhbHVlKGNvbCwgcm93LCB0cnVlKSB9fVxyXG4gICAgICAgICAgICAgICAgICAgIDwvYT5cclxuICAgICAgICAgICAgICAgICAgICA8YVxyXG4gICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJjb2wuaGFzTGluayAmJiBpc1N0cmluZyhjb2wuaGFzTGluaylcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgW2hyZWZdPVwiY29sLmhhc0xpbmtcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgdGFyZ2V0PVwiX2JsYW5rXCJcclxuICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgICB7eyBnZXREaXNwbGF5VmFsdWUoY29sLCByb3csIHRydWUpIH19XHJcbiAgICAgICAgICAgICAgICAgICAgPC9hPlxyXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImNvbC5oYXNMaW5rICE9PSB0cnVlICYmICFpc1N0cmluZyhjb2wuaGFzTGluaylcIlxyXG4gICAgICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgICAgIHt7IGdldERpc3BsYXlWYWx1ZShjb2wsIHJvdywgdHJ1ZSkgfX1cclxuICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8IS0tLS0tLS0tLS0tLS0tLS0tLS0gSU1BR0UgLS0tLS0tLS0tLS0tLS0tLS0tPlxyXG4gICAgICAgICAgICAgICAgPCEtLSBJbWFnZW0gY29tIGxvYWRpbmcgLS0+XHJcbiAgICAgICAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgY29sLmltYWdlICYmIGNvbC5pbWFnZS5wYXRoICYmICFjb2wuaWNvbkNsYXNzICYmICFjb2wubWV0aG9kXHJcbiAgICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICAgIGNsYXNzPVwicmVsYXRpdmUgaW5saW5lLWJsb2NrXCJcclxuICAgICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgICAgPG1hdC1zcGlubmVyXHJcbiAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJpc0ltYWdlTG9hZGluZyhyb3csIGNvbClcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtkaWFtZXRlcl09XCIzMlwiXHJcbiAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJhYnNvbHV0ZSBpbnNldC0wIG0tYXV0b1wiXHJcbiAgICAgICAgICAgICAgICAgID48L21hdC1zcGlubmVyPlxyXG4gICAgICAgICAgICAgICAgICA8aW1nXHJcbiAgICAgICAgICAgICAgICAgICAgW3NyY109XCJjb2wuaW1hZ2UucGF0aCArICcvJyArIHJvd1tjb2wucHJvcGVydHldXCJcclxuICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJjb2wuaW1hZ2UuY2xhc3NcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtjbGFzcy5vcGFjaXR5LTBdPVwiaXNJbWFnZUxvYWRpbmcocm93LCBjb2wpXCJcclxuICAgICAgICAgICAgICAgICAgICBhbHQ9XCJcIlxyXG4gICAgICAgICAgICAgICAgICAgIChsb2FkKT1cIm9uSW1hZ2VMb2FkKHJvdywgY29sKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGVycm9yKT1cIm9uSW1hZ2VFcnJvcigkZXZlbnQsIHJvdywgY29sLCBjb2wuaW1hZ2UuZGVmYXVsdClcIlxyXG4gICAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgPCEtLSBJbWFnZW0gY29tIFVSTCBjb21wbGV0YSBlIGxvYWRpbmcgLS0+XHJcbiAgICAgICAgICAgICAgICA8ZGl2XHJcbiAgICAgICAgICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgY29sLmltYWdlICYmIGNvbC5pbWFnZS51cmwgJiYgIWNvbC5pY29uQ2xhc3MgJiYgIWNvbC5tZXRob2RcclxuICAgICAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAgICAgY2xhc3M9XCJyZWxhdGl2ZSBpbmxpbmUtYmxvY2tcIlxyXG4gICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICA8bWF0LXNwaW5uZXJcclxuICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImlzSW1hZ2VMb2FkaW5nKHJvdywgY29sKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2RpYW1ldGVyXT1cIjMyXCJcclxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImFic29sdXRlIGluc2V0LTAgbS1hdXRvXCJcclxuICAgICAgICAgICAgICAgICAgPjwvbWF0LXNwaW5uZXI+XHJcbiAgICAgICAgICAgICAgICAgIDxpbWdcclxuICAgICAgICAgICAgICAgICAgICBbc3JjXT1cInJvd1tjb2wucHJvcGVydHldXCJcclxuICAgICAgICAgICAgICAgICAgICBbbmdDbGFzc109XCJjb2wuaW1hZ2UuY2xhc3NcIlxyXG4gICAgICAgICAgICAgICAgICAgIFtjbGFzcy5vcGFjaXR5LTBdPVwiaXNJbWFnZUxvYWRpbmcocm93LCBjb2wpXCJcclxuICAgICAgICAgICAgICAgICAgICBhbHQ9XCJcIlxyXG4gICAgICAgICAgICAgICAgICAgIChsb2FkKT1cIm9uSW1hZ2VMb2FkKHJvdywgY29sKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgKGVycm9yKT1cIm9uSW1hZ2VFcnJvcigkZXZlbnQsIHJvdywgY29sLCBjb2wuaW1hZ2UuZGVmYXVsdClcIlxyXG4gICAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY29sLmljb25DbGFzc1wiPlxyXG4gICAgICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGljb25DbGFzcyBvZiBjb2wuaWNvbkNsYXNzXCJcclxuICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICBpY29uQ2xhc3MuYnV0dG9uTWV0aG9kXHJcbiAgICAgICAgICAgICAgICAgICAgICAgID8gaWNvbkNsYXNzLmJ1dHRvbk1ldGhvZChyb3csICRldmVudClcclxuICAgICAgICAgICAgICAgICAgICAgICAgOiAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcclxuICAgICAgICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cImljb25DbGFzcy5jbGFzc1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpY29uQ2xhc3MuY29uZGl0aW9uID09PSB1bmRlZmluZWQgfHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKGljb25DbGFzcy5jb25kaXRpb24gIT09IHVuZGVmaW5lZCAmJlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICRhbnkoaWNvbkNsYXNzLmNvbmRpdGlvbikocm93KSlcclxuICAgICAgICAgICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICA+e3sgaWNvbkNsYXNzLnRleHQgfX08L3NwYW5cclxuICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICA8dHIgbWF0LWhlYWRlci1yb3cgKm1hdEhlYWRlclJvd0RlZj1cImNvbHVtblByb3BlcnRpZXNcIj48L3RyPlxyXG4gICAgICAgICAgPHRyXHJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcclxuICAgICAgICAgICAgICAnZXhhbXBsZS1lbGVtZW50LXJvdyc6IGRhdGEuaXNOb3RDbGlja2FibGUgPT09IHRydWUsXHJcbiAgICAgICAgICAgICAgJ2V4YW1wbGUtZWxlbWVudC1yb3cgY3Vyc29yLXBvaW50ZXInOiAhZGF0YS5pc05vdENsaWNrYWJsZSxcclxuICAgICAgICAgICAgfVwiXHJcbiAgICAgICAgICAgIG1hdC1yb3dcclxuICAgICAgICAgICAgKm1hdFJvd0RlZj1cImxldCByb3c7IGNvbHVtbnM6IGNvbHVtblByb3BlcnRpZXNcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwiZ29Ub0RldGFpbHMocm93KVwiXHJcbiAgICAgICAgICA+PC90cj5cclxuXHJcbiAgICAgICAgICA8IS0tIFJPVyBTSE9XTiBXSEVOIFRIRVJFIElTIE5PIE1BVENISU5HIERBVEEuIC0tPlxyXG4gICAgICAgICAgPHRyIGNsYXNzPVwibWF0LXJvd1wiICptYXROb0RhdGFSb3c+XHJcbiAgICAgICAgICAgIDx0ZCAqbmdJZj1cIiEoaXNMb2FkaW5nJCB8IGFzeW5jKVwiIGNsYXNzPVwibWF0LWNlbGwgcC00XCIgY29sc3Bhbj1cIjRcIj5cclxuICAgICAgICAgICAgICBOZW5odW0gcmVzdWx0YWRvIGVuY29udHJhZG8gcGFyYSBhIGJ1c2NhXHJcbiAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgIDwvdGFibGU+XHJcblxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGp1c3RpZnktY2VudGVyXCIgKm5nSWY9XCJpc0xvYWRpbmckIHwgYXN5bmNcIj5cclxuICAgICAgICAgIDxtYXQtc3Bpbm5lcj48L21hdC1zcGlubmVyPlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwicGFnaW5hdG9yLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgPG1hdC1wYWdpbmF0b3JcclxuICAgICAgICAgICAgI3BhZ2luYXRvclxyXG4gICAgICAgICAgICBbcGFnZVNpemVPcHRpb25zXT1cIlsyNSwgNTAsIDEwMF1cIlxyXG4gICAgICAgICAgICBbcGFnZVNpemVdPVwicGFnZVNpemVcIlxyXG4gICAgICAgICAgICBbbGVuZ3RoXT1cInRvdGFsSXRlbXNcIlxyXG4gICAgICAgICAgICBzaG93Rmlyc3RMYXN0QnV0dG9uc1xyXG4gICAgICAgICAgICBhcmlhLWxhYmVsPVwiU2VsZWN0IHBhZ2Ugb2YgcGVyaW9kaWMgZWxlbWVudHNcIlxyXG4gICAgICAgICAgICAocGFnZSk9XCJvblBhZ2VDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cIntcclxuICAgICAgICAgICAgICAnaGlkZS1sZW5ndGgnOlxyXG4gICAgICAgICAgICAgICAgWydmaWx0ZXInLCAnZmlsdGVyQnlEYXRlJywgJ2VxdWFscyddLmluY2x1ZGVzKFxyXG4gICAgICAgICAgICAgICAgICB0aGlzLmN1cnJlbnRBcnJhbmdlXHJcbiAgICAgICAgICAgICAgICApIHx8IHRoaXMuZGF0YS5maWx0ZXJGbixcclxuICAgICAgICAgICAgICAnaGlkZS1uZXh0LWJ1dHRvbic6ICFoYXNOZXh0UGFnZSAmJiBkYXRhLnBhZ2luYXRpb24gPT09IHRydWUsXHJcbiAgICAgICAgICAgICAgJ2hpZGUtbGFzdC1idXR0b24nOlxyXG4gICAgICAgICAgICAgICAgKCFoYXNOZXh0UGFnZSAmJiBkYXRhLnBhZ2luYXRpb24gPT09IHRydWUpIHx8XHJcbiAgICAgICAgICAgICAgICB0aGlzLmRhdGEuZmlsdGVyRm4sXHJcbiAgICAgICAgICAgIH1cIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgPC9tYXQtcGFnaW5hdG9yPlxyXG4gICAgICAgICAgPGRpdlxyXG4gICAgICAgICAgICAqbmdJZj1cIlxyXG4gICAgICAgICAgICAgICEoaXNMb2FkaW5nJCB8IGFzeW5jKSAmJlxyXG4gICAgICAgICAgICAgIGRhdGFTb3VyY2U/LmRhdGEgJiZcclxuICAgICAgICAgICAgICBkYXRhU291cmNlLmRhdGEubGVuZ3RoID4gMCAmJlxyXG4gICAgICAgICAgICAgIGRhdGE/LmZpbHRlckZuXHJcbiAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwicGFnZS1udW1iZXItZGlzcGxheVwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIHt7IGN1cnJlbnRQYWdlTnVtYmVyIH19XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBUT09MVElQIFBFUlNPTkFMSVpBRE8gLS0+XHJcbiAgPGxpYi10YWJsZS10b29sdGlwXHJcbiAgICBbc3RhdGVdPVwidG9vbHRpcFN0YXRlXCJcclxuICAgIFtzdHlsZXNdPVwiZ2V0VG9vbHRpcFN0eWxlcygpXCJcclxuICA+PC9saWItdGFibGUtdG9vbHRpcD5cclxuPC9kaXY+XHJcbiJdfQ==