@libs-ui/components-table 0.2.78

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 (35) hide show
  1. package/README.md +3 -0
  2. package/esm2022/index.mjs +4 -0
  3. package/esm2022/interfaces/button-action-event.interface.mjs +3 -0
  4. package/esm2022/interfaces/button-bar-event.interface.mjs +3 -0
  5. package/esm2022/interfaces/function-control-event.interface.mjs +2 -0
  6. package/esm2022/interfaces/hover-button-action-event.interface.mjs +2 -0
  7. package/esm2022/interfaces/index.mjs +11 -0
  8. package/esm2022/interfaces/load-more-event.interface.mjs +2 -0
  9. package/esm2022/interfaces/no-data-config.interface.mjs +2 -0
  10. package/esm2022/interfaces/sort-event.interface.mjs +2 -0
  11. package/esm2022/interfaces/table-config.interface.mjs +2 -0
  12. package/esm2022/interfaces/table.type.mjs +2 -0
  13. package/esm2022/interfaces/template-config.interface.mjs +3 -0
  14. package/esm2022/libs-ui-components-table.mjs +5 -0
  15. package/esm2022/table.component.mjs +608 -0
  16. package/esm2022/templates/template.abstract.component.mjs +16 -0
  17. package/esm2022/templates/templates.component.mjs +111 -0
  18. package/fesm2022/libs-ui-components-table.mjs +735 -0
  19. package/fesm2022/libs-ui-components-table.mjs.map +1 -0
  20. package/index.d.ts +3 -0
  21. package/interfaces/button-action-event.interface.d.ts +12 -0
  22. package/interfaces/button-bar-event.interface.d.ts +7 -0
  23. package/interfaces/function-control-event.interface.d.ts +13 -0
  24. package/interfaces/hover-button-action-event.interface.d.ts +4 -0
  25. package/interfaces/index.d.ts +10 -0
  26. package/interfaces/load-more-event.interface.d.ts +4 -0
  27. package/interfaces/no-data-config.interface.d.ts +8 -0
  28. package/interfaces/sort-event.interface.d.ts +5 -0
  29. package/interfaces/table-config.interface.d.ts +88 -0
  30. package/interfaces/table.type.d.ts +12 -0
  31. package/interfaces/template-config.interface.d.ts +60 -0
  32. package/package.json +25 -0
  33. package/table.component.d.ts +137 -0
  34. package/templates/template.abstract.component.d.ts +7 -0
  35. package/templates/templates.component.d.ts +25 -0
@@ -0,0 +1,608 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ import { AsyncPipe, NgClass, NgComponentOutlet, NgStyle, NgTemplateOutlet } from "@angular/common";
3
+ import { HttpParams } from "@angular/common/http";
4
+ import { ChangeDetectionStrategy, Component, computed, effect, inject, input, output, signal, untracked, viewChild } from "@angular/core";
5
+ import { VirtualScrollerModule } from '@iharbeck/ngx-virtual-scroller';
6
+ import { LibsUiComponentsButtonsButtonComponent } from '@libs-ui/components-buttons-button';
7
+ import { LibsUiComponentsButtonsSortArrowComponent } from '@libs-ui/components-buttons-sort';
8
+ import { LibsUiComponentsCheckboxSingleComponent } from "@libs-ui/components-checkbox-single";
9
+ import { LibsUiComponentsDropdownComponent } from '@libs-ui/components-dropdown';
10
+ import { LibsUiComponentsPopoverComponent } from "@libs-ui/components-popover";
11
+ import { LibsUiComponentsScrollOverlayDirective } from "@libs-ui/components-scroll-overlay";
12
+ import { LibsUiComponentsSpinnerComponent } from "@libs-ui/components-spinner";
13
+ import { LibsUiIconsGetIconComponentPipe } from "@libs-ui/icons";
14
+ import { LibsUiPipesCallFunctionInTemplatePipe } from "@libs-ui/pipes-call-function-in-template";
15
+ import { LibsUiPipesCheckSelectedByKeyPipe } from '@libs-ui/pipes-check-selected-by-key';
16
+ import { LibsUiPipesConvertObjectToSignalPipe } from '@libs-ui/pipes-convert-object-to-signal';
17
+ import { LibsUiHttpRequestService } from "@libs-ui/services-http-request";
18
+ import { convertObjectToSignal, deleteUnicode, get, set, viewDataNumberByLanguage } from "@libs-ui/utils";
19
+ import { TranslateModule } from "@ngx-translate/core";
20
+ import { lastValueFrom, Subject, takeUntil, timer } from "rxjs";
21
+ import { LibsUiComponentsTableTemplatesComponent } from "./templates/templates.component";
22
+ import * as i0 from "@angular/core";
23
+ import * as i1 from "@ngx-translate/core";
24
+ import * as i2 from "@iharbeck/ngx-virtual-scroller";
25
+ export class LibsUiComponentsTableComponent {
26
+ /** PROPERTY */
27
+ classHeaderContainer = computed(() => `libs-ui-table-header-container w-full flex ${this.ignoreClassBgHeader() ? '' : 'bg-white'} overflow-x-hidden z-[1] items-center ${this.classHeaderInclude() || ''}`);
28
+ keysSelected = signal([]);
29
+ loading = signal(false);
30
+ stores = signal([]);
31
+ items = signal([]);
32
+ itemFooter = signal({});
33
+ itemOfIndexHover;
34
+ keySearch = signal('');
35
+ totalItemInBackend = signal(0);
36
+ hasItemHightLight = signal(false);
37
+ totalItemDisplay = computed(() => viewDataNumberByLanguage((this.totalItem() ?? this.totalItemInBackend()), false));
38
+ hasScroll = signal(false);
39
+ instanceSort = signal(undefined);
40
+ hasActionButtonDropdownContent = signal(false);
41
+ pagingStore = signal({});
42
+ loadedLastItem = signal(false);
43
+ storeParamsCallApi = signal({});
44
+ timeoutLeaveItem = signal(undefined);
45
+ functionControlSelectMoreItem;
46
+ onDestroy = new Subject();
47
+ /** INPUT */
48
+ timeHighlighNewItem = input(2000, { transform: val => val ?? 2000 });
49
+ headerLeft = input([], { transform: val => val ?? [] });
50
+ headerRight = input([], { transform: val => val ?? [] });
51
+ configTemplateItemCollapseExpand = input();
52
+ showFooter = input();
53
+ ignoreBorderFooter = input();
54
+ customPositionFooter = input('bottom', { transform: val => val ?? 'bottom' });
55
+ footerLeft = input();
56
+ footerRight = input();
57
+ disableCheckbox = input(false, { transform: val => val ?? false });
58
+ enableUnequalChildrenSizes = input(false, { transform: val => val ?? false });
59
+ bufferAmount = input(5, { transform: val => val ? (val > 25 ? 25 : val) : 5 });
60
+ totalItem = input();
61
+ isDashBorder = input();
62
+ classHeaderInclude = input();
63
+ classBodyInclude = input('', { transform: val => val ?? '' });
64
+ classFooterInclude = input('', { transform: val => val ?? '' });
65
+ fieldKey = input('id', { transform: val => val || 'id' }); // tên field định danh item của listDatas
66
+ defaultKeysSelected = input();
67
+ labelBarNoSelectItem = input(`i18n_total_quantity`); // sử dụng để hiên thị khi tích chọn item
68
+ labelBarButtons = input('i18n_number_item_selected', { transform: val => val || 'i18n_number_item_selected' }); // sử dụng để hiên thị khi tích chọn item
69
+ classLabelBarButtons = input('', { transform: val => val ?? '' }); // sử dụng để hiên thị khi tích chọn item
70
+ barButtons = input();
71
+ sortLocal = input(); // trường hợp nếu sortLocal này không đáp ứng được nghiệp vụ thì mới cân nhắc sử dụng filterLocal
72
+ filterOrSortLocal = input();
73
+ httpRequestData = input();
74
+ httpRequestDataFooter = input();
75
+ newData = input();
76
+ filter = input({ filterData: {} }, { transform: val => val ?? { filterData: {} } });
77
+ ignoreBar = input();
78
+ classLabelBarNoSelectItem = input();
79
+ ignoreClassBgHeader = input();
80
+ noDataConfig = input({ textNoData: 'i18n_no_data_yet', textSearchNoData: 'i18n_no_result' });
81
+ ignoreBorderItemLast = input();
82
+ isHiddenHeaderWhenNodata = input();
83
+ maxItemSelected = input(100, { transform: val => val ?? 100 });
84
+ configSelectMoreItem = input();
85
+ onlyShowNoResult = input();
86
+ ignoreBorderItem = input();
87
+ /** OUTPUT */
88
+ outLoadMore = output();
89
+ outScrollIsGone = output();
90
+ outLoading = output();
91
+ outClickButtonAction = output();
92
+ outSort = output();
93
+ outClickBarButton = output();
94
+ outHoverButtonAction = output();
95
+ outKeysSelected = output();
96
+ outFunctionsControl = output();
97
+ outLoadDataComplete = output();
98
+ outTotalItem = output();
99
+ outLoadDataError = output();
100
+ /**VIEW CHILD */
101
+ headerElementRef = viewChild('headerElementRef');
102
+ footerElementRef = viewChild('footerElementRef');
103
+ footerLeftElementRef = viewChild('footerLeftElementRef');
104
+ bodyElementRef = viewChild('bodyElementRef');
105
+ bodyComponentRef = viewChild('bodyComponentRef');
106
+ ;
107
+ httpRequestService = inject(LibsUiHttpRequestService);
108
+ constructor() {
109
+ effect(() => {
110
+ if (this.defaultKeysSelected()?.length) {
111
+ untracked(() => this.keysSelected.update(keys => ([...keys, ...(this.defaultKeysSelected() || [])])));
112
+ }
113
+ });
114
+ effect(() => {
115
+ if (this.showFooter()) {
116
+ untracked(() => this.callApiByServiceFooter());
117
+ }
118
+ });
119
+ effect(() => {
120
+ if (this.newData()?.data().length) {
121
+ untracked(() => this.addItems(this.newData()?.data, !this.newData()?.addToLastList));
122
+ }
123
+ });
124
+ effect(() => {
125
+ if (!this.filter().filterData || this.filter().ignoreCallApiAuto) {
126
+ return;
127
+ }
128
+ untracked(() => {
129
+ this.keySearch.set(get(this.filter().filterData, 'keySearch', ''));
130
+ this.storeParamsCallApi.set(this.filter());
131
+ if (this.filter()?.filterData && !this.filter().filterData['instanceSort'] && this.instanceSort()) {
132
+ this.storeParamsCallApi.update(data => ({ ...data, instanceSort: this.instanceSort() }));
133
+ }
134
+ if (this.filterOrSortLocal() && this.stores().length) {
135
+ this.items.set(this.filterOrSortLocal()?.(signal([...this.stores()]), { ...(this.filter().filterData || {}), instanceSort: this.instanceSort() }) || []);
136
+ return;
137
+ }
138
+ this.callApiByService(true);
139
+ });
140
+ });
141
+ }
142
+ ngOnInit() {
143
+ this.outFunctionsControl.emit({
144
+ reset: this.reset.bind(this),
145
+ callApiByService: this.callApiByService.bind(this),
146
+ resetScroll: this.resetScroll.bind(this),
147
+ addItems: this.addItems.bind(this),
148
+ removeItems: this.removeItems.bind(this),
149
+ getCount: this.getCount.bind(this),
150
+ getScrollContainer: this.getScrollContainer.bind(this),
151
+ hideToolBarBottom: () => {
152
+ return;
153
+ },
154
+ resetKeySelected: () => this.keysSelected.set([])
155
+ });
156
+ }
157
+ getScrollContainer() {
158
+ return this.bodyComponentRef();
159
+ }
160
+ async callApiByService(firstCall, resetAfterCallApi) {
161
+ try {
162
+ if (firstCall) {
163
+ this.loadedLastItem.set(false);
164
+ }
165
+ if (!this.httpRequestData() || this.loading() || this.loadedLastItem()) {
166
+ return;
167
+ }
168
+ this.loading.set(true);
169
+ this.outLoading.emit(this.loading());
170
+ this.resetIndexHover();
171
+ const { argumentsValue, guideAutoUpdateArgumentsValue } = this.httpRequestData();
172
+ if (guideAutoUpdateArgumentsValue && !guideAutoUpdateArgumentsValue.sortOrderBy && this.instanceSort()) {
173
+ guideAutoUpdateArgumentsValue.sortOrderBy = {
174
+ fieldGetValue: 'storeParamsCallApi.instanceSort.fieldSort',
175
+ fieldUpdate: '[0]',
176
+ subFieldUpdate: 'order_by'
177
+ };
178
+ }
179
+ if (guideAutoUpdateArgumentsValue && !guideAutoUpdateArgumentsValue.sortOrderType && this.instanceSort()) {
180
+ guideAutoUpdateArgumentsValue.sortOrderType = {
181
+ fieldGetValue: 'storeParamsCallApi.instanceSort.mode',
182
+ fieldUpdate: '[0]',
183
+ subFieldUpdate: 'order_type'
184
+ };
185
+ }
186
+ if (firstCall) {
187
+ if (!resetAfterCallApi) {
188
+ this.hasScroll.set(false);
189
+ this.stores.set([]);
190
+ this.items.set([]);
191
+ }
192
+ this.loadedLastItem.set(this.httpRequestService.updateArguments(argumentsValue, { ...this.fakeResponseApi(), storeParamsCallApi: this.storeParamsCallApi() }, this.pagingStore(), this.keySearch(), true, this.loadedLastItem(), guideAutoUpdateArgumentsValue));
193
+ }
194
+ const result = await this.httpRequestService.callApi(this.httpRequestData());
195
+ if (firstCall && resetAfterCallApi) {
196
+ this.hasScroll.set(false);
197
+ this.stores.set([]);
198
+ this.items.set([]);
199
+ }
200
+ this.pagingStore.set(result.paging);
201
+ this.totalItemInBackend.set(result.paging?.total_items || 0);
202
+ this.outTotalItem.emit(this.totalItemInBackend());
203
+ if (!this.pagingStore()) {
204
+ this.loadedLastItem.set(true);
205
+ }
206
+ this.loadedLastItem.set(this.httpRequestService.updateArguments(argumentsValue, { ...result, storeParamsCallApi: this.storeParamsCallApi() }, this.pagingStore(), this.keySearch(), true, this.loadedLastItem(), guideAutoUpdateArgumentsValue));
207
+ await this.addItems(convertObjectToSignal(result.data || []), false, true);
208
+ this.outLoadDataComplete.emit(this.stores);
209
+ }
210
+ catch (error) {
211
+ console.log(error);
212
+ this.outLoadDataError.emit(error);
213
+ }
214
+ finally {
215
+ this.loading.set(false);
216
+ this.outLoading.emit(this.loading());
217
+ }
218
+ }
219
+ fakeResponseApi() {
220
+ this.loadedLastItem.set(false);
221
+ this.pagingStore.set({});
222
+ return this.httpRequestService.fakeResponsePagingApi();
223
+ }
224
+ async callApiByServiceFooter() {
225
+ if (!this.httpRequestDataFooter() || !this.showFooter()) {
226
+ return;
227
+ }
228
+ const { argumentsValue, guideAutoUpdateArgumentsValue } = this.httpRequestDataFooter();
229
+ this.httpRequestService.updateArguments(argumentsValue, { storeParamsCallApi: this.storeParamsCallApi() }, this.pagingStore(), this.keySearch(), true, false, guideAutoUpdateArgumentsValue);
230
+ const result = await this.httpRequestService.callApi(this.httpRequestDataFooter());
231
+ this.itemFooter.set(convertObjectToSignal(result.data)());
232
+ }
233
+ async addItems(items, addFirst, ignoreHightLight, ignoreReCallFooter, autoCountNewItem) {
234
+ if (!items() || !items().length) {
235
+ return;
236
+ }
237
+ const itemsAdd = [];
238
+ items().forEach(item => {
239
+ if (!this.checkExistItem(item)) {
240
+ itemsAdd.push(item);
241
+ if (!ignoreHightLight) {
242
+ this.hasItemHightLight.set(true);
243
+ item.update(data => ({ ...data, specificHightLight: true }));
244
+ }
245
+ if (addFirst) {
246
+ this.items.update(data => [item, ...data]);
247
+ this.stores.update(data => [item, ...data]);
248
+ return;
249
+ }
250
+ this.items.update(data => [...data, item]);
251
+ this.stores.update(data => [...data, item]);
252
+ }
253
+ });
254
+ if (autoCountNewItem && itemsAdd.length) {
255
+ this.totalItemInBackend.update(value => value + itemsAdd.length);
256
+ }
257
+ if (!ignoreHightLight) {
258
+ setTimeout(() => {
259
+ itemsAdd.forEach(item => item.update(data => ({ ...data, specificHightLight: false })));
260
+ this.hasItemHightLight.set(false);
261
+ }, this.timeHighlighNewItem());
262
+ }
263
+ await this.checkScroll();
264
+ if (!ignoreReCallFooter) {
265
+ await this.callApiByServiceFooter();
266
+ }
267
+ }
268
+ checkExistItem(itemNew) {
269
+ return this.items().find(item => `${item()[this.fieldKey()]}` === `${itemNew()[this.fieldKey()]}`) ? true : false;
270
+ }
271
+ async removeItems(keys, ignoreReCallFooter) {
272
+ this.resetIndexHover();
273
+ if (!this.items().length) {
274
+ return;
275
+ }
276
+ keys.forEach(key => {
277
+ this.items.update(items => {
278
+ let isUpdate = false;
279
+ const newItems = items.filter(item => {
280
+ if (`${item()[this.fieldKey()]}` === `${key}`) {
281
+ isUpdate = true;
282
+ return false;
283
+ }
284
+ return true;
285
+ });
286
+ return isUpdate ? newItems : items;
287
+ });
288
+ this.stores.update(items => {
289
+ let isUpdate = false;
290
+ const newItems = items.filter(item => {
291
+ if (`${item()[this.fieldKey()]}` === `${key}`) {
292
+ isUpdate = true;
293
+ return false;
294
+ }
295
+ return true;
296
+ });
297
+ return isUpdate ? newItems : items;
298
+ });
299
+ if (!this.keysSelected() || !this.keysSelected().length) {
300
+ return;
301
+ }
302
+ this.keysSelected.update(keys => keys.filter(keySelected => keySelected !== key));
303
+ });
304
+ this.totalItemInBackend.update(value => value - keys.length);
305
+ await this.checkScroll();
306
+ if (!ignoreReCallFooter) {
307
+ await this.callApiByServiceFooter();
308
+ }
309
+ this.outKeysSelected.emit({ keys: this.keysSelected() });
310
+ }
311
+ getCount() {
312
+ if (this.httpRequestData()) {
313
+ return this.pagingStore()?.total_items || this.items().length;
314
+ }
315
+ return this.items().length;
316
+ }
317
+ handlerScroll(e) {
318
+ e.stopPropagation();
319
+ this.headerElementRef().nativeElement.scrollLeft = e.target.scrollLeft;
320
+ if (this.footerElementRef()) {
321
+ this.footerElementRef().nativeElement.scrollLeft = e.target.scrollLeft;
322
+ }
323
+ this.resetIndexHover(e);
324
+ }
325
+ handlerScrollBottom(e) {
326
+ e.stopPropagation();
327
+ this.loadMore();
328
+ }
329
+ loadMore() {
330
+ if (this.loading()) {
331
+ return;
332
+ }
333
+ this.outLoadMore.emit({ loadMoreSuccess: this.loadMoreSuccess.bind(this) });
334
+ this.callApiByService(false);
335
+ }
336
+ loadMoreSuccess(data) {
337
+ this.addItems(data, false);
338
+ this.loading.set(false);
339
+ this.outLoading.emit(this.loading());
340
+ }
341
+ handlerChangeAllChecked() {
342
+ this.keysSelected.set([]);
343
+ this.outKeysSelected.emit({ keys: this.keysSelected() });
344
+ }
345
+ handlerChangeCheckedAllItems(event) {
346
+ if (event.checked) {
347
+ this.keysSelected.set(this.items().filter(async (item) => !(await this.checkCancelConditionCheckedItem(item))).map(item => `${item()[this.fieldKey()]}`));
348
+ this.outKeysSelected.emit({ keys: this.keysSelected() });
349
+ return;
350
+ }
351
+ this.keysSelected.set([]);
352
+ this.outKeysSelected.emit({ keys: this.keysSelected() });
353
+ }
354
+ async checkCancelConditionCheckedItem(item) {
355
+ let isCancelCheck = false;
356
+ if (!isCancelCheck && this.headerLeft().length && this.headerLeft()[0].checkConditionCheckBoxHidden) {
357
+ isCancelCheck = await lastValueFrom(this.headerLeft()[0].checkConditionCheckBoxHidden({ item: item() })) || false;
358
+ }
359
+ if (!isCancelCheck && this.headerRight().length && this.headerRight()[0].checkConditionCheckBoxHidden) {
360
+ isCancelCheck = await lastValueFrom(this.headerRight()[0].checkConditionCheckBoxHidden({ item: item() })) || false;
361
+ }
362
+ return isCancelCheck;
363
+ }
364
+ handlerChangeItemChecked(event, item) {
365
+ const key = item[this.fieldKey()];
366
+ const keys = new Set(this.keysSelected());
367
+ keys.add(key);
368
+ if (!event.checked) {
369
+ keys.delete(key);
370
+ }
371
+ this.keysSelected.set(Array.from(keys));
372
+ this.outKeysSelected.emit({ keys: this.keysSelected() });
373
+ }
374
+ handlerChangeSort(sort) {
375
+ if (this.instanceSort && this.instanceSort()?.fieldSort !== sort.fieldSort) {
376
+ this.instanceSort()?.reset();
377
+ }
378
+ this.instanceSort.set(sort);
379
+ if (this.sortLocal()) {
380
+ this.handlerSortLocal(sort);
381
+ return;
382
+ }
383
+ this.storeParamsCallApi.update(data => ({ ...data, instanceSort: this.instanceSort() }));
384
+ this.callApiByService(true);
385
+ this.outSort.emit({
386
+ sort: sort,
387
+ onSortSuccess: this.onSortSuccess.bind(this)
388
+ });
389
+ }
390
+ handlerSortLocal(sort) {
391
+ if (this.filterOrSortLocal() && this.stores().length) {
392
+ this.items.set(this.filterOrSortLocal()?.(signal([...this.stores()]), { ...this.storeParamsCallApi(), instanceSort: sort }) || []);
393
+ return;
394
+ }
395
+ const { fieldSort, mode } = sort;
396
+ this.items.update(items => {
397
+ items.sort((itemA, itemB) => {
398
+ let value1 = mode === 'asc' ? itemA()[fieldSort] : itemB()[fieldSort];
399
+ let value2 = mode === 'asc' ? itemB()[fieldSort] : itemA()[fieldSort];
400
+ if (typeof value1 === 'string' && typeof value2 === 'string') {
401
+ value1 = deleteUnicode(value1).toLocaleLowerCase();
402
+ value2 = deleteUnicode(value2).toLocaleLowerCase();
403
+ }
404
+ if (value1 === value2) {
405
+ return 0;
406
+ }
407
+ return value1 > value2 ? 1 : -1;
408
+ });
409
+ return [...items];
410
+ });
411
+ this.onSortSuccess();
412
+ }
413
+ handlerFunctionControlMoreSelectItem(functionControl) {
414
+ this.functionControlSelectMoreItem = functionControl;
415
+ }
416
+ handlerSelectedMoreItem(event) {
417
+ if (!event || !event.key || !this.configSelectMoreItem()) {
418
+ return;
419
+ }
420
+ this.functionControlSelectMoreItem?.reset();
421
+ const perPage = Number(event.key).valueOf();
422
+ const currentPage = Number(this.setPerPageSelectMoreItem(perPage)).valueOf();
423
+ const isPagingNumber = this.configSelectMoreItem()?.pagingNumber;
424
+ if (currentPage > perPage || this.items.length >= perPage) {
425
+ if (!isPagingNumber) {
426
+ this.setPerPageSelectMoreItem(currentPage);
427
+ }
428
+ this.keysSelected.set(this.items().slice(0, perPage).map(item => `${item()[this.fieldKey()]}`));
429
+ return;
430
+ }
431
+ this.callApiByService(true, true);
432
+ const sub = this.outLoadDataComplete.subscribe(() => {
433
+ sub.unsubscribe();
434
+ if (!isPagingNumber) {
435
+ this.setPerPageSelectMoreItem(currentPage);
436
+ }
437
+ this.keysSelected.set(this.items().slice(0, perPage).map(item => `${item()[this.fieldKey()]}`));
438
+ });
439
+ this.outLoadDataError.subscribe(() => {
440
+ this.setPerPageSelectMoreItem(currentPage);
441
+ });
442
+ }
443
+ setPerPageSelectMoreItem(perPage) {
444
+ const argumentsValue = this.httpRequestData()?.argumentsValue;
445
+ if (!argumentsValue || !this.configSelectMoreItem()) {
446
+ return '-1';
447
+ }
448
+ const keyPerPage = this.configSelectMoreItem()?.keyPerPage || 'per_page';
449
+ for (let i = 0; i < argumentsValue.length; i++) {
450
+ let argument = argumentsValue[i];
451
+ if (argument instanceof HttpParams && argument.has(keyPerPage)) {
452
+ const currentPerPage = argument.get(keyPerPage) || '25';
453
+ argument = argument.set(keyPerPage, perPage);
454
+ set(argumentsValue, `${i}`, argument);
455
+ return currentPerPage;
456
+ }
457
+ if (argument instanceof Object && Object.keys(argument).includes(keyPerPage)) {
458
+ const currentPerPage = argument.get(keyPerPage) || '25';
459
+ set(argument, keyPerPage, perPage);
460
+ return currentPerPage;
461
+ }
462
+ }
463
+ return '-1';
464
+ }
465
+ onSortSuccess() {
466
+ this.loading.set(false);
467
+ this.outLoading.emit(this.loading());
468
+ this.resetScroll();
469
+ }
470
+ handlerButtonClick(type, buttonDropdownData, button) {
471
+ if (type === 'button') {
472
+ return this.outClickButtonAction.emit({ item: this.itemOfIndexHover, button: button });
473
+ }
474
+ this.outClickButtonAction.emit({ item: this.itemOfIndexHover, button, buttonDropdownData });
475
+ }
476
+ handlerBarButtonClick(button) {
477
+ const items = [];
478
+ this.keysSelected().forEach(key => {
479
+ const item = this.items().find(item => `${item()[this.fieldKey()]}` === `${key}`);
480
+ if (item) {
481
+ items.push(item);
482
+ }
483
+ });
484
+ return this.outClickBarButton.emit({
485
+ button,
486
+ items,
487
+ keys: this.keysSelected(),
488
+ hiddenBarButtons: () => {
489
+ return;
490
+ }
491
+ });
492
+ }
493
+ handlerButtonDropdownEvent(eventName) {
494
+ this.hasActionButtonDropdownContent.set(true);
495
+ if (eventName === 'remove' || eventName === 'mouseleave-content') {
496
+ this.hasActionButtonDropdownContent.set(false);
497
+ }
498
+ }
499
+ setIndexHover(e, item) {
500
+ e.stopPropagation();
501
+ if (!this.items().length) {
502
+ this.resetIndexHover();
503
+ return;
504
+ }
505
+ this.itemOfIndexHover = item;
506
+ }
507
+ resetIndexHoverWhenMouseLeave(e) {
508
+ e?.stopPropagation();
509
+ const currentIndexItemHover = this.itemOfIndexHover;
510
+ clearTimeout(this.timeoutLeaveItem());
511
+ this.timeoutLeaveItem.set(setTimeout(() => {
512
+ if (this.itemOfIndexHover && this.itemOfIndexHover !== currentIndexItemHover) {
513
+ return;
514
+ }
515
+ this.resetIndexHover(e);
516
+ }));
517
+ }
518
+ resetIndexHover(e) {
519
+ e?.stopPropagation();
520
+ if (this.hasActionButtonDropdownContent()) {
521
+ return;
522
+ }
523
+ this.itemOfIndexHover = undefined;
524
+ }
525
+ handlerMouseEnter(event) {
526
+ event.stopPropagation();
527
+ this.resetIndexHover(event);
528
+ if (this.classFooterInclude()) {
529
+ this.footerElementRef()?.nativeElement?.classList.remove('bg-[#f8f9fa]');
530
+ this.footerLeftElementRef()?.nativeElement?.classList.remove('bg-[#f8f9fa]');
531
+ this.footerElementRef()?.nativeElement?.classList.add(this.classFooterInclude());
532
+ this.footerLeftElementRef()?.nativeElement?.classList.add(this.classFooterInclude());
533
+ }
534
+ }
535
+ handlerMouseLeave(event) {
536
+ event.stopPropagation();
537
+ if (this.classFooterInclude()) {
538
+ this.footerElementRef()?.nativeElement?.classList.remove(this.classFooterInclude());
539
+ this.footerLeftElementRef()?.nativeElement?.classList.remove(this.classFooterInclude());
540
+ this.footerElementRef()?.nativeElement?.classList.add('bg-[#f8f9fa]');
541
+ this.footerLeftElementRef()?.nativeElement?.classList.add('bg-[#f8f9fa]');
542
+ }
543
+ }
544
+ resetScroll() {
545
+ if (this.headerElementRef()) {
546
+ this.headerElementRef().nativeElement.scrollLeft = 0;
547
+ }
548
+ if (this.BodyElement) {
549
+ this.BodyElement.scrollTop = 0;
550
+ this.BodyElement.scrollLeft = 0;
551
+ }
552
+ if (this.footerElementRef()) {
553
+ this.footerElementRef().nativeElement.scrollLeft = 0;
554
+ }
555
+ }
556
+ reset(clearSort) {
557
+ if (clearSort) {
558
+ this.instanceSort()?.reset();
559
+ this.instanceSort.set(undefined);
560
+ }
561
+ this.hasScroll.set(false);
562
+ this.loading.set(false);
563
+ this.outLoading.emit(this.loading());
564
+ this.items.set([]);
565
+ this.stores.set([]);
566
+ this.fakeResponseApi();
567
+ }
568
+ async checkScroll() {
569
+ const hasScroll = this.hasScroll();
570
+ return new Promise(resolve => {
571
+ timer(500).pipe(takeUntil(this.onDestroy)).subscribe(() => {
572
+ if (this.BodyElement) {
573
+ this.hasScroll.set(this.BodyElement.scrollHeight > this.BodyElement.offsetHeight);
574
+ }
575
+ if (hasScroll && !this.hasScroll()) {
576
+ this.outScrollIsGone.emit({});
577
+ if (!this.filterOrSortLocal()) {
578
+ this.callApiByService(true);
579
+ }
580
+ }
581
+ resolve();
582
+ });
583
+ });
584
+ }
585
+ get BodyElement() {
586
+ return this.bodyElementRef()?.nativeElement;
587
+ }
588
+ ngOnDestroy() {
589
+ this.onDestroy.next();
590
+ this.onDestroy.complete();
591
+ clearTimeout(this.timeoutLeaveItem());
592
+ }
593
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
594
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: LibsUiComponentsTableComponent, isStandalone: true, selector: "libs_ui-components-table", inputs: { timeHighlighNewItem: { classPropertyName: "timeHighlighNewItem", publicName: "timeHighlighNewItem", isSignal: true, isRequired: false, transformFunction: null }, headerLeft: { classPropertyName: "headerLeft", publicName: "headerLeft", isSignal: true, isRequired: false, transformFunction: null }, headerRight: { classPropertyName: "headerRight", publicName: "headerRight", isSignal: true, isRequired: false, transformFunction: null }, configTemplateItemCollapseExpand: { classPropertyName: "configTemplateItemCollapseExpand", publicName: "configTemplateItemCollapseExpand", isSignal: true, isRequired: false, transformFunction: null }, showFooter: { classPropertyName: "showFooter", publicName: "showFooter", isSignal: true, isRequired: false, transformFunction: null }, ignoreBorderFooter: { classPropertyName: "ignoreBorderFooter", publicName: "ignoreBorderFooter", isSignal: true, isRequired: false, transformFunction: null }, customPositionFooter: { classPropertyName: "customPositionFooter", publicName: "customPositionFooter", isSignal: true, isRequired: false, transformFunction: null }, footerLeft: { classPropertyName: "footerLeft", publicName: "footerLeft", isSignal: true, isRequired: false, transformFunction: null }, footerRight: { classPropertyName: "footerRight", publicName: "footerRight", isSignal: true, isRequired: false, transformFunction: null }, disableCheckbox: { classPropertyName: "disableCheckbox", publicName: "disableCheckbox", isSignal: true, isRequired: false, transformFunction: null }, enableUnequalChildrenSizes: { classPropertyName: "enableUnequalChildrenSizes", publicName: "enableUnequalChildrenSizes", isSignal: true, isRequired: false, transformFunction: null }, bufferAmount: { classPropertyName: "bufferAmount", publicName: "bufferAmount", isSignal: true, isRequired: false, transformFunction: null }, totalItem: { classPropertyName: "totalItem", publicName: "totalItem", isSignal: true, isRequired: false, transformFunction: null }, isDashBorder: { classPropertyName: "isDashBorder", publicName: "isDashBorder", isSignal: true, isRequired: false, transformFunction: null }, classHeaderInclude: { classPropertyName: "classHeaderInclude", publicName: "classHeaderInclude", isSignal: true, isRequired: false, transformFunction: null }, classBodyInclude: { classPropertyName: "classBodyInclude", publicName: "classBodyInclude", isSignal: true, isRequired: false, transformFunction: null }, classFooterInclude: { classPropertyName: "classFooterInclude", publicName: "classFooterInclude", isSignal: true, isRequired: false, transformFunction: null }, fieldKey: { classPropertyName: "fieldKey", publicName: "fieldKey", isSignal: true, isRequired: false, transformFunction: null }, defaultKeysSelected: { classPropertyName: "defaultKeysSelected", publicName: "defaultKeysSelected", isSignal: true, isRequired: false, transformFunction: null }, labelBarNoSelectItem: { classPropertyName: "labelBarNoSelectItem", publicName: "labelBarNoSelectItem", isSignal: true, isRequired: false, transformFunction: null }, labelBarButtons: { classPropertyName: "labelBarButtons", publicName: "labelBarButtons", isSignal: true, isRequired: false, transformFunction: null }, classLabelBarButtons: { classPropertyName: "classLabelBarButtons", publicName: "classLabelBarButtons", isSignal: true, isRequired: false, transformFunction: null }, barButtons: { classPropertyName: "barButtons", publicName: "barButtons", isSignal: true, isRequired: false, transformFunction: null }, sortLocal: { classPropertyName: "sortLocal", publicName: "sortLocal", isSignal: true, isRequired: false, transformFunction: null }, filterOrSortLocal: { classPropertyName: "filterOrSortLocal", publicName: "filterOrSortLocal", isSignal: true, isRequired: false, transformFunction: null }, httpRequestData: { classPropertyName: "httpRequestData", publicName: "httpRequestData", isSignal: true, isRequired: false, transformFunction: null }, httpRequestDataFooter: { classPropertyName: "httpRequestDataFooter", publicName: "httpRequestDataFooter", isSignal: true, isRequired: false, transformFunction: null }, newData: { classPropertyName: "newData", publicName: "newData", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, ignoreBar: { classPropertyName: "ignoreBar", publicName: "ignoreBar", isSignal: true, isRequired: false, transformFunction: null }, classLabelBarNoSelectItem: { classPropertyName: "classLabelBarNoSelectItem", publicName: "classLabelBarNoSelectItem", isSignal: true, isRequired: false, transformFunction: null }, ignoreClassBgHeader: { classPropertyName: "ignoreClassBgHeader", publicName: "ignoreClassBgHeader", isSignal: true, isRequired: false, transformFunction: null }, noDataConfig: { classPropertyName: "noDataConfig", publicName: "noDataConfig", isSignal: true, isRequired: false, transformFunction: null }, ignoreBorderItemLast: { classPropertyName: "ignoreBorderItemLast", publicName: "ignoreBorderItemLast", isSignal: true, isRequired: false, transformFunction: null }, isHiddenHeaderWhenNodata: { classPropertyName: "isHiddenHeaderWhenNodata", publicName: "isHiddenHeaderWhenNodata", isSignal: true, isRequired: false, transformFunction: null }, maxItemSelected: { classPropertyName: "maxItemSelected", publicName: "maxItemSelected", isSignal: true, isRequired: false, transformFunction: null }, configSelectMoreItem: { classPropertyName: "configSelectMoreItem", publicName: "configSelectMoreItem", isSignal: true, isRequired: false, transformFunction: null }, onlyShowNoResult: { classPropertyName: "onlyShowNoResult", publicName: "onlyShowNoResult", isSignal: true, isRequired: false, transformFunction: null }, ignoreBorderItem: { classPropertyName: "ignoreBorderItem", publicName: "ignoreBorderItem", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outLoadMore: "outLoadMore", outScrollIsGone: "outScrollIsGone", outLoading: "outLoading", outClickButtonAction: "outClickButtonAction", outSort: "outSort", outClickBarButton: "outClickBarButton", outHoverButtonAction: "outHoverButtonAction", outKeysSelected: "outKeysSelected", outFunctionsControl: "outFunctionsControl", outLoadDataComplete: "outLoadDataComplete", outTotalItem: "outTotalItem", outLoadDataError: "outLoadDataError" }, viewQueries: [{ propertyName: "headerElementRef", first: true, predicate: ["headerElementRef"], descendants: true, isSignal: true }, { propertyName: "footerElementRef", first: true, predicate: ["footerElementRef"], descendants: true, isSignal: true }, { propertyName: "footerLeftElementRef", first: true, predicate: ["footerLeftElementRef"], descendants: true, isSignal: true }, { propertyName: "bodyElementRef", first: true, predicate: ["bodyElementRef"], descendants: true, isSignal: true }, { propertyName: "bodyComponentRef", first: true, predicate: ["bodyComponentRef"], descendants: true, isSignal: true }], ngImport: i0, template: "<div class='flex flex-col w-full h-full'>\n @if (!ignoreBar()) {\n <div\n class=\"flex items-center justify-between relative z-[1] bottom-0 left-0 w-full bg-white mb-[16px] libs-ui-table-shadow-bottom\"\n [class.px-[16px]]=\"keysSelected().length || labelBarNoSelectItem()\"\n [class.py-[6px]]=\"keysSelected().length || labelBarNoSelectItem()\"\n (mouseenter)=\"resetIndexHover($event)\">\n @if (!keysSelected().length && labelBarNoSelectItem()) {\n <div class=\"{{ classLabelBarNoSelectItem() ?? 'px-[12px] py-[5px]' }}\"\n [innerHtml]='labelBarNoSelectItem() | translate:{value:totalItemDisplay()}'>\n </div>\n }\n @if (keysSelected().length) {\n <div class=\"flex items-center pl-[12px]\">\n <div class=\"flex items-center h-full mt-[-2px]\">\n <libs_ui-components-checkbox-single [checked]=\"true\"\n [disable]=\"loading() || disableCheckbox()\"\n (outChange)=\"handlerChangeAllChecked()\" />\n </div>\n <div class=\"libs-ui-font-h5m text-[#071631] mr-[8px] {{ classLabelBarButtons() }}\">\n {{ labelBarButtons() | translate:{ value:keysSelected().length } }}\n </div>\n @if (configSelectMoreItem()) {\n <libs_ui-components-dropdown [isNgContent]=\"true\"\n [popoverCustomConfig]=\"{\n widthByParent:false,\n ignoreArrow: true,\n maxHeight: 2048,\n classInclude:'w-[121px]',\n position: {\n mode:'start',\n distance:0\n }\n }\"\n [listConfig]=\"({\n type:'text',\n configTemplateText:{\n fieldKey:'key',\n ignoreIconSelected:true,\n getValue:configSelectMoreItem()?.getValue\n }\n } | LibsUiPipesConvertObjectToSignalPipe:true)()\"\n [listMaxItemShow]=\"5\"\n class=\"w-[16px] h-[16px] mr-[8px]\"\n (outSelectKey)=\"handlerSelectedMoreItem($event)\"\n (outFunctionsControl)=\"handlerFunctionControlMoreSelectItem($event)\">\n <libs_ui-components-buttons-button [type]=\"'button-link-primary'\"\n [classInclude]=\"'p-0 m-0'\"\n [classIconLeft]=\"'before:!text-[16px] libs-ui-con-dropdown mr-[6px]'\"\n [popover]=\"{config:{content:'i18n_more_select'}}\"\n [ignoreStopPropagationEvent]=\"true\" />\n </libs_ui-components-dropdown>\n }\n <div class=\"h-[16px] libs-ui-border-left-general ml-[16px]\"></div>\n @if (barButtons()?.length) {\n @for (button of barButtons();track button) {\n <libs_ui-components-buttons-button [type]=\"button.type || 'button-link-primary'\"\n [classIconLeft]=\"button.classIconLeft || ''\"\n [classInclude]=\"button.classInclude || ''\"\n [label]=\"(button.label || ' ') | translate\"\n (outClick)=\"handlerBarButtonClick(button)\" />\n }\n }\n </div>\n }\n <ng-content select='div.libs-ui-table-bar-right'></ng-content>\n </div>\n }\n\n <div #tableContainerElementRef\n class=\"libs-ui-table flex flex-col w-full h-full relative\"\n [class.px-[16px]]='!ignoreBar()'\n (mouseleave)=\"resetIndexHover($event)\">\n <div #headerElementRef\n [class.libs-ui-border-bottom-dashed-general]=\"!hasItemHightLight() && isDashBorder()\"\n [class.libs-ui-border-bottom-general]=\"!hasItemHightLight() && !isDashBorder()\"\n [class.!hidden]=\"!items().length && isHiddenHeaderWhenNodata()\"\n [class]=\"classHeaderContainer()\"\n (mouseenter)=\"resetIndexHover($event)\">\n @if (headerLeft().length) {\n <div class=\"h-full flex sticky top-0 left-0 bg-[#ffffff] z-[1]\">\n @for (header of headerLeft();track header) {\n <ng-container *ngTemplateOutlet=\"templateHeaderRef;context:{headerItem:header,isHederLeft:true}\" />\n }\n </div>\n }\n @if (headerRight().length) {\n @for (header of headerRight();track header) {\n <ng-container *ngTemplateOutlet=\"templateHeaderRef;context:{headerItem:header,isHederLeft:false}\" />\n }\n }\n </div>\n @if (showFooter() && itemFooter() && customPositionFooter() === 'top') {\n <ng-container *ngTemplateOutlet='templateFooterRef' />\n }\n <div class=\"relative flex flex-col w-full h-full overflow-x-hidden bg-white {{ classBodyInclude() || '' }}\">\n @if (items().length) {\n <div #bodyElementRef\n class=\"flex h-full w-full relative\"\n LibsUiComponentsScrollOverlayDirective\n [options]=\"{scrollX: (!headerLeft().length || !headerRight()) ? 'hidden':'scroll'}\"\n (outScroll)=\"handlerScroll($event)\"\n (outScrollBottom)=\"handlerScrollBottom($event)\">\n <virtual-scroller #bodyComponentRef\n [items]=\"items()\"\n [enableUnequalChildrenSizes]=\"enableUnequalChildrenSizes()\"\n class=\"h-full\"\n [style.width.px]=\"headerElementRef.scrollWidth > (bodyElementRef ? bodyElementRef.scrollWidth : 0) ? headerElementRef.scrollWidth: undefined\"\n [parentScroll]=\"bodyElementRef\"\n [bufferAmount]=\"bufferAmount()\">\n @for (data of bodyComponentRef.viewPortItems;track data()) {\n <div #elementHover\n class=\"flex\"\n [class.bg-[#f3fcfc]]=\"data().specificHightLight\"\n [class.libs-ui-border-top-1px-36d3d3]=\"data().specificHightLight && $first && !ignoreBorderItem()\"\n [class.libs-ui-border-bottom-1px-36d3d3]=\"data().specificHightLight && !ignoreBorderItem()\"\n [ngClass]=\"(data().specificHightLight || ($last && ignoreBorderItemLast())) ? 'libs-ui-border-radius-bottom-left-4px libs-ui-border-radius-bottom-right-4px' : ignoreBorderItem() ? '' : isDashBorder() ? 'libs-ui-border-bottom-dashed-general' : 'libs-ui-border-bottom-general'\"\n [style.width.px]=\"headerElementRef.scrollWidth\"\n [class.bg-[#f8f9fa]]=\"itemOfIndexHover === data && !data().specificHightLight\"\n (mouseenter)=\"setIndexHover($event,data)\"\n (mouseleave)=\"resetIndexHoverWhenMouseLeave($event)\">\n @if (headerLeft().length || headerRight().length) {\n <div class=\"flex flex-col w-full\">\n <div class=\"flex w-full\">\n @if (headerLeft().length) {\n <div class=\"flex sticky top-0 left-0 z-[1]\"\n [class.bg-white]=\"!data().specificHightLight\"\n [class.bg-[#f3fcfc]]=\"data().specificHightLight\">\n @for (header of headerLeft();track header) {\n <div\n class=\"relative flex px-[12px] py-[8px] {{ header.ignoreBorderRight ? '': 'libs-ui-border-right-general' }}\"\n [class.bg-[#f8f9fa]]=\"itemOfIndexHover === data && !data().specificHightLight\"\n [ngStyle]=\"header.ngStyle || {}\"\n [ngClass]=\"header.ngClass || {}\">\n <ng-container *ngTemplateOutlet=\"templateBodyRef;context:{header:header,data:data}\" />\n </div>\n }\n </div>\n }\n @if (headerRight().length) {\n @for (header of headerRight();track header) {\n <div class=\"relative flex px-[12px] py-[8px]\"\n [ngStyle]=\"header.ngStyle || {}\"\n [ngClass]=\"header.ngClass || {}\">\n <ng-container *ngTemplateOutlet=\"templateBodyRef;context:{header:header,data:data}\" />\n </div>\n }\n }\n </div>\n @if (configTemplateItemCollapseExpand() && data().specificExpand && data()[configTemplateItemCollapseExpand()?.fieldGetDataExpand || 'specificDataExpand']) {\n <div [class]=\"configTemplateItemCollapseExpand()?.cssWrapper || 'flex w-full'\">\n @for (dataExpand of data()[configTemplateItemCollapseExpand()?.fieldGetDataExpand || 'specificDataExpand']();track $index) {\n @if (configTemplateItemCollapseExpand()?.colTemplateConfig) {\n <libs_ui-components-table-templates [item]=\"dataExpand\"\n [templateCssWrapper]=\"configTemplateItemCollapseExpand()?.templateCssWrapper\"\n [configs]=\"configTemplateItemCollapseExpand()?.colTemplateConfig\" />\n }\n } @empty {\n <div class=\"relative h-[100px]\">\n <ng-container *ngTemplateOutlet=\"templateNodataRef\" />\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </virtual-scroller>\n\n @if ((!items().length) && !loading() && noDataConfig()) {\n <div class=\"h-full\"\n [style.flex]=\"'0 0 '+headerElementRef.scrollWidth+'px'\">\n </div>\n }\n </div>\n }\n @if ((!items().length) && !loading()) {\n <div class=\"relative h-full w-full\">\n <ng-container *ngTemplateOutlet=\"templateNodataRef\" />\n </div>\n }\n\n @if (showFooter() && itemFooter() && customPositionFooter() === 'bottom') {\n <ng-container *ngTemplateOutlet='templateFooterRef' />\n }\n\n @if (loading()) {\n <div class=\"absolute w-full h-full z-[2] flex items-center content-center\">\n <libs_ui-components-spinner />\n </div>\n }\n </div>\n </div>\n</div>\n\n<ng-template #templateHeaderRef\n let-header='headerItem'\n let-isHederLeft='isHederLeft'>\n <div\n [class]=\"'relative flex '+ (header.paddingLeftRightHeaderContainer ?? ' px-[12px] ') + (isHederLeft && !header.ignoreBorderRight ? ' libs-ui-border-right-general ' : ' ')+ ' libs-ui-table-header-col '\"\n [class.flex-col]=\"header.rowsConfig\"\n [class.py-[8px]]='!header.ignorePyDefault'\n [ngStyle]=\"header.ngStyle || {}\"\n [ngClass]=\"header.ngClass || {}\">\n @if (!header.rowsConfig) {\n <ng-container *ngTemplateOutlet=\"templateHeaderContentRef;context:{headerItem:header,isColRender:false}\" />\n }\n @if (header.rowsConfig;as rowsConfig) {\n @for (row of rowsConfig.rows;track row) {\n <div [class]=\"row.classRow\">\n @for (col of row.cols ; track col) {\n <ng-container *ngTemplateOutlet=\"templateHeaderContentRef;context:{headerItem:col,isColRender:true}\" />\n }\n </div>\n }\n }\n </div>\n</ng-template>\n\n<ng-template #templateHeaderContentRef\n let-header='headerItem'\n let-isColRender='isColRender'>\n <div class=\"flex libs-ui-font-h6m min-h-[18px] text-[#6a7383] max-w-full\"\n [class.items-center]='header.contentHeaderAlignCenter ?? true'\n [class.justify-end]='header.contentHeaderJustifyContentEnd'\n [ngStyle]=\"isColRender ? (header.ngStyle || {}) : {}\"\n [ngClass]=\"isColRender ? (header.ngClass || {}) : {}\">\n @if (header.hasCheckbox && !header.hasCheckboxAll) {\n <div class=\"flex h-full ml-[24px] {{ header.checkboxClassInclude }}\">\n </div>\n }\n @if (header.hasCheckboxAll) {\n <div class=\"flex h-full {{ header.checkboxAllClassInclude || 'mr-[16px]' }}\"\n [class.items-center]=\"header.checkboxAlignCenter\">\n <libs_ui-components-checkbox-single [key]=\"'all'\"\n [stillOtherOptions]=\"!!keysSelected().length && keysSelected().length !== items().length\"\n [checked]=\"!!keysSelected().length && keysSelected().length === items().length\"\n [disable]=\"loading()\"\n [classInclude]=\"header.checkboxClassInclude\"\n (outChange)=\"handlerChangeCheckedAllItems($event)\" />\n </div>\n }\n @if ((header.label | LibsUiPipesCallFunctionInTemplatePipe:header.parseValue:header)| async | translate; as labelHeaderColumn) {\n <libs_ui-components-popover [type]=\"header?.labelConfig?.type || 'text'\"\n [mode]=\"header?.labelConfig?.mode || 'hover'\"\n [classInclude]=\"(header?.labelConfig?.classInclude || '')\"\n [ignoreShowPopover]=\"header?.labelConfig?.ignoreShowTooltip || false\"\n [config]=\"header.labelConfig?.config || {content:labelHeaderColumn}\"\n [innerHTML]=\"labelHeaderColumn\" />\n }\n\n @if (header.tooltipOther; as tooltip) {\n <div class=\"ml-[4px]\">\n <libs_ui-components-popover [type]=\"tooltip?.type || 'other'\"\n [mode]=\"tooltip?.mode || 'hover'\"\n [classInclude]=\"tooltip.classInclude || 'text-[#6a7383]'\"\n [ignoreShowPopover]=\"tooltip.ignoreShowTooltip || false\"\n [config]=\"tooltip.config || {content:(tooltip.dataView || ' ') | translate, position: {\n mode: 'center',\n distance: 0,\n autoUpdatePosition: {\n endDistance: 12,\n startDistance: -12\n }\n }}\"\n [innerHTML]=\"tooltip.dataView\" />\n </div>\n }\n\n @if (header.hasSort && header.orderby) {\n <div class=\"ml-[4px]\">\n <libs_ui-components-buttons-sort-arrow [disable]=\"loading() || !items().length\"\n [fieldSort]=\"header.orderby\"\n [ignorePopoverContent]=\"header.sortIgnoreTooltipContent ?? true\"\n [popoverContentAsc]=\"header.sortTooltipContentAsc\"\n [popoverContentDesc]=\"header.sortTooltipContentDesc\"\n [defaultMode]=\"header.defaultMode\"\n [zIndex]=\"header.zIndexTooltipSort\"\n (outChange)=\"handlerChangeSort($event)\" />\n </div>\n }\n </div>\n @if (header.labelDescription) {\n <div class=\"flex\">\n <libs_ui-components-popover [type]=\"'text'\"\n [classInclude]=\"header.labelDescription.classInclude || ''\"\n [config]=\"{content: header.labelDescription.content | translate}\"\n [innerHTML]=\"header.labelDescription.content | translate\" />\n </div>\n }\n</ng-template>\n\n<ng-template #templateBodyRef\n let-header='header'\n let-data='data'>\n <div class=\"flex w-full h-full\">\n @if (header.hasCheckbox) {\n <div class=\"flex h-full\"\n [class.invisible]=\"header.checkConditionCheckBoxHidden &&( data() | LibsUiPipesCallFunctionInTemplatePipe:header.checkConditionCheckBoxHidden:data() | async)\"\n [class.items-center]=\"header.checkboxAlignCenter\">\n <libs_ui-components-checkbox-single [key]=\"data()[fieldKey()]\"\n [classInclude]=\"header.checkboxClassInclude\"\n [checked]=\"data()[fieldKey()] | LibsUiPipesCheckSelectedByKeyPipe:keysSelected():keysSelected().length\"\n [disable]=\"loading() || disableCheckbox() || !!(maxItemSelected() && !(data()[fieldKey()] | LibsUiPipesCheckSelectedByKeyPipe:keysSelected():keysSelected().length) && keysSelected().length >= maxItemSelected())\"\n (outChange)=\"handlerChangeItemChecked($event,data())\" />\n </div>\n }\n\n @if (header.colTemplateConfig) {\n <libs_ui-components-table-templates [isHover]=\"itemOfIndexHover === data && !data.specificHightLight\"\n [class]=\"header.templateCssWrapperHost || ''\"\n [item]=\"data\"\n [templateCssWrapper]=\"header.templateCssWrapper\"\n [configs]=\"header.colTemplateConfig\" />\n }\n </div>\n</ng-template>\n\n<ng-template #templateFooterRef>\n @if (!isHiddenHeaderWhenNodata() || (isHiddenHeaderWhenNodata() && items().length)) {\n <div #footerElementRef\n class=\"flex w-full bg-[#f8f9fa] overflow-x-hidden z-[1] {{ ignoreBorderFooter() ? '': (customPositionFooter() === 'top' ? 'libs-ui-border-bottom-general':'libs-ui-table-shadow-top libs-ui-border-top-general') }} min-h-[35px]\"\n (mouseenter)=\"handlerMouseEnter($event)\"\n (mouseleave)=\"handlerMouseLeave($event)\">\n @if (footerLeft()) {\n <div #footerLeftElementRef\n class=\"flex sticky top-0 left-0 z-[1] bg-[#f8f9fa]\">\n @for (footer of footerLeft();track footer) {\n <div\n class=\"flex items-center px-[12px] py-[8px] {{ footer.ignoreBorderRight ? '': 'libs-ui-border-right-general' }}\"\n [ngStyle]=\"footer.ngStyle || {}\"\n [ngClass]=\"footer.ngClass || {}\">\n @if (footer.colTemplateConfig) {\n <libs_ui-components-table-templates [item]=\"itemFooter\"\n [templateCssWrapper]=\"footer.templateCssWrapper\"\n [configs]=\"footer.colTemplateConfig\" />\n }\n </div>\n }\n </div>\n }\n @if (footerRight()) {\n @for (footer of footerRight();track footer) {\n <div class=\"flex items-center px-[12px] py-[8px]\"\n [ngStyle]=\"footer.ngStyle || {}\"\n [ngClass]=\"footer.ngClass || {}\">\n @if (footer.colTemplateConfig) {\n <libs_ui-components-table-templates [item]=\"itemFooter\"\n [templateCssWrapper]=\"footer.templateCssWrapper\"\n [configs]=\"footer.colTemplateConfig\" />\n }\n </div>\n }\n }\n\n </div>\n }\n</ng-template>\n\n<ng-template #templateNodataRef>\n @if (noDataConfig(); as config) {\n <div class=\"flex items-center justify-center w-full h-full absolute left-0 top-0 z-[1]\">\n <div class=\"flex flex-col items-center justify-center w-full h-full shrink-0\"\n LibsUiComponentsScrollOverlayDirective>\n @if (!keySearch() && !onlyShowNoResult()) {\n <ng-container *ngComponentOutlet=\" ('no-data' | LibsUiIconsGetIconComponentPipe | async);inputs:{size:64}\" />\n <div class=\"libs-ui-table-no-data-config-text\"\n [ngStyle]=\"config.ngStyle || {}\"\n [ngClass]=\"config.ngClass || {}\"\n [innerHtml]=\"config.textNoData | translate\">\n </div>\n }\n @if (keySearch() || onlyShowNoResult()) {\n <ng-container *ngComponentOutlet=\"('no-result' | LibsUiIconsGetIconComponentPipe | async);inputs:{size:64}\" />\n <div class=\"libs-ui-table-no-data-config-text\"\n [ngStyle]=\"config.ngStyle || {}\"\n [ngClass]=\"config.ngClass || {}\"\n [innerHtml]=\"config.textSearchNoData | translate\">\n </div>\n }\n </div>\n </div>\n }\n</ng-template>\n", styles: [".libs-ui-table-header-container{height:33px;flex-shrink:0}.libs-ui-table-header-col{height:100%;width:100%;align-items:center}.libs-ui-table-no-data-config-text{margin-top:16px;font-size:12px;color:#9ca2ad;font-family:var(--libs-ui-font-family-name, \"Arial\");font-weight:400}.libs-ui-table-no-data-config-icon{margin-bottom:12px}.libs-ui-table-no-data-config-icon:before{font-size:84px;color:#c1c1c1}.libs-ui-table-shadow-bottom{box-shadow:0 1px 1px #00143305,0 4px 8px #0014330a}@media only screen and (min-width: 1921px){.libs-ui-border-bottom-general{border-bottom:solid 2px #e6e8ed!important}}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"] }, { kind: "component", type: LibsUiComponentsTableTemplatesComponent, selector: "libs_ui-components-table-templates", inputs: ["isHover", "configs", "templateCssWrapper", "item"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i1.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: VirtualScrollerModule }, { kind: "component", type: i2.VirtualScrollerComponent, selector: "virtual-scroller,[virtualScroller]", inputs: ["executeRefreshOutsideAngularZone", "enableUnequalChildrenSizes", "RTL", "useMarginInsteadOfTranslate", "modifyOverflowStyleOfParentScroll", "stripedTable", "scrollbarWidth", "scrollbarHeight", "childWidth", "childHeight", "ssrChildWidth", "ssrChildHeight", "ssrViewportWidth", "ssrViewportHeight", "bufferAmount", "scrollAnimationTime", "resizeBypassRefreshThreshold", "scrollThrottlingTime", "scrollDebounceTime", "checkResizeInterval", "items", "compareItems", "horizontal", "parentScroll"], outputs: ["vsUpdate", "vsChange", "vsStart", "vsEnd"], exportAs: ["virtualScroller"] }, { kind: "component", type: LibsUiComponentsButtonsButtonComponent, selector: "libs_ui-components-buttons-button", inputs: ["flagMouse", "type", "buttonCustom", "sizeButton", "label", "disable", "isPending", "imageLeft", "classInclude", "classIconLeft", "classIconRight", "classLabel", "iconOnlyType", "popover", "ignoreStopPropagationEvent", "zIndex", "widthLabelPopover", "styleIconLeft", "styleButton", "ignoreFocusWhenInputTab", "ignoreSetClickWhenShowPopover", "ignorePointerEvent", "isActive"], outputs: ["outClick", "outPopoverEvent", "outFunctionsControl"] }, { kind: "component", type: LibsUiComponentsDropdownComponent, selector: "libs_ui-components-dropdown", inputs: ["useXssFilter", "popoverElementRefCustom", "classInclude", "ignoreStopPropagationEvent", "flagMouse", "flagMouseContent", "popoverCustomConfig", "isNgContent", "zIndex", "convertItemSelected", "getPopoverItemSelected", "httpRequestDetailItemById", "lengthKeys", "textDisplayWhenNoSelect", "textDisplayWhenMultiSelect", "classIncludeTextDisplayWhenNoSelect", "fieldGetLabel", "labelPopoverConfig", "labelPopoverFullWidth", "hasContentUnitRight", "listSearchNoDataTemplateRef", "fieldGetImage", "imageSize", "typeShape", "fieldGetIcon", "fieldGetTextAvatar", "fieldGetColorAvatar", "classAvatarInclude", "getLastTextAfterSpace", "linkImageError", "showError", "showBorderError", "disable", "readonly", "labelConfig", "listSearchConfig", "isSearchOnline", "listHiddenInputSearch", "listSearchPadding", "listKeySearch", "listDividerClassInclude", "listConfig", "listButtonsOther", "listHasButtonUnSelectOption", "listClickExactly", "listBackgroundCustom", "listMaxItemShow", "listKeySelected", "listMultiKeySelected", "listKeysDisable", "listKeysHidden", "validRequired", "validMaxItemSelected", "changeValidUndefinedResetError", "allowSelectItemMultiple", "focusInputSearch", "onlyEmitDataWhenReset", "resetKeyWhenSelectAllKey", "listConfigHasDivider", "classIncludeIcon", "classIncludeContent", "listIgnoreClassDisableDefaultWhenUseKeysDisableItem", "tabKeyActive", "tabsConfig", "ignoreBorderBottom"], outputs: ["flagMouseChange", "flagMouseContentChange", "lengthKeysChange", "showBorderErrorChange", "listKeySelectedChange", "listMultiKeySelectedChange", "tabKeyActiveChange", "outSelectKey", "outSelectMultiKey", "outFunctionsControl", "outValidEvent", "outChangStageFlagMouse", "outDataChange", "outClickButtonOther", "outShowList", "outChangeTabKeyActive"] }, { kind: "component", type: LibsUiComponentsButtonsSortArrowComponent, selector: "libs_ui-components-buttons-sort-arrow", inputs: ["size", "mode", "fieldSort", "disable", "ignorePopoverContent", "popoverContentAsc", "popoverContentDesc", "defaultMode", "zIndex"], outputs: ["modeChange", "outChange"] }, { kind: "component", type: LibsUiComponentsCheckboxSingleComponent, selector: "libs_ui-components-checkbox-single", inputs: ["key", "checked", "label", "classLabelInclude", "ignoreShowPopoverLabel", "typeLabelPopover", "popover", "linkImage", "linkImageError", "avatarConfig", "classImageInclude", "imgTypeIcon", "bullet", "classInclude", "clickExactly", "disable", "disableLabel", "ignoreCheckbox", "zIndexLabel", "stillOtherOptions", "error", "showBorderError", "description", "iconImageClass", "classIconInclude", "modeBorder"], outputs: ["checkedChange", "linkImageChange", "outChange", "outEventPopover", "outClickLabel", "outChangStageFlagMousePopover"] }, { kind: "pipe", type: LibsUiPipesConvertObjectToSignalPipe, name: "LibsUiPipesConvertObjectToSignalPipe" }, { kind: "component", type: LibsUiComponentsSpinnerComponent, selector: "libs_ui-components-spinner", inputs: ["type", "size"] }, { kind: "component", type: LibsUiComponentsPopoverComponent, selector: "libs_ui-components-popover,[LibsUiComponentsPopoverDirective]", inputs: ["debugId", "flagMouse", "type", "mode", "config", "ignoreShowPopover", "elementRefCustom", "classInclude", "ignoreHiddenPopoverContentWhenMouseLeave", "ignoreStopPropagationEvent", "ignoreCursorPointerModeLikeClick", "isAddContentToParentDocument", "ignoreClickOutside"], outputs: ["outEvent", "outChangStageFlagMouse", "outEventPopoverContent", "outFunctionsControl"] }, { kind: "directive", type: LibsUiComponentsScrollOverlayDirective, selector: "[LibsUiComponentsScrollOverlayDirective]", inputs: ["debugMode", "classContainer", "options"], outputs: ["outScroll", "outScrollX", "outScrollY", "outScrollTop", "outScrollBottom"] }, { kind: "pipe", type: LibsUiIconsGetIconComponentPipe, name: "LibsUiIconsGetIconComponentPipe" }, { kind: "pipe", type: LibsUiPipesCallFunctionInTemplatePipe, name: "LibsUiPipesCallFunctionInTemplatePipe" }, { kind: "pipe", type: LibsUiPipesCheckSelectedByKeyPipe, name: "LibsUiPipesCheckSelectedByKeyPipe" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
595
+ }
596
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: LibsUiComponentsTableComponent, decorators: [{
597
+ type: Component,
598
+ args: [{ selector: 'libs_ui-components-table', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [
599
+ NgClass, NgStyle, AsyncPipe, NgTemplateOutlet, NgComponentOutlet, LibsUiComponentsTableTemplatesComponent,
600
+ TranslateModule, VirtualScrollerModule, LibsUiComponentsButtonsButtonComponent,
601
+ LibsUiComponentsDropdownComponent, LibsUiComponentsButtonsSortArrowComponent,
602
+ LibsUiComponentsCheckboxSingleComponent, LibsUiPipesConvertObjectToSignalPipe,
603
+ LibsUiComponentsSpinnerComponent, LibsUiComponentsPopoverComponent,
604
+ LibsUiComponentsScrollOverlayDirective, LibsUiIconsGetIconComponentPipe,
605
+ LibsUiPipesCallFunctionInTemplatePipe, LibsUiPipesCheckSelectedByKeyPipe
606
+ ], template: "<div class='flex flex-col w-full h-full'>\n @if (!ignoreBar()) {\n <div\n class=\"flex items-center justify-between relative z-[1] bottom-0 left-0 w-full bg-white mb-[16px] libs-ui-table-shadow-bottom\"\n [class.px-[16px]]=\"keysSelected().length || labelBarNoSelectItem()\"\n [class.py-[6px]]=\"keysSelected().length || labelBarNoSelectItem()\"\n (mouseenter)=\"resetIndexHover($event)\">\n @if (!keysSelected().length && labelBarNoSelectItem()) {\n <div class=\"{{ classLabelBarNoSelectItem() ?? 'px-[12px] py-[5px]' }}\"\n [innerHtml]='labelBarNoSelectItem() | translate:{value:totalItemDisplay()}'>\n </div>\n }\n @if (keysSelected().length) {\n <div class=\"flex items-center pl-[12px]\">\n <div class=\"flex items-center h-full mt-[-2px]\">\n <libs_ui-components-checkbox-single [checked]=\"true\"\n [disable]=\"loading() || disableCheckbox()\"\n (outChange)=\"handlerChangeAllChecked()\" />\n </div>\n <div class=\"libs-ui-font-h5m text-[#071631] mr-[8px] {{ classLabelBarButtons() }}\">\n {{ labelBarButtons() | translate:{ value:keysSelected().length } }}\n </div>\n @if (configSelectMoreItem()) {\n <libs_ui-components-dropdown [isNgContent]=\"true\"\n [popoverCustomConfig]=\"{\n widthByParent:false,\n ignoreArrow: true,\n maxHeight: 2048,\n classInclude:'w-[121px]',\n position: {\n mode:'start',\n distance:0\n }\n }\"\n [listConfig]=\"({\n type:'text',\n configTemplateText:{\n fieldKey:'key',\n ignoreIconSelected:true,\n getValue:configSelectMoreItem()?.getValue\n }\n } | LibsUiPipesConvertObjectToSignalPipe:true)()\"\n [listMaxItemShow]=\"5\"\n class=\"w-[16px] h-[16px] mr-[8px]\"\n (outSelectKey)=\"handlerSelectedMoreItem($event)\"\n (outFunctionsControl)=\"handlerFunctionControlMoreSelectItem($event)\">\n <libs_ui-components-buttons-button [type]=\"'button-link-primary'\"\n [classInclude]=\"'p-0 m-0'\"\n [classIconLeft]=\"'before:!text-[16px] libs-ui-con-dropdown mr-[6px]'\"\n [popover]=\"{config:{content:'i18n_more_select'}}\"\n [ignoreStopPropagationEvent]=\"true\" />\n </libs_ui-components-dropdown>\n }\n <div class=\"h-[16px] libs-ui-border-left-general ml-[16px]\"></div>\n @if (barButtons()?.length) {\n @for (button of barButtons();track button) {\n <libs_ui-components-buttons-button [type]=\"button.type || 'button-link-primary'\"\n [classIconLeft]=\"button.classIconLeft || ''\"\n [classInclude]=\"button.classInclude || ''\"\n [label]=\"(button.label || ' ') | translate\"\n (outClick)=\"handlerBarButtonClick(button)\" />\n }\n }\n </div>\n }\n <ng-content select='div.libs-ui-table-bar-right'></ng-content>\n </div>\n }\n\n <div #tableContainerElementRef\n class=\"libs-ui-table flex flex-col w-full h-full relative\"\n [class.px-[16px]]='!ignoreBar()'\n (mouseleave)=\"resetIndexHover($event)\">\n <div #headerElementRef\n [class.libs-ui-border-bottom-dashed-general]=\"!hasItemHightLight() && isDashBorder()\"\n [class.libs-ui-border-bottom-general]=\"!hasItemHightLight() && !isDashBorder()\"\n [class.!hidden]=\"!items().length && isHiddenHeaderWhenNodata()\"\n [class]=\"classHeaderContainer()\"\n (mouseenter)=\"resetIndexHover($event)\">\n @if (headerLeft().length) {\n <div class=\"h-full flex sticky top-0 left-0 bg-[#ffffff] z-[1]\">\n @for (header of headerLeft();track header) {\n <ng-container *ngTemplateOutlet=\"templateHeaderRef;context:{headerItem:header,isHederLeft:true}\" />\n }\n </div>\n }\n @if (headerRight().length) {\n @for (header of headerRight();track header) {\n <ng-container *ngTemplateOutlet=\"templateHeaderRef;context:{headerItem:header,isHederLeft:false}\" />\n }\n }\n </div>\n @if (showFooter() && itemFooter() && customPositionFooter() === 'top') {\n <ng-container *ngTemplateOutlet='templateFooterRef' />\n }\n <div class=\"relative flex flex-col w-full h-full overflow-x-hidden bg-white {{ classBodyInclude() || '' }}\">\n @if (items().length) {\n <div #bodyElementRef\n class=\"flex h-full w-full relative\"\n LibsUiComponentsScrollOverlayDirective\n [options]=\"{scrollX: (!headerLeft().length || !headerRight()) ? 'hidden':'scroll'}\"\n (outScroll)=\"handlerScroll($event)\"\n (outScrollBottom)=\"handlerScrollBottom($event)\">\n <virtual-scroller #bodyComponentRef\n [items]=\"items()\"\n [enableUnequalChildrenSizes]=\"enableUnequalChildrenSizes()\"\n class=\"h-full\"\n [style.width.px]=\"headerElementRef.scrollWidth > (bodyElementRef ? bodyElementRef.scrollWidth : 0) ? headerElementRef.scrollWidth: undefined\"\n [parentScroll]=\"bodyElementRef\"\n [bufferAmount]=\"bufferAmount()\">\n @for (data of bodyComponentRef.viewPortItems;track data()) {\n <div #elementHover\n class=\"flex\"\n [class.bg-[#f3fcfc]]=\"data().specificHightLight\"\n [class.libs-ui-border-top-1px-36d3d3]=\"data().specificHightLight && $first && !ignoreBorderItem()\"\n [class.libs-ui-border-bottom-1px-36d3d3]=\"data().specificHightLight && !ignoreBorderItem()\"\n [ngClass]=\"(data().specificHightLight || ($last && ignoreBorderItemLast())) ? 'libs-ui-border-radius-bottom-left-4px libs-ui-border-radius-bottom-right-4px' : ignoreBorderItem() ? '' : isDashBorder() ? 'libs-ui-border-bottom-dashed-general' : 'libs-ui-border-bottom-general'\"\n [style.width.px]=\"headerElementRef.scrollWidth\"\n [class.bg-[#f8f9fa]]=\"itemOfIndexHover === data && !data().specificHightLight\"\n (mouseenter)=\"setIndexHover($event,data)\"\n (mouseleave)=\"resetIndexHoverWhenMouseLeave($event)\">\n @if (headerLeft().length || headerRight().length) {\n <div class=\"flex flex-col w-full\">\n <div class=\"flex w-full\">\n @if (headerLeft().length) {\n <div class=\"flex sticky top-0 left-0 z-[1]\"\n [class.bg-white]=\"!data().specificHightLight\"\n [class.bg-[#f3fcfc]]=\"data().specificHightLight\">\n @for (header of headerLeft();track header) {\n <div\n class=\"relative flex px-[12px] py-[8px] {{ header.ignoreBorderRight ? '': 'libs-ui-border-right-general' }}\"\n [class.bg-[#f8f9fa]]=\"itemOfIndexHover === data && !data().specificHightLight\"\n [ngStyle]=\"header.ngStyle || {}\"\n [ngClass]=\"header.ngClass || {}\">\n <ng-container *ngTemplateOutlet=\"templateBodyRef;context:{header:header,data:data}\" />\n </div>\n }\n </div>\n }\n @if (headerRight().length) {\n @for (header of headerRight();track header) {\n <div class=\"relative flex px-[12px] py-[8px]\"\n [ngStyle]=\"header.ngStyle || {}\"\n [ngClass]=\"header.ngClass || {}\">\n <ng-container *ngTemplateOutlet=\"templateBodyRef;context:{header:header,data:data}\" />\n </div>\n }\n }\n </div>\n @if (configTemplateItemCollapseExpand() && data().specificExpand && data()[configTemplateItemCollapseExpand()?.fieldGetDataExpand || 'specificDataExpand']) {\n <div [class]=\"configTemplateItemCollapseExpand()?.cssWrapper || 'flex w-full'\">\n @for (dataExpand of data()[configTemplateItemCollapseExpand()?.fieldGetDataExpand || 'specificDataExpand']();track $index) {\n @if (configTemplateItemCollapseExpand()?.colTemplateConfig) {\n <libs_ui-components-table-templates [item]=\"dataExpand\"\n [templateCssWrapper]=\"configTemplateItemCollapseExpand()?.templateCssWrapper\"\n [configs]=\"configTemplateItemCollapseExpand()?.colTemplateConfig\" />\n }\n } @empty {\n <div class=\"relative h-[100px]\">\n <ng-container *ngTemplateOutlet=\"templateNodataRef\" />\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </virtual-scroller>\n\n @if ((!items().length) && !loading() && noDataConfig()) {\n <div class=\"h-full\"\n [style.flex]=\"'0 0 '+headerElementRef.scrollWidth+'px'\">\n </div>\n }\n </div>\n }\n @if ((!items().length) && !loading()) {\n <div class=\"relative h-full w-full\">\n <ng-container *ngTemplateOutlet=\"templateNodataRef\" />\n </div>\n }\n\n @if (showFooter() && itemFooter() && customPositionFooter() === 'bottom') {\n <ng-container *ngTemplateOutlet='templateFooterRef' />\n }\n\n @if (loading()) {\n <div class=\"absolute w-full h-full z-[2] flex items-center content-center\">\n <libs_ui-components-spinner />\n </div>\n }\n </div>\n </div>\n</div>\n\n<ng-template #templateHeaderRef\n let-header='headerItem'\n let-isHederLeft='isHederLeft'>\n <div\n [class]=\"'relative flex '+ (header.paddingLeftRightHeaderContainer ?? ' px-[12px] ') + (isHederLeft && !header.ignoreBorderRight ? ' libs-ui-border-right-general ' : ' ')+ ' libs-ui-table-header-col '\"\n [class.flex-col]=\"header.rowsConfig\"\n [class.py-[8px]]='!header.ignorePyDefault'\n [ngStyle]=\"header.ngStyle || {}\"\n [ngClass]=\"header.ngClass || {}\">\n @if (!header.rowsConfig) {\n <ng-container *ngTemplateOutlet=\"templateHeaderContentRef;context:{headerItem:header,isColRender:false}\" />\n }\n @if (header.rowsConfig;as rowsConfig) {\n @for (row of rowsConfig.rows;track row) {\n <div [class]=\"row.classRow\">\n @for (col of row.cols ; track col) {\n <ng-container *ngTemplateOutlet=\"templateHeaderContentRef;context:{headerItem:col,isColRender:true}\" />\n }\n </div>\n }\n }\n </div>\n</ng-template>\n\n<ng-template #templateHeaderContentRef\n let-header='headerItem'\n let-isColRender='isColRender'>\n <div class=\"flex libs-ui-font-h6m min-h-[18px] text-[#6a7383] max-w-full\"\n [class.items-center]='header.contentHeaderAlignCenter ?? true'\n [class.justify-end]='header.contentHeaderJustifyContentEnd'\n [ngStyle]=\"isColRender ? (header.ngStyle || {}) : {}\"\n [ngClass]=\"isColRender ? (header.ngClass || {}) : {}\">\n @if (header.hasCheckbox && !header.hasCheckboxAll) {\n <div class=\"flex h-full ml-[24px] {{ header.checkboxClassInclude }}\">\n </div>\n }\n @if (header.hasCheckboxAll) {\n <div class=\"flex h-full {{ header.checkboxAllClassInclude || 'mr-[16px]' }}\"\n [class.items-center]=\"header.checkboxAlignCenter\">\n <libs_ui-components-checkbox-single [key]=\"'all'\"\n [stillOtherOptions]=\"!!keysSelected().length && keysSelected().length !== items().length\"\n [checked]=\"!!keysSelected().length && keysSelected().length === items().length\"\n [disable]=\"loading()\"\n [classInclude]=\"header.checkboxClassInclude\"\n (outChange)=\"handlerChangeCheckedAllItems($event)\" />\n </div>\n }\n @if ((header.label | LibsUiPipesCallFunctionInTemplatePipe:header.parseValue:header)| async | translate; as labelHeaderColumn) {\n <libs_ui-components-popover [type]=\"header?.labelConfig?.type || 'text'\"\n [mode]=\"header?.labelConfig?.mode || 'hover'\"\n [classInclude]=\"(header?.labelConfig?.classInclude || '')\"\n [ignoreShowPopover]=\"header?.labelConfig?.ignoreShowTooltip || false\"\n [config]=\"header.labelConfig?.config || {content:labelHeaderColumn}\"\n [innerHTML]=\"labelHeaderColumn\" />\n }\n\n @if (header.tooltipOther; as tooltip) {\n <div class=\"ml-[4px]\">\n <libs_ui-components-popover [type]=\"tooltip?.type || 'other'\"\n [mode]=\"tooltip?.mode || 'hover'\"\n [classInclude]=\"tooltip.classInclude || 'text-[#6a7383]'\"\n [ignoreShowPopover]=\"tooltip.ignoreShowTooltip || false\"\n [config]=\"tooltip.config || {content:(tooltip.dataView || ' ') | translate, position: {\n mode: 'center',\n distance: 0,\n autoUpdatePosition: {\n endDistance: 12,\n startDistance: -12\n }\n }}\"\n [innerHTML]=\"tooltip.dataView\" />\n </div>\n }\n\n @if (header.hasSort && header.orderby) {\n <div class=\"ml-[4px]\">\n <libs_ui-components-buttons-sort-arrow [disable]=\"loading() || !items().length\"\n [fieldSort]=\"header.orderby\"\n [ignorePopoverContent]=\"header.sortIgnoreTooltipContent ?? true\"\n [popoverContentAsc]=\"header.sortTooltipContentAsc\"\n [popoverContentDesc]=\"header.sortTooltipContentDesc\"\n [defaultMode]=\"header.defaultMode\"\n [zIndex]=\"header.zIndexTooltipSort\"\n (outChange)=\"handlerChangeSort($event)\" />\n </div>\n }\n </div>\n @if (header.labelDescription) {\n <div class=\"flex\">\n <libs_ui-components-popover [type]=\"'text'\"\n [classInclude]=\"header.labelDescription.classInclude || ''\"\n [config]=\"{content: header.labelDescription.content | translate}\"\n [innerHTML]=\"header.labelDescription.content | translate\" />\n </div>\n }\n</ng-template>\n\n<ng-template #templateBodyRef\n let-header='header'\n let-data='data'>\n <div class=\"flex w-full h-full\">\n @if (header.hasCheckbox) {\n <div class=\"flex h-full\"\n [class.invisible]=\"header.checkConditionCheckBoxHidden &&( data() | LibsUiPipesCallFunctionInTemplatePipe:header.checkConditionCheckBoxHidden:data() | async)\"\n [class.items-center]=\"header.checkboxAlignCenter\">\n <libs_ui-components-checkbox-single [key]=\"data()[fieldKey()]\"\n [classInclude]=\"header.checkboxClassInclude\"\n [checked]=\"data()[fieldKey()] | LibsUiPipesCheckSelectedByKeyPipe:keysSelected():keysSelected().length\"\n [disable]=\"loading() || disableCheckbox() || !!(maxItemSelected() && !(data()[fieldKey()] | LibsUiPipesCheckSelectedByKeyPipe:keysSelected():keysSelected().length) && keysSelected().length >= maxItemSelected())\"\n (outChange)=\"handlerChangeItemChecked($event,data())\" />\n </div>\n }\n\n @if (header.colTemplateConfig) {\n <libs_ui-components-table-templates [isHover]=\"itemOfIndexHover === data && !data.specificHightLight\"\n [class]=\"header.templateCssWrapperHost || ''\"\n [item]=\"data\"\n [templateCssWrapper]=\"header.templateCssWrapper\"\n [configs]=\"header.colTemplateConfig\" />\n }\n </div>\n</ng-template>\n\n<ng-template #templateFooterRef>\n @if (!isHiddenHeaderWhenNodata() || (isHiddenHeaderWhenNodata() && items().length)) {\n <div #footerElementRef\n class=\"flex w-full bg-[#f8f9fa] overflow-x-hidden z-[1] {{ ignoreBorderFooter() ? '': (customPositionFooter() === 'top' ? 'libs-ui-border-bottom-general':'libs-ui-table-shadow-top libs-ui-border-top-general') }} min-h-[35px]\"\n (mouseenter)=\"handlerMouseEnter($event)\"\n (mouseleave)=\"handlerMouseLeave($event)\">\n @if (footerLeft()) {\n <div #footerLeftElementRef\n class=\"flex sticky top-0 left-0 z-[1] bg-[#f8f9fa]\">\n @for (footer of footerLeft();track footer) {\n <div\n class=\"flex items-center px-[12px] py-[8px] {{ footer.ignoreBorderRight ? '': 'libs-ui-border-right-general' }}\"\n [ngStyle]=\"footer.ngStyle || {}\"\n [ngClass]=\"footer.ngClass || {}\">\n @if (footer.colTemplateConfig) {\n <libs_ui-components-table-templates [item]=\"itemFooter\"\n [templateCssWrapper]=\"footer.templateCssWrapper\"\n [configs]=\"footer.colTemplateConfig\" />\n }\n </div>\n }\n </div>\n }\n @if (footerRight()) {\n @for (footer of footerRight();track footer) {\n <div class=\"flex items-center px-[12px] py-[8px]\"\n [ngStyle]=\"footer.ngStyle || {}\"\n [ngClass]=\"footer.ngClass || {}\">\n @if (footer.colTemplateConfig) {\n <libs_ui-components-table-templates [item]=\"itemFooter\"\n [templateCssWrapper]=\"footer.templateCssWrapper\"\n [configs]=\"footer.colTemplateConfig\" />\n }\n </div>\n }\n }\n\n </div>\n }\n</ng-template>\n\n<ng-template #templateNodataRef>\n @if (noDataConfig(); as config) {\n <div class=\"flex items-center justify-center w-full h-full absolute left-0 top-0 z-[1]\">\n <div class=\"flex flex-col items-center justify-center w-full h-full shrink-0\"\n LibsUiComponentsScrollOverlayDirective>\n @if (!keySearch() && !onlyShowNoResult()) {\n <ng-container *ngComponentOutlet=\" ('no-data' | LibsUiIconsGetIconComponentPipe | async);inputs:{size:64}\" />\n <div class=\"libs-ui-table-no-data-config-text\"\n [ngStyle]=\"config.ngStyle || {}\"\n [ngClass]=\"config.ngClass || {}\"\n [innerHtml]=\"config.textNoData | translate\">\n </div>\n }\n @if (keySearch() || onlyShowNoResult()) {\n <ng-container *ngComponentOutlet=\"('no-result' | LibsUiIconsGetIconComponentPipe | async);inputs:{size:64}\" />\n <div class=\"libs-ui-table-no-data-config-text\"\n [ngStyle]=\"config.ngStyle || {}\"\n [ngClass]=\"config.ngClass || {}\"\n [innerHtml]=\"config.textSearchNoData | translate\">\n </div>\n }\n </div>\n </div>\n }\n</ng-template>\n", styles: [".libs-ui-table-header-container{height:33px;flex-shrink:0}.libs-ui-table-header-col{height:100%;width:100%;align-items:center}.libs-ui-table-no-data-config-text{margin-top:16px;font-size:12px;color:#9ca2ad;font-family:var(--libs-ui-font-family-name, \"Arial\");font-weight:400}.libs-ui-table-no-data-config-icon{margin-bottom:12px}.libs-ui-table-no-data-config-icon:before{font-size:84px;color:#c1c1c1}.libs-ui-table-shadow-bottom{box-shadow:0 1px 1px #00143305,0 4px 8px #0014330a}@media only screen and (min-width: 1921px){.libs-ui-border-bottom-general{border-bottom:solid 2px #e6e8ed!important}}\n"] }]
607
+ }], ctorParameters: () => [] });
608
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy11aS9jb21wb25lbnRzL3RhYmxlL3NyYy90YWJsZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9saWJzLXVpL2NvbXBvbmVudHMvdGFibGUvc3JjL3RhYmxlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHVEQUF1RDtBQUN2RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFjLE1BQU0sRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBa0IsTUFBTSxlQUFlLENBQUM7QUFDekwsT0FBTyxFQUE0QixxQkFBcUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2pHLE9BQU8sRUFBVyxzQ0FBc0MsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQ3JHLE9BQU8sRUFBUyx5Q0FBeUMsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBRXBHLE9BQU8sRUFBa0IsdUNBQXVDLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUM5RyxPQUFPLEVBQWlELGlDQUFpQyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDaEksT0FBTyxFQUFFLGdDQUFnQyxFQUFzQixNQUFNLDZCQUE2QixDQUFDO0FBQ25HLE9BQU8sRUFBRSxzQ0FBc0MsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQzVGLE9BQU8sRUFBRSxnQ0FBZ0MsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQy9FLE9BQU8sRUFBRSwrQkFBK0IsRUFBRSxNQUFNLGdC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bUJBQ0MsdUJBQXVCLENBQUMsTUFBTSxXQUN0Qzt3QkFDUCxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBRSx1Q0FBdUM7d0JBQ3pHLGVBQWUsRUFBRSxxQkFBcUIsRUFBRSxzQ0FBc0M7d0JBQzlFLGlDQUFpQyxFQUFFLHlDQUF5Qzt3QkFDNUUsdUNBQXVDLEVBQUUsb0NBQW9DO3dCQUM3RSxnQ0FBZ0MsRUFBRSxnQ0FBZ0M7d0JBQ2xFLHNDQUFzQyxFQUFFLCtCQUErQjt3QkFDdkUscUNBQXFDLEVBQUUsaUNBQWlDO3FCQUN6RSIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi9cbmltcG9ydCB7IEFzeW5jUGlwZSwgTmdDbGFzcywgTmdDb21wb25lbnRPdXRsZXQsIE5nU3R5bGUsIE5nVGVtcGxhdGVPdXRsZXQgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uXCI7XG5pbXBvcnQgeyBIdHRwUGFyYW1zIH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vbi9odHRwXCI7XG5pbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBjb21wdXRlZCwgZWZmZWN0LCBFbGVtZW50UmVmLCBpbmplY3QsIGlucHV0LCBPbkRlc3Ryb3ksIE9uSW5pdCwgb3V0cHV0LCBzaWduYWwsIHVudHJhY2tlZCwgdmlld0NoaWxkLCBXcml0YWJsZVNpZ25hbCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBWaXJ0dWFsU2Nyb2xsZXJDb21wb25lbnQsIFZpcnR1YWxTY3JvbGxlck1vZHVsZSB9IGZyb20gJ0BpaGFyYmVjay9uZ3gtdmlydHVhbC1zY3JvbGxlcic7XG5pbXBvcnQgeyBJQnV0dG9uLCBMaWJzVWlDb21wb25lbnRzQnV0dG9uc0J1dHRvbkNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtYnV0dG9ucy1idXR0b24nO1xuaW1wb3J0IHsgSVNvcnQsIExpYnNVaUNvbXBvbmVudHNCdXR0b25zU29ydEFycm93Q29tcG9uZW50IH0gZnJvbSAnQGxpYnMtdWkvY29tcG9uZW50cy1idXR0b25zLXNvcnQnO1xuaW1wb3J0IHsgSUNoZWNrYm94SXRlbSB9IGZyb20gXCJAbGlicy11aS9jb21wb25lbnRzLWNoZWNrYm94LWdyb3VwXCI7XG5pbXBvcnQgeyBJQ2hlY2tib3hFdmVudCwgTGlic1VpQ29tcG9uZW50c0NoZWNrYm94U2luZ2xlQ29tcG9uZW50IH0gZnJvbSBcIkBsaWJzLXVpL2NvbXBvbmVudHMtY2hlY2tib3gtc2luZ2xlXCI7XG5pbXBvcnQgeyBJRHJvcGRvd25GdW5jdGlvbkNvbnRyb2xFdmVudCwgSUVtaXRTZWxlY3RLZXksIExpYnNVaUNvbXBvbmVudHNEcm9wZG93bkNvbXBvbmVudCB9IGZyb20gJ0BsaWJzLXVpL2NvbXBvbmVudHMtZHJvcGRvd24nO1xuaW1wb3J0IHsgTGlic1VpQ29tcG9uZW50c1BvcG92ZXJDb21wb25lbnQsIFRZUEVfUE9QT1ZFUl9FVkVOVCB9IGZyb20gXCJAbGlicy11aS9jb21wb25lbnRzLXBvcG92ZXJcIjtcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNTY3JvbGxPdmVybGF5RGlyZWN0aXZlIH0gZnJvbSBcIkBsaWJzLXVpL2NvbXBvbmVudHMtc2Nyb2xsLW92ZXJsYXlcIjtcbmltcG9ydCB7IExpYnNVaUNvbXBvbmVudHNTcGlubmVyQ29tcG9uZW50IH0gZnJvbSBcIkBsaWJzLXVpL2NvbXBvbmVudHMtc3Bpbm5lclwiO1xuaW1wb3J0IHsgTGlic1VpSWNvbnNHZXRJY29uQ29tcG9uZW50UGlwZSB9IGZyb20gXCJAbGlicy11aS9pY29uc1wiO1xuaW1wb3J0IHsgSUh0dHBSZXNwb25zZUVycm9yLCBJUGFnaW5nIH0gZnJvbSBcIkBsaWJzLXVpL2ludGVyZmFjZXMtdHlwZXNcIjtcbmltcG9ydCB7IExpYnNVaVBpcGVzQ2FsbEZ1bmN0aW9uSW5UZW1wbGF0ZVBpcGUgfSBmcm9tIFwiQGxpYnMtdWkvcGlwZXMtY2FsbC1mdW5jdGlvbi1pbi10ZW1wbGF0ZVwiO1xuaW1wb3J0IHsgTGlic1VpUGlwZXNDaGVja1NlbGVjdGVkQnlLZXlQaXBlIH0gZnJvbSAnQGxpYnMtdWkvcGlwZXMtY2hlY2stc2VsZWN0ZWQtYnkta2V5JztcbmltcG9ydCB7IExpYnNVaVBpcGVzQ29udmVydE9iamVjdFRvU2lnbmFsUGlwZSB9IGZyb20gJ0BsaWJzLXVpL3BpcGVzLWNvbnZlcnQtb2JqZWN0LXRvLXNpZ25hbCc7XG5pbXBvcnQgeyBJSHR0cFJlcXVlc3RDb25maWcsIExpYnNVaUh0dHBSZXF1ZXN0U2VydmljZSB9IGZyb20gXCJAbGlicy11aS9zZXJ2aWNlcy1odHRwLXJlcXVlc3RcIjtcbmltcG9ydCB7IGNvbnZlcnRPYmplY3RUb1NpZ25hbCwgZGVsZXRlVW5pY29kZSwgZ2V0LCBzZXQsIHZpZXdEYXRhTnVtYmVyQnlMYW5ndWFnZSB9IGZyb20gXCJAbGlicy11aS91dGlsc1wiO1xuaW1wb3J0IHsgVHJhbnNsYXRlTW9kdWxlIH0gZnJvbSBcIkBuZ3gtdHJhbnNsYXRlL2NvcmVcIjtcbmltcG9ydCB7IGxhc3RWYWx1ZUZyb20sIFN1YmplY3QsIHRha2VVbnRpbCwgdGltZXIgfSBmcm9tIFwicnhqc1wiO1xuaW1wb3J0IHsgSUJ1dHRvbkJhckV2ZW50LCBJQ29uZmlnU2VsZWN0TW9yZUl0ZW0sIElDb25maWdUZW1wbGF0ZUl0ZW1Db2xsYXBzZUV4cGFuZCwgSUhvdmVyQnV0dG9uQWN0aW9uRXZlbnQsIElMb2FkTW9yZUV2ZW50LCBJU29ydEV2ZW50LCBJVGFiZWxCdXR0b25BY3Rpb25FdmVudCwgSVRhYmxlRm9vdGVyQ29uZmlnLCBJVGFibGVIZWFkZXJDb25maWcsIFRZUEVfREFUQV9GSUxURVJfVEFCTEUsIFRZUEVfREFUQV9UQUJMRSwgVFlQRV9ORVdfREFUQV9UQUJMRSwgVFlQRV9UQUJMRV9GSUxURVIgfSBmcm9tIFwiLi9pbnRlcmZhY2VzXCI7XG5pbXBvcnQgeyBJVGFibGVGdW5jdGlvbkNvbnRyb2xFdmVudCB9IGZyb20gXCIuL2ludGVyZmFjZXMvZnVuY3Rpb24tY29udHJvbC1ldmVudC5pbnRlcmZhY2VcIjtcbmltcG9ydCB7IElUYWJsZU5vRGF0YUNvbmZpZyB9IGZyb20gXCIuL2ludGVyZmFjZXMvbm8tZGF0YS1jb25maWcuaW50ZXJmYWNlXCI7XG5pbXBvcnQgeyBMaWJzVWlDb21wb25lbnRzVGFibGVUZW1wbGF0ZXNDb21wb25lbnQgfSBmcm9tIFwiLi90ZW1wbGF0ZXMvdGVtcGxhdGVzLmNvbXBvbmVudFwiO1xuXG5AQ29tcG9uZW50KHtcbiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEBhbmd1bGFyLWVzbGludC9jb21wb25lbnQtc2VsZWN0b3JcbiAgc2VsZWN0b3I6ICdsaWJzX3VpLWNvbXBvbmVudHMtdGFibGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vdGFibGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90YWJsZS5jb21wb25lbnQuc2NzcyddLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgaW1wb3J0czogW1xuICAgIE5nQ2xhc3MsIE5nU3R5bGUsIEFzeW5jUGlwZSwgTmdUZW1wbGF0ZU91dGxldCwgTmdDb21wb25lbnRPdXRsZXQsIExpYnNVaUNvbXBvbmVudHNUYWJsZVRlbXBsYXRlc0NvbXBvbmVudCxcbiAgICBUcmFuc2xhdGVNb2R1bGUsIFZpcnR1YWxTY3JvbGxlck1vZHVsZSwgTGlic1VpQ29tcG9uZW50c0J1dHRvbnNCdXR0b25Db21wb25lbnQsXG4gICAgTGlic1VpQ29tcG9uZW50c0Ryb3Bkb3duQ29tcG9uZW50LCBMaWJzVWlDb21wb25lbnRzQnV0dG9uc1NvcnRBcnJvd0NvbXBvbmVudCxcbiAgICBMaWJzVWlDb21wb25lbnRzQ2hlY2tib3hTaW5nbGVDb21wb25lbnQsIExpYnNVaVBpcGVzQ29udmVydE9iamVjdFRvU2lnbmFsUGlwZSxcbiAgICBMaWJzVWlDb21wb25lbnRzU3Bpbm5lckNvbXBvbmVudCwgTGlic1VpQ29tcG9uZW50c1BvcG92ZXJDb21wb25lbnQsXG4gICAgTGlic1VpQ29tcG9uZW50c1Njcm9sbE92ZXJsYXlEaXJlY3RpdmUsIExpYnNVaUljb25zR2V0SWNvbkNvbXBvbmVudFBpcGUsXG4gICAgTGlic1VpUGlwZXNDYWxsRnVuY3Rpb25JblRlbXBsYXRlUGlwZSwgTGlic1VpUGlwZXNDaGVja1NlbGVjdGVkQnlLZXlQaXBlXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgTGlic1VpQ29tcG9uZW50c1RhYmxlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICAvKiogUFJPUEVSVFkgKi9cbiAgcHJvdGVjdGVkIGNsYXNzSGVhZGVyQ29udGFpbmVyID0gY29tcHV0ZWQoKCkgPT4gYGxpYnMtdWktdGFibGUtaGVhZGVyLWNvbnRhaW5lciB3LWZ1bGwgZmxleCAke3RoaXMuaWdub3JlQ2xhc3NCZ0hlYWRlcigpID8gJycgOiAnYmctd2hpdGUnfSBvdmVyZmxvdy14LWhpZGRlbiB6LVsxXSBpdGVtcy1jZW50ZXIgJHt0aGlzLmNsYXNzSGVhZGVySW5jbHVkZSgpIHx8ICcnfWApXG4gIHByb3RlY3RlZCBrZXlzU2VsZWN0ZWQgPSBzaWduYWw8QXJyYXk8YW55Pj4oW10pO1xuICBwcm90ZWN0ZWQgbG9hZGluZyA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHByb3RlY3RlZCBzdG9yZXMgPSBzaWduYWw8QXJyYXk8V3JpdGFibGVTaWduYWw8UmVjb3JkPGFueSwgYW55Pj4+PihbXSk7XG4gIHByb3RlY3RlZCBpdGVtcyA9IHNpZ25hbDxBcnJheTxXcml0YWJsZVNpZ25hbDxSZWNvcmQ8YW55LCBhbnk+Pj4+KFtdKTtcbiAgcHJvdGVjdGVkIGl0ZW1Gb290ZXIgPSBzaWduYWw8UmVjb3JkPGFueSwgYW55Pj4oe30pO1xuICBwcm90ZWN0ZWQgaXRlbU9mSW5kZXhIb3Zlcj86IFdyaXRhYmxlU2lnbmFsPGFueT47XG4gIHByb3RlY3RlZCBrZXlTZWFyY2ggPSBzaWduYWw8c3RyaW5nPignJyk7XG4gIHByb3RlY3RlZCB0b3RhbEl0ZW1JbkJhY2tlbmQgPSBzaWduYWw8bnVtYmVyPigwKTtcbiAgcHJvdGVjdGVkIGhhc0l0ZW1IaWdodExpZ2h0ID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgcHJvdGVjdGVkIHRvdGFsSXRlbURpc3BsYXkgPSBjb21wdXRlZCgoKSA9PiB2aWV3RGF0YU51bWJlckJ5TGFuZ3VhZ2UoKHRoaXMudG90YWxJdGVtKCkgPz8gdGhpcy50b3RhbEl0ZW1JbkJhY2tlbmQoKSksIGZhbHNlKSlcblxuICBwcml2YXRlIGhhc1Njcm9sbCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHByaXZhdGUgaW5zdGFuY2VTb3J0ID0gc2lnbmFsPElTb3J0IHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBwcml2YXRlIGhhc0FjdGlvbkJ1dHRvbkRyb3Bkb3duQ29udGVudCA9IHNpZ25hbDxib29sZWFuPihmYWxzZSk7XG4gIHByaXZhdGUgcGFnaW5nU3RvcmUgPSBzaWduYWw8SVBhZ2luZz4oe30pO1xuICBwcml2YXRlIGxvYWRlZExhc3RJdGVtID0gc2lnbmFsPGJvb2xlYW4+KGZhbHNlKTtcbiAgcHJpdmF0ZSBzdG9yZVBhcmFtc0NhbGxBcGkgPSBzaWduYWw8UmVjb3JkPGFueSwgYW55Pj4oe30pO1xuICBwcml2YXRlIHRpbWVvdXRMZWF2ZUl0ZW0gPSBzaWduYWw8bnVtYmVyIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBwcml2YXRlIGZ1bmN0aW9uQ29udHJvbFNlbGVjdE1vcmVJdGVtPzogSURyb3Bkb3duRnVuY3Rpb25Db250cm9sRXZlbnQ7XG4gIHByaXZhdGUgb25EZXN0cm95ID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcblxuICAvKiogSU5QVVQgKi9cbiAgcmVhZG9ubHkgdGltZUhpZ2hsaWdoTmV3SXRlbSA9IGlucHV0PG51bWJlciwgbnVtYmVyIHwgdW5kZWZpbmVkPigyMDAwLCB7IHRyYW5zZm9ybTogdmFsID0+IHZhbCA/PyAyMDAwIH0pO1xuICByZWFkb25seSBoZWFkZXJMZWZ0ID0gaW5wdXQ8QXJyYXk8SVRhYmxlSGVhZGVyQ29uZmlnPiwgQXJyYXk8SVRhYmxlSGVhZGVyQ29uZmlnPiB8IHVuZGVmaW5lZD4oW10sIHsgdHJhbnNmb3JtOiB2YWwgPT4gdmFsID8/IFtdIH0pO1xuICByZWFkb25seSBoZWFkZXJSaWdodCA9IGlucHV0PEFycmF5PElUYWJsZUhlYWRlckNvbmZpZz4sIEFycmF5PElUYWJsZUhlYWRlckNvbmZpZz4gfCB1bmRlZmluZWQ+KFtdLCB7IHRyYW5zZm9ybTogdmFsID0+IHZhbCA/PyBbXSB9KTtcbiAgcmVhZG9ubHkgY29uZmlnVGVtcGxhdGVJdGVtQ29sbGFwc2VFeHBhbmQgPSBpbnB1dDxJQ29uZmlnVGVtcGxhdGVJdGVtQ29sbGFwc2VFeHBhbmQ+KCk7XG4gIHJlYWRvbmx5IHNob3dGb290ZXIgPSBpbnB1dDxib29sZWFuPigpO1xuICByZWFkb25seSBpZ25vcmVCb3JkZXJGb290ZXIgPSBpbnB1dDxib29sZWFuPigpO1xuICByZWFkb25seSBjdXN0b21Qb3NpdGlvbkZvb3RlciA9IGlucHV0PCd0b3AnIHwgJ2JvdHRvbScsICd0b3AnIHwgJ2JvdHRvbScgfCB1bmRlZmluZWQ+KCdib3R0b20nLCB7IHRyYW5zZm9ybTogdmFsID0+IHZhbCA/PyAnYm90dG9tJyB9KTtcbiAgcmVhZG9ubHkgZm9vdGVyTGVmdCA9IGlucHV0PEFycmF5PElUYWJsZUZvb3RlckNvbmZpZz4gfCB1bmRlZmluZWQ+KCk7XG4gIHJlYWRvbmx5IGZvb3RlclJpZ2h0ID0gaW5wdXQ8QXJyYXk8SVRhYmxlRm9vdGVyQ29uZmlnPiB8IHVuZGVmaW5lZD4oKTtcbiAgcmVhZG9ubHkgZGlzYWJsZUNoZWNrYm94ID0gaW5wdXQ8Ym9vbGVhbiwgYm9vbGVhbiB8IHVuZGVmaW5lZD4oZmFsc2UsIHsgdHJhbnNmb3JtOiB2YWwgPT4gdmFsID8/IGZhbHNlIH0pO1xuICByZWFkb25seSBlbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcyA9IGlucHV0PGJvb2xlYW4sIGJvb2xlYW4gfCB1bmRlZmluZWQ+KGZhbHNlLCB7IHRyYW5zZm9ybTogdmFsID0+IHZhbCA/PyBmYWxzZSB9KTtcbiAgcmVhZG9ubHkgYnVmZmVyQW1vdW50ID0gaW5wdXQ8bnVtYmVyLCBudW1iZXIgfCB1bmRlZmluZWQ+KDUsIHsgdHJhbnNmb3JtOiB2YWwgPT4gdmFsID8gKHZhbCA+IDI1ID8gMjUgOiB2YWwpIDogNSB9KVxuICByZWFkb25seSB0b3RhbEl0ZW0gPSBpbnB1dDxudW1iZXI+KCk7XG4gIHJlYWRvbmx5IGlzRGFzaEJvcmRlciA9IGlucHV0PGJvb2xlYW4+KCk7XG4gIHJlYWRvbmx5IGNsYXNzSGVhZGVySW5jbHVkZSA9IGlucHV0PHN0cmluZz4oKTtcbiAgcmVhZG9ubHkgY2xhc3NCb2R5SW5jbHVkZSA9IGlucHV0PHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPignJywgeyB0cmFuc2Zvcm06IHZhbCA9PiB2YWwgPz8gJycgfSk7XG4gIHJlYWRvbmx5IGNsYXNzRm9vdGVySW5jbHVkZSA9IGlucHV0PHN0cmluZywgc3RyaW5nIHwgdW5kZWZpbmVkPignJywgeyB0cmFuc2Zvcm06IHZhbCA9PiB2YWwgPz8gJycgfSk7XG5cbiAgcmVhZG9ubHkgZmllbGRLZXkgPSBpbnB1dDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4oJ2lkJywgeyB0cmFuc2Zvcm06IHZhbCA9PiB2YWwgfHwgJ2lkJyB9KTsgLy8gdMOqbiBmaWVsZCDEkeG7i25oIGRhbmggaXRlbSBj4bunYSBsaXN0RGF0YXNcbiAgcmVhZG9ubHkgZGVmYXVsdEtleXNTZWxlY3RlZCA9IGlucHV0PEFycmF5PGFueT4+KCk7XG4gIHJlYWRvbmx5IGxhYmVsQmFyTm9TZWxlY3RJdGVtID0gaW5wdXQ8c3RyaW5nPihgaTE4bl90b3RhbF9xdWFudGl0eWApOyAvLyBz4butIGThu6VuZyDEkeG7gyBoacOqbiB0aOG7iyBraGkgdMOtY2ggY2jhu41uIGl0ZW1cbiAgcmVhZG9ubHkgbGFiZWxCYXJCdXR0b25zID0gaW5wdXQ8c3RyaW5nLCBzdHJpbmcgfCB1bmRlZmluZWQ+KCdpMThuX251bWJlcl9pdGVtX3NlbGVjdGVkJywgeyB0cmFuc2Zvcm06IHZhbCA9PiB2YWwgfHwgJ2kxOG5fbnVtYmVyX2l0ZW1fc2VsZWN0ZWQnIH0pOyAvLyBz4butIGThu6VuZyDEkeG7gyBoacOqbiB0aOG7iyBraGkgdMOtY2ggY2jhu41uIGl0ZW1cbiAgcmVhZG9ubHkgY2xhc3NMYWJlbEJhckJ1dHRvbnMgPSBpbnB1dDxzdHJpbmcsIHN0cmluZyB8IHVuZGVmaW5lZD4oJycsIHsgdHJhbnNmb3JtOiB2YWwgPT4gdmFsID8/ICcnIH0pOyAvLyBz4butIGThu6VuZyDEkeG7gyBoacOqbiB0aOG7iyBraGkgdMOtY2ggY2jhu41uIGl0ZW1cbiAgcmVhZG9ubHkgYmFyQnV0dG9ucyA9IGlucHV0PEFycmF5PElCdXR0b24+PigpO1xuICByZWFkb25seSBzb3J0TG9jYWwgPSBpbnB1dDxib29sZWFuPigpOyAvLyB0csaw4budbmcgaOG7o3AgbuG6v3Ugc29ydExvY2FsIG7DoHkga2jDtG5nIMSRw6FwIOG7qW5nIMSRxrDhu6NjIG5naGnhu4dwIHbhu6UgdGjDrCBt4bubaSBjw6JuIG5o4bqvYyBz4butIGThu6VuZyBmaWx0ZXJMb2NhbFxuICByZWFkb25seSBmaWx0ZXJPclNvcnRMb2NhbCA9IGlucHV0PFRZUEVfVEFCTEVfRklMVEVSPigpO1xuICByZWFkb25seSBodHRwUmVxdWVzdERhdGEgPSBpbnB1dDxJSHR0cFJlcXVlc3RDb25maWc+KCk7XG4gIHJlYWRvbmx5IGh0dHBSZXF1ZXN0RGF0YUZvb3RlciA9IGlucHV0PElIdHRwUmVxdWVzdENvbmZpZz4oKTtcbiAgcmVhZG9ubHkgbmV3RGF0YSA9IGlucHV0PFRZUEVfTkVXX0RBVEFfVEFCTEU+KCk7XG4gIHJlYWRvbmx5IGZpbHRlciA9IGlucHV0PFRZUEVfREFUQV9GSUxURVJfVEFCTEUsIFRZUEVfREFUQV9GSUxURVJfVEFCTEUgfCB1bmRlZmluZWQ+KHsgZmlsdGVyRGF0YToge30gfSwgeyB0cmFuc2Zvcm06IHZhbCA9PiB2YWwgPz8geyBmaWx0ZXJEYXRhOiB7fSB9IH0pO1xuICByZWFkb25seSBpZ25vcmVCYXIgPSBpbnB1dDxib29sZWFuPigpO1xuICByZWFkb25seSBjbGFzc0xhYmVsQmFyTm9TZWxlY3RJdGVtID0gaW5wdXQ8c3RyaW5nPigpO1xuICByZWFkb25seSBpZ25vcmVDbGFzc0JnSGVhZGVyID0gaW5wdXQ8Ym9vbGVhbj4oKTtcbiAgcmVhZG9ubHkgbm9EYXRhQ29uZmlnID0gaW5wdXQ8SVRhYmxlTm9EYXRhQ29uZmlnPih7IHRleHROb0RhdGE6ICdpMThuX25vX2RhdGFfeWV0JywgdGV4dFNlYXJjaE5vRGF0YTogJ2kxOG5fbm9fcmVzdWx0JyB9KTtcbiAgcmVhZG9ubHkgaWdub3JlQm9yZGVySXRlbUxhc3QgPSBpbnB1dDxib29sZWFuPigpO1xuICByZWFkb25seSBpc0hpZGRlbkhlYWRlcldoZW5Ob2RhdGEgPSBpbnB1dDxib29sZWFuPigpO1xuICByZWFkb25seSBtYXhJdGVtU2VsZWN0ZWQgPSBpbnB1dDxudW1iZXIsIG51bWJlciB8IHVuZGVmaW5lZD4oMTAwLCB7IHRyYW5zZm9ybTogdmFsID0+IHZhbCA/PyAxMDAgfSk7XG4gIHJlYWRvbmx5IGNvbmZpZ1NlbGVjdE1vcmVJdGVtID0gaW5wdXQ8SUNvbmZpZ1NlbGVjdE1vcmVJdGVtPigpO1xuICByZWFkb25seSBvbmx5U2hvd05vUmVzdWx0ID0gaW5wdXQ8Ym9vbGVhbj4oKTtcbiAgcmVhZG9ubHkgaWdub3JlQm9yZGVySXRlbSA9IGlucHV0PGJvb2xlYW4+KCk7XG5cbiAgLyoqIE9VVFBVVCAqL1xuXG4gIHJlYWRvbmx5IG91dExvYWRNb3JlID0gb3V0cHV0PElMb2FkTW9yZUV2ZW50PigpO1xuICByZWFkb25seSBvdXRTY3JvbGxJc0dvbmUgPSBvdXRwdXQ8SUxvYWRNb3JlRXZlbnQ+KCk7XG4gIHJlYWRvbmx5IG91dExvYWRpbmcgPSBvdXRwdXQ8Ym9vbGVhbj4oKTtcbiAgcmVhZG9ubHkgb3V0Q2xpY2tCdXR0b25BY3Rpb24gPSBvdXRwdXQ8SVRhYmVsQnV0dG9uQWN0aW9uRXZlbnQ+KCk7XG4gIHJlYWRvbmx5IG91dFNvcnQgPSBvdXRwdXQ8SVNvcnRFdmVudD4oKTtcbiAgcmVhZG9ubHkgb3V0Q2xpY2tCYXJCdXR0b24gPSBvdXRwdXQ8SUJ1dHRvbkJhckV2ZW50PigpO1xuICByZWFkb25seSBvdXRIb3ZlckJ1dHRvbkFjdGlvbiA9IG91dHB1dDxJSG92ZXJCdXR0b25BY3Rpb25FdmVudD4oKTtcbiAgcmVhZG9ubHkgb3V0S2V5c1NlbGVjdGVkID0gb3V0cHV0PHsga2V5czogQXJyYXk8YW55PiB9PigpO1xuICByZWFkb25seSBvdXRGdW5jdGlvbnNDb250cm9sID0gb3V0cHV0PElUYWJsZUZ1bmN0aW9uQ29udHJvbEV2ZW50PigpO1xuICByZWFkb25seSBvdXRMb2FkRGF0YUNvbXBsZXRlID0gb3V0cHV0PFdyaXRhYmxlU2lnbmFsPEFycmF5PFdyaXRhYmxlU2lnbmFsPGFueT4+Pj4oKTtcbiAgcmVhZG9ubHkgb3V0VG90YWxJdGVtID0gb3V0cHV0PG51bWJlcj4oKTtcbiAgcmVhZG9ubHkgb3V0TG9hZERhdGFFcnJvciA9IG91dHB1dDxJSHR0cFJlc3BvbnNlRXJyb3I+KCk7XG5cbiAgLyoqVklFVyBDSElMRCAqL1xuICBwcm90ZWN0ZWQgaGVhZGVyRWxlbWVudFJlZiA9IHZpZXdDaGlsZDxFbGVtZW50UmVmPignaGVhZGVyRWxlbWVudFJlZicpO1xuICBwcm90ZWN0ZWQgZm9vdGVyRWxlbWVudFJlZiA9IHZpZXdDaGlsZDxFbGVtZW50UmVmPignZm9vdGVyRWxlbWVudFJlZicpO1xuICBwcm90ZWN0ZWQgZm9vdGVyTGVmdEVsZW1lbnRSZWYgPSB2aWV3Q2hpbGQ8RWxlbWVudFJlZj4oJ2Zvb3RlckxlZnRFbGVtZW50UmVmJyk7XG5cbiAgcHJpdmF0ZSBib2R5RWxlbWVudFJlZiA9IHZpZXdDaGlsZDxFbGVtZW50UmVmPignYm9keUVsZW1lbnRSZWYnKTtcbiAgcHJpdmF0ZSBib2R5Q29tcG9uZW50UmVmID0gdmlld0NoaWxkPFZpcnR1YWxTY3JvbGxlckNvbXBvbmVudD4oJ2JvZHlDb21wb25lbnRSZWYnKTs7XG5cbiAgcHJpdmF0ZSBodHRwUmVxdWVzdFNlcnZpY2UgPSBpbmplY3QoTGlic1VpSHR0cFJlcXVlc3RTZXJ2aWNlKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgaWYgKHRoaXMuZGVmYXVsdEtleXNTZWxlY3RlZCgpPy5sZW5ndGgpIHtcbiAgICAgICAgdW50cmFja2VkKCgpID0+IHRoaXMua2V5c1NlbGVjdGVkLnVwZGF0ZShrZXlzID0+IChbLi4ua2V5cywgLi4uKHRoaXMuZGVmYXVsdEtleXNTZWxlY3RlZCgpIHx8IFtdKV0pKSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLnNob3dGb290ZXIoKSkge1xuICAgICAgICB1bnRyYWNrZWQoKCkgPT4gdGhpcy5jYWxsQXBpQnlTZXJ2aWNlRm9vdGVyKCkpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIGlmICh0aGlzLm5ld0RhdGEoKT8uZGF0YSgpLmxlbmd0aCkge1xuICAgICAgICB1bnRyYWNrZWQoKCkgPT4gdGhpcy5hZGRJdGVtcyh0aGlzLm5ld0RhdGEoKT8uZGF0YSBhcyBhbnksICF0aGlzLm5ld0RhdGEoKT8uYWRkVG9MYXN0TGlzdCkpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIGlmICghdGhpcy5maWx0ZXIoKS5maWx0ZXJEYXRhIHx8IHRoaXMuZmlsdGVyKCkuaWdub3JlQ2FsbEFwaUF1dG8pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdW50cmFja2VkKCgpID0+IHtcbiAgICAgICAgdGhpcy5rZXlTZWFyY2guc2V0KGdldDxhbnk+KHRoaXMuZmlsdGVyKCkuZmlsdGVyRGF0YSwgJ2tleVNlYXJjaCcsICcnKSk7XG4gICAgICAgIHRoaXMuc3RvcmVQYXJhbXNDYWxsQXBpLnNldCh0aGlzLmZpbHRlcigpKTtcbiAgICAgICAgaWYgKHRoaXMuZmlsdGVyKCk/LmZpbHRlckRhdGEgJiYgIXRoaXMuZmlsdGVyKCkuZmlsdGVyRGF0YVsnaW5zdGFuY2VTb3J0J10gJiYgdGhpcy5pbnN0YW5jZVNvcnQoKSkge1xuICAgICAgICAgIHRoaXMuc3RvcmVQYXJhbXNDYWxsQXBpLnVwZGF0ZShkYXRhID0+ICh7IC4uLmRhdGEsIGluc3RhbmNlU29ydDogdGhpcy5pbnN0YW5jZVNvcnQoKSB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMuZmlsdGVyT3JTb3J0TG9jYWwoKSAmJiB0aGlzLnN0b3JlcygpLmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuaXRlbXMuc2V0KHRoaXMuZmlsdGVyT3JTb3J0TG9jYWwoKT8uKHNpZ25hbChbLi4udGhpcy5zdG9yZXMoKV0pLCB7IC4uLih0aGlzLmZpbHRlcigpLmZpbHRlckRhdGEgfHwge30pLCBpbnN0YW5jZVNvcnQ6IHRoaXMuaW5zdGFuY2VTb3J0KCkgfSkgfHwgW10pO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jYWxsQXBpQnlTZXJ2aWNlKHRydWUpO1xuICAgICAgfSk7XG5cbiAgICB9KTtcbiAgfVxuXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMub3V0RnVuY3Rpb25zQ29udHJvbC5lbWl0KHtcbiAgICAgIHJlc2V0OiB0aGlzLnJlc2V0LmJpbmQodGhpcyksXG4gICAgICBjYWxsQXBpQnlTZXJ2aWNlOiB0aGlzLmNhbGxBcGlCeVNlcnZpY2UuYmluZCh0aGlzKSxcbiAgICAgIHJlc2V0U2Nyb2xsOiB0aGlzLnJlc2V0U2Nyb2xsLmJpbmQodGhpcyksXG4gICAgICBhZGRJdGVtczogdGhpcy5hZGRJdGVtcy5iaW5kKHRoaXMpLFxuICAgICAgcmVtb3ZlSXRlbXM6IHRoaXMucmVtb3ZlSXRlbXMuYmluZCh0aGlzKSxcbiAgICAgIGdldENvdW50OiB0aGlzLmdldENvdW50LmJpbmQodGhpcyksXG4gICAgICBnZXRTY3JvbGxDb250YWluZXI6IHRoaXMuZ2V0U2Nyb2xsQ29udGFpbmVyLmJpbmQodGhpcyksXG4gICAgICBoaWRlVG9vbEJhckJvdHRvbTogKCkgPT4ge1xuICAgICAgICByZXR1cm47XG4gICAgICB9LFxuICAgICAgcmVzZXRLZXlTZWxlY3RlZDogKCkgPT4gdGhpcy5rZXlzU2VsZWN0ZWQuc2V0KFtdKVxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTY3JvbGxDb250YWluZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuYm9keUNvbXBvbmVudFJlZigpIGFzIFZpcnR1YWxTY3JvbGxlckNvbXBvbmVudDtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2FsbEFwaUJ5U2VydmljZShmaXJzdENhbGw6IGJvb2xlYW4sIHJlc2V0QWZ0ZXJDYWxsQXBpPzogYm9vbGVhbikge1xuICAgIHRyeSB7XG4gICAgICBpZiAoZmlyc3RDYWxsKSB7XG4gICAgICAgIHRoaXMubG9hZGVkTGFzdEl0ZW0uc2V0KGZhbHNlKTtcbiAgICAgIH1cbiAgICAgIGlmICghdGhpcy5odHRwUmVxdWVzdERhdGEoKSB8fCB0aGlzLmxvYWRpbmcoKSB8fCB0aGlzLmxvYWRlZExhc3RJdGVtKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhpcy5sb2FkaW5nLnNldCh0cnVlKTtcbiAgICAgIHRoaXMub3V0TG9hZGluZy5lbWl0KHRoaXMubG9hZGluZygpKTtcbiAgICAgIHRoaXMucmVzZXRJbmRleEhvdmVyKCk7XG4gICAgICBjb25zdCB7IGFyZ3VtZW50c1ZhbHVlLCBndWlkZUF1dG9VcGRhdGVBcmd1bWVudHNWYWx1ZSB9ID0gdGhpcy5odHRwUmVxdWVzdERhdGEoKSBhcyBJSHR0cFJlcXVlc3RDb25maWc7XG5cbiAgICAgIGlmIChndWlkZUF1dG9VcGRhdGVBcmd1bWVudHNWYWx1ZSAmJiAhZ3VpZGVBdXRvVXBkYXRlQXJndW1lbnRzVmFsdWUuc29ydE9yZGVyQnkgJiYgdGhpcy5pbnN0YW5jZVNvcnQoKSkge1xuICAgICAgICBndWlkZUF1dG9VcGRhdGVBcmd1bWVudHNWYWx1ZS5zb3J0T3JkZXJCeSA9IHtcbiAgICAgICAgICBmaWVsZEdldFZhbHVlOiAnc3RvcmVQYXJhbXNDYWxsQXBpLmluc3RhbmNlU29ydC5maWVsZFNvcnQnLFxuICAgICAgICAgIGZpZWxkVXBkYXRlOiAnWzBdJyxcbiAgICAgICAgICBzdWJGaWVsZFVwZGF0ZTogJ29yZGVyX2J5J1xuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICBpZiAoZ3VpZGVBdXRvVXBkYXRlQXJndW1lbnRzVmFsdWUgJiYgIWd1aWRlQXV0b1VwZGF0ZUFyZ3VtZW50c1ZhbHVlLnNvcnRPcmRlclR5cGUgJiYgdGhpcy5pbnN0YW5jZVNvcnQoKSkge1xuICAgICAgICBndWlkZUF1dG9VcGRhdGVBcmd1bWVudHNWYWx1ZS5zb3J0T3JkZXJUeXBlID0ge1xuICAgICAgICAgIGZpZWxkR2V0VmFsdWU6ICdzdG9yZVBhcmFtc0NhbGxBcGkuaW5zdGFuY2VTb3J0Lm1vZGUnLFxuICAgICAgICAgIGZpZWxkVXBkYXRlOiAnWzBdJyxcbiAgICAgICAgICBzdWJGaWVsZFVwZGF0ZTogJ29yZGVyX3R5cGUnXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgICBpZiAoZmlyc3RDYWxsKSB7XG4gICAgICAgIGlmICghcmVzZXRBZnRlckNhbGxBcGkpIHtcbiAgICAgICAgICB0aGlzLmhhc1Njcm9sbC5zZXQoZmFsc2UpO1xuICAgICAgICAgIHRoaXMuc3RvcmVzLnNldChbXSk7XG4gICAgICAgICAgdGhpcy5pdGVtcy5zZXQoW10pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubG9hZGVkTGFzdEl0ZW0uc2V0KHRoaXMuaHR0cFJlcXVlc3RTZXJ2aWNlLnVwZGF0ZUFyZ3VtZW50cyhhcmd1bWVudHNWYWx1ZSwgeyAuLi50aGlzLmZha2VSZXNwb25zZUFwaSgpLCBzdG9yZVBhcmFtc0NhbGxBcGk6IHRoaXMuc3RvcmVQYXJhbXNDYWxsQXBpKCkgfSwgdGhpcy5wYWdpbmdTdG9yZSgpLCB0aGlzLmtleVNlYXJjaCgpLCB0cnVlLCB0aGlzLmxvYWRlZExhc3RJdGVtKCksIGd1aWRlQXV0b1VwZGF0ZUFyZ3VtZW50c1ZhbHVlKSk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmh0dHBSZXF1ZXN0U2VydmljZS5jYWxsQXBpKHRoaXMuaHR0cFJlcXVlc3REYXRhKCkgYXMgSUh0dHBSZXF1ZXN0Q29uZmlnKTtcblxuICAgICAgaWYgKGZpcnN0Q2FsbCAmJiByZXNldEFmdGVyQ2FsbEFwaSkge1xuICAgICAgICB0aGlzLmhhc1Njcm9sbC5zZXQoZmFsc2UpO1xuICAgICAgICB0aGlzLnN0b3Jlcy5zZXQoW10pO1xuICAgICAgICB0aGlzLml0ZW1zLnNldChbXSk7XG4gICAgICB9XG4gICAgICB0aGlzLnBhZ2luZ1N0b3JlLnNldChyZXN1bHQucGFnaW5nKTtcbiAgICAgIHRoaXMudG90YWxJdGVtSW5CYWNrZW5kLnNldChyZXN1bHQucGFnaW5nPy50b3RhbF9pdGVtcyB8fCAwKTtcbiAgICAgIHRoaXMub3V0VG90YWxJdGVtLmVtaXQodGhpcy50b3RhbEl0ZW1JbkJhY2tlbmQoKSk7XG4gICAgICBpZiAoIXRoaXMucGFnaW5nU3RvcmUoKSkge1xuICAgICAgICB0aGlzLmxvYWRlZExhc3RJdGVtLnNldCh0cnVlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubG9hZGVkTGFzdEl0ZW0uc2V0KHRoaXMuaHR0cFJlcXVlc3RTZXJ2aWNlLnVwZGF0ZUFyZ3VtZW50cyhhcmd1bWVudHNWYWx1ZSwgeyAuLi5yZXN1bHQsIHN0b3JlUGFyYW1zQ2FsbEFwaTogdGhpcy5zdG9yZVBhcmFtc0NhbGxBcGkoKSB9LCB0aGlzLnBhZ2luZ1N0b3JlKCksIHRoaXMua2V5U2VhcmNoKCksIHRydWUsIHRoaXMubG9hZGVkTGFzdEl0ZW0oKSwgZ3VpZGVBdXRvVXBkYXRlQXJndW1lbnRzVmFsdWUpKTtcbiAgICAgIGF3YWl0IHRoaXMuYWRkSXRlbXMoY29udmVydE9iamVjdFRvU2lnbmFsKHJlc3VsdC5kYXRhIHx8IFtdKSwgZmFsc2UsIHRydWUpO1xuICAgICAgdGhpcy5vdXRMb2FkRGF0YUNvbXBsZXRlLmVtaXQodGhpcy5zdG9yZXMpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmxvZyhlcnJvcik7XG4gICAgICB0aGlzLm91dExvYWREYXRhRXJyb3IuZW1pdChlcnJvciBhcyBJSHR0cFJlc3BvbnNlRXJyb3IpO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICAgIHRoaXMub3V0TG9hZGluZy5lbWl0KHRoaXMubG9hZGluZygpKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgZmFrZVJlc3BvbnNlQXBpKCk6IFJlY29yZDxhbnksIGFueT4ge1xuICAgIHRoaXMubG9hZGVkTGFzdEl0ZW0uc2V0KGZhbHNlKTtcbiAgICB0aGlzLnBhZ2luZ1N0b3JlLnNldCh7fSk7XG5cbiAgICByZXR1cm4gdGhpcy5odHRwUmVxdWVzdFNlcnZpY2UuZmFrZVJlc3BvbnNlUGFnaW5nQXBpKCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGxBcGlCeVNlcnZpY2VGb290ZXIoKSB7XG4gICAgaWYgKCF0aGlzLmh0dHBSZXF1ZXN0RGF0YUZvb3RlcigpIHx8ICF0aGlzLnNob3dGb290ZXIoKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCB7IGFyZ3VtZW50c1ZhbHVlLCBndWlkZUF1dG9VcGRhdGVBcmd1bWVudHNWYWx1ZSB9ID0gdGhpcy5odHRwUmVxdWVzdERhdGFGb290ZXIoKSBhcyBJSHR0cFJlcXVlc3RDb25maWc7XG5cbiAgICB0aGlzLmh0dHBSZXF1ZXN0U2VydmljZS51cGRhdGVBcmd1bWVudHMoYXJndW1lbnRzVmFsdWUsIHsgc3RvcmVQYXJhbXNDYWxsQXBpOiB0aGlzLnN0b3JlUGFyYW1zQ2FsbEFwaSgpIH0sIHRoaXMucGFnaW5nU3RvcmUoKSwgdGhpcy5rZXlTZWFyY2goKSwgdHJ1ZSwgZmFsc2UsIGd1aWRlQXV0b1VwZGF0ZUFyZ3VtZW50c1ZhbHVlKTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLmh0dHBSZXF1ZXN0U2VydmljZS5jYWxsQXBpKHRoaXMuaHR0cFJlcXVlc3REYXRhRm9vdGVyKCkgYXMgSUh0dHBSZXF1ZXN0Q29uZmlnKTtcblxuICAgIHRoaXMuaXRlbUZvb3Rlci5zZXQoY29udmVydE9iamVjdFRvU2lnbmFsKHJlc3VsdC5kYXRhKSgpKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWRkSXRlbXMoaXRlbXM6IFRZUEVfREFUQV9UQUJMRSwgYWRkRmlyc3Q6IGJvb2xlYW4sIGlnbm9yZUhpZ2h0TGlnaHQ/OiBib29sZWFuLCBpZ25vcmVSZUNhbGxGb290ZXI/OiBib29sZWFuLCBhdXRvQ291bnROZXdJdGVtPzogYm9vbGVhbikge1xuICAgIGlmICghaXRlbXMoKSB8fCAhaXRlbXMoKS5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgaXRlbXNBZGQ6IEFycmF5PFdyaXRhYmxlU2lnbmFsPFJlY29yZDxhbnksIGFueT4+PiA9IFtdO1xuXG4gICAgaXRlbXMoKS5mb3JFYWNoKGl0ZW0gPT4ge1xuICAgICAgaWYgKCF0aGlzLmNoZWNrRXhpc3RJdGVtKGl0ZW0pKSB7XG4gICAgICAgIGl0ZW1zQWRkLnB1c2goaXRlbSk7XG4gICAgICAgIGlmICghaWdub3JlSGlnaHRMaWdodCkge1xuICAgICAgICAgIHRoaXMuaGFzSXRlbUhpZ2h0TGlnaHQuc2V0KHRydWUpO1xuICAgICAgICAgIGl0ZW0udXBkYXRlKGRhdGEgPT4gKHsgLi4uZGF0YSwgc3BlY2lmaWNIaWdodExpZ2h0OiB0cnVlIH0pKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYWRkRmlyc3QpIHtcbiAgICAgICAgICB0aGlzLml0ZW1zLnVwZGF0ZShkYXRhID0+IFtpdGVtLCAuLi5kYXRhXSk7XG4gICAgICAgICAgdGhpcy5zdG9yZXMudXBkYXRlKGRhdGEgPT4gW2l0ZW0sIC4uLmRhdGFdKTtcblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLml0ZW1zLnVwZGF0ZShkYXRhID0+IFsuLi5kYXRhLCBpdGVtXSk7XG4gICAgICAgIHRoaXMuc3RvcmVzLnVwZGF0ZShkYXRhID0+IFsuLi5kYXRhLCBpdGVtXSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgaWYgKGF1dG9Db3VudE5ld0l0ZW0gJiYgaXRlbXNBZGQubGVuZ3RoKSB7XG4gICAgICB0aGlzLnRvdGFsSXRlbUluQmFja2VuZC51cGRhdGUodmFsdWUgPT4gdmFsdWUgKyBpdGVtc0FkZC5sZW5ndGgpO1xuICAgIH1cbiAgICBpZiAoIWlnbm9yZUhpZ2h0TGlnaHQpIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpdGVtc0FkZC5mb3JFYWNoKGl0ZW0gPT4gaXRlbS51cGRhdGUoZGF0YSA9PiAoeyAuLi5kYXRhLCBzcGVjaWZpY0hpZ2h0TGlnaHQ6IGZhbHNlIH0pKSk7XG4gICAgICAgIHRoaXMuaGFzSXRlbUhpZ2h0TGlnaHQuc2V0KGZhbHNlKTtcbiAgICAgIH0sIHRoaXMudGltZUhpZ2hsaWdoTmV3SXRlbSgpKTtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy5jaGVja1Njcm9sbCgpO1xuICAgIGlmICghaWdub3JlUmVDYWxsRm9vdGVyKSB7XG4gICAgICBhd2FpdCB0aGlzLmNhbGxBcGlCeVNlcnZpY2VGb290ZXIoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGNoZWNrRXhpc3RJdGVtKGl0ZW1OZXc6IFdyaXRhYmxlU2lnbmFsPFJlY29yZDxhbnksIGFueT4+KTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaXRlbXMoKS5maW5kKGl0ZW0gPT4gYCR7aXRlbSgpW3RoaXMuZmllbGRLZXkoKV19YCA9PT0gYCR7aXRlbU5ldygpW3RoaXMuZmllbGRLZXkoKV19YCkgPyB0cnVlIDogZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHJlbW92ZUl0ZW1zKGtleXM6IEFycmF5PHVua25vd24+LCBpZ25vcmVSZUNhbGxGb290ZXI/OiBib29sZWFuKSB7XG4gICAgdGhpcy5yZXNldEluZGV4SG92ZXIoKTtcbiAgICBpZiAoIXRoaXMuaXRlbXMoKS5sZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAga2V5cy5mb3JFYWNoKGtleSA9PiB7XG4gICAgICB0aGlzLml0ZW1zLnVwZGF0ZShpdGVtcyA9PiB7XG4gICAgICAgIGxldCBpc1VwZGF0ZSA9IGZhbHNlO1xuXG4gICAgICAgIGNvbnN0IG5ld0l0ZW1zID0gaXRlbXMuZmlsdGVyKGl0ZW0gPT4ge1xuICAgICAgICAgIGlmIChgJHtpdGVtKClbdGhpcy5maWVsZEtleSgpXX1gID09PSBgJHtrZXl9YCkge1xuICAgICAgICAgICAgaXNVcGRhdGUgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGlzVXBkYXRlID8gbmV3SXRlbXMgOiBpdGVtcztcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLnN0b3Jlcy51cGRhdGUoaXRlbXMgPT4ge1xuICAgICAgICBsZXQgaXNVcGRhdGUgPSBmYWxzZTtcblxuICAgICAgICBjb25zdCBuZXdJdGVtcyA9IGl0ZW1zLmZpbHRlcihpdGVtID0+IHtcbiAgICAgICAgICBpZiAoYCR7aXRlbSgpW3RoaXMuZmllbGRLZXkoKV19YCA9PT0gYCR7a2V5fWApIHtcbiAgICAgICAgICAgIGlzVXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBpc1VwZGF0ZSA/IG5ld0l0ZW1zIDogaXRlbXM7XG4gICAgICB9KTtcblxuICAgICAgaWYgKCF0aGlzLmtleXNTZWxlY3RlZCgpIHx8ICF0aGlzLmtleXNTZWxlY3RlZCgpLmxlbmd0aCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICB0aGlzLmtleXNTZWxlY3RlZC51cGRhdGUoa2V5cyA9PiBrZXlzLmZpbHRlcihrZXlTZWxlY3RlZCA9PiBrZXlTZWxlY3RlZCAhPT0ga2V5KSk7XG4gICAgfSk7XG4gICAgdGhpcy50b3RhbEl0ZW1JbkJhY2tlbmQudXBkYXRlKHZhbHVlID0+IHZhbHVlIC0ga2V5cy5sZW5ndGgpO1xuICAgIGF3YWl0IHRoaXMuY2hlY2tTY3JvbGwoKTtcbiAgICBpZiAoIWlnbm9yZVJlQ2FsbEZvb3Rlcikge1xuICAgICAgYXdhaXQgdGhpcy5jYWxsQXBpQnlTZXJ2aWNlRm9vdGVyKCk7XG4gICAgfVxuICAgIHRoaXMub3V0S2V5c1NlbGVjdGVkLmVtaXQoeyBrZXlzOiB0aGlzLmtleXNTZWxlY3RlZCgpIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRDb3VudCgpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmh0dHBSZXF1ZXN0RGF0YSgpKSB7XG4gICAgICByZXR1cm4gdGhpcy5wYWdpbmdTdG9yZSgpPy50b3RhbF9pdGVtcyB8fCB0aGlzLml0ZW1zKCkubGVuZ3RoO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLml0ZW1zKCkubGVuZ3RoO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZXJTY3JvbGwoZTogYW55KSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAodGhpcy5oZWFkZXJFbGVtZW50UmVmKCkgYXMgYW55KS5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSBlLnRhcmdldC5zY3JvbGxMZWZ0O1xuICAgIGlmICh0aGlzLmZvb3RlckVsZW1lbnRSZWYoKSkge1xuICAgICAgKHRoaXMuZm9vdGVyRWxlbWVudFJlZigpIGFzIGFueSkubmF0aXZlRWxlbWVudC5zY3JvbGxMZWZ0ID0gZS50YXJnZXQuc2Nyb2xsTGVmdDtcbiAgICB9XG4gICAgdGhpcy5yZXNldEluZGV4SG92ZXIoZSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlclNjcm9sbEJvdHRvbShlOiBFdmVudCkge1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgdGhpcy5sb2FkTW9yZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2FkTW9yZSgpIHtcbiAgICBpZiAodGhpcy5sb2FkaW5nKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5vdXRMb2FkTW9yZS5lbWl0KHsgbG9hZE1vcmVTdWNjZXNzOiB0aGlzLmxvYWRNb3JlU3VjY2Vzcy5iaW5kKHRoaXMpIH0pO1xuICAgIHRoaXMuY2FsbEFwaUJ5U2VydmljZShmYWxzZSk7XG4gIH1cblxuICBwcml2YXRlIGxvYWRNb3JlU3VjY2VzcyhkYXRhOiBXcml0YWJsZVNpZ25hbDxBcnJheTxXcml0YWJsZVNpZ25hbDxSZWNvcmQ8YW55LCBhbnk+Pj4+KSB7XG4gICAgdGhpcy5hZGRJdGVtcyhkYXRhLCBmYWxzZSk7XG4gICAgdGhpcy5sb2FkaW5nLnNldChmYWxzZSk7XG4gICAgdGhpcy5vdXRMb2FkaW5nLmVtaXQodGhpcy5sb2FkaW5nKCkpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZXJDaGFuZ2VBbGxDaGVja2VkKCkge1xuICAgIHRoaXMua2V5c1NlbGVjdGVkLnNldChbXSk7XG4gICAgdGhpcy5vdXRLZXlzU2VsZWN0ZWQuZW1pdCh7IGtleXM6IHRoaXMua2V5c1NlbGVjdGVkKCkgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlckNoYW5nZUNoZWNrZWRBbGxJdGVtcyhldmVudDogSUNoZWNrYm94RXZlbnQpIHtcbiAgICBpZiAoZXZlbnQuY2hlY2tlZCkge1xuICAgICAgdGhpcy5rZXlzU2VsZWN0ZWQuc2V0KHRoaXMuaXRlbXMoKS5maWx0ZXIoYXN5bmMgKGl0ZW0pID0+ICEoYXdhaXQgdGhpcy5jaGVja0NhbmNlbENvbmRpdGlvbkNoZWNrZWRJdGVtKGl0ZW0pKSkubWFwKGl0ZW0gPT4gYCR7aXRlbSgpW3RoaXMuZmllbGRLZXkoKV19YCkpO1xuICAgICAgdGhpcy5vdXRLZXlzU2VsZWN0ZWQuZW1pdCh7IGtleXM6IHRoaXMua2V5c1NlbGVjdGVkKCkgfSk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5rZXlzU2VsZWN0ZWQuc2V0KFtdKTtcbiAgICB0aGlzLm91dEtleXNTZWxlY3RlZC5lbWl0KHsga2V5czogdGhpcy5rZXlzU2VsZWN0ZWQoKSB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tDYW5jZWxDb25kaXRpb25DaGVja2VkSXRlbShpdGVtOiBXcml0YWJsZVNpZ25hbDxSZWNvcmQ8YW55LCBhbnk+Pikge1xuICAgIGxldCBpc0NhbmNlbENoZWNrID0gZmFsc2U7XG5cbiAgICBpZiAoIWlzQ2FuY2VsQ2hlY2sgJiYgdGhpcy5oZWFkZXJMZWZ0KCkubGVuZ3RoICYmIHRoaXMuaGVhZGVyTGVmdCgpWzBdLmNoZWNrQ29uZGl0aW9uQ2hlY2tCb3hIaWRkZW4pIHtcbiAgICAgIGlzQ2FuY2VsQ2hlY2sgPSBhd2FpdCBsYXN0VmFsdWVGcm9tKCh0aGlzLmhlYWRlckxlZnQoKVswXS5jaGVja0NvbmRpdGlvbkNoZWNrQm94SGlkZGVuIGFzIGFueSkoeyBpdGVtOiBpdGVtKCkgfSkpIHx8IGZhbHNlO1xuICAgIH1cblxuICAgIGlmICghaXNDYW5jZWxDaGVjayAmJiB0aGlzLmhlYWRlclJpZ2h0KCkubGVuZ3RoICYmIHRoaXMuaGVhZGVyUmlnaHQoKVswXS5jaGVja0NvbmRpdGlvbkNoZWNrQm94SGlkZGVuKSB7XG4gICAgICBpc0NhbmNlbENoZWNrID0gYXdhaXQgbGFzdFZhbHVlRnJvbSgodGhpcy5oZWFkZXJSaWdodCgpWzBdLmNoZWNrQ29uZGl0aW9uQ2hlY2tCb3hIaWRkZW4gYXMgYW55KSh7IGl0ZW06IGl0ZW0oKSB9KSkgfHwgZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIGlzQ2FuY2VsQ2hlY2s7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlckNoYW5nZUl0ZW1DaGVja2VkKGV2ZW50OiBJQ2hlY2tib3hJdGVtLCBpdGVtOiBSZWNvcmQ8YW55LCBhbnk+KSB7XG4gICAgY29uc3Qga2V5ID0gaXRlbVt0aGlzLmZpZWxkS2V5KCldO1xuICAgIGNvbnN0IGtleXMgPSBuZXcgU2V0KHRoaXMua2V5c1NlbGVjdGVkKCkpO1xuXG4gICAga2V5cy5hZGQoa2V5KTtcbiAgICBpZiAoIWV2ZW50LmNoZWNrZWQpIHtcbiAgICAgIGtleXMuZGVsZXRlKGtleSk7XG4gICAgfVxuICAgIHRoaXMua2V5c1NlbGVjdGVkLnNldChBcnJheS5mcm9tKGtleXMpKTtcbiAgICB0aGlzLm91dEtleXNTZWxlY3RlZC5lbWl0KHsga2V5czogdGhpcy5rZXlzU2VsZWN0ZWQoKSB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVyQ2hhbmdlU29ydChzb3J0OiBJU29ydCkge1xuICAgIGlmICh0aGlzLmluc3RhbmNlU29ydCAmJiB0aGlzLmluc3RhbmNlU29ydCgpPy5maWVsZFNvcnQgIT09IHNvcnQuZmllbGRTb3J0KSB7XG4gICAgICB0aGlzLmluc3RhbmNlU29ydCgpPy5yZXNldCgpO1xuICAgIH1cbiAgICB0aGlzLmluc3RhbmNlU29ydC5zZXQoc29ydCk7XG4gICAgaWYgKHRoaXMuc29ydExvY2FsKCkpIHtcbiAgICAgIHRoaXMuaGFuZGxlclNvcnRMb2NhbChzb3J0KTtcblxuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLnN0b3JlUGFyYW1zQ2FsbEFwaS51cGRhdGUoZGF0YSA9PiAoeyAuLi5kYXRhLCBpbnN0YW5jZVNvcnQ6IHRoaXMuaW5zdGFuY2VTb3J0KCkgfSkpO1xuICAgIHRoaXMuY2FsbEFwaUJ5U2VydmljZSh0cnVlKTtcbiAgICB0aGlzLm91dFNvcnQuZW1pdCh7XG4gICAgICBzb3J0OiBzb3J0LFxuICAgICAgb25Tb3J0U3VjY2VzczogdGhpcy5vblNvcnRTdWNjZXNzLmJpbmQodGhpcylcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlclNvcnRMb2NhbChzb3J0OiBJU29ydCkge1xuICAgIGlmICh0aGlzLmZpbHRlck9yU29ydExvY2FsKCkgJiYgdGhpcy5zdG9yZXMoKS5sZW5ndGgpIHtcbiAgICAgIHRoaXMuaXRlbXMuc2V0KHRoaXMuZmlsdGVyT3JTb3J0TG9jYWwoKT8uKHNpZ25hbChbLi4udGhpcy5zdG9yZXMoKV0pLCB7IC4uLnRoaXMuc3RvcmVQYXJhbXNDYWxsQXBpKCksIGluc3RhbmNlU29ydDogc29ydCB9KSB8fCBbXSk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgeyBmaWVsZFNvcnQsIG1vZGUgfSA9IHNvcnQ7XG5cbiAgICB0aGlzLml0ZW1zLnVwZGF0ZShpdGVtcyA9PiB7XG4gICAgICBpdGVtcy5zb3J0KChpdGVtQSwgaXRlbUIpID0+IHtcbiAgICAgICAgbGV0IHZhbHVlMSA9IG1vZGUgPT09ICdhc2MnID8gaXRlbUEoKVtmaWVsZFNvcnRdIDogaXRlbUIoKVtmaWVsZFNvcnRdO1xuICAgICAgICBsZXQgdmFsdWUyID0gbW9kZSA9PT0gJ2FzYycgPyBpdGVtQigpW2ZpZWxkU29ydF0gOiBpdGVtQSgpW2ZpZWxkU29ydF07XG5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZTEgPT09ICdzdHJpbmcnICYmIHR5cGVvZiB2YWx1ZTIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdmFsdWUxID0gZGVsZXRlVW5pY29kZSh2YWx1ZTEpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgICAgdmFsdWUyID0gZGVsZXRlVW5pY29kZSh2YWx1ZTIpLnRvTG9jYWxlTG93ZXJDYXNlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUxID09PSB2YWx1ZTIpIHtcbiAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YWx1ZTEgPiB2YWx1ZTIgPyAxIDogLTE7XG4gICAgICB9KTtcblxuICAgICAgcmV0dXJuIFsuLi5pdGVtc107XG4gICAgfSk7XG4gICAgdGhpcy5vblNvcnRTdWNjZXNzKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlckZ1bmN0aW9uQ29udHJvbE1vcmVTZWxlY3RJdGVtKGZ1bmN0aW9uQ29udHJvbDogSURyb3Bkb3duRnVuY3Rpb25Db250cm9sRXZlbnQpIHtcbiAgICB0aGlzLmZ1bmN0aW9uQ29udHJvbFNlbGVjdE1vcmVJdGVtID0gZnVuY3Rpb25Db250cm9sO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZXJTZWxlY3RlZE1vcmVJdGVtKGV2ZW50OiBJRW1pdFNlbGVjdEtleSB8IHVuZGVmaW5lZCkge1xuICAgIGlmICghZXZlbnQgfHwgIWV2ZW50LmtleSB8fCAhdGhpcy5jb25maWdTZWxlY3RNb3JlSXRlbSgpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5mdW5jdGlvbkNvbnRyb2xTZWxlY3RNb3JlSXRlbT8ucmVzZXQoKTtcblxuICAgIGNvbnN0IHBlclBhZ2UgPSBOdW1iZXIoZXZlbnQua2V5KS52YWx1ZU9mKCk7XG4gICAgY29uc3QgY3VycmVudFBhZ2UgPSBOdW1iZXIodGhpcy5zZXRQZXJQYWdlU2VsZWN0TW9yZUl0ZW0ocGVyUGFnZSkpLnZhbHVlT2YoKTtcbiAgICBjb25zdCBpc1BhZ2luZ051bWJlciA9IHRoaXMuY29uZmlnU2VsZWN0TW9yZUl0ZW0oKT8ucGFnaW5nTnVtYmVyO1xuXG4gICAgaWYgKGN1cnJlbnRQYWdlID4gcGVyUGFnZSB8fCB0aGlzLml0ZW1zLmxlbmd0aCA+PSBwZXJQYWdlKSB7XG4gICAgICBpZiAoIWlzUGFnaW5nTnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0UGVyUGFnZVNlbGVjdE1vcmVJdGVtKGN1cnJlbnRQYWdlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMua2V5c1NlbGVjdGVkLnNldCh0aGlzLml0ZW1zKCkuc2xpY2UoMCwgcGVyUGFnZSkubWFwKGl0ZW0gPT4gYCR7aXRlbSgpW3RoaXMuZmllbGRLZXkoKV19YCkpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5jYWxsQXBpQnlTZXJ2aWNlKHRydWUsIHRydWUpO1xuICAgIGNvbnN0IHN1YiA9IHRoaXMub3V0TG9hZERhdGFDb21wbGV0ZS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgc3ViLnVuc3Vic2NyaWJlKCk7XG4gICAgICBpZiAoIWlzUGFnaW5nTnVtYmVyKSB7XG4gICAgICAgIHRoaXMuc2V0UGVyUGFnZVNlbGVjdE1vcmVJdGVtKGN1cnJlbnRQYWdlKTtcbiAgICAgIH1cbiAgICAgIHRoaXMua2V5c1NlbGVjdGVkLnNldCh0aGlzLml0ZW1zKCkuc2xpY2UoMCwgcGVyUGFnZSkubWFwKGl0ZW0gPT4gYCR7aXRlbSgpW3RoaXMuZmllbGRLZXkoKV19YCkpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vdXRMb2FkRGF0YUVycm9yLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICB0aGlzLnNldFBlclBhZ2VTZWxlY3RNb3JlSXRlbShjdXJyZW50UGFnZSk7XG4gICAgfSk7XG4gIH1cbiAgcHJpdmF0ZSBzZXRQZXJQYWdlU2VsZWN0TW9yZUl0ZW0ocGVyUGFnZTogc3RyaW5nIHwgbnVtYmVyKTogc3RyaW5nIHtcbiAgICBjb25zdCBhcmd1bWVudHNWYWx1ZSA9IHRoaXMuaHR0cFJlcXVlc3REYXRhKCk/LmFyZ3VtZW50c1ZhbHVlO1xuXG4gICAgaWYgKCFhcmd1bWVudHNWYWx1ZSB8fCAhdGhpcy5jb25maWdTZWxlY3RNb3JlSXRlbSgpKSB7XG4gICAgICByZXR1cm4gJy0xJztcbiAgICB9XG4gICAgY29uc3Qga2V5UGVyUGFnZSA9IHRoaXMuY29uZmlnU2VsZWN0TW9yZUl0ZW0oKT8ua2V5UGVyUGFnZSB8fCAncGVyX3BhZ2UnO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcmd1bWVudHNWYWx1ZS5sZW5ndGg7IGkrKykge1xuICAgICAgbGV0IGFyZ3VtZW50ID0gYXJndW1lbnRzVmFsdWVbaV07XG5cbiAgICAgIGlmIChhcmd1bWVudCBpbnN0YW5jZW9mIEh0dHBQYXJhbXMgJiYgYXJndW1lbnQuaGFzKGtleVBlclBhZ2UpKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRQZXJQYWdlID0gYXJndW1lbnQuZ2V0KGtleVBlclBhZ2UpIHx8ICcyNSc7XG5cbiAgICAgICAgYXJndW1lbnQgPSBhcmd1bWVudC5zZXQoa2V5UGVyUGFnZSwgcGVyUGFnZSk7XG4gICAgICAgIHNldChhcmd1bWVudHNWYWx1ZSwgYCR7aX1gLCBhcmd1bWVudCk7XG5cbiAgICAgICAgcmV0dXJuIGN1cnJlbnRQZXJQYWdlO1xuICAgICAgfVxuXG4gICAgICBpZiAoYXJndW1lbnQgaW5zdGFuY2VvZiBPYmplY3QgJiYgT2JqZWN0LmtleXMoYXJndW1lbnQpLmluY2x1ZGVzKGtleVBlclBhZ2UpKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRQZXJQYWdlID0gYXJndW1lbnQuZ2V0KGtleVBlclBhZ2UpIHx8ICcyNSc7XG5cbiAgICAgICAgc2V0KGFyZ3VtZW50LCBrZXlQZXJQYWdlLCBwZXJQYWdlKTtcblxuICAgICAgICByZXR1cm4gY3VycmVudFBlclBhZ2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuICctMSc7XG4gIH1cblxuICBwcml2YXRlIG9uU29ydFN1Y2Nlc3MoKSB7XG4gICAgdGhpcy5sb2FkaW5nLnNldChmYWxzZSk7XG4gICAgdGhpcy5vdXRMb2FkaW5nLmVtaXQodGhpcy5sb2FkaW5nKCkpO1xuICAgIHRoaXMucmVzZXRTY3JvbGwoKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVyQnV0dG9uQ2xpY2sodHlwZTogJ2J1dHRvbicgfCAnYnV0dG9uLWRyb3Bkb3duJywgYnV0dG9uRHJvcGRvd25EYXRhOiBhbnksIGJ1dHRvbjogSUJ1dHRvbikgeyAvLyBidXR0b25PcmlnaW4gY2jhu4kgc+G7rSBk4bulbmcga2hpIGTDuW5nIGJ1dHRvbkFjdGlvbnMgY8OzIGJ1dHRvbi1kcm9wZG93blxuICAgIGlmICh0eXBlID09PSAnYnV0dG9uJykge1xuICAgICAgcmV0dXJuIHRoaXMub3V0Q2xpY2tCdXR0b25BY3Rpb24uZW1pdCh7IGl0ZW06IHRoaXMuaXRlbU9mSW5kZXhIb3ZlciwgYnV0dG9uOiBidXR0b24gfSk7XG4gICAgfVxuICAgIHRoaXMub3V0Q2xpY2tCdXR0b25BY3Rpb24uZW1pdCh7IGl0ZW06IHRoaXMuaXRlbU9mSW5kZXhIb3ZlciwgYnV0dG9uLCBidXR0b25Ecm9wZG93bkRhdGEgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgaGFuZGxlckJhckJ1dHRvbkNsaWNrKGJ1dHRvbjogSUJ1dHRvbikge1xuICAgIGNvbnN0IGl0ZW1zOiBBcnJheTxXcml0YWJsZVNpZ25hbDxhbnk+PiA9IFtdO1xuXG4gICAgdGhpcy5rZXlzU2VsZWN0ZWQoKS5mb3JFYWNoKGtleSA9PiB7XG4gICAgICBjb25zdCBpdGVtID0gdGhpcy5pdGVtcygpLmZpbmQoaXRlbSA9PiBgJHtpdGVtKClbdGhpcy5maWVsZEtleSgpXX1gID09PSBgJHtrZXl9YCk7XG5cbiAgICAgIGlmIChpdGVtKSB7XG4gICAgICAgIGl0ZW1zLnB1c2goaXRlbSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gdGhpcy5vdXRDbGlja0JhckJ1dHRvbi5lbWl0KHtcbiAgICAgIGJ1dHRvbixcbiAgICAgIGl0ZW1zLFxuICAgICAga2V5czogdGhpcy5rZXlzU2VsZWN0ZWQoKSxcbiAgICAgIGhpZGRlbkJhckJ1dHRvbnM6ICgpID0+IHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZXJCdXR0b25Ecm9wZG93bkV2ZW50KGV2ZW50TmFtZTogVFlQRV9QT1BPVkVSX0VWRU5UKSB7XG4gICAgdGhpcy5oYXNBY3Rpb25CdXR0b25Ecm9wZG93bkNvbnRlbnQuc2V0KHRydWUpO1xuICAgIGlmIChldmVudE5hbWUgPT09ICdyZW1vdmUnIHx8IGV2ZW50TmFtZSA9PT0gJ21vdXNlbGVhdmUtY29udGVudCcpIHtcbiAgICAgIHRoaXMuaGFzQWN0aW9uQnV0dG9uRHJvcGRvd25Db250ZW50LnNldChmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIHNldEluZGV4SG92ZXIoZTogRXZlbnQsIGl0ZW06IFdyaXRhYmxlU2lnbmFsPFJlY29yZDxhbnksIGFueT4+KSB7XG4gICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBpZiAoIXRoaXMuaXRlbXMoKS5sZW5ndGgpIHtcbiAgICAgIHRoaXMucmVzZXRJbmRleEhvdmVyKCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5pdGVtT2ZJbmRleEhvdmVyID0gaXRlbTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZXNldEluZGV4SG92ZXJXaGVuTW91c2VMZWF2ZShlPzogRXZlbnQpIHtcbiAgICBlPy5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBjb25zdCBjdXJyZW50SW5kZXhJdGVtSG92ZXIgPSB0aGlzLml0ZW1PZkluZGV4SG92ZXI7XG5cbiAgICBjbGVhclRpbWVvdXQodGhpcy50aW1lb3V0TGVhdmVJdGVtKCkpO1xuICAgIHRoaXMudGltZW91dExlYXZlSXRlbS5zZXQoc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBpZiAodGhpcy5pdGVtT2ZJbmRleEhvdmVyICYmIHRoaXMuaXRlbU9mSW5kZXhIb3ZlciAhPT0gY3VycmVudEluZGV4SXRlbUhvdmVyKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRoaXMucmVzZXRJbmRleEhvdmVyKGUpO1xuICAgIH0pKTtcbiAgfVxuXG4gIHByb3RlY3RlZCByZXNldEluZGV4SG92ZXIoZT86IEV2ZW50KSB7XG4gICAgZT8uc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgaWYgKHRoaXMuaGFzQWN0aW9uQnV0dG9uRHJvcGRvd25Db250ZW50KCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5pdGVtT2ZJbmRleEhvdmVyID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJvdGVjdGVkIGhhbmRsZXJNb3VzZUVudGVyKGV2ZW50OiBFdmVudCkge1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIHRoaXMucmVzZXRJbmRleEhvdmVyKGV2ZW50KTtcbiAgICBpZiAodGhpcy5jbGFzc0Zvb3RlckluY2x1ZGUoKSkge1xuICAgICAgdGhpcy5mb290ZXJFbGVtZW50UmVmKCk/Lm5hdGl2ZUVsZW1lbnQ/LmNsYXNzTGlzdC5yZW1vdmUoJ2JnLVsjZjhmOWZhXScpO1xuICAgICAgdGhpcy5mb290ZXJMZWZ0RWxlbWVudFJlZigpPy5uYXRpdmVFbGVtZW50Py5jbGFzc0xpc3QucmVtb3ZlKCdiZy1bI2Y4ZjlmYV0nKTtcbiAgICAgIHRoaXMuZm9vdGVyRWxlbWVudFJlZigpPy5uYXRpdmVFbGVtZW50Py5jbGFzc0xpc3QuYWRkKHRoaXMuY2xhc3NGb290ZXJJbmNsdWRlKCkpO1xuICAgICAgdGhpcy5mb290ZXJMZWZ0RWxlbWVudFJlZigpPy5uYXRpdmVFbGVtZW50Py5jbGFzc0xpc3QuYWRkKHRoaXMuY2xhc3NGb290ZXJJbmNsdWRlKCkpO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBoYW5kbGVyTW91c2VMZWF2ZShldmVudDogRXZlbnQpIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICBpZiAodGhpcy5jbGFzc0Zvb3RlckluY2x1ZGUoKSkge1xuICAgICAgdGhpcy5mb290ZXJFbGVtZW50UmVmKCk/Lm5hdGl2ZUVsZW1lbnQ/LmNsYXNzTGlzdC5yZW1vdmUodGhpcy5jbGFzc0Zvb3RlckluY2x1ZGUoKSk7XG4gICAgICB0aGlzLmZvb3RlckxlZnRFbGVtZW50UmVmKCk/Lm5hdGl2ZUVsZW1lbnQ/LmNsYXNzTGlzdC5yZW1vdmUodGhpcy5jbGFzc0Zvb3RlckluY2x1ZGUoKSk7XG4gICAgICB0aGlzLmZvb3RlckVsZW1lbnRSZWYoKT8ubmF0aXZlRWxlbWVudD8uY2xhc3NMaXN0LmFkZCgnYmctWyNmOGY5ZmFdJyk7XG4gICAgICB0aGlzLmZvb3RlckxlZnRFbGVtZW50UmVmKCk/Lm5hdGl2ZUVsZW1lbnQ/LmNsYXNzTGlzdC5hZGQoJ2JnLVsjZjhmOWZhXScpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVzZXRTY3JvbGwoKSB7XG4gICAgaWYgKHRoaXMuaGVhZGVyRWxlbWVudFJlZigpKSB7XG4gICAgICAodGhpcy5oZWFkZXJFbGVtZW50UmVmKCkgYXMgYW55KS5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSAwO1xuICAgIH1cbiAgICBpZiAodGhpcy5Cb2R5RWxlbWVudCkge1xuICAgICAgdGhpcy5Cb2R5RWxlbWVudC5zY3JvbGxUb3AgPSAwO1xuICAgICAgdGhpcy5Cb2R5RWxlbWVudC5zY3JvbGxMZWZ0ID0gMDtcbiAgICB9XG4gICAgaWYgKHRoaXMuZm9vdGVyRWxlbWVudFJlZigpKSB7XG4gICAgICAodGhpcy5mb290ZXJFbGVtZW50UmVmKCkgYXMgYW55KS5uYXRpdmVFbGVtZW50LnNjcm9sbExlZnQgPSAwO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgcmVzZXQoY2xlYXJTb3J0PzogYm9vbGVhbikge1xuICAgIGlmIChjbGVhclNvcnQpIHtcbiAgICAgIHRoaXMuaW5zdGFuY2VTb3J0KCk/LnJlc2V0KCk7XG4gICAgICB0aGlzLmluc3RhbmNlU29ydC5zZXQodW5kZWZpbmVkKTtcbiAgICB9XG4gICAgdGhpcy5oYXNTY3JvbGwuc2V0KGZhbHNlKTtcbiAgICB0aGlzLmxvYWRpbmcuc2V0KGZhbHNlKTtcbiAgICB0aGlzLm91dExvYWRpbmcuZW1pdCh0aGlzLmxvYWRpbmcoKSk7XG4gICAgdGhpcy5pdGVtcy5zZXQoW10pO1xuICAgIHRoaXMuc3RvcmVzLnNldChbXSk7XG4gICAgdGhpcy5mYWtlUmVzcG9uc2VBcGkoKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2hlY2tTY3JvbGwoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgaGFzU2Nyb2xsID0gdGhpcy5oYXNTY3JvbGwoKTtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHRpbWVyKDUwMCkucGlwZSh0YWtlVW50aWwodGhpcy5vbkRlc3Ryb3kpKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5Cb2R5RWxlbWVudCkge1xuICAgICAgICAgIHRoaXMuaGFzU2Nyb2xsLnNldCh0aGlzLkJvZHlFbGVtZW50LnNjcm9sbEhlaWdodCA+IHRoaXMuQm9keUVsZW1lbnQub2Zmc2V0SGVpZ2h0KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaGFzU2Nyb2xsICYmICF0aGlzLmhhc1Njcm9sbCgpKSB7XG4gICAgICAgICAgdGhpcy5vdXRTY3JvbGxJc0dvbmUuZW1pdCh7fSk7XG4gICAgICAgICAgaWYgKCF0aGlzLmZpbHRlck9yU29ydExvY2FsKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY2FsbEFwaUJ5U2VydmljZSh0cnVlKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0IEJvZHlFbGVtZW50KCk6IEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5ib2R5RWxlbWVudFJlZigpPy5uYXRpdmVFbGVtZW50O1xuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5vbkRlc3Ryb3kubmV4dCgpO1xuICAgIHRoaXMub25EZXN0cm95LmNvbXBsZXRlKCk7XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMudGltZW91dExlYXZlSXRlbSgpKTtcbiAgfVxuXG59XG4iLCI8ZGl2IGNsYXNzPSdmbGV4IGZsZXgtY29sIHctZnVsbCBoLWZ1bGwnPlxuICBAaWYgKCFpZ25vcmVCYXIoKSkge1xuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuIHJlbGF0aXZlIHotWzFdIGJvdHRvbS0wIGxlZnQtMCB3LWZ1bGwgYmctd2hpdGUgbWItWzE2cHhdIGxpYnMtdWktdGFibGUtc2hhZG93LWJvdHRvbVwiXG4gICAgICBbY2xhc3MucHgtWzE2cHhdXT1cImtleXNTZWxlY3RlZCgpLmxlbmd0aCB8fCBsYWJlbEJhck5vU2VsZWN0SXRlbSgpXCJcbiAgICAgIFtjbGFzcy5weS1bNnB4XV09XCJrZXlzU2VsZWN0ZWQoKS5sZW5ndGggfHwgbGFiZWxCYXJOb1NlbGVjdEl0ZW0oKVwiXG4gICAgICAobW91c2VlbnRlcik9XCJyZXNldEluZGV4SG92ZXIoJGV2ZW50KVwiPlxuICAgICAgQGlmICgha2V5c1NlbGVjdGVkKCkubGVuZ3RoICYmIGxhYmVsQmFyTm9TZWxlY3RJdGVtKCkpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cInt7IGNsYXNzTGFiZWxCYXJOb1NlbGVjdEl0ZW0oKSA/PyAncHgtWzEycHhdIHB5LVs1cHhdJyB9fVwiXG4gICAgICAgICAgW2lubmVySHRtbF09J2xhYmVsQmFyTm9TZWxlY3RJdGVtKCkgfCB0cmFuc2xhdGU6e3ZhbHVlOnRvdGFsSXRlbURpc3BsYXkoKX0nPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICAgIEBpZiAoa2V5c1NlbGVjdGVkKCkubGVuZ3RoKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBwbC1bMTJweF1cIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgaC1mdWxsIG10LVstMnB4XVwiPlxuICAgICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1jaGVja2JveC1zaW5nbGUgW2NoZWNrZWRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIFtkaXNhYmxlXT1cImxvYWRpbmcoKSB8fCBkaXNhYmxlQ2hlY2tib3goKVwiXG4gICAgICAgICAgICAgIChvdXRDaGFuZ2UpPVwiaGFuZGxlckNoYW5nZUFsbENoZWNrZWQoKVwiIC8+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cImxpYnMtdWktZm9udC1oNW0gdGV4dC1bIzA3MTYzMV0gbXItWzhweF0ge3sgY2xhc3NMYWJlbEJhckJ1dHRvbnMoKSB9fVwiPlxuICAgICAgICAgICAge3sgbGFiZWxCYXJCdXR0b25zKCkgfCB0cmFuc2xhdGU6eyB2YWx1ZTprZXlzU2VsZWN0ZWQoKS5sZW5ndGggfSB9fVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIEBpZiAoY29uZmlnU2VsZWN0TW9yZUl0ZW0oKSkge1xuICAgICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1kcm9wZG93biBbaXNOZ0NvbnRlbnRdPVwidHJ1ZVwiXG4gICAgICAgICAgICAgIFtwb3BvdmVyQ3VzdG9tQ29uZmlnXT1cIntcbiAgICAgICAgICAgICAgICB3aWR0aEJ5UGFyZW50OmZhbHNlLFxuICAgICAgICAgICAgICAgIGlnbm9yZUFycm93OiB0cnVlLFxuICAgICAgICAgICAgICAgIG1heEhlaWdodDogIDIwNDgsXG4gICAgICAgICAgICAgICAgY2xhc3NJbmNsdWRlOid3LVsxMjFweF0nLFxuICAgICAgICAgICAgICAgIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgICBtb2RlOidzdGFydCcsXG4gICAgICAgICAgICAgICAgICBkaXN0YW5jZTowXG4gICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAgIFtsaXN0Q29uZmlnXT1cIih7XG4gICAgICAgICAgICAgICAgICB0eXBlOid0ZXh0JyxcbiAgICAgICAgICAgICAgICAgIGNvbmZpZ1RlbXBsYXRlVGV4dDp7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkS2V5OidrZXknLFxuICAgICAgICAgICAgICAgICAgICBpZ25vcmVJY29uU2VsZWN0ZWQ6dHJ1ZSxcbiAgICAgICAgICAgICAgICAgICAgZ2V0VmFsdWU6Y29uZmlnU2VsZWN0TW9yZUl0ZW0oKT8uZ2V0VmFsdWVcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IHwgTGlic1VpUGlwZXNDb252ZXJ0T2JqZWN0VG9TaWduYWxQaXBlOnRydWUpKClcIlxuICAgICAgICAgICAgICBbbGlzdE1heEl0ZW1TaG93XT1cIjVcIlxuICAgICAgICAgICAgICBjbGFzcz1cInctWzE2cHhdIGgtWzE2cHhdIG1yLVs4cHhdXCJcbiAgICAgICAgICAgICAgKG91dFNlbGVjdEtleSk9XCJoYW5kbGVyU2VsZWN0ZWRNb3JlSXRlbSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKG91dEZ1bmN0aW9uc0NvbnRyb2wpPVwiaGFuZGxlckZ1bmN0aW9uQ29udHJvbE1vcmVTZWxlY3RJdGVtKCRldmVudClcIj5cbiAgICAgICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1idXR0b25zLWJ1dHRvbiBbdHlwZV09XCInYnV0dG9uLWxpbmstcHJpbWFyeSdcIlxuICAgICAgICAgICAgICAgIFtjbGFzc0luY2x1ZGVdPVwiJ3AtMCBtLTAnXCJcbiAgICAgICAgICAgICAgICBbY2xhc3NJY29uTGVmdF09XCInYmVmb3JlOiF0ZXh0LVsxNnB4XSBsaWJzLXVpLWNvbi1kcm9wZG93biBtci1bNnB4XSdcIlxuICAgICAgICAgICAgICAgIFtwb3BvdmVyXT1cIntjb25maWc6e2NvbnRlbnQ6J2kxOG5fbW9yZV9zZWxlY3QnfX1cIlxuICAgICAgICAgICAgICAgIFtpZ25vcmVTdG9wUHJvcGFnYXRpb25FdmVudF09XCJ0cnVlXCIgLz5cbiAgICAgICAgICAgIDwvbGlic191aS1jb21wb25lbnRzLWRyb3Bkb3duPlxuICAgICAgICAgIH1cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiaC1bMTZweF0gbGlicy11aS1ib3JkZXItbGVmdC1nZW5lcmFsIG1sLVsxNnB4XVwiPjwvZGl2PlxuICAgICAgICAgIEBpZiAoYmFyQnV0dG9ucygpPy5sZW5ndGgpIHtcbiAgICAgICAgICAgIEBmb3IgKGJ1dHRvbiBvZiBiYXJCdXR0b25zKCk7dHJhY2sgYnV0dG9uKSB7XG4gICAgICAgICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtYnV0dG9ucy1idXR0b24gW3R5cGVdPVwiYnV0dG9uLnR5cGUgfHwgJ2J1dHRvbi1saW5rLXByaW1hcnknXCJcbiAgICAgICAgICAgICAgICBbY2xhc3NJY29uTGVmdF09XCJidXR0b24uY2xhc3NJY29uTGVmdCB8fCAnJ1wiXG4gICAgICAgICAgICAgICAgW2NsYXNzSW5jbHVkZV09XCJidXR0b24uY2xhc3NJbmNsdWRlIHx8ICcnXCJcbiAgICAgICAgICAgICAgICBbbGFiZWxdPVwiKGJ1dHRvbi5sYWJlbCB8fCAnICcpIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAob3V0Q2xpY2spPVwiaGFuZGxlckJhckJ1dHRvbkNsaWNrKGJ1dHRvbilcIiAvPlxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgICA8bmctY29udGVudCBzZWxlY3Q9J2Rpdi5saWJzLXVpLXRhYmxlLWJhci1yaWdodCc+PC9uZy1jb250ZW50PlxuICAgIDwvZGl2PlxuICB9XG5cbiAgPGRpdiAjdGFibGVDb250YWluZXJFbGVtZW50UmVmXG4gICAgY2xhc3M9XCJsaWJzLXVpLXRhYmxlIGZsZXggZmxleC1jb2wgdy1mdWxsIGgtZnVsbCByZWxhdGl2ZVwiXG4gICAgW2NsYXNzLnB4LVsxNnB4XV09JyFpZ25vcmVCYXIoKSdcbiAgICAobW91c2VsZWF2ZSk9XCJyZXNldEluZGV4SG92ZXIoJGV2ZW50KVwiPlxuICAgIDxkaXYgI2hlYWRlckVsZW1lbnRSZWZcbiAgICAgIFtjbGFzcy5saWJzLXVpLWJvcmRlci1ib3R0b20tZGFzaGVkLWdlbmVyYWxdPVwiIWhhc0l0ZW1IaWdodExpZ2h0KCkgJiYgaXNEYXNoQm9yZGVyKClcIlxuICAgICAgW2NsYXNzLmxpYnMtdWktYm9yZGVyLWJvdHRvbS1nZW5lcmFsXT1cIiFoYXNJdGVtSGlnaHRMaWdodCgpICYmICFpc0Rhc2hCb3JkZXIoKVwiXG4gICAgICBbY2xhc3MuIWhpZGRlbl09XCIhaXRlbXMoKS5sZW5ndGggJiYgaXNIaWRkZW5IZWFkZXJXaGVuTm9kYXRhKClcIlxuICAgICAgW2NsYXNzXT1cImNsYXNzSGVhZGVyQ29udGFpbmVyKClcIlxuICAgICAgKG1vdXNlZW50ZXIpPVwicmVzZXRJbmRleEhvdmVyKCRldmVudClcIj5cbiAgICAgIEBpZiAoaGVhZGVyTGVmdCgpLmxlbmd0aCkge1xuICAgICAgICA8ZGl2IGNsYXNzPVwiaC1mdWxsIGZsZXggc3RpY2t5IHRvcC0wIGxlZnQtMCBiZy1bI2ZmZmZmZl0gei1bMV1cIj5cbiAgICAgICAgICBAZm9yIChoZWFkZXIgb2YgaGVhZGVyTGVmdCgpO3RyYWNrIGhlYWRlcikge1xuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRlbXBsYXRlSGVhZGVyUmVmO2NvbnRleHQ6e2hlYWRlckl0ZW06aGVhZGVyLGlzSGVkZXJMZWZ0OnRydWV9XCIgLz5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuICAgICAgQGlmIChoZWFkZXJSaWdodCgpLmxlbmd0aCkge1xuICAgICAgICBAZm9yIChoZWFkZXIgb2YgaGVhZGVyUmlnaHQoKTt0cmFjayBoZWFkZXIpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGVtcGxhdGVIZWFkZXJSZWY7Y29udGV4dDp7aGVhZGVySXRlbTpoZWFkZXIsaXNIZWRlckxlZnQ6ZmFsc2V9XCIgLz5cbiAgICAgICAgfVxuICAgICAgfVxuICAgIDwvZGl2PlxuICAgIEBpZiAoc2hvd0Zvb3RlcigpICYmIGl0ZW1Gb290ZXIoKSAmJiBjdXN0b21Qb3NpdGlvbkZvb3RlcigpID09PSAndG9wJykge1xuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD0ndGVtcGxhdGVGb290ZXJSZWYnIC8+XG4gICAgfVxuICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZSBmbGV4IGZsZXgtY29sIHctZnVsbCBoLWZ1bGwgb3ZlcmZsb3cteC1oaWRkZW4gYmctd2hpdGUge3sgY2xhc3NCb2R5SW5jbHVkZSgpIHx8ICcnIH19XCI+XG4gICAgICBAaWYgKGl0ZW1zKCkubGVuZ3RoKSB7XG4gICAgICAgIDxkaXYgI2JvZHlFbGVtZW50UmVmXG4gICAgICAgICAgY2xhc3M9XCJmbGV4IGgtZnVsbCB3LWZ1bGwgcmVsYXRpdmVcIlxuICAgICAgICAgIExpYnNVaUNvbXBvbmVudHNTY3JvbGxPdmVybGF5RGlyZWN0aXZlXG4gICAgICAgICAgW29wdGlvbnNdPVwie3Njcm9sbFg6ICghaGVhZGVyTGVmdCgpLmxlbmd0aCB8fCAhaGVhZGVyUmlnaHQoKSkgPyAnaGlkZGVuJzonc2Nyb2xsJ31cIlxuICAgICAgICAgIChvdXRTY3JvbGwpPVwiaGFuZGxlclNjcm9sbCgkZXZlbnQpXCJcbiAgICAgICAgICAob3V0U2Nyb2xsQm90dG9tKT1cImhhbmRsZXJTY3JvbGxCb3R0b20oJGV2ZW50KVwiPlxuICAgICAgICAgIDx2aXJ0dWFsLXNjcm9sbGVyICNib2R5Q29tcG9uZW50UmVmXG4gICAgICAgICAgICBbaXRlbXNdPVwiaXRlbXMoKVwiXG4gICAgICAgICAgICBbZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXNdPVwiZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMoKVwiXG4gICAgICAgICAgICBjbGFzcz1cImgtZnVsbFwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwiaGVhZGVyRWxlbWVudFJlZi5zY3JvbGxXaWR0aCA+IChib2R5RWxlbWVudFJlZiA/IGJvZHlFbGVtZW50UmVmLnNjcm9sbFdpZHRoIDogMCkgPyBoZWFkZXJFbGVtZW50UmVmLnNjcm9sbFdpZHRoOiB1bmRlZmluZWRcIlxuICAgICAgICAgICAgW3BhcmVudFNjcm9sbF09XCJib2R5RWxlbWVudFJlZlwiXG4gICAgICAgICAgICBbYnVmZmVyQW1vdW50XT1cImJ1ZmZlckFtb3VudCgpXCI+XG4gICAgICAgICAgICBAZm9yIChkYXRhIG9mIGJvZHlDb21wb25lbnRSZWYudmlld1BvcnRJdGVtczt0cmFjayBkYXRhKCkpIHtcbiAgICAgICAgICAgICAgPGRpdiAjZWxlbWVudEhvdmVyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4XCJcbiAgICAgICAgICAgICAgICBbY2xhc3MuYmctWyNmM2ZjZmNdXT1cImRhdGEoKS5zcGVjaWZpY0hpZ2h0TGlnaHRcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5saWJzLXVpLWJvcmRlci10b3AtMXB4LTM2ZDNkM109XCJkYXRhKCkuc3BlY2lmaWNIaWdodExpZ2h0ICYmICRmaXJzdCAmJiAhaWdub3JlQm9yZGVySXRlbSgpXCJcbiAgICAgICAgICAgICAgICBbY2xhc3MubGlicy11aS1ib3JkZXItYm90dG9tLTFweC0zNmQzZDNdPVwiZGF0YSgpLnNwZWNpZmljSGlnaHRMaWdodCAmJiAhaWdub3JlQm9yZGVySXRlbSgpXCJcbiAgICAgICAgICAgICAgICBbbmdDbGFzc109XCIoZGF0YSgpLnNwZWNpZmljSGlnaHRMaWdodCB8fCAoJGxhc3QgJiYgaWdub3JlQm9yZGVySXRlbUxhc3QoKSkpID8gJ2xpYnMtdWktYm9yZGVyLXJhZGl1cy1ib3R0b20tbGVmdC00cHggbGlicy11aS1ib3JkZXItcmFkaXVzLWJvdHRvbS1yaWdodC00cHgnIDogaWdub3JlQm9yZGVySXRlbSgpID8gJycgOiBpc0Rhc2hCb3JkZXIoKSA/ICdsaWJzLXVpLWJvcmRlci1ib3R0b20tZGFzaGVkLWdlbmVyYWwnIDogJ2xpYnMtdWktYm9yZGVyLWJvdHRvbS1nZW5lcmFsJ1wiXG4gICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoLnB4XT1cImhlYWRlckVsZW1lbnRSZWYuc2Nyb2xsV2lkdGhcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5iZy1bI2Y4ZjlmYV1dPVwiaXRlbU9mSW5kZXhIb3ZlciA9PT0gZGF0YSAmJiAhZGF0YSgpLnNwZWNpZmljSGlnaHRMaWdodFwiXG4gICAgICAgICAgICAgICAgKG1vdXNlZW50ZXIpPVwic2V0SW5kZXhIb3ZlcigkZXZlbnQsZGF0YSlcIlxuICAgICAgICAgICAgICAgIChtb3VzZWxlYXZlKT1cInJlc2V0SW5kZXhIb3ZlcldoZW5Nb3VzZUxlYXZlKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICBAaWYgKGhlYWRlckxlZnQoKS5sZW5ndGggfHwgaGVhZGVyUmlnaHQoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIHctZnVsbFwiPlxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCB3LWZ1bGxcIj5cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKGhlYWRlckxlZnQoKS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IHN0aWNreSB0b3AtMCBsZWZ0LTAgei1bMV1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuYmctd2hpdGVdPVwiIWRhdGEoKS5zcGVjaWZpY0hpZ2h0TGlnaHRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3MuYmctWyNmM2ZjZmNdXT1cImRhdGEoKS5zcGVjaWZpY0hpZ2h0TGlnaHRcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgQGZvciAoaGVhZGVyIG9mIGhlYWRlckxlZnQoKTt0cmFjayBoZWFkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInJlbGF0aXZlIGZsZXggcHgtWzEycHhdIHB5LVs4cHhdIHt7IGhlYWRlci5pZ25vcmVCb3JkZXJSaWdodCA/ICcnOiAnbGlicy11aS1ib3JkZXItcmlnaHQtZ2VuZXJhbCcgfX1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLmJnLVsjZjhmOWZhXV09XCJpdGVtT2ZJbmRleEhvdmVyID09PSBkYXRhICYmICFkYXRhKCkuc3BlY2lmaWNIaWdodExpZ2h0XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cImhlYWRlci5uZ1N0eWxlIHx8IHt9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtuZ0NsYXNzXT1cImhlYWRlci5uZ0NsYXNzIHx8IHt9XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGVtcGxhdGVCb2R5UmVmO2NvbnRleHQ6e2hlYWRlcjpoZWFkZXIsZGF0YTpkYXRhfVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKGhlYWRlclJpZ2h0KCkubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBAZm9yIChoZWFkZXIgb2YgaGVhZGVyUmlnaHQoKTt0cmFjayBoZWFkZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInJlbGF0aXZlIGZsZXggcHgtWzEycHhdIHB5LVs4cHhdXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJoZWFkZXIubmdTdHlsZSB8fCB7fVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwiaGVhZGVyLm5nQ2xhc3MgfHwge31cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGVtcGxhdGVCb2R5UmVmO2NvbnRleHQ6e2hlYWRlcjpoZWFkZXIsZGF0YTpkYXRhfVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoY29uZmlnVGVtcGxhdGVJdGVtQ29sbGFwc2VFeHBhbmQoKSAmJiBkYXRhKCkuc3BlY2lmaWNFeHBhbmQgJiYgZGF0YSgpW2NvbmZpZ1RlbXBsYXRlSXRlbUNvbGxhcHNlRXhwYW5kKCk/LmZpZWxkR2V0RGF0YUV4cGFuZCB8fCAnc3BlY2lmaWNEYXRhRXhwYW5kJ10pIHtcbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IFtjbGFzc109XCJjb25maWdUZW1wbGF0ZUl0ZW1Db2xsYXBzZUV4cGFuZCgpPy5jc3NXcmFwcGVyIHx8ICdmbGV4IHctZnVsbCdcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKGRhdGFFeHBhbmQgb2YgZGF0YSgpW2NvbmZpZ1RlbXBsYXRlSXRlbUNvbGxhcHNlRXhwYW5kKCk/LmZpZWxkR2V0RGF0YUV4cGFuZCB8fCAnc3BlY2lmaWNEYXRhRXhwYW5kJ10oKTt0cmFjayAkaW5kZXgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChjb25maWdUZW1wbGF0ZUl0ZW1Db2xsYXBzZUV4cGFuZCgpPy5jb2xUZW1wbGF0ZUNvbmZpZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtdGFibGUtdGVtcGxhdGVzIFtpdGVtXT1cImRhdGFFeHBhbmRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3RlbXBsYXRlQ3NzV3JhcHBlcl09XCJjb25maWdUZW1wbGF0ZUl0ZW1Db2xsYXBzZUV4cGFuZCgpPy50ZW1wbGF0ZUNzc1dyYXBwZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NvbmZpZ3NdPVwiY29uZmlnVGVtcGxhdGVJdGVtQ29sbGFwc2VFeHBhbmQoKT8uY29sVGVtcGxhdGVDb25maWdcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IEBlbXB0eSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZSBoLVsxMDBweF1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGVtcGxhdGVOb2RhdGFSZWZcIiAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3ZpcnR1YWwtc2Nyb2xsZXI+XG5cbiAgICAgICAgICBAaWYgKCghaXRlbXMoKS5sZW5ndGgpICYmICFsb2FkaW5nKCkgJiYgbm9EYXRhQ29uZmlnKCkpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoLWZ1bGxcIlxuICAgICAgICAgICAgICBbc3R5bGUuZmxleF09XCInMCAwICcraGVhZGVyRWxlbWVudFJlZi5zY3JvbGxXaWR0aCsncHgnXCI+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvZGl2PlxuICAgICAgfVxuICAgICAgQGlmICgoIWl0ZW1zKCkubGVuZ3RoKSAmJiAhbG9hZGluZygpKSB7XG4gICAgICAgIDxkaXYgY2xhc3M9XCJyZWxhdGl2ZSBoLWZ1bGwgdy1mdWxsXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRlbXBsYXRlTm9kYXRhUmVmXCIgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG5cbiAgICAgIEBpZiAoc2hvd0Zvb3RlcigpICYmIGl0ZW1Gb290ZXIoKSAmJiBjdXN0b21Qb3NpdGlvbkZvb3RlcigpID09PSAnYm90dG9tJykge1xuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PSd0ZW1wbGF0ZUZvb3RlclJlZicgLz5cbiAgICAgIH1cblxuICAgICAgQGlmIChsb2FkaW5nKCkpIHtcbiAgICAgICAgPGRpdiBjbGFzcz1cImFic29sdXRlIHctZnVsbCBoLWZ1bGwgei1bMl0gZmxleCBpdGVtcy1jZW50ZXIgY29udGVudC1jZW50ZXJcIj5cbiAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLXNwaW5uZXIgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9kaXY+XG5cbjxuZy10ZW1wbGF0ZSAjdGVtcGxhdGVIZWFkZXJSZWZcbiAgbGV0LWhlYWRlcj0naGVhZGVySXRlbSdcbiAgbGV0LWlzSGVkZXJMZWZ0PSdpc0hlZGVyTGVmdCc+XG4gIDxkaXZcbiAgICBbY2xhc3NdPVwiJ3JlbGF0aXZlIGZsZXggJysgKGhlYWRlci5wYWRkaW5nTGVmdFJpZ2h0SGVhZGVyQ29udGFpbmVyID8/ICcgcHgtWzEycHhdICcpICsgKGlzSGVkZXJMZWZ0ICYmICFoZWFkZXIuaWdub3JlQm9yZGVyUmlnaHQgPyAnIGxpYnMtdWktYm9yZGVyLXJpZ2h0LWdlbmVyYWwgJyA6ICcgJykrICcgbGlicy11aS10YWJsZS1oZWFkZXItY29sICdcIlxuICAgIFtjbGFzcy5mbGV4LWNvbF09XCJoZWFkZXIucm93c0NvbmZpZ1wiXG4gICAgW2NsYXNzLnB5LVs4cHhdXT0nIWhlYWRlci5pZ25vcmVQeURlZmF1bHQnXG4gICAgW25nU3R5bGVdPVwiaGVhZGVyLm5nU3R5bGUgfHwge31cIlxuICAgIFtuZ0NsYXNzXT1cImhlYWRlci5uZ0NsYXNzIHx8IHt9XCI+XG4gICAgQGlmICghaGVhZGVyLnJvd3NDb25maWcpIHtcbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0ZW1wbGF0ZUhlYWRlckNvbnRlbnRSZWY7Y29udGV4dDp7aGVhZGVySXRlbTpoZWFkZXIsaXNDb2xSZW5kZXI6ZmFsc2V9XCIgLz5cbiAgICB9XG4gICAgQGlmIChoZWFkZXIucm93c0NvbmZpZzthcyByb3dzQ29uZmlnKSB7XG4gICAgICBAZm9yIChyb3cgb2Ygcm93c0NvbmZpZy5yb3dzO3RyYWNrIHJvdykge1xuICAgICAgICA8ZGl2IFtjbGFzc109XCJyb3cuY2xhc3NSb3dcIj5cbiAgICAgICAgICBAZm9yIChjb2wgb2Ygcm93LmNvbHMgOyB0cmFjayBjb2wpIHtcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJ0ZW1wbGF0ZUhlYWRlckNvbnRlbnRSZWY7Y29udGV4dDp7aGVhZGVySXRlbTpjb2wsaXNDb2xSZW5kZXI6dHJ1ZX1cIiAvPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICB9XG4gICAgfVxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjdGVtcGxhdGVIZWFkZXJDb250ZW50UmVmXG4gIGxldC1oZWFkZXI9J2hlYWRlckl0ZW0nXG4gIGxldC1pc0NvbFJlbmRlcj0naXNDb2xSZW5kZXInPlxuICA8ZGl2IGNsYXNzPVwiZmxleCBsaWJzLXVpLWZvbnQtaDZtIG1pbi1oLVsxOHB4XSB0ZXh0LVsjNmE3MzgzXSBtYXgtdy1mdWxsXCJcbiAgICBbY2xhc3MuaXRlbXMtY2VudGVyXT0naGVhZGVyLmNvbnRlbnRIZWFkZXJBbGlnbkNlbnRlciA/PyB0cnVlJ1xuICAgIFtjbGFzcy5qdXN0aWZ5LWVuZF09J2hlYWRlci5jb250ZW50SGVhZGVySnVzdGlmeUNvbnRlbnRFbmQnXG4gICAgW25nU3R5bGVdPVwiaXNDb2xSZW5kZXIgPyAoaGVhZGVyLm5nU3R5bGUgfHwge30pIDoge31cIlxuICAgIFtuZ0NsYXNzXT1cImlzQ29sUmVuZGVyID8gKGhlYWRlci5uZ0NsYXNzIHx8IHt9KSA6IHt9XCI+XG4gICAgQGlmIChoZWFkZXIuaGFzQ2hlY2tib3ggJiYgIWhlYWRlci5oYXNDaGVja2JveEFsbCkge1xuICAgICAgPGRpdiBjbGFzcz1cImZsZXggaC1mdWxsIG1sLVsyNHB4XSB7eyBoZWFkZXIuY2hlY2tib3hDbGFzc0luY2x1ZGUgfX1cIj5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICBAaWYgKGhlYWRlci5oYXNDaGVja2JveEFsbCkge1xuICAgICAgPGRpdiBjbGFzcz1cImZsZXggaC1mdWxsIHt7IGhlYWRlci5jaGVja2JveEFsbENsYXNzSW5jbHVkZSB8fCAnbXItWzE2cHhdJyB9fVwiXG4gICAgICAgIFtjbGFzcy5pdGVtcy1jZW50ZXJdPVwiaGVhZGVyLmNoZWNrYm94QWxpZ25DZW50ZXJcIj5cbiAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1jaGVja2JveC1zaW5nbGUgW2tleV09XCInYWxsJ1wiXG4gICAgICAgICAgW3N0aWxsT3RoZXJPcHRpb25zXT1cIiEha2V5c1NlbGVjdGVkKCkubGVuZ3RoICYmIGtleXNTZWxlY3RlZCgpLmxlbmd0aCAhPT0gaXRlbXMoKS5sZW5ndGhcIlxuICAgICAgICAgIFtjaGVja2VkXT1cIiEha2V5c1NlbGVjdGVkKCkubGVuZ3RoICYmIGtleXNTZWxlY3RlZCgpLmxlbmd0aCA9PT0gaXRlbXMoKS5sZW5ndGhcIlxuICAgICAgICAgIFtkaXNhYmxlXT1cImxvYWRpbmcoKVwiXG4gICAgICAgICAgW2NsYXNzSW5jbHVkZV09XCJoZWFkZXIuY2hlY2tib3hDbGFzc0luY2x1ZGVcIlxuICAgICAgICAgIChvdXRDaGFuZ2UpPVwiaGFuZGxlckNoYW5nZUNoZWNrZWRBbGxJdGVtcygkZXZlbnQpXCIgLz5cbiAgICAgIDwvZGl2PlxuICAgIH1cbiAgICBAaWYgKChoZWFkZXIubGFiZWwgfCBMaWJzVWlQaXBlc0NhbGxGdW5jdGlvbkluVGVtcGxhdGVQaXBlOmhlYWRlci5wYXJzZVZhbHVlOmhlYWRlcil8IGFzeW5jIHwgdHJhbnNsYXRlOyBhcyBsYWJlbEhlYWRlckNvbHVtbikge1xuICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1wb3BvdmVyIFt0eXBlXT1cImhlYWRlcj8ubGFiZWxDb25maWc/LnR5cGUgfHwgJ3RleHQnXCJcbiAgICAgICAgW21vZGVdPVwiaGVhZGVyPy5sYWJlbENvbmZpZz8ubW9kZSB8fCAnaG92ZXInXCJcbiAgICAgICAgW2NsYXNzSW5jbHVkZV09XCIoaGVhZGVyPy5sYWJlbENvbmZpZz8uY2xhc3NJbmNsdWRlIHx8ICcnKVwiXG4gICAgICAgIFtpZ25vcmVTaG93UG9wb3Zlcl09XCJoZWFkZXI/LmxhYmVsQ29uZmlnPy5pZ25vcmVTaG93VG9vbHRpcCB8fCBmYWxzZVwiXG4gICAgICAgIFtjb25maWddPVwiaGVhZGVyLmxhYmVsQ29uZmlnPy5jb25maWcgfHwge2NvbnRlbnQ6bGFiZWxIZWFkZXJDb2x1bW59XCJcbiAgICAgICAgW2lubmVySFRNTF09XCJsYWJlbEhlYWRlckNvbHVtblwiIC8+XG4gICAgfVxuXG4gICAgQGlmIChoZWFkZXIudG9vbHRpcE90aGVyOyBhcyB0b29sdGlwKSB7XG4gICAgICA8ZGl2IGNsYXNzPVwibWwtWzRweF1cIj5cbiAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy1wb3BvdmVyIFt0eXBlXT1cInRvb2x0aXA/LnR5cGUgfHwgJ290aGVyJ1wiXG4gICAgICAgICAgW21vZGVdPVwidG9vbHRpcD8ubW9kZSB8fCAnaG92ZXInXCJcbiAgICAgICAgICBbY2xhc3NJbmNsdWRlXT1cInRvb2x0aXAuY2xhc3NJbmNsdWRlIHx8ICd0ZXh0LVsjNmE3MzgzXSdcIlxuICAgICAgICAgIFtpZ25vcmVTaG93UG9wb3Zlcl09XCJ0b29sdGlwLmlnbm9yZVNob3dUb29sdGlwIHx8IGZhbHNlXCJcbiAgICAgICAgICBbY29uZmlnXT1cInRvb2x0aXAuY29uZmlnIHx8IHtjb250ZW50Oih0b29sdGlwLmRhdGFWaWV3IHx8ICcgJykgfCB0cmFuc2xhdGUsIHBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgIG1vZGU6ICdjZW50ZXInLFxuICAgICAgICAgICAgICBkaXN0YW5jZTogMCxcbiAgICAgICAgICAgICAgYXV0b1VwZGF0ZVBvc2l0aW9uOiB7XG4gICAgICAgICAgICAgICAgZW5kRGlzdGFuY2U6IDEyLFxuICAgICAgICAgICAgICAgIHN0YXJ0RGlzdGFuY2U6IC0xMlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9fVwiXG4gICAgICAgICAgW2lubmVySFRNTF09XCJ0b29sdGlwLmRhdGFWaWV3XCIgLz5cbiAgICAgIDwvZGl2PlxuICAgIH1cblxuICAgIEBpZiAoaGVhZGVyLmhhc1NvcnQgJiYgaGVhZGVyLm9yZGVyYnkpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJtbC1bNHB4XVwiPlxuICAgICAgICA8bGlic191aS1jb21wb25lbnRzLWJ1dHRvbnMtc29ydC1hcnJvdyBbZGlzYWJsZV09XCJsb2FkaW5nKCkgfHwgIWl0ZW1zKCkubGVuZ3RoXCJcbiAgICAgICAgICBbZmllbGRTb3J0XT1cImhlYWRlci5vcmRlcmJ5XCJcbiAgICAgICAgICBbaWdub3JlUG9wb3ZlckNvbnRlbnRdPVwiaGVhZGVyLnNvcnRJZ25vcmVUb29sdGlwQ29udGVudCA/PyB0cnVlXCJcbiAgICAgICAgICBbcG9wb3ZlckNvbnRlbnRBc2NdPVwiaGVhZGVyLnNvcnRUb29sdGlwQ29udGVudEFzY1wiXG4gICAgICAgICAgW3BvcG92ZXJDb250ZW50RGVzY109XCJoZWFkZXIuc29ydFRvb2x0aXBDb250ZW50RGVzY1wiXG4gICAgICAgICAgW2RlZmF1bHRNb2RlXT1cImhlYWRlci5kZWZhdWx0TW9kZVwiXG4gICAgICAgICAgW3pJbmRleF09XCJoZWFkZXIuekluZGV4VG9vbHRpcFNvcnRcIlxuICAgICAgICAgIChvdXRDaGFuZ2UpPVwiaGFuZGxlckNoYW5nZVNvcnQoJGV2ZW50KVwiIC8+XG4gICAgICA8L2Rpdj5cbiAgICB9XG4gIDwvZGl2PlxuICBAaWYgKGhlYWRlci5sYWJlbERlc2NyaXB0aW9uKSB7XG4gICAgPGRpdiBjbGFzcz1cImZsZXhcIj5cbiAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtcG9wb3ZlciBbdHlwZV09XCIndGV4dCdcIlxuICAgICAgICBbY2xhc3NJbmNsdWRlXT1cImhlYWRlci5sYWJlbERlc2NyaXB0aW9uLmNsYXNzSW5jbHVkZSB8fCAnJ1wiXG4gICAgICAgIFtjb25maWddPVwie2NvbnRlbnQ6IGhlYWRlci5sYWJlbERlc2NyaXB0aW9uLmNvbnRlbnQgfCB0cmFuc2xhdGV9XCJcbiAgICAgICAgW2lubmVySFRNTF09XCJoZWFkZXIubGFiZWxEZXNjcmlwdGlvbi5jb250ZW50IHwgdHJhbnNsYXRlXCIgLz5cbiAgICA8L2Rpdj5cbiAgfVxuPC9uZy10ZW1wbGF0ZT5cblxuPG5nLXRlbXBsYXRlICN0ZW1wbGF0ZUJvZHlSZWZcbiAgbGV0LWhlYWRlcj0naGVhZGVyJ1xuICBsZXQtZGF0YT0nZGF0YSc+XG4gIDxkaXYgY2xhc3M9XCJmbGV4IHctZnVsbCBoLWZ1bGxcIj5cbiAgICBAaWYgKGhlYWRlci5oYXNDaGVja2JveCkge1xuICAgICAgPGRpdiBjbGFzcz1cImZsZXggaC1mdWxsXCJcbiAgICAgICAgW2NsYXNzLmludmlzaWJsZV09XCJoZWFkZXIuY2hlY2tDb25kaXRpb25DaGVja0JveEhpZGRlbiAmJiggZGF0YSgpIHwgTGlic1VpUGlwZXNDYWxsRnVuY3Rpb25JblRlbXBsYXRlUGlwZTpoZWFkZXIuY2hlY2tDb25kaXRpb25DaGVja0JveEhpZGRlbjpkYXRhKCkgfCBhc3luYylcIlxuICAgICAgICBbY2xhc3MuaXRlbXMtY2VudGVyXT1cImhlYWRlci5jaGVja2JveEFsaWduQ2VudGVyXCI+XG4gICAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtY2hlY2tib3gtc2luZ2xlIFtrZXldPVwiZGF0YSgpW2ZpZWxkS2V5KCldXCJcbiAgICAgICAgICBbY2xhc3NJbmNsdWRlXT1cImhlYWRlci5jaGVja2JveENsYXNzSW5jbHVkZVwiXG4gICAgICAgICAgW2NoZWNrZWRdPVwiZGF0YSgpW2ZpZWxkS2V5KCldIHwgTGlic1VpUGlwZXNDaGVja1NlbGVjdGVkQnlLZXlQaXBlOmtleXNTZWxlY3RlZCgpOmtleXNTZWxlY3RlZCgpLmxlbmd0aFwiXG4gICAgICAgICAgW2Rpc2FibGVdPVwibG9hZGluZygpIHx8IGRpc2FibGVDaGVja2JveCgpIHx8ICEhKG1heEl0ZW1TZWxlY3RlZCgpICYmICEoZGF0YSgpW2ZpZWxkS2V5KCldIHwgTGlic1VpUGlwZXNDaGVja1NlbGVjdGVkQnlLZXlQaXBlOmtleXNTZWxlY3RlZCgpOmtleXNTZWxlY3RlZCgpLmxlbmd0aCkgJiYga2V5c1NlbGVjdGVkKCkubGVuZ3RoID49IG1heEl0ZW1TZWxlY3RlZCgpKVwiXG4gICAgICAgICAgKG91dENoYW5nZSk9XCJoYW5kbGVyQ2hhbmdlSXRlbUNoZWNrZWQoJGV2ZW50LGRhdGEoKSlcIiAvPlxuICAgICAgPC9kaXY+XG4gICAgfVxuXG4gICAgQGlmIChoZWFkZXIuY29sVGVtcGxhdGVDb25maWcpIHtcbiAgICAgIDxsaWJzX3VpLWNvbXBvbmVudHMtdGFibGUtdGVtcGxhdGVzIFtpc0hvdmVyXT1cIml0ZW1PZkluZGV4SG92ZXIgPT09IGRhdGEgJiYgIWRhdGEuc3BlY2lmaWNIaWdodExpZ2h0XCJcbiAgICAgICAgW2NsYXNzXT1cImhlYWRlci50ZW1wbGF0ZUNzc1dyYXBwZXJIb3N0IHx8ICcnXCJcbiAgICAgICAgW2l0ZW1dPVwiZGF0YVwiXG4gICAgICAgIFt0ZW1wbGF0ZUNzc1dyYXBwZXJdPVwiaGVhZGVyLnRlbXBsYXRlQ3NzV3JhcHBlclwiXG4gICAgICAgIFtjb25maWdzXT1cImhlYWRlci5jb2xUZW1wbGF0ZUNvbmZpZ1wiIC8+XG4gICAgfVxuICA8L2Rpdj5cbjwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjdGVtcGxhdGVGb290ZXJSZWY+XG4gIEBpZiAoIWlzSGlkZGVuSGVhZGVyV2hlbk5vZGF0YSgpIHx8IChpc0hpZGRlbkhlYWRlcldoZW5Ob2RhdGEoKSAmJiBpdGVtcygpLmxlbmd0aCkpIHtcbiAgICA8ZGl2ICNmb290ZXJFbGVtZW50UmVmXG4gICAgICBjbGFzcz1cImZsZXggdy1mdWxsIGJnLVsjZjhmOWZhXSBvdmVyZmxvdy14LWhpZGRlbiB6LVsxXSB7eyBpZ25vcmVCb3JkZXJGb290ZXIoKSA/ICcnOiAoY3VzdG9tUG9zaXRpb25Gb290ZXIoKSA9PT0gJ3RvcCcgPyAnbGlicy11aS1ib3JkZXItYm90dG9tLWdlbmVyYWwnOidsaWJzLXVpLXRhYmxlLXNoYWRvdy10b3AgbGlicy11aS1ib3JkZXItdG9wLWdlbmVyYWwnKSB9fSBtaW4taC1bMzVweF1cIlxuICAgICAgKG1vdXNlZW50ZXIpPVwiaGFuZGxlck1vdXNlRW50ZXIoJGV2ZW50KVwiXG4gICAgICAobW91c2VsZWF2ZSk9XCJoYW5kbGVyTW91c2VMZWF2ZSgkZXZlbnQpXCI+XG4gICAgICBAaWYgKGZvb3RlckxlZnQoKSkge1xuICAgICAgICA8ZGl2ICNmb290ZXJMZWZ0RWxlbWVudFJlZlxuICAgICAgICAgIGNsYXNzPVwiZmxleCBzdGlja3kgdG9wLTAgbGVmdC0wIHotWzFdIGJnLVsjZjhmOWZhXVwiPlxuICAgICAgICAgIEBmb3IgKGZvb3RlciBvZiBmb290ZXJMZWZ0KCk7dHJhY2sgZm9vdGVyKSB7XG4gICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgcHgtWzEycHhdIHB5LVs4cHhdIHt7IGZvb3Rlci5pZ25vcmVCb3JkZXJSaWdodCA/ICcnOiAnbGlicy11aS1ib3JkZXItcmlnaHQtZ2VuZXJhbCcgfX1cIlxuICAgICAgICAgICAgICBbbmdTdHlsZV09XCJmb290ZXIubmdTdHlsZSB8fCB7fVwiXG4gICAgICAgICAgICAgIFtuZ0NsYXNzXT1cImZvb3Rlci5uZ0NsYXNzIHx8IHt9XCI+XG4gICAgICAgICAgICAgIEBpZiAoZm9vdGVyLmNvbFRlbXBsYXRlQ29uZmlnKSB7XG4gICAgICAgICAgICAgICAgPGxpYnNfdWktY29tcG9uZW50cy10YWJsZS10ZW1wbGF0ZXMgW2l0ZW1dPVwiaXRlbUZvb3RlclwiXG4gICAgICAgICAgICAgICAgICBbdGVtcGxhdGVDc3NXcmFwcGVyXT1cImZvb3Rlci50ZW1wbGF0ZUNzc1dyYXBwZXJcIlxuICAgICAgICAgICAgICAgICAgW2NvbmZpZ3NdPVwiZm9vdGVyLmNvbFRlbXBsYXRlQ29uZmlnXCIgLz5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICAgIEBpZiAoZm9vdGVyUmlnaHQoKSkge1xuICAgICAgICBAZm9yIChmb290ZXIgb2YgZm9vdGVyUmlnaHQoKTt0cmFjayBmb290ZXIpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgcHgtWzEycHhdIHB5LVs4cHhdXCJcbiAgICAgICAgICAgIFtuZ1N0eWxlXT1cImZvb3Rlci5uZ1N0eWxlIHx8IHt9XCJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cImZvb3Rlci5uZ0NsYXNzIHx8IHt9XCI+XG4gICAgICAgICAgICBAaWYgKGZvb3Rlci5jb2xUZW1wbGF0ZUNvbmZpZykge1xuICAgICAgICAgICAgICA8bGlic191aS1jb21wb25lbnRzLXRhYmxlLXRlbXBsYXRlcyBbaXRlbV09XCJpdGVtRm9vdGVyXCJcbiAgICAgICAgICAgICAgICBbdGVtcGxhdGVDc3NXcmFwcGVyXT1cImZvb3Rlci50ZW1wbGF0ZUNzc1dyYXBwZXJcIlxuICAgICAgICAgICAgICAgIFtjb25maWdzXT1cImZvb3Rlci5jb2xUZW1wbGF0ZUNvbmZpZ1wiIC8+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgIDwvZGl2PlxuICB9XG48L25nLXRlbXBsYXRlPlxuXG48bmctdGVtcGxhdGUgI3RlbXBsYXRlTm9kYXRhUmVmPlxuICBAaWYgKG5vRGF0YUNvbmZpZygpOyBhcyBjb25maWcpIHtcbiAgICA8ZGl2IGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgdy1mdWxsIGgtZnVsbCBhYnNvbHV0ZSBsZWZ0LTAgdG9wLTAgei1bMV1cIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciB3LWZ1bGwgaC1mdWxsIHNocmluay0wXCJcbiAgICAgICAgTGlic1VpQ29tcG9uZW50c1Njcm9sbE92ZXJsYXlEaXJlY3RpdmU+XG4gICAgICAgIEBpZiAoIWtleVNlYXJjaCgpICYmICFvbmx5U2hvd05vUmVzdWx0KCkpIHtcbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0NvbXBvbmVudE91dGxldD1cIiAoJ25vLWRhdGEnIHwgTGlic1VpSWNvbnNHZXRJY29uQ29tcG9uZW50UGlwZSB8IGFzeW5jKTtpbnB1dHM6e3NpemU6NjR9XCIgLz5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlicy11aS10YWJsZS1uby1kYXRhLWNvbmZpZy10ZXh0XCJcbiAgICAgICAgICAgIFtuZ1N0eWxlXT1cImNvbmZpZy5uZ1N0eWxlIHx8IHt9XCJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cImNvbmZpZy5uZ0NsYXNzIHx8IHt9XCJcbiAgICAgICAgICAgIFtpbm5lckh0bWxdPVwiY29uZmlnLnRleHROb0RhdGEgfCB0cmFuc2xhdGVcIj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICBAaWYgKGtleVNlYXJjaCgpIHx8IG9ubHlTaG93Tm9SZXN1bHQoKSkge1xuICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nQ29tcG9uZW50T3V0bGV0PVwiKCduby1yZXN1bHQnIHwgTGlic1VpSWNvbnNHZXRJY29uQ29tcG9uZW50UGlwZSB8IGFzeW5jKTtpbnB1dHM6e3NpemU6NjR9XCIgLz5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlicy11aS10YWJsZS1uby1kYXRhLWNvbmZpZy10ZXh0XCJcbiAgICAgICAgICAgIFtuZ1N0eWxlXT1cImNvbmZpZy5uZ1N0eWxlIHx8IHt9XCJcbiAgICAgICAgICAgIFtuZ0NsYXNzXT1cImNvbmZpZy5uZ0NsYXNzIHx8IHt9XCJcbiAgICAgICAgICAgIFtpbm5lckh0bWxdPVwiY29uZmlnLnRleHRTZWFyY2hOb0RhdGEgfCB0cmFuc2xhdGVcIj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgPC9kaXY+XG4gICAgPC9kaXY+XG4gIH1cbjwvbmctdGVtcGxhdGU+XG4iXX0=