@competer/primeng-table 0.0.0-stage → 14.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -3
- package/esm2020/competer-primeng-table.mjs +5 -0
- package/esm2020/lib/components/column-selector/column-selector.mjs +147 -0
- package/esm2020/lib/components/ecs-primeng-table/ecs-primeng-table.mjs +1411 -0
- package/esm2020/lib/components/ecs-primeng-table/ecs-primeng-table.service.mjs +222 -0
- package/esm2020/lib/components/export-excel/export-excel.mjs +153 -0
- package/esm2020/lib/components/export-excel/export-excel.service.mjs +23 -0
- package/esm2020/lib/components/table-button/table-button.mjs +63 -0
- package/esm2020/lib/components/table-cell/table-cell.mjs +159 -0
- package/esm2020/lib/components/table-predefined-filters/table-predefined-filters.mjs +94 -0
- package/esm2020/lib/components/views-management/views-management.mjs +117 -0
- package/esm2020/lib/enums/cell-display.enum.mjs +7 -0
- package/esm2020/lib/enums/cell-overflow-behaviour.enum.mjs +14 -0
- package/esm2020/lib/enums/data-align-horizontal.enum.mjs +16 -0
- package/esm2020/lib/enums/data-align-vertical.enum.mjs +16 -0
- package/esm2020/lib/enums/data-type.enum.enum.mjs +21 -0
- package/esm2020/lib/enums/device-type.enum.mjs +8 -0
- package/esm2020/lib/enums/frozen-column-align.enum.mjs +17 -0
- package/esm2020/lib/enums/index.mjs +9 -0
- package/esm2020/lib/enums/table-view-save-mode.enum.mjs +19 -0
- package/esm2020/lib/interfaces/columns-metadata.interface.mjs +2 -0
- package/esm2020/lib/interfaces/excel-export-request.interface.mjs +2 -0
- package/esm2020/lib/interfaces/index.mjs +11 -0
- package/esm2020/lib/interfaces/predefined-filter.interface.mjs +2 -0
- package/esm2020/lib/interfaces/table-button.interface.mjs +2 -0
- package/esm2020/lib/interfaces/table-configuration.interface.mjs +2 -0
- package/esm2020/lib/interfaces/table-options.interface.mjs +107 -0
- package/esm2020/lib/interfaces/table-paged-response.interface.mjs +2 -0
- package/esm2020/lib/interfaces/table-query-request.interface.mjs +2 -0
- package/esm2020/lib/interfaces/table-view-data.interface.mjs +2 -0
- package/esm2020/lib/interfaces/table-view.interface.mjs +2 -0
- package/esm2020/lib/pipes/ui-translate.pipe.mjs +21 -0
- package/esm2020/lib/services/http.service.mjs +18 -0
- package/esm2020/lib/services/i18n.service.mjs +61 -0
- package/esm2020/lib/services/index.mjs +5 -0
- package/esm2020/lib/services/notification.service.mjs +17 -0
- package/esm2020/lib/services/table-state.service.mjs +38 -0
- package/esm2020/lib/utils/create-table-options.mjs +37 -0
- package/esm2020/lib/utils/data-align-horizontal-as-text.mjs +23 -0
- package/esm2020/lib/utils/data-align-vertical-as-text.mjs +23 -0
- package/esm2020/lib/utils/data-type-as-text.mjs +25 -0
- package/esm2020/lib/utils/frozen-column-align-as-text.mjs +21 -0
- package/esm2020/lib/utils/highlight-text.mjs +36 -0
- package/esm2020/lib/utils/index.mjs +7 -0
- package/esm2020/lib/utils/tree-table-state.mjs +239 -0
- package/esm2020/public-api.mjs +19 -0
- package/fesm2015/competer-primeng-table.mjs +3119 -0
- package/fesm2015/competer-primeng-table.mjs.map +1 -0
- package/fesm2020/competer-primeng-table.mjs +3049 -0
- package/fesm2020/competer-primeng-table.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/lib/components/column-selector/column-selector.d.ts +55 -0
- package/lib/components/ecs-primeng-table/ecs-primeng-table.d.ts +256 -0
- package/lib/components/ecs-primeng-table/ecs-primeng-table.service.d.ts +52 -0
- package/lib/components/export-excel/export-excel.d.ts +51 -0
- package/lib/components/export-excel/export-excel.service.d.ts +6 -0
- package/lib/components/table-button/table-button.d.ts +16 -0
- package/lib/components/table-cell/table-cell.d.ts +69 -0
- package/lib/components/table-predefined-filters/table-predefined-filters.d.ts +39 -0
- package/lib/components/views-management/views-management.d.ts +34 -0
- package/lib/enums/cell-display.enum.d.ts +5 -0
- package/lib/enums/cell-overflow-behaviour.enum.d.ts +12 -0
- package/lib/enums/data-align-horizontal.enum.d.ts +14 -0
- package/lib/enums/data-align-vertical.enum.d.ts +14 -0
- package/lib/enums/data-type.enum.enum.d.ts +19 -0
- package/lib/enums/device-type.enum.d.ts +6 -0
- package/lib/enums/frozen-column-align.enum.d.ts +15 -0
- package/lib/enums/index.d.ts +8 -0
- package/lib/enums/table-view-save-mode.enum.d.ts +17 -0
- package/lib/interfaces/columns-metadata.interface.d.ts +66 -0
- package/lib/interfaces/excel-export-request.interface.d.ts +20 -0
- package/lib/interfaces/index.d.ts +10 -0
- package/lib/interfaces/predefined-filter.interface.d.ts +101 -0
- package/lib/interfaces/table-button.interface.d.ts +75 -0
- package/lib/interfaces/table-configuration.interface.d.ts +23 -0
- package/lib/interfaces/table-options.interface.d.ts +604 -0
- package/lib/interfaces/table-paged-response.interface.d.ts +16 -0
- package/lib/interfaces/table-query-request.interface.d.ts +28 -0
- package/lib/interfaces/table-view-data.interface.d.ts +28 -0
- package/lib/interfaces/table-view.interface.d.ts +15 -0
- package/lib/pipes/ui-translate.pipe.d.ts +13 -0
- package/lib/services/http.service.d.ts +34 -0
- package/lib/services/i18n.service.d.ts +20 -0
- package/lib/services/index.d.ts +4 -0
- package/lib/services/notification.service.d.ts +23 -0
- package/lib/services/table-state.service.d.ts +31 -0
- package/lib/utils/create-table-options.d.ts +5 -0
- package/lib/utils/data-align-horizontal-as-text.d.ts +11 -0
- package/lib/utils/data-align-vertical-as-text.d.ts +11 -0
- package/lib/utils/data-type-as-text.d.ts +11 -0
- package/lib/utils/frozen-column-align-as-text.d.ts +11 -0
- package/lib/utils/highlight-text.d.ts +17 -0
- package/lib/utils/index.d.ts +6 -0
- package/lib/utils/tree-table-state.d.ts +66 -0
- package/package.json +58 -3
- package/public-api.d.ts +10 -0
|
@@ -0,0 +1,1411 @@
|
|
|
1
|
+
import { ECSPrimengTableI18nService } from '../../services/i18n.service';
|
|
2
|
+
import { ECSTableTranslatePipe } from '../../pipes/ui-translate.pipe';
|
|
3
|
+
import { Component, EventEmitter, HostListener, Input, ChangeDetectorRef, inject, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
4
|
+
import { TranslateModule } from '@ngx-translate/core';
|
|
5
|
+
import { CommonModule } from '@angular/common';
|
|
6
|
+
import { FormsModule } from '@angular/forms';
|
|
7
|
+
// PrimeNG imports
|
|
8
|
+
import { TableModule } from 'primeng/table';
|
|
9
|
+
import { ButtonModule } from 'primeng/button';
|
|
10
|
+
import { TooltipModule } from 'primeng/tooltip';
|
|
11
|
+
import { InputTextModule } from 'primeng/inputtext';
|
|
12
|
+
import { MultiSelectModule } from 'primeng/multiselect';
|
|
13
|
+
import { CheckboxModule } from 'primeng/checkbox';
|
|
14
|
+
import { PaginatorModule } from 'primeng/paginator';
|
|
15
|
+
import { OverlayPanelModule } from 'primeng/overlaypanel';
|
|
16
|
+
import { MenuModule } from 'primeng/menu';
|
|
17
|
+
import { DeviceType, CellOverflowBehaviour, DataAlignHorizontal, DataAlignVertical, DataType, FrozenColumnAlign, TableViewSaveMode } from '../../enums';
|
|
18
|
+
import { DEFAULT_TABLE_OPTIONS } from '../../interfaces';
|
|
19
|
+
import { dataAlignHorizontalAsText, dataAlignVerticalAsText, dataTypeAsText, frozenColumnAlignAsText } from '../../utils';
|
|
20
|
+
import { ECSPrimengTableStateService } from '../../services';
|
|
21
|
+
import { TableCell } from '../table-cell/table-cell';
|
|
22
|
+
import { TablePredefinedFilters } from '../table-predefined-filters/table-predefined-filters';
|
|
23
|
+
import { TableButton } from '../table-button/table-button';
|
|
24
|
+
import { ColumnSelector } from "../column-selector/column-selector";
|
|
25
|
+
import { ExportExcel } from '../export-excel/export-excel';
|
|
26
|
+
import { finalize, firstValueFrom, Observable, Subject, takeUntil } from 'rxjs';
|
|
27
|
+
import { ViewsManagement } from "../views-management/views-management";
|
|
28
|
+
import { TreeTableState } from '../../utils/tree-table-state';
|
|
29
|
+
import * as i0 from "@angular/core";
|
|
30
|
+
import * as i1 from "./ecs-primeng-table.service";
|
|
31
|
+
import * as i2 from "../../services";
|
|
32
|
+
import * as i3 from "@ngx-translate/core";
|
|
33
|
+
import * as i4 from "@angular/common";
|
|
34
|
+
import * as i5 from "@angular/forms";
|
|
35
|
+
import * as i6 from "primeng/table";
|
|
36
|
+
import * as i7 from "primeng/api";
|
|
37
|
+
import * as i8 from "primeng/button";
|
|
38
|
+
import * as i9 from "primeng/tooltip";
|
|
39
|
+
import * as i10 from "primeng/inputtext";
|
|
40
|
+
import * as i11 from "primeng/multiselect";
|
|
41
|
+
import * as i12 from "primeng/checkbox";
|
|
42
|
+
import * as i13 from "primeng/paginator";
|
|
43
|
+
import * as i14 from "primeng/overlaypanel";
|
|
44
|
+
import * as i15 from "primeng/menu";
|
|
45
|
+
export class ECSPrimengTable {
|
|
46
|
+
constructor(tableService, notification) {
|
|
47
|
+
this.tableService = tableService;
|
|
48
|
+
this.notification = notification;
|
|
49
|
+
this.i18n = inject(ECSPrimengTableI18nService);
|
|
50
|
+
this.changeDetector = inject(ChangeDetectorRef, { optional: true });
|
|
51
|
+
this.stateScope = inject(ECSPrimengTableStateService, { optional: true });
|
|
52
|
+
this.destroy$ = new Subject();
|
|
53
|
+
this.initialStateApplied = false;
|
|
54
|
+
this.destroyed = false;
|
|
55
|
+
this.tableOptions = DEFAULT_TABLE_OPTIONS;
|
|
56
|
+
this.treeStateRestored = false;
|
|
57
|
+
this.onRowCheckboxChange = new EventEmitter(); // Emitter that returns the column selected and if it was selected or unselected
|
|
58
|
+
this.onRowSelect = new EventEmitter;
|
|
59
|
+
this.onRowUnselect = new EventEmitter;
|
|
60
|
+
this.onDataEndUpdate = new EventEmitter();
|
|
61
|
+
this.viewsModalShow = false;
|
|
62
|
+
this.tableViewCurrentSelectedAlias = null;
|
|
63
|
+
this.tableViewsFirstFetchDone = false;
|
|
64
|
+
this.excelReportTitle = "";
|
|
65
|
+
this.showExportModal = false;
|
|
66
|
+
this.showColumnSelector = false;
|
|
67
|
+
this.selectedRowsCheckbox = []; // An array to keep all the selected rows
|
|
68
|
+
this.selectAllLoading = false;
|
|
69
|
+
this.selectionQueryKey = '';
|
|
70
|
+
this.globalSearchText = null; // The text used by the global search
|
|
71
|
+
this.appliedGlobalSearchText = null;
|
|
72
|
+
this.globalSearchManaged = false;
|
|
73
|
+
this.tableViewsList = [];
|
|
74
|
+
this.tableViews_menuItems = [];
|
|
75
|
+
this.DataType = DataType;
|
|
76
|
+
this.CellOverflowBehaviour = CellOverflowBehaviour;
|
|
77
|
+
this.DataAlignHorizontal = DataAlignHorizontal;
|
|
78
|
+
this.DataAlignVertical = DataAlignVertical;
|
|
79
|
+
this.FrozenColumnAlign = FrozenColumnAlign;
|
|
80
|
+
this.TableViewSaveMode = TableViewSaveMode;
|
|
81
|
+
this.currentPage = 0; // The current page we are at
|
|
82
|
+
this.currentRowsPerPage = 0; // The current rows per page selected
|
|
83
|
+
this.allowedRowsPerPage = []; // The different values of rows per page allowed
|
|
84
|
+
this.totalRecords = 0; // The number of total records that are available (taking into account the filters)
|
|
85
|
+
this.totalRecordsNotFiltered = 0; // The total number of records available if no filters were applied
|
|
86
|
+
this.dateFormat = "dd-MMM-yyyy HH:mm:ss zzzz";
|
|
87
|
+
this.dateTimezone = "+00:00";
|
|
88
|
+
this.dateCulture = "en-US";
|
|
89
|
+
this.exportDateFormat = "dd-MMM-yyyy HH:mm:ss";
|
|
90
|
+
this.columns = [];
|
|
91
|
+
this.columnsCantBeHidden = [];
|
|
92
|
+
this.columnsSelected = [];
|
|
93
|
+
this.columnModalData = [];
|
|
94
|
+
this.filteredColumnData = [];
|
|
95
|
+
this.predefinedFiltersSelectedValuesCollection = {}; // Contains a collection of the predefined column filters selection (possible values come from 'predefinedFiltersCollection')
|
|
96
|
+
this.tableLazyLoadEventInformation = {}; // Data of the last lazy load event of the table
|
|
97
|
+
this.initialConfigurationFetched = false;
|
|
98
|
+
this.maxViews = 0;
|
|
99
|
+
this.deviceType = DeviceType.Desktop;
|
|
100
|
+
this.columnSelectionCustomized = false;
|
|
101
|
+
this.headerMenuItems = [];
|
|
102
|
+
this.rowMenuItems = [];
|
|
103
|
+
this.i18n.changes.pipe(takeUntil(this.destroy$)).subscribe(() => {
|
|
104
|
+
this.headerMenuItems = this.translateMenuItems(this.headerMenuItems);
|
|
105
|
+
this.rowMenuItems = this.translateMenuItems(this.rowMenuItems);
|
|
106
|
+
this.changeDetector?.markForCheck();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/** The applied query stays separate from text being typed during the debounce. */
|
|
110
|
+
get effectiveGlobalSearchText() {
|
|
111
|
+
return this.globalSearchManaged ? this.appliedGlobalSearchText : this.globalSearchText;
|
|
112
|
+
}
|
|
113
|
+
cancelGlobalSearch() {
|
|
114
|
+
if (this.globalSearchTimer !== undefined)
|
|
115
|
+
clearTimeout(this.globalSearchTimer);
|
|
116
|
+
this.globalSearchTimer = undefined;
|
|
117
|
+
}
|
|
118
|
+
restoreGlobalSearch(value) {
|
|
119
|
+
this.cancelGlobalSearch();
|
|
120
|
+
this.globalSearchText = value;
|
|
121
|
+
this.appliedGlobalSearchText = value || null;
|
|
122
|
+
this.globalSearchManaged = true;
|
|
123
|
+
}
|
|
124
|
+
globalSearchOption(value) {
|
|
125
|
+
return typeof value === 'number' && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
|
|
126
|
+
}
|
|
127
|
+
onGlobalSearchInput(value) {
|
|
128
|
+
if (this.destroyed)
|
|
129
|
+
return;
|
|
130
|
+
this.cancelGlobalSearch();
|
|
131
|
+
if (!this.globalSearchManaged)
|
|
132
|
+
this.appliedGlobalSearchText = this.globalSearchText || null;
|
|
133
|
+
this.globalSearchManaged = true;
|
|
134
|
+
this.globalSearchText = value;
|
|
135
|
+
const minLength = this.globalSearchOption(this.tableOptions.globalFilter?.minLength);
|
|
136
|
+
const delay = this.globalSearchOption(this.tableOptions.globalFilter?.debounceTime);
|
|
137
|
+
const trimmed = value.trim();
|
|
138
|
+
const effective = trimmed.length >= minLength ? (trimmed || null) : null;
|
|
139
|
+
if (effective === (this.appliedGlobalSearchText?.trim() || null))
|
|
140
|
+
return;
|
|
141
|
+
const apply = () => {
|
|
142
|
+
this.globalSearchTimer = undefined;
|
|
143
|
+
if (this.destroyed)
|
|
144
|
+
return;
|
|
145
|
+
this.appliedGlobalSearchText = effective;
|
|
146
|
+
this.currentPage = 0;
|
|
147
|
+
this.dt.first = 0;
|
|
148
|
+
if (minLength === 0 && delay === 0) {
|
|
149
|
+
// Keep PrimeNG's existing filtering behavior when the feature is not configured.
|
|
150
|
+
this.dt.filterGlobal(value, 'contains');
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// Own the global delay so it is not added to PrimeNG's column-filter delay.
|
|
154
|
+
this.dt.filters = { ...this.dt.filters, global: { value: effective, matchMode: 'contains' } };
|
|
155
|
+
this.fetchTableData({ ...this.tableLazyLoadEventInformation, first: 0,
|
|
156
|
+
rows: this.currentRowsPerPage, filters: this.dt.filters });
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
if (effective === null || delay === 0)
|
|
160
|
+
apply();
|
|
161
|
+
else
|
|
162
|
+
this.globalSearchTimer = setTimeout(apply, delay);
|
|
163
|
+
}
|
|
164
|
+
ngOnInit() {
|
|
165
|
+
this.i18n.connectPrimeNG();
|
|
166
|
+
if (this.tableOptions.tree)
|
|
167
|
+
this.treeState = new TreeTableState(this.tableOptions.tree);
|
|
168
|
+
this.validateStatePersistence();
|
|
169
|
+
this.updateResponsiveViewport();
|
|
170
|
+
this.fetchTableConfiguration();
|
|
171
|
+
}
|
|
172
|
+
ngAfterViewInit() {
|
|
173
|
+
this.calculateScrollHeight();
|
|
174
|
+
this.changeDetector?.detectChanges();
|
|
175
|
+
}
|
|
176
|
+
get compactHeader() {
|
|
177
|
+
return !!this.tableOptions.responsive?.headerMenu && this.deviceType !== DeviceType.Desktop;
|
|
178
|
+
}
|
|
179
|
+
get compactRows() {
|
|
180
|
+
return !!this.tableOptions.responsive?.rowMenu && this.deviceType !== DeviceType.Desktop;
|
|
181
|
+
}
|
|
182
|
+
get actionColumnWidth() {
|
|
183
|
+
return this.compactRows ? 56 : (this.tableOptions.rows?.action?.width ?? 150);
|
|
184
|
+
}
|
|
185
|
+
getColumnHeaderGroups(columns) {
|
|
186
|
+
if (!columns.some(column => column.headerGroup?.trim()))
|
|
187
|
+
return [];
|
|
188
|
+
const groups = [];
|
|
189
|
+
for (const column of columns) {
|
|
190
|
+
const label = column.headerGroup?.trim() ?? '';
|
|
191
|
+
const frozenColumnAlign = column.frozenColumnAlign ?? FrozenColumnAlign.Noone;
|
|
192
|
+
const previous = groups[groups.length - 1];
|
|
193
|
+
if (previous && previous.label === label && previous.frozenColumnAlign === frozenColumnAlign) {
|
|
194
|
+
previous.colspan++;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
groups.push({ field: column.field, label, colspan: 1, frozenColumnAlign });
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return groups;
|
|
201
|
+
}
|
|
202
|
+
isInitiallyVisible(column) {
|
|
203
|
+
if (!column.canBeHidden)
|
|
204
|
+
return true;
|
|
205
|
+
if (column.startHidden)
|
|
206
|
+
return false;
|
|
207
|
+
const devices = column.visibleOnlyIn;
|
|
208
|
+
return !devices?.length || devices.some(device => device === this.deviceType || String(device).toLowerCase() === DeviceType[this.deviceType].toLowerCase());
|
|
209
|
+
}
|
|
210
|
+
updateResponsiveViewport() {
|
|
211
|
+
const options = this.tableOptions.responsive;
|
|
212
|
+
const tablet = options?.tabletMinWidth ?? 768;
|
|
213
|
+
const desktop = options?.desktopMinWidth ?? 1200;
|
|
214
|
+
if (!Number.isFinite(tablet) || !Number.isFinite(desktop) || tablet <= 0 || desktop <= tablet) {
|
|
215
|
+
throw new Error('ECS table responsive widths must be finite and 0 < tabletMinWidth < desktopMinWidth.');
|
|
216
|
+
}
|
|
217
|
+
const width = typeof window === 'undefined' ? desktop : window.innerWidth;
|
|
218
|
+
const next = width < tablet ? DeviceType.Mobile : width < desktop ? DeviceType.Tablet : DeviceType.Desktop;
|
|
219
|
+
if (next === this.deviceType)
|
|
220
|
+
return;
|
|
221
|
+
this.deviceType = next;
|
|
222
|
+
this.responsiveHeaderMenu?.hide();
|
|
223
|
+
this.responsiveRowMenu?.hide();
|
|
224
|
+
if (!this.initialConfigurationFetched || this.columnSelectionCustomized ||
|
|
225
|
+
!this.columns.some(column => column.visibleOnlyIn?.length))
|
|
226
|
+
return;
|
|
227
|
+
const selected = this.columns.filter(column => column.canBeHidden && this.isInitiallyVisible(column));
|
|
228
|
+
const shown = this.tableService.orderColumnsWithFrozens(this.columnsCantBeHidden.concat(selected));
|
|
229
|
+
const previous = this.tableOptions.columns?.shown ?? [];
|
|
230
|
+
if (shown.length === previous.length && shown.every((column, i) => column.field === previous[i].field))
|
|
231
|
+
return;
|
|
232
|
+
this.columnsSelected = selected;
|
|
233
|
+
this.tableOptions.columns.shown = shown;
|
|
234
|
+
this.showColumnSelector = false;
|
|
235
|
+
// Request newly visible fields without resetting filters, sorting or pagination.
|
|
236
|
+
if (this.initialStateApplied)
|
|
237
|
+
this.fetchTableData(this.tableLazyLoadEventInformation);
|
|
238
|
+
}
|
|
239
|
+
buttonVisible(button, row) {
|
|
240
|
+
return (button.visibleCondition?.(row) ?? true) &&
|
|
241
|
+
((button.enabledCondition?.(row) ?? true) || !button.conditionFailHide);
|
|
242
|
+
}
|
|
243
|
+
hasRowMenuActions(row) {
|
|
244
|
+
return (this.tableOptions.rows?.action?.buttons ?? []).some(button => this.buttonVisible(button, row));
|
|
245
|
+
}
|
|
246
|
+
buttonMenuItems(buttons, row) {
|
|
247
|
+
return buttons.filter(button => this.buttonVisible(button, row)).map((button, index) => ({
|
|
248
|
+
label: button.label || button.tooltip || 'Action {{number}}',
|
|
249
|
+
_uiParams: { number: index + 1 },
|
|
250
|
+
icon: button.icon,
|
|
251
|
+
disabled: !(button.enabledCondition?.(row) ?? true),
|
|
252
|
+
command: () => {
|
|
253
|
+
if (this.buttonVisible(button, row) && (button.enabledCondition?.(row) ?? true) && button.action) {
|
|
254
|
+
this.tableService.handleButtonsClick(button.action, row);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
closeResponsiveMenus() {
|
|
260
|
+
this.responsiveHeaderMenu?.hide();
|
|
261
|
+
this.responsiveRowMenu?.hide();
|
|
262
|
+
}
|
|
263
|
+
openRowMenu(event, row) {
|
|
264
|
+
event.stopPropagation();
|
|
265
|
+
this.responsiveHeaderMenu?.hide();
|
|
266
|
+
if (this.responsiveRowMenu?.visible && this.rowMenuRow === row) {
|
|
267
|
+
this.responsiveRowMenu.hide();
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
// Use one overlay for all rows. Replacing the model binds every action to this row.
|
|
271
|
+
this.rowMenuRow = row;
|
|
272
|
+
this.rowMenuItems = this.translateMenuItems(this.buttonMenuItems(this.tableOptions.rows?.action?.buttons ?? [], row));
|
|
273
|
+
const wasOpen = this.responsiveRowMenu?.visible;
|
|
274
|
+
this.responsiveRowMenu?.show(event);
|
|
275
|
+
if (wasOpen)
|
|
276
|
+
this.responsiveRowMenu?.alignOverlay();
|
|
277
|
+
}
|
|
278
|
+
translateMenuItems(items) {
|
|
279
|
+
return items.map(item => {
|
|
280
|
+
if (item['_literalLabel'])
|
|
281
|
+
return item;
|
|
282
|
+
const key = item['_uiLabelKey'] ?? item.label;
|
|
283
|
+
return { ...item, _uiLabelKey: key, label: this.i18n.text(key, item['_uiParams']) };
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
openHeaderMenu(event) {
|
|
287
|
+
this.responsiveRowMenu?.hide();
|
|
288
|
+
const options = this.tableOptions;
|
|
289
|
+
const items = [];
|
|
290
|
+
if (options.columns?.selectorEnabled)
|
|
291
|
+
items.push({ label: 'Modify columns', icon: options.columns.selectorIcon, command: () => this.columnSelectorShow() });
|
|
292
|
+
if (options.header?.clearSortsEnabled)
|
|
293
|
+
items.push({ label: 'Clear sorts', icon: options.header.clearSortsIcon, disabled: !this.hasToClearSorts(this.dt), command: () => this.clearSorts(this.dt) });
|
|
294
|
+
if (options.header?.clearFiltersEnabled)
|
|
295
|
+
items.push({ label: 'Clear filters', icon: options.header.clearFiltersIcon, disabled: !this.hasToClearFilters(this.dt, this.globalSearchText), command: () => this.clearFilters(this.dt) });
|
|
296
|
+
if (this.tableViewsEnabled()) {
|
|
297
|
+
items.push({ label: this.tableViewCurrentSelectedAlias || options.views?.noViewSelectedText || 'Select a view', _literalLabel: !!this.tableViewCurrentSelectedAlias, icon: 'pi pi-bookmark', command: () => { this.viewsModalShow = true; } });
|
|
298
|
+
items.push({ label: 'Apply view again', icon: options.views?.reloadViewButtonIcon || 'pi pi-refresh', disabled: !this.tableViewCurrentSelectedAlias, command: () => this.viewLoad(this.tableViewCurrentSelectedAlias) });
|
|
299
|
+
}
|
|
300
|
+
if (options.excelReport?.url?.trim())
|
|
301
|
+
items.push({ label: 'Export to Excel', icon: 'pi pi-file-excel', command: () => this.openExcelExport() });
|
|
302
|
+
if (options.resetTableView?.enabled)
|
|
303
|
+
items.push({ label: 'Reset table view', icon: options.resetTableView.icon, command: () => this.resetTableView() });
|
|
304
|
+
items.push({ label: 'Refresh data', icon: 'pi pi-refresh', command: () => this.refreshData(event) });
|
|
305
|
+
items.push(...this.buttonMenuItems(options.header?.buttons ?? [], null));
|
|
306
|
+
this.headerMenuItems = this.translateMenuItems(items);
|
|
307
|
+
this.responsiveHeaderMenu?.toggle(event);
|
|
308
|
+
}
|
|
309
|
+
validateStatePersistence() {
|
|
310
|
+
if (!this.tableOptions.statePersistence?.enabled)
|
|
311
|
+
return;
|
|
312
|
+
if (!this.tableOptions.statePersistence.key?.trim() || !this.stateScope) {
|
|
313
|
+
throw new Error('ECS table statePersistence requires a non-empty key and ECSPrimengTableStateService provided on a parent scope component.');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
ngOnDestroy() {
|
|
317
|
+
this.cancelGlobalSearch();
|
|
318
|
+
this.destroyed = true;
|
|
319
|
+
this.destroy$.next();
|
|
320
|
+
this.destroy$.complete();
|
|
321
|
+
this.treeState?.cancel();
|
|
322
|
+
const options = this.tableOptions.statePersistence;
|
|
323
|
+
const key = options?.key?.trim();
|
|
324
|
+
if (!key || !this.stateScope)
|
|
325
|
+
return;
|
|
326
|
+
if (!options?.enabled) {
|
|
327
|
+
this.stateScope.clear(key);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
if (!this.initialStateApplied || !this.dt)
|
|
331
|
+
return;
|
|
332
|
+
const filters = structuredClone(this.dt.filters ?? {});
|
|
333
|
+
delete filters['global'];
|
|
334
|
+
delete filters['selector'];
|
|
335
|
+
this.stateScope.set(key, {
|
|
336
|
+
configurationUrl: this.tableOptions.urlTableConfiguration ?? '',
|
|
337
|
+
dataUrl: this.tableOptions.urlTableData ?? '',
|
|
338
|
+
filters,
|
|
339
|
+
multiSortMeta: structuredClone(this.dt.multiSortMeta ?? []),
|
|
340
|
+
globalSearchText: this.effectiveGlobalSearchText,
|
|
341
|
+
currentPage: this.currentPage,
|
|
342
|
+
currentRowsPerPage: this.currentRowsPerPage,
|
|
343
|
+
treeMode: this.treeState?.mode,
|
|
344
|
+
treeExpandedKeys: this.treeState ? [...this.treeState.expanded] : undefined,
|
|
345
|
+
treeChildPages: this.treeState?.snapshotPages()
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
restoreNavigationState() {
|
|
349
|
+
this.validateStatePersistence();
|
|
350
|
+
const options = this.tableOptions.statePersistence;
|
|
351
|
+
const key = options?.key?.trim();
|
|
352
|
+
if (!options?.enabled) {
|
|
353
|
+
if (key)
|
|
354
|
+
this.stateScope?.clear(key);
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
const state = this.stateScope.get(key);
|
|
358
|
+
if (!state)
|
|
359
|
+
return false;
|
|
360
|
+
if (state.configurationUrl !== this.tableOptions.urlTableConfiguration ||
|
|
361
|
+
state.dataUrl !== this.tableOptions.urlTableData || state.treeMode !== this.treeState?.mode) {
|
|
362
|
+
this.stateScope.clear(key);
|
|
363
|
+
return false;
|
|
364
|
+
}
|
|
365
|
+
const fields = new Set(this.columns.map(column => column.field));
|
|
366
|
+
const filters = {};
|
|
367
|
+
for (const [field, filter] of Object.entries(state.filters)) {
|
|
368
|
+
if (fields.has(field))
|
|
369
|
+
filters[field] = filter;
|
|
370
|
+
}
|
|
371
|
+
this.currentRowsPerPage = this.allowedRowsPerPage.includes(state.currentRowsPerPage)
|
|
372
|
+
? state.currentRowsPerPage : this.currentRowsPerPage;
|
|
373
|
+
this.currentPage = this.currentRowsPerPage === state.currentRowsPerPage
|
|
374
|
+
? Math.max(0, state.currentPage) : 0;
|
|
375
|
+
this.restoreGlobalSearch(state.globalSearchText);
|
|
376
|
+
this.treeState?.restore(state.treeExpandedKeys, state.treeChildPages);
|
|
377
|
+
this.treeStateRestored = !!this.treeState;
|
|
378
|
+
if (this.globalSearchText) {
|
|
379
|
+
filters['global'] = { value: this.globalSearchText, matchMode: 'contains' };
|
|
380
|
+
}
|
|
381
|
+
const sorts = state.multiSortMeta.filter(sort => fields.has(sort.field));
|
|
382
|
+
this.dt.filters = { ...this.dt.filters, ...structuredClone(filters) };
|
|
383
|
+
// Keep initialStateApplied=false while PrimeNG setters can emit lazy-load events.
|
|
384
|
+
this.dt.multiSortMeta = sorts;
|
|
385
|
+
this.dt.first = this.currentPage * this.currentRowsPerPage;
|
|
386
|
+
this.dt.rows = this.currentRowsPerPage;
|
|
387
|
+
this.tableLazyLoadEventInformation = {
|
|
388
|
+
first: this.dt.first,
|
|
389
|
+
rows: this.currentRowsPerPage,
|
|
390
|
+
filters: this.dt.filters,
|
|
391
|
+
multiSortMeta: sorts
|
|
392
|
+
};
|
|
393
|
+
this.restorePredefinedSelections(filters);
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
restorePredefinedSelections(filters) {
|
|
397
|
+
this.predefinedFiltersSelectedValuesCollection = {};
|
|
398
|
+
for (const column of this.columns) {
|
|
399
|
+
const key = column.filterPredefinedValuesName;
|
|
400
|
+
if (!key)
|
|
401
|
+
continue;
|
|
402
|
+
const criteria = filters[column.field];
|
|
403
|
+
const value = (Array.isArray(criteria) ? criteria[0] : criteria)?.value;
|
|
404
|
+
if (value === null || value === undefined)
|
|
405
|
+
continue;
|
|
406
|
+
this.predefinedFiltersSelectedValuesCollection[key] =
|
|
407
|
+
(this.tableOptions.predefinedFilters?.[key] ?? []).filter(option => Array.isArray(value) ? value.includes(option.value) : value === option.value);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
onResize() {
|
|
411
|
+
this.updateResponsiveViewport();
|
|
412
|
+
this.calculateScrollHeight();
|
|
413
|
+
}
|
|
414
|
+
calculateScrollHeight() {
|
|
415
|
+
if (this.tableOptions.verticalScroll?.cssFormula) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (this.tableOptions.verticalScroll?.fitToContainer && this.tableContainer && this.paginatorContainer && this.headerContainer) {
|
|
419
|
+
const containerRect = this.tableContainer.nativeElement.getBoundingClientRect();
|
|
420
|
+
const paginatorHeight = this.paginatorContainer.nativeElement.offsetHeight;
|
|
421
|
+
const headerHeight = this.headerContainer.nativeElement.offsetHeight;
|
|
422
|
+
const viewportHeight = window.innerHeight;
|
|
423
|
+
const topOffset = containerRect.top + window.scrollY;
|
|
424
|
+
this.tableOptions.verticalScroll.height = (viewportHeight - topOffset - paginatorHeight - headerHeight) - 60;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
get scrollHeightValue() {
|
|
428
|
+
if (this.tableOptions.verticalScroll?.cssFormula) {
|
|
429
|
+
return this.tableOptions.verticalScroll.cssFormula;
|
|
430
|
+
}
|
|
431
|
+
const height = this.tableOptions.verticalScroll?.height;
|
|
432
|
+
return height && height > 0 ? `${height}px` : '';
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Updates the table data and, if needed, retrieves the initial table configuration from an external source.
|
|
436
|
+
*
|
|
437
|
+
* Also allows resetting the table to its original state before any user manipulations.
|
|
438
|
+
*
|
|
439
|
+
* @param {boolean} [resetTableView=false] Optional.
|
|
440
|
+
* - `true`: resets the table state before loading data.
|
|
441
|
+
* - `false`: refreshes data using the current configuration (and retrieves initial configuration if necessary).
|
|
442
|
+
*
|
|
443
|
+
* **_Behavior_**
|
|
444
|
+
* - The table is automatically set to `isActive = true`.
|
|
445
|
+
* - If the initial configuration has not been fetched, it will fetch it and then update the data.
|
|
446
|
+
* - If the initial configuration is already fetched, it will just update the data.
|
|
447
|
+
* - If `resetTableView` is true and the configuration is already initialized, the table will be reset to its original state before updating the data.
|
|
448
|
+
*/
|
|
449
|
+
updateData(resetTableView = false) {
|
|
450
|
+
this.tableOptions.isActive = true; // Enable table actions: the table is now active and can perform updates
|
|
451
|
+
if (!this.initialConfigurationFetched || resetTableView) { // If initial configuration hasn't been fetched yet or a reset is explicitly requested
|
|
452
|
+
if (this.initialConfigurationFetched && resetTableView) { // Reset the table only if it was already initialized and a reset is explicitly requested
|
|
453
|
+
this.resetTableView(); // Reset table state (filters, pagination, sorting, etc.) and then refresh data
|
|
454
|
+
}
|
|
455
|
+
else { // We only need to get the table configuration without reseting the view
|
|
456
|
+
this.fetchTableConfiguration(); // Fetch the initial table configuration before updating data
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
else { // Table is already initialized and no reset requested, just refresh the data
|
|
460
|
+
this.fetchTableData(this.tableLazyLoadEventInformation); // Update table rows using the last lazy load event
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
canFetchData() {
|
|
464
|
+
return !this.destroyed
|
|
465
|
+
&& !!this.tableOptions.isActive
|
|
466
|
+
&& !!this.tableOptions.urlTableConfiguration?.trim()
|
|
467
|
+
&& !!this.tableOptions.urlTableData?.trim();
|
|
468
|
+
}
|
|
469
|
+
fetchTableConfiguration(resetTableView = false) {
|
|
470
|
+
if (!this.canFetchData()) {
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
this.tableService.fetchTableConfiguration(this.tableOptions.urlTableConfiguration)
|
|
474
|
+
.pipe(takeUntil(this.destroy$)).subscribe({
|
|
475
|
+
next: (response) => {
|
|
476
|
+
this.handleTableConfigurationResponse(response.body, resetTableView);
|
|
477
|
+
},
|
|
478
|
+
error: (err) => this.tableService.handleTableError(err, 'Columns Error')
|
|
479
|
+
});
|
|
480
|
+
}
|
|
481
|
+
handleTableConfigurationResponse(body, resetTableView = false) {
|
|
482
|
+
this.allowedRowsPerPage = body.allowedItemsPerPage; // Update the number of rows allowed per page
|
|
483
|
+
this.currentRowsPerPage = Math.min(...this.allowedRowsPerPage); // Update the current rows per page to use the minimum value of allowed rows per page by default
|
|
484
|
+
this.columns = body.columnsInfo; // Update columns with fetched data
|
|
485
|
+
this.columnsCantBeHidden = this.columns.filter((col) => !col.canBeHidden); // Filter columns that cannot be hidden
|
|
486
|
+
this.columnSelectionCustomized = false;
|
|
487
|
+
this.columnsSelected = this.columns.filter(col => col.canBeHidden && this.isInitiallyVisible(col)); // Selected columns that are not hidden by default
|
|
488
|
+
this.tableOptions.columns.shown = this.tableService.orderColumnsWithFrozens(this.columnsCantBeHidden.concat(this.columnsSelected));
|
|
489
|
+
this.dateFormat = body.dateFormat;
|
|
490
|
+
this.dateTimezone = body.dateTimezone;
|
|
491
|
+
this.dateCulture = body.dateCulture;
|
|
492
|
+
this.exportDateFormat = body.exportDateFormat;
|
|
493
|
+
this.currentPage = 0;
|
|
494
|
+
this.initialConfigurationFetched = true;
|
|
495
|
+
this.maxViews = body.maxViews;
|
|
496
|
+
if (resetTableView) {
|
|
497
|
+
this.tableOptions.isActive = false;
|
|
498
|
+
this.clearFilters(this.dt, true);
|
|
499
|
+
this.clearSorts(this.dt, true);
|
|
500
|
+
this.dt.tableWidthState = this.initialTableWidth;
|
|
501
|
+
this.dt.columnWidthsState = this.initialColumnWidths;
|
|
502
|
+
this.dt.restoreColumnWidths();
|
|
503
|
+
this.tableLazyLoadEventInformation.multiSortMeta = [];
|
|
504
|
+
this.tableOptions.isActive = true;
|
|
505
|
+
this.initialStateApplied = true;
|
|
506
|
+
this.tableLazyLoadEventInformation.first = 0;
|
|
507
|
+
this.tableLazyLoadEventInformation.rows = this.currentRowsPerPage;
|
|
508
|
+
this.fetchTableData(this.tableLazyLoadEventInformation);
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
setTimeout(() => {
|
|
512
|
+
if (this.destroyed)
|
|
513
|
+
return;
|
|
514
|
+
this.initialColumnWidths = this.tableService.computeColumnWidths(this.dt);
|
|
515
|
+
this.initialTableWidth = this.tableService.computeTableWidth(this.dt);
|
|
516
|
+
}, 0);
|
|
517
|
+
this.fetchTableViews();
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
refreshData(event) {
|
|
521
|
+
this.fetchTableData(this.tableLazyLoadEventInformation);
|
|
522
|
+
}
|
|
523
|
+
tableViewsEnabled() {
|
|
524
|
+
const views = this.tableOptions.views;
|
|
525
|
+
if (views?.saveMode === TableViewSaveMode.None) { // saveMode must be different from noone
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
if (!views?.saveKey?.trim()) { // saveKey must exist and must not be empty after trim
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
if (this.maxViews <= 0) { // maxViews must be greater than 0
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
if (views?.saveMode === TableViewSaveMode.DatabaseStorage) { // If saveMode is database, urlGet and urlSave must exist and must not be empty after trim
|
|
535
|
+
if (!views?.urlGet?.trim() || !views?.urlSave?.trim()) {
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
return true; // All checks passed, views are enabled
|
|
540
|
+
}
|
|
541
|
+
fetchTableViews() {
|
|
542
|
+
if (!this.tableViewsEnabled()) {
|
|
543
|
+
this.startInitialDataLoad();
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
const tableViews = this.tableService.fetchTableViews(this.tableOptions.views.saveMode, this.tableOptions.views.urlGet, this.tableOptions.views.saveKey);
|
|
547
|
+
if (tableViews instanceof Observable) {
|
|
548
|
+
tableViews.pipe(takeUntil(this.destroy$)).subscribe({
|
|
549
|
+
next: (response) => {
|
|
550
|
+
let parsedResult = response.body.map((item) => ({
|
|
551
|
+
viewAlias: item.viewAlias,
|
|
552
|
+
viewData: JSON.parse(item.viewData),
|
|
553
|
+
lastActive: item.lastActive
|
|
554
|
+
}));
|
|
555
|
+
this.tableViewListProcess(parsedResult);
|
|
556
|
+
},
|
|
557
|
+
error: (err) => {
|
|
558
|
+
this.tableService.handleTableError(err, 'Views get error');
|
|
559
|
+
this.startInitialDataLoad();
|
|
560
|
+
}
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
else {
|
|
564
|
+
this.tableViewListProcess(tableViews);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
tableViewListProcess(tableViews) {
|
|
568
|
+
this.tableViewsList = [...tableViews];
|
|
569
|
+
if (this.tableViewsList.length > 0) {
|
|
570
|
+
this.tableService.sortViews(this.tableViewsList);
|
|
571
|
+
}
|
|
572
|
+
this.tableViews_menuItems = [...this.tableService.updateViewsMenuItems(this.tableViewsList)];
|
|
573
|
+
this.startInitialDataLoad();
|
|
574
|
+
}
|
|
575
|
+
startInitialDataLoad() {
|
|
576
|
+
if (this.initialStateApplied || this.destroyed)
|
|
577
|
+
return;
|
|
578
|
+
const restored = this.restoreNavigationState();
|
|
579
|
+
this.initialStateApplied = true;
|
|
580
|
+
const viewToStartup = restored ? undefined : this.tableViewsList.find(v => v.lastActive);
|
|
581
|
+
if (viewToStartup) { // If there is a view that needs to be loaded on startup
|
|
582
|
+
this.viewLoad(viewToStartup.viewAlias);
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
this.fetchTableData(this.tableLazyLoadEventInformation);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
viewLoad(tableViewAlias) {
|
|
589
|
+
const viewToLoad = this.tableViewsList.find(v => v.viewAlias === tableViewAlias);
|
|
590
|
+
if (!viewToLoad) {
|
|
591
|
+
this.notification.showToast("error", this.i18n.text("VIEW TO LOAD DOESN'T EXIST"), this.i18n.text("The view to load doesn't exist"));
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
594
|
+
this.columnSelectionCustomized = true;
|
|
595
|
+
let viewData = viewToLoad.viewData;
|
|
596
|
+
this.treeState?.restore(viewData.treeExpandedKeys, viewData.treeChildPages);
|
|
597
|
+
this.treeStateRestored = !!this.treeState;
|
|
598
|
+
this.columnsSelected = viewData.columnsShown
|
|
599
|
+
.map(data => this.columns.find((col) => col.field === data.field))
|
|
600
|
+
.filter((col) => col !== undefined)
|
|
601
|
+
.filter(col => !this.columnsCantBeHidden.includes(col));
|
|
602
|
+
this.tableOptions.columns.shown = this.tableService.orderColumnsWithFrozens(this.columnsCantBeHidden.concat(this.columnsSelected));
|
|
603
|
+
this.currentPage = viewData.currentPage;
|
|
604
|
+
this.currentRowsPerPage = viewData.currentRowsPerPage;
|
|
605
|
+
this.restoreGlobalSearch(viewData.globalSearchText);
|
|
606
|
+
this.tableOptions.isActive = false;
|
|
607
|
+
this.tableLazyLoadEventInformation.multiSortMeta = [...(viewData.multiSortMeta ?? [])];
|
|
608
|
+
this.dt.multiSortMeta = [...(viewData.multiSortMeta ?? [])];
|
|
609
|
+
this.dt.sortMultiple();
|
|
610
|
+
this.dt.first = this.currentPage * this.currentRowsPerPage;
|
|
611
|
+
this.dt.rows = this.currentRowsPerPage;
|
|
612
|
+
this.tableLazyLoadEventInformation.first = this.dt.first;
|
|
613
|
+
this.tableLazyLoadEventInformation.rows = this.currentRowsPerPage;
|
|
614
|
+
this.tableOptions.isActive = true;
|
|
615
|
+
this.tableLazyLoadEventInformation.filters = structuredClone(viewData.filters);
|
|
616
|
+
this.dt.filters = structuredClone(viewData.filters);
|
|
617
|
+
this.restorePredefinedSelections(viewData.filters);
|
|
618
|
+
this.dt.tableWidthState = viewData.tableWidth;
|
|
619
|
+
this.dt.columnWidthsState = viewData.columnsWidth;
|
|
620
|
+
this.tableViewCurrentSelectedAlias = tableViewAlias;
|
|
621
|
+
this.notification.showToast("info", this.i18n.text("TABLE VIEW RESTORED"), this.i18n.text("The table view '{{value0}}' has been restored.", { value0: this.tableViewCurrentSelectedAlias }));
|
|
622
|
+
this.viewsModalShow = false;
|
|
623
|
+
this.fetchTableData(this.tableLazyLoadEventInformation);
|
|
624
|
+
}
|
|
625
|
+
viewCreate(viewAlias) {
|
|
626
|
+
if (this.tableViewsList.length >= this.maxViews) {
|
|
627
|
+
this.notification.showToast("error", this.i18n.text("NO MORE VIEWS ALLOWED"), this.i18n.text("You have created the maximum number of allowed views for this table"));
|
|
628
|
+
return;
|
|
629
|
+
}
|
|
630
|
+
let viewData = this.generateViewData();
|
|
631
|
+
let newView = {
|
|
632
|
+
lastActive: false,
|
|
633
|
+
viewAlias: viewAlias,
|
|
634
|
+
viewData: viewData
|
|
635
|
+
};
|
|
636
|
+
this.tableViewsList.push(newView);
|
|
637
|
+
this.tableService.sortViews(this.tableViewsList);
|
|
638
|
+
this.tableViews_menuItems = [...this.tableService.updateViewsMenuItems(this.tableViewsList)];
|
|
639
|
+
this.tableViewCurrentSelectedAlias = viewAlias;
|
|
640
|
+
this.viewsSave(0);
|
|
641
|
+
}
|
|
642
|
+
viewDelete(viewAlias) {
|
|
643
|
+
const index = this.tableViewsList.findIndex(v => v.viewAlias === viewAlias);
|
|
644
|
+
if (index === -1) {
|
|
645
|
+
this.notification.showToast("error", this.i18n.text("Table view delete failed"), this.i18n.text("The table view could not be deleted since it was not found."));
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
this.tableViewsList.splice(index, 1);
|
|
649
|
+
this.tableViews_menuItems = [...this.tableService.updateViewsMenuItems(this.tableViewsList)];
|
|
650
|
+
if (this.tableViewCurrentSelectedAlias === viewAlias) {
|
|
651
|
+
this.tableViewCurrentSelectedAlias = null;
|
|
652
|
+
}
|
|
653
|
+
this.viewsSave(3);
|
|
654
|
+
}
|
|
655
|
+
viewEditAlias(event) {
|
|
656
|
+
const index = this.tableViewsList.findIndex(v => v.viewAlias === event.viewAliasOld);
|
|
657
|
+
if (index === -1) {
|
|
658
|
+
this.notification.showToast("error", this.i18n.text("Table view alias change failed"), this.i18n.text("The table view alias could not be changed since it was not found."));
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
this.tableViewsList[index].viewAlias = event.viewAliasNew;
|
|
662
|
+
this.tableService.sortViews(this.tableViewsList);
|
|
663
|
+
this.tableViews_menuItems = [...this.tableService.updateViewsMenuItems(this.tableViewsList)];
|
|
664
|
+
if (this.tableViewCurrentSelectedAlias === event.viewAliasOld) {
|
|
665
|
+
this.tableViewCurrentSelectedAlias = event.viewAliasNew;
|
|
666
|
+
}
|
|
667
|
+
this.viewsSave(2);
|
|
668
|
+
}
|
|
669
|
+
viewUpdateData(viewAlias) {
|
|
670
|
+
const index = this.tableViewsList.findIndex(v => v.viewAlias === viewAlias);
|
|
671
|
+
if (index === -1) {
|
|
672
|
+
this.notification.showToast("error", this.i18n.text("Table view not found"), this.i18n.text("The table view to update data from was not found."));
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
let viewData = this.generateViewData();
|
|
676
|
+
this.tableViewsList[index].viewData = viewData;
|
|
677
|
+
this.viewsSave(1);
|
|
678
|
+
}
|
|
679
|
+
viewUpdateActiveStartup(viewAlias) {
|
|
680
|
+
const index = this.tableViewsList.findIndex(v => v.viewAlias === viewAlias);
|
|
681
|
+
if (index === -1) {
|
|
682
|
+
this.notification.showToast("error", this.i18n.text("Table view not found"), this.i18n.text("The table view to update data from was not found."));
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
685
|
+
let newStatus = !this.tableViewsList[index].lastActive;
|
|
686
|
+
this.tableViewsList.forEach(v => v.lastActive = false);
|
|
687
|
+
this.tableViewsList[index].lastActive = newStatus;
|
|
688
|
+
this.tableViews_menuItems = [...this.tableService.updateViewsMenuItems(this.tableViewsList)];
|
|
689
|
+
this.viewsSave(4);
|
|
690
|
+
}
|
|
691
|
+
viewsSave(endMessage) {
|
|
692
|
+
let tableView = JSON.stringify(this.tableViewsList);
|
|
693
|
+
switch (this.tableOptions.views.saveMode) {
|
|
694
|
+
case TableViewSaveMode.SessionStorage:
|
|
695
|
+
sessionStorage.setItem(this.tableOptions.views.saveKey, tableView);
|
|
696
|
+
break;
|
|
697
|
+
case TableViewSaveMode.LocalStorage:
|
|
698
|
+
localStorage.setItem(this.tableOptions.views.saveKey, tableView);
|
|
699
|
+
break;
|
|
700
|
+
case TableViewSaveMode.DatabaseStorage:
|
|
701
|
+
const saveObsv = this.tableService.viewsSaveToDatabase(this.tableViewsList, this.tableOptions.views.urlSave, this.tableOptions.views.saveKey);
|
|
702
|
+
saveObsv.subscribe({
|
|
703
|
+
next: (response) => {
|
|
704
|
+
this.viewsSaveEnd(endMessage);
|
|
705
|
+
},
|
|
706
|
+
error: (err) => this.tableService.handleTableError(err, 'Views save error')
|
|
707
|
+
});
|
|
708
|
+
return;
|
|
709
|
+
default:
|
|
710
|
+
this.notification.showToast("error", this.i18n.text("NOT IMPLEMENTED"), this.i18n.text("This type os save view has not been implemented yet."));
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
this.viewsSaveEnd(endMessage);
|
|
714
|
+
}
|
|
715
|
+
viewsSaveEnd(endMessage) {
|
|
716
|
+
this.changeDetector?.markForCheck();
|
|
717
|
+
switch (endMessage) {
|
|
718
|
+
case 0: // NEW VIEW
|
|
719
|
+
this.notification.showToast("info", this.i18n.text("Table view created"), this.i18n.text("New table view has been created."));
|
|
720
|
+
this.viewsModalShow = false;
|
|
721
|
+
break;
|
|
722
|
+
case 1: // UPDATE VIEW
|
|
723
|
+
this.notification.showToast("info", this.i18n.text("Table view data updated"), this.i18n.text("The table view data was updated."));
|
|
724
|
+
break;
|
|
725
|
+
case 2: // UPDATE ALIAS
|
|
726
|
+
this.notification.showToast("info", this.i18n.text("Table view name updated"), this.i18n.text("The table view alias was updated."));
|
|
727
|
+
break;
|
|
728
|
+
case 3: // DELETE VIEW
|
|
729
|
+
this.notification.showToast("info", this.i18n.text("Table view delete"), this.i18n.text("The table view was deleted."));
|
|
730
|
+
break;
|
|
731
|
+
case 4: // DELETE VIEW
|
|
732
|
+
this.notification.showToast("info", this.i18n.text("Table view active on startup"), this.i18n.text("Changed the view that will be active on startup."));
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
fetchTableData(event) {
|
|
737
|
+
if (!this.canFetchData()) {
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
if (!this.initialConfigurationFetched || !this.initialStateApplied) {
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
743
|
+
this.responsiveRowMenu?.hide();
|
|
744
|
+
this.tableLazyLoadEventInformation = event; // Store the event information for later use
|
|
745
|
+
if (event.rows != null && event.rows !== undefined) {
|
|
746
|
+
this.currentRowsPerPage = event.rows;
|
|
747
|
+
}
|
|
748
|
+
if (event.first != null && event.first !== undefined && event.rows != null && event.rows !== undefined) {
|
|
749
|
+
this.currentPage = event.first / event.rows;
|
|
750
|
+
}
|
|
751
|
+
let filtersWithoutGlobalAndSelectedRows = this.modifyFiltersWithoutGlobalAndSelectedRows(this.tableLazyLoadEventInformation.filters); // Create filters excluding the global filter
|
|
752
|
+
filtersWithoutGlobalAndSelectedRows = this.revertDateTimeZoneFilters(filtersWithoutGlobalAndSelectedRows);
|
|
753
|
+
const requestData = {
|
|
754
|
+
page: this.currentPage,
|
|
755
|
+
pageSize: this.currentRowsPerPage,
|
|
756
|
+
sort: this.tableLazyLoadEventInformation.multiSortMeta,
|
|
757
|
+
filter: filtersWithoutGlobalAndSelectedRows,
|
|
758
|
+
globalFilter: this.effectiveGlobalSearchText,
|
|
759
|
+
columns: this.tableOptions.columns.shown.map(col => col.field),
|
|
760
|
+
dateFormat: this.dateFormat,
|
|
761
|
+
dateTimezone: this.dateTimezone,
|
|
762
|
+
dateCulture: this.dateCulture,
|
|
763
|
+
exportDateFormat: this.exportDateFormat
|
|
764
|
+
};
|
|
765
|
+
const selectionKey = JSON.stringify({ ...requestData, page: 0, pageSize: 0, sort: null });
|
|
766
|
+
if (selectionKey !== this.selectionQueryKey)
|
|
767
|
+
this.matchingSelectionKeys = undefined;
|
|
768
|
+
this.selectionQueryKey = selectionKey;
|
|
769
|
+
this.selectionQuery = structuredClone(requestData);
|
|
770
|
+
if (this.treeState) {
|
|
771
|
+
const tree = this.treeState;
|
|
772
|
+
if (!this.treeStateRestored)
|
|
773
|
+
tree.restore([...tree.expanded], tree.snapshotPages());
|
|
774
|
+
this.treeStateRestored = false;
|
|
775
|
+
const structural = [tree.options.keyExpr, tree.options.parentIdExpr, tree.options.hasItemsExpr, 'rowID'];
|
|
776
|
+
requestData.columns = [...new Set([...requestData.columns, ...structural.filter((field) => !!field)])];
|
|
777
|
+
this.treeQuery = structuredClone(requestData);
|
|
778
|
+
const loading = tree.load(this.currentPage, this.currentRowsPerPage, this.treeFetcher(requestData));
|
|
779
|
+
this.tableOptions.data = [];
|
|
780
|
+
loading.then(updated => {
|
|
781
|
+
if (updated && !this.destroyed)
|
|
782
|
+
this.syncTreeRows();
|
|
783
|
+
}).catch(error => {
|
|
784
|
+
if (!this.destroyed)
|
|
785
|
+
this.tableService.handleTableError(error, 'Tree data error');
|
|
786
|
+
}).finally(() => {
|
|
787
|
+
if (!this.destroyed) {
|
|
788
|
+
this.changeDetector?.markForCheck();
|
|
789
|
+
this.onDataEndUpdate.emit();
|
|
790
|
+
}
|
|
791
|
+
});
|
|
792
|
+
return;
|
|
793
|
+
}
|
|
794
|
+
this.tableService.fetchTableData(this.tableOptions.urlTableData, requestData)
|
|
795
|
+
.pipe(takeUntil(this.destroy$), finalize(() => {
|
|
796
|
+
if (this.destroyed)
|
|
797
|
+
return;
|
|
798
|
+
this.onDataEndUpdate.emit(); // This is always executed after data update.
|
|
799
|
+
}))
|
|
800
|
+
.subscribe({
|
|
801
|
+
next: (response) => this.handleTableDataResponse(response.body),
|
|
802
|
+
error: (err) => this.tableService.handleTableError(err, 'Columns Error')
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
modifyFiltersWithoutGlobalAndSelectedRows(filters, overrideOption = -1) {
|
|
806
|
+
let filtersWithoutGlobalAndSelectedRows = structuredClone(filters ?? {}); // Create a copy of filters to delete the global.
|
|
807
|
+
if (filtersWithoutGlobalAndSelectedRows.hasOwnProperty('global')) { // If there is an entry with the global filter
|
|
808
|
+
delete filtersWithoutGlobalAndSelectedRows['global']; // Remove the global filter
|
|
809
|
+
}
|
|
810
|
+
this.selectorRowFilterBuilder(filtersWithoutGlobalAndSelectedRows, overrideOption);
|
|
811
|
+
return filtersWithoutGlobalAndSelectedRows; // Return the filters without global array
|
|
812
|
+
}
|
|
813
|
+
resetTableView() {
|
|
814
|
+
this.cancelGlobalSearch();
|
|
815
|
+
const key = this.tableOptions.statePersistence?.key?.trim();
|
|
816
|
+
if (key)
|
|
817
|
+
this.stateScope?.clear(key);
|
|
818
|
+
this.treeState?.restore();
|
|
819
|
+
this.treeStateRestored = !!this.treeState;
|
|
820
|
+
this.initialStateApplied = false;
|
|
821
|
+
this.tableViewCurrentSelectedAlias = '';
|
|
822
|
+
this.fetchTableConfiguration(true);
|
|
823
|
+
}
|
|
824
|
+
selectorRowFilterBuilder(filtersWithoutGlobalAndSelectedRows, overrideOption = -1) {
|
|
825
|
+
if (filtersWithoutGlobalAndSelectedRows.hasOwnProperty('selector') || overrideOption === 1 || overrideOption === 2) {
|
|
826
|
+
const selectorFilter = filtersWithoutGlobalAndSelectedRows['selector']?.[0];
|
|
827
|
+
let filterType = null;
|
|
828
|
+
if (overrideOption < 0 || overrideOption > 2) {
|
|
829
|
+
filterType = selectorFilter?.value ?? null;
|
|
830
|
+
}
|
|
831
|
+
else {
|
|
832
|
+
switch (overrideOption) {
|
|
833
|
+
case 0: // All
|
|
834
|
+
filterType = null;
|
|
835
|
+
break;
|
|
836
|
+
case 1: // Only selected rows
|
|
837
|
+
filterType = true;
|
|
838
|
+
break;
|
|
839
|
+
case 2: // Only NOT selected
|
|
840
|
+
filterType = false;
|
|
841
|
+
break;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
if (!filtersWithoutGlobalAndSelectedRows.hasOwnProperty('rowID')) {
|
|
845
|
+
filtersWithoutGlobalAndSelectedRows['rowID'] = [
|
|
846
|
+
{
|
|
847
|
+
"value": null,
|
|
848
|
+
"matchMode": "in",
|
|
849
|
+
"operator": "or"
|
|
850
|
+
}
|
|
851
|
+
];
|
|
852
|
+
}
|
|
853
|
+
const idFilter = filtersWithoutGlobalAndSelectedRows['rowID'][0];
|
|
854
|
+
if (filterType === true) {
|
|
855
|
+
idFilter.matchMode = "in";
|
|
856
|
+
idFilter.value = this.selectedRowsCheckbox;
|
|
857
|
+
}
|
|
858
|
+
else if (filterType === false) {
|
|
859
|
+
idFilter.operator = "and";
|
|
860
|
+
idFilter.matchMode = "notIn";
|
|
861
|
+
idFilter.value = this.selectedRowsCheckbox;
|
|
862
|
+
}
|
|
863
|
+
else if (filterType === null) {
|
|
864
|
+
idFilter.value = null;
|
|
865
|
+
idFilter.matchMode = "in";
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
revertDateTimeZoneFilters(inputFilter) {
|
|
870
|
+
this.tableOptions.columns.shown.forEach((column) => {
|
|
871
|
+
if (column.dataType === DataType.Date) { // If its date type
|
|
872
|
+
if (inputFilter.hasOwnProperty(column.field)) {
|
|
873
|
+
const originalDate = inputFilter[column.field][0].value;
|
|
874
|
+
if (originalDate !== null && originalDate instanceof Date) {
|
|
875
|
+
const utcDate = new Date(Date.UTC(originalDate.getFullYear(), originalDate.getMonth(), originalDate.getDate()));
|
|
876
|
+
inputFilter[column.field][0].value = utcDate;
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
});
|
|
881
|
+
return inputFilter;
|
|
882
|
+
}
|
|
883
|
+
handleTableDataResponse(body) {
|
|
884
|
+
this.tableOptions.data = body.data; // Update the table data
|
|
885
|
+
this.totalRecords = body.totalRecords; // Update the total number of records
|
|
886
|
+
this.totalRecordsNotFiltered = body.totalRecordsNotFiltered; // Update the total records not filtered
|
|
887
|
+
this.currentPage = body.page; // Update the current page
|
|
888
|
+
}
|
|
889
|
+
generateViewData() {
|
|
890
|
+
const view = this.tableService.viewGenerateData(this.dt, this.effectiveGlobalSearchText, this.currentPage, this.currentRowsPerPage, this.modifyFiltersWithoutGlobalAndSelectedRows.bind(this));
|
|
891
|
+
if (this.treeState) {
|
|
892
|
+
view.treeExpandedKeys = [...this.treeState.expanded];
|
|
893
|
+
view.treeChildPages = this.treeState.snapshotPages();
|
|
894
|
+
}
|
|
895
|
+
return view;
|
|
896
|
+
}
|
|
897
|
+
treeFetcher(query) {
|
|
898
|
+
return async (request) => {
|
|
899
|
+
const response = await firstValueFrom(this.tableService.fetchTableData(this.tableOptions.urlTableData, { ...structuredClone(query), ...request }).pipe(takeUntil(this.destroy$)));
|
|
900
|
+
if (!response.body)
|
|
901
|
+
throw new Error('Empty tree response.');
|
|
902
|
+
return response.body;
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
syncTreeRows() {
|
|
906
|
+
const tree = this.treeState;
|
|
907
|
+
this.tableOptions.data = tree.visible;
|
|
908
|
+
this.totalRecords = tree.totalRecords;
|
|
909
|
+
this.totalRecordsNotFiltered = tree.totalRecordsNotFiltered;
|
|
910
|
+
this.currentPage = tree.page;
|
|
911
|
+
this.changeDetector?.markForCheck();
|
|
912
|
+
}
|
|
913
|
+
async toggleTreeRow(event, row) {
|
|
914
|
+
event.stopPropagation();
|
|
915
|
+
if (!this.treeState || !this.treeQuery || this.treeState.loading)
|
|
916
|
+
return;
|
|
917
|
+
try {
|
|
918
|
+
const update = this.treeState.toggle(row, this.treeFetcher(this.treeQuery));
|
|
919
|
+
this.changeDetector?.markForCheck();
|
|
920
|
+
await update;
|
|
921
|
+
if (!this.destroyed)
|
|
922
|
+
this.syncTreeRows();
|
|
923
|
+
}
|
|
924
|
+
catch (error) {
|
|
925
|
+
if (!this.destroyed)
|
|
926
|
+
this.tableService.handleTableError(error, 'Tree data error');
|
|
927
|
+
}
|
|
928
|
+
finally {
|
|
929
|
+
if (!this.destroyed) {
|
|
930
|
+
this.changeDetector?.markForCheck();
|
|
931
|
+
this.onDataEndUpdate.emit();
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
async loadMoreTreeRows(event, row) {
|
|
936
|
+
event.stopPropagation();
|
|
937
|
+
if (!this.treeState || !this.treeQuery || this.treeState.loading)
|
|
938
|
+
return;
|
|
939
|
+
try {
|
|
940
|
+
await this.treeState.loadMore(row, this.treeFetcher(this.treeQuery));
|
|
941
|
+
if (!this.destroyed)
|
|
942
|
+
this.syncTreeRows();
|
|
943
|
+
}
|
|
944
|
+
catch (error) {
|
|
945
|
+
if (!this.destroyed)
|
|
946
|
+
this.tableService.handleTableError(error, 'Tree data error');
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
get treeColumn() {
|
|
950
|
+
const columns = this.tableOptions.columns?.shown ?? [];
|
|
951
|
+
return columns.find(column => column.field === this.treeState?.options.column)?.field ?? columns[0]?.field;
|
|
952
|
+
}
|
|
953
|
+
treePageChange(event) {
|
|
954
|
+
this.fetchTableData({ ...this.tableLazyLoadEventInformation, first: event.first ?? 0,
|
|
955
|
+
rows: event.rows ?? this.currentRowsPerPage });
|
|
956
|
+
}
|
|
957
|
+
clearFilters(dt, force = false, onlyGlobalFilter = false) {
|
|
958
|
+
this.cancelGlobalSearch();
|
|
959
|
+
let hasToClear = this.hasToClearFilters(dt, this.globalSearchText, force);
|
|
960
|
+
if (hasToClear) {
|
|
961
|
+
if (!onlyGlobalFilter) {
|
|
962
|
+
this.predefinedFiltersSelectedValuesCollection = {};
|
|
963
|
+
for (const key in dt.filters) {
|
|
964
|
+
if (dt.filters.hasOwnProperty(key)) {
|
|
965
|
+
const filters = dt.filters[key];
|
|
966
|
+
if (Array.isArray(filters)) {
|
|
967
|
+
filters.forEach(filter => {
|
|
968
|
+
filter.value = null; // Set value to null
|
|
969
|
+
});
|
|
970
|
+
}
|
|
971
|
+
else {
|
|
972
|
+
filters.value = null; // Set value to null
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
let filters = { ...this.dt.filters };
|
|
977
|
+
dt.columns?.forEach(element => {
|
|
978
|
+
dt.filter(null, element.field, element.matchMode);
|
|
979
|
+
});
|
|
980
|
+
this.dt.filters = filters;
|
|
981
|
+
}
|
|
982
|
+
this.restoreGlobalSearch(null);
|
|
983
|
+
if (this.globalSearchOption(this.tableOptions.globalFilter?.minLength) > 0 ||
|
|
984
|
+
this.globalSearchOption(this.tableOptions.globalFilter?.debounceTime) > 0) {
|
|
985
|
+
this.currentPage = 0;
|
|
986
|
+
dt.first = 0;
|
|
987
|
+
dt.filters = { ...dt.filters, global: { value: null, matchMode: 'contains' } };
|
|
988
|
+
this.fetchTableData({ ...this.tableLazyLoadEventInformation, first: 0,
|
|
989
|
+
rows: this.currentRowsPerPage, filters: dt.filters });
|
|
990
|
+
}
|
|
991
|
+
else
|
|
992
|
+
dt.filterGlobal('', '');
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
clearSorts(dt, force = false) {
|
|
996
|
+
let hasToClear = this.hasToClearSorts(dt, force);
|
|
997
|
+
if (hasToClear) {
|
|
998
|
+
dt.multiSortMeta = [];
|
|
999
|
+
dt.sortMultiple();
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
hasToClearSorts(dt, force = false) {
|
|
1003
|
+
let hasToClear = false;
|
|
1004
|
+
const hasSorts = (dt.multiSortMeta && dt.multiSortMeta.length > 0);
|
|
1005
|
+
if (force || hasSorts) {
|
|
1006
|
+
hasToClear = true;
|
|
1007
|
+
}
|
|
1008
|
+
return hasToClear;
|
|
1009
|
+
}
|
|
1010
|
+
hasToClearFilters(dt, globalSearchText, force = false) {
|
|
1011
|
+
let hasToClear = false;
|
|
1012
|
+
const filtersWithoutGlobalAndSelectedRows = this.modifyFiltersWithoutGlobalAndSelectedRows(dt.filters);
|
|
1013
|
+
const hasFilters = this.hasFilters(filtersWithoutGlobalAndSelectedRows);
|
|
1014
|
+
const hasGlobalFilter = (globalSearchText && globalSearchText.trim() !== "");
|
|
1015
|
+
if (force || hasFilters || hasGlobalFilter) {
|
|
1016
|
+
hasToClear = true;
|
|
1017
|
+
}
|
|
1018
|
+
return hasToClear;
|
|
1019
|
+
}
|
|
1020
|
+
/**
|
|
1021
|
+
* Determines whether there are active filters based on the provided filter rules.
|
|
1022
|
+
*
|
|
1023
|
+
* @param {any} filterRules An object representing filter rules for each column.
|
|
1024
|
+
* The keys are column names, and the values are arrays of filter rules.
|
|
1025
|
+
* Each filter rule has the following properties:
|
|
1026
|
+
* - `field`: The field or property name of the column.
|
|
1027
|
+
* - `value`: The filter value entered by the user.
|
|
1028
|
+
* - Other properties depending on the type of filter (e.g., `matchMode` for string filters).
|
|
1029
|
+
* @returns {boolean} `true` if at least one active filter is found, otherwise `false`.
|
|
1030
|
+
*/
|
|
1031
|
+
hasFilters(filterRules) {
|
|
1032
|
+
for (const columnName of Object.keys(filterRules)) { // Iterate over each column name in the filter rules
|
|
1033
|
+
const columnFilters = filterRules[columnName]; // Get the filter rules for the current column
|
|
1034
|
+
for (const filterRule of columnFilters) { // Iterate over each filter rule for the current column
|
|
1035
|
+
if (filterRule.value !== null && filterRule.value !== "") { // Check if the filter value is not null or an empty string
|
|
1036
|
+
return true; // At least one active filter found
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
return false; // No active filters found
|
|
1041
|
+
}
|
|
1042
|
+
getColumnStyle(col, headerCols = false) {
|
|
1043
|
+
return this.tableService.getColumnStyle(col, headerCols);
|
|
1044
|
+
}
|
|
1045
|
+
getPredefinedFilterValues(columnKeyName) {
|
|
1046
|
+
return this.tableOptions.predefinedFilters?.[columnKeyName] || []; // Return the predefined filter values or an empty array if the option name does not exist
|
|
1047
|
+
}
|
|
1048
|
+
getFrozenColumnAlignAsText(frozenColumnAlign) {
|
|
1049
|
+
return frozenColumnAlignAsText(frozenColumnAlign);
|
|
1050
|
+
}
|
|
1051
|
+
getDataTypeAsText(dataType) {
|
|
1052
|
+
return dataTypeAsText(dataType);
|
|
1053
|
+
}
|
|
1054
|
+
/**
|
|
1055
|
+
* Updates the filters of a PrimeNG data table based on predefined filter changes.
|
|
1056
|
+
*
|
|
1057
|
+
* @param {string} filterName - The name of the filter to be updated.
|
|
1058
|
+
* @param {IPrimengPredefinedFilter[]} selectedValues - An array of selected predefined filter values.
|
|
1059
|
+
*/
|
|
1060
|
+
onPredefinedFilterChange(filterName, selectedValues) {
|
|
1061
|
+
const filters = { ...this.dt.filters }; // Create a shallow copy of the current filters to avoid mutating the original filters directly
|
|
1062
|
+
const newValue = selectedValues && selectedValues.length ? selectedValues.map(value => value.value) : null; // Convert empty selection to null so PrimeNG removes the filter instead of applying an empty array
|
|
1063
|
+
if (Array.isArray(filters[filterName])) { // Check if the filter for the given filterName is an array
|
|
1064
|
+
filters[filterName].forEach(criteria => {
|
|
1065
|
+
criteria.value = newValue; // Update the value of each criteria with the values from selectedValues
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
else if (filters[filterName]) { // Check if the filter for the given filterName exists and is not an array
|
|
1069
|
+
const criteria = filters[filterName]; // Cast the filter criteria to FilterMetadata
|
|
1070
|
+
criteria.value = newValue; // Update the value of the criteria with the values from selectedValues
|
|
1071
|
+
}
|
|
1072
|
+
this.dt.filters = filters; // Update the data table's filters with the modified filters object
|
|
1073
|
+
this.dt._filter(); // Trigger the filtering operation on the data table to apply the new filters
|
|
1074
|
+
}
|
|
1075
|
+
/**
|
|
1076
|
+
* Checks if the provided column metadata matches a specific style of the predefined filters
|
|
1077
|
+
* that need to be applied to an item on a row.
|
|
1078
|
+
*
|
|
1079
|
+
* @param {IprimengColumnsMetadata} colMetadata - The metadata of the column being checked.
|
|
1080
|
+
* @param {any} value - The value to be matched against the predefined filter values.
|
|
1081
|
+
* @returns {any} The matching predefined filter value if found, otherwise null.
|
|
1082
|
+
*/
|
|
1083
|
+
getPredfinedFilterMatch(colMetadata, value) {
|
|
1084
|
+
if (colMetadata.filterPredefinedValuesName && colMetadata.filterPredefinedValuesName.length > 0) { // Check if the column uses predefined filter values
|
|
1085
|
+
const options = this.getPredefinedFilterValues(colMetadata.filterPredefinedValuesName); // Get the predefined filter values based on the name
|
|
1086
|
+
return options.find(option => option.value === value); // Return the matching option if found
|
|
1087
|
+
}
|
|
1088
|
+
return null; // Return null if the column does not use predefined filter values
|
|
1089
|
+
}
|
|
1090
|
+
copyToClipboardStart(event) {
|
|
1091
|
+
if ((this.tableOptions.copyToClipboardTime ?? 0) > 0) {
|
|
1092
|
+
const cellContent = event.target.innerText;
|
|
1093
|
+
this.copyCellDataTimer = setTimeout(() => {
|
|
1094
|
+
navigator.clipboard.writeText(cellContent).then(() => {
|
|
1095
|
+
this.notification.clearToasts();
|
|
1096
|
+
this.notification.showToast("info", this.i18n.text("CELL CONTENT COPIED"), this.i18n.text("The cell content has been copied to your clipboard."));
|
|
1097
|
+
}).catch(err => {
|
|
1098
|
+
this.notification.clearToasts();
|
|
1099
|
+
this.notification.showToast("error", this.i18n.text("CELL CONTENT COPIED"), this.i18n.text("The cell content failed to copy to your clipboard with error: {{value0}}", { value0: err }));
|
|
1100
|
+
});
|
|
1101
|
+
}, (this.tableOptions.copyToClipboardTime ?? 0) * 1000);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
copyToClipboardCancel() {
|
|
1105
|
+
if ((this.tableOptions.copyToClipboardTime ?? 0) > 0) {
|
|
1106
|
+
clearTimeout(this.copyCellDataTimer);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
getDataAlignHorizontalAsText(dataAlignHorizontal) {
|
|
1110
|
+
return dataAlignHorizontalAsText(dataAlignHorizontal);
|
|
1111
|
+
}
|
|
1112
|
+
getDataAlignVerticalAsText(dataAlignVertical) {
|
|
1113
|
+
return dataAlignVerticalAsText(dataAlignVertical);
|
|
1114
|
+
}
|
|
1115
|
+
isRowCheckboxSelected(rowID) {
|
|
1116
|
+
return this.selectedRowsCheckbox.includes(rowID);
|
|
1117
|
+
}
|
|
1118
|
+
get allMatchingRowsSelected() {
|
|
1119
|
+
if (!this.matchingSelectionKeys?.length)
|
|
1120
|
+
return false;
|
|
1121
|
+
const selected = new Set(this.selectedRowsCheckbox);
|
|
1122
|
+
return this.matchingSelectionKeys.every(key => selected.has(key));
|
|
1123
|
+
}
|
|
1124
|
+
get matchingRowsPartiallySelected() {
|
|
1125
|
+
if (this.allMatchingRowsSelected)
|
|
1126
|
+
return false;
|
|
1127
|
+
if (!this.matchingSelectionKeys)
|
|
1128
|
+
return this.selectedRowsCheckbox.length > 0;
|
|
1129
|
+
const selected = new Set(this.selectedRowsCheckbox);
|
|
1130
|
+
return this.matchingSelectionKeys.some(key => selected.has(key));
|
|
1131
|
+
}
|
|
1132
|
+
async toggleAllMatchingRows(checked) {
|
|
1133
|
+
const options = this.tableOptions.rows?.checkboxSelector;
|
|
1134
|
+
if (!options?.enabled || !options.selectAllEnabled || !options.urlSelectAll ||
|
|
1135
|
+
!this.selectionQuery || this.selectAllLoading)
|
|
1136
|
+
return;
|
|
1137
|
+
const queryKey = this.selectionQueryKey;
|
|
1138
|
+
this.selectAllLoading = true;
|
|
1139
|
+
try {
|
|
1140
|
+
const response = await firstValueFrom(this.tableService.fetchSelectionKeys(options.urlSelectAll, structuredClone(this.selectionQuery)).pipe(takeUntil(this.destroy$)));
|
|
1141
|
+
if (this.destroyed || queryKey !== this.selectionQueryKey)
|
|
1142
|
+
return;
|
|
1143
|
+
if (!Array.isArray(response.body) || response.body.some(key => typeof key !== 'string' && typeof key !== 'number'))
|
|
1144
|
+
throw new Error('Invalid selection identifiers.');
|
|
1145
|
+
const disabledKeys = new Set((this.tableOptions.data ?? [])
|
|
1146
|
+
.filter(row => !(options.enabledCondition?.(row) ?? true)).map(row => row.rowID));
|
|
1147
|
+
const keys = [...new Set(response.body)].filter(key => !disabledKeys.has(key));
|
|
1148
|
+
this.matchingSelectionKeys = keys;
|
|
1149
|
+
const selected = new Set(this.selectedRowsCheckbox);
|
|
1150
|
+
const changed = keys.filter(key => selected.has(key) !== checked);
|
|
1151
|
+
for (const key of changed) {
|
|
1152
|
+
if (checked)
|
|
1153
|
+
selected.add(key);
|
|
1154
|
+
else
|
|
1155
|
+
selected.delete(key);
|
|
1156
|
+
}
|
|
1157
|
+
this.selectedRowsCheckbox = [...selected];
|
|
1158
|
+
for (const rowID of changed)
|
|
1159
|
+
this.onRowCheckboxChange.emit({ rowID, selected: checked });
|
|
1160
|
+
}
|
|
1161
|
+
catch (error) {
|
|
1162
|
+
if (!this.destroyed)
|
|
1163
|
+
this.tableService.handleTableError(error, 'Selection error');
|
|
1164
|
+
}
|
|
1165
|
+
finally {
|
|
1166
|
+
this.selectAllLoading = false;
|
|
1167
|
+
this.changeDetector?.markForCheck();
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
onRowChekboxChange(event, rowID) {
|
|
1171
|
+
if (event.checked) { // Add the selected item
|
|
1172
|
+
if (!this.selectedRowsCheckbox.includes(rowID))
|
|
1173
|
+
this.selectedRowsCheckbox.push(rowID);
|
|
1174
|
+
}
|
|
1175
|
+
else { // Remove the selected item
|
|
1176
|
+
this.selectedRowsCheckbox = this.selectedRowsCheckbox.filter(selectedId => selectedId !== rowID);
|
|
1177
|
+
}
|
|
1178
|
+
this.onRowCheckboxChange.emit({
|
|
1179
|
+
rowID: rowID,
|
|
1180
|
+
selected: event.checked
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
rowSelect(event) {
|
|
1184
|
+
this.onRowSelect.emit({
|
|
1185
|
+
rowID: event.data.rowID,
|
|
1186
|
+
rowData: event.data
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
rowUnselect(event) {
|
|
1190
|
+
this.onRowUnselect.emit({
|
|
1191
|
+
rowID: event.data.rowID,
|
|
1192
|
+
rowData: event.data
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
pageChange(event) {
|
|
1196
|
+
this.currentPage = event.rows ? event.first / event.rows : 0;
|
|
1197
|
+
this.currentRowsPerPage = event.rows ? event.rows : 0;
|
|
1198
|
+
}
|
|
1199
|
+
columnSelectorShow() {
|
|
1200
|
+
this.tableOptions.columns?.selectorOrderByColumnName;
|
|
1201
|
+
let tempData = this.columns.map(column => {
|
|
1202
|
+
const isSelected = this.columnsSelected.some(selectedColumn => selectedColumn.field === column.field) || this.columnsCantBeHidden.some(selectedColumn => selectedColumn.field === column.field);
|
|
1203
|
+
const isSelectDisabled = this.columnsCantBeHidden.some(selectedColumn => selectedColumn.field === column.field);
|
|
1204
|
+
return {
|
|
1205
|
+
field: column.field,
|
|
1206
|
+
header: column.header,
|
|
1207
|
+
selected: isSelected,
|
|
1208
|
+
selectDisabled: isSelectDisabled,
|
|
1209
|
+
cellOverflowBehaviour: column.cellOverflowBehaviour,
|
|
1210
|
+
cellOverflowBehaviourDisabled: !column.cellOverflowBehaviourAllowUserEdit,
|
|
1211
|
+
dataAlignHorizontal: column.dataAlignHorizontal,
|
|
1212
|
+
dataAlignHorizontalDisabled: !column.dataAlignHorizontalAllowUserEdit,
|
|
1213
|
+
dataAlignVertical: column.dataAlignVertical,
|
|
1214
|
+
dataAlignVerticalDisabled: !column.dataAlignVerticalAllowUserEdit
|
|
1215
|
+
};
|
|
1216
|
+
});
|
|
1217
|
+
this.columnModalData = [...tempData];
|
|
1218
|
+
this.filteredColumnData = this.columnModalData;
|
|
1219
|
+
this.showColumnSelector = true;
|
|
1220
|
+
}
|
|
1221
|
+
applyColumnModalChanges(selectedColumns) {
|
|
1222
|
+
this.columnSelectionCustomized = true;
|
|
1223
|
+
const existingColumns = this.dt.columns;
|
|
1224
|
+
const columnsToKeep = new Set();
|
|
1225
|
+
this.columnsCantBeHidden.forEach(col => columnsToKeep.add(col.field));
|
|
1226
|
+
selectedColumns.forEach(col => columnsToKeep.add(col.field));
|
|
1227
|
+
const finalColumns = [];
|
|
1228
|
+
existingColumns.forEach(col => {
|
|
1229
|
+
if (columnsToKeep.has(col.field)) {
|
|
1230
|
+
finalColumns.push(col);
|
|
1231
|
+
}
|
|
1232
|
+
});
|
|
1233
|
+
selectedColumns.forEach(col => {
|
|
1234
|
+
const matchingColumn = this.columns.find(c => c.field === col.field);
|
|
1235
|
+
if (matchingColumn && !finalColumns.find(c => c.field === matchingColumn.field)) {
|
|
1236
|
+
finalColumns.push(matchingColumn);
|
|
1237
|
+
}
|
|
1238
|
+
});
|
|
1239
|
+
let prevColsToShow = this.tableOptions.columns.shown;
|
|
1240
|
+
this.tableOptions.columns.shown = this.tableService.orderColumnsWithFrozens(finalColumns);
|
|
1241
|
+
let sameColumnsAsBefore = prevColsToShow.length === this.tableOptions.columns.shown.length &&
|
|
1242
|
+
prevColsToShow.every((prevCol, index) => prevCol.field === this.tableOptions.columns.shown[index].field);
|
|
1243
|
+
this.columnsSelected = this.tableOptions.columns.shown.filter(column => !this.columnsCantBeHidden.some(nonSelectable => nonSelectable.field === column.field));
|
|
1244
|
+
this.updateColumnsSpecialProperties(this.columnModalData);
|
|
1245
|
+
if (!sameColumnsAsBefore) {
|
|
1246
|
+
this.tableOptions.isActive = false;
|
|
1247
|
+
this.clearSorts(this.dt, true);
|
|
1248
|
+
this.clearFilters(this.dt, true, false);
|
|
1249
|
+
setTimeout(() => {
|
|
1250
|
+
this.tableOptions.isActive = true;
|
|
1251
|
+
}, 1);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
updateColumnsSpecialProperties(columnsSource) {
|
|
1255
|
+
const allColumns = [this.columns, this.tableOptions.columns.shown, this.columnsSelected, this.columnsCantBeHidden];
|
|
1256
|
+
const columnModalDataMap = new Map(columnsSource.map((item) => [item.field, {
|
|
1257
|
+
cellOverflowBehaviour: item.cellOverflowBehaviour,
|
|
1258
|
+
dataAlignHorizontal: item.dataAlignHorizontal,
|
|
1259
|
+
dataAlignVertical: item.dataAlignVertical,
|
|
1260
|
+
width: item.width
|
|
1261
|
+
}]));
|
|
1262
|
+
const updatedFields = new Set(); // To track updated fields
|
|
1263
|
+
allColumns.forEach((columnList) => {
|
|
1264
|
+
columnList.forEach((col) => {
|
|
1265
|
+
if (columnModalDataMap.has(col.field) && !updatedFields.has(col.field)) {
|
|
1266
|
+
const columnData = columnModalDataMap.get(col.field);
|
|
1267
|
+
if (columnData) {
|
|
1268
|
+
col.cellOverflowBehaviour = columnData.cellOverflowBehaviour;
|
|
1269
|
+
col.dataAlignHorizontal = columnData.dataAlignHorizontal;
|
|
1270
|
+
col.dataAlignVertical = columnData.dataAlignVertical;
|
|
1271
|
+
col.width = columnData.width;
|
|
1272
|
+
updatedFields.add(col.field);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
});
|
|
1276
|
+
});
|
|
1277
|
+
}
|
|
1278
|
+
openExcelExport() {
|
|
1279
|
+
const defaultTitle = this.tableOptions.excelReport?.defaultTitle?.trim();
|
|
1280
|
+
const allowEdit = this.tableOptions.excelReport?.titleAllowUserEdit === true;
|
|
1281
|
+
this.excelReportTitle = this.i18n.text((!defaultTitle && !allowEdit) ? 'Report' : defaultTitle);
|
|
1282
|
+
this.showExportModal = true;
|
|
1283
|
+
}
|
|
1284
|
+
generateExcelReport(event) {
|
|
1285
|
+
if (!this.tableOptions.excelReport?.url?.trim()) {
|
|
1286
|
+
return;
|
|
1287
|
+
}
|
|
1288
|
+
let filtersWithoutGlobalAndSelectedRows = this.modifyFiltersWithoutGlobalAndSelectedRows(this.tableLazyLoadEventInformation.filters, event.selectedRows); // Create filters excluding the global filter
|
|
1289
|
+
filtersWithoutGlobalAndSelectedRows = this.revertDateTimeZoneFilters(filtersWithoutGlobalAndSelectedRows);
|
|
1290
|
+
const filtersMustBeApplied = (event.selectedRows === 1 || event.selectedRows === 2)
|
|
1291
|
+
? true
|
|
1292
|
+
: event.applyFilters;
|
|
1293
|
+
const requestData = {
|
|
1294
|
+
page: this.currentPage,
|
|
1295
|
+
pageSize: this.currentRowsPerPage,
|
|
1296
|
+
sort: this.tableLazyLoadEventInformation.multiSortMeta,
|
|
1297
|
+
filter: filtersWithoutGlobalAndSelectedRows,
|
|
1298
|
+
globalFilter: this.effectiveGlobalSearchText,
|
|
1299
|
+
columns: this.tableOptions.columns.shown.map(col => col.field),
|
|
1300
|
+
dateFormat: this.dateFormat,
|
|
1301
|
+
dateTimezone: this.dateTimezone,
|
|
1302
|
+
dateCulture: this.dateCulture,
|
|
1303
|
+
exportDateFormat: this.exportDateFormat,
|
|
1304
|
+
allColumns: event.allColumns,
|
|
1305
|
+
applyFilters: filtersMustBeApplied,
|
|
1306
|
+
applySorts: event.applySorts,
|
|
1307
|
+
filename: event.filename,
|
|
1308
|
+
useIconInBools: event.useIconInBools
|
|
1309
|
+
};
|
|
1310
|
+
if (this.treeState)
|
|
1311
|
+
Object.assign(requestData, { expandedKeys: [...this.treeState.expanded] });
|
|
1312
|
+
this.tableService.fetchExcelReport(this.tableOptions.excelReport.url, requestData).subscribe({
|
|
1313
|
+
next: (response) => {
|
|
1314
|
+
this.tableService.downloadFile(response.body, event.filename, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
|
|
1315
|
+
this.showExportModal = false;
|
|
1316
|
+
},
|
|
1317
|
+
error: (err) => this.tableService.handleTableError(err, 'Excel export error')
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
updateIconBlobsForCollections() {
|
|
1321
|
+
Object.keys(this.tableOptions.predefinedFilters ?? {}).forEach(key => {
|
|
1322
|
+
const filters = this.tableOptions.predefinedFilters?.[key];
|
|
1323
|
+
if (Array.isArray(filters) && filters.length > 0) {
|
|
1324
|
+
filters.forEach(filter => {
|
|
1325
|
+
if (filter.imageBlobSourceEndpoint && !filter.imageBlob) {
|
|
1326
|
+
filter.imageBlob = undefined;
|
|
1327
|
+
filter.imageBlobFetchError = false;
|
|
1328
|
+
this.tableService.getIconBlob(filter.imageBlobSourceEndpoint).subscribe({
|
|
1329
|
+
next: (response) => {
|
|
1330
|
+
filter.imageBlob = response.body;
|
|
1331
|
+
this.showExportModal = false;
|
|
1332
|
+
},
|
|
1333
|
+
error: () => {
|
|
1334
|
+
filter.imageBlobFetchError = true;
|
|
1335
|
+
}
|
|
1336
|
+
});
|
|
1337
|
+
}
|
|
1338
|
+
});
|
|
1339
|
+
}
|
|
1340
|
+
else {
|
|
1341
|
+
console.warn(`Filters for key ${key} is not an array:`, filters);
|
|
1342
|
+
}
|
|
1343
|
+
});
|
|
1344
|
+
}
|
|
1345
|
+
ecsTrack1(index, button) { return button; }
|
|
1346
|
+
ecsTrack2(index, button) { return index; }
|
|
1347
|
+
ecsTrack3(index, group) { return group.field; }
|
|
1348
|
+
ecsTrack4(index, col) { return col.header; }
|
|
1349
|
+
ecsTrack5(index, col) { return col.field; }
|
|
1350
|
+
}
|
|
1351
|
+
ECSPrimengTable.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ECSPrimengTable, deps: [{ token: i1.ECSPrimengTableService }, { token: i2.ECSPrimengTableNotificationService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1352
|
+
ECSPrimengTable.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: ECSPrimengTable, isStandalone: true, selector: "ecs-primeng-table", inputs: { tableOptions: "tableOptions" }, outputs: { onRowCheckboxChange: "onRowCheckboxChange", onRowSelect: "onRowSelect", onRowUnselect: "onRowUnselect", onDataEndUpdate: "onDataEndUpdate" }, host: { listeners: { "document:keydown.escape": "closeResponsiveMenus()", "window:resize": "onResize()" } }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }, { propertyName: "tableContainer", first: true, predicate: ["tableContainer"], descendants: true }, { propertyName: "headerContainer", first: true, predicate: ["headerContainer"], descendants: true }, { propertyName: "paginatorContainer", first: true, predicate: ["paginatorContainer"], descendants: true }, { propertyName: "responsiveHeaderMenu", first: true, predicate: ["responsiveHeaderMenu"], descendants: true }, { propertyName: "responsiveRowMenu", first: true, predicate: ["responsiveRowMenu"], descendants: true }], ngImport: i0, template: "<div #tableContainer>\r\n <p-table #dt\r\n styleClass=\"p-datatable-sm p-datatable-gridlines p-datatable-striped\"\r\n sortMode=\"multiple\"\r\n [resizableColumns]=\"true\" columnResizeMode=\"expand\"\r\n [reorderableColumns]=\"true\"\r\n [scrollable]=\"true\" [scrollHeight]=\"scrollHeightValue\"\r\n [columns]=\"tableOptions.columns?.shown ?? []\" [value]=\"tableOptions.data ?? []\" dataKey=\"rowID\" \r\n [paginator]=\"!treeState\" [loading]=\"treeState?.loading ?? false\" paginatorDropdownAppendTo=\"body\" [first]=\"currentPage * currentRowsPerPage\" [rows]=\"currentRowsPerPage\" [totalRecords]=\"totalRecords\"\r\n [rowsPerPageOptions]=\"allowedRowsPerPage\" [showCurrentPageReport]=\"false\" (onPage)=\"pageChange($event)\"\r\n [selectionMode]=\"tableOptions.rows?.singleSelector?.enabled ? 'single' : ''\" [metaKeySelection]=\"tableOptions.rows?.singleSelector?.metakey ?? true\" [(selection)]=\"rowSelection\" (onRowSelect)=\"rowSelect($event)\" (onRowUnselect)=\"rowUnselect($event)\"\r\n [lazy]=\"true\" (onLazyLoad)=\"fetchTableData($event)\">\r\n\r\n <!--TEMPLATE FOR THE ACTIONS HEADER COLUMN-->\r\n <ng-template #actionColumnHeaderTemplate>\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0\">\r\n <th [ngStyle]=\"{\r\n 'text-align': 'center',\r\n 'vertical-align': 'middle',\r\n 'max-width': actionColumnWidth + 'px',\r\n 'min-width': actionColumnWidth + 'px',\r\n 'width': actionColumnWidth + 'px'\r\n }\"\r\n pResizableColumn [pResizableColumnDisabled]=\"!tableOptions.rows?.action?.resizable\" pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\"\r\n [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.action?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\" id=\"actions-header\"\r\n [attr.scope]=\"'col'\">\r\n {{ (tableOptions.rows?.action?.header ?? '') | ecsTranslate }}\r\n </th>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!--TEMPLATE FOR THE ACTIONS ROW COLUMN-->\r\n <ng-template #actionColumnTemplate let-rowData=\"rowData\">\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0\">\r\n <td \r\n [ngStyle]=\"{\r\n 'text-align': (getDataAlignHorizontalAsText(tableOptions.rows?.action?.horizontalAlignment ?? DataAlignHorizontal.Center)),\r\n 'vertical-align': (getDataAlignVerticalAsText(tableOptions.rows?.action?.verticalAlignment ?? DataAlignVertical.Middle)),\r\n 'max-width': actionColumnWidth + 'px',\r\n 'min-width': actionColumnWidth + 'px',\r\n 'width': actionColumnWidth + 'px'\r\n }\"\r\n pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\"\r\n [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.action?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\">\r\n <ng-container *ngIf=\"compactRows; else ecsElse0\">\r\n <ng-container *ngIf=\"hasRowMenuActions(rowData)\">\r\n <button pButton type=\"button\" icon=\"pi pi-ellipsis-v\" [attr.aria-label]=\"(tableOptions.responsive?.rowMenuLabel || 'Row actions') | ecsTranslate\"\r\n aria-haspopup=\"menu\" [attr.aria-expanded]=\"responsiveRowMenu.visible && rowMenuRow === rowData\"\r\n (click)=\"openRowMenu($event, rowData)\" class=\"ecs-responsive-trigger\"></button>\r\n </ng-container>\r\n </ng-container><ng-template #ecsElse0>\r\n <ng-container *ngFor=\"let button of tableOptions.rows?.action?.buttons; trackBy: ecsTrack1; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count; let last = last\">\r\n <ecs-table-button [button]=\"button\" [rowData]=\"rowData\" [isActionButton]=\"true\" [isLastActionButton]=\"last\"></ecs-table-button>\r\n </ng-container>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!-- TEMPLATE FOR THE ROW CHECKBOX SELECTOR HEADER COLUMN -->\r\n <ng-template #rowSelectorColumnHeaderTemplate>\r\n <th \r\n [ngStyle]=\"{\r\n 'text-align': 'center',\r\n 'vertical-align': 'middle',\r\n 'max-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'min-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px'\r\n }\"\r\n id=\"rowSelector-header\" [attr.scope]=\"'col'\" pResizableColumn [pResizableColumnDisabled]=\"!tableOptions.rows?.checkboxSelector?.resizable\" pFrozenColumn \r\n [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.checkboxSelector?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\">\r\n <div style=\"display: flex; justify-content: space-between; align-items: center;\">\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.selectAllEnabled\">\r\n <input type=\"checkbox\" class=\"ecs-select-all\" [checked]=\"allMatchingRowsSelected\"\r\n [indeterminate]=\"matchingRowsPartiallySelected\"\r\n [disabled]=\"selectAllLoading || !tableOptions.rows?.checkboxSelector?.urlSelectAll\"\r\n [attr.aria-label]=\"'Select all filtered rows' | ecsTranslate\"\r\n [pTooltip]=\"'Select all filtered rows' | ecsTranslate\"\r\n (change)=\"toggleAllMatchingRows($any($event.target).checked)\">\r\n </ng-container>\r\n {{ (tableOptions.rows?.checkboxSelector?.header ?? '') | ecsTranslate }}\r\n <p-columnFilter type=\"boolean\" field=\"selector\" display=\"menu\" [showButtons]=\"false\"></p-columnFilter>\r\n </div>\r\n </th>\r\n </ng-template>\r\n\r\n <!--TEMPLATE FOR THE ROW CHECKBOX SELECTOR COLUMN-->\r\n <ng-template #rowSelectorColumnTemplate let-rowData=\"rowData\">\r\n <td \r\n [ngStyle]=\"{\r\n 'text-align': (getDataAlignHorizontalAsText(tableOptions.rows?.checkboxSelector?.horizontalAlignment ?? DataAlignHorizontal.Center)),\r\n 'vertical-align': (getDataAlignVerticalAsText(tableOptions.rows?.checkboxSelector?.verticalAlignment ?? DataAlignVertical.Middle)),\r\n 'max-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'min-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px'\r\n }\"\r\n pFrozenColumn [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" \r\n [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.checkboxSelector?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\">\r\n <p-checkbox \r\n [disabled]=\"!(tableOptions.rows?.checkboxSelector?.enabledCondition?.(rowData) ?? true)\"\r\n [binary]=\"true\"\r\n [ngModel]=\"isRowCheckboxSelected(rowData.rowID)\"\r\n (onChange)=\"onRowChekboxChange($event, rowData.rowID)\"></p-checkbox>\r\n </td>\r\n </ng-template>\r\n\r\n\r\n <!-- LOGIC FOR DRAWING TABLE ACTIONS ABOVE THE HEADER -->\r\n <ng-template pTemplate=\"caption\">\r\n <div #headerContainer [class.ecs-compact-header]=\"compactHeader\" style=\"display: flex; justify-content: space-between; align-items: center;\">\r\n <ng-container *ngIf=\"compactHeader; else ecsElse1\">\r\n <ng-container *ngIf=\"tableOptions.globalFilter?.enabled\">\r\n <span class=\"ecs-global-search ecs-responsive-search\">\r\n <span class=\"ecs-input-icon\"><i class=\"pi pi-search\"></i></span>\r\n <input pInputText type=\"text\" [attr.aria-label]=\"'Search keyword' | ecsTranslate\" [placeholder]=\"'Search keyword' | ecsTranslate\" autocomplete=\"off\"\r\n [maxlength]=\"tableOptions.globalFilter?.maxLength ?? null\" [ngModel]=\"globalSearchText\"\r\n (ngModelChange)=\"onGlobalSearchInput($event)\"/>\r\n <ng-container *ngIf=\"globalSearchText\">\r\n <span class=\"ecs-input-icon\" position=\"right\"><button type=\"button\" class=\"ecs-clear-search\" [attr.aria-label]=\"'Clear search' | ecsTranslate\" (click)=\"clearFilters(dt, true, true)\"><i class=\"pi pi-times\"></i></button></span>\r\n </ng-container>\r\n </span>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.description?.text\">\r\n <i [class]=\"tableOptions.description!.icon\" [pTooltip]=\"(tableOptions.description!.text) | ecsTranslate\" [escape]=\"false\"></i>\r\n </ng-container>\r\n <button pButton type=\"button\" icon=\"pi pi-bars\" [attr.aria-label]=\"(tableOptions.responsive?.headerMenuLabel || 'Table actions') | ecsTranslate\"\r\n aria-haspopup=\"menu\" [attr.aria-expanded]=\"responsiveHeaderMenu.visible\"\r\n (click)=\"openHeaderMenu($event)\" class=\"ecs-responsive-trigger ecs-header-menu-trigger\"></button>\r\n </ng-container><ng-template #ecsElse1>\r\n\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <!--CHOOSE COLUMNS TO SHOW-->\r\n <ng-container *ngIf=\"tableOptions.columns?.selectorEnabled\">\r\n <p-button [icon]=\"tableOptions.columns?.selectorIcon ?? 'pi pi-pencil'\" (onClick)=\"columnSelectorShow()\" [pTooltip]=\"'Modify columns' | ecsTranslate\"\r\n [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n <!--CLEAR SORTS AND FILTERS-->\r\n <ng-container *ngIf=\"tableOptions.header?.clearSortsEnabled\">\r\n <p-button [icon]=\"tableOptions.header?.clearSortsIcon ?? 'pi pi-sort-alt-slash'\" (onClick)=\"clearSorts(dt)\" [disabled]=\"!hasToClearSorts(dt)\"\r\n [pTooltip]=\"'Clear sorts' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.header?.clearFiltersEnabled\">\r\n <p-button\r\n [icon]=\"tableOptions.header?.clearFiltersIcon ?? 'pi pi-filter-slash'\" (onClick)=\"clearFilters(dt)\" [disabled]=\"!hasToClearFilters(dt, globalSearchText)\"\r\n [pTooltip]=\"'Clear filters' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n\r\n <!--TABLE DESCRIPTION-->\r\n <ng-container *ngIf=\"tableOptions.description?.text\"> <!-- If a table description text is provided -->\r\n <ng-container *ngIf=\"!tableOptions.description!.tooltip; else ecsElse2\"> <!-- The table description must be shown as text next to the icon -->\r\n <i [class]=\"tableOptions.description!.icon\"></i>\r\n <span [innerHTML]=\"(tableOptions.description!.text) | ecsTranslate\"></span>\r\n </ng-container><ng-template #ecsElse2>\r\n <i [escape]=\"false\" [pTooltip]=\"(tableOptions.description!.text) | ecsTranslate\" tooltipPosition=\"right\" [class]=\"tableOptions.description!.icon\"></i>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n\r\n <!--TABLE VIEWS-->\r\n <ng-container *ngIf=\"tableViewsEnabled()\">\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <span class=\"p-buttonset ecs-view-buttons\">\r\n <p-button (click)=\"viewsModalShow=true;\"\r\n [label]=\"tableViewCurrentSelectedAlias \r\n ? tableViewCurrentSelectedAlias \r\n : ((tableOptions.views?.noViewSelectedText || '--- Select a view ---') | ecsTranslate)\"\r\n [class]=\"'viewButton' + (tableOptions.views?.selectViewButtonClass ? ' ' + tableOptions.views!.selectViewButtonClass : '')\"></p-button>\r\n <p-button (click)=\"viewLoad(tableViewCurrentSelectedAlias!)\" [disabled]=\"!tableViewCurrentSelectedAlias\" [pTooltip]=\"'Apply view again' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\"\r\n [icon]=\"tableOptions.views?.reloadViewButtonIcon || 'pi pi-refresh'\"\r\n [class]=\"tableOptions.views?.reloadViewButtonClass || ''\"></p-button>\r\n </span>\r\n </div>\r\n </ng-container>\r\n\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <!--GLOBAL FILTER-->\r\n <ng-container *ngIf=\"tableOptions.globalFilter?.enabled\">\r\n <span class=\"ecs-global-search ml-auto\">\r\n <span class=\"ecs-input-icon\">\r\n <i class=\"pi pi-search\"></i>\r\n </span>\r\n <input pInputText type=\"text\" \r\n (ngModelChange)=\"onGlobalSearchInput($event)\" autocomplete=\"off\"\r\n [maxlength]=\"tableOptions.globalFilter?.maxLength ?? null\" [placeholder]=\"'Search keyword' | ecsTranslate\" [ngModel]=\"globalSearchText\"\r\n style=\"width: 220px;\"/>\r\n <!-- Right icon (only if there is text) -->\r\n <ng-container *ngIf=\"globalSearchText\">\r\n <span class=\"ecs-input-icon\" position=\"right\">\r\n <i class=\"pi pi-times\" style=\"cursor: pointer;\" (click)=\"clearFilters(dt, true, true); $event.stopPropagation()\"></i>\r\n </span>\r\n </ng-container>\r\n </span>\r\n </ng-container>\r\n\r\n <!--EXPORT DATA-->\r\n <ng-container *ngIf=\"tableOptions.excelReport?.url?.trim()\">\r\n <p-button icon=\"pi pi-file-excel\" (onClick)=\"openExcelExport()\"\r\n [pTooltip]=\"'Export to Excel' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n\r\n <!--RESET TABLE VIEW-->\r\n <ng-container *ngIf=\"tableOptions.resetTableView?.enabled\">\r\n <p-button [icon]=\"tableOptions.resetTableView?.icon ?? 'pi pi-eraser'\" (click)=\"resetTableView()\" [pTooltip]=\"'Reset table view' | ecsTranslate\" [showDelay]=\"700\"\r\n tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n\r\n <!--REFRESH DATA-->\r\n <p-button icon=\"pi pi-refresh\" (onClick)=\"refreshData($event)\" [pTooltip]=\"'Refresh data' | ecsTranslate\" [showDelay]=\"700\"\r\n tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n \r\n <!-- HEADER ACTION BUTTONS -->\r\n <ng-container *ngIf=\"(tableOptions.header?.buttons?.length ?? 0) > 0\">\r\n <td style=\"display: flex; justify-content: center; align-items: center; gap: 10px;\">\r\n <ng-container *ngFor=\"let button of tableOptions.header?.buttons; trackBy: ecsTrack2; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <ecs-table-button [button]=\"button\" [rowData]=\"null\"></ecs-table-button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- LOGIC FOR DRAWING TABLE HEADERS -->\r\n <ng-template pTemplate=\"header\" let-columns>\r\n <ng-container *ngIf=\"getColumnHeaderGroups(columns) as headerGroups\">\r\n <ng-container *ngIf=\"headerGroups.length\">\r\n <tr class=\"ecs-column-groups\">\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0 && !tableOptions.rows?.action?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\" alignFrozen=\"left\"\r\n [style.width.px]=\"actionColumnWidth\" [style.min-width.px]=\"actionColumnWidth\"></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && !tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" alignFrozen=\"left\"\r\n [style.width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\" [style.min-width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\"></td>\r\n </ng-container>\r\n <ng-container *ngFor=\"let group of headerGroups; trackBy: ecsTrack3; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <td [attr.colspan]=\"group.colspan\" role=\"columnheader\" [attr.aria-colspan]=\"group.colspan\" style=\"text-align: center; vertical-align: middle;\"\r\n pFrozenColumn [frozen]=\"group.frozenColumnAlign !== FrozenColumnAlign.Noone\"\r\n [alignFrozen]=\"getFrozenColumnAlignAsText(group.frozenColumnAlign)\">\r\n {{ group.label | translate }}\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" alignFrozen=\"right\"\r\n [style.width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\" [style.min-width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\"></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0 && tableOptions.rows?.action?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\" alignFrozen=\"right\"\r\n [style.width.px]=\"actionColumnWidth\" [style.min-width.px]=\"actionColumnWidth\"></td>\r\n </ng-container>\r\n </tr>\r\n </ng-container>\r\n <tr>\r\n <ng-container *ngIf=\"!tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && !tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let col of columns; trackBy: ecsTrack4; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <th [ngStyle]=\"getColumnStyle(col, true)\"\r\n pResizableColumn [pResizableColumnDisabled]=\"!col.canBeResized ? true : false\"\r\n pReorderableColumn [pReorderableColumnDisabled]=\"!col.canBeReordered ? true : false\"\r\n pFrozenColumn [frozen]=\"col.frozenColumnAlign === FrozenColumnAlign.Left || col.frozenColumnAlign === FrozenColumnAlign.Right\" [alignFrozen]=\"getFrozenColumnAlignAsText(col.frozenColumnAlign)\"\r\n [pSortableColumn]=\"col.field\" [pSortableColumnDisabled]=\"!col.canBeSorted ? true : false\"\r\n style=\"text-align: center;\"\r\n [id]=\"col.field + '-header'\" [attr.scope]=\"'col'\">\r\n <div style=\"display: flex; justify-content: space-between; align-items: center; width: 100%;\">\r\n <div style=\"margin-right: 15px;\">\r\n <span>{{ col.header | translate }}</span>\r\n </div>\r\n <div style=\"display: flex; align-items: center; gap: 5px;\">\r\n <ng-container *ngIf=\"col.canBeSorted\">\r\n <p-sortIcon [field]=\"col.field\"></p-sortIcon>\r\n </ng-container>\r\n <ng-container *ngIf=\"col.canBeFiltered\">\r\n <ng-container *ngIf=\"!col.filterPredefinedValuesName || col.filterPredefinedValuesName.length === 0; else ecsElse3\">\r\n <p-columnFilter [type]=\"getDataTypeAsText(col.dataType)\" [field]=\"col.field\" display=\"menu\" [showButtons]=\"false\" (click)=\"$event.stopPropagation()\"></p-columnFilter>\r\n </ng-container><ng-template #ecsElse3>\r\n <p-columnFilter\r\n [type]=\"getDataTypeAsText(col.dataType)\" [field]=\"col.field\" display=\"menu\"\r\n (click)=\"$event.stopPropagation()\"\r\n [showButtons]=\"false\" matchMode=\"in\" operator=\"or\" [showMatchModes]=\"false\"\r\n [showOperator]=\"false\" [showAddButton]=\"false\" [showClearButton]=\"false\" [showApplyButton]=\"false\">\r\n <ng-template pTemplate=\"filter\">\r\n <p-multiSelect\r\n [style]=\"{ minWidth: '400px' }\" [(ngModel)]=\"predefinedFiltersSelectedValuesCollection[col.filterPredefinedValuesName]\"\r\n [options]=\"getPredefinedFilterValues(col.filterPredefinedValuesName)\" [placeholder]=\"'Any value' | ecsTranslate\"\r\n (onChange)=\"onPredefinedFilterChange(col.field, $event.value)\" optionLabel=\"name\">\r\n <ng-template pTemplate=\"item\" let-option >\r\n <div style=\"display: inline-block; vertical-align: middle;\">\r\n <ecs-table-predefined-filters [option]=\"option\" [col]=\"col\" [selectable]=\"false\" [rowData]=\"null\"></ecs-table-predefined-filters>\r\n </div>\r\n </ng-template>\r\n </p-multiSelect>\r\n </ng-template>\r\n </p-columnFilter>\r\n </ng-template>\r\n </ng-container>\r\n <ng-container *ngIf=\"col.columnDescription && col.columnDescription.length > 0\">\r\n <i [pTooltip]=\"(col.columnDescription) | ecsTranslate\" tooltipPosition=\"top\" [class]=\"tableOptions.columnDescriptionIcon || 'pi pi-info-circle'\"></i>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </th>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!-- LOGIC FOR DRAWING TABLE DATA WHEN THERE IS CONTENTS -->\r\n <ng-template pTemplate=\"body\" let-rowData let-columns=\"columns\">\r\n <ng-container *ngIf=\"treeState?.isMore(rowData); else ecsElse4\">\r\n <tr class=\"ecs-tree-more-row\">\r\n <td colspan=\"999\">\r\n <p-button icon=\"pi pi-plus\" styleClass=\"p-button-text\" [label]=\"'Load more children' | ecsTranslate\"\r\n (onClick)=\"loadMoreTreeRows($event, rowData)\" ></p-button>\r\n </td>\r\n </tr>\r\n </ng-container><ng-template #ecsElse4>\r\n <tr [pSelectableRow]=\"rowData\" [ngClass]=\"tableOptions.rows?.class?.(rowData)\" [ngStyle]=\"tableOptions.rows?.style?.(rowData)\"\r\n [attr.aria-level]=\"treeState ? treeState.depth(rowData) + 1 : null\"\r\n [attr.aria-expanded]=\"treeState?.hasChildren(rowData) ? treeState?.isExpanded(rowData) : null\">\r\n <ng-container *ngIf=\"!tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnTemplate; context: { rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && !tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnTemplate\" [ngTemplateOutletContext]=\"{ rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let col of columns; trackBy: ecsTrack5; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <td (mousedown)=\"col.dataType !== DataType.Boolean && copyToClipboardStart($event)\" (mouseup)=\"copyToClipboardCancel()\"\r\n [ngStyle]=\"getColumnStyle(col)\" pFrozenColumn [frozen]=\"col.frozenColumnAlign === FrozenColumnAlign.Left || col.frozenColumnAlign === FrozenColumnAlign.Right\" \r\n [alignFrozen]=\"getFrozenColumnAlignAsText(col.frozenColumnAlign)\" [style.text-align]=\"getDataAlignHorizontalAsText(col.dataAlignHorizontal)\" [style.vertical-align]=\"getDataAlignVerticalAsText(col.dataAlignVertical)\">\r\n <ng-container *ngIf=\"treeState && col.field === treeColumn; else ecsElse5\">\r\n <div class=\"ecs-tree-cell\" [style.padding-inline-start.px]=\"treeState.depth(rowData) * 20\">\r\n <button type=\"button\" class=\"ecs-tree-toggle\" [class.ecs-tree-leaf]=\"!treeState.hasChildren(rowData)\"\r\n [disabled]=\"!treeState.hasChildren(rowData) || treeState.isLoading(rowData) || treeState.loading\"\r\n [attr.aria-label]=\"(treeState.isExpanded(rowData) ? 'Collapse node' : 'Expand node') | ecsTranslate\"\r\n [attr.aria-expanded]=\"treeState.hasChildren(rowData) ? treeState.isExpanded(rowData) : null\"\r\n [pTooltip]=\"(treeState.isExpanded(rowData) ? 'Collapse node' : 'Expand node') | ecsTranslate\"\r\n (mousedown)=\"$event.stopPropagation()\" (mouseup)=\"$event.stopPropagation()\"\r\n (click)=\"toggleTreeRow($event, rowData)\">\r\n <i [class]=\"treeState.isLoading(rowData) ? 'pi pi-spinner pi-spin' : treeState.isExpanded(rowData) ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\" aria-hidden=\"true\"></i>\r\n </button>\r\n <ecs-table-cell [col]=\"col\" [rowData]=\"rowData\" [globalSearchText]=\"effectiveGlobalSearchText\"\r\n [dateFormat]=\"dateFormat\" [dateTimezone]=\"dateTimezone\" [dateCulture]=\"dateCulture\"\r\n [predefinedFiltersCollection]=\"tableOptions.predefinedFilters\" ></ecs-table-cell>\r\n </div>\r\n </ng-container><ng-template #ecsElse5>\r\n <ecs-table-cell [col]=\"col\" [rowData]=\"rowData\" [globalSearchText]=\"effectiveGlobalSearchText\"\r\n [dateFormat]=\"dateFormat\" [dateTimezone]=\"dateTimezone\" [dateCulture]=\"dateCulture\"\r\n [predefinedFiltersCollection]=\"tableOptions.predefinedFilters\"></ecs-table-cell>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnTemplate\" [ngTemplateOutletContext]=\"{ rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnTemplate; context: { rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-template>\r\n </ng-template>\r\n\r\n <!-- LOGIC FOR DRAWING TABLE DATA WHEN THERE IS NO CONTENTS -->\r\n <ng-template pTemplate=\"emptymessage\">\r\n <tr>\r\n <td colspan=\"999\">{{ 'No data found for the current filter criteria.' | ecsTranslate }}</td>\r\n </tr>\r\n </ng-template>\r\n\r\n <!-- SHOW CUSTOM RECORDS REPORT -->\r\n <ng-template pTemplate=\"paginatorleft\">\r\n <div #paginatorContainer>\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <ng-container *ngIf=\"tableOptions.legend?.content\">\r\n <ecs-table-button [button]=\"tableOptions.legend?.button\" [rowData]=\"null\" [overrideAction]=\"op.toggle.bind(op)\"></ecs-table-button>\r\n <p-overlayPanel #op>\r\n <div [innerHTML]=\"(tableOptions.legend?.content) | ecsTranslate\"></div>\r\n </p-overlayPanel>\r\n </ng-container>\r\n <span>{{ 'Showing {{count}} records of {{total}} available records' | ecsTranslate: { count: totalRecords, total: totalRecordsNotFiltered } }}</span>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </p-table>\r\n <ng-container *ngIf=\"treeState\">\r\n <div #paginatorContainer class=\"ecs-tree-paginator\">\r\n <ng-container *ngIf=\"tableOptions.legend?.content\">\r\n <ecs-table-button [button]=\"tableOptions.legend?.button\" [rowData]=\"null\" [overrideAction]=\"treeLegend.toggle.bind(treeLegend)\" ></ecs-table-button>\r\n <p-overlayPanel #treeLegend><div [innerHTML]=\"(tableOptions.legend?.content) | ecsTranslate\"></div></p-overlayPanel>\r\n </ng-container>\r\n <span>{{ 'Showing {{count}} root nodes of {{total}} available root nodes' | ecsTranslate: { count: totalRecords, total: totalRecordsNotFiltered } }}</span>\r\n <p-paginator [first]=\"currentPage * currentRowsPerPage\" [rows]=\"currentRowsPerPage\" [totalRecords]=\"totalRecords\"\r\n [rowsPerPageOptions]=\"allowedRowsPerPage\" dropdownAppendTo=\"body\" (onPageChange)=\"treePageChange($event)\" ></p-paginator>\r\n </div>\r\n </ng-container>\r\n</div>\r\n<ecs-column-selector [visible]=\"showColumnSelector\" [columnModalData]=\"columnModalData\" [filteredColumnData]=\"filteredColumnData\" [orderByHeader]=\"tableOptions.columns?.selectorOrderByColumnName === true\" (visibleChange)=\"showColumnSelector=false\" (applyChanges)=\"applyColumnModalChanges($event)\"></ecs-column-selector>\r\n<ecs-export-excel [visible]=\"showExportModal\" [rowCheckboxSelectorActive]=\"tableOptions.rows?.checkboxSelector?.enabled ?? false\" [excelReportTitle]=\"excelReportTitle\" [allowTitleUserEdit]=\"tableOptions.excelReport?.titleAllowUserEdit ?? false\" (visibleChange)=\"showExportModal=false\" (exportToExcel)=\"generateExcelReport($event)\"></ecs-export-excel>\r\n<ecs-views-management [visible]=\"viewsModalShow\" [tableViews_menuItems]=\"tableViews_menuItems\" \r\n (onViewSelect)=\"viewLoad($event)\" (onViewCreate)=\"viewCreate($event)\" (onViewDelete)=\"viewDelete($event)\" (onViewEditAlias)=\"viewEditAlias($event)\" (onViewUpdateData)=\"viewUpdateData($event)\" (onViewUpdateActiveStartup)=\"viewUpdateActiveStartup($event)\"\r\n (visibleChange)=\"viewsModalShow=false\"></ecs-views-management>\r\n<!-- Body-level overlays avoid clipping inside scrollable and frozen table cells. -->\r\n<p-menu #responsiveHeaderMenu [model]=\"headerMenuItems\" [popup]=\"true\" appendTo=\"body\" styleClass=\"ecs-responsive-menu\"></p-menu>\r\n<p-menu #responsiveRowMenu [model]=\"rowMenuItems\" [popup]=\"true\" appendTo=\"body\" styleClass=\"ecs-responsive-menu\"></p-menu>\r\n", styles: [".highlighted-text{background-color:#ff0;color:#000;border-radius:2px}.excel-export-tooltip .bool-icon{text-shadow:0 0 2px white,0 0 3px white}.excel-export-tooltip .bool-true{color:green}.excel-export-tooltip .bool-false{color:red}.p-datatable-column-filter-button.p-button-icon-only.p-button-rounded,.p-datatable-column-filter-clear-button.p-button-icon-only.p-button-rounded{height:var(--p-icon-size)!important;width:var(--p-icon-size)!important;border-radius:0!important}.ecs-view-buttons{display:inline-flex;align-items:center;flex-wrap:nowrap}.ecs-view-buttons>p-button{display:inline-flex;flex:0 0 auto}.viewButton{width:200px}.viewButton .p-button{width:100%;justify-content:center}.viewButton .p-button-label{display:block;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.ecs-compact-header{gap:.5rem;min-width:0}.ecs-header-menu-trigger{margin-left:auto;flex:0 0 auto}.ecs-responsive-trigger{min-width:44px;min-height:44px}.ecs-global-search{display:inline-flex;align-items:center;gap:8px;min-width:0}.ecs-global-search>.ecs-input-icon{display:inline-flex;flex:0 0 auto}.ecs-global-search input{min-width:0}.ecs-responsive-search{flex:1 1 220px;min-width:0;max-width:320px}.ecs-responsive-search input{width:100%;padding-right:2.5rem}.ecs-clear-search{border:0;background:transparent;color:inherit;cursor:pointer}.ecs-responsive-menu{max-width:calc(100vw - 16px);max-height:calc(100dvh - 32px);overflow-y:auto}.ecs-responsive-menu .p-menu-item-link{min-height:44px;white-space:normal}.ecs-tree-cell{display:flex;align-items:center;gap:4px;min-width:0}.ecs-tree-cell>ecs-table-cell{flex:1;min-width:0}.ecs-tree-toggle{width:32px;height:32px;flex:0 0 32px;border:0;background:transparent;color:inherit;cursor:pointer}.ecs-tree-toggle:focus-visible{outline:2px solid var(--p-primary-color);outline-offset:1px}.ecs-tree-leaf{visibility:hidden}.ecs-tree-paginator{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.p-datatable-thead>.ecs-column-groups>td{padding:var(--p-datatable-header-cell-padding);background:var(--p-datatable-header-cell-background);color:var(--p-datatable-header-cell-color);font-weight:var(--p-datatable-column-title-font-weight);border:1px solid var(--p-datatable-header-cell-border-color);white-space:normal;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "pipe", type: ECSTableTranslatePipe, name: "ecsTranslate" }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i5.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: TableModule }, { kind: "component", type: i6.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "style", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "scrollDirection", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "responsive", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "autoLayout", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "groupRowsByOrder", "responsiveLayout", "breakpoint", "virtualRowHeight", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["selectAllChange", "selectionChange", "contextMenuSelectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i7.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i6.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i6.FrozenColumn, selector: "[pFrozenColumn]", inputs: ["frozen", "alignFrozen"] }, { kind: "directive", type: i6.SelectableRow, selector: "[pSelectableRow]", inputs: ["pSelectableRow", "pSelectableRowIndex", "pSelectableRowDisabled"] }, { kind: "directive", type: i6.ResizableColumn, selector: "[pResizableColumn]", inputs: ["pResizableColumnDisabled"] }, { kind: "directive", type: i6.ReorderableColumn, selector: "[pReorderableColumn]", inputs: ["pReorderableColumnDisabled"] }, { kind: "component", type: i6.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "component", type: i6.ColumnFilter, selector: "p-columnFilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "useGrouping", "showButtons"] }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i8.ButtonDirective, selector: "[pButton]", inputs: ["iconPos", "loadingIcon", "label", "icon", "loading"] }, { kind: "component", type: i8.Button, selector: "p-button", inputs: ["type", "iconPos", "icon", "badge", "label", "disabled", "loading", "loadingIcon", "style", "styleClass", "badgeClass", "ariaLabel"], outputs: ["onClick", "onFocus", "onBlur"] }, { kind: "ngmodule", type: TooltipModule }, { kind: "directive", type: i9.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "appendTo", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "fitContent", "pTooltip", "tooltipDisabled", "tooltipOptions"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i10.InputText, selector: "[pInputText]" }, { kind: "ngmodule", type: MultiSelectModule }, { kind: "component", type: i11.MultiSelect, selector: "p-multiSelect", inputs: ["style", "styleClass", "panelStyle", "panelStyleClass", "inputId", "disabled", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "appendTo", "dataKey", "name", "label", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions", "defaultLabel", "placeholder", "options", "filterValue", "itemSize"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad"] }, { kind: "ngmodule", type: CheckboxModule }, { kind: "component", type: i12.Checkbox, selector: "p-checkbox", inputs: ["value", "name", "disabled", "binary", "label", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "style", "styleClass", "labelStyleClass", "formControl", "checkboxIcon", "readonly", "required", "trueValue", "falseValue"], outputs: ["onChange"] }, { kind: "ngmodule", type: PaginatorModule }, { kind: "component", type: i13.Paginator, selector: "p-paginator", inputs: ["pageLinkSize", "style", "styleClass", "alwaysShow", "templateLeft", "templateRight", "dropdownAppendTo", "dropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showFirstLastIcon", "totalRecords", "rows", "rowsPerPageOptions", "showJumpToPageDropdown", "showJumpToPageInput", "showPageLinks", "dropdownItemTemplate", "first"], outputs: ["onPageChange"] }, { kind: "component", type: TableCell, selector: "ecs-table-cell", inputs: ["col", "rowData", "globalSearchText", "predefinedFiltersCollection", "dateFormat", "dateTimezone", "dateCulture"] }, { kind: "component", type: TablePredefinedFilters, selector: "ecs-table-predefined-filters", inputs: ["option", "col", "selectable", "rowData", "globalSearchText"] }, { kind: "component", type: TableButton, selector: "ecs-table-button", inputs: ["button", "rowData", "isActionButton", "isLastActionButton", "overrideAction"] }, { kind: "component", type: ColumnSelector, selector: "ecs-column-selector", inputs: ["orderByHeader", "visible", "columnModalData", "filteredColumnData"], outputs: ["visibleChange", "applyChanges"] }, { kind: "component", type: ExportExcel, selector: "ecs-export-excel", inputs: ["visible", "rowCheckboxSelectorActive", "excelReportTitle", "allowTitleUserEdit"], outputs: ["exportToExcel", "visibleChange"] }, { kind: "component", type: ViewsManagement, selector: "ecs-views-management", inputs: ["visible", "tableViews_menuItems"], outputs: ["onViewSelect", "onViewDelete", "onViewUpdateData", "onViewUpdateActiveStartup", "onViewEditAlias", "onViewCreate", "visibleChange"] }, { kind: "ngmodule", type: OverlayPanelModule }, { kind: "component", type: i14.OverlayPanel, selector: "p-overlayPanel", inputs: ["dismissable", "showCloseIcon", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }, { kind: "ngmodule", type: MenuModule }, { kind: "component", type: i15.Menu, selector: "p-menu", inputs: ["model", "popup", "style", "styleClass", "appendTo", "autoZIndex", "baseZIndex", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
1353
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ECSPrimengTable, decorators: [{
|
|
1354
|
+
type: Component,
|
|
1355
|
+
args: [{ selector: 'ecs-primeng-table', imports: [
|
|
1356
|
+
ECSTableTranslatePipe,
|
|
1357
|
+
TranslateModule,
|
|
1358
|
+
CommonModule,
|
|
1359
|
+
FormsModule,
|
|
1360
|
+
TableModule,
|
|
1361
|
+
ButtonModule,
|
|
1362
|
+
TooltipModule,
|
|
1363
|
+
InputTextModule,
|
|
1364
|
+
MultiSelectModule,
|
|
1365
|
+
CheckboxModule,
|
|
1366
|
+
PaginatorModule,
|
|
1367
|
+
TableCell,
|
|
1368
|
+
TablePredefinedFilters,
|
|
1369
|
+
TableButton,
|
|
1370
|
+
ColumnSelector,
|
|
1371
|
+
ExportExcel,
|
|
1372
|
+
ViewsManagement,
|
|
1373
|
+
OverlayPanelModule,
|
|
1374
|
+
MenuModule
|
|
1375
|
+
], standalone: true, encapsulation: ViewEncapsulation.None, template: "<div #tableContainer>\r\n <p-table #dt\r\n styleClass=\"p-datatable-sm p-datatable-gridlines p-datatable-striped\"\r\n sortMode=\"multiple\"\r\n [resizableColumns]=\"true\" columnResizeMode=\"expand\"\r\n [reorderableColumns]=\"true\"\r\n [scrollable]=\"true\" [scrollHeight]=\"scrollHeightValue\"\r\n [columns]=\"tableOptions.columns?.shown ?? []\" [value]=\"tableOptions.data ?? []\" dataKey=\"rowID\" \r\n [paginator]=\"!treeState\" [loading]=\"treeState?.loading ?? false\" paginatorDropdownAppendTo=\"body\" [first]=\"currentPage * currentRowsPerPage\" [rows]=\"currentRowsPerPage\" [totalRecords]=\"totalRecords\"\r\n [rowsPerPageOptions]=\"allowedRowsPerPage\" [showCurrentPageReport]=\"false\" (onPage)=\"pageChange($event)\"\r\n [selectionMode]=\"tableOptions.rows?.singleSelector?.enabled ? 'single' : ''\" [metaKeySelection]=\"tableOptions.rows?.singleSelector?.metakey ?? true\" [(selection)]=\"rowSelection\" (onRowSelect)=\"rowSelect($event)\" (onRowUnselect)=\"rowUnselect($event)\"\r\n [lazy]=\"true\" (onLazyLoad)=\"fetchTableData($event)\">\r\n\r\n <!--TEMPLATE FOR THE ACTIONS HEADER COLUMN-->\r\n <ng-template #actionColumnHeaderTemplate>\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0\">\r\n <th [ngStyle]=\"{\r\n 'text-align': 'center',\r\n 'vertical-align': 'middle',\r\n 'max-width': actionColumnWidth + 'px',\r\n 'min-width': actionColumnWidth + 'px',\r\n 'width': actionColumnWidth + 'px'\r\n }\"\r\n pResizableColumn [pResizableColumnDisabled]=\"!tableOptions.rows?.action?.resizable\" pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\"\r\n [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.action?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\" id=\"actions-header\"\r\n [attr.scope]=\"'col'\">\r\n {{ (tableOptions.rows?.action?.header ?? '') | ecsTranslate }}\r\n </th>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!--TEMPLATE FOR THE ACTIONS ROW COLUMN-->\r\n <ng-template #actionColumnTemplate let-rowData=\"rowData\">\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0\">\r\n <td \r\n [ngStyle]=\"{\r\n 'text-align': (getDataAlignHorizontalAsText(tableOptions.rows?.action?.horizontalAlignment ?? DataAlignHorizontal.Center)),\r\n 'vertical-align': (getDataAlignVerticalAsText(tableOptions.rows?.action?.verticalAlignment ?? DataAlignVertical.Middle)),\r\n 'max-width': actionColumnWidth + 'px',\r\n 'min-width': actionColumnWidth + 'px',\r\n 'width': actionColumnWidth + 'px'\r\n }\"\r\n pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\"\r\n [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.action?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\">\r\n <ng-container *ngIf=\"compactRows; else ecsElse0\">\r\n <ng-container *ngIf=\"hasRowMenuActions(rowData)\">\r\n <button pButton type=\"button\" icon=\"pi pi-ellipsis-v\" [attr.aria-label]=\"(tableOptions.responsive?.rowMenuLabel || 'Row actions') | ecsTranslate\"\r\n aria-haspopup=\"menu\" [attr.aria-expanded]=\"responsiveRowMenu.visible && rowMenuRow === rowData\"\r\n (click)=\"openRowMenu($event, rowData)\" class=\"ecs-responsive-trigger\"></button>\r\n </ng-container>\r\n </ng-container><ng-template #ecsElse0>\r\n <ng-container *ngFor=\"let button of tableOptions.rows?.action?.buttons; trackBy: ecsTrack1; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count; let last = last\">\r\n <ecs-table-button [button]=\"button\" [rowData]=\"rowData\" [isActionButton]=\"true\" [isLastActionButton]=\"last\"></ecs-table-button>\r\n </ng-container>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!-- TEMPLATE FOR THE ROW CHECKBOX SELECTOR HEADER COLUMN -->\r\n <ng-template #rowSelectorColumnHeaderTemplate>\r\n <th \r\n [ngStyle]=\"{\r\n 'text-align': 'center',\r\n 'vertical-align': 'middle',\r\n 'max-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'min-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px'\r\n }\"\r\n id=\"rowSelector-header\" [attr.scope]=\"'col'\" pResizableColumn [pResizableColumnDisabled]=\"!tableOptions.rows?.checkboxSelector?.resizable\" pFrozenColumn \r\n [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.checkboxSelector?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\">\r\n <div style=\"display: flex; justify-content: space-between; align-items: center;\">\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.selectAllEnabled\">\r\n <input type=\"checkbox\" class=\"ecs-select-all\" [checked]=\"allMatchingRowsSelected\"\r\n [indeterminate]=\"matchingRowsPartiallySelected\"\r\n [disabled]=\"selectAllLoading || !tableOptions.rows?.checkboxSelector?.urlSelectAll\"\r\n [attr.aria-label]=\"'Select all filtered rows' | ecsTranslate\"\r\n [pTooltip]=\"'Select all filtered rows' | ecsTranslate\"\r\n (change)=\"toggleAllMatchingRows($any($event.target).checked)\">\r\n </ng-container>\r\n {{ (tableOptions.rows?.checkboxSelector?.header ?? '') | ecsTranslate }}\r\n <p-columnFilter type=\"boolean\" field=\"selector\" display=\"menu\" [showButtons]=\"false\"></p-columnFilter>\r\n </div>\r\n </th>\r\n </ng-template>\r\n\r\n <!--TEMPLATE FOR THE ROW CHECKBOX SELECTOR COLUMN-->\r\n <ng-template #rowSelectorColumnTemplate let-rowData=\"rowData\">\r\n <td \r\n [ngStyle]=\"{\r\n 'text-align': (getDataAlignHorizontalAsText(tableOptions.rows?.checkboxSelector?.horizontalAlignment ?? DataAlignHorizontal.Center)),\r\n 'vertical-align': (getDataAlignVerticalAsText(tableOptions.rows?.checkboxSelector?.verticalAlignment ?? DataAlignVertical.Middle)),\r\n 'max-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'min-width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px',\r\n 'width': (tableOptions.rows?.checkboxSelector?.width ?? 150) + 'px'\r\n }\"\r\n pFrozenColumn [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" \r\n [alignFrozen]=\"getFrozenColumnAlignAsText(tableOptions.rows?.checkboxSelector?.positionRight ? FrozenColumnAlign.Right : FrozenColumnAlign.Left)\">\r\n <p-checkbox \r\n [disabled]=\"!(tableOptions.rows?.checkboxSelector?.enabledCondition?.(rowData) ?? true)\"\r\n [binary]=\"true\"\r\n [ngModel]=\"isRowCheckboxSelected(rowData.rowID)\"\r\n (onChange)=\"onRowChekboxChange($event, rowData.rowID)\"></p-checkbox>\r\n </td>\r\n </ng-template>\r\n\r\n\r\n <!-- LOGIC FOR DRAWING TABLE ACTIONS ABOVE THE HEADER -->\r\n <ng-template pTemplate=\"caption\">\r\n <div #headerContainer [class.ecs-compact-header]=\"compactHeader\" style=\"display: flex; justify-content: space-between; align-items: center;\">\r\n <ng-container *ngIf=\"compactHeader; else ecsElse1\">\r\n <ng-container *ngIf=\"tableOptions.globalFilter?.enabled\">\r\n <span class=\"ecs-global-search ecs-responsive-search\">\r\n <span class=\"ecs-input-icon\"><i class=\"pi pi-search\"></i></span>\r\n <input pInputText type=\"text\" [attr.aria-label]=\"'Search keyword' | ecsTranslate\" [placeholder]=\"'Search keyword' | ecsTranslate\" autocomplete=\"off\"\r\n [maxlength]=\"tableOptions.globalFilter?.maxLength ?? null\" [ngModel]=\"globalSearchText\"\r\n (ngModelChange)=\"onGlobalSearchInput($event)\"/>\r\n <ng-container *ngIf=\"globalSearchText\">\r\n <span class=\"ecs-input-icon\" position=\"right\"><button type=\"button\" class=\"ecs-clear-search\" [attr.aria-label]=\"'Clear search' | ecsTranslate\" (click)=\"clearFilters(dt, true, true)\"><i class=\"pi pi-times\"></i></button></span>\r\n </ng-container>\r\n </span>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.description?.text\">\r\n <i [class]=\"tableOptions.description!.icon\" [pTooltip]=\"(tableOptions.description!.text) | ecsTranslate\" [escape]=\"false\"></i>\r\n </ng-container>\r\n <button pButton type=\"button\" icon=\"pi pi-bars\" [attr.aria-label]=\"(tableOptions.responsive?.headerMenuLabel || 'Table actions') | ecsTranslate\"\r\n aria-haspopup=\"menu\" [attr.aria-expanded]=\"responsiveHeaderMenu.visible\"\r\n (click)=\"openHeaderMenu($event)\" class=\"ecs-responsive-trigger ecs-header-menu-trigger\"></button>\r\n </ng-container><ng-template #ecsElse1>\r\n\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <!--CHOOSE COLUMNS TO SHOW-->\r\n <ng-container *ngIf=\"tableOptions.columns?.selectorEnabled\">\r\n <p-button [icon]=\"tableOptions.columns?.selectorIcon ?? 'pi pi-pencil'\" (onClick)=\"columnSelectorShow()\" [pTooltip]=\"'Modify columns' | ecsTranslate\"\r\n [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n <!--CLEAR SORTS AND FILTERS-->\r\n <ng-container *ngIf=\"tableOptions.header?.clearSortsEnabled\">\r\n <p-button [icon]=\"tableOptions.header?.clearSortsIcon ?? 'pi pi-sort-alt-slash'\" (onClick)=\"clearSorts(dt)\" [disabled]=\"!hasToClearSorts(dt)\"\r\n [pTooltip]=\"'Clear sorts' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.header?.clearFiltersEnabled\">\r\n <p-button\r\n [icon]=\"tableOptions.header?.clearFiltersIcon ?? 'pi pi-filter-slash'\" (onClick)=\"clearFilters(dt)\" [disabled]=\"!hasToClearFilters(dt, globalSearchText)\"\r\n [pTooltip]=\"'Clear filters' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n\r\n <!--TABLE DESCRIPTION-->\r\n <ng-container *ngIf=\"tableOptions.description?.text\"> <!-- If a table description text is provided -->\r\n <ng-container *ngIf=\"!tableOptions.description!.tooltip; else ecsElse2\"> <!-- The table description must be shown as text next to the icon -->\r\n <i [class]=\"tableOptions.description!.icon\"></i>\r\n <span [innerHTML]=\"(tableOptions.description!.text) | ecsTranslate\"></span>\r\n </ng-container><ng-template #ecsElse2>\r\n <i [escape]=\"false\" [pTooltip]=\"(tableOptions.description!.text) | ecsTranslate\" tooltipPosition=\"right\" [class]=\"tableOptions.description!.icon\"></i>\r\n </ng-template>\r\n </ng-container>\r\n </div>\r\n\r\n <!--TABLE VIEWS-->\r\n <ng-container *ngIf=\"tableViewsEnabled()\">\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <span class=\"p-buttonset ecs-view-buttons\">\r\n <p-button (click)=\"viewsModalShow=true;\"\r\n [label]=\"tableViewCurrentSelectedAlias \r\n ? tableViewCurrentSelectedAlias \r\n : ((tableOptions.views?.noViewSelectedText || '--- Select a view ---') | ecsTranslate)\"\r\n [class]=\"'viewButton' + (tableOptions.views?.selectViewButtonClass ? ' ' + tableOptions.views!.selectViewButtonClass : '')\"></p-button>\r\n <p-button (click)=\"viewLoad(tableViewCurrentSelectedAlias!)\" [disabled]=\"!tableViewCurrentSelectedAlias\" [pTooltip]=\"'Apply view again' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\"\r\n [icon]=\"tableOptions.views?.reloadViewButtonIcon || 'pi pi-refresh'\"\r\n [class]=\"tableOptions.views?.reloadViewButtonClass || ''\"></p-button>\r\n </span>\r\n </div>\r\n </ng-container>\r\n\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <!--GLOBAL FILTER-->\r\n <ng-container *ngIf=\"tableOptions.globalFilter?.enabled\">\r\n <span class=\"ecs-global-search ml-auto\">\r\n <span class=\"ecs-input-icon\">\r\n <i class=\"pi pi-search\"></i>\r\n </span>\r\n <input pInputText type=\"text\" \r\n (ngModelChange)=\"onGlobalSearchInput($event)\" autocomplete=\"off\"\r\n [maxlength]=\"tableOptions.globalFilter?.maxLength ?? null\" [placeholder]=\"'Search keyword' | ecsTranslate\" [ngModel]=\"globalSearchText\"\r\n style=\"width: 220px;\"/>\r\n <!-- Right icon (only if there is text) -->\r\n <ng-container *ngIf=\"globalSearchText\">\r\n <span class=\"ecs-input-icon\" position=\"right\">\r\n <i class=\"pi pi-times\" style=\"cursor: pointer;\" (click)=\"clearFilters(dt, true, true); $event.stopPropagation()\"></i>\r\n </span>\r\n </ng-container>\r\n </span>\r\n </ng-container>\r\n\r\n <!--EXPORT DATA-->\r\n <ng-container *ngIf=\"tableOptions.excelReport?.url?.trim()\">\r\n <p-button icon=\"pi pi-file-excel\" (onClick)=\"openExcelExport()\"\r\n [pTooltip]=\"'Export to Excel' | ecsTranslate\" [showDelay]=\"700\" tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n\r\n <!--RESET TABLE VIEW-->\r\n <ng-container *ngIf=\"tableOptions.resetTableView?.enabled\">\r\n <p-button [icon]=\"tableOptions.resetTableView?.icon ?? 'pi pi-eraser'\" (click)=\"resetTableView()\" [pTooltip]=\"'Reset table view' | ecsTranslate\" [showDelay]=\"700\"\r\n tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n </ng-container>\r\n\r\n <!--REFRESH DATA-->\r\n <p-button icon=\"pi pi-refresh\" (onClick)=\"refreshData($event)\" [pTooltip]=\"'Refresh data' | ecsTranslate\" [showDelay]=\"700\"\r\n tooltipPosition=\"top\" styleClass=\"p-button-icon-only\"></p-button>\r\n \r\n <!-- HEADER ACTION BUTTONS -->\r\n <ng-container *ngIf=\"(tableOptions.header?.buttons?.length ?? 0) > 0\">\r\n <td style=\"display: flex; justify-content: center; align-items: center; gap: 10px;\">\r\n <ng-container *ngFor=\"let button of tableOptions.header?.buttons; trackBy: ecsTrack2; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <ecs-table-button [button]=\"button\" [rowData]=\"null\"></ecs-table-button>\r\n </ng-container>\r\n </td>\r\n </ng-container>\r\n </div>\r\n </ng-template>\r\n </div>\r\n </ng-template>\r\n\r\n <!-- LOGIC FOR DRAWING TABLE HEADERS -->\r\n <ng-template pTemplate=\"header\" let-columns>\r\n <ng-container *ngIf=\"getColumnHeaderGroups(columns) as headerGroups\">\r\n <ng-container *ngIf=\"headerGroups.length\">\r\n <tr class=\"ecs-column-groups\">\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0 && !tableOptions.rows?.action?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\" alignFrozen=\"left\"\r\n [style.width.px]=\"actionColumnWidth\" [style.min-width.px]=\"actionColumnWidth\"></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && !tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" alignFrozen=\"left\"\r\n [style.width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\" [style.min-width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\"></td>\r\n </ng-container>\r\n <ng-container *ngFor=\"let group of headerGroups; trackBy: ecsTrack3; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <td [attr.colspan]=\"group.colspan\" role=\"columnheader\" [attr.aria-colspan]=\"group.colspan\" style=\"text-align: center; vertical-align: middle;\"\r\n pFrozenColumn [frozen]=\"group.frozenColumnAlign !== FrozenColumnAlign.Noone\"\r\n [alignFrozen]=\"getFrozenColumnAlignAsText(group.frozenColumnAlign)\">\r\n {{ group.label | translate }}\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.checkboxSelector?.frozen ?? false\" alignFrozen=\"right\"\r\n [style.width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\" [style.min-width.px]=\"tableOptions.rows?.checkboxSelector?.width ?? 150\"></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"(tableOptions.rows?.action?.buttons?.length ?? 0) > 0 && tableOptions.rows?.action?.positionRight\">\r\n <td aria-hidden=\"true\" pFrozenColumn [frozen]=\"tableOptions.rows?.action?.frozen ?? false\" alignFrozen=\"right\"\r\n [style.width.px]=\"actionColumnWidth\" [style.min-width.px]=\"actionColumnWidth\"></td>\r\n </ng-container>\r\n </tr>\r\n </ng-container>\r\n <tr>\r\n <ng-container *ngIf=\"!tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && !tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let col of columns; trackBy: ecsTrack4; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <th [ngStyle]=\"getColumnStyle(col, true)\"\r\n pResizableColumn [pResizableColumnDisabled]=\"!col.canBeResized ? true : false\"\r\n pReorderableColumn [pReorderableColumnDisabled]=\"!col.canBeReordered ? true : false\"\r\n pFrozenColumn [frozen]=\"col.frozenColumnAlign === FrozenColumnAlign.Left || col.frozenColumnAlign === FrozenColumnAlign.Right\" [alignFrozen]=\"getFrozenColumnAlignAsText(col.frozenColumnAlign)\"\r\n [pSortableColumn]=\"col.field\" [pSortableColumnDisabled]=\"!col.canBeSorted ? true : false\"\r\n style=\"text-align: center;\"\r\n [id]=\"col.field + '-header'\" [attr.scope]=\"'col'\">\r\n <div style=\"display: flex; justify-content: space-between; align-items: center; width: 100%;\">\r\n <div style=\"margin-right: 15px;\">\r\n <span>{{ col.header | translate }}</span>\r\n </div>\r\n <div style=\"display: flex; align-items: center; gap: 5px;\">\r\n <ng-container *ngIf=\"col.canBeSorted\">\r\n <p-sortIcon [field]=\"col.field\"></p-sortIcon>\r\n </ng-container>\r\n <ng-container *ngIf=\"col.canBeFiltered\">\r\n <ng-container *ngIf=\"!col.filterPredefinedValuesName || col.filterPredefinedValuesName.length === 0; else ecsElse3\">\r\n <p-columnFilter [type]=\"getDataTypeAsText(col.dataType)\" [field]=\"col.field\" display=\"menu\" [showButtons]=\"false\" (click)=\"$event.stopPropagation()\"></p-columnFilter>\r\n </ng-container><ng-template #ecsElse3>\r\n <p-columnFilter\r\n [type]=\"getDataTypeAsText(col.dataType)\" [field]=\"col.field\" display=\"menu\"\r\n (click)=\"$event.stopPropagation()\"\r\n [showButtons]=\"false\" matchMode=\"in\" operator=\"or\" [showMatchModes]=\"false\"\r\n [showOperator]=\"false\" [showAddButton]=\"false\" [showClearButton]=\"false\" [showApplyButton]=\"false\">\r\n <ng-template pTemplate=\"filter\">\r\n <p-multiSelect\r\n [style]=\"{ minWidth: '400px' }\" [(ngModel)]=\"predefinedFiltersSelectedValuesCollection[col.filterPredefinedValuesName]\"\r\n [options]=\"getPredefinedFilterValues(col.filterPredefinedValuesName)\" [placeholder]=\"'Any value' | ecsTranslate\"\r\n (onChange)=\"onPredefinedFilterChange(col.field, $event.value)\" optionLabel=\"name\">\r\n <ng-template pTemplate=\"item\" let-option >\r\n <div style=\"display: inline-block; vertical-align: middle;\">\r\n <ecs-table-predefined-filters [option]=\"option\" [col]=\"col\" [selectable]=\"false\" [rowData]=\"null\"></ecs-table-predefined-filters>\r\n </div>\r\n </ng-template>\r\n </p-multiSelect>\r\n </ng-template>\r\n </p-columnFilter>\r\n </ng-template>\r\n </ng-container>\r\n <ng-container *ngIf=\"col.columnDescription && col.columnDescription.length > 0\">\r\n <i [pTooltip]=\"(col.columnDescription) | ecsTranslate\" tooltipPosition=\"top\" [class]=\"tableOptions.columnDescriptionIcon || 'pi pi-info-circle'\"></i>\r\n </ng-container>\r\n </div>\r\n </div>\r\n </th>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnHeaderTemplate\"></ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-container>\r\n </ng-template>\r\n\r\n <!-- LOGIC FOR DRAWING TABLE DATA WHEN THERE IS CONTENTS -->\r\n <ng-template pTemplate=\"body\" let-rowData let-columns=\"columns\">\r\n <ng-container *ngIf=\"treeState?.isMore(rowData); else ecsElse4\">\r\n <tr class=\"ecs-tree-more-row\">\r\n <td colspan=\"999\">\r\n <p-button icon=\"pi pi-plus\" styleClass=\"p-button-text\" [label]=\"'Load more children' | ecsTranslate\"\r\n (onClick)=\"loadMoreTreeRows($event, rowData)\" ></p-button>\r\n </td>\r\n </tr>\r\n </ng-container><ng-template #ecsElse4>\r\n <tr [pSelectableRow]=\"rowData\" [ngClass]=\"tableOptions.rows?.class?.(rowData)\" [ngStyle]=\"tableOptions.rows?.style?.(rowData)\"\r\n [attr.aria-level]=\"treeState ? treeState.depth(rowData) + 1 : null\"\r\n [attr.aria-expanded]=\"treeState?.hasChildren(rowData) ? treeState?.isExpanded(rowData) : null\">\r\n <ng-container *ngIf=\"!tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnTemplate; context: { rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && !tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnTemplate\" [ngTemplateOutletContext]=\"{ rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let col of columns; trackBy: ecsTrack5; let $index = index; let $first = first; let $last = last; let $even = even; let $odd = odd; let $count = count\">\r\n <td (mousedown)=\"col.dataType !== DataType.Boolean && copyToClipboardStart($event)\" (mouseup)=\"copyToClipboardCancel()\"\r\n [ngStyle]=\"getColumnStyle(col)\" pFrozenColumn [frozen]=\"col.frozenColumnAlign === FrozenColumnAlign.Left || col.frozenColumnAlign === FrozenColumnAlign.Right\" \r\n [alignFrozen]=\"getFrozenColumnAlignAsText(col.frozenColumnAlign)\" [style.text-align]=\"getDataAlignHorizontalAsText(col.dataAlignHorizontal)\" [style.vertical-align]=\"getDataAlignVerticalAsText(col.dataAlignVertical)\">\r\n <ng-container *ngIf=\"treeState && col.field === treeColumn; else ecsElse5\">\r\n <div class=\"ecs-tree-cell\" [style.padding-inline-start.px]=\"treeState.depth(rowData) * 20\">\r\n <button type=\"button\" class=\"ecs-tree-toggle\" [class.ecs-tree-leaf]=\"!treeState.hasChildren(rowData)\"\r\n [disabled]=\"!treeState.hasChildren(rowData) || treeState.isLoading(rowData) || treeState.loading\"\r\n [attr.aria-label]=\"(treeState.isExpanded(rowData) ? 'Collapse node' : 'Expand node') | ecsTranslate\"\r\n [attr.aria-expanded]=\"treeState.hasChildren(rowData) ? treeState.isExpanded(rowData) : null\"\r\n [pTooltip]=\"(treeState.isExpanded(rowData) ? 'Collapse node' : 'Expand node') | ecsTranslate\"\r\n (mousedown)=\"$event.stopPropagation()\" (mouseup)=\"$event.stopPropagation()\"\r\n (click)=\"toggleTreeRow($event, rowData)\">\r\n <i [class]=\"treeState.isLoading(rowData) ? 'pi pi-spinner pi-spin' : treeState.isExpanded(rowData) ? 'pi pi-chevron-down' : 'pi pi-chevron-right'\" aria-hidden=\"true\"></i>\r\n </button>\r\n <ecs-table-cell [col]=\"col\" [rowData]=\"rowData\" [globalSearchText]=\"effectiveGlobalSearchText\"\r\n [dateFormat]=\"dateFormat\" [dateTimezone]=\"dateTimezone\" [dateCulture]=\"dateCulture\"\r\n [predefinedFiltersCollection]=\"tableOptions.predefinedFilters\" ></ecs-table-cell>\r\n </div>\r\n </ng-container><ng-template #ecsElse5>\r\n <ecs-table-cell [col]=\"col\" [rowData]=\"rowData\" [globalSearchText]=\"effectiveGlobalSearchText\"\r\n [dateFormat]=\"dateFormat\" [dateTimezone]=\"dateTimezone\" [dateCulture]=\"dateCulture\"\r\n [predefinedFiltersCollection]=\"tableOptions.predefinedFilters\"></ecs-table-cell>\r\n </ng-template>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.checkboxSelector?.enabled && tableOptions.rows?.checkboxSelector?.positionRight\">\r\n <ng-container [ngTemplateOutlet]=\"rowSelectorColumnTemplate\" [ngTemplateOutletContext]=\"{ rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"tableOptions.rows?.action?.positionRight\">\r\n <ng-container *ngTemplateOutlet=\"actionColumnTemplate; context: { rowData: rowData }\"></ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-template>\r\n </ng-template>\r\n\r\n <!-- LOGIC FOR DRAWING TABLE DATA WHEN THERE IS NO CONTENTS -->\r\n <ng-template pTemplate=\"emptymessage\">\r\n <tr>\r\n <td colspan=\"999\">{{ 'No data found for the current filter criteria.' | ecsTranslate }}</td>\r\n </tr>\r\n </ng-template>\r\n\r\n <!-- SHOW CUSTOM RECORDS REPORT -->\r\n <ng-template pTemplate=\"paginatorleft\">\r\n <div #paginatorContainer>\r\n <div style=\"display: flex; align-items: center; gap: 10px;\">\r\n <ng-container *ngIf=\"tableOptions.legend?.content\">\r\n <ecs-table-button [button]=\"tableOptions.legend?.button\" [rowData]=\"null\" [overrideAction]=\"op.toggle.bind(op)\"></ecs-table-button>\r\n <p-overlayPanel #op>\r\n <div [innerHTML]=\"(tableOptions.legend?.content) | ecsTranslate\"></div>\r\n </p-overlayPanel>\r\n </ng-container>\r\n <span>{{ 'Showing {{count}} records of {{total}} available records' | ecsTranslate: { count: totalRecords, total: totalRecordsNotFiltered } }}</span>\r\n </div>\r\n </div>\r\n </ng-template>\r\n </p-table>\r\n <ng-container *ngIf=\"treeState\">\r\n <div #paginatorContainer class=\"ecs-tree-paginator\">\r\n <ng-container *ngIf=\"tableOptions.legend?.content\">\r\n <ecs-table-button [button]=\"tableOptions.legend?.button\" [rowData]=\"null\" [overrideAction]=\"treeLegend.toggle.bind(treeLegend)\" ></ecs-table-button>\r\n <p-overlayPanel #treeLegend><div [innerHTML]=\"(tableOptions.legend?.content) | ecsTranslate\"></div></p-overlayPanel>\r\n </ng-container>\r\n <span>{{ 'Showing {{count}} root nodes of {{total}} available root nodes' | ecsTranslate: { count: totalRecords, total: totalRecordsNotFiltered } }}</span>\r\n <p-paginator [first]=\"currentPage * currentRowsPerPage\" [rows]=\"currentRowsPerPage\" [totalRecords]=\"totalRecords\"\r\n [rowsPerPageOptions]=\"allowedRowsPerPage\" dropdownAppendTo=\"body\" (onPageChange)=\"treePageChange($event)\" ></p-paginator>\r\n </div>\r\n </ng-container>\r\n</div>\r\n<ecs-column-selector [visible]=\"showColumnSelector\" [columnModalData]=\"columnModalData\" [filteredColumnData]=\"filteredColumnData\" [orderByHeader]=\"tableOptions.columns?.selectorOrderByColumnName === true\" (visibleChange)=\"showColumnSelector=false\" (applyChanges)=\"applyColumnModalChanges($event)\"></ecs-column-selector>\r\n<ecs-export-excel [visible]=\"showExportModal\" [rowCheckboxSelectorActive]=\"tableOptions.rows?.checkboxSelector?.enabled ?? false\" [excelReportTitle]=\"excelReportTitle\" [allowTitleUserEdit]=\"tableOptions.excelReport?.titleAllowUserEdit ?? false\" (visibleChange)=\"showExportModal=false\" (exportToExcel)=\"generateExcelReport($event)\"></ecs-export-excel>\r\n<ecs-views-management [visible]=\"viewsModalShow\" [tableViews_menuItems]=\"tableViews_menuItems\" \r\n (onViewSelect)=\"viewLoad($event)\" (onViewCreate)=\"viewCreate($event)\" (onViewDelete)=\"viewDelete($event)\" (onViewEditAlias)=\"viewEditAlias($event)\" (onViewUpdateData)=\"viewUpdateData($event)\" (onViewUpdateActiveStartup)=\"viewUpdateActiveStartup($event)\"\r\n (visibleChange)=\"viewsModalShow=false\"></ecs-views-management>\r\n<!-- Body-level overlays avoid clipping inside scrollable and frozen table cells. -->\r\n<p-menu #responsiveHeaderMenu [model]=\"headerMenuItems\" [popup]=\"true\" appendTo=\"body\" styleClass=\"ecs-responsive-menu\"></p-menu>\r\n<p-menu #responsiveRowMenu [model]=\"rowMenuItems\" [popup]=\"true\" appendTo=\"body\" styleClass=\"ecs-responsive-menu\"></p-menu>\r\n", styles: [".highlighted-text{background-color:#ff0;color:#000;border-radius:2px}.excel-export-tooltip .bool-icon{text-shadow:0 0 2px white,0 0 3px white}.excel-export-tooltip .bool-true{color:green}.excel-export-tooltip .bool-false{color:red}.p-datatable-column-filter-button.p-button-icon-only.p-button-rounded,.p-datatable-column-filter-clear-button.p-button-icon-only.p-button-rounded{height:var(--p-icon-size)!important;width:var(--p-icon-size)!important;border-radius:0!important}.ecs-view-buttons{display:inline-flex;align-items:center;flex-wrap:nowrap}.ecs-view-buttons>p-button{display:inline-flex;flex:0 0 auto}.viewButton{width:200px}.viewButton .p-button{width:100%;justify-content:center}.viewButton .p-button-label{display:block;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:center}.ecs-compact-header{gap:.5rem;min-width:0}.ecs-header-menu-trigger{margin-left:auto;flex:0 0 auto}.ecs-responsive-trigger{min-width:44px;min-height:44px}.ecs-global-search{display:inline-flex;align-items:center;gap:8px;min-width:0}.ecs-global-search>.ecs-input-icon{display:inline-flex;flex:0 0 auto}.ecs-global-search input{min-width:0}.ecs-responsive-search{flex:1 1 220px;min-width:0;max-width:320px}.ecs-responsive-search input{width:100%;padding-right:2.5rem}.ecs-clear-search{border:0;background:transparent;color:inherit;cursor:pointer}.ecs-responsive-menu{max-width:calc(100vw - 16px);max-height:calc(100dvh - 32px);overflow-y:auto}.ecs-responsive-menu .p-menu-item-link{min-height:44px;white-space:normal}.ecs-tree-cell{display:flex;align-items:center;gap:4px;min-width:0}.ecs-tree-cell>ecs-table-cell{flex:1;min-width:0}.ecs-tree-toggle{width:32px;height:32px;flex:0 0 32px;border:0;background:transparent;color:inherit;cursor:pointer}.ecs-tree-toggle:focus-visible{outline:2px solid var(--p-primary-color);outline-offset:1px}.ecs-tree-leaf{visibility:hidden}.ecs-tree-paginator{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:8px}.p-datatable-thead>.ecs-column-groups>td{padding:var(--p-datatable-header-cell-padding);background:var(--p-datatable-header-cell-background);color:var(--p-datatable-header-cell-color);font-weight:var(--p-datatable-column-title-font-weight);border:1px solid var(--p-datatable-header-cell-border-color);white-space:normal;overflow-wrap:anywhere}\n"] }]
|
|
1376
|
+
}], ctorParameters: function () { return [{ type: i1.ECSPrimengTableService }, { type: i2.ECSPrimengTableNotificationService }]; }, propDecorators: { tableOptions: [{
|
|
1377
|
+
type: Input
|
|
1378
|
+
}], onRowCheckboxChange: [{
|
|
1379
|
+
type: Output
|
|
1380
|
+
}], onRowSelect: [{
|
|
1381
|
+
type: Output
|
|
1382
|
+
}], onRowUnselect: [{
|
|
1383
|
+
type: Output
|
|
1384
|
+
}], onDataEndUpdate: [{
|
|
1385
|
+
type: Output
|
|
1386
|
+
}], dt: [{
|
|
1387
|
+
type: ViewChild,
|
|
1388
|
+
args: ['dt']
|
|
1389
|
+
}], tableContainer: [{
|
|
1390
|
+
type: ViewChild,
|
|
1391
|
+
args: ['tableContainer', { static: false }]
|
|
1392
|
+
}], headerContainer: [{
|
|
1393
|
+
type: ViewChild,
|
|
1394
|
+
args: ['headerContainer', { static: false }]
|
|
1395
|
+
}], paginatorContainer: [{
|
|
1396
|
+
type: ViewChild,
|
|
1397
|
+
args: ['paginatorContainer', { static: false }]
|
|
1398
|
+
}], responsiveHeaderMenu: [{
|
|
1399
|
+
type: ViewChild,
|
|
1400
|
+
args: ['responsiveHeaderMenu']
|
|
1401
|
+
}], responsiveRowMenu: [{
|
|
1402
|
+
type: ViewChild,
|
|
1403
|
+
args: ['responsiveRowMenu']
|
|
1404
|
+
}], closeResponsiveMenus: [{
|
|
1405
|
+
type: HostListener,
|
|
1406
|
+
args: ['document:keydown.escape']
|
|
1407
|
+
}], onResize: [{
|
|
1408
|
+
type: HostListener,
|
|
1409
|
+
args: ['window:resize']
|
|
1410
|
+
}] } });
|
|
1411
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWNzLXByaW1lbmctdGFibGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lY3MtcHJpbWVuZy10YWJsZS9zcmMvbGliL2NvbXBvbmVudHMvZWNzLXByaW1lbmctdGFibGUvZWNzLXByaW1lbmctdGFibGUudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lY3MtcHJpbWVuZy10YWJsZS9zcmMvbGliL2NvbXBvbmVudHMvZWNzLXByaW1lbmctdGFibGUvZWNzLXByaW1lbmctdGFibGUuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN6RSxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUN0RSxPQUFPLEVBQWlCLFNBQVMsRUFBYyxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBcUIsaUJBQWlCLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDNUwsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHN0Msa0JBQWtCO0FBQ2xCLE9BQU8sRUFBUyxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDcEQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGNBQWMs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QUFVOzRGQU9ELGVBQWU7a0JBNUIzQixTQUFTOytCQUNFLG1CQUFtQixXQUNwQjt3QkFDUCxxQkFBcUI7d0JBQ3JCLGVBQWU7d0JBQ2YsWUFBWTt3QkFDWixXQUFXO3dCQUNYLFdBQVc7d0JBQ1gsWUFBWTt3QkFDWixhQUFhO3dCQUNiLGVBQWU7d0JBQ2YsaUJBQWlCO3dCQUNqQixjQUFjO3dCQUNkLGVBQWU7d0JBQ2YsU0FBUzt3QkFDVCxzQkFBc0I7d0JBQ3RCLFdBQVc7d0JBQ1gsY0FBYzt3QkFDZCxXQUFXO3dCQUNYLGVBQWU7d0JBQ2Ysa0JBQWtCO3dCQUNsQixVQUFVO3FCQUNYLGNBQ1csSUFBSSxpQkFHRCxpQkFBaUIsQ0FBQyxJQUFJOzhKQW9CNUIsWUFBWTtzQkFBcEIsS0FBSztnQkFJSSxtQkFBbUI7c0JBQTVCLE1BQU07Z0JBSUcsV0FBVztzQkFBcEIsTUFBTTtnQkFJRyxhQUFhO3NCQUF0QixNQUFNO2dCQUlHLGVBQWU7c0JBQXhCLE1BQU07Z0JBWVUsRUFBRTtzQkFBbEIsU0FBUzt1QkFBQyxJQUFJO2dCQW1HaUMsY0FBYztzQkFBN0QsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBQ0csZUFBZTtzQkFBL0QsU0FBUzt1QkFBQyxpQkFBaUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBQ0ssa0JBQWtCO3NCQUFyRSxTQUFTO3VCQUFDLG9CQUFvQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFXZixvQkFBb0I7c0JBQXRELFNBQVM7dUJBQUMsc0JBQXNCO2dCQUNELGlCQUFpQjtzQkFBaEQsU0FBUzt1QkFBQyxtQkFBbUI7Z0JBd0Y5QixvQkFBb0I7c0JBRG5CLFlBQVk7dUJBQUMseUJBQXlCO2dCQW9KdkMsUUFBUTtzQkFEUCxZQUFZO3VCQUFDLGVBQWUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFQ1NQcmltZW5nVGFibGVJMThuU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2kxOG4uc2VydmljZSc7XHJcbmltcG9ydCB7IEVDU1RhYmxlVHJhbnNsYXRlUGlwZSB9IGZyb20gJy4uLy4uL3BpcGVzL3VpLXRyYW5zbGF0ZS5waXBlJztcclxuaW1wb3J0IHsgQWZ0ZXJWaWV3SW5pdCwgQ29tcG9uZW50LCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIEhvc3RMaXN0ZW5lciwgSW5wdXQsIE9uSW5pdCwgT25EZXN0cm95LCBDaGFuZ2VEZXRlY3RvclJlZiwgaW5qZWN0LCBPdXRwdXQsIFZpZXdDaGlsZCwgVmlld0VuY2Fwc3VsYXRpb24gfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgVHJhbnNsYXRlTW9kdWxlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBIdHRwUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XHJcblxyXG4vLyBQcmltZU5HIGltcG9ydHNcclxuaW1wb3J0IHsgVGFibGUsIFRhYmxlTW9kdWxlIH0gZnJvbSAncHJpbWVuZy90YWJsZSc7XHJcbmltcG9ydCB7IExhenlMb2FkRXZlbnQgfSBmcm9tICdwcmltZW5nL2FwaSc7XHJcbmltcG9ydCB7IEJ1dHRvbk1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvYnV0dG9uJztcclxuaW1wb3J0IHsgVG9vbHRpcE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvdG9vbHRpcCc7XHJcbmltcG9ydCB7IElucHV0VGV4dE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvaW5wdXR0ZXh0JztcclxuaW1wb3J0IHsgTXVsdGlTZWxlY3RNb2R1bGUgfSBmcm9tICdwcmltZW5nL211bHRpc2VsZWN0JztcclxuaW1wb3J0IHsgQ2hlY2tib3hNb2R1bGUgfSBmcm9tICdwcmltZW5nL2NoZWNrYm94JztcclxuaW1wb3J0IHsgUGFnaW5hdG9yTW9kdWxlIH0gZnJvbSAncHJpbWVuZy9wYWdpbmF0b3InO1xyXG5pbXBvcnQgeyBGaWx0ZXJNZXRhZGF0YSwgTWVudUl0ZW0gfSBmcm9tICdwcmltZW5nL2FwaSc7XHJcbmltcG9ydCB7IE92ZXJsYXlQYW5lbE1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvb3ZlcmxheXBhbmVsJztcclxuaW1wb3J0IHsgTWVudSwgTWVudU1vZHVsZSB9IGZyb20gJ3ByaW1lbmcvbWVudSc7XHJcblxyXG5pbXBvcnQgeyBFQ1NQcmltZW5nVGFibGVTZXJ2aWNlIH0gZnJvbSAnLi9lY3MtcHJpbWVuZy10YWJsZS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgRGV2aWNlVHlwZSwgQ2VsbE92ZXJmbG93QmVoYXZpb3VyLCBEYXRhQWxpZ25Ib3Jpem9udGFsLCBEYXRhQWxpZ25WZXJ0aWNhbCwgRGF0YVR5cGUsIEZyb3plbkNvbHVtbkFsaWduLCBUYWJsZVZpZXdTYXZlTW9kZSB9IGZyb20gJy4uLy4uL2VudW1zJztcclxuaW1wb3J0IHsgSVRhYmxlQnV0dG9uLCBJQ29sdW1uTWV0YWRhdGEsIElQcmVkZWZpbmVkRmlsdGVyLCBJVGFibGVDb25maWd1cmF0aW9uLCBJVGFibGVQYWdlZFJlc3BvbnNlLCBJVGFibGVRdWVyeVJlcXVlc3QsIElFeGNlbEV4cG9ydFJlcXVlc3QsIElUYWJsZVZpZXcsIElUYWJsZVZpZXdEYXRhLCBJVGFibGVPcHRpb25zLCBERUZBVUxUX1RBQkxFX09QVElPTlMgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzJztcclxuaW1wb3J0IHsgZGF0YUFsaWduSG9yaXpvbnRhbEFzVGV4dCwgZGF0YUFsaWduVmVydGljYWxBc1RleHQsIGRhdGFUeXBlQXNUZXh0LCBmcm96ZW5Db2x1bW5BbGlnbkFzVGV4dCB9IGZyb20gJy4uLy4uL3V0aWxzJztcclxuaW1wb3J0IHsgRUNTUHJpbWVuZ1RhYmxlTm90aWZpY2F0aW9uU2VydmljZSwgRUNTUHJpbWVuZ1RhYmxlU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMnO1xyXG5pbXBvcnQgeyBUYWJsZUNlbGwgfSBmcm9tICcuLi90YWJsZS1jZWxsL3RhYmxlLWNlbGwnO1xyXG5pbXBvcnQgeyBUYWJsZVByZWRlZmluZWRGaWx0ZXJzIH0gZnJvbSAnLi4vdGFibGUtcHJlZGVmaW5lZC1maWx0ZXJzL3RhYmxlLXByZWRlZmluZWQtZmlsdGVycyc7XHJcbmltcG9ydCB7IFRhYmxlQnV0dG9uIH0gZnJvbSAnLi4vdGFibGUtYnV0dG9uL3RhYmxlLWJ1dHRvbic7XHJcbmltcG9ydCB7IENvbHVtblNlbGVjdG9yIH0gZnJvbSBcIi4uL2NvbHVtbi1zZWxlY3Rvci9jb2x1bW4tc2VsZWN0b3JcIjtcclxuaW1wb3J0IHsgRXhwb3J0RXhjZWwgfSBmcm9tICcuLi9leHBvcnQtZXhjZWwvZXhwb3J0LWV4Y2VsJztcclxuaW1wb3J0IHsgZmluYWxpemUsIGZpcnN0VmFsdWVGcm9tLCBPYnNlcnZhYmxlLCBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgVmlld3NNYW5hZ2VtZW50IH0gZnJvbSBcIi4uL3ZpZXdzLW1hbmFnZW1lbnQvdmlld3MtbWFuYWdlbWVudFwiO1xyXG5pbXBvcnQgeyBJVHJlZVJlcXVlc3QsIElUcmVlUmVzcG9uc2UsIFRyZWVSb3csIFRyZWVUYWJsZVN0YXRlIH0gZnJvbSAnLi4vLi4vdXRpbHMvdHJlZS10YWJsZS1zdGF0ZSc7XHJcblxyXG50eXBlIFRhYmxlTGF6eUxvYWRFdmVudCA9IE9taXQ8TGF6eUxvYWRFdmVudCwgJ2ZpbHRlcnMnPiAmIHtcclxuICBmaWx0ZXJzPzogUmVjb3JkPHN0cmluZywgRmlsdGVyTWV0YWRhdGEgfCBGaWx0ZXJNZXRhZGF0YVtdPjtcclxufTtcclxuaW50ZXJmYWNlIFRhYmxlUGFnZUV2ZW50IHsgZmlyc3Q6IG51bWJlcjsgcm93czogbnVtYmVyOyB9XHJcbmludGVyZmFjZSBUYWJsZVJvd1NlbGVjdEV2ZW50PFQ+IHsgZGF0YTogVDsgfVxyXG5pbnRlcmZhY2UgVGFibGVSb3dVblNlbGVjdEV2ZW50PFQ+IHsgZGF0YTogVDsgfVxyXG5pbnRlcmZhY2UgVGFibGVNZW51SXRlbSBleHRlbmRzIE1lbnVJdGVtIHtcclxuICBfbGl0ZXJhbExhYmVsPzogYm9vbGVhbjtcclxuICBfdWlMYWJlbEtleT86IHN0cmluZztcclxuICBfdWlQYXJhbXM/OiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xyXG59XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2Vjcy1wcmltZW5nLXRhYmxlJyxcclxuICBpbXBvcnRzOiBbXHJcbiAgICBFQ1NUYWJsZVRyYW5zbGF0ZVBpcGUsXHJcbiAgICBUcmFuc2xhdGVNb2R1bGUsXHJcbiAgICBDb21tb25Nb2R1bGUsXHJcbiAgICBGb3Jtc01vZHVsZSxcclxuICAgIFRhYmxlTW9kdWxlLFxyXG4gICAgQnV0dG9uTW9kdWxlLFxyXG4gICAgVG9vbHRpcE1vZHVsZSxcclxuICAgIElucHV0VGV4dE1vZHVsZSxcclxuICAgIE11bHRpU2VsZWN0TW9kdWxlLFxyXG4gICAgQ2hlY2tib3hNb2R1bGUsXHJcbiAgICBQYWdpbmF0b3JNb2R1bGUsXHJcbiAgICBUYWJsZUNlbGwsXHJcbiAgICBUYWJsZVByZWRlZmluZWRGaWx0ZXJzLFxyXG4gICAgVGFibGVCdXR0b24sXHJcbiAgICBDb2x1bW5TZWxlY3RvcixcclxuICAgIEV4cG9ydEV4Y2VsLFxyXG4gICAgVmlld3NNYW5hZ2VtZW50LFxyXG4gICAgT3ZlcmxheVBhbmVsTW9kdWxlLFxyXG4gICAgTWVudU1vZHVsZVxyXG4gIF0sXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICB0ZW1wbGF0ZVVybDogJy4vZWNzLXByaW1lbmctdGFibGUuaHRtbCcsXHJcbiAgc3R5bGVVcmxzOiBbJy4vZWNzLXByaW1lbmctdGFibGUuc2NzcyddLFxyXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmVcclxufSlcclxuZXhwb3J0IGNsYXNzIEVDU1ByaW1lbmdUYWJsZSBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcclxuICBwcml2YXRlIHJlYWRvbmx5IGkxOG4gPSBpbmplY3QoRUNTUHJpbWVuZ1RhYmxlSTE4blNlcnZpY2UpO1xyXG4gIHByaXZhdGUgcmVhZG9ubHkgY2hhbmdlRGV0ZWN0b3IgPSBpbmplY3QoQ2hhbmdlRGV0ZWN0b3JSZWYsIHsgb3B0aW9uYWw6IHRydWUgfSk7XHJcbiAgcHJpdmF0ZSByZWFkb25seSBzdGF0ZVNjb3BlID0gaW5qZWN0KEVDU1ByaW1lbmdUYWJsZVN0YXRlU2VydmljZSwgeyBvcHRpb25hbDogdHJ1ZSB9KTtcclxuICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3kkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcclxuICBwcml2YXRlIGluaXRpYWxTdGF0ZUFwcGxpZWQgPSBmYWxzZTtcclxuICBwcml2YXRlIGRlc3Ryb3llZCA9IGZhbHNlO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgdGFibGVTZXJ2aWNlOiBFQ1NQcmltZW5nVGFibGVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBub3RpZmljYXRpb246IEVDU1ByaW1lbmdUYWJsZU5vdGlmaWNhdGlvblNlcnZpY2VcclxuICApIHtcclxuICAgIHRoaXMuaTE4bi5jaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKS5zdWJzY3JpYmUoKCkgPT4ge1xyXG4gICAgICB0aGlzLmhlYWRlck1lbnVJdGVtcyA9IHRoaXMudHJhbnNsYXRlTWVudUl0ZW1zKHRoaXMuaGVhZGVyTWVudUl0ZW1zKTtcclxuICAgICAgdGhpcy5yb3dNZW51SXRlbXMgPSB0aGlzLnRyYW5zbGF0ZU1lbnVJdGVtcyh0aGlzLnJvd01lbnVJdGVtcyk7XHJcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0b3I/Lm1hcmtGb3JDaGVjaygpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG4gIEBJbnB1dCgpIHRhYmxlT3B0aW9uczogSVRhYmxlT3B0aW9ucyA9IERFRkFVTFRfVEFCTEVfT1BUSU9OUztcclxuICB0cmVlU3RhdGU/OiBUcmVlVGFibGVTdGF0ZTtcclxuICBwcml2YXRlIHRyZWVRdWVyeT86IElUYWJsZVF1ZXJ5UmVxdWVzdDtcclxuICBwcml2YXRlIHRyZWVTdGF0ZVJlc3RvcmVkID0gZmFsc2U7XHJcbiAgQE91dHB1dCgpIG9uUm93Q2hlY2tib3hDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHtcclxuICAgIHJvd0lEOiBhbnksXHJcbiAgICBzZWxlY3RlZDogYm9vbGVhblxyXG4gIH0+KCk7IC8vIEVtaXR0ZXIgdGhhdCByZXR1cm5zIHRoZSBjb2x1bW4gc2VsZWN0ZWQgYW5kIGlmIGl0IHdhcyBzZWxlY3RlZCBvciB1bnNlbGVjdGVkXHJcbiAgQE91dHB1dCgpIG9uUm93U2VsZWN0ID0gbmV3IEV2ZW50RW1pdHRlcjx7XHJcbiAgICByb3dJRDogYW55LFxyXG4gICAgcm93RGF0YTogYW55XHJcbiAgfT5cclxuICBAT3V0cHV0KCkgb25Sb3dVbnNlbGVjdCA9IG5ldyBFdmVudEVtaXR0ZXI8e1xyXG4gICAgcm93SUQ6IGFueSxcclxuICAgIHJvd0RhdGE6IGFueVxyXG4gIH0+XHJcbiAgQE91dHB1dCgpIG9uRGF0YUVuZFVwZGF0ZSA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTtcclxuICB2aWV3c01vZGFsU2hvdzpib29sZWFuID0gZmFsc2U7XHJcbiAgdGFibGVWaWV3Q3VycmVudFNlbGVjdGVkQWxpYXM6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG4gIHRhYmxlVmlld3NGaXJzdEZldGNoRG9uZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIGV4Y2VsUmVwb3J0VGl0bGU6IHN0cmluZyA9IFwiXCI7XHJcbiAgc2hvd0V4cG9ydE1vZGFsOiBib29sZWFuID0gZmFsc2U7XHJcbiAgc2hvd0NvbHVtblNlbGVjdG9yOiBib29sZWFuID0gZmFsc2U7XHJcbiAgc2VsZWN0ZWRSb3dzQ2hlY2tib3g6IGFueVtdID0gW107IC8vIEFuIGFycmF5IHRvIGtlZXAgYWxsIHRoZSBzZWxlY3RlZCByb3dzXHJcbiAgc2VsZWN0QWxsTG9hZGluZyA9IGZhbHNlO1xyXG4gIHByaXZhdGUgc2VsZWN0aW9uUXVlcnk/OiBJVGFibGVRdWVyeVJlcXVlc3Q7XHJcbiAgcHJpdmF0ZSBzZWxlY3Rpb25RdWVyeUtleSA9ICcnO1xyXG4gIHByaXZhdGUgbWF0Y2hpbmdTZWxlY3Rpb25LZXlzPzogYW55W107XHJcbiAgQFZpZXdDaGlsZCgnZHQnKSBkdCE6IFRhYmxlOyAvLyBHZXQgdGhlIHJlZmVyZW5jZSB0byB0aGUgb2JqZWN0IHRhYmxlXHJcbiAgXHJcbiAgZ2xvYmFsU2VhcmNoVGV4dDogc3RyaW5nIHwgbnVsbCA9IG51bGw7IC8vIFRoZSB0ZXh0IHVzZWQgYnkgdGhlIGdsb2JhbCBzZWFyY2hcclxuICBwcml2YXRlIGFwcGxpZWRHbG9iYWxTZWFyY2hUZXh0OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIGdsb2JhbFNlYXJjaE1hbmFnZWQgPSBmYWxzZTtcclxuICBwcml2YXRlIGdsb2JhbFNlYXJjaFRpbWVyPzogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD47XHJcblxyXG4gIC8qKiBUaGUgYXBwbGllZCBxdWVyeSBzdGF5cyBzZXBhcmF0ZSBmcm9tIHRleHQgYmVpbmcgdHlwZWQgZHVyaW5nIHRoZSBkZWJvdW5jZS4gKi9cclxuICBnZXQgZWZmZWN0aXZlR2xvYmFsU2VhcmNoVGV4dCgpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIHJldHVybiB0aGlzLmdsb2JhbFNlYXJjaE1hbmFnZWQgPyB0aGlzLmFwcGxpZWRHbG9iYWxTZWFyY2hUZXh0IDogdGhpcy5nbG9iYWxTZWFyY2hUZXh0O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjYW5jZWxHbG9iYWxTZWFyY2goKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5nbG9iYWxTZWFyY2hUaW1lciAhPT0gdW5kZWZpbmVkKSBjbGVhclRpbWVvdXQodGhpcy5nbG9iYWxTZWFyY2hUaW1lcik7XHJcbiAgICB0aGlzLmdsb2JhbFNlYXJjaFRpbWVyID0gdW5kZWZpbmVkO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSByZXN0b3JlR2xvYmFsU2VhcmNoKHZhbHVlOiBzdHJpbmcgfCBudWxsKTogdm9pZCB7XHJcbiAgICB0aGlzLmNhbmNlbEdsb2JhbFNlYXJjaCgpO1xyXG4gICAgdGhpcy5nbG9iYWxTZWFyY2hUZXh0ID0gdmFsdWU7XHJcbiAgICB0aGlzLmFwcGxpZWRHbG9iYWxTZWFyY2hUZXh0ID0gdmFsdWUgfHwgbnVsbDtcclxuICAgIHRoaXMuZ2xvYmFsU2VhcmNoTWFuYWdlZCA9IHRydWU7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdsb2JhbFNlYXJjaE9wdGlvbih2YWx1ZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmIE51bWJlci5pc0Zpbml0ZSh2YWx1ZSkgPyBNYXRoLm1heCgwLCBNYXRoLmZsb29yKHZhbHVlKSkgOiAwO1xyXG4gIH1cclxuXHJcbiAgb25HbG9iYWxTZWFyY2hJbnB1dCh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5kZXN0cm95ZWQpIHJldHVybjtcclxuICAgIHRoaXMuY2FuY2VsR2xvYmFsU2VhcmNoKCk7XHJcbiAgICBpZiAoIXRoaXMuZ2xvYmFsU2VhcmNoTWFuYWdlZCkgdGhpcy5hcHBsaWVkR2xvYmFsU2VhcmNoVGV4dCA9IHRoaXMuZ2xvYmFsU2VhcmNoVGV4dCB8fCBudWxsO1xyXG4gICAgdGhpcy5nbG9iYWxTZWFyY2hNYW5hZ2VkID0gdHJ1ZTtcclxuICAgIHRoaXMuZ2xvYmFsU2VhcmNoVGV4dCA9IHZhbHVlO1xyXG4gICAgY29uc3QgbWluTGVuZ3RoID0gdGhpcy5nbG9iYWxTZWFyY2hPcHRpb24odGhpcy50YWJsZU9wdGlvbnMuZ2xvYmFsRmlsdGVyPy5taW5MZW5ndGgpO1xyXG4gICAgY29uc3QgZGVsYXkgPSB0aGlzLmdsb2JhbFNlYXJjaE9wdGlvbih0aGlzLnRhYmxlT3B0aW9ucy5nbG9iYWxGaWx0ZXI/LmRlYm91bmNlVGltZSk7XHJcbiAgICBjb25zdCB0cmltbWVkID0gdmFsdWUudHJpbSgpO1xyXG4gICAgY29uc3QgZWZmZWN0aXZlID0gdHJpbW1lZC5sZW5ndGggPj0gbWluTGVuZ3RoID8gKHRyaW1tZWQgfHwgbnVsbCkgOiBudWxsO1xyXG4gICAgaWYgKGVmZmVjdGl2ZSA9PT0gKHRoaXMuYXBwbGllZEdsb2JhbFNlYXJjaFRleHQ/LnRyaW0oKSB8fCBudWxsKSkgcmV0dXJuO1xyXG4gICAgY29uc3QgYXBwbHkgPSAoKSA9PiB7XHJcbiAgICAgIHRoaXMuZ2xvYmFsU2VhcmNoVGltZXIgPSB1bmRlZmluZWQ7XHJcbiAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgcmV0dXJuO1xyXG4gICAgICB0aGlzLmFwcGxpZWRHbG9iYWxTZWFyY2hUZXh0ID0gZWZmZWN0aXZlO1xyXG4gICAgICB0aGlzLmN1cnJlbnRQYWdlID0gMDtcclxuICAgICAgdGhpcy5kdC5maXJzdCA9IDA7XHJcbiAgICAgIGlmIChtaW5MZW5ndGggPT09IDAgJiYgZGVsYXkgPT09IDApIHtcclxuICAgICAgICAvLyBLZWVwIFByaW1lTkcncyBleGlzdGluZyBmaWx0ZXJpbmcgYmVoYXZpb3Igd2hlbiB0aGUgZmVhdHVyZSBpcyBub3QgY29uZmlndXJlZC5cclxuICAgICAgICB0aGlzLmR0LmZpbHRlckdsb2JhbCh2YWx1ZSwgJ2NvbnRhaW5zJyk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgLy8gT3duIHRoZSBnbG9iYWwgZGVsYXkgc28gaXQgaXMgbm90IGFkZGVkIHRvIFByaW1lTkcncyBjb2x1bW4tZmlsdGVyIGRlbGF5LlxyXG4gICAgICAgIHRoaXMuZHQuZmlsdGVycyA9IHsgLi4udGhpcy5kdC5maWx0ZXJzLCBnbG9iYWw6IHsgdmFsdWU6IGVmZmVjdGl2ZSwgbWF0Y2hNb2RlOiAnY29udGFpbnMnIH0gfTtcclxuICAgICAgICB0aGlzLmZldGNoVGFibGVEYXRhKHsgLi4udGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbiwgZmlyc3Q6IDAsXHJcbiAgICAgICAgICByb3dzOiB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSwgZmlsdGVyczogdGhpcy5kdC5maWx0ZXJzIH0pO1xyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgaWYgKGVmZmVjdGl2ZSA9PT0gbnVsbCB8fCBkZWxheSA9PT0gMCkgYXBwbHkoKTtcclxuICAgIGVsc2UgdGhpcy5nbG9iYWxTZWFyY2hUaW1lciA9IHNldFRpbWVvdXQoYXBwbHksIGRlbGF5KTtcclxuICB9XHJcbiAgdGFibGVWaWV3c0xpc3Q6IElUYWJsZVZpZXdbXSA9IFtdO1xyXG4gIHRhYmxlVmlld3NfbWVudUl0ZW1zOiBhbnlbXSA9IFtdO1xyXG5cclxuICBEYXRhVHlwZSA9IERhdGFUeXBlO1xyXG4gIENlbGxPdmVyZmxvd0JlaGF2aW91ciA9IENlbGxPdmVyZmxvd0JlaGF2aW91cjtcclxuICBEYXRhQWxpZ25Ib3Jpem9udGFsID0gRGF0YUFsaWduSG9yaXpvbnRhbDtcclxuICBEYXRhQWxpZ25WZXJ0aWNhbCA9IERhdGFBbGlnblZlcnRpY2FsO1xyXG4gIEZyb3plbkNvbHVtbkFsaWduID0gRnJvemVuQ29sdW1uQWxpZ247XHJcbiAgVGFibGVWaWV3U2F2ZU1vZGUgPSBUYWJsZVZpZXdTYXZlTW9kZTtcclxuXHJcbiAgcm93U2VsZWN0aW9uOiBhbnk7XHJcbiAgY3VycmVudFBhZ2U6IG51bWJlciA9IDA7IC8vIFRoZSBjdXJyZW50IHBhZ2Ugd2UgYXJlIGF0XHJcbiAgY3VycmVudFJvd3NQZXJQYWdlOiBudW1iZXIgPSAwOyAvLyBUaGUgY3VycmVudCByb3dzIHBlciBwYWdlIHNlbGVjdGVkXHJcbiAgYWxsb3dlZFJvd3NQZXJQYWdlOiBudW1iZXJbXSA9IFtdOyAvLyBUaGUgZGlmZmVyZW50IHZhbHVlcyBvZiByb3dzIHBlciBwYWdlIGFsbG93ZWRcclxuICB0b3RhbFJlY29yZHM6IG51bWJlciA9IDA7IC8vIFRoZSBudW1iZXIgb2YgdG90YWwgcmVjb3JkcyB0aGF0IGFyZSBhdmFpbGFibGUgKHRha2luZyBpbnRvIGFjY291bnQgdGhlIGZpbHRlcnMpXHJcbiAgdG90YWxSZWNvcmRzTm90RmlsdGVyZWQ6IG51bWJlciA9IDA7IC8vIFRoZSB0b3RhbCBudW1iZXIgb2YgcmVjb3JkcyBhdmFpbGFibGUgaWYgbm8gZmlsdGVycyB3ZXJlIGFwcGxpZWRcclxuXHJcbiAgZGF0ZUZvcm1hdDogc3RyaW5nID0gXCJkZC1NTU0teXl5eSBISDptbTpzcyB6enp6XCI7XHJcbiAgZGF0ZVRpbWV6b25lOiBzdHJpbmcgPSBcIiswMDowMFwiO1xyXG4gIGRhdGVDdWx0dXJlOiBzdHJpbmcgPSBcImVuLVVTXCI7XHJcbiAgZXhwb3J0RGF0ZUZvcm1hdDogc3RyaW5nID0gXCJkZC1NTU0teXl5eSBISDptbTpzc1wiXHJcblxyXG4gIGNvbHVtbnM6IElDb2x1bW5NZXRhZGF0YVtdID0gW107XHJcbiAgY29sdW1uc0NhbnRCZUhpZGRlbjogSUNvbHVtbk1ldGFkYXRhW10gPSBbXTtcclxuICBjb2x1bW5zU2VsZWN0ZWQ6IElDb2x1bW5NZXRhZGF0YVtdID0gW107XHJcbiAgY29sdW1uTW9kYWxEYXRhOiBhbnlbXSA9IFtdOyBcclxuICBmaWx0ZXJlZENvbHVtbkRhdGE6IGFueVtdID0gW107IFxyXG4gIHByaXZhdGUgaW5pdGlhbENvbHVtbldpZHRoczogYW55O1xyXG4gIHByaXZhdGUgaW5pdGlhbFRhYmxlV2lkdGg6IGFueTtcclxuICBwcmVkZWZpbmVkRmlsdGVyc1NlbGVjdGVkVmFsdWVzQ29sbGVjdGlvbjogeyBba2V5OiBzdHJpbmddOiBhbnlbXSB9ID0ge307IC8vIENvbnRhaW5zIGEgY29sbGVjdGlvbiBvZiB0aGUgcHJlZGVmaW5lZCBjb2x1bW4gZmlsdGVycyBzZWxlY3Rpb24gKHBvc3NpYmxlIHZhbHVlcyBjb21lIGZyb20gJ3ByZWRlZmluZWRGaWx0ZXJzQ29sbGVjdGlvbicpXHJcbiAgcHJpdmF0ZSBjb3B5Q2VsbERhdGFUaW1lcjogYW55OyAvLyBBIHRpbWVyIHRoYXQgaGFuZGxlcyB0aGUgYW1vdW50IG9mIHRpbWUgbGVmdCB0byBjb3B5IHRoZSBjZWxsIGRhdGEgdG8gdGhlIGNsaXBib2FyZFxyXG4gIHRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uOiBUYWJsZUxhenlMb2FkRXZlbnQgPSB7fTsgLy8gRGF0YSBvZiB0aGUgbGFzdCBsYXp5IGxvYWQgZXZlbnQgb2YgdGhlIHRhYmxlXHJcbiAgcHJpdmF0ZSBpbml0aWFsQ29uZmlndXJhdGlvbkZldGNoZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuICBwcml2YXRlIG1heFZpZXdzID0gMDtcclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuaTE4bi5jb25uZWN0UHJpbWVORygpO1xyXG4gICAgaWYgKHRoaXMudGFibGVPcHRpb25zLnRyZWUpIHRoaXMudHJlZVN0YXRlID0gbmV3IFRyZWVUYWJsZVN0YXRlKHRoaXMudGFibGVPcHRpb25zLnRyZWUpO1xyXG4gICAgdGhpcy52YWxpZGF0ZVN0YXRlUGVyc2lzdGVuY2UoKTtcclxuICAgIHRoaXMudXBkYXRlUmVzcG9uc2l2ZVZpZXdwb3J0KCk7XHJcbiAgICB0aGlzLmZldGNoVGFibGVDb25maWd1cmF0aW9uKCk7XHJcbiAgfVxyXG4gIEBWaWV3Q2hpbGQoJ3RhYmxlQ29udGFpbmVyJywgeyBzdGF0aWM6IGZhbHNlIH0pIHRhYmxlQ29udGFpbmVyITogRWxlbWVudFJlZjtcclxuICBAVmlld0NoaWxkKCdoZWFkZXJDb250YWluZXInLCB7IHN0YXRpYzogZmFsc2UgfSkgaGVhZGVyQ29udGFpbmVyITogRWxlbWVudFJlZjtcclxuICBAVmlld0NoaWxkKCdwYWdpbmF0b3JDb250YWluZXInLCB7IHN0YXRpYzogZmFsc2UgfSkgcGFnaW5hdG9yQ29udGFpbmVyITogRWxlbWVudFJlZjtcclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICB0aGlzLmNhbGN1bGF0ZVNjcm9sbEhlaWdodCgpO1xyXG4gICAgdGhpcy5jaGFuZ2VEZXRlY3Rvcj8uZGV0ZWN0Q2hhbmdlcygpO1xyXG4gIH1cclxuXHJcbiAgZGV2aWNlVHlwZTogRGV2aWNlVHlwZSA9IERldmljZVR5cGUuRGVza3RvcDtcclxuICBwcml2YXRlIGNvbHVtblNlbGVjdGlvbkN1c3RvbWl6ZWQgPSBmYWxzZTtcclxuICBoZWFkZXJNZW51SXRlbXM6IE1lbnVJdGVtW10gPSBbXTtcclxuICByb3dNZW51SXRlbXM6IE1lbnVJdGVtW10gPSBbXTtcclxuICByb3dNZW51Um93OiBhbnk7XHJcbiAgQFZpZXdDaGlsZCgncmVzcG9uc2l2ZUhlYWRlck1lbnUnKSByZXNwb25zaXZlSGVhZGVyTWVudT86IE1lbnU7XHJcbiAgQFZpZXdDaGlsZCgncmVzcG9uc2l2ZVJvd01lbnUnKSByZXNwb25zaXZlUm93TWVudT86IE1lbnU7XHJcblxyXG4gIGdldCBjb21wYWN0SGVhZGVyKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICEhdGhpcy50YWJsZU9wdGlvbnMucmVzcG9uc2l2ZT8uaGVhZGVyTWVudSAmJiB0aGlzLmRldmljZVR5cGUgIT09IERldmljZVR5cGUuRGVza3RvcDtcclxuICB9XHJcblxyXG4gIGdldCBjb21wYWN0Um93cygpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAhIXRoaXMudGFibGVPcHRpb25zLnJlc3BvbnNpdmU/LnJvd01lbnUgJiYgdGhpcy5kZXZpY2VUeXBlICE9PSBEZXZpY2VUeXBlLkRlc2t0b3A7XHJcbiAgfVxyXG5cclxuICBnZXQgYWN0aW9uQ29sdW1uV2lkdGgoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmNvbXBhY3RSb3dzID8gNTYgOiAodGhpcy50YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy53aWR0aCA/PyAxNTApO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q29sdW1uSGVhZGVyR3JvdXBzKGNvbHVtbnM6IElDb2x1bW5NZXRhZGF0YVtdKTogeyBmaWVsZDogc3RyaW5nOyBsYWJlbDogc3RyaW5nOyBjb2xzcGFuOiBudW1iZXI7IGZyb3plbkNvbHVtbkFsaWduOiBGcm96ZW5Db2x1bW5BbGlnbiB9W10ge1xyXG4gICAgaWYgKCFjb2x1bW5zLnNvbWUoY29sdW1uID0+IGNvbHVtbi5oZWFkZXJHcm91cD8udHJpbSgpKSkgcmV0dXJuIFtdO1xyXG4gICAgY29uc3QgZ3JvdXBzOiB7IGZpZWxkOiBzdHJpbmc7IGxhYmVsOiBzdHJpbmc7IGNvbHNwYW46IG51bWJlcjsgZnJvemVuQ29sdW1uQWxpZ246IEZyb3plbkNvbHVtbkFsaWduIH1bXSA9IFtdO1xyXG4gICAgZm9yIChjb25zdCBjb2x1bW4gb2YgY29sdW1ucykge1xyXG4gICAgICBjb25zdCBsYWJlbCA9IGNvbHVtbi5oZWFkZXJHcm91cD8udHJpbSgpID8/ICcnO1xyXG4gICAgICBjb25zdCBmcm96ZW5Db2x1bW5BbGlnbiA9IGNvbHVtbi5mcm96ZW5Db2x1bW5BbGlnbiA/PyBGcm96ZW5Db2x1bW5BbGlnbi5Ob29uZTtcclxuICAgICAgY29uc3QgcHJldmlvdXMgPSBncm91cHNbZ3JvdXBzLmxlbmd0aCAtIDFdO1xyXG4gICAgICBpZiAocHJldmlvdXMgJiYgcHJldmlvdXMubGFiZWwgPT09IGxhYmVsICYmIHByZXZpb3VzLmZyb3plbkNvbHVtbkFsaWduID09PSBmcm96ZW5Db2x1bW5BbGlnbikge1xyXG4gICAgICAgIHByZXZpb3VzLmNvbHNwYW4rKztcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBncm91cHMucHVzaCh7IGZpZWxkOiBjb2x1bW4uZmllbGQsIGxhYmVsLCBjb2xzcGFuOiAxLCBmcm96ZW5Db2x1bW5BbGlnbiB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGdyb3VwcztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaXNJbml0aWFsbHlWaXNpYmxlKGNvbHVtbjogSUNvbHVtbk1ldGFkYXRhKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIWNvbHVtbi5jYW5CZUhpZGRlbikgcmV0dXJuIHRydWU7XHJcbiAgICBpZiAoY29sdW1uLnN0YXJ0SGlkZGVuKSByZXR1cm4gZmFsc2U7XHJcbiAgICBjb25zdCBkZXZpY2VzID0gY29sdW1uLnZpc2libGVPbmx5SW47XHJcbiAgICByZXR1cm4gIWRldmljZXM/Lmxlbmd0aCB8fCBkZXZpY2VzLnNvbWUoZGV2aWNlID0+XHJcbiAgICAgIGRldmljZSA9PT0gdGhpcy5kZXZpY2VUeXBlIHx8IFN0cmluZyhkZXZpY2UpLnRvTG93ZXJDYXNlKCkgPT09IERldmljZVR5cGVbdGhpcy5kZXZpY2VUeXBlXS50b0xvd2VyQ2FzZSgpKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlUmVzcG9uc2l2ZVZpZXdwb3J0KCk6IHZvaWQge1xyXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMudGFibGVPcHRpb25zLnJlc3BvbnNpdmU7XHJcbiAgICBjb25zdCB0YWJsZXQgPSBvcHRpb25zPy50YWJsZXRNaW5XaWR0aCA/PyA3Njg7XHJcbiAgICBjb25zdCBkZXNrdG9wID0gb3B0aW9ucz8uZGVza3RvcE1pbldpZHRoID8/IDEyMDA7XHJcbiAgICBpZiAoIU51bWJlci5pc0Zpbml0ZSh0YWJsZXQpIHx8ICFOdW1iZXIuaXNGaW5pdGUoZGVza3RvcCkgfHwgdGFibGV0IDw9IDAgfHwgZGVza3RvcCA8PSB0YWJsZXQpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFQ1MgdGFibGUgcmVzcG9uc2l2ZSB3aWR0aHMgbXVzdCBiZSBmaW5pdGUgYW5kIDAgPCB0YWJsZXRNaW5XaWR0aCA8IGRlc2t0b3BNaW5XaWR0aC4nKTtcclxuICAgIH1cclxuICAgIGNvbnN0IHdpZHRoID0gdHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgPyBkZXNrdG9wIDogd2luZG93LmlubmVyV2lkdGg7XHJcbiAgICBjb25zdCBuZXh0ID0gd2lkdGggPCB0YWJsZXQgPyBEZXZpY2VUeXBlLk1vYmlsZSA6IHdpZHRoIDwgZGVza3RvcCA/IERldmljZVR5cGUuVGFibGV0IDogRGV2aWNlVHlwZS5EZXNrdG9wO1xyXG4gICAgaWYgKG5leHQgPT09IHRoaXMuZGV2aWNlVHlwZSkgcmV0dXJuO1xyXG4gICAgdGhpcy5kZXZpY2VUeXBlID0gbmV4dDtcclxuICAgIHRoaXMucmVzcG9uc2l2ZUhlYWRlck1lbnU/LmhpZGUoKTtcclxuICAgIHRoaXMucmVzcG9uc2l2ZVJvd01lbnU/LmhpZGUoKTtcclxuICAgIGlmICghdGhpcy5pbml0aWFsQ29uZmlndXJhdGlvbkZldGNoZWQgfHwgdGhpcy5jb2x1bW5TZWxlY3Rpb25DdXN0b21pemVkIHx8XHJcbiAgICAgICAgIXRoaXMuY29sdW1ucy5zb21lKGNvbHVtbiA9PiBjb2x1bW4udmlzaWJsZU9ubHlJbj8ubGVuZ3RoKSkgcmV0dXJuO1xyXG4gICAgY29uc3Qgc2VsZWN0ZWQgPSB0aGlzLmNvbHVtbnMuZmlsdGVyKGNvbHVtbiA9PiBjb2x1bW4uY2FuQmVIaWRkZW4gJiYgdGhpcy5pc0luaXRpYWxseVZpc2libGUoY29sdW1uKSk7XHJcbiAgICBjb25zdCBzaG93biA9IHRoaXMudGFibGVTZXJ2aWNlLm9yZGVyQ29sdW1uc1dpdGhGcm96ZW5zKHRoaXMuY29sdW1uc0NhbnRCZUhpZGRlbi5jb25jYXQoc2VsZWN0ZWQpKTtcclxuICAgIGNvbnN0IHByZXZpb3VzID0gdGhpcy50YWJsZU9wdGlvbnMuY29sdW1ucz8uc2hvd24gPz8gW107XHJcbiAgICBpZiAoc2hvd24ubGVuZ3RoID09PSBwcmV2aW91cy5sZW5ndGggJiYgc2hvd24uZXZlcnkoKGNvbHVtbiwgaSkgPT4gY29sdW1uLmZpZWxkID09PSBwcmV2aW91c1tpXS5maWVsZCkpIHJldHVybjtcclxuICAgIHRoaXMuY29sdW1uc1NlbGVjdGVkID0gc2VsZWN0ZWQ7XHJcbiAgICB0aGlzLnRhYmxlT3B0aW9ucy5jb2x1bW5zIS5zaG93biA9IHNob3duO1xyXG4gICAgdGhpcy5zaG93Q29sdW1uU2VsZWN0b3IgPSBmYWxzZTtcclxuICAgIC8vIFJlcXVlc3QgbmV3bHkgdmlzaWJsZSBmaWVsZHMgd2l0aG91dCByZXNldHRpbmcgZmlsdGVycywgc29ydGluZyBvciBwYWdpbmF0aW9uLlxyXG4gICAgaWYgKHRoaXMuaW5pdGlhbFN0YXRlQXBwbGllZCkgdGhpcy5mZXRjaFRhYmxlRGF0YSh0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnV0dG9uVmlzaWJsZShidXR0b246IElUYWJsZUJ1dHRvbiwgcm93OiBhbnkpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAoYnV0dG9uLnZpc2libGVDb25kaXRpb24/Lihyb3cpID8/IHRydWUpICYmXHJcbiAgICAgICgoYnV0dG9uLmVuYWJsZWRDb25kaXRpb24/Lihyb3cpID8/IHRydWUpIHx8ICFidXR0b24uY29uZGl0aW9uRmFpbEhpZGUpO1xyXG4gIH1cclxuXHJcbiAgaGFzUm93TWVudUFjdGlvbnMocm93OiBhbnkpOiBib29sZWFuIHtcclxuICAgIHJldHVybiAodGhpcy50YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5idXR0b25zID8/IFtdKS5zb21lKGJ1dHRvbiA9PiB0aGlzLmJ1dHRvblZpc2libGUoYnV0dG9uLCByb3cpKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYnV0dG9uTWVudUl0ZW1zKGJ1dHRvbnM6IElUYWJsZUJ1dHRvbltdLCByb3c6IGFueSk6IE1lbnVJdGVtW10ge1xyXG4gICAgcmV0dXJuIGJ1dHRvbnMuZmlsdGVyKGJ1dHRvbiA9PiB0aGlzLmJ1dHRvblZpc2libGUoYnV0dG9uLCByb3cpKS5tYXAoKGJ1dHRvbiwgaW5kZXgpID0+ICh7XHJcbiAgICAgIGxhYmVsOiBidXR0b24ubGFiZWwgfHwgYnV0dG9uLnRvb2x0aXAgfHwgJ0FjdGlvbiB7e251bWJlcn19JyxcclxuICAgICAgX3VpUGFyYW1zOiB7IG51bWJlcjogaW5kZXggKyAxIH0sXHJcbiAgICAgIGljb246IGJ1dHRvbi5pY29uLFxyXG4gICAgICBkaXNhYmxlZDogIShidXR0b24uZW5hYmxlZENvbmRpdGlvbj8uKHJvdykgPz8gdHJ1ZSksXHJcbiAgICAgIGNvbW1hbmQ6ICgpID0+IHtcclxuICAgICAgICBpZiAodGhpcy5idXR0b25WaXNpYmxlKGJ1dHRvbiwgcm93KSAmJiAoYnV0dG9uLmVuYWJsZWRDb25kaXRpb24/Lihyb3cpID8/IHRydWUpICYmIGJ1dHRvbi5hY3Rpb24pIHtcclxuICAgICAgICAgIHRoaXMudGFibGVTZXJ2aWNlLmhhbmRsZUJ1dHRvbnNDbGljayhidXR0b24uYWN0aW9uLCByb3cpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSkpO1xyXG4gIH1cclxuXHJcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6a2V5ZG93bi5lc2NhcGUnKVxyXG4gIGNsb3NlUmVzcG9uc2l2ZU1lbnVzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5yZXNwb25zaXZlSGVhZGVyTWVudT8uaGlkZSgpO1xyXG4gICAgdGhpcy5yZXNwb25zaXZlUm93TWVudT8uaGlkZSgpO1xyXG4gIH1cclxuXHJcbiAgb3BlblJvd01lbnUoZXZlbnQ6IEV2ZW50LCByb3c6IGFueSk6IHZvaWQge1xyXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICB0aGlzLnJlc3BvbnNpdmVIZWFkZXJNZW51Py5oaWRlKCk7XHJcbiAgICBpZiAodGhpcy5yZXNwb25zaXZlUm93TWVudT8udmlzaWJsZSAmJiB0aGlzLnJvd01lbnVSb3cgPT09IHJvdykge1xyXG4gICAgICB0aGlzLnJlc3BvbnNpdmVSb3dNZW51LmhpZGUoKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgLy8gVXNlIG9uZSBvdmVybGF5IGZvciBhbGwgcm93cy4gUmVwbGFjaW5nIHRoZSBtb2RlbCBiaW5kcyBldmVyeSBhY3Rpb24gdG8gdGhpcyByb3cuXHJcbiAgICB0aGlzLnJvd01lbnVSb3cgPSByb3c7XHJcbiAgICB0aGlzLnJvd01lbnVJdGVtcyA9IHRoaXMudHJhbnNsYXRlTWVudUl0ZW1zKHRoaXMuYnV0dG9uTWVudUl0ZW1zKHRoaXMudGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8uYnV0dG9ucyA/PyBbXSwgcm93KSk7XHJcbiAgICBjb25zdCB3YXNPcGVuID0gdGhpcy5yZXNwb25zaXZlUm93TWVudT8udmlzaWJsZTtcclxuICAgIHRoaXMucmVzcG9uc2l2ZVJvd01lbnU/LnNob3coZXZlbnQpO1xyXG4gICAgaWYgKHdhc09wZW4pIHRoaXMucmVzcG9uc2l2ZVJvd01lbnU/LmFsaWduT3ZlcmxheSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB0cmFuc2xhdGVNZW51SXRlbXMoaXRlbXM6IFRhYmxlTWVudUl0ZW1bXSk6IFRhYmxlTWVudUl0ZW1bXSB7XHJcbiAgICByZXR1cm4gaXRlbXMubWFwKGl0ZW0gPT4ge1xyXG4gICAgICBpZiAoaXRlbVsnX2xpdGVyYWxMYWJlbCddKSByZXR1cm4gaXRlbTtcclxuICAgICAgY29uc3Qga2V5ID0gaXRlbVsnX3VpTGFiZWxLZXknXSA/PyBpdGVtLmxhYmVsO1xyXG4gICAgICByZXR1cm4geyAuLi5pdGVtLCBfdWlMYWJlbEtleToga2V5LCBsYWJlbDogdGhpcy5pMThuLnRleHQoa2V5LCBpdGVtWydfdWlQYXJhbXMnXSkgfTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgb3BlbkhlYWRlck1lbnUoZXZlbnQ6IEV2ZW50KTogdm9pZCB7XHJcbiAgICB0aGlzLnJlc3BvbnNpdmVSb3dNZW51Py5oaWRlKCk7XHJcbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy50YWJsZU9wdGlvbnM7XHJcbiAgICBjb25zdCBpdGVtczogVGFibGVNZW51SXRlbVtdID0gW107XHJcbiAgICBpZiAob3B0aW9ucy5jb2x1bW5zPy5zZWxlY3RvckVuYWJsZWQpIGl0ZW1zLnB1c2goeyBsYWJlbDogJ01vZGlmeSBjb2x1bW5zJywgaWNvbjogb3B0aW9ucy5jb2x1bW5zLnNlbGVjdG9ySWNvbiwgY29tbWFuZDogKCkgPT4gdGhpcy5jb2x1bW5TZWxlY3RvclNob3coKSB9KTtcclxuICAgIGlmIChvcHRpb25zLmhlYWRlcj8uY2xlYXJTb3J0c0VuYWJsZWQpIGl0ZW1zLnB1c2goeyBsYWJlbDogJ0NsZWFyIHNvcnRzJywgaWNvbjogb3B0aW9ucy5oZWFkZXIuY2xlYXJTb3J0c0ljb24sIGRpc2FibGVkOiAhdGhpcy5oYXNUb0NsZWFyU29ydHModGhpcy5kdCksIGNvbW1hbmQ6ICgpID0+IHRoaXMuY2xlYXJTb3J0cyh0aGlzLmR0KSB9KTtcclxuICAgIGlmIChvcHRpb25zLmhlYWRlcj8uY2xlYXJGaWx0ZXJzRW5hYmxlZCkgaXRlbXMucHVzaCh7IGxhYmVsOiAnQ2xlYXIgZmlsdGVycycsIGljb246IG9wdGlvbnMuaGVhZGVyLmNsZWFyRmlsdGVyc0ljb24sIGRpc2FibGVkOiAhdGhpcy5oYXNUb0NsZWFyRmlsdGVycyh0aGlzLmR0LCB0aGlzLmdsb2JhbFNlYXJjaFRleHQpLCBjb21tYW5kOiAoKSA9PiB0aGlzLmNsZWFyRmlsdGVycyh0aGlzLmR0KSB9KTtcclxuICAgIGlmICh0aGlzLnRhYmxlVmlld3NFbmFibGVkKCkpIHtcclxuICAgICAgaXRlbXMucHVzaCh7IGxhYmVsOiB0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzIHx8IG9wdGlvbnMudmlld3M/Lm5vVmlld1NlbGVjdGVkVGV4dCB8fCAnU2VsZWN0IGEgdmlldycsIF9saXRlcmFsTGFiZWw6ICEhdGhpcy50YWJsZVZpZXdDdXJyZW50U2VsZWN0ZWRBbGlhcywgaWNvbjogJ3BpIHBpLWJvb2ttYXJrJywgY29tbWFuZDogKCkgPT4geyB0aGlzLnZpZXdzTW9kYWxTaG93ID0gdHJ1ZTsgfSB9KTtcclxuICAgICAgaXRlbXMucHVzaCh7IGxhYmVsOiAnQXBwbHkgdmlldyBhZ2FpbicsIGljb246IG9wdGlvbnMudmlld3M/LnJlbG9hZFZpZXdCdXR0b25JY29uIHx8ICdwaSBwaS1yZWZyZXNoJywgZGlzYWJsZWQ6ICF0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzLCBjb21tYW5kOiAoKSA9PiB0aGlzLnZpZXdMb2FkKHRoaXMudGFibGVWaWV3Q3VycmVudFNlbGVjdGVkQWxpYXMhKSB9KTtcclxuICAgIH1cclxuICAgIGlmIChvcHRpb25zLmV4Y2VsUmVwb3J0Py51cmw/LnRyaW0oKSkgaXRlbXMucHVzaCh7IGxhYmVsOiAnRXhwb3J0IHRvIEV4Y2VsJywgaWNvbjogJ3BpIHBpLWZpbGUtZXhjZWwnLCBjb21tYW5kOiAoKSA9PiB0aGlzLm9wZW5FeGNlbEV4cG9ydCgpIH0pO1xyXG4gICAgaWYgKG9wdGlvbnMucmVzZXRUYWJsZVZpZXc/LmVuYWJsZWQpIGl0ZW1zLnB1c2goeyBsYWJlbDogJ1Jlc2V0IHRhYmxlIHZpZXcnLCBpY29uOiBvcHRpb25zLnJlc2V0VGFibGVWaWV3Lmljb24sIGNvbW1hbmQ6ICgpID0+IHRoaXMucmVzZXRUYWJsZVZpZXcoKSB9KTtcclxuICAgIGl0ZW1zLnB1c2goeyBsYWJlbDogJ1JlZnJlc2ggZGF0YScsIGljb246ICdwaSBwaS1yZWZyZXNoJywgY29tbWFuZDogKCkgPT4gdGhpcy5yZWZyZXNoRGF0YShldmVudCkgfSk7XHJcbiAgICBpdGVtcy5wdXNoKC4uLnRoaXMuYnV0dG9uTWVudUl0ZW1zKG9wdGlvbnMuaGVhZGVyPy5idXR0b25zID8/IFtdLCBudWxsKSk7XHJcbiAgICB0aGlzLmhlYWRlck1lbnVJdGVtcyA9IHRoaXMudHJhbnNsYXRlTWVudUl0ZW1zKGl0ZW1zKTtcclxuICAgIHRoaXMucmVzcG9uc2l2ZUhlYWRlck1lbnU/LnRvZ2dsZShldmVudCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHZhbGlkYXRlU3RhdGVQZXJzaXN0ZW5jZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy50YWJsZU9wdGlvbnMuc3RhdGVQZXJzaXN0ZW5jZT8uZW5hYmxlZCkgcmV0dXJuO1xyXG4gICAgaWYgKCF0aGlzLnRhYmxlT3B0aW9ucy5zdGF0ZVBlcnNpc3RlbmNlLmtleT8udHJpbSgpIHx8ICF0aGlzLnN0YXRlU2NvcGUpIHtcclxuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFQ1MgdGFibGUgc3RhdGVQZXJzaXN0ZW5jZSByZXF1aXJlcyBhIG5vbi1lbXB0eSBrZXkgYW5kIEVDU1ByaW1lbmdUYWJsZVN0YXRlU2VydmljZSBwcm92aWRlZCBvbiBhIHBhcmVudCBzY29wZSBjb21wb25lbnQuJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2FuY2VsR2xvYmFsU2VhcmNoKCk7XHJcbiAgICB0aGlzLmRlc3Ryb3llZCA9IHRydWU7XHJcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcclxuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxuICAgIHRoaXMudHJlZVN0YXRlPy5jYW5jZWwoKTtcclxuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLnRhYmxlT3B0aW9ucy5zdGF0ZVBlcnNpc3RlbmNlO1xyXG4gICAgY29uc3Qga2V5ID0gb3B0aW9ucz8ua2V5Py50cmltKCk7XHJcbiAgICBpZiAoIWtleSB8fCAhdGhpcy5zdGF0ZVNjb3BlKSByZXR1cm47XHJcbiAgICBpZiAoIW9wdGlvbnM/LmVuYWJsZWQpIHtcclxuICAgICAgdGhpcy5zdGF0ZVNjb3BlLmNsZWFyKGtleSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICghdGhpcy5pbml0aWFsU3RhdGVBcHBsaWVkIHx8ICF0aGlzLmR0KSByZXR1cm47XHJcbiAgICBjb25zdCBmaWx0ZXJzID0gc3RydWN0dXJlZENsb25lKHRoaXMuZHQuZmlsdGVycyA/PyB7fSk7XHJcbiAgICBkZWxldGUgZmlsdGVyc1snZ2xvYmFsJ107XHJcbiAgICBkZWxldGUgZmlsdGVyc1snc2VsZWN0b3InXTtcclxuICAgIHRoaXMuc3RhdGVTY29wZS5zZXQoa2V5LCB7XHJcbiAgICAgIGNvbmZpZ3VyYXRpb25Vcmw6IHRoaXMudGFibGVPcHRpb25zLnVybFRhYmxlQ29uZmlndXJhdGlvbiA/PyAnJyxcclxuICAgICAgZGF0YVVybDogdGhpcy50YWJsZU9wdGlvbnMudXJsVGFibGVEYXRhID8/ICcnLFxyXG4gICAgICBmaWx0ZXJzLFxyXG4gICAgICBtdWx0aVNvcnRNZXRhOiBzdHJ1Y3R1cmVkQ2xvbmUodGhpcy5kdC5tdWx0aVNvcnRNZXRhID8/IFtdKSxcclxuICAgICAgZ2xvYmFsU2VhcmNoVGV4dDogdGhpcy5lZmZlY3RpdmVHbG9iYWxTZWFyY2hUZXh0LFxyXG4gICAgICBjdXJyZW50UGFnZTogdGhpcy5jdXJyZW50UGFnZSxcclxuICAgICAgY3VycmVudFJvd3NQZXJQYWdlOiB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSxcclxuICAgICAgdHJlZU1vZGU6IHRoaXMudHJlZVN0YXRlPy5tb2RlLFxyXG4gICAgICB0cmVlRXhwYW5kZWRLZXlzOiB0aGlzLnRyZWVTdGF0ZSA/IFsuLi50aGlzLnRyZWVTdGF0ZS5leHBhbmRlZF0gOiB1bmRlZmluZWQsXHJcbiAgICAgIHRyZWVDaGlsZFBhZ2VzOiB0aGlzLnRyZWVTdGF0ZT8uc25hcHNob3RQYWdlcygpXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVzdG9yZU5hdmlnYXRpb25TdGF0ZSgpOiBib29sZWFuIHtcclxuICAgIHRoaXMudmFsaWRhdGVTdGF0ZVBlcnNpc3RlbmNlKCk7XHJcbiAgICBjb25zdCBvcHRpb25zID0gdGhpcy50YWJsZU9wdGlvbnMuc3RhdGVQZXJzaXN0ZW5jZTtcclxuICAgIGNvbnN0IGtleSA9IG9wdGlvbnM/LmtleT8udHJpbSgpO1xyXG4gICAgaWYgKCFvcHRpb25zPy5lbmFibGVkKSB7XHJcbiAgICAgIGlmIChrZXkpIHRoaXMuc3RhdGVTY29wZT8uY2xlYXIoa2V5KTtcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgY29uc3Qgc3RhdGUgPSB0aGlzLnN0YXRlU2NvcGUhLmdldChrZXkhKTtcclxuICAgIGlmICghc3RhdGUpIHJldHVybiBmYWxzZTtcclxuICAgIGlmIChzdGF0ZS5jb25maWd1cmF0aW9uVXJsICE9PSB0aGlzLnRhYmxlT3B0aW9ucy51cmxUYWJsZUNvbmZpZ3VyYXRpb24gfHxcclxuICAgICAgc3RhdGUuZGF0YVVybCAhPT0gdGhpcy50YWJsZU9wdGlvbnMudXJsVGFibGVEYXRhIHx8IHN0YXRlLnRyZWVNb2RlICE9PSB0aGlzLnRyZWVTdGF0ZT8ubW9kZSkge1xyXG4gICAgICB0aGlzLnN0YXRlU2NvcGUhLmNsZWFyKGtleSEpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICBjb25zdCBmaWVsZHMgPSBuZXcgU2V0KHRoaXMuY29sdW1ucy5tYXAoY29sdW1uID0+IGNvbHVtbi5maWVsZCkpO1xyXG4gICAgY29uc3QgZmlsdGVyczogUmVjb3JkPHN0cmluZywgRmlsdGVyTWV0YWRhdGEgfCBGaWx0ZXJNZXRhZGF0YVtdPiA9IHt9O1xyXG4gICAgZm9yIChjb25zdCBbZmllbGQsIGZpbHRlcl0gb2YgT2JqZWN0LmVudHJpZXMoc3RhdGUuZmlsdGVycykpIHtcclxuICAgICAgaWYgKGZpZWxkcy5oYXMoZmllbGQpKSBmaWx0ZXJzW2ZpZWxkXSA9IGZpbHRlcjtcclxuICAgIH1cclxuICAgIHRoaXMuY3VycmVudFJvd3NQZXJQYWdlID0gdGhpcy5hbGxvd2VkUm93c1BlclBhZ2UuaW5jbHVkZXMoc3RhdGUuY3VycmVudFJvd3NQZXJQYWdlKVxyXG4gICAgICA/IHN0YXRlLmN1cnJlbnRSb3dzUGVyUGFnZSA6IHRoaXMuY3VycmVudFJvd3NQZXJQYWdlO1xyXG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IHRoaXMuY3VycmVudFJvd3NQZXJQYWdlID09PSBzdGF0ZS5jdXJyZW50Um93c1BlclBhZ2VcclxuICAgICAgPyBNYXRoLm1heCgwLCBzdGF0ZS5jdXJyZW50UGFnZSkgOiAwO1xyXG4gICAgdGhpcy5yZXN0b3JlR2xvYmFsU2VhcmNoKHN0YXRlLmdsb2JhbFNlYXJjaFRleHQpO1xyXG4gICAgdGhpcy50cmVlU3RhdGU/LnJlc3RvcmUoc3RhdGUudHJlZUV4cGFuZGVkS2V5cywgc3RhdGUudHJlZUNoaWxkUGFnZXMpO1xyXG4gICAgdGhpcy50cmVlU3RhdGVSZXN0b3JlZCA9ICEhdGhpcy50cmVlU3RhdGU7XHJcbiAgICBpZiAodGhpcy5nbG9iYWxTZWFyY2hUZXh0KSB7XHJcbiAgICAgIGZpbHRlcnNbJ2dsb2JhbCddID0geyB2YWx1ZTogdGhpcy5nbG9iYWxTZWFyY2hUZXh0LCBtYXRjaE1vZGU6ICdjb250YWlucycgfTtcclxuICAgIH1cclxuICAgIGNvbnN0IHNvcnRzID0gc3RhdGUubXVsdGlTb3J0TWV0YS5maWx0ZXIoc29ydCA9PiBmaWVsZHMuaGFzKHNvcnQuZmllbGQpKTtcclxuICAgIHRoaXMuZHQuZmlsdGVycyA9IHsgLi4udGhpcy5kdC5maWx0ZXJzLCAuLi5zdHJ1Y3R1cmVkQ2xvbmUoZmlsdGVycykgfTtcclxuICAgIC8vIEtlZXAgaW5pdGlhbFN0YXRlQXBwbGllZD1mYWxzZSB3aGlsZSBQcmltZU5HIHNldHRlcnMgY2FuIGVtaXQgbGF6eS1sb2FkIGV2ZW50cy5cclxuICAgIHRoaXMuZHQubXVsdGlTb3J0TWV0YSA9IHNvcnRzO1xyXG4gICAgdGhpcy5kdC5maXJzdCA9IHRoaXMuY3VycmVudFBhZ2UgKiB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZTtcclxuICAgIHRoaXMuZHQucm93cyA9IHRoaXMuY3VycmVudFJvd3NQZXJQYWdlO1xyXG4gICAgdGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbiA9IHtcclxuICAgICAgZmlyc3Q6IHRoaXMuZHQuZmlyc3QsXHJcbiAgICAgIHJvd3M6IHRoaXMuY3VycmVudFJvd3NQZXJQYWdlLFxyXG4gICAgICBmaWx0ZXJzOiB0aGlzLmR0LmZpbHRlcnMsXHJcbiAgICAgIG11bHRpU29ydE1ldGE6IHNvcnRzXHJcbiAgICB9O1xyXG4gICAgdGhpcy5yZXN0b3JlUHJlZGVmaW5lZFNlbGVjdGlvbnMoZmlsdGVycyk7XHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgcmVzdG9yZVByZWRlZmluZWRTZWxlY3Rpb25zKGZpbHRlcnM6IFJlY29yZDxzdHJpbmcsIEZpbHRlck1ldGFkYXRhIHwgRmlsdGVyTWV0YWRhdGFbXT4pOiB2b2lkIHtcclxuICAgIHRoaXMucHJlZGVmaW5lZEZpbHRlcnNTZWxlY3RlZFZhbHVlc0NvbGxlY3Rpb24gPSB7fTtcclxuICAgIGZvciAoY29uc3QgY29sdW1uIG9mIHRoaXMuY29sdW1ucykge1xyXG4gICAgICBjb25zdCBrZXkgPSBjb2x1bW4uZmlsdGVyUHJlZGVmaW5lZFZhbHVlc05hbWU7XHJcbiAgICAgIGlmICgha2V5KSBjb250aW51ZTtcclxuICAgICAgY29uc3QgY3JpdGVyaWEgPSBmaWx0ZXJzW2NvbHVtbi5maWVsZF07XHJcbiAgICAgIGNvbnN0IHZhbHVlID0gKEFycmF5LmlzQXJyYXkoY3JpdGVyaWEpID8gY3JpdGVyaWFbMF0gOiBjcml0ZXJpYSk/LnZhbHVlO1xyXG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgY29udGludWU7XHJcbiAgICAgIHRoaXMucHJlZGVmaW5lZEZpbHRlcnNTZWxlY3RlZFZhbHVlc0NvbGxlY3Rpb25ba2V5XSA9XHJcbiAgICAgICAgKHRoaXMudGFibGVPcHRpb25zLnByZWRlZmluZWRGaWx0ZXJzPy5ba2V5XSA/PyBbXSkuZmlsdGVyKG9wdGlvbiA9PlxyXG4gICAgICAgICAgQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZS5pbmNsdWRlcyhvcHRpb24udmFsdWUpIDogdmFsdWUgPT09IG9wdGlvbi52YWx1ZVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6cmVzaXplJylcclxuICBvblJlc2l6ZSgpIHtcclxuICAgIHRoaXMudXBkYXRlUmVzcG9uc2l2ZVZpZXdwb3J0KCk7XHJcbiAgICB0aGlzLmNhbGN1bGF0ZVNjcm9sbEhlaWdodCgpO1xyXG4gIH1cclxuICBcclxuICBwcml2YXRlIGNhbGN1bGF0ZVNjcm9sbEhlaWdodCgpe1xyXG4gICAgaWYgKHRoaXMudGFibGVPcHRpb25zLnZlcnRpY2FsU2Nyb2xsPy5jc3NGb3JtdWxhKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLnRhYmxlT3B0aW9ucy52ZXJ0aWNhbFNjcm9sbD8uZml0VG9Db250YWluZXIgJiYgdGhpcy50YWJsZUNvbnRhaW5lciAmJiB0aGlzLnBhZ2luYXRvckNvbnRhaW5lciAmJiB0aGlzLmhlYWRlckNvbnRhaW5lcikge1xyXG4gICAgICBjb25zdCBjb250YWluZXJSZWN0ID0gdGhpcy50YWJsZUNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgICBjb25zdCBwYWdpbmF0b3JIZWlnaHQgPSB0aGlzLnBhZ2luYXRvckNvbnRhaW5lci5uYXRpdmVFbGVtZW50Lm9mZnNldEhlaWdodDtcclxuICAgICAgY29uc3QgaGVhZGVySGVpZ2h0ID0gdGhpcy5oZWFkZXJDb250YWluZXIubmF0aXZlRWxlbWVudC5vZmZzZXRIZWlnaHQ7XHJcbiAgICAgIGNvbnN0IHZpZXdwb3J0SGVpZ2h0ID0gd2luZG93LmlubmVySGVpZ2h0O1xyXG4gICAgICBjb25zdCB0b3BPZmZzZXQgPSBjb250YWluZXJSZWN0LnRvcCArIHdpbmRvdy5zY3JvbGxZO1xyXG4gICAgICB0aGlzLnRhYmxlT3B0aW9ucy52ZXJ0aWNhbFNjcm9sbC5oZWlnaHQgPSAodmlld3BvcnRIZWlnaHQgLSB0b3BPZmZzZXQgLSBwYWdpbmF0b3JIZWlnaHQgLSBoZWFkZXJIZWlnaHQpLTYwO1xyXG4gICAgfVxyXG4gIH1cclxuICBnZXQgc2Nyb2xsSGVpZ2h0VmFsdWUoKTogc3RyaW5nIHtcclxuICAgIGlmICh0aGlzLnRhYmxlT3B0aW9ucy52ZXJ0aWNhbFNjcm9sbD8uY3NzRm9ybXVsYSkge1xyXG4gICAgICByZXR1cm4gdGhpcy50YWJsZU9wdGlvbnMudmVydGljYWxTY3JvbGwuY3NzRm9ybXVsYTtcclxuICAgIH1cclxuICAgIGNvbnN0IGhlaWdodCA9IHRoaXMudGFibGVPcHRpb25zLnZlcnRpY2FsU2Nyb2xsPy5oZWlnaHQ7XHJcbiAgICByZXR1cm4gaGVpZ2h0ICYmIGhlaWdodCA+IDAgPyBgJHtoZWlnaHR9cHhgIDogJyc7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIHRoZSB0YWJsZSBkYXRhIGFuZCwgaWYgbmVlZGVkLCByZXRyaWV2ZXMgdGhlIGluaXRpYWwgdGFibGUgY29uZmlndXJhdGlvbiBmcm9tIGFuIGV4dGVybmFsIHNvdXJjZS5cclxuICAgKiBcclxuICAgKiBBbHNvIGFsbG93cyByZXNldHRpbmcgdGhlIHRhYmxlIHRvIGl0cyBvcmlnaW5hbCBzdGF0ZSBiZWZvcmUgYW55IHVzZXIgbWFuaXB1bGF0aW9ucy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW3Jlc2V0VGFibGVWaWV3PWZhbHNlXSBPcHRpb25hbC5cclxuICAgKiAtIGB0cnVlYDogcmVzZXRzIHRoZSB0YWJsZSBzdGF0ZSBiZWZvcmUgbG9hZGluZyBkYXRhLlxyXG4gICAqIC0gYGZhbHNlYDogcmVmcmVzaGVzIGRhdGEgdXNpbmcgdGhlIGN1cnJlbnQgY29uZmlndXJhdGlvbiAoYW5kIHJldHJpZXZlcyBpbml0aWFsIGNvbmZpZ3VyYXRpb24gaWYgbmVjZXNzYXJ5KS5cclxuICAgKlxyXG4gICAqICoqX0JlaGF2aW9yXyoqXHJcbiAgICogLSBUaGUgdGFibGUgaXMgYXV0b21hdGljYWxseSBzZXQgdG8gYGlzQWN0aXZlID0gdHJ1ZWAuXHJcbiAgICogLSBJZiB0aGUgaW5pdGlhbCBjb25maWd1cmF0aW9uIGhhcyBub3QgYmVlbiBmZXRjaGVkLCBpdCB3aWxsIGZldGNoIGl0IGFuZCB0aGVuIHVwZGF0ZSB0aGUgZGF0YS5cclxuICAgKiAtIElmIHRoZSBpbml0aWFsIGNvbmZpZ3VyYXRpb24gaXMgYWxyZWFkeSBmZXRjaGVkLCBpdCB3aWxsIGp1c3QgdXBkYXRlIHRoZSBkYXRhLlxyXG4gICAqIC0gSWYgYHJlc2V0VGFibGVWaWV3YCBpcyB0cnVlIGFuZCB0aGUgY29uZmlndXJhdGlvbiBpcyBhbHJlYWR5IGluaXRpYWxpemVkLCB0aGUgdGFibGUgd2lsbCBiZSByZXNldCB0byBpdHMgb3JpZ2luYWwgc3RhdGUgYmVmb3JlIHVwZGF0aW5nIHRoZSBkYXRhLlxyXG4gICAqL1xyXG4gIHVwZGF0ZURhdGEocmVzZXRUYWJsZVZpZXc6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xyXG4gICAgdGhpcy50YWJsZU9wdGlvbnMuaXNBY3RpdmUgPSB0cnVlOyAvLyBFbmFibGUgdGFibGUgYWN0aW9uczogdGhlIHRhYmxlIGlzIG5vdyBhY3RpdmUgYW5kIGNhbiBwZXJmb3JtIHVwZGF0ZXNcclxuICAgIGlmICghdGhpcy5pbml0aWFsQ29uZmlndXJhdGlvbkZldGNoZWQgfHwgcmVzZXRUYWJsZVZpZXcpIHsgLy8gSWYgaW5pdGlhbCBjb25maWd1cmF0aW9uIGhhc24ndCBiZWVuIGZldGNoZWQgeWV0IG9yIGEgcmVzZXQgaXMgZXhwbGljaXRseSByZXF1ZXN0ZWRcclxuICAgICAgaWYodGhpcy5pbml0aWFsQ29uZmlndXJhdGlvbkZldGNoZWQgJiYgcmVzZXRUYWJsZVZpZXcpIHsgLy8gUmVzZXQgdGhlIHRhYmxlIG9ubHkgaWYgaXQgd2FzIGFscmVhZHkgaW5pdGlhbGl6ZWQgYW5kIGEgcmVzZXQgaXMgZXhwbGljaXRseSByZXF1ZXN0ZWRcclxuICAgICAgICB0aGlzLnJlc2V0VGFibGVWaWV3KCk7IC8vIFJlc2V0IHRhYmxlIHN0YXRlIChmaWx0ZXJzLCBwYWdpbmF0aW9uLCBzb3J0aW5nLCBldGMuKSBhbmQgdGhlbiByZWZyZXNoIGRhdGFcclxuICAgICAgfSBlbHNlIHsgLy8gV2Ugb25seSBuZWVkIHRvIGdldCB0aGUgdGFibGUgY29uZmlndXJhdGlvbiB3aXRob3V0IHJlc2V0aW5nIHRoZSB2aWV3XHJcbiAgICAgICAgdGhpcy5mZXRjaFRhYmxlQ29uZmlndXJhdGlvbigpOyAvLyBGZXRjaCB0aGUgaW5pdGlhbCB0YWJsZSBjb25maWd1cmF0aW9uIGJlZm9yZSB1cGRhdGluZyBkYXRhXHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7IC8vIFRhYmxlIGlzIGFscmVhZHkgaW5pdGlhbGl6ZWQgYW5kIG5vIHJlc2V0IHJlcXVlc3RlZCwganVzdCByZWZyZXNoIHRoZSBkYXRhXHJcbiAgICAgIHRoaXMuZmV0Y2hUYWJsZURhdGEodGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbik7IC8vIFVwZGF0ZSB0YWJsZSByb3dzIHVzaW5nIHRoZSBsYXN0IGxhenkgbG9hZCBldmVudFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBjYW5GZXRjaERhdGEoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gIXRoaXMuZGVzdHJveWVkXHJcbiAgICAgICYmICEhdGhpcy50YWJsZU9wdGlvbnMuaXNBY3RpdmVcclxuICAgICAgJiYgISF0aGlzLnRhYmxlT3B0aW9ucy51cmxUYWJsZUNvbmZpZ3VyYXRpb24/LnRyaW0oKVxyXG4gICAgICAmJiAhIXRoaXMudGFibGVPcHRpb25zLnVybFRhYmxlRGF0YT8udHJpbSgpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmZXRjaFRhYmxlQ29uZmlndXJhdGlvbihyZXNldFRhYmxlVmlldzogYm9vbGVhbiA9IGZhbHNlKTogdm9pZCB7XHJcbiAgICBpZighdGhpcy5jYW5GZXRjaERhdGEoKSl7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMudGFibGVTZXJ2aWNlLmZldGNoVGFibGVDb25maWd1cmF0aW9uKHRoaXMudGFibGVPcHRpb25zLnVybFRhYmxlQ29uZmlndXJhdGlvbiEpXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKHtcclxuICAgICAgbmV4dDogKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2U8SVRhYmxlQ29uZmlndXJhdGlvbj4pID0+IHtcclxuICAgICAgICB0aGlzLmhhbmRsZVRhYmxlQ29uZmlndXJhdGlvblJlc3BvbnNlKHJlc3BvbnNlLmJvZHkhLCByZXNldFRhYmxlVmlldyk7XHJcbiAgICAgIH0sXHJcbiAgICAgIGVycm9yOiAoZXJyKSA9PiB0aGlzLnRhYmxlU2VydmljZS5oYW5kbGVUYWJsZUVycm9yKGVyciwgJ0NvbHVtbnMgRXJyb3InKVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGhhbmRsZVRhYmxlQ29uZmlndXJhdGlvblJlc3BvbnNlKGJvZHk6IElUYWJsZUNvbmZpZ3VyYXRpb24sIHJlc2V0VGFibGVWaWV3OiBib29sZWFuID0gZmFsc2UpOiB2b2lkIHtcclxuICAgIHRoaXMuYWxsb3dlZFJvd3NQZXJQYWdlID0gYm9keS5hbGxvd2VkSXRlbXNQZXJQYWdlOyAvLyBVcGRhdGUgdGhlIG51bWJlciBvZiByb3dzIGFsbG93ZWQgcGVyIHBhZ2VcclxuICAgIHRoaXMuY3VycmVudFJvd3NQZXJQYWdlID0gTWF0aC5taW4oLi4udGhpcy5hbGxvd2VkUm93c1BlclBhZ2UpOyAvLyBVcGRhdGUgdGhlIGN1cnJlbnQgcm93cyBwZXIgcGFnZSB0byB1c2UgdGhlIG1pbmltdW0gdmFsdWUgb2YgYWxsb3dlZCByb3dzIHBlciBwYWdlIGJ5IGRlZmF1bHRcclxuICAgIHRoaXMuY29sdW1ucyA9IGJvZHkuY29sdW1uc0luZm87IC8vIFVwZGF0ZSBjb2x1bW5zIHdpdGggZmV0Y2hlZCBkYXRhXHJcbiAgICB0aGlzLmNvbHVtbnNDYW50QmVIaWRkZW4gPSB0aGlzLmNvbHVtbnMuZmlsdGVyKChjb2w6IGFueSkgPT4gIWNvbC5jYW5CZUhpZGRlbik7IC8vIEZpbHRlciBjb2x1bW5zIHRoYXQgY2Fubm90IGJlIGhpZGRlblxyXG4gICAgdGhpcy5jb2x1bW5TZWxlY3Rpb25DdXN0b21pemVkID0gZmFsc2U7XHJcbiAgICB0aGlzLmNvbHVtbnNTZWxlY3RlZCA9IHRoaXMuY29sdW1ucy5maWx0ZXIoY29sID0+IGNvbC5jYW5CZUhpZGRlbiAmJiB0aGlzLmlzSW5pdGlhbGx5VmlzaWJsZShjb2wpKTsgLy8gU2VsZWN0ZWQgY29sdW1ucyB0aGF0IGFyZSBub3QgaGlkZGVuIGJ5IGRlZmF1bHRcclxuICAgIHRoaXMudGFibGVPcHRpb25zLmNvbHVtbnMhLnNob3duID0gdGhpcy50YWJsZVNlcnZpY2Uub3JkZXJDb2x1bW5zV2l0aEZyb3plbnModGhpcy5jb2x1bW5zQ2FudEJlSGlkZGVuLmNvbmNhdCh0aGlzLmNvbHVtbnNTZWxlY3RlZCkpO1xyXG4gICAgdGhpcy5kYXRlRm9ybWF0ID0gYm9keS5kYXRlRm9ybWF0O1xyXG4gICAgdGhpcy5kYXRlVGltZXpvbmUgPSBib2R5LmRhdGVUaW1lem9uZTtcclxuICAgIHRoaXMuZGF0ZUN1bHR1cmUgPSBib2R5LmRhdGVDdWx0dXJlO1xyXG4gICAgdGhpcy5leHBvcnREYXRlRm9ybWF0ID0gYm9keS5leHBvcnREYXRlRm9ybWF0O1xyXG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IDA7XHJcbiAgICB0aGlzLmluaXRpYWxDb25maWd1cmF0aW9uRmV0Y2hlZCA9IHRydWU7XHJcbiAgICB0aGlzLm1heFZpZXdzID0gYm9keS5tYXhWaWV3cztcclxuICAgIGlmKHJlc2V0VGFibGVWaWV3KXtcclxuICAgICAgdGhpcy50YWJsZU9wdGlvbnMuaXNBY3RpdmUgPSBmYWxzZVxyXG4gICAgICB0aGlzLmNsZWFyRmlsdGVycyh0aGlzLmR0LCB0cnVlKTtcclxuICAgICAgdGhpcy5jbGVhclNvcnRzKHRoaXMuZHQsIHRydWUpO1xyXG4gICAgICB0aGlzLmR0LnRhYmxlV2lkdGhTdGF0ZSA9IHRoaXMuaW5pdGlhbFRhYmxlV2lkdGg7XHJcbiAgICAgIHRoaXMuZHQuY29sdW1uV2lkdGhzU3RhdGUgPSB0aGlzLmluaXRpYWxDb2x1bW5XaWR0aHM7XHJcbiAgICAgIHRoaXMuZHQucmVzdG9yZUNvbHVtbldpZHRocygpXHJcbiAgICAgIHRoaXMudGFibGVMYXp5TG9hZEV2ZW50SW5mb3JtYXRpb24ubXVsdGlTb3J0TWV0YT1bXTtcclxuICAgICAgdGhpcy50YWJsZU9wdGlvbnMuaXNBY3RpdmUgPSB0cnVlO1xyXG4gICAgICB0aGlzLmluaXRpYWxTdGF0ZUFwcGxpZWQgPSB0cnVlO1xyXG4gICAgICB0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uLmZpcnN0ID0gMDtcclxuICAgICAgdGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbi5yb3dzID0gdGhpcy5jdXJyZW50Um93c1BlclBhZ2U7XHJcbiAgICAgIHRoaXMuZmV0Y2hUYWJsZURhdGEodGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICBpZiAodGhpcy5kZXN0cm95ZWQpIHJldHVybjtcclxuICAgICAgICB0aGlzLmluaXRpYWxDb2x1bW5XaWR0aHMgPSB0aGlzLnRhYmxlU2VydmljZS5jb21wdXRlQ29sdW1uV2lkdGhzKHRoaXMuZHQpO1xyXG4gICAgICAgIHRoaXMuaW5pdGlhbFRhYmxlV2lkdGggPSB0aGlzLnRhYmxlU2VydmljZS5jb21wdXRlVGFibGVXaWR0aCh0aGlzLmR0KTtcclxuICAgICAgfSwgMCk7XHJcbiAgICAgIHRoaXMuZmV0Y2hUYWJsZVZpZXdzKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZWZyZXNoRGF0YShldmVudDogYW55KXtcclxuICAgIHRoaXMuZmV0Y2hUYWJsZURhdGEodGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbik7XHJcbiAgfVxyXG5cclxuICB0YWJsZVZpZXdzRW5hYmxlZCgpOiBib29sZWFuIHtcclxuICAgIGNvbnN0IHZpZXdzID0gdGhpcy50YWJsZU9wdGlvbnMudmlld3M7XHJcbiAgICBpZiAodmlld3M/LnNhdmVNb2RlID09PSBUYWJsZVZpZXdTYXZlTW9kZS5Ob25lKSB7IC8vIHNhdmVNb2RlIG11c3QgYmUgZGlmZmVyZW50IGZyb20gbm9vbmVcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgaWYgKCF2aWV3cz8uc2F2ZUtleT8udHJpbSgpKSB7IC8vIHNhdmVLZXkgbXVzdCBleGlzdCBhbmQgbXVzdCBub3QgYmUgZW1wdHkgYWZ0ZXIgdHJpbVxyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcbiAgICBpZiAodGhpcy5tYXhWaWV3cyA8PSAwKSB7IC8vIG1heFZpZXdzIG11c3QgYmUgZ3JlYXRlciB0aGFuIDBcclxuICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG4gICAgaWYgKHZpZXdzPy5zYXZlTW9kZSA9PT0gVGFibGVWaWV3U2F2ZU1vZGUuRGF0YWJhc2VTdG9yYWdlKSB7IC8vIElmIHNhdmVNb2RlIGlzIGRhdGFiYXNlLCB1cmxHZXQgYW5kIHVybFNhdmUgbXVzdCBleGlzdCBhbmQgbXVzdCBub3QgYmUgZW1wdHkgYWZ0ZXIgdHJpbVxyXG4gICAgICBpZiAoIXZpZXdzPy51cmxHZXQ/LnRyaW0oKSB8fCAhdmlld3M/LnVybFNhdmU/LnRyaW0oKSkge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIHRydWU7IC8vIEFsbCBjaGVja3MgcGFzc2VkLCB2aWV3cyBhcmUgZW5hYmxlZFxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBmZXRjaFRhYmxlVmlld3MoKTogdm9pZCB7XHJcbiAgICBpZighdGhpcy50YWJsZVZpZXdzRW5hYmxlZCgpKXtcclxuICAgICAgdGhpcy5zdGFydEluaXRpYWxEYXRhTG9hZCgpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBjb25zdCB0YWJsZVZpZXdzID0gdGhpcy50YWJsZVNlcnZpY2UuZmV0Y2hUYWJsZVZpZXdzKHRoaXMudGFibGVPcHRpb25zLnZpZXdzIS5zYXZlTW9kZSEsIHRoaXMudGFibGVPcHRpb25zLnZpZXdzIS51cmxHZXQhLCB0aGlzLnRhYmxlT3B0aW9ucy52aWV3cyEuc2F2ZUtleSEpO1xyXG4gICAgaWYgKHRhYmxlVmlld3MgaW5zdGFuY2VvZiBPYnNlcnZhYmxlKSB7XHJcbiAgICAgIHRhYmxlVmlld3MucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlc3BvbnNlOiBIdHRwUmVzcG9uc2U8SVRhYmxlVmlld1tdPikgPT4ge1xyXG4gICAgICAgICAgIGxldCBwYXJzZWRSZXN1bHQgPSByZXNwb25zZS5ib2R5IS5tYXAoKGl0ZW06IGFueSkgPT4gKHtcclxuICAgICAgICAgICAgdmlld0FsaWFzOiBpdGVtLnZpZXdBbGlhcyxcclxuICAgICAgICAgICAgdmlld0RhdGE6IEpTT04ucGFyc2UoaXRlbS52aWV3RGF0YSksXHJcbiAgICAgICAgICAgIGxhc3RBY3RpdmU6IGl0ZW0ubGFzdEFjdGl2ZVxyXG4gICAgICAgICAgfSkpO1xyXG4gICAgICAgICAgdGhpcy50YWJsZVZpZXdMaXN0UHJvY2VzcyhwYXJzZWRSZXN1bHQpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgZXJyb3I6IChlcnIpID0+IHtcclxuICAgICAgICAgIHRoaXMudGFibGVTZXJ2aWNlLmhhbmRsZVRhYmxlRXJyb3IoZXJyLCAnVmlld3MgZ2V0IGVycm9yJyk7XHJcbiAgICAgICAgICB0aGlzLnN0YXJ0SW5pdGlhbERhdGFMb2FkKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy50YWJsZVZpZXdMaXN0UHJvY2Vzcyh0YWJsZVZpZXdzKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgdGFibGVWaWV3TGlzdFByb2Nlc3ModGFibGVWaWV3czogSVRhYmxlVmlld1tdKXtcclxuICAgIHRoaXMudGFibGVWaWV3c0xpc3QgPSBbLi4udGFibGVWaWV3c107XHJcbiAgICBpZih0aGlzLnRhYmxlVmlld3NMaXN0Lmxlbmd0aCA+IDApe1xyXG4gICAgICB0aGlzLnRhYmxlU2VydmljZS5zb3J0Vmlld3ModGhpcy50YWJsZVZpZXdzTGlzdCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLnRhYmxlVmlld3NfbWVudUl0ZW1zPVsuLi50aGlzLnRhYmxlU2VydmljZS51cGRhdGVWaWV3c01lbnVJdGVtcyh0aGlzLnRhYmxlVmlld3NMaXN0KV07XHJcbiAgICB0aGlzLnN0YXJ0SW5pdGlhbERhdGFMb2FkKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN0YXJ0SW5pdGlhbERhdGFMb2FkKCk6IHZvaWQge1xyXG4gICAgaWYgKHRoaXMuaW5pdGlhbFN0YXRlQXBwbGllZCB8fCB0aGlzLmRlc3Ryb3llZCkgcmV0dXJuO1xyXG4gICAgY29uc3QgcmVzdG9yZWQgPSB0aGlzLnJlc3RvcmVOYXZpZ2F0aW9uU3RhdGUoKTtcclxuICAgIHRoaXMuaW5pdGlhbFN0YXRlQXBwbGllZCA9IHRydWU7XHJcbiAgICBjb25zdCB2aWV3VG9TdGFydHVwID0gcmVzdG9yZWQgPyB1bmRlZmluZWQgOiB0aGlzLnRhYmxlVmlld3NMaXN0LmZpbmQodiA9PiB2Lmxhc3RBY3RpdmUpO1xyXG4gICAgaWYgKHZpZXdUb1N0YXJ0dXApIHsgLy8gSWYgdGhlcmUgaXMgYSB2aWV3IHRoYXQgbmVlZHMgdG8gYmUgbG9hZGVkIG9uIHN0YXJ0dXBcclxuICAgICAgdGhpcy52aWV3TG9hZCh2aWV3VG9TdGFydHVwLnZpZXdBbGlhcyk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmZldGNoVGFibGVEYXRhKHRoaXMudGFibGVMYXp5TG9hZEV2ZW50SW5mb3JtYXRpb24pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgdmlld0xvYWQodGFibGVWaWV3QWxpYXM6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgY29uc3Qgdmlld1RvTG9hZDogSVRhYmxlVmlldyB8IHVuZGVmaW5lZCA9IHRoaXMudGFibGVWaWV3c0xpc3QuZmluZCh2ID0+IHYudmlld0FsaWFzID09PSB0YWJsZVZpZXdBbGlhcyk7XHJcbiAgICBpZighdmlld1RvTG9hZCl7XHJcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uLnNob3dUb2FzdChcImVycm9yXCIsIHRoaXMuaTE4bi50ZXh0KFwiVklFVyBUTyBMT0FEIERPRVNOJ1QgRVhJU1RcIiksIHRoaXMuaTE4bi50ZXh0KFwiVGhlIHZpZXcgdG8gbG9hZCBkb2Vzbid0IGV4aXN0XCIpKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy5jb2x1bW5TZWxlY3Rpb25DdXN0b21pemVkID0gdHJ1ZTtcclxuICAgIGxldCB2aWV3RGF0YTogSVRhYmxlVmlld0RhdGEgPSB2aWV3VG9Mb2FkLnZpZXdEYXRhO1xyXG4gICAgdGhpcy50cmVlU3RhdGU/LnJlc3RvcmUodmlld0RhdGEudHJlZUV4cGFuZGVkS2V5cywgdmlld0RhdGEudHJlZUNoaWxkUGFnZXMpO1xyXG4gICAgdGhpcy50cmVlU3RhdGVSZXN0b3JlZCA9ICEhdGhpcy50cmVlU3RhdGU7XHJcbiAgICB0aGlzLmNvbHVtbnNTZWxlY3RlZCA9IHZpZXdEYXRhLmNvbHVtbnNTaG93blxyXG4gICAgICAgIC5tYXAoZGF0YSA9PiB0aGlzLmNvbHVtbnMuZmluZCgoY29sOiBhbnkpID0+IGNvbC5maWVsZCA9PT0gZGF0YS5maWVsZCkpXHJcbiAgICAgICAgLmZpbHRlcigoY29sKTogY29sIGlzIElDb2x1bW5NZXRhZGF0YSA9PiBjb2wgIT09IHVuZGVmaW5lZClcclxuICAgICAgICAuZmlsdGVyKGNvbCA9PiAhdGhpcy5jb2x1bW5zQ2FudEJlSGlkZGVuLmluY2x1ZGVzKGNvbCkpO1xyXG4gICAgdGhpcy50YWJsZU9wdGlvbnMuY29sdW1ucyEuc2hvd24gPSB0aGlzLnRhYmxlU2VydmljZS5vcmRlckNvbHVtbnNXaXRoRnJvemVucyh0aGlzLmNvbHVtbnNDYW50QmVIaWRkZW4uY29uY2F0KHRoaXMuY29sdW1uc1NlbGVjdGVkKSk7XHJcbiAgICB0aGlzLmN1cnJlbnRQYWdlID0gdmlld0RhdGEuY3VycmVudFBhZ2U7XHJcbiAgICB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSA9IHZpZXdEYXRhLmN1cnJlbnRSb3dzUGVyUGFnZTtcclxuICAgIHRoaXMucmVzdG9yZUdsb2JhbFNlYXJjaCh2aWV3RGF0YS5nbG9iYWxTZWFyY2hUZXh0KTtcclxuICAgIHRoaXMudGFibGVPcHRpb25zLmlzQWN0aXZlID0gZmFsc2U7XHJcbiAgICB0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uLm11bHRpU29ydE1ldGEgPSBbLi4uKHZpZXdEYXRhLm11bHRpU29ydE1ldGEgPz8gW10pXTtcclxuICAgIHRoaXMuZHQubXVsdGlTb3J0TWV0YSA9IFsuLi4odmlld0RhdGEubXVsdGlTb3J0TWV0YSA/PyBbXSldO1xyXG4gICAgdGhpcy5kdC5zb3J0TXVsdGlwbGUoKTtcclxuICAgIHRoaXMuZHQuZmlyc3QgPSB0aGlzLmN1cnJlbnRQYWdlICogdGhpcy5jdXJyZW50Um93c1BlclBhZ2U7XHJcbiAgICB0aGlzLmR0LnJvd3MgPSB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZTtcclxuICAgIHRoaXMudGFibGVMYXp5TG9hZEV2ZW50SW5mb3JtYXRpb24uZmlyc3QgPSB0aGlzLmR0LmZpcnN0O1xyXG4gICAgdGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbi5yb3dzID0gdGhpcy5jdXJyZW50Um93c1BlclBhZ2U7XHJcbiAgICB0aGlzLnRhYmxlT3B0aW9ucy5pc0FjdGl2ZSA9IHRydWU7XHJcbiAgICB0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uLmZpbHRlcnMgPSBzdHJ1Y3R1cmVkQ2xvbmUodmlld0RhdGEuZmlsdGVycyk7XHJcbiAgICB0aGlzLmR0LmZpbHRlcnMgPSBzdHJ1Y3R1cmVkQ2xvbmUodmlld0RhdGEuZmlsdGVycyk7XHJcbiAgICB0aGlzLnJlc3RvcmVQcmVkZWZpbmVkU2VsZWN0aW9ucyh2aWV3RGF0YS5maWx0ZXJzKTtcclxuICAgIHRoaXMuZHQudGFibGVXaWR0aFN0YXRlID0gdmlld0RhdGEudGFibGVXaWR0aDtcclxuICAgIHRoaXMuZHQuY29sdW1uV2lkdGhzU3RhdGUgPSB2aWV3RGF0YS5jb2x1bW5zV2lkdGg7XHJcbiAgICB0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzID0gdGFibGVWaWV3QWxpYXM7XHJcbiAgICB0aGlzLm5vdGlmaWNhdGlvbi5zaG93VG9hc3QoXCJpbmZvXCIsIHRoaXMuaTE4bi50ZXh0KFwiVEFCTEUgVklFVyBSRVNUT1JFRFwiKSwgdGhpcy5pMThuLnRleHQoXCJUaGUgdGFibGUgdmlldyAne3t2YWx1ZTB9fScgaGFzIGJlZW4gcmVzdG9yZWQuXCIsIHsgdmFsdWUwOiB0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzIH0pKTtcclxuICAgIHRoaXMudmlld3NNb2RhbFNob3cgPSBmYWxzZTtcclxuICAgIHRoaXMuZmV0Y2hUYWJsZURhdGEodGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbik7XHJcbiAgfVxyXG5cclxuICB2aWV3Q3JlYXRlKHZpZXdBbGlhczogc3RyaW5nKXtcclxuICAgIGlmKHRoaXMudGFibGVWaWV3c0xpc3QubGVuZ3RoID49IHRoaXMubWF4Vmlld3Mpe1xyXG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbi5zaG93VG9hc3QoXCJlcnJvclwiLCB0aGlzLmkxOG4udGV4dChcIk5PIE1PUkUgVklFV1MgQUxMT1dFRFwiKSwgdGhpcy5pMThuLnRleHQoXCJZb3UgaGF2ZSBjcmVhdGVkIHRoZSBtYXhpbXVtIG51bWJlciBvZiBhbGxvd2VkIHZpZXdzIGZvciB0aGlzIHRhYmxlXCIpKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgbGV0IHZpZXdEYXRhOiBJVGFibGVWaWV3RGF0YSA9IHRoaXMuZ2VuZXJhdGVWaWV3RGF0YSgpO1xyXG4gICAgbGV0IG5ld1ZpZXc6IElUYWJsZVZpZXcgPSB7XHJcbiAgICAgIGxhc3RBY3RpdmU6IGZhbHNlLFxyXG4gICAgICB2aWV3QWxpYXM6IHZpZXdBbGlhcyxcclxuICAgICAgdmlld0RhdGE6IHZpZXdEYXRhXHJcbiAgICB9XHJcbiAgICB0aGlzLnRhYmxlVmlld3NMaXN0LnB1c2gobmV3Vmlldyk7XHJcbiAgICB0aGlzLnRhYmxlU2VydmljZS5zb3J0Vmlld3ModGhpcy50YWJsZVZpZXdzTGlzdCk7XHJcbiAgICB0aGlzLnRhYmxlVmlld3NfbWVudUl0ZW1zPVsuLi50aGlzLnRhYmxlU2VydmljZS51cGRhdGVWaWV3c01lbnVJdGVtcyh0aGlzLnRhYmxlVmlld3NMaXN0KV07XHJcbiAgICB0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzID0gdmlld0FsaWFzO1xyXG4gICAgdGhpcy52aWV3c1NhdmUoMCk7XHJcbiAgfVxyXG5cclxuICB2aWV3RGVsZXRlKHZpZXdBbGlhczogc3RyaW5nKXtcclxuICAgIGNvbnN0IGluZGV4ID0gdGhpcy50YWJsZVZpZXdzTGlzdC5maW5kSW5kZXgodiA9PiB2LnZpZXdBbGlhcyA9PT0gdmlld0FsaWFzKTtcclxuICAgIGlmIChpbmRleCA9PT0gLTEpIHtcclxuICAgICAgdGhpcy5ub3RpZmljYXRpb24uc2hvd1RvYXN0KFwiZXJyb3JcIiwgdGhpcy5pMThuLnRleHQoXCJUYWJsZSB2aWV3IGRlbGV0ZSBmYWlsZWRcIiksIHRoaXMuaTE4bi50ZXh0KFwiVGhlIHRhYmxlIHZpZXcgY291bGQgbm90IGJlIGRlbGV0ZWQgc2luY2UgaXQgd2FzIG5vdCBmb3VuZC5cIikpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnRhYmxlVmlld3NMaXN0LnNwbGljZShpbmRleCwgMSk7XHJcbiAgICB0aGlzLnRhYmxlVmlld3NfbWVudUl0ZW1zPVsuLi50aGlzLnRhYmxlU2VydmljZS51cGRhdGVWaWV3c01lbnVJdGVtcyh0aGlzLnRhYmxlVmlld3NMaXN0KV07XHJcbiAgICBpZih0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzID09PSB2aWV3QWxpYXMpe1xyXG4gICAgICB0aGlzLnRhYmxlVmlld0N1cnJlbnRTZWxlY3RlZEFsaWFzID0gbnVsbDtcclxuICAgIH1cclxuICAgIHRoaXMudmlld3NTYXZlKDMpO1xyXG4gIH1cclxuXHJcbiAgdmlld0VkaXRBbGlhcyhldmVudDogeyB2aWV3QWxpYXNPbGQ6IHN0cmluZzsgdmlld0FsaWFzTmV3OiBzdHJpbmcgfSl7XHJcbiAgICBjb25zdCBpbmRleCA9IHRoaXMudGFibGVWaWV3c0xpc3QuZmluZEluZGV4KHYgPT4gdi52aWV3QWxpYXMgPT09IGV2ZW50LnZpZXdBbGlhc09sZCk7XHJcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7XHJcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uLnNob3dUb2FzdChcImVycm9yXCIsIHRoaXMuaTE4bi50ZXh0KFwiVGFibGUgdmlldyBhbGlhcyBjaGFuZ2UgZmFpbGVkXCIpLCB0aGlzLmkxOG4udGV4dChcIlRoZSB0YWJsZSB2aWV3IGFsaWFzIGNvdWxkIG5vdCBiZSBjaGFuZ2VkIHNpbmNlIGl0IHdhcyBub3QgZm91bmQuXCIpKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgdGhpcy50YWJsZVZpZXdzTGlzdFtpbmRleF0udmlld0FsaWFzID0gZXZlbnQudmlld0FsaWFzTmV3O1xyXG4gICAgdGhpcy50YWJsZVNlcnZpY2Uuc29ydFZpZXdzKHRoaXMudGFibGVWaWV3c0xpc3QpO1xyXG4gICAgdGhpcy50YWJsZVZpZXdzX21lbnVJdGVtcz1bLi4udGhpcy50YWJsZVNlcnZpY2UudXBkYXRlVmlld3NNZW51SXRlbXModGhpcy50YWJsZVZpZXdzTGlzdCldO1xyXG4gICAgaWYodGhpcy50YWJsZVZpZXdDdXJyZW50U2VsZWN0ZWRBbGlhcyA9PT0gZXZlbnQudmlld0FsaWFzT2xkKXtcclxuICAgICAgdGhpcy50YWJsZVZpZXdDdXJyZW50U2VsZWN0ZWRBbGlhcyA9IGV2ZW50LnZpZXdBbGlhc05ldztcclxuICAgIH1cclxuICAgIHRoaXMudmlld3NTYXZlKDIpO1xyXG4gIH1cclxuXHJcbiAgdmlld1VwZGF0ZURhdGEodmlld0FsaWFzOiBzdHJpbmcpe1xyXG4gICAgY29uc3QgaW5kZXggPSB0aGlzLnRhYmxlVmlld3NMaXN0LmZpbmRJbmRleCh2ID0+IHYudmlld0FsaWFzID09PSB2aWV3QWxpYXMpO1xyXG4gICAgaWYgKGluZGV4ID09PSAtMSkge1xyXG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbi5zaG93VG9hc3QoXCJlcnJvclwiLCB0aGlzLmkxOG4udGV4dChcIlRhYmxlIHZpZXcgbm90IGZvdW5kXCIpLCB0aGlzLmkxOG4udGV4dChcIlRoZSB0YWJsZSB2aWV3IHRvIHVwZGF0ZSBkYXRhIGZyb20gd2FzIG5vdCBmb3VuZC5cIikpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBsZXQgdmlld0RhdGE6IElUYWJsZVZpZXdEYXRhID0gdGhpcy5nZW5lcmF0ZVZpZXdEYXRhKCk7XHJcbiAgICB0aGlzLnRhYmxlVmlld3NMaXN0W2luZGV4XS52aWV3RGF0YSA9IHZpZXdEYXRhO1xyXG4gICAgdGhpcy52aWV3c1NhdmUoMSk7XHJcbiAgfVxyXG5cclxuICB2aWV3VXBkYXRlQWN0aXZlU3RhcnR1cCh2aWV3QWxpYXM6IHN0cmluZyl7XHJcbiAgICBjb25zdCBpbmRleCA9IHRoaXMudGFibGVWaWV3c0xpc3QuZmluZEluZGV4KHYgPT4gdi52aWV3QWxpYXMgPT09IHZpZXdBbGlhcyk7XHJcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7XHJcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uLnNob3dUb2FzdChcImVycm9yXCIsIHRoaXMuaTE4bi50ZXh0KFwiVGFibGUgdmlldyBub3QgZm91bmRcIiksIHRoaXMuaTE4bi50ZXh0KFwiVGhlIHRhYmxlIHZpZXcgdG8gdXBkYXRlIGRhdGEgZnJvbSB3YXMgbm90IGZvdW5kLlwiKSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGxldCBuZXdTdGF0dXM6IGJvb2xlYW4gPSAhdGhpcy50YWJsZVZpZXdzTGlzdFtpbmRleF0ubGFzdEFjdGl2ZTtcclxuICAgIHRoaXMudGFibGVWaWV3c0xpc3QuZm9yRWFjaCh2ID0+IHYubGFzdEFjdGl2ZSA9IGZhbHNlKTtcclxuICAgIHRoaXMudGFibGVWaWV3c0xpc3RbaW5kZXhdLmxhc3RBY3RpdmUgPSBuZXdTdGF0dXM7XHJcbiAgICB0aGlzLnRhYmxlVmlld3NfbWVudUl0ZW1zPVsuLi50aGlzLnRhYmxlU2VydmljZS51cGRhdGVWaWV3c01lbnVJdGVtcyh0aGlzLnRhYmxlVmlld3NMaXN0KV07XHJcbiAgICB0aGlzLnZpZXdzU2F2ZSg0KTtcclxuICB9XHJcblxyXG4gIHZpZXdzU2F2ZShlbmRNZXNzYWdlOiBudW1iZXIpOiB2b2lke1xyXG4gICAgbGV0IHRhYmxlVmlldzogc3RyaW5nID0gSlNPTi5zdHJpbmdpZnkodGhpcy50YWJsZVZpZXdzTGlzdCk7XHJcbiAgICBzd2l0Y2godGhpcy50YWJsZU9wdGlvbnMudmlld3MhLnNhdmVNb2RlKXtcclxuICAgICAgY2FzZSBUYWJsZVZpZXdTYXZlTW9kZS5TZXNzaW9uU3RvcmFnZTpcclxuICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKHRoaXMudGFibGVPcHRpb25zLnZpZXdzIS5zYXZlS2V5ISwgdGFibGVWaWV3KTtcclxuICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgVGFibGVWaWV3U2F2ZU1vZGUuTG9jYWxTdG9yYWdlOlxyXG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKHRoaXMudGFibGVPcHRpb25zLnZpZXdzIS5zYXZlS2V5ISwgdGFibGVWaWV3KTtcclxuICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgVGFibGVWaWV3U2F2ZU1vZGUuRGF0YWJhc2VTdG9yYWdlOlxyXG4gICAgICAgIGNvbnN0IHNhdmVPYnN2ID0gdGhpcy50YWJsZVNlcnZpY2Uudmlld3NTYXZlVG9EYXRhYmFzZSh0aGlzLnRhYmxlVmlld3NMaXN0LCB0aGlzLnRhYmxlT3B0aW9ucy52aWV3cyEudXJsU2F2ZSEsIHRoaXMudGFibGVPcHRpb25zLnZpZXdzIS5zYXZlS2V5ISk7XHJcbiAgICAgICAgc2F2ZU9ic3Yuc3Vic2NyaWJlKHtcclxuICAgICAgICAgIG5leHQ6IChyZXNwb25zZTogSHR0cFJlc3BvbnNlPGFueT4pID0+IHtcclxuICAgICAgICAgICAgdGhpcy52aWV3c1NhdmVFbmQoZW5kTWVzc2FnZSk7XHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICAgZXJyb3I6IChlcnIpID0+IHRoaXMudGFibGVTZXJ2aWNlLmhhbmRsZVRhYmxlRXJyb3IoZXJyLCAnVmlld3Mgc2F2ZSBlcnJvcicpXHJcbiAgICAgICAgfSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbi5zaG93VG9hc3QoXCJlcnJvclwiLCB0aGlzLmkxOG4udGV4dChcIk5PVCBJTVBMRU1FTlRFRFwiKSwgdGhpcy5pMThuLnRleHQoXCJUaGlzIHR5cGUgb3Mgc2F2ZSB2aWV3IGhhcyBub3QgYmVlbiBpbXBsZW1lbnRlZCB5ZXQuXCIpKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnZpZXdzU2F2ZUVuZChlbmRNZXNzYWdlKTtcclxuICB9XHJcbiAgdmlld3NTYXZlRW5kKGVuZE1lc3NhZ2U6IG51bWJlcil7XHJcbiAgICB0aGlzLmNoYW5nZURldGVjdG9yPy5tYXJrRm9yQ2hlY2soKTtcclxuICAgIHN3aXRjaChlbmRNZXNzYWdlKXtcclxuICAgICAgY2FzZSAwOiAvLyBORVcgVklFV1xyXG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uLnNob3dUb2FzdChcImluZm9cIiwgdGhpcy5pMThuLnRleHQoXCJUYWJsZSB2aWV3IGNyZWF0ZWRcIiksIHRoaXMuaTE4bi50ZXh0KFwiTmV3IHRhYmxlIHZpZXcgaGFzIGJlZW4gY3JlYXRlZC5cIikpO1xyXG4gICAgICAgIHRoaXMudmlld3NNb2RhbFNob3cgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSAxOiAvLyBVUERBVEUgVklFV1xyXG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uLnNob3dUb2FzdChcImluZm9cIiwgdGhpcy5pMThuLnRleHQoXCJUYWJsZSB2aWV3IGRhdGEgdXBkYXRlZFwiKSwgdGhpcy5pMThuLnRleHQoXCJUaGUgdGFibGUgdmlldyBkYXRhIHdhcyB1cGRhdGVkLlwiKSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgMjogLy8gVVBEQVRFIEFMSUFTXHJcbiAgICAgICAgdGhpcy5ub3RpZmljYXRpb24uc2hvd1RvYXN0KFwiaW5mb1wiLCB0aGlzLmkxOG4udGV4dChcIlRhYmxlIHZpZXcgbmFtZSB1cGRhdGVkXCIpLCB0aGlzLmkxOG4udGV4dChcIlRoZSB0YWJsZSB2aWV3IGFsaWFzIHdhcyB1cGRhdGVkLlwiKSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgMzogLy8gREVMRVRFIFZJRVdcclxuICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbi5zaG93VG9hc3QoXCJpbmZvXCIsIHRoaXMuaTE4bi50ZXh0KFwiVGFibGUgdmlldyBkZWxldGVcIiksIHRoaXMuaTE4bi50ZXh0KFwiVGhlIHRhYmxlIHZpZXcgd2FzIGRlbGV0ZWQuXCIpKTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSA0OiAvLyBERUxFVEUgVklFV1xyXG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uLnNob3dUb2FzdChcImluZm9cIiwgdGhpcy5pMThuLnRleHQoXCJUYWJsZSB2aWV3IGFjdGl2ZSBvbiBzdGFydHVwXCIpLCB0aGlzLmkxOG4udGV4dChcIkNoYW5nZWQgdGhlIHZpZXcgdGhhdCB3aWxsIGJlIGFjdGl2ZSBvbiBzdGFydHVwLlwiKSk7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBmZXRjaFRhYmxlRGF0YShldmVudDogVGFibGVMYXp5TG9hZEV2ZW50KTogdm9pZCB7XHJcbiAgICBpZighdGhpcy5jYW5GZXRjaERhdGEoKSl7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICghdGhpcy5pbml0aWFsQ29uZmlndXJhdGlvbkZldGNoZWQgfHwgIXRoaXMuaW5pdGlhbFN0YXRlQXBwbGllZCkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnJlc3BvbnNpdmVSb3dNZW51Py5oaWRlKCk7XHJcbiAgICB0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uID0gZXZlbnQ7IC8vIFN0b3JlIHRoZSBldmVudCBpbmZvcm1hdGlvbiBmb3IgbGF0ZXIgdXNlXHJcbiAgICBpZiAoZXZlbnQucm93cyAhPSBudWxsICYmIGV2ZW50LnJvd3MgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSA9IGV2ZW50LnJvd3M7XHJcbiAgICB9XHJcbiAgICBpZiAoZXZlbnQuZmlyc3QgIT0gbnVsbCAmJiBldmVudC5maXJzdCAhPT0gdW5kZWZpbmVkICYmIGV2ZW50LnJvd3MgIT0gbnVsbCAmJiBldmVudC5yb3dzICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgdGhpcy5jdXJyZW50UGFnZSA9IGV2ZW50LmZpcnN0IC8gZXZlbnQucm93cztcclxuICAgIH1cclxuICAgIGxldCBmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cyA9IHRoaXMubW9kaWZ5RmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3ModGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbi5maWx0ZXJzKTsgLy8gQ3JlYXRlIGZpbHRlcnMgZXhjbHVkaW5nIHRoZSBnbG9iYWwgZmlsdGVyXHJcbiAgICBmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cz10aGlzLnJldmVydERhdGVUaW1lWm9uZUZpbHRlcnMoZmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3MpO1xyXG4gICAgY29uc3QgcmVxdWVzdERhdGE6IElUYWJsZVF1ZXJ5UmVxdWVzdCA9IHtcclxuICAgICAgcGFnZTogdGhpcy5jdXJyZW50UGFnZSwgLy8gU2V0IHRoZSBjdXJyZW50IHBhZ2UgbnVtYmVyXHJcbiAgICAgIHBhZ2VTaXplOiB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSwgLy8gU2V0IHRoZSBudW1iZXIgb2Ygcm93cyBwZXIgcGFnZVxyXG4gICAgICBzb3J0OiB0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uLm11bHRpU29ydE1ldGEsIC8vIFNldCB0aGUgc29ydGluZyBpbmZvcm1hdGlvblxyXG4gICAgICBmaWx0ZXI6IGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzLCAvLyBTZXQgdGhlIGZpbHRlcnMgZXhjbHVkaW5nIHRoZSBnbG9iYWwgZmlsdGVyXHJcbiAgICAgIGdsb2JhbEZpbHRlcjogdGhpcy5lZmZlY3RpdmVHbG9iYWxTZWFyY2hUZXh0LCAvLyBVc2UgdGhlIGFwcGxpZWQgcXVlcnksIG5vdCBwZW5kaW5nIGlucHV0XHJcbiAgICAgIGNvbHVtbnM6IHRoaXMudGFibGVPcHRpb25zLmNvbHVtbnMhLnNob3duIS5tYXAoY29sID0+IGNvbC5maWVsZCksIC8vIFNldCB0aGUgY29sdW1ucyB0byBzaG93XHJcbiAgICAgIGRhdGVGb3JtYXQ6IHRoaXMuZGF0ZUZvcm1hdCxcclxuICAgICAgZGF0ZVRpbWV6b25lOiB0aGlzLmRhdGVUaW1lem9uZSxcclxuICAgICAgZGF0ZUN1bHR1cmU6IHRoaXMuZGF0ZUN1bHR1cmUsXHJcbiAgICAgIGV4cG9ydERhdGVGb3JtYXQ6IHRoaXMuZXhwb3J0RGF0ZUZvcm1hdFxyXG4gICAgfTtcclxuICAgIGNvbnN0IHNlbGVjdGlvbktleSA9IEpTT04uc3RyaW5naWZ5KHsgLi4ucmVxdWVzdERhdGEsIHBhZ2U6IDAsIHBhZ2VTaXplOiAwLCBzb3J0OiBudWxsIH0pO1xyXG4gICAgaWYgKHNlbGVjdGlvbktleSAhPT0gdGhpcy5zZWxlY3Rpb25RdWVyeUtleSkgdGhpcy5tYXRjaGluZ1NlbGVjdGlvbktleXMgPSB1bmRlZmluZWQ7XHJcbiAgICB0aGlzLnNlbGVjdGlvblF1ZXJ5S2V5ID0gc2VsZWN0aW9uS2V5O1xyXG4gICAgdGhpcy5zZWxlY3Rpb25RdWVyeSA9IHN0cnVjdHVyZWRDbG9uZShyZXF1ZXN0RGF0YSk7XHJcbiAgICBpZiAodGhpcy50cmVlU3RhdGUpIHtcclxuICAgICAgY29uc3QgdHJlZSA9IHRoaXMudHJlZVN0YXRlO1xyXG4gICAgICBpZiAoIXRoaXMudHJlZVN0YXRlUmVzdG9yZWQpIHRyZWUucmVzdG9yZShbLi4udHJlZS5leHBhbmRlZF0sIHRyZWUuc25hcHNob3RQYWdlcygpKTtcclxuICAgICAgdGhpcy50cmVlU3RhdGVSZXN0b3JlZCA9IGZhbHNlO1xyXG4gICAgICBjb25zdCBzdHJ1Y3R1cmFsID0gW3RyZWUub3B0aW9ucy5rZXlFeHByLCB0cmVlLm9wdGlvbnMucGFyZW50SWRFeHByLCB0cmVlLm9wdGlvbnMuaGFzSXRlbXNFeHByLCAncm93SUQnXTtcclxuICAgICAgcmVxdWVzdERhdGEuY29sdW1ucyA9IFsuLi5uZXcgU2V0KFsuLi5yZXF1ZXN0RGF0YS5jb2x1bW5zISwgLi4uc3RydWN0dXJhbC5maWx0ZXIoKGZpZWxkKTogZmllbGQgaXMgc3RyaW5nID0+ICEhZmllbGQpXSldO1xyXG4gICAgICB0aGlzLnRyZWVRdWVyeSA9IHN0cnVjdHVyZWRDbG9uZShyZXF1ZXN0RGF0YSk7XHJcbiAgICAgIGNvbnN0IGxvYWRpbmcgPSB0cmVlLmxvYWQodGhpcy5jdXJyZW50UGFnZSwgdGhpcy5jdXJyZW50Um93c1BlclBhZ2UsIHRoaXMudHJlZUZldGNoZXIocmVxdWVzdERhdGEpKTtcclxuICAgICAgdGhpcy50YWJsZU9wdGlvbnMuZGF0YSA9IFtdO1xyXG4gICAgICBsb2FkaW5nLnRoZW4odXBkYXRlZCA9PiB7XHJcbiAgICAgICAgaWYgKHVwZGF0ZWQgJiYgIXRoaXMuZGVzdHJveWVkKSB0aGlzLnN5bmNUcmVlUm93cygpO1xyXG4gICAgICB9KS5jYXRjaChlcnJvciA9PiB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmRlc3Ryb3llZCkgdGhpcy50YWJsZVNlcnZpY2UuaGFuZGxlVGFibGVFcnJvcihlcnJvciwgJ1RyZWUgZGF0YSBlcnJvcicpO1xyXG4gICAgICB9KS5maW5hbGx5KCgpID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMuZGVzdHJveWVkKSB7XHJcbiAgICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yPy5tYXJrRm9yQ2hlY2soKTtcclxuICAgICAgICAgIHRoaXMub25EYXRhRW5kVXBkYXRlLmVtaXQoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICB0aGlzLnRhYmxlU2VydmljZS5mZXRjaFRhYmxlRGF0YSh0aGlzLnRhYmxlT3B0aW9ucy51cmxUYWJsZURhdGEhLCByZXF1ZXN0RGF0YSlcclxuICAgICAgLnBpcGUoXHJcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuZGVzdHJveSQpLFxyXG4gICAgICAgIGZpbmFsaXplKCgpID0+IHtcclxuICAgICAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCkgcmV0dXJuO1xyXG4gICAgICAgICAgdGhpcy5vbkRhdGFFbmRVcGRhdGUuZW1pdCgpOyAvLyBUaGlzIGlzIGFsd2F5cyBleGVjdXRlZCBhZnRlciBkYXRhIHVwZGF0ZS5cclxuICAgICAgICB9KVxyXG4gICAgICApXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6IChyZXNwb25zZTogSHR0cFJlc3BvbnNlPElUYWJsZVBhZ2VkUmVzcG9uc2U+KSA9PiB0aGlzLmhhbmRsZVRhYmxlRGF0YVJlc3BvbnNlKHJlc3BvbnNlLmJvZHkhKSxcclxuICAgICAgICBlcnJvcjogKGVycikgPT4gdGhpcy50YWJsZVNlcnZpY2UuaGFuZGxlVGFibGVFcnJvcihlcnIsICdDb2x1bW5zIEVycm9yJylcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICBtb2RpZnlGaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cyhmaWx0ZXJzOiBhbnksIG92ZXJyaWRlT3B0aW9uOiBudW1iZXIgPSAtMSk6IGFueSB7XHJcbiAgICBsZXQgZmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3MgPSBzdHJ1Y3R1cmVkQ2xvbmUoZmlsdGVycyA/PyB7fSk7IC8vIENyZWF0ZSBhIGNvcHkgb2YgZmlsdGVycyB0byBkZWxldGUgdGhlIGdsb2JhbC5cclxuICAgIGlmIChmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cy5oYXNPd25Qcm9wZXJ0eSgnZ2xvYmFsJykpIHsgLy8gSWYgdGhlcmUgaXMgYW4gZW50cnkgd2l0aCB0aGUgZ2xvYmFsIGZpbHRlclxyXG4gICAgICBkZWxldGUgZmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3NbJ2dsb2JhbCddOyAvLyBSZW1vdmUgdGhlIGdsb2JhbCBmaWx0ZXJcclxuICAgIH1cclxuICAgIHRoaXMuc2VsZWN0b3JSb3dGaWx0ZXJCdWlsZGVyKGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzLCBvdmVycmlkZU9wdGlvbik7XHJcbiAgICByZXR1cm4gZmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3M7IC8vIFJldHVybiB0aGUgZmlsdGVycyB3aXRob3V0IGdsb2JhbCBhcnJheVxyXG4gIH1cclxuXHJcbiAgcmVzZXRUYWJsZVZpZXcoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNhbmNlbEdsb2JhbFNlYXJjaCgpO1xyXG4gICAgY29uc3Qga2V5ID0gdGhpcy50YWJsZU9wdGlvbnMuc3RhdGVQZXJzaXN0ZW5jZT8ua2V5Py50cmltKCk7XHJcbiAgICBpZiAoa2V5KSB0aGlzLnN0YXRlU2NvcGU/LmNsZWFyKGtleSk7XHJcbiAgICB0aGlzLnRyZWVTdGF0ZT8ucmVzdG9yZSgpO1xyXG4gICAgdGhpcy50cmVlU3RhdGVSZXN0b3JlZCA9ICEhdGhpcy50cmVlU3RhdGU7XHJcbiAgICB0aGlzLmluaXRpYWxTdGF0ZUFwcGxpZWQgPSBmYWxzZTtcclxuICAgIHRoaXMudGFibGVWaWV3Q3VycmVudFNlbGVjdGVkQWxpYXMgPSAnJztcclxuICAgIHRoaXMuZmV0Y2hUYWJsZUNvbmZpZ3VyYXRpb24odHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHNlbGVjdG9yUm93RmlsdGVyQnVpbGRlcihmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93czogYW55LCBvdmVycmlkZU9wdGlvbjogbnVtYmVyID0gLTEpOiB2b2lkIHtcclxuICAgIGlmIChmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cy5oYXNPd25Qcm9wZXJ0eSgnc2VsZWN0b3InKSB8fCBvdmVycmlkZU9wdGlvbiA9PT0gMSB8fCBvdmVycmlkZU9wdGlvbiA9PT0gMikge1xyXG4gICAgICBjb25zdCBzZWxlY3RvckZpbHRlciA9IGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzWydzZWxlY3RvciddPy5bMF07XHJcbiAgICAgIGxldCBmaWx0ZXJUeXBlOiBib29sZWFuIHwgbnVsbCA9IG51bGw7XHJcbiAgICAgIGlmKG92ZXJyaWRlT3B0aW9uPDAgfHwgb3ZlcnJpZGVPcHRpb24+Mil7XHJcbiAgICAgICAgZmlsdGVyVHlwZSA9IHNlbGVjdG9yRmlsdGVyPy52YWx1ZSA/PyBudWxsO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHN3aXRjaCAob3ZlcnJpZGVPcHRpb24pe1xyXG4gICAgICAgICAgY2FzZSAwOiAvLyBBbGxcclxuICAgICAgICAgICAgZmlsdGVyVHlwZSA9IG51bGw7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAxOiAvLyBPbmx5IHNlbGVjdGVkIHJvd3NcclxuICAgICAgICAgICAgZmlsdGVyVHlwZSA9IHRydWU7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgY2FzZSAyOiAvLyBPbmx5IE5PVCBzZWxlY3RlZFxyXG4gICAgICAgICAgICBmaWx0ZXJUeXBlID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgICBpZiAoIWZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzLmhhc093blByb3BlcnR5KCdyb3dJRCcpKSB7XHJcbiAgICAgICAgICBmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93c1sncm93SUQnXSA9IFtcclxuICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgIFwidmFsdWVcIjogbnVsbCxcclxuICAgICAgICAgICAgICAgICAgXCJtYXRjaE1vZGVcIjogXCJpblwiLFxyXG4gICAgICAgICAgICAgICAgICBcIm9wZXJhdG9yXCI6IFwib3JcIlxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgIF07XHJcbiAgICAgIH1cclxuICAgICAgY29uc3QgaWRGaWx0ZXIgPSBmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93c1sncm93SUQnXVswXTtcclxuICAgICAgaWYgKGZpbHRlclR5cGUgPT09IHRydWUpIHtcclxuICAgICAgICAgIGlkRmlsdGVyLm1hdGNoTW9kZSA9IFwiaW5cIjtcclxuICAgICAgICAgIGlkRmlsdGVyLnZhbHVlID0gdGhpcy5zZWxlY3RlZFJvd3NDaGVja2JveDtcclxuICAgICAgfSBlbHNlIGlmIChmaWx0ZXJUeXBlID09PSBmYWxzZSkge1xyXG4gICAgICAgICAgaWRGaWx0ZXIub3BlcmF0b3IgPSBcImFuZFwiXHJcbiAgICAgICAgICBpZEZpbHRlci5tYXRjaE1vZGUgPSBcIm5vdEluXCI7XHJcbiAgICAgICAgICBpZEZpbHRlci52YWx1ZSA9IHRoaXMuc2VsZWN0ZWRSb3dzQ2hlY2tib3g7XHJcbiAgICAgIH0gZWxzZSBpZiAoZmlsdGVyVHlwZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgaWRGaWx0ZXIudmFsdWUgPSBudWxsO1xyXG4gICAgICAgICAgaWRGaWx0ZXIubWF0Y2hNb2RlID0gXCJpblwiO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXZlcnREYXRlVGltZVpvbmVGaWx0ZXJzKGlucHV0RmlsdGVyOiBhbnkpe1xyXG4gICAgdGhpcy50YWJsZU9wdGlvbnMuY29sdW1ucyEuc2hvd24hLmZvckVhY2goKGNvbHVtbikgPT4ge1xyXG4gICAgICBpZiAoY29sdW1uLmRhdGFUeXBlID09PSBEYXRhVHlwZS5EYXRlKSB7IC8vIElmIGl0cyBkYXRlIHR5cGVcclxuICAgICAgICBpZiAoaW5wdXRGaWx0ZXIuaGFzT3duUHJvcGVydHkoY29sdW1uLmZpZWxkKSkge1xyXG4gICAgICAgICAgY29uc3Qgb3JpZ2luYWxEYXRlID0gaW5wdXRGaWx0ZXJbY29sdW1uLmZpZWxkXVswXS52YWx1ZTtcclxuICAgICAgICAgIGlmKG9yaWdpbmFsRGF0ZSAhPT0gbnVsbCAmJiBvcmlnaW5hbERhdGUgaW5zdGFuY2VvZiBEYXRlKXtcclxuICAgICAgICAgICAgY29uc3QgdXRjRGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKG9yaWdpbmFsRGF0ZS5nZXRGdWxsWWVhcigpLCBvcmlnaW5hbERhdGUuZ2V0TW9udGgoKSwgb3JpZ2luYWxEYXRlLmdldERhdGUoKSkpXHJcbiAgICAgICAgICAgIGlucHV0RmlsdGVyW2NvbHVtbi5maWVsZF1bMF0udmFsdWU9dXRjRGF0ZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgcmV0dXJuIGlucHV0RmlsdGVyO1xyXG4gIH1cclxuXHJcbiAgaGFuZGxlVGFibGVEYXRhUmVzcG9uc2UoYm9keTogSVRhYmxlUGFnZWRSZXNwb25zZSk6IHZvaWR7XHJcbiAgICB0aGlzLnRhYmxlT3B0aW9ucy5kYXRhID0gYm9keS5kYXRhOyAvLyBVcGRhdGUgdGhlIHRhYmxlIGRhdGFcclxuICAgIHRoaXMudG90YWxSZWNvcmRzID0gYm9keS50b3RhbFJlY29yZHM7IC8vIFVwZGF0ZSB0aGUgdG90YWwgbnVtYmVyIG9mIHJlY29yZHNcclxuICAgIHRoaXMudG90YWxSZWNvcmRzTm90RmlsdGVyZWQgPSBib2R5LnRvdGFsUmVjb3Jkc05vdEZpbHRlcmVkOyAvLyBVcGRhdGUgdGhlIHRvdGFsIHJlY29yZHMgbm90IGZpbHRlcmVkXHJcbiAgICB0aGlzLmN1cnJlbnRQYWdlID0gYm9keS5wYWdlOyAvLyBVcGRhdGUgdGhlIGN1cnJlbnQgcGFnZVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZW5lcmF0ZVZpZXdEYXRhKCk6IElUYWJsZVZpZXdEYXRhIHtcclxuICAgIGNvbnN0IHZpZXcgPSB0aGlzLnRhYmxlU2VydmljZS52aWV3R2VuZXJhdGVEYXRhKHRoaXMuZHQsIHRoaXMuZWZmZWN0aXZlR2xvYmFsU2VhcmNoVGV4dCwgdGhpcy5jdXJyZW50UGFnZSxcclxuICAgICAgdGhpcy5jdXJyZW50Um93c1BlclBhZ2UsIHRoaXMubW9kaWZ5RmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3MuYmluZCh0aGlzKSk7XHJcbiAgICBpZiAodGhpcy50cmVlU3RhdGUpIHtcclxuICAgICAgdmlldy50cmVlRXhwYW5kZWRLZXlzID0gWy4uLnRoaXMudHJlZVN0YXRlLmV4cGFuZGVkXTtcclxuICAgICAgdmlldy50cmVlQ2hpbGRQYWdlcyA9IHRoaXMudHJlZVN0YXRlLnNuYXBzaG90UGFnZXMoKTtcclxuICAgIH1cclxuICAgIHJldHVybiB2aWV3O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB0cmVlRmV0Y2hlcihxdWVyeTogSVRhYmxlUXVlcnlSZXF1ZXN0KTogKHJlcXVlc3Q6IElUcmVlUmVxdWVzdCkgPT4gUHJvbWlzZTxJVHJlZVJlc3BvbnNlPiB7XHJcbiAgICByZXR1cm4gYXN5bmMgcmVxdWVzdCA9PiB7XHJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmlyc3RWYWx1ZUZyb20odGhpcy50YWJsZVNlcnZpY2UuZmV0Y2hUYWJsZURhdGEodGhpcy50YWJsZU9wdGlvbnMudXJsVGFibGVEYXRhISxcclxuICAgICAgICB7IC4uLnN0cnVjdHVyZWRDbG9uZShxdWVyeSksIC4uLnJlcXVlc3QgfSkucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpKTtcclxuICAgICAgaWYgKCFyZXNwb25zZS5ib2R5KSB0aHJvdyBuZXcgRXJyb3IoJ0VtcHR5IHRyZWUgcmVzcG9uc2UuJyk7XHJcbiAgICAgIHJldHVybiByZXNwb25zZS5ib2R5IGFzIElUcmVlUmVzcG9uc2U7XHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzeW5jVHJlZVJvd3MoKTogdm9pZCB7XHJcbiAgICBjb25zdCB0cmVlID0gdGhpcy50cmVlU3RhdGUhO1xyXG4gICAgdGhpcy50YWJsZU9wdGlvbnMuZGF0YSA9IHRyZWUudmlzaWJsZTtcclxuICAgIHRoaXMudG90YWxSZWNvcmRzID0gdHJlZS50b3RhbFJlY29yZHM7XHJcbiAgICB0aGlzLnRvdGFsUmVjb3Jkc05vdEZpbHRlcmVkID0gdHJlZS50b3RhbFJlY29yZHNOb3RGaWx0ZXJlZDtcclxuICAgIHRoaXMuY3VycmVudFBhZ2UgPSB0cmVlLnBhZ2U7XHJcbiAgICB0aGlzLmNoYW5nZURldGVjdG9yPy5tYXJrRm9yQ2hlY2soKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHRvZ2dsZVRyZWVSb3coZXZlbnQ6IEV2ZW50LCByb3c6IFRyZWVSb3cpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgaWYgKCF0aGlzLnRyZWVTdGF0ZSB8fCAhdGhpcy50cmVlUXVlcnkgfHwgdGhpcy50cmVlU3RhdGUubG9hZGluZykgcmV0dXJuO1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgdXBkYXRlID0gdGhpcy50cmVlU3RhdGUudG9nZ2xlKHJvdywgdGhpcy50cmVlRmV0Y2hlcih0aGlzLnRyZWVRdWVyeSkpO1xyXG4gICAgICB0aGlzLmNoYW5nZURldGVjdG9yPy5tYXJrRm9yQ2hlY2soKTtcclxuICAgICAgYXdhaXQgdXBkYXRlO1xyXG4gICAgICBpZiAoIXRoaXMuZGVzdHJveWVkKSB0aGlzLnN5bmNUcmVlUm93cygpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgaWYgKCF0aGlzLmRlc3Ryb3llZCkgdGhpcy50YWJsZVNlcnZpY2UuaGFuZGxlVGFibGVFcnJvcihlcnJvciwgJ1RyZWUgZGF0YSBlcnJvcicpO1xyXG4gICAgfSBmaW5hbGx5IHtcclxuICAgICAgaWYgKCF0aGlzLmRlc3Ryb3llZCkgeyB0aGlzLmNoYW5nZURldGVjdG9yPy5tYXJrRm9yQ2hlY2soKTsgdGhpcy5vbkRhdGFFbmRVcGRhdGUuZW1pdCgpOyB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyBsb2FkTW9yZVRyZWVSb3dzKGV2ZW50OiBFdmVudCwgcm93OiBUcmVlUm93KTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIGlmICghdGhpcy50cmVlU3RhdGUgfHwgIXRoaXMudHJlZVF1ZXJ5IHx8IHRoaXMudHJlZVN0YXRlLmxvYWRpbmcpIHJldHVybjtcclxuICAgIHRyeSB7XHJcbiAgICAgIGF3YWl0IHRoaXMudHJlZVN0YXRlLmxvYWRNb3JlKHJvdywgdGhpcy50cmVlRmV0Y2hlcih0aGlzLnRyZWVRdWVyeSkpO1xyXG4gICAgICBpZiAoIXRoaXMuZGVzdHJveWVkKSB0aGlzLnN5bmNUcmVlUm93cygpO1xyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgaWYgKCF0aGlzLmRlc3Ryb3llZCkgdGhpcy50YWJsZVNlcnZpY2UuaGFuZGxlVGFibGVFcnJvcihlcnJvciwgJ1RyZWUgZGF0YSBlcnJvcicpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0IHRyZWVDb2x1bW4oKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcclxuICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLnRhYmxlT3B0aW9ucy5jb2x1bW5zPy5zaG93biA/PyBbXTtcclxuICAgIHJldHVybiBjb2x1bW5zLmZpbmQoY29sdW1uID0+IGNvbHVtbi5maWVsZCA9PT0gdGhpcy50cmVlU3RhdGU/Lm9wdGlvbnMuY29sdW1uKT8uZmllbGQgPz8gY29sdW1uc1swXT8uZmllbGQ7XHJcbiAgfVxyXG5cclxuICB0cmVlUGFnZUNoYW5nZShldmVudDogeyBmaXJzdD86IG51bWJlcjsgcm93cz86IG51bWJlciB9KTogdm9pZCB7XHJcbiAgICB0aGlzLmZldGNoVGFibGVEYXRhKHsgLi4udGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbiwgZmlyc3Q6IGV2ZW50LmZpcnN0ID8/IDAsXHJcbiAgICAgIHJvd3M6IGV2ZW50LnJvd3MgPz8gdGhpcy5jdXJyZW50Um93c1BlclBhZ2UgfSk7XHJcbiAgfVxyXG5cclxuICBjbGVhckZpbHRlcnMoZHQ6IFRhYmxlLCBmb3JjZTogYm9vbGVhbiA9IGZhbHNlLCBvbmx5R2xvYmFsRmlsdGVyOiBib29sZWFuID0gZmFsc2UpOiB2b2lke1xyXG4gICAgdGhpcy5jYW5jZWxHbG9iYWxTZWFyY2goKTtcclxuICAgIGxldCBoYXNUb0NsZWFyID0gdGhpcy5oYXNUb0NsZWFyRmlsdGVycyhkdCwgdGhpcy5nbG9iYWxTZWFyY2hUZXh0LCBmb3JjZSk7XHJcbiAgICBpZihoYXNUb0NsZWFyKXtcclxuICAgICAgaWYoIW9ubHlHbG9iYWxGaWx0ZXIpe1xyXG4gICAgICAgIHRoaXMucHJlZGVmaW5lZEZpbHRlcnNTZWxlY3RlZFZhbHVlc0NvbGxlY3Rpb24gPSB7fTtcclxuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBkdC5maWx0ZXJzKSB7XHJcbiAgICAgICAgICBpZiAoZHQuZmlsdGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZpbHRlcnMgPSBkdC5maWx0ZXJzW2tleV07XHJcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcnMpKSB7XHJcbiAgICAgICAgICAgICAgZmlsdGVycy5mb3JFYWNoKGZpbHRlciA9PiB7XHJcbiAgICAgICAgICAgICAgICBmaWx0ZXIudmFsdWUgPSBudWxsOyAgLy8gU2V0IHZhbHVlIHRvIG51bGxcclxuICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBmaWx0ZXJzLnZhbHVlID0gbnVsbDsgLy8gU2V0IHZhbHVlIHRvIG51bGxcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBsZXQgZmlsdGVycyA9IHsuLi50aGlzLmR0LmZpbHRlcnN9O1xyXG4gICAgICAgIGR0LmNvbHVtbnM/LmZvckVhY2goXHJcbiAgICAgICAgICBlbGVtZW50ID0+IHtcclxuICAgICAgICAgICAgZHQuZmlsdGVyKG51bGwsIGVsZW1lbnQuZmllbGQsIGVsZW1lbnQubWF0Y2hNb2RlKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICAgICAgdGhpcy5kdC5maWx0ZXJzID0gZmlsdGVycztcclxuICAgICAgfVxyXG4gICAgICB0aGlzLnJlc3RvcmVHbG9iYWxTZWFyY2gobnVsbCk7XHJcbiAgICAgIGlmICh0aGlzLmdsb2JhbFNlYXJjaE9wdGlvbih0aGlzLnRhYmxlT3B0aW9ucy5nbG9iYWxGaWx0ZXI/Lm1pbkxlbmd0aCkgPiAwIHx8XHJcbiAgICAgICAgICB0aGlzLmdsb2JhbFNlYXJjaE9wdGlvbih0aGlzLnRhYmxlT3B0aW9ucy5nbG9iYWxGaWx0ZXI/LmRlYm91bmNlVGltZSkgPiAwKSB7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50UGFnZSA9IDA7XHJcbiAgICAgICAgZHQuZmlyc3QgPSAwO1xyXG4gICAgICAgIGR0LmZpbHRlcnMgPSB7IC4uLmR0LmZpbHRlcnMsIGdsb2JhbDogeyB2YWx1ZTogbnVsbCwgbWF0Y2hNb2RlOiAnY29udGFpbnMnIH0gfTtcclxuICAgICAgICB0aGlzLmZldGNoVGFibGVEYXRhKHsgLi4udGhpcy50YWJsZUxhenlMb2FkRXZlbnRJbmZvcm1hdGlvbiwgZmlyc3Q6IDAsXHJcbiAgICAgICAgICByb3dzOiB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSwgZmlsdGVyczogZHQuZmlsdGVycyB9KTtcclxuICAgICAgfSBlbHNlIGR0LmZpbHRlckdsb2JhbCgnJywnJyk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjbGVhclNvcnRzKGR0OiBUYWJsZSwgZm9yY2U6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWR7XHJcbiAgICBsZXQgaGFzVG9DbGVhciA9IHRoaXMuaGFzVG9DbGVhclNvcnRzKGR0LCBmb3JjZSk7XHJcbiAgICBpZihoYXNUb0NsZWFyKXtcclxuICAgICAgZHQubXVsdGlTb3J0TWV0YSA9IFtdO1xyXG4gICAgICBkdC5zb3J0TXVsdGlwbGUoKTtcclxuICAgIH1cclxuICB9XHJcbiAgaGFzVG9DbGVhclNvcnRzKGR0OiBUYWJsZSwgZm9yY2U6IGJvb2xlYW4gPSBmYWxzZSk6IGJvb2xlYW57XHJcbiAgICBsZXQgaGFzVG9DbGVhcjogYm9vbGVhbiA9IGZhbHNlO1xyXG4gICAgY29uc3QgaGFzU29ydHMgPSAoZHQubXVsdGlTb3J0TWV0YSAmJiBkdC5tdWx0aVNvcnRNZXRhLmxlbmd0aCA+IDApO1xyXG4gICAgaWYoZm9yY2UgfHwgaGFzU29ydHMpe1xyXG4gICAgICBoYXNUb0NsZWFyID0gdHJ1ZTtcclxuICAgIH1cclxuICAgIHJldHVybiBoYXNUb0NsZWFyO1xyXG4gIH1cclxuICBoYXNUb0NsZWFyRmlsdGVycyhkdDogVGFibGUsIGdsb2JhbFNlYXJjaFRleHQ6IHN0cmluZ3xudWxsLCBmb3JjZTpib29sZWFuID0gZmFsc2UpOiBib29sZWFue1xyXG4gICAgbGV0IGhhc1RvQ2xlYXI6IGJvb2xlYW4gPSBmYWxzZTtcclxuICAgIGNvbnN0IGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzID0gdGhpcy5tb2RpZnlGaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cyhkdC5maWx0ZXJzKVxyXG4gICAgY29uc3QgaGFzRmlsdGVycyA9IHRoaXMuaGFzRmlsdGVycyhmaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cyk7XHJcbiAgICBjb25zdCBoYXNHbG9iYWxGaWx0ZXIgPSAoZ2xvYmFsU2VhcmNoVGV4dCAmJiBnbG9iYWxTZWFyY2hUZXh0LnRyaW0oKSAhPT0gXCJcIik7XHJcbiAgICBpZihmb3JjZSB8fCBoYXNGaWx0ZXJzIHx8IGhhc0dsb2JhbEZpbHRlcil7XHJcbiAgICAgIGhhc1RvQ2xlYXIgPSB0cnVlO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIGhhc1RvQ2xlYXI7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBEZXRlcm1pbmVzIHdoZXRoZXIgdGhlcmUgYXJlIGFjdGl2ZSBmaWx0ZXJzIGJhc2VkIG9uIHRoZSBwcm92aWRlZCBmaWx0ZXIgcnVsZXMuXHJcbiAgICpcclxuICAgKiBAcGFyYW0ge2FueX0gZmlsdGVyUnVsZXMgQW4gb2JqZWN0IHJlcHJlc2VudGluZyBmaWx0ZXIgcnVsZXMgZm9yIGVhY2ggY29sdW1uLlxyXG4gICAqICAgVGhlIGtleXMgYXJlIGNvbHVtbiBuYW1lcywgYW5kIHRoZSB2YWx1ZXMgYXJlIGFycmF5cyBvZiBmaWx0ZXIgcnVsZXMuXHJcbiAgICogICBFYWNoIGZpbHRlciBydWxlIGhhcyB0aGUgZm9sbG93aW5nIHByb3BlcnRpZXM6XHJcbiAgICogICAgIC0gYGZpZWxkYDogVGhlIGZpZWxkIG9yIHByb3BlcnR5IG5hbWUgb2YgdGhlIGNvbHVtbi5cclxuICAgKiAgICAgLSBgdmFsdWVgOiBUaGUgZmlsdGVyIHZhbHVlIGVudGVyZWQgYnkgdGhlIHVzZXIuXHJcbiAgICogICAgIC0gT3RoZXIgcHJvcGVydGllcyBkZXBlbmRpbmcgb24gdGhlIHR5cGUgb2YgZmlsdGVyIChlLmcuLCBgbWF0Y2hNb2RlYCBmb3Igc3RyaW5nIGZpbHRlcnMpLlxyXG4gICAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgYXQgbGVhc3Qgb25lIGFjdGl2ZSBmaWx0ZXIgaXMgZm91bmQsIG90aGVyd2lzZSBgZmFsc2VgLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgaGFzRmlsdGVycyhmaWx0ZXJSdWxlczogYW55KTogYm9vbGVhbiB7XHJcbiAgICBmb3IgKGNvbnN0IGNvbHVtbk5hbWUgb2YgT2JqZWN0LmtleXMoZmlsdGVyUnVsZXMpKSB7IC8vIEl0ZXJhdGUgb3ZlciBlYWNoIGNvbHVtbiBuYW1lIGluIHRoZSBmaWx0ZXIgcnVsZXNcclxuICAgICAgICBjb25zdCBjb2x1bW5GaWx0ZXJzID0gZmlsdGVyUnVsZXNbY29sdW1uTmFtZV07IC8vIEdldCB0aGUgZmlsdGVyIHJ1bGVzIGZvciB0aGUgY3VycmVudCBjb2x1bW5cclxuICAgICAgICBmb3IgKGNvbnN0IGZpbHRlclJ1bGUgb2YgY29sdW1uRmlsdGVycykgeyAvLyBJdGVyYXRlIG92ZXIgZWFjaCBmaWx0ZXIgcnVsZSBmb3IgdGhlIGN1cnJlbnQgY29sdW1uXHJcbiAgICAgICAgICAgIGlmIChmaWx0ZXJSdWxlLnZhbHVlICE9PSBudWxsICYmIGZpbHRlclJ1bGUudmFsdWUgIT09IFwiXCIpIHsgLy8gQ2hlY2sgaWYgdGhlIGZpbHRlciB2YWx1ZSBpcyBub3QgbnVsbCBvciBhbiBlbXB0eSBzdHJpbmdcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlOyAvLyBBdCBsZWFzdCBvbmUgYWN0aXZlIGZpbHRlciBmb3VuZFxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlOyAvLyBObyBhY3RpdmUgZmlsdGVycyBmb3VuZFxyXG4gIH1cclxuXHJcbiAgZ2V0Q29sdW1uU3R5bGUoY29sOiBhbnksIGhlYWRlckNvbHM6IGJvb2xlYW4gPSBmYWxzZSk6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4ge1xyXG4gICAgcmV0dXJuIHRoaXMudGFibGVTZXJ2aWNlLmdldENvbHVtblN0eWxlKGNvbCwgaGVhZGVyQ29scyk7XHJcbiAgfVxyXG5cclxuICBnZXRQcmVkZWZpbmVkRmlsdGVyVmFsdWVzKGNvbHVtbktleU5hbWU6IHN0cmluZyk6IElQcmVkZWZpbmVkRmlsdGVyW10ge1xyXG4gICAgcmV0dXJuIHRoaXMudGFibGVPcHRpb25zLnByZWRlZmluZWRGaWx0ZXJzPy5bY29sdW1uS2V5TmFtZV0gfHwgW107IC8vIFJldHVybiB0aGUgcHJlZGVmaW5lZCBmaWx0ZXIgdmFsdWVzIG9yIGFuIGVtcHR5IGFycmF5IGlmIHRoZSBvcHRpb24gbmFtZSBkb2VzIG5vdCBleGlzdFxyXG4gIH1cclxuXHJcbiAgZ2V0RnJvemVuQ29sdW1uQWxpZ25Bc1RleHQoZnJvemVuQ29sdW1uQWxpZ246IEZyb3plbkNvbHVtbkFsaWduKTogc3RyaW5nIHtcclxuICAgIHJldHVybiBmcm96ZW5Db2x1bW5BbGlnbkFzVGV4dChmcm96ZW5Db2x1bW5BbGlnbik7XHJcbiAgfVxyXG5cclxuICBnZXREYXRhVHlwZUFzVGV4dChkYXRhVHlwZTogRGF0YVR5cGUpOiBzdHJpbmcge1xyXG4gICAgcmV0dXJuIGRhdGFUeXBlQXNUZXh0KGRhdGFUeXBlKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZXMgdGhlIGZpbHRlcnMgb2YgYSBQcmltZU5HIGRhdGEgdGFibGUgYmFzZWQgb24gcHJlZGVmaW5lZCBmaWx0ZXIgY2hhbmdlcy5cclxuICAgKlxyXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmaWx0ZXJOYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGZpbHRlciB0byBiZSB1cGRhdGVkLlxyXG4gICAqIEBwYXJhbSB7SVByaW1lbmdQcmVkZWZpbmVkRmlsdGVyW119IHNlbGVjdGVkVmFsdWVzIC0gQW4gYXJyYXkgb2Ygc2VsZWN0ZWQgcHJlZGVmaW5lZCBmaWx0ZXIgdmFsdWVzLlxyXG4gICAqL1xyXG4gIG9uUHJlZGVmaW5lZEZpbHRlckNoYW5nZShmaWx0ZXJOYW1lOiBzdHJpbmcsIHNlbGVjdGVkVmFsdWVzOiBJUHJlZGVmaW5lZEZpbHRlcltdKTogdm9pZCB7XHJcbiAgICBjb25zdCBmaWx0ZXJzID0geyAuLi50aGlzLmR0LmZpbHRlcnMgfTsgLy8gQ3JlYXRlIGEgc2hhbGxvdyBjb3B5IG9mIHRoZSBjdXJyZW50IGZpbHRlcnMgdG8gYXZvaWQgbXV0YXRpbmcgdGhlIG9yaWdpbmFsIGZpbHRlcnMgZGlyZWN0bHlcclxuICAgIGNvbnN0IG5ld1ZhbHVlID0gc2VsZWN0ZWRWYWx1ZXMgJiYgc2VsZWN0ZWRWYWx1ZXMubGVuZ3RoID8gc2VsZWN0ZWRWYWx1ZXMubWFwKHZhbHVlID0+IHZhbHVlLnZhbHVlKSA6IG51bGw7IC8vIENvbnZlcnQgZW1wdHkgc2VsZWN0aW9uIHRvIG51bGwgc28gUHJpbWVORyByZW1vdmVzIHRoZSBmaWx0ZXIgaW5zdGVhZCBvZiBhcHBseWluZyBhbiBlbXB0eSBhcnJheVxyXG4gICAgaWYgKEFycmF5LmlzQXJyYXkoZmlsdGVyc1tmaWx0ZXJOYW1lXSkpIHsgLy8gQ2hlY2sgaWYgdGhlIGZpbHRlciBmb3IgdGhlIGdpdmVuIGZpbHRlck5hbWUgaXMgYW4gYXJyYXlcclxuICAgICAgKGZpbHRlcnNbZmlsdGVyTmFtZV0gYXMgRmlsdGVyTWV0YWRhdGFbXSkuZm9yRWFjaChjcml0ZXJpYSA9PiB7IC8vIElmIGl0IGlzIGFuIGFycmF5LCBpdGVyYXRlIG92ZXIgZWFjaCBmaWx0ZXIgY3JpdGVyaWFcclxuICAgICAgICAgIGNyaXRlcmlhLnZhbHVlID0gbmV3VmFsdWU7IC8vIFVwZGF0ZSB0aGUgdmFsdWUgb2YgZWFjaCBjcml0ZXJpYSB3aXRoIHRoZSB2YWx1ZXMgZnJvbSBzZWxlY3RlZFZhbHVlc1xyXG4gICAgICB9KTtcclxuICAgIH0gZWxzZSBpZiAoZmlsdGVyc1tmaWx0ZXJOYW1lXSkgeyAvLyBDaGVjayBpZiB0aGUgZmlsdGVyIGZvciB0aGUgZ2l2ZW4gZmlsdGVyTmFtZSBleGlzdHMgYW5kIGlzIG5vdCBhbiBhcnJheVxyXG4gICAgICBjb25zdCBjcml0ZXJpYSA9IGZpbHRlcnNbZmlsdGVyTmFtZV0gYXMgRmlsdGVyTWV0YWRhdGE7IC8vIENhc3QgdGhlIGZpbHRlciBjcml0ZXJpYSB0byBGaWx0ZXJNZXRhZGF0YVxyXG4gICAgICBjcml0ZXJpYS52YWx1ZSA9IG5ld1ZhbHVlOyAvLyBVcGRhdGUgdGhlIHZhbHVlIG9mIHRoZSBjcml0ZXJpYSB3aXRoIHRoZSB2YWx1ZXMgZnJvbSBzZWxlY3RlZFZhbHVlc1xyXG4gICAgfVxyXG4gICAgdGhpcy5kdC5maWx0ZXJzID0gZmlsdGVyczsgLy8gVXBkYXRlIHRoZSBkYXRhIHRhYmxlJ3MgZmlsdGVycyB3aXRoIHRoZSBtb2RpZmllZCBmaWx0ZXJzIG9iamVjdFxyXG4gICAgdGhpcy5kdC5fZmlsdGVyKCk7IC8vIFRyaWdnZXIgdGhlIGZpbHRlcmluZyBvcGVyYXRpb24gb24gdGhlIGRhdGEgdGFibGUgdG8gYXBwbHkgdGhlIG5ldyBmaWx0ZXJzXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDaGVja3MgaWYgdGhlIHByb3ZpZGVkIGNvbHVtbiBtZXRhZGF0YSBtYXRjaGVzIGEgc3BlY2lmaWMgc3R5bGUgb2YgdGhlIHByZWRlZmluZWQgZmlsdGVycyBcclxuICAgKiB0aGF0IG5lZWQgdG8gYmUgYXBwbGllZCB0byBhbiBpdGVtIG9uIGEgcm93LlxyXG4gICAqXHJcbiAgICogQHBhcmFtIHtJcHJpbWVuZ0NvbHVtbnNNZXRhZGF0YX0gY29sTWV0YWRhdGEgLSBUaGUgbWV0YWRhdGEgb2YgdGhlIGNvbHVtbiBiZWluZyBjaGVja2VkLlxyXG4gICAqIEBwYXJhbSB7YW55fSB2YWx1ZSAtIFRoZSB2YWx1ZSB0byBiZSBtYXRjaGVkIGFnYWluc3QgdGhlIHByZWRlZmluZWQgZmlsdGVyIHZhbHVlcy5cclxuICAgKiBAcmV0dXJucyB7YW55fSBUaGUgbWF0Y2hpbmcgcHJlZGVmaW5lZCBmaWx0ZXIgdmFsdWUgaWYgZm91bmQsIG90aGVyd2lzZSBudWxsLlxyXG4gICAqL1xyXG4gIGdldFByZWRmaW5lZEZpbHRlck1hdGNoKGNvbE1ldGFkYXRhOiBJQ29sdW1uTWV0YWRhdGEsIHZhbHVlOiBhbnkpOiBhbnkge1xyXG4gICAgaWYgKGNvbE1ldGFkYXRhLmZpbHRlclByZWRlZmluZWRWYWx1ZXNOYW1lICYmIGNvbE1ldGFkYXRhLmZpbHRlclByZWRlZmluZWRWYWx1ZXNOYW1lLmxlbmd0aCA+IDApIHsgLy8gQ2hlY2sgaWYgdGhlIGNvbHVtbiB1c2VzIHByZWRlZmluZWQgZmlsdGVyIHZhbHVlc1xyXG4gICAgICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmdldFByZWRlZmluZWRGaWx0ZXJWYWx1ZXMoY29sTWV0YWRhdGEuZmlsdGVyUHJlZGVmaW5lZFZhbHVlc05hbWUpOyAvLyBHZXQgdGhlIHByZWRlZmluZWQgZmlsdGVyIHZhbHVlcyBiYXNlZCBvbiB0aGUgbmFtZVxyXG4gICAgICAgIHJldHVybiBvcHRpb25zLmZpbmQob3B0aW9uID0+IG9wdGlvbi52YWx1ZSA9PT0gdmFsdWUpOyAvLyBSZXR1cm4gdGhlIG1hdGNoaW5nIG9wdGlvbiBpZiBmb3VuZFxyXG4gICAgfVxyXG4gICAgcmV0dXJuIG51bGw7IC8vIFJldHVybiBudWxsIGlmIHRoZSBjb2x1bW4gZG9lcyBub3QgdXNlIHByZWRlZmluZWQgZmlsdGVyIHZhbHVlc1xyXG4gIH1cclxuXHJcbiAgY29weVRvQ2xpcGJvYXJkU3RhcnQoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcclxuICAgIGlmKCh0aGlzLnRhYmxlT3B0aW9ucy5jb3B5VG9DbGlwYm9hcmRUaW1lID8/IDApID4gMCkge1xyXG4gICAgICBjb25zdCBjZWxsQ29udGVudCA9IChldmVudC50YXJnZXQgYXMgSFRNTEVsZW1lbnQpLmlubmVyVGV4dDtcclxuICAgICAgdGhpcy5jb3B5Q2VsbERhdGFUaW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIG5hdmlnYXRvci5jbGlwYm9hcmQud3JpdGVUZXh0KGNlbGxDb250ZW50KS50aGVuKCgpID0+IHtcclxuICAgICAgICAgIHRoaXMubm90aWZpY2F0aW9uLmNsZWFyVG9hc3RzKCk7XHJcbiAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbi5zaG93VG9hc3QoXCJpbmZvXCIsIHRoaXMuaTE4bi50ZXh0KFwiQ0VMTCBDT05URU5UIENPUElFRFwiKSwgdGhpcy5pMThuLnRleHQoXCJUaGUgY2VsbCBjb250ZW50IGhhcyBiZWVuIGNvcGllZCB0byB5b3VyIGNsaXBib2FyZC5cIikpO1xyXG4gICAgICAgIH0pLmNhdGNoKGVyciA9PiB7XHJcbiAgICAgICAgICB0aGlzLm5vdGlmaWNhdGlvbi5jbGVhclRvYXN0cygpO1xyXG4gICAgICAgICAgdGhpcy5ub3RpZmljYXRpb24uc2hvd1RvYXN0KFwiZXJyb3JcIiwgdGhpcy5pMThuLnRleHQoXCJDRUxMIENPTlRFTlQgQ09QSUVEXCIpLCB0aGlzLmkxOG4udGV4dChcIlRoZSBjZWxsIGNvbnRlbnQgZmFpbGVkIHRvIGNvcHkgdG8geW91ciBjbGlwYm9hcmQgd2l0aCBlcnJvcjoge3t2YWx1ZTB9fVwiLCB7IHZhbHVlMDogZXJyIH0pKTtcclxuICAgICAgICB9KTtcclxuICAgICAgfSwgKHRoaXMudGFibGVPcHRpb25zLmNvcHlUb0NsaXBib2FyZFRpbWUgPz8gMCkgKiAxMDAwICk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb3B5VG9DbGlwYm9hcmRDYW5jZWwoKXtcclxuICAgIGlmKCh0aGlzLnRhYmxlT3B0aW9ucy5jb3B5VG9DbGlwYm9hcmRUaW1lID8/IDApID4gMCkge1xyXG4gICAgICBjbGVhclRpbWVvdXQodGhpcy5jb3B5Q2VsbERhdGFUaW1lcik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBnZXREYXRhQWxpZ25Ib3Jpem9udGFsQXNUZXh0KGRhdGFBbGlnbkhvcml6b250YWw6IERhdGFBbGlnbkhvcml6b250YWwpe1xyXG4gICAgcmV0dXJuIGRhdGFBbGlnbkhvcml6b250YWxBc1RleHQoZGF0YUFsaWduSG9yaXpvbnRhbCk7XHJcbiAgfVxyXG4gIGdldERhdGFBbGlnblZlcnRpY2FsQXNUZXh0KGRhdGFBbGlnblZlcnRpY2FsOiBEYXRhQWxpZ25WZXJ0aWNhbCl7XHJcbiAgICByZXR1cm4gZGF0YUFsaWduVmVydGljYWxBc1RleHQoZGF0YUFsaWduVmVydGljYWwpO1xyXG4gIH1cclxuXHJcbiAgaXNSb3dDaGVja2JveFNlbGVjdGVkKHJvd0lEOiBhbnkpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkUm93c0NoZWNrYm94LmluY2x1ZGVzKHJvd0lEKTtcclxuICB9XHJcblxyXG4gIGdldCBhbGxNYXRjaGluZ1Jvd3NTZWxlY3RlZCgpOiBib29sZWFuIHtcclxuICAgIGlmICghdGhpcy5tYXRjaGluZ1NlbGVjdGlvbktleXM/Lmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xyXG4gICAgY29uc3Qgc2VsZWN0ZWQgPSBuZXcgU2V0KHRoaXMuc2VsZWN0ZWRSb3dzQ2hlY2tib3gpO1xyXG4gICAgcmV0dXJuIHRoaXMubWF0Y2hpbmdTZWxlY3Rpb25LZXlzLmV2ZXJ5KGtleSA9PiBzZWxlY3RlZC5oYXMoa2V5KSk7XHJcbiAgfVxyXG5cclxuICBnZXQgbWF0Y2hpbmdSb3dzUGFydGlhbGx5U2VsZWN0ZWQoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5hbGxNYXRjaGluZ1Jvd3NTZWxlY3RlZCkgcmV0dXJuIGZhbHNlO1xyXG4gICAgaWYgKCF0aGlzLm1hdGNoaW5nU2VsZWN0aW9uS2V5cykgcmV0dXJuIHRoaXMuc2VsZWN0ZWRSb3dzQ2hlY2tib3gubGVuZ3RoID4gMDtcclxuICAgIGNvbnN0IHNlbGVjdGVkID0gbmV3IFNldCh0aGlzLnNlbGVjdGVkUm93c0NoZWNrYm94KTtcclxuICAgIHJldHVybiB0aGlzLm1hdGNoaW5nU2VsZWN0aW9uS2V5cy5zb21lKGtleSA9PiBzZWxlY3RlZC5oYXMoa2V5KSk7XHJcbiAgfVxyXG5cclxuICBhc3luYyB0b2dnbGVBbGxNYXRjaGluZ1Jvd3MoY2hlY2tlZDogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMudGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I7XHJcbiAgICBpZiAoIW9wdGlvbnM/LmVuYWJsZWQgfHwgIW9wdGlvbnMuc2VsZWN0QWxsRW5hYmxlZCB8fCAhb3B0aW9ucy51cmxTZWxlY3RBbGwgfHxcclxuICAgICAgICAhdGhpcy5zZWxlY3Rpb25RdWVyeSB8fCB0aGlzLnNlbGVjdEFsbExvYWRpbmcpIHJldHVybjtcclxuICAgIGNvbnN0IHF1ZXJ5S2V5ID0gdGhpcy5zZWxlY3Rpb25RdWVyeUtleTtcclxuICAgIHRoaXMuc2VsZWN0QWxsTG9hZGluZyA9IHRydWU7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZpcnN0VmFsdWVGcm9tKHRoaXMudGFibGVTZXJ2aWNlLmZldGNoU2VsZWN0aW9uS2V5cyhvcHRpb25zLnVybFNlbGVjdEFsbCxcclxuICAgICAgICBzdHJ1Y3R1cmVkQ2xvbmUodGhpcy5zZWxlY3Rpb25RdWVyeSkpLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKSk7XHJcbiAgICAgIGlmICh0aGlzLmRlc3Ryb3llZCB8fCBxdWVyeUtleSAhPT0gdGhpcy5zZWxlY3Rpb25RdWVyeUtleSkgcmV0dXJuO1xyXG4gICAgICBpZiAoIUFycmF5LmlzQXJyYXkocmVzcG9uc2UuYm9keSkgfHwgcmVzcG9uc2UuYm9keS5zb21lKGtleSA9PlxyXG4gICAgICAgICAgdHlwZW9mIGtleSAhPT0gJ3N0cmluZycgJiYgdHlwZW9mIGtleSAhPT0gJ251bWJlcicpKSB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc2VsZWN0aW9uIGlkZW50aWZpZXJzLicpO1xyXG4gICAgICBjb25zdCBkaXNhYmxlZEtleXMgPSBuZXcgU2V0KCh0aGlzLnRhYmxlT3B0aW9ucy5kYXRhID8/IFtdKVxyXG4gICAgICAgIC5maWx0ZXIocm93ID0+ICEob3B0aW9ucy5lbmFibGVkQ29uZGl0aW9uPy4ocm93KSA/PyB0cnVlKSkubWFwKHJvdyA9PiByb3cucm93SUQpKTtcclxuICAgICAgY29uc3Qga2V5cyA9IFsuLi5uZXcgU2V0KHJlc3BvbnNlLmJvZHkpXS5maWx0ZXIoa2V5ID0+ICFkaXNhYmxlZEtleXMuaGFzKGtleSkpO1xyXG4gICAgICB0aGlzLm1hdGNoaW5nU2VsZWN0aW9uS2V5cyA9IGtleXM7XHJcbiAgICAgIGNvbnN0IHNlbGVjdGVkID0gbmV3IFNldCh0aGlzLnNlbGVjdGVkUm93c0NoZWNrYm94KTtcclxuICAgICAgY29uc3QgY2hhbmdlZCA9IGtleXMuZmlsdGVyKGtleSA9PiBzZWxlY3RlZC5oYXMoa2V5KSAhPT0gY2hlY2tlZCk7XHJcbiAgICAgIGZvciAoY29uc3Qga2V5IG9mIGNoYW5nZWQpIHtcclxuICAgICAgICBpZiAoY2hlY2tlZCkgc2VsZWN0ZWQuYWRkKGtleSk7IGVsc2Ugc2VsZWN0ZWQuZGVsZXRlKGtleSk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5zZWxlY3RlZFJvd3NDaGVja2JveCA9IFsuLi5zZWxlY3RlZF07XHJcbiAgICAgIGZvciAoY29uc3Qgcm93SUQgb2YgY2hhbmdlZCkgdGhpcy5vblJvd0NoZWNrYm94Q2hhbmdlLmVtaXQoeyByb3dJRCwgc2VsZWN0ZWQ6IGNoZWNrZWQgfSk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBpZiAoIXRoaXMuZGVzdHJveWVkKSB0aGlzLnRhYmxlU2VydmljZS5oYW5kbGVUYWJsZUVycm9yKGVycm9yLCAnU2VsZWN0aW9uIGVycm9yJyk7XHJcbiAgICB9IGZpbmFsbHkge1xyXG4gICAgICB0aGlzLnNlbGVjdEFsbExvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgdGhpcy5jaGFuZ2VEZXRlY3Rvcj8ubWFya0ZvckNoZWNrKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvblJvd0NoZWtib3hDaGFuZ2UoZXZlbnQ6IGFueSwgcm93SUQ6IGFueSk6IHZvaWQge1xyXG4gICAgaWYgKGV2ZW50LmNoZWNrZWQpIHsgLy8gQWRkIHRoZSBzZWxlY3RlZCBpdGVtXHJcbiAgICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkUm93c0NoZWNrYm94LmluY2x1ZGVzKHJvd0lEKSkgdGhpcy5zZWxlY3RlZFJvd3NDaGVja2JveC5wdXNoKHJvd0lEKTtcclxuICAgIH0gZWxzZSB7IC8vIFJlbW92ZSB0aGUgc2VsZWN0ZWQgaXRlbVxyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRSb3dzQ2hlY2tib3ggPSB0aGlzLnNlbGVjdGVkUm93c0NoZWNrYm94LmZpbHRlcihzZWxlY3RlZElkID0+IHNlbGVjdGVkSWQgIT09IHJvd0lEKTtcclxuICAgIH1cclxuICAgIHRoaXMub25Sb3dDaGVja2JveENoYW5nZS5lbWl0KHtcclxuICAgICAgcm93SUQ6IHJvd0lELFxyXG4gICAgICBzZWxlY3RlZDogZXZlbnQuY2hlY2tlZFxyXG4gICAgfSk7XHJcbiAgfVxyXG4gIHJvd1NlbGVjdChldmVudDogVGFibGVSb3dTZWxlY3RFdmVudDxhbnk+KTogdm9pZHtcclxuICAgIHRoaXMub25Sb3dTZWxlY3QuZW1pdCh7XHJcbiAgICAgIHJvd0lEOiBldmVudC5kYXRhLnJvd0lELFxyXG4gICAgICByb3dEYXRhOiBldmVudC5kYXRhXHJcbiAgICB9KTtcclxuICB9XHJcbiAgcm93VW5zZWxlY3QoZXZlbnQ6IFRhYmxlUm93VW5TZWxlY3RFdmVudDxhbnk+KTogdm9pZHtcclxuICAgIHRoaXMub25Sb3dVbnNlbGVjdC5lbWl0KHtcclxuICAgICAgcm93SUQ6IGV2ZW50LmRhdGEucm93SUQsXHJcbiAgICAgIHJvd0RhdGE6IGV2ZW50LmRhdGFcclxuICAgIH0pO1xyXG4gIH1cclxuICBwYWdlQ2hhbmdlKGV2ZW50OiBUYWJsZVBhZ2VFdmVudCk6IHZvaWQge1xyXG4gICAgdGhpcy5jdXJyZW50UGFnZSA9IGV2ZW50LnJvd3MgPyBldmVudC5maXJzdCAvIGV2ZW50LnJvd3MgOiAwO1xyXG4gICAgdGhpcy5jdXJyZW50Um93c1BlclBhZ2UgPSBldmVudC5yb3dzID8gZXZlbnQucm93cyA6IDA7XHJcbiAgfVxyXG5cclxuICBjb2x1bW5TZWxlY3RvclNob3coKXtcclxuICAgIHRoaXMudGFibGVPcHRpb25zLmNvbHVtbnM/LnNlbGVjdG9yT3JkZXJCeUNvbHVtbk5hbWVcclxuICAgIGxldCB0ZW1wRGF0YSA9IHRoaXMuY29sdW1ucy5tYXAoY29sdW1uID0+IHtcclxuICAgICAgY29uc3QgaXNTZWxlY3RlZCA9IHRoaXMuY29sdW1uc1NlbGVjdGVkLnNvbWUoc2VsZWN0ZWRDb2x1bW4gPT4gc2VsZWN0ZWRDb2x1bW4uZmllbGQgPT09IGNvbHVtbi5maWVsZCkgfHwgdGhpcy5jb2x1bW5zQ2FudEJlSGlkZGVuLnNvbWUoc2VsZWN0ZWRDb2x1bW4gPT4gc2VsZWN0ZWRDb2x1bW4uZmllbGQgPT09IGNvbHVtbi5maWVsZCk7XHJcbiAgICAgIGNvbnN0IGlzU2VsZWN0RGlzYWJsZWQgPSAgdGhpcy5jb2x1bW5zQ2FudEJlSGlkZGVuLnNvbWUoc2VsZWN0ZWRDb2x1bW4gPT4gc2VsZWN0ZWRDb2x1bW4uZmllbGQgPT09IGNvbHVtbi5maWVsZCk7XHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgZmllbGQ6IGNvbHVtbi5maWVsZCxcclxuICAgICAgICBoZWFkZXI6IGNvbHVtbi5oZWFkZXIsXHJcbiAgICAgICAgc2VsZWN0ZWQ6IGlzU2VsZWN0ZWQsXHJcbiAgICAgICAgc2VsZWN0RGlzYWJsZWQ6IGlzU2VsZWN0RGlzYWJsZWQsXHJcbiAgICAgICAgY2VsbE92ZXJmbG93QmVoYXZpb3VyOiBjb2x1bW4uY2VsbE92ZXJmbG93QmVoYXZpb3VyLFxyXG4gICAgICAgIGNlbGxPdmVyZmxvd0JlaGF2aW91ckRpc2FibGVkOiAhY29sdW1uLmNlbGxPdmVyZmxvd0JlaGF2aW91ckFsbG93VXNlckVkaXQsXHJcbiAgICAgICAgZGF0YUFsaWduSG9yaXpvbnRhbDogY29sdW1uLmRhdGFBbGlnbkhvcml6b250YWwsXHJcbiAgICAgICAgZGF0YUFsaWduSG9yaXpvbnRhbERpc2FibGVkOiAhY29sdW1uLmRhdGFBbGlnbkhvcml6b250YWxBbGxvd1VzZXJFZGl0LFxyXG4gICAgICAgIGRhdGFBbGlnblZlcnRpY2FsOiBjb2x1bW4uZGF0YUFsaWduVmVydGljYWwsXHJcbiAgICAgICAgZGF0YUFsaWduVmVydGljYWxEaXNhYmxlZDogIWNvbHVtbi5kYXRhQWxpZ25WZXJ0aWNhbEFsbG93VXNlckVkaXRcclxuICAgICAgfTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5jb2x1bW5Nb2RhbERhdGEgPSBbLi4udGVtcERhdGFdO1xyXG4gICAgdGhpcy5maWx0ZXJlZENvbHVtbkRhdGEgPSB0aGlzLmNvbHVtbk1vZGFsRGF0YTtcclxuICAgIHRoaXMuc2hvd0NvbHVtblNlbGVjdG9yPXRydWU7XHJcbiAgfVxyXG5cclxuICBhcHBseUNvbHVtbk1vZGFsQ2hhbmdlcyhzZWxlY3RlZENvbHVtbnM6IElDb2x1bW5NZXRhZGF0YVtdKSB7XHJcbiAgICB0aGlzLmNvbHVtblNlbGVjdGlvbkN1c3RvbWl6ZWQgPSB0cnVlO1xyXG4gICAgY29uc3QgZXhpc3RpbmdDb2x1bW5zID0gdGhpcy5kdC5jb2x1bW5zITtcclxuICAgIGNvbnN0IGNvbHVtbnNUb0tlZXAgPSBuZXcgU2V0PHN0cmluZz4oKTtcclxuXHJcbiAgICB0aGlzLmNvbHVtbnNDYW50QmVIaWRkZW4uZm9yRWFjaChjb2wgPT4gY29sdW1uc1RvS2VlcC5hZGQoY29sLmZpZWxkKSk7XHJcbiAgICBzZWxlY3RlZENvbHVtbnMuZm9yRWFjaChjb2wgPT4gY29sdW1uc1RvS2VlcC5hZGQoY29sLmZpZWxkKSk7XHJcblxyXG4gICAgY29uc3QgZmluYWxDb2x1bW5zOiBJQ29sdW1uTWV0YWRhdGFbXSA9IFtdO1xyXG4gICAgZXhpc3RpbmdDb2x1bW5zLmZvckVhY2goY29sID0+IHtcclxuICAgICAgaWYgKGNvbHVtbnNUb0tlZXAuaGFzKGNvbC5maWVsZCkpIHtcclxuICAgICAgICBmaW5hbENvbHVtbnMucHVzaChjb2wpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBzZWxlY3RlZENvbHVtbnMuZm9yRWFjaChjb2wgPT4ge1xyXG4gICAgICBjb25zdCBtYXRjaGluZ0NvbHVtbiA9IHRoaXMuY29sdW1ucy5maW5kKGMgPT4gYy5maWVsZCA9PT0gY29sLmZpZWxkKTtcclxuICAgICAgaWYgKG1hdGNoaW5nQ29sdW1uICYmICFmaW5hbENvbHVtbnMuZmluZChjID0+IGMuZmllbGQgPT09IG1hdGNoaW5nQ29sdW1uLmZpZWxkKSkge1xyXG4gICAgICAgIGZpbmFsQ29sdW1ucy5wdXNoKG1hdGNoaW5nQ29sdW1uKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgbGV0IHByZXZDb2xzVG9TaG93ID0gdGhpcy50YWJsZU9wdGlvbnMuY29sdW1ucyEuc2hvd247XHJcbiAgICB0aGlzLnRhYmxlT3B0aW9ucy5jb2x1bW5zIS5zaG93biA9IHRoaXMudGFibGVTZXJ2aWNlLm9yZGVyQ29sdW1uc1dpdGhGcm96ZW5zKGZpbmFsQ29sdW1ucyk7XHJcblxyXG4gICAgbGV0IHNhbWVDb2x1bW5zQXNCZWZvcmUgPVxyXG4gICAgICBwcmV2Q29sc1RvU2hvdyEubGVuZ3RoID09PSB0aGlzLnRhYmxlT3B0aW9ucy5jb2x1bW5zIS5zaG93bi5sZW5ndGggJiZcclxuICAgICAgcHJldkNvbHNUb1Nob3chLmV2ZXJ5KChwcmV2Q29sLCBpbmRleCkgPT4gcHJldkNvbC5maWVsZCA9PT0gdGhpcy50YWJsZU9wdGlvbnMuY29sdW1ucyEuc2hvd24hW2luZGV4XS5maWVsZCk7XHJcblxyXG4gICAgdGhpcy5jb2x1bW5zU2VsZWN0ZWQgPSB0aGlzLnRhYmxlT3B0aW9ucy5jb2x1bW5zIS5zaG93bi5maWx0ZXIoXHJcbiAgICAgIGNvbHVtbiA9PiAhdGhpcy5jb2x1bW5zQ2FudEJlSGlkZGVuLnNvbWUobm9uU2VsZWN0YWJsZSA9PiBub25TZWxlY3RhYmxlLmZpZWxkID09PSBjb2x1bW4uZmllbGQpXHJcbiAgICApO1xyXG5cclxuICAgIHRoaXMudXBkYXRlQ29sdW1uc1NwZWNpYWxQcm9wZXJ0aWVzKHRoaXMuY29sdW1uTW9kYWxEYXRhKTtcclxuXHJcbiAgICBpZiAoIXNhbWVDb2x1bW5zQXNCZWZvcmUpIHtcclxuICAgICAgdGhpcy50YWJsZU9wdGlvbnMuaXNBY3RpdmUgPSBmYWxzZTtcclxuICAgICAgdGhpcy5jbGVhclNvcnRzKHRoaXMuZHQsIHRydWUpO1xyXG4gICAgICB0aGlzLmNsZWFyRmlsdGVycyh0aGlzLmR0LCB0cnVlLCBmYWxzZSk7XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMudGFibGVPcHRpb25zLmlzQWN0aXZlID0gdHJ1ZTtcclxuICAgICAgfSwgMSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZUNvbHVtbnNTcGVjaWFsUHJvcGVydGllcyhjb2x1bW5zU291cmNlOiBhbnlbXSl7XHJcbiAgICBjb25zdCBhbGxDb2x1bW5zID0gW3RoaXMuY29sdW1ucywgdGhpcy50YWJsZU9wdGlvbnMuY29sdW1ucyEuc2hvd24hLCB0aGlzLmNvbHVtbnNTZWxlY3RlZCwgdGhpcy5jb2x1bW5zQ2FudEJlSGlkZGVuXTtcclxuICAgIGNvbnN0IGNvbHVtbk1vZGFsRGF0YU1hcCA9IG5ldyBNYXAoY29sdW1uc1NvdXJjZS5tYXAoKGl0ZW06IGFueSkgPT4gW2l0ZW0uZmllbGQsIHsgXHJcbiAgICAgICAgY2VsbE92ZXJmbG93QmVoYXZpb3VyOiBpdGVtLmNlbGxPdmVyZmxvd0JlaGF2aW91ciwgXHJcbiAgICAgICAgZGF0YUFsaWduSG9yaXpvbnRhbDogaXRlbS5kYXRhQWxpZ25Ib3Jpem9udGFsLFxyXG4gICAgICAgIGRhdGFBbGlnblZlcnRpY2FsOiBpdGVtLmRhdGFBbGlnblZlcnRpY2FsLFxyXG4gICAgICAgIHdpZHRoOiBpdGVtLndpZHRoXHJcbiAgICB9XSkpO1xyXG4gICAgY29uc3QgdXBkYXRlZEZpZWxkcyA9IG5ldyBTZXQoKTsgLy8gVG8gdHJhY2sgdXBkYXRlZCBmaWVsZHNcclxuICAgIGFsbENvbHVtbnMuZm9yRWFjaCgoY29sdW1uTGlzdCkgPT4ge1xyXG4gICAgICAgIGNvbHVtbkxpc3QuZm9yRWFjaCgoY29sOiBhbnkpID0+IHtcclxuICAgICAgICAgICAgaWYgKGNvbHVtbk1vZGFsRGF0YU1hcC5oYXMoY29sLmZpZWxkKSAmJiAhdXBkYXRlZEZpZWxkcy5oYXMoY29sLmZpZWxkKSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgY29sdW1uRGF0YSA9IGNvbHVtbk1vZGFsRGF0YU1hcC5nZXQoY29sLmZpZWxkKTtcclxuICAgICAgICAgICAgICAgIGlmIChjb2x1bW5EYXRhKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29sLmNlbGxPdmVyZmxvd0JlaGF2aW91ciA9IGNvbHVtbkRhdGEuY2VsbE92ZXJmbG93QmVoYXZpb3VyO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbC5kYXRhQWxpZ25Ib3Jpem9udGFsID0gY29sdW1uRGF0YS5kYXRhQWxpZ25Ib3Jpem9udGFsO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbC5kYXRhQWxpZ25WZXJ0aWNhbCA9IGNvbHVtbkRhdGEuZGF0YUFsaWduVmVydGljYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgY29sLndpZHRoID0gY29sdW1uRGF0YS53aWR0aDtcclxuICAgICAgICAgICAgICAgICAgICB1cGRhdGVkRmllbGRzLmFkZChjb2wuZmllbGQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG9wZW5FeGNlbEV4cG9ydCgpe1xyXG4gICAgY29uc3QgZGVmYXVsdFRpdGxlID0gdGhpcy50YWJsZU9wdGlvbnMuZXhjZWxSZXBvcnQ/LmRlZmF1bHRUaXRsZT8udHJpbSgpO1xyXG4gICAgY29uc3QgYWxsb3dFZGl0ID0gdGhpcy50YWJsZU9wdGlvbnMuZXhjZWxSZXBvcnQ/LnRpdGxlQWxsb3dVc2VyRWRpdCA9PT0gdHJ1ZTtcclxuICAgIHRoaXMuZXhjZWxSZXBvcnRUaXRsZSA9IHRoaXMuaTE4bi50ZXh0KCghZGVmYXVsdFRpdGxlICYmICFhbGxvd0VkaXQpID8gJ1JlcG9ydCcgOiBkZWZhdWx0VGl0bGUhKTtcclxuICAgIHRoaXMuc2hvd0V4cG9ydE1vZGFsPXRydWU7XHJcbiAgfVxyXG4gIGdlbmVyYXRlRXhjZWxSZXBvcnQoZXZlbnQ6IGFueSl7XHJcbiAgICBpZighdGhpcy50YWJsZU9wdGlvbnMuZXhjZWxSZXBvcnQ/LnVybD8udHJpbSgpKXtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgbGV0IGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzID0gdGhpcy5tb2RpZnlGaWx0ZXJzV2l0aG91dEdsb2JhbEFuZFNlbGVjdGVkUm93cyh0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uLmZpbHRlcnMsIGV2ZW50LnNlbGVjdGVkUm93cyk7IC8vIENyZWF0ZSBmaWx0ZXJzIGV4Y2x1ZGluZyB0aGUgZ2xvYmFsIGZpbHRlclxyXG4gICAgZmlsdGVyc1dpdGhvdXRHbG9iYWxBbmRTZWxlY3RlZFJvd3M9dGhpcy5yZXZlcnREYXRlVGltZVpvbmVGaWx0ZXJzKGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzKTtcclxuICAgIGNvbnN0IGZpbHRlcnNNdXN0QmVBcHBsaWVkOiBib29sZWFuID0gKGV2ZW50LnNlbGVjdGVkUm93cyA9PT0gMSB8fCBldmVudC5zZWxlY3RlZFJvd3MgPT09IDIpIFxyXG4gICAgPyB0cnVlIFxyXG4gICAgOiBldmVudC5hcHBseUZpbHRlcnM7XHJcbiAgICBjb25zdCByZXF1ZXN0RGF0YTogSUV4Y2VsRXhwb3J0UmVxdWVzdCA9IHtcclxuICAgICAgcGFnZTogdGhpcy5jdXJyZW50UGFnZSwgLy8gU2V0IHRoZSBjdXJyZW50IHBhZ2UgbnVtYmVyXHJcbiAgICAgIHBhZ2VTaXplOiB0aGlzLmN1cnJlbnRSb3dzUGVyUGFnZSwgLy8gU2V0IHRoZSBudW1iZXIgb2Ygcm93cyBwZXIgcGFnZVxyXG4gICAgICBzb3J0OiB0aGlzLnRhYmxlTGF6eUxvYWRFdmVudEluZm9ybWF0aW9uLm11bHRpU29ydE1ldGEsIC8vIFNldCB0aGUgc29ydGluZyBpbmZvcm1hdGlvblxyXG4gICAgICBmaWx0ZXI6IGZpbHRlcnNXaXRob3V0R2xvYmFsQW5kU2VsZWN0ZWRSb3dzLCAvLyBTZXQgdGhlIGZpbHRlcnMgZXhjbHVkaW5nIHRoZSBnbG9iYWwgZmlsdGVyXHJcbiAgICAgIGdsb2JhbEZpbHRlcjogdGhpcy5lZmZlY3RpdmVHbG9iYWxTZWFyY2hUZXh0LCAvLyBVc2UgdGhlIGFwcGxpZWQgcXVlcnksIG5vdCBwZW5kaW5nIGlucHV0XHJcbiAgICAgIGNvbHVtbnM6IHRoaXMudGFibGVPcHRpb25zLmNvbHVtbnMhLnNob3duIS5tYXAoY29sID0+IGNvbC5maWVsZCksIC8vIFNldCB0aGUgY29sdW1ucyB0byBzaG93XHJcbiAgICAgIGRhdGVGb3JtYXQ6IHRoaXMuZGF0ZUZvcm1hdCxcclxuICAgICAgZGF0ZVRpbWV6b25lOiB0aGlzLmRhdGVUaW1lem9uZSxcclxuICAgICAgZGF0ZUN1bHR1cmU6IHRoaXMuZGF0ZUN1bHR1cmUsXHJcbiAgICAgIGV4cG9ydERhdGVGb3JtYXQ6IHRoaXMuZXhwb3J0RGF0ZUZvcm1hdCxcclxuICAgICAgYWxsQ29sdW1uczogZXZlbnQuYWxsQ29sdW1ucyxcclxuICAgICAgYXBwbHlGaWx0ZXJzOiBmaWx0ZXJzTXVzdEJlQXBwbGllZCxcclxuICAgICAgYXBwbHlTb3J0czogZXZlbnQuYXBwbHlTb3J0cyxcclxuICAgICAgZmlsZW5hbWU6IGV2ZW50LmZpbGVuYW1lLFxyXG4gICAgICB1c2VJY29uSW5Cb29sczogZXZlbnQudXNlSWNvbkluQm9vbHNcclxuICAgIH07XHJcbiAgICBpZiAodGhpcy50cmVlU3RhdGUpIE9iamVjdC5hc3NpZ24ocmVxdWVzdERhdGEsIHsgZXhwYW5kZWRLZXlzOiBbLi4udGhpcy50cmVlU3RhdGUuZXhwYW5kZWRdIH0pO1xyXG4gICAgdGhpcy50YWJsZVNlcnZpY2UuZmV0Y2hFeGNlbFJlcG9ydCh0aGlzLnRhYmxlT3B0aW9ucy5leGNlbFJlcG9ydC51cmwsIHJlcXVlc3REYXRhKS5zdWJzY3JpYmUoe1xyXG4gICAgICBuZXh0OiAocmVzcG9uc2U6IEh0dHBSZXNwb25zZTxCbG9iPikgPT4ge1xyXG4gICAgICAgIHRoaXMudGFibGVTZXJ2aWNlLmRvd25sb2FkRmlsZShyZXNwb25zZS5ib2R5ISwgZXZlbnQuZmlsZW5hbWUsICdhcHBsaWNhdGlvbi92bmQub3BlbnhtbGZvcm1hdHMtb2ZmaWNlZG9jdW1lbnQuc3ByZWFkc2hlZXRtbC5zaGVldCcpO1xyXG4gICAgICAgIHRoaXMuc2hvd0V4cG9ydE1vZGFsPWZhbHNlO1xyXG4gICAgICB9LFxyXG4gICAgICBlcnJvcjogKGVycikgPT4gdGhpcy50YWJsZVNlcnZpY2UuaGFuZGxlVGFibGVFcnJvcihlcnIsICdFeGNlbCBleHBvcnQgZXJyb3InKVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICB1cGRhdGVJY29uQmxvYnNGb3JDb2xsZWN0aW9ucygpOiB2b2lkIHtcclxuICAgIE9iamVjdC5rZXlzKHRoaXMudGFibGVPcHRpb25zLnByZWRlZmluZWRGaWx0ZXJzID8/IHt9KS5mb3JFYWNoKGtleSA9PiB7XHJcbiAgICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLnRhYmxlT3B0aW9ucy5wcmVkZWZpbmVkRmlsdGVycz8uW2tleV07XHJcbiAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpbHRlcnMpICAmJiBmaWx0ZXJzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBmaWx0ZXJzLmZvckVhY2goZmlsdGVyID0+IHtcclxuICAgICAgICAgIGlmIChmaWx0ZXIuaW1hZ2VCbG9iU291cmNlRW5kcG9pbnQgJiYgIWZpbHRlci5pbWFnZUJsb2IpIHtcclxuICAgICAgICAgICAgZmlsdGVyLmltYWdlQmxvYiA9IHVuZGVmaW5lZDtcclxuICAgICAgICAgICAgZmlsdGVyLmltYWdlQmxvYkZldGNoRXJyb3IgPSBmYWxzZTtcclxuICAgICAgICAgICAgdGhpcy50YWJsZVNlcnZpY2UuZ2V0SWNvbkJsb2IoZmlsdGVyLmltYWdlQmxvYlNvdXJjZUVuZHBvaW50KS5zdWJzY3JpYmUoe1xyXG4gICAgICAgICAgICAgIG5leHQ6IChyZXNwb25zZTogSHR0cFJlc3BvbnNlPEJsb2I+KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBmaWx0ZXIuaW1hZ2VCbG9iID0gcmVzcG9uc2UuYm9keSE7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNob3dFeHBvcnRNb2RhbD1mYWxzZTtcclxuICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgIGVycm9yOiAoKSA9PiB7IC8vIEhhbmRsZSBlcnJvciByZXNwb25zZVxyXG4gICAgICAgICAgICAgICAgZmlsdGVyLmltYWdlQmxvYkZldGNoRXJyb3IgPSB0cnVlO1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1lbHNlIHtcclxuICAgICAgICBjb25zb2xlLndhcm4oYEZpbHRlcnMgZm9yIGtleSAke2tleX0gaXMgbm90IGFuIGFycmF5OmAsIGZpbHRlcnMpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGVjc1RyYWNrMShpbmRleDogbnVtYmVyLCBidXR0b246IGFueSk6IGFueSB7IHJldHVybiBidXR0b247IH1cclxuICBlY3NUcmFjazIoaW5kZXg6IG51bWJlciwgYnV0dG9uOiBhbnkpOiBhbnkgeyByZXR1cm4gaW5kZXg7IH1cclxuICBlY3NUcmFjazMoaW5kZXg6IG51bWJlciwgZ3JvdXA6IGFueSk6IGFueSB7IHJldHVybiBncm91cC5maWVsZDsgfVxyXG4gIGVjc1RyYWNrNChpbmRleDogbnVtYmVyLCBjb2w6IGFueSk6IGFueSB7IHJldHVybiBjb2wuaGVhZGVyOyB9XHJcbiAgZWNzVHJhY2s1KGluZGV4OiBudW1iZXIsIGNvbDogYW55KTogYW55IHsgcmV0dXJuIGNvbC5maWVsZDsgfVxyXG59XHJcbiIsIjxkaXYgI3RhYmxlQ29udGFpbmVyPlxyXG4gICAgPHAtdGFibGUgI2R0XHJcbiAgICAgICAgc3R5bGVDbGFzcz1cInAtZGF0YXRhYmxlLXNtIHAtZGF0YXRhYmxlLWdyaWRsaW5lcyBwLWRhdGF0YWJsZS1zdHJpcGVkXCJcclxuICAgICAgICBzb3J0TW9kZT1cIm11bHRpcGxlXCJcclxuICAgICAgICBbcmVzaXphYmxlQ29sdW1uc109XCJ0cnVlXCIgY29sdW1uUmVzaXplTW9kZT1cImV4cGFuZFwiXHJcbiAgICAgICAgW3Jlb3JkZXJhYmxlQ29sdW1uc109XCJ0cnVlXCJcclxuICAgICAgICBbc2Nyb2xsYWJsZV09XCJ0cnVlXCIgW3Njcm9sbEhlaWdodF09XCJzY3JvbGxIZWlnaHRWYWx1ZVwiXHJcbiAgICAgICAgW2NvbHVtbnNdPVwidGFibGVPcHRpb25zLmNvbHVtbnM/LnNob3duID8/IFtdXCIgW3ZhbHVlXT1cInRhYmxlT3B0aW9ucy5kYXRhID8/IFtdXCIgZGF0YUtleT1cInJvd0lEXCIgXHJcbiAgICAgICAgW3BhZ2luYXRvcl09XCIhdHJlZVN0YXRlXCIgW2xvYWRpbmddPVwidHJlZVN0YXRlPy5sb2FkaW5nID8/IGZhbHNlXCIgcGFnaW5hdG9yRHJvcGRvd25BcHBlbmRUbz1cImJvZHlcIiBbZmlyc3RdPVwiY3VycmVudFBhZ2UgKiBjdXJyZW50Um93c1BlclBhZ2VcIiBbcm93c109XCJjdXJyZW50Um93c1BlclBhZ2VcIiBbdG90YWxSZWNvcmRzXT1cInRvdGFsUmVjb3Jkc1wiXHJcbiAgICAgICAgW3Jvd3NQZXJQYWdlT3B0aW9uc109XCJhbGxvd2VkUm93c1BlclBhZ2VcIiBbc2hvd0N1cnJlbnRQYWdlUmVwb3J0XT1cImZhbHNlXCIgKG9uUGFnZSk9XCJwYWdlQ2hhbmdlKCRldmVudClcIlxyXG4gICAgICAgIFtzZWxlY3Rpb25Nb2RlXT1cInRhYmxlT3B0aW9ucy5yb3dzPy5zaW5nbGVTZWxlY3Rvcj8uZW5hYmxlZCA/ICdzaW5nbGUnIDogJydcIiBbbWV0YUtleVNlbGVjdGlvbl09XCJ0YWJsZU9wdGlvbnMucm93cz8uc2luZ2xlU2VsZWN0b3I/Lm1ldGFrZXkgPz8gdHJ1ZVwiIFsoc2VsZWN0aW9uKV09XCJyb3dTZWxlY3Rpb25cIiAob25Sb3dTZWxlY3QpPVwicm93U2VsZWN0KCRldmVudClcIiAob25Sb3dVbnNlbGVjdCk9XCJyb3dVbnNlbGVjdCgkZXZlbnQpXCJcclxuICAgICAgICBbbGF6eV09XCJ0cnVlXCIgKG9uTGF6eUxvYWQpPVwiZmV0Y2hUYWJsZURhdGEoJGV2ZW50KVwiPlxyXG5cclxuICAgICAgICA8IS0tVEVNUExBVEUgRk9SIFRIRSBBQ1RJT05TIEhFQURFUiBDT0xVTU4tLT5cclxuICAgICAgICA8bmctdGVtcGxhdGUgI2FjdGlvbkNvbHVtbkhlYWRlclRlbXBsYXRlPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiKHRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LmJ1dHRvbnM/Lmxlbmd0aCA/PyAwKSA+IDBcIj5cclxuICAgICAgICAgICAgICAgIDx0aCBbbmdTdHlsZV09XCJ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICd0ZXh0LWFsaWduJzogJ2NlbnRlcicsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICd2ZXJ0aWNhbC1hbGlnbic6ICdtaWRkbGUnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAnbWF4LXdpZHRoJzogYWN0aW9uQ29sdW1uV2lkdGggKyAncHgnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAnbWluLXdpZHRoJzogYWN0aW9uQ29sdW1uV2lkdGggKyAncHgnLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAnd2lkdGgnOiBhY3Rpb25Db2x1bW5XaWR0aCArICdweCdcclxuICAgICAgICAgICAgICAgICAgICB9XCJcclxuICAgICAgICAgICAgICAgICAgICBwUmVzaXphYmxlQ29sdW1uIFtwUmVzaXphYmxlQ29sdW1uRGlzYWJsZWRdPVwiIXRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LnJlc2l6YWJsZVwiIHBGcm96ZW5Db2x1bW4gW2Zyb3plbl09XCJ0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5mcm96ZW4gPz8gZmFsc2VcIlxyXG4gICAgICAgICAgICAgICAgICAgIFthbGlnbkZyb3plbl09XCJnZXRGcm96ZW5Db2x1bW5BbGlnbkFzVGV4dCh0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5wb3NpdGlvblJpZ2h0ID8gRnJvemVuQ29sdW1uQWxpZ24uUmlnaHQgOiBGcm96ZW5Db2x1bW5BbGlnbi5MZWZ0KVwiIGlkPVwiYWN0aW9ucy1oZWFkZXJcIlxyXG4gICAgICAgICAgICAgICAgICAgIFthdHRyLnNjb3BlXT1cIidjb2wnXCI+XHJcbiAgICAgICAgICAgICAgICAgICAge3sgKHRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LmhlYWRlciA/PyAnJykgfCBlY3NUcmFuc2xhdGUgfX1cclxuICAgICAgICAgICAgICAgIDwvdGg+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICAgIDwhLS1URU1QTEFURSBGT1IgVEhFIEFDVElPTlMgUk9XIENPTFVNTi0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjYWN0aW9uQ29sdW1uVGVtcGxhdGUgbGV0LXJvd0RhdGE9XCJyb3dEYXRhXCI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIodGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8uYnV0dG9ucz8ubGVuZ3RoID8/IDApID4gMFwiPlxyXG4gICAgICAgICAgICAgICAgPHRkIFxyXG4gICAgICAgICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ3RleHQtYWxpZ24nOiAoZ2V0RGF0YUFsaWduSG9yaXpvbnRhbEFzVGV4dCh0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5ob3Jpem9udGFsQWxpZ25tZW50ID8/IERhdGFBbGlnbkhvcml6b250YWwuQ2VudGVyKSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICd2ZXJ0aWNhbC1hbGlnbic6IChnZXREYXRhQWxpZ25WZXJ0aWNhbEFzVGV4dCh0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy52ZXJ0aWNhbEFsaWdubWVudCA/PyBEYXRhQWxpZ25WZXJ0aWNhbC5NaWRkbGUpKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ21heC13aWR0aCc6IGFjdGlvbkNvbHVtbldpZHRoICsgJ3B4JyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ21pbi13aWR0aCc6IGFjdGlvbkNvbHVtbldpZHRoICsgJ3B4JyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogYWN0aW9uQ29sdW1uV2lkdGggKyAncHgnXHJcbiAgICAgICAgICAgICAgICAgICAgfVwiXHJcbiAgICAgICAgICAgICAgICAgICAgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cInRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LmZyb3plbiA/PyBmYWxzZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgW2FsaWduRnJvemVuXT1cImdldEZyb3plbkNvbHVtbkFsaWduQXNUZXh0KHRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LnBvc2l0aW9uUmlnaHQgPyBGcm96ZW5Db2x1bW5BbGlnbi5SaWdodCA6IEZyb3plbkNvbHVtbkFsaWduLkxlZnQpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvbXBhY3RSb3dzOyBlbHNlIGVjc0Vsc2UwXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJoYXNSb3dNZW51QWN0aW9ucyhyb3dEYXRhKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBwQnV0dG9uIHR5cGU9XCJidXR0b25cIiBpY29uPVwicGkgcGktZWxsaXBzaXMtdlwiIFthdHRyLmFyaWEtbGFiZWxdPVwiKHRhYmxlT3B0aW9ucy5yZXNwb25zaXZlPy5yb3dNZW51TGFiZWwgfHwgJ1JvdyBhY3Rpb25zJykgfCBlY3NUcmFuc2xhdGVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFyaWEtaGFzcG9wdXA9XCJtZW51XCIgW2F0dHIuYXJpYS1leHBhbmRlZF09XCJyZXNwb25zaXZlUm93TWVudS52aXNpYmxlICYmIHJvd01lbnVSb3cgPT09IHJvd0RhdGFcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvcGVuUm93TWVudSgkZXZlbnQsIHJvd0RhdGEpXCIgY2xhc3M9XCJlY3MtcmVzcG9uc2l2ZS10cmlnZ2VyXCI+PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPjxuZy10ZW1wbGF0ZSAjZWNzRWxzZTA+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgYnV0dG9uIG9mIHRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LmJ1dHRvbnM7IHRyYWNrQnk6IGVjc1RyYWNrMTsgbGV0ICRpbmRleCA9IGluZGV4OyBsZXQgJGZpcnN0ID0gZmlyc3Q7IGxldCAkbGFzdCA9IGxhc3Q7IGxldCAkZXZlbiA9IGV2ZW47IGxldCAkb2RkID0gb2RkOyBsZXQgJGNvdW50ID0gY291bnQ7IGxldCBsYXN0ID0gbGFzdFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZWNzLXRhYmxlLWJ1dHRvbiBbYnV0dG9uXT1cImJ1dHRvblwiIFtyb3dEYXRhXT1cInJvd0RhdGFcIiBbaXNBY3Rpb25CdXR0b25dPVwidHJ1ZVwiIFtpc0xhc3RBY3Rpb25CdXR0b25dPVwibGFzdFwiPjwvZWNzLXRhYmxlLWJ1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuXHJcbiAgICAgICAgPCEtLSBURU1QTEFURSBGT1IgVEhFIFJPVyBDSEVDS0JPWCBTRUxFQ1RPUiBIRUFERVIgQ09MVU1OIC0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjcm93U2VsZWN0b3JDb2x1bW5IZWFkZXJUZW1wbGF0ZT5cclxuICAgICAgICAgICAgPHRoIFxyXG4gICAgICAgICAgICAgICAgW25nU3R5bGVdPVwie1xyXG4gICAgICAgICAgICAgICAgICAgICd0ZXh0LWFsaWduJzogJ2NlbnRlcicsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3ZlcnRpY2FsLWFsaWduJzogJ21pZGRsZScsXHJcbiAgICAgICAgICAgICAgICAgICAgJ21heC13aWR0aCc6ICh0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ud2lkdGggPz8gMTUwKSArICdweCcsXHJcbiAgICAgICAgICAgICAgICAgICAgJ21pbi13aWR0aCc6ICh0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ud2lkdGggPz8gMTUwKSArICdweCcsXHJcbiAgICAgICAgICAgICAgICAgICAgJ3dpZHRoJzogKHRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy53aWR0aCA/PyAxNTApICsgJ3B4J1xyXG4gICAgICAgICAgICAgICAgfVwiXHJcbiAgICAgICAgICAgICAgICBpZD1cInJvd1NlbGVjdG9yLWhlYWRlclwiICBbYXR0ci5zY29wZV09XCInY29sJ1wiIHBSZXNpemFibGVDb2x1bW4gW3BSZXNpemFibGVDb2x1bW5EaXNhYmxlZF09XCIhdGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I/LnJlc2l6YWJsZVwiIHBGcm96ZW5Db2x1bW4gXHJcbiAgICAgICAgICAgICAgICBbZnJvemVuXT1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5mcm96ZW4gPz8gZmFsc2VcIiBbYWxpZ25Gcm96ZW5dPVwiZ2V0RnJvemVuQ29sdW1uQWxpZ25Bc1RleHQodGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I/LnBvc2l0aW9uUmlnaHQgPyBGcm96ZW5Db2x1bW5BbGlnbi5SaWdodCA6IEZyb3plbkNvbHVtbkFsaWduLkxlZnQpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImRpc3BsYXk6IGZsZXg7IGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjsgYWxpZ24taXRlbXM6IGNlbnRlcjtcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5zZWxlY3RBbGxFbmFibGVkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cImNoZWNrYm94XCIgY2xhc3M9XCJlY3Mtc2VsZWN0LWFsbFwiIFtjaGVja2VkXT1cImFsbE1hdGNoaW5nUm93c1NlbGVjdGVkXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaW5kZXRlcm1pbmF0ZV09XCJtYXRjaGluZ1Jvd3NQYXJ0aWFsbHlTZWxlY3RlZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cInNlbGVjdEFsbExvYWRpbmcgfHwgIXRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy51cmxTZWxlY3RBbGxcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiJ1NlbGVjdCBhbGwgZmlsdGVyZWQgcm93cycgfCBlY3NUcmFuc2xhdGVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtwVG9vbHRpcF09XCInU2VsZWN0IGFsbCBmaWx0ZXJlZCByb3dzJyB8IGVjc1RyYW5zbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNoYW5nZSk9XCJ0b2dnbGVBbGxNYXRjaGluZ1Jvd3MoJGFueSgkZXZlbnQudGFyZ2V0KS5jaGVja2VkKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAge3sgKHRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5oZWFkZXIgPz8gJycpIHwgZWNzVHJhbnNsYXRlIH19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxwLWNvbHVtbkZpbHRlciB0eXBlPVwiYm9vbGVhblwiIGZpZWxkPVwic2VsZWN0b3JcIiBkaXNwbGF5PVwibWVudVwiIFtzaG93QnV0dG9uc109XCJmYWxzZVwiPjwvcC1jb2x1bW5GaWx0ZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvdGg+XHJcbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuXHJcbiAgICAgICAgPCEtLVRFTVBMQVRFIEZPUiBUSEUgUk9XIENIRUNLQk9YIFNFTEVDVE9SIENPTFVNTi0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSAjcm93U2VsZWN0b3JDb2x1bW5UZW1wbGF0ZSBsZXQtcm93RGF0YT1cInJvd0RhdGFcIj5cclxuICAgICAgICAgICAgPHRkIFxyXG4gICAgICAgICAgICBbbmdTdHlsZV09XCJ7XHJcbiAgICAgICAgICAgICAgICAndGV4dC1hbGlnbic6IChnZXREYXRhQWxpZ25Ib3Jpem9udGFsQXNUZXh0KHRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5ob3Jpem9udGFsQWxpZ25tZW50ID8/IERhdGFBbGlnbkhvcml6b250YWwuQ2VudGVyKSksXHJcbiAgICAgICAgICAgICAgICAndmVydGljYWwtYWxpZ24nOiAoZ2V0RGF0YUFsaWduVmVydGljYWxBc1RleHQodGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I/LnZlcnRpY2FsQWxpZ25tZW50ID8/IERhdGFBbGlnblZlcnRpY2FsLk1pZGRsZSkpLFxyXG4gICAgICAgICAgICAgICAgJ21heC13aWR0aCc6ICh0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ud2lkdGggPz8gMTUwKSArICdweCcsXHJcbiAgICAgICAgICAgICAgICAnbWluLXdpZHRoJzogKHRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy53aWR0aCA/PyAxNTApICsgJ3B4JyxcclxuICAgICAgICAgICAgICAgICd3aWR0aCc6ICh0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ud2lkdGggPz8gMTUwKSArICdweCdcclxuICAgICAgICAgICAgfVwiXHJcbiAgICAgICAgICAgIHBGcm96ZW5Db2x1bW4gW2Zyb3plbl09XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8uZnJvemVuID8/IGZhbHNlXCIgXHJcbiAgICAgICAgICAgIFthbGlnbkZyb3plbl09XCJnZXRGcm96ZW5Db2x1bW5BbGlnbkFzVGV4dCh0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ucG9zaXRpb25SaWdodCA/IEZyb3plbkNvbHVtbkFsaWduLlJpZ2h0IDogRnJvemVuQ29sdW1uQWxpZ24uTGVmdClcIj5cclxuICAgICAgICAgICAgPHAtY2hlY2tib3ggXHJcbiAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiISh0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8uZW5hYmxlZENvbmRpdGlvbj8uKHJvd0RhdGEpID8/IHRydWUpXCJcclxuICAgICAgICAgICAgICAgIFtiaW5hcnldPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICBbbmdNb2RlbF09XCJpc1Jvd0NoZWNrYm94U2VsZWN0ZWQocm93RGF0YS5yb3dJRClcIlxyXG4gICAgICAgICAgICAgICAgKG9uQ2hhbmdlKT1cIm9uUm93Q2hla2JveENoYW5nZSgkZXZlbnQsIHJvd0RhdGEucm93SUQpXCI+PC9wLWNoZWNrYm94PlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG5cclxuICAgICAgICA8IS0tIExPR0lDIEZPUiBEUkFXSU5HIFRBQkxFIEFDVElPTlMgQUJPVkUgVEhFIEhFQURFUiAtLT5cclxuICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiY2FwdGlvblwiPlxyXG4gICAgICAgICAgICA8ZGl2ICNoZWFkZXJDb250YWluZXIgW2NsYXNzLmVjcy1jb21wYWN0LWhlYWRlcl09XCJjb21wYWN0SGVhZGVyXCIgc3R5bGU9XCJkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47IGFsaWduLWl0ZW1zOiBjZW50ZXI7XCI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiY29tcGFjdEhlYWRlcjsgZWxzZSBlY3NFbHNlMVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0YWJsZU9wdGlvbnMuZ2xvYmFsRmlsdGVyPy5lbmFibGVkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZWNzLWdsb2JhbC1zZWFyY2ggZWNzLXJlc3BvbnNpdmUtc2VhcmNoXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImVjcy1pbnB1dC1pY29uXCI+PGkgY2xhc3M9XCJwaSBwaS1zZWFyY2hcIj48L2k+PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHBJbnB1dFRleHQgdHlwZT1cInRleHRcIiBbYXR0ci5hcmlhLWxhYmVsXT1cIidTZWFyY2gga2V5d29yZCcgfCBlY3NUcmFuc2xhdGVcIiBbcGxhY2Vob2xkZXJdPVwiJ1NlYXJjaCBrZXl3b3JkJyB8IGVjc1RyYW5zbGF0ZVwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21heGxlbmd0aF09XCJ0YWJsZU9wdGlvbnMuZ2xvYmFsRmlsdGVyPy5tYXhMZW5ndGggPz8gbnVsbFwiIFtuZ01vZGVsXT1cImdsb2JhbFNlYXJjaFRleHRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uR2xvYmFsU2VhcmNoSW5wdXQoJGV2ZW50KVwiLz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJnbG9iYWxTZWFyY2hUZXh0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJlY3MtaW5wdXQtaWNvblwiIHBvc2l0aW9uPVwicmlnaHRcIj48YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImVjcy1jbGVhci1zZWFyY2hcIiBbYXR0ci5hcmlhLWxhYmVsXT1cIidDbGVhciBzZWFyY2gnIHwgZWNzVHJhbnNsYXRlXCIgKGNsaWNrKT1cImNsZWFyRmlsdGVycyhkdCwgdHJ1ZSwgdHJ1ZSlcIj48aSBjbGFzcz1cInBpIHBpLXRpbWVzXCI+PC9pPjwvYnV0dG9uPjwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5kZXNjcmlwdGlvbj8udGV4dFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8aSBbY2xhc3NdPVwidGFibGVPcHRpb25zLmRlc2NyaXB0aW9uIS5pY29uXCIgW3BUb29sdGlwXT1cIih0YWJsZU9wdGlvbnMuZGVzY3JpcHRpb24hLnRleHQpIHwgZWNzVHJhbnNsYXRlXCIgW2VzY2FwZV09XCJmYWxzZVwiPjwvaT5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHBCdXR0b24gdHlwZT1cImJ1dHRvblwiIGljb249XCJwaSBwaS1iYXJzXCIgW2F0dHIuYXJpYS1sYWJlbF09XCIodGFibGVPcHRpb25zLnJlc3BvbnNpdmU/LmhlYWRlck1lbnVMYWJlbCB8fCAnVGFibGUgYWN0aW9ucycpIHwgZWNzVHJhbnNsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgYXJpYS1oYXNwb3B1cD1cIm1lbnVcIiBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cInJlc3BvbnNpdmVIZWFkZXJNZW51LnZpc2libGVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib3BlbkhlYWRlck1lbnUoJGV2ZW50KVwiIGNsYXNzPVwiZWNzLXJlc3BvbnNpdmUtdHJpZ2dlciBlY3MtaGVhZGVyLW1lbnUtdHJpZ2dlclwiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+PG5nLXRlbXBsYXRlICNlY3NFbHNlMT5cclxuXHJcbiAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwiZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsgZ2FwOiAxMHB4O1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwhLS1DSE9PU0UgQ09MVU1OUyBUTyBTSE9XLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5jb2x1bW5zPy5zZWxlY3RvckVuYWJsZWRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHAtYnV0dG9uIFtpY29uXT1cInRhYmxlT3B0aW9ucy5jb2x1bW5zPy5zZWxlY3Rvckljb24gPz8gJ3BpIHBpLXBlbmNpbCdcIiAob25DbGljayk9XCJjb2x1bW5TZWxlY3RvclNob3coKVwiIFtwVG9vbHRpcF09XCInTW9kaWZ5IGNvbHVtbnMnIHwgZWNzVHJhbnNsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93RGVsYXldPVwiNzAwXCIgdG9vbHRpcFBvc2l0aW9uPVwidG9wXCIgc3R5bGVDbGFzcz1cInAtYnV0dG9uLWljb24tb25seVwiPjwvcC1idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLUNMRUFSIFNPUlRTIEFORCBGSUxURVJTLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5oZWFkZXI/LmNsZWFyU29ydHNFbmFibGVkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxwLWJ1dHRvbiBbaWNvbl09XCJ0YWJsZU9wdGlvbnMuaGVhZGVyPy5jbGVhclNvcnRzSWNvbiA/PyAncGkgcGktc29ydC1hbHQtc2xhc2gnXCIgKG9uQ2xpY2spPVwiY2xlYXJTb3J0cyhkdClcIiBbZGlzYWJsZWRdPVwiIWhhc1RvQ2xlYXJTb3J0cyhkdClcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BUb29sdGlwXT1cIidDbGVhciBzb3J0cycgfCBlY3NUcmFuc2xhdGVcIiBbc2hvd0RlbGF5XT1cIjcwMFwiIHRvb2x0aXBQb3NpdGlvbj1cInRvcFwiIHN0eWxlQ2xhc3M9XCJwLWJ1dHRvbi1pY29uLW9ubHlcIj48L3AtYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0YWJsZU9wdGlvbnMuaGVhZGVyPy5jbGVhckZpbHRlcnNFbmFibGVkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxwLWJ1dHRvblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ljb25dPVwidGFibGVPcHRpb25zLmhlYWRlcj8uY2xlYXJGaWx0ZXJzSWNvbiA/PyAncGkgcGktZmlsdGVyLXNsYXNoJ1wiIChvbkNsaWNrKT1cImNsZWFyRmlsdGVycyhkdClcIiBbZGlzYWJsZWRdPVwiIWhhc1RvQ2xlYXJGaWx0ZXJzKGR0LCBnbG9iYWxTZWFyY2hUZXh0KVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcFRvb2x0aXBdPVwiJ0NsZWFyIGZpbHRlcnMnIHwgZWNzVHJhbnNsYXRlXCIgW3Nob3dEZWxheV09XCI3MDBcIiB0b29sdGlwUG9zaXRpb249XCJ0b3BcIiBzdHlsZUNsYXNzPVwicC1idXR0b24taWNvbi1vbmx5XCI+PC9wLWJ1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLVRBQkxFIERFU0NSSVBUSU9OLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5kZXNjcmlwdGlvbj8udGV4dFwiPiA8IS0tIElmIGEgdGFibGUgZGVzY3JpcHRpb24gdGV4dCBpcyBwcm92aWRlZCAtLT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiF0YWJsZU9wdGlvbnMuZGVzY3JpcHRpb24hLnRvb2x0aXA7IGVsc2UgZWNzRWxzZTJcIj4gPCEtLSBUaGUgdGFibGUgZGVzY3JpcHRpb24gbXVzdCBiZSBzaG93biBhcyB0ZXh0IG5leHQgdG8gdGhlIGljb24gLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aSBbY2xhc3NdPVwidGFibGVPcHRpb25zLmRlc2NyaXB0aW9uIS5pY29uXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gW2lubmVySFRNTF09XCIodGFibGVPcHRpb25zLmRlc2NyaXB0aW9uIS50ZXh0KSB8IGVjc1RyYW5zbGF0ZVwiPjwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+PG5nLXRlbXBsYXRlICNlY3NFbHNlMj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpIFtlc2NhcGVdPVwiZmFsc2VcIiBbcFRvb2x0aXBdPVwiKHRhYmxlT3B0aW9ucy5kZXNjcmlwdGlvbiEudGV4dCkgfCBlY3NUcmFuc2xhdGVcIiB0b29sdGlwUG9zaXRpb249XCJyaWdodFwiIFtjbGFzc109XCJ0YWJsZU9wdGlvbnMuZGVzY3JpcHRpb24hLmljb25cIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgICAgICA8IS0tVEFCTEUgVklFV1MtLT5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0YWJsZVZpZXdzRW5hYmxlZCgpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGdhcDogMTBweDtcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJwLWJ1dHRvbnNldCBlY3Mtdmlldy1idXR0b25zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1idXR0b24gKGNsaWNrKT1cInZpZXdzTW9kYWxTaG93PXRydWU7XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbGFiZWxdPVwidGFibGVWaWV3Q3VycmVudFNlbGVjdGVkQWxpYXMgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gdGFibGVWaWV3Q3VycmVudFNlbGVjdGVkQWxpYXMgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogKCh0YWJsZU9wdGlvbnMudmlld3M/Lm5vVmlld1NlbGVjdGVkVGV4dCB8fCAnLS0tIFNlbGVjdCBhIHZpZXcgLS0tJykgfCBlY3NUcmFuc2xhdGUpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3NdPVwiJ3ZpZXdCdXR0b24nICsgKHRhYmxlT3B0aW9ucy52aWV3cz8uc2VsZWN0Vmlld0J1dHRvbkNsYXNzID8gJyAnICsgdGFibGVPcHRpb25zLnZpZXdzIS5zZWxlY3RWaWV3QnV0dG9uQ2xhc3MgOiAnJylcIj48L3AtYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtYnV0dG9uIChjbGljayk9XCJ2aWV3TG9hZCh0YWJsZVZpZXdDdXJyZW50U2VsZWN0ZWRBbGlhcyEpXCIgIFtkaXNhYmxlZF09XCIhdGFibGVWaWV3Q3VycmVudFNlbGVjdGVkQWxpYXNcIiBbcFRvb2x0aXBdPVwiJ0FwcGx5IHZpZXcgYWdhaW4nIHwgZWNzVHJhbnNsYXRlXCIgW3Nob3dEZWxheV09XCI3MDBcIiB0b29sdGlwUG9zaXRpb249XCJ0b3BcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpY29uXT1cInRhYmxlT3B0aW9ucy52aWV3cz8ucmVsb2FkVmlld0J1dHRvbkljb24gfHwgJ3BpIHBpLXJlZnJlc2gnXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3NdPVwidGFibGVPcHRpb25zLnZpZXdzPy5yZWxvYWRWaWV3QnV0dG9uQ2xhc3MgfHwgJydcIj48L3AtYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwiZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsgZ2FwOiAxMHB4O1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwhLS1HTE9CQUwgRklMVEVSLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5nbG9iYWxGaWx0ZXI/LmVuYWJsZWRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJlY3MtZ2xvYmFsLXNlYXJjaCBtbC1hdXRvXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImVjcy1pbnB1dC1pY29uXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJwaSBwaS1zZWFyY2hcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgcElucHV0VGV4dCB0eXBlPVwidGV4dFwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChuZ01vZGVsQ2hhbmdlKT1cIm9uR2xvYmFsU2VhcmNoSW5wdXQoJGV2ZW50KVwiIGF1dG9jb21wbGV0ZT1cIm9mZlwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21heGxlbmd0aF09XCJ0YWJsZU9wdGlvbnMuZ2xvYmFsRmlsdGVyPy5tYXhMZW5ndGggPz8gbnVsbFwiIFtwbGFjZWhvbGRlcl09XCInU2VhcmNoIGtleXdvcmQnIHwgZWNzVHJhbnNsYXRlXCIgW25nTW9kZWxdPVwiZ2xvYmFsU2VhcmNoVGV4dFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGU9XCJ3aWR0aDogMjIwcHg7XCIvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBSaWdodCBpY29uIChvbmx5IGlmIHRoZXJlIGlzIHRleHQpIC0tPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImdsb2JhbFNlYXJjaFRleHRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImVjcy1pbnB1dC1pY29uXCIgcG9zaXRpb249XCJyaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aSBjbGFzcz1cInBpIHBpLXRpbWVzXCIgc3R5bGU9XCJjdXJzb3I6IHBvaW50ZXI7XCIgIChjbGljayk9XCJjbGVhckZpbHRlcnMoZHQsIHRydWUsIHRydWUpOyAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj48L2k+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLUVYUE9SVCBEQVRBLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5leGNlbFJlcG9ydD8udXJsPy50cmltKClcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHAtYnV0dG9uIGljb249XCJwaSBwaS1maWxlLWV4Y2VsXCIgKG9uQ2xpY2spPVwib3BlbkV4Y2VsRXhwb3J0KClcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BUb29sdGlwXT1cIidFeHBvcnQgdG8gRXhjZWwnIHwgZWNzVHJhbnNsYXRlXCIgW3Nob3dEZWxheV09XCI3MDBcIiB0b29sdGlwUG9zaXRpb249XCJ0b3BcIiBzdHlsZUNsYXNzPVwicC1idXR0b24taWNvbi1vbmx5XCI+PC9wLWJ1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLVJFU0VUIFRBQkxFIFZJRVctLT5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidGFibGVPcHRpb25zLnJlc2V0VGFibGVWaWV3Py5lbmFibGVkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxwLWJ1dHRvbiBbaWNvbl09XCJ0YWJsZU9wdGlvbnMucmVzZXRUYWJsZVZpZXc/Lmljb24gPz8gJ3BpIHBpLWVyYXNlcidcIiAoY2xpY2spPVwicmVzZXRUYWJsZVZpZXcoKVwiIFtwVG9vbHRpcF09XCInUmVzZXQgdGFibGUgdmlldycgfCBlY3NUcmFuc2xhdGVcIiBbc2hvd0RlbGF5XT1cIjcwMFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b29sdGlwUG9zaXRpb249XCJ0b3BcIiBzdHlsZUNsYXNzPVwicC1idXR0b24taWNvbi1vbmx5XCI+PC9wLWJ1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLVJFRlJFU0ggREFUQS0tPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwLWJ1dHRvbiBpY29uPVwicGkgcGktcmVmcmVzaFwiIChvbkNsaWNrKT1cInJlZnJlc2hEYXRhKCRldmVudClcIiBbcFRvb2x0aXBdPVwiJ1JlZnJlc2ggZGF0YScgfCBlY3NUcmFuc2xhdGVcIiBbc2hvd0RlbGF5XT1cIjcwMFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvb2x0aXBQb3NpdGlvbj1cInRvcFwiIHN0eWxlQ2xhc3M9XCJwLWJ1dHRvbi1pY29uLW9ubHlcIj48L3AtYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gSEVBREVSIEFDVElPTiBCVVRUT05TIC0tPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIodGFibGVPcHRpb25zLmhlYWRlcj8uYnV0dG9ucz8ubGVuZ3RoID8/IDApID4gMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8dGQgc3R5bGU9XCJkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjsgYWxpZ24taXRlbXM6IGNlbnRlcjsgZ2FwOiAxMHB4O1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgYnV0dG9uIG9mIHRhYmxlT3B0aW9ucy5oZWFkZXI/LmJ1dHRvbnM7IHRyYWNrQnk6IGVjc1RyYWNrMjsgbGV0ICRpbmRleCA9IGluZGV4OyBsZXQgJGZpcnN0ID0gZmlyc3Q7IGxldCAkbGFzdCA9IGxhc3Q7IGxldCAkZXZlbiA9IGV2ZW47IGxldCAkb2RkID0gb2RkOyBsZXQgJGNvdW50ID0gY291bnRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZWNzLXRhYmxlLWJ1dHRvbiBbYnV0dG9uXT1cImJ1dHRvblwiIFtyb3dEYXRhXT1cIm51bGxcIj48L2Vjcy10YWJsZS1idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuXHJcbiAgICAgICAgPCEtLSBMT0dJQyBGT1IgRFJBV0lORyBUQUJMRSBIRUFERVJTIC0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJoZWFkZXJcIiBsZXQtY29sdW1ucz5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImdldENvbHVtbkhlYWRlckdyb3Vwcyhjb2x1bW5zKSBhcyBoZWFkZXJHcm91cHNcIj5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImhlYWRlckdyb3Vwcy5sZW5ndGhcIj5cclxuICAgICAgICAgICAgICAgIDx0ciBjbGFzcz1cImVjcy1jb2x1bW4tZ3JvdXBzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIih0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5idXR0b25zPy5sZW5ndGggPz8gMCkgPiAwICYmICF0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5wb3NpdGlvblJpZ2h0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBhcmlhLWhpZGRlbj1cInRydWVcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwidGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8uZnJvemVuID8/IGZhbHNlXCIgYWxpZ25Gcm96ZW49XCJsZWZ0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC5weF09XCJhY3Rpb25Db2x1bW5XaWR0aFwiIFtzdHlsZS5taW4td2lkdGgucHhdPVwiYWN0aW9uQ29sdW1uV2lkdGhcIj48L3RkPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8uZW5hYmxlZCAmJiAhdGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I/LnBvc2l0aW9uUmlnaHRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIGFyaWEtaGlkZGVuPVwidHJ1ZVwiIHBGcm96ZW5Db2x1bW4gW2Zyb3plbl09XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8uZnJvemVuID8/IGZhbHNlXCIgYWxpZ25Gcm96ZW49XCJsZWZ0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS53aWR0aC5weF09XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ud2lkdGggPz8gMTUwXCIgW3N0eWxlLm1pbi13aWR0aC5weF09XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ud2lkdGggPz8gMTUwXCI+PC90ZD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBncm91cCBvZiBoZWFkZXJHcm91cHM7IHRyYWNrQnk6IGVjc1RyYWNrMzsgbGV0ICRpbmRleCA9IGluZGV4OyBsZXQgJGZpcnN0ID0gZmlyc3Q7IGxldCAkbGFzdCA9IGxhc3Q7IGxldCAkZXZlbiA9IGV2ZW47IGxldCAkb2RkID0gb2RkOyBsZXQgJGNvdW50ID0gY291bnRcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHRkIFthdHRyLmNvbHNwYW5dPVwiZ3JvdXAuY29sc3BhblwiIHJvbGU9XCJjb2x1bW5oZWFkZXJcIiBbYXR0ci5hcmlhLWNvbHNwYW5dPVwiZ3JvdXAuY29sc3BhblwiIHN0eWxlPVwidGV4dC1hbGlnbjogY2VudGVyOyB2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlO1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwiZ3JvdXAuZnJvemVuQ29sdW1uQWxpZ24gIT09IEZyb3plbkNvbHVtbkFsaWduLk5vb25lXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthbGlnbkZyb3plbl09XCJnZXRGcm96ZW5Db2x1bW5BbGlnbkFzVGV4dChncm91cC5mcm96ZW5Db2x1bW5BbGlnbilcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGdyb3VwLmxhYmVsIHwgdHJhbnNsYXRlIH19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5lbmFibGVkICYmIHRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5wb3NpdGlvblJpZ2h0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBhcmlhLWhpZGRlbj1cInRydWVcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwidGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I/LmZyb3plbiA/PyBmYWxzZVwiIGFsaWduRnJvemVuPVwicmlnaHRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLndpZHRoLnB4XT1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy53aWR0aCA/PyAxNTBcIiBbc3R5bGUubWluLXdpZHRoLnB4XT1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy53aWR0aCA/PyAxNTBcIj48L3RkPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIodGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8uYnV0dG9ucz8ubGVuZ3RoID8/IDApID4gMCAmJiB0YWJsZU9wdGlvbnMucm93cz8uYWN0aW9uPy5wb3NpdGlvblJpZ2h0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx0ZCBhcmlhLWhpZGRlbj1cInRydWVcIiBwRnJvemVuQ29sdW1uIFtmcm96ZW5dPVwidGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8uZnJvemVuID8/IGZhbHNlXCIgYWxpZ25Gcm96ZW49XCJyaWdodFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUud2lkdGgucHhdPVwiYWN0aW9uQ29sdW1uV2lkdGhcIiBbc3R5bGUubWluLXdpZHRoLnB4XT1cImFjdGlvbkNvbHVtbldpZHRoXCI+PC90ZD5cclxuICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8dHI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIXRhYmxlT3B0aW9ucy5yb3dzPy5hY3Rpb24/LnBvc2l0aW9uUmlnaHRcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYWN0aW9uQ29sdW1uSGVhZGVyVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5lbmFibGVkICYmICF0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93U2VsZWN0b3JDb2x1bW5IZWFkZXJUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2wgb2YgY29sdW1uczsgdHJhY2tCeTogZWNzVHJhY2s0OyBsZXQgJGluZGV4ID0gaW5kZXg7IGxldCAkZmlyc3QgPSBmaXJzdDsgbGV0ICRsYXN0ID0gbGFzdDsgbGV0ICRldmVuID0gZXZlbjsgbGV0ICRvZGQgPSBvZGQ7IGxldCAkY291bnQgPSBjb3VudFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0aCBbbmdTdHlsZV09XCJnZXRDb2x1bW5TdHlsZShjb2wsIHRydWUpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgcFJlc2l6YWJsZUNvbHVtbiBbcFJlc2l6YWJsZUNvbHVtbkRpc2FibGVkXT1cIiFjb2wuY2FuQmVSZXNpemVkID8gdHJ1ZSA6IGZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgcFJlb3JkZXJhYmxlQ29sdW1uIFtwUmVvcmRlcmFibGVDb2x1bW5EaXNhYmxlZF09XCIhY29sLmNhbkJlUmVvcmRlcmVkID8gdHJ1ZSA6IGZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cImNvbC5mcm96ZW5Db2x1bW5BbGlnbiA9PT0gRnJvemVuQ29sdW1uQWxpZ24uTGVmdCB8fCBjb2wuZnJvemVuQ29sdW1uQWxpZ24gPT09IEZyb3plbkNvbHVtbkFsaWduLlJpZ2h0XCIgW2FsaWduRnJvemVuXT1cImdldEZyb3plbkNvbHVtbkFsaWduQXNUZXh0KGNvbC5mcm96ZW5Db2x1bW5BbGlnbilcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbcFNvcnRhYmxlQ29sdW1uXT1cImNvbC5maWVsZFwiIFtwU29ydGFibGVDb2x1bW5EaXNhYmxlZF09XCIhY29sLmNhbkJlU29ydGVkID8gdHJ1ZSA6IGZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGU9XCJ0ZXh0LWFsaWduOiBjZW50ZXI7XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cImNvbC5maWVsZCArICctaGVhZGVyJ1wiIFthdHRyLnNjb3BlXT1cIidjb2wnXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJkaXNwbGF5OiBmbGV4OyBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47IGFsaWduLWl0ZW1zOiBjZW50ZXI7IHdpZHRoOiAxMDAlO1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cIm1hcmdpbi1yaWdodDogMTVweDtcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj57eyBjb2wuaGVhZGVyIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IHN0eWxlPVwiZGlzcGxheTogZmxleDsgYWxpZ24taXRlbXM6IGNlbnRlcjsgZ2FwOiA1cHg7XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvbC5jYW5CZVNvcnRlZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1zb3J0SWNvbiBbZmllbGRdPVwiY29sLmZpZWxkXCI+PC9wLXNvcnRJY29uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJjb2wuY2FuQmVGaWx0ZXJlZFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWNvbC5maWx0ZXJQcmVkZWZpbmVkVmFsdWVzTmFtZSB8fCBjb2wuZmlsdGVyUHJlZGVmaW5lZFZhbHVlc05hbWUubGVuZ3RoID09PSAwOyBlbHNlIGVjc0Vsc2UzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cC1jb2x1bW5GaWx0ZXIgW3R5cGVdPVwiZ2V0RGF0YVR5cGVBc1RleHQoY29sLmRhdGFUeXBlKVwiIFtmaWVsZF09XCJjb2wuZmllbGRcIiBkaXNwbGF5PVwibWVudVwiIFtzaG93QnV0dG9uc109XCJmYWxzZVwiIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj48L3AtY29sdW1uRmlsdGVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj48bmctdGVtcGxhdGUgI2Vjc0Vsc2UzPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtY29sdW1uRmlsdGVyXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3R5cGVdPVwiZ2V0RGF0YVR5cGVBc1RleHQoY29sLmRhdGFUeXBlKVwiIFtmaWVsZF09XCJjb2wuZmllbGRcIiBkaXNwbGF5PVwibWVudVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3Nob3dCdXR0b25zXT1cImZhbHNlXCIgbWF0Y2hNb2RlPVwiaW5cIiBvcGVyYXRvcj1cIm9yXCIgW3Nob3dNYXRjaE1vZGVzXT1cImZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2hvd09wZXJhdG9yXT1cImZhbHNlXCIgW3Nob3dBZGRCdXR0b25dPVwiZmFsc2VcIiBbc2hvd0NsZWFyQnV0dG9uXT1cImZhbHNlXCIgW3Nob3dBcHBseUJ1dHRvbl09XCJmYWxzZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJmaWx0ZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHAtbXVsdGlTZWxlY3RcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZV09XCJ7IG1pbldpZHRoOiAnNDAwcHgnIH1cIiBbKG5nTW9kZWwpXT1cInByZWRlZmluZWRGaWx0ZXJzU2VsZWN0ZWRWYWx1ZXNDb2xsZWN0aW9uW2NvbC5maWx0ZXJQcmVkZWZpbmVkVmFsdWVzTmFtZV1cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW29wdGlvbnNdPVwiZ2V0UHJlZGVmaW5lZEZpbHRlclZhbHVlcyhjb2wuZmlsdGVyUHJlZGVmaW5lZFZhbHVlc05hbWUpXCIgW3BsYWNlaG9sZGVyXT1cIidBbnkgdmFsdWUnIHwgZWNzVHJhbnNsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChvbkNoYW5nZSk9XCJvblByZWRlZmluZWRGaWx0ZXJDaGFuZ2UoY29sLmZpZWxkLCAkZXZlbnQudmFsdWUpXCIgb3B0aW9uTGFiZWw9XCJuYW1lXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGUgcFRlbXBsYXRlPVwiaXRlbVwiIGxldC1vcHRpb24gPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgc3R5bGU9XCJkaXNwbGF5OiBpbmxpbmUtYmxvY2s7IHZlcnRpY2FsLWFsaWduOiBtaWRkbGU7XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxlY3MtdGFibGUtcHJlZGVmaW5lZC1maWx0ZXJzIFtvcHRpb25dPVwib3B0aW9uXCIgW2NvbF09XCJjb2xcIiBbc2VsZWN0YWJsZV09XCJmYWxzZVwiIFtyb3dEYXRhXT1cIm51bGxcIj48L2Vjcy10YWJsZS1wcmVkZWZpbmVkLWZpbHRlcnM+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3AtbXVsdGlTZWxlY3Q+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvcC1jb2x1bW5GaWx0ZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImNvbC5jb2x1bW5EZXNjcmlwdGlvbiAmJiBjb2wuY29sdW1uRGVzY3JpcHRpb24ubGVuZ3RoID4gMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aSBbcFRvb2x0aXBdPVwiKGNvbC5jb2x1bW5EZXNjcmlwdGlvbikgfCBlY3NUcmFuc2xhdGVcIiB0b29sdGlwUG9zaXRpb249XCJ0b3BcIiBbY2xhc3NdPVwidGFibGVPcHRpb25zLmNvbHVtbkRlc2NyaXB0aW9uSWNvbiB8fCAncGkgcGktaW5mby1jaXJjbGUnXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvdGg+XHJcbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8uZW5hYmxlZCAmJiB0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93U2VsZWN0b3JDb2x1bW5IZWFkZXJUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhY3Rpb25Db2x1bW5IZWFkZXJUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICAgIDwhLS0gTE9HSUMgRk9SIERSQVdJTkcgVEFCTEUgREFUQSBXSEVOIFRIRVJFIElTIENPTlRFTlRTIC0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJib2R5XCIgbGV0LXJvd0RhdGEgbGV0LWNvbHVtbnM9XCJjb2x1bW5zXCI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0cmVlU3RhdGU/LmlzTW9yZShyb3dEYXRhKTsgZWxzZSBlY3NFbHNlNFwiPlxyXG4gICAgICAgICAgICAgICAgPHRyIGNsYXNzPVwiZWNzLXRyZWUtbW9yZS1yb3dcIj5cclxuICAgICAgICAgICAgICAgICAgICA8dGQgY29sc3Bhbj1cIjk5OVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8cC1idXR0b24gaWNvbj1cInBpIHBpLXBsdXNcIiBzdHlsZUNsYXNzPVwicC1idXR0b24tdGV4dFwiIFtsYWJlbF09XCInTG9hZCBtb3JlIGNoaWxkcmVuJyB8IGVjc1RyYW5zbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAob25DbGljayk9XCJsb2FkTW9yZVRyZWVSb3dzKCRldmVudCwgcm93RGF0YSlcIiA+PC9wLWJ1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICAgICAgPC90cj5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+PG5nLXRlbXBsYXRlICNlY3NFbHNlND5cclxuICAgICAgICAgICAgPHRyIFtwU2VsZWN0YWJsZVJvd109XCJyb3dEYXRhXCIgW25nQ2xhc3NdPVwidGFibGVPcHRpb25zLnJvd3M/LmNsYXNzPy4ocm93RGF0YSlcIiBbbmdTdHlsZV09XCJ0YWJsZU9wdGlvbnMucm93cz8uc3R5bGU/Lihyb3dEYXRhKVwiXHJcbiAgICAgICAgICAgICAgICBbYXR0ci5hcmlhLWxldmVsXT1cInRyZWVTdGF0ZSA/IHRyZWVTdGF0ZS5kZXB0aChyb3dEYXRhKSArIDEgOiBudWxsXCJcclxuICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwidHJlZVN0YXRlPy5oYXNDaGlsZHJlbihyb3dEYXRhKSA/IHRyZWVTdGF0ZT8uaXNFeHBhbmRlZChyb3dEYXRhKSA6IG51bGxcIj5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhdGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhY3Rpb25Db2x1bW5UZW1wbGF0ZTsgY29udGV4dDogeyByb3dEYXRhOiByb3dEYXRhIH1cIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5yb3dzPy5jaGVja2JveFNlbGVjdG9yPy5lbmFibGVkICYmICF0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93U2VsZWN0b3JDb2x1bW5UZW1wbGF0ZVwiIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHJvd0RhdGE6IHJvd0RhdGEgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2wgb2YgY29sdW1uczsgdHJhY2tCeTogZWNzVHJhY2s1OyBsZXQgJGluZGV4ID0gaW5kZXg7IGxldCAkZmlyc3QgPSBmaXJzdDsgbGV0ICRsYXN0ID0gbGFzdDsgbGV0ICRldmVuID0gZXZlbjsgbGV0ICRvZGQgPSBvZGQ7IGxldCAkY291bnQgPSBjb3VudFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0ZCAobW91c2Vkb3duKT1cImNvbC5kYXRhVHlwZSAhPT0gRGF0YVR5cGUuQm9vbGVhbiAmJiBjb3B5VG9DbGlwYm9hcmRTdGFydCgkZXZlbnQpXCIgKG1vdXNldXApPVwiY29weVRvQ2xpcGJvYXJkQ2FuY2VsKClcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbbmdTdHlsZV09XCJnZXRDb2x1bW5TdHlsZShjb2wpXCIgcEZyb3plbkNvbHVtbiBbZnJvemVuXT1cImNvbC5mcm96ZW5Db2x1bW5BbGlnbiA9PT0gRnJvemVuQ29sdW1uQWxpZ24uTGVmdCB8fCBjb2wuZnJvemVuQ29sdW1uQWxpZ24gPT09IEZyb3plbkNvbHVtbkFsaWduLlJpZ2h0XCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFthbGlnbkZyb3plbl09XCJnZXRGcm96ZW5Db2x1bW5BbGlnbkFzVGV4dChjb2wuZnJvemVuQ29sdW1uQWxpZ24pXCIgW3N0eWxlLnRleHQtYWxpZ25dPVwiZ2V0RGF0YUFsaWduSG9yaXpvbnRhbEFzVGV4dChjb2wuZGF0YUFsaWduSG9yaXpvbnRhbClcIiBbc3R5bGUudmVydGljYWwtYWxpZ25dPVwiZ2V0RGF0YUFsaWduVmVydGljYWxBc1RleHQoY29sLmRhdGFBbGlnblZlcnRpY2FsKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidHJlZVN0YXRlICYmIGNvbC5maWVsZCA9PT0gdHJlZUNvbHVtbjsgZWxzZSBlY3NFbHNlNVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImVjcy10cmVlLWNlbGxcIiBbc3R5bGUucGFkZGluZy1pbmxpbmUtc3RhcnQucHhdPVwidHJlZVN0YXRlLmRlcHRoKHJvd0RhdGEpICogMjBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImVjcy10cmVlLXRvZ2dsZVwiIFtjbGFzcy5lY3MtdHJlZS1sZWFmXT1cIiF0cmVlU3RhdGUuaGFzQ2hpbGRyZW4ocm93RGF0YSlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIXRyZWVTdGF0ZS5oYXNDaGlsZHJlbihyb3dEYXRhKSB8fCB0cmVlU3RhdGUuaXNMb2FkaW5nKHJvd0RhdGEpIHx8IHRyZWVTdGF0ZS5sb2FkaW5nXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2F0dHIuYXJpYS1sYWJlbF09XCIodHJlZVN0YXRlLmlzRXhwYW5kZWQocm93RGF0YSkgPyAnQ29sbGFwc2Ugbm9kZScgOiAnRXhwYW5kIG5vZGUnKSB8IGVjc1RyYW5zbGF0ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFthdHRyLmFyaWEtZXhwYW5kZWRdPVwidHJlZVN0YXRlLmhhc0NoaWxkcmVuKHJvd0RhdGEpID8gdHJlZVN0YXRlLmlzRXhwYW5kZWQocm93RGF0YSkgOiBudWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3BUb29sdGlwXT1cIih0cmVlU3RhdGUuaXNFeHBhbmRlZChyb3dEYXRhKSA/ICdDb2xsYXBzZSBub2RlJyA6ICdFeHBhbmQgbm9kZScpIHwgZWNzVHJhbnNsYXRlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKG1vdXNlZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIiAobW91c2V1cCk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlVHJlZVJvdygkZXZlbnQsIHJvd0RhdGEpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpIFtjbGFzc109XCJ0cmVlU3RhdGUuaXNMb2FkaW5nKHJvd0RhdGEpID8gJ3BpIHBpLXNwaW5uZXIgcGktc3BpbicgOiB0cmVlU3RhdGUuaXNFeHBhbmRlZChyb3dEYXRhKSA/ICdwaSBwaS1jaGV2cm9uLWRvd24nIDogJ3BpIHBpLWNoZXZyb24tcmlnaHQnXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxlY3MtdGFibGUtY2VsbCBbY29sXT1cImNvbFwiIFtyb3dEYXRhXT1cInJvd0RhdGFcIiBbZ2xvYmFsU2VhcmNoVGV4dF09XCJlZmZlY3RpdmVHbG9iYWxTZWFyY2hUZXh0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2RhdGVGb3JtYXRdPVwiZGF0ZUZvcm1hdFwiIFtkYXRlVGltZXpvbmVdPVwiZGF0ZVRpbWV6b25lXCIgW2RhdGVDdWx0dXJlXT1cImRhdGVDdWx0dXJlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ByZWRlZmluZWRGaWx0ZXJzQ29sbGVjdGlvbl09XCJ0YWJsZU9wdGlvbnMucHJlZGVmaW5lZEZpbHRlcnNcIiA+PC9lY3MtdGFibGUtY2VsbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj48bmctdGVtcGxhdGUgI2Vjc0Vsc2U1PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZWNzLXRhYmxlLWNlbGwgW2NvbF09XCJjb2xcIiBbcm93RGF0YV09XCJyb3dEYXRhXCIgW2dsb2JhbFNlYXJjaFRleHRdPVwiZWZmZWN0aXZlR2xvYmFsU2VhcmNoVGV4dFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGF0ZUZvcm1hdF09XCJkYXRlRm9ybWF0XCIgW2RhdGVUaW1lem9uZV09XCJkYXRlVGltZXpvbmVcIiBbZGF0ZUN1bHR1cmVdPVwiZGF0ZUN1bHR1cmVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ByZWRlZmluZWRGaWx0ZXJzQ29sbGVjdGlvbl09XCJ0YWJsZU9wdGlvbnMucHJlZGVmaW5lZEZpbHRlcnNcIj48L2Vjcy10YWJsZS1jZWxsPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8uZW5hYmxlZCAmJiB0YWJsZU9wdGlvbnMucm93cz8uY2hlY2tib3hTZWxlY3Rvcj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwicm93U2VsZWN0b3JDb2x1bW5UZW1wbGF0ZVwiIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJ7IHJvd0RhdGE6IHJvd0RhdGEgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidGFibGVPcHRpb25zLnJvd3M/LmFjdGlvbj8ucG9zaXRpb25SaWdodFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhY3Rpb25Db2x1bW5UZW1wbGF0ZTsgY29udGV4dDogeyByb3dEYXRhOiByb3dEYXRhIH1cIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICAgIDwhLS0gTE9HSUMgRk9SIERSQVdJTkcgVEFCTEUgREFUQSBXSEVOIFRIRVJFIElTIE5PIENPTlRFTlRTIC0tPlxyXG4gICAgICAgIDxuZy10ZW1wbGF0ZSBwVGVtcGxhdGU9XCJlbXB0eW1lc3NhZ2VcIj5cclxuICAgICAgICAgICAgPHRyPlxyXG4gICAgICAgICAgICAgICAgPHRkIGNvbHNwYW49XCI5OTlcIj57eyAnTm8gZGF0YSBmb3VuZCBmb3IgdGhlIGN1cnJlbnQgZmlsdGVyIGNyaXRlcmlhLicgfCBlY3NUcmFuc2xhdGUgfX08L3RkPlxyXG4gICAgICAgICAgICA8L3RyPlxyXG4gICAgICAgIDwvbmctdGVtcGxhdGU+XHJcblxyXG4gICAgICAgIDwhLS0gU0hPVyBDVVNUT00gUkVDT1JEUyBSRVBPUlQgLS0+XHJcbiAgICAgICAgPG5nLXRlbXBsYXRlIHBUZW1wbGF0ZT1cInBhZ2luYXRvcmxlZnRcIj5cclxuICAgICAgICAgICAgPGRpdiAjcGFnaW5hdG9yQ29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBzdHlsZT1cImRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGdhcDogMTBweDtcIj5cclxuICAgICAgICAgICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwidGFibGVPcHRpb25zLmxlZ2VuZD8uY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZWNzLXRhYmxlLWJ1dHRvbiBbYnV0dG9uXT1cInRhYmxlT3B0aW9ucy5sZWdlbmQ/LmJ1dHRvblwiIFtyb3dEYXRhXT1cIm51bGxcIiBbb3ZlcnJpZGVBY3Rpb25dPVwib3AudG9nZ2xlLmJpbmQob3ApXCI+PC9lY3MtdGFibGUtYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8cC1vdmVybGF5UGFuZWwgI29wPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBbaW5uZXJIVE1MXT1cIih0YWJsZU9wdGlvbnMubGVnZW5kPy5jb250ZW50KSB8IGVjc1RyYW5zbGF0ZVwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3Atb3ZlcmxheVBhbmVsPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgICAgICAgICAgIDxzcGFuPnt7ICdTaG93aW5nIHt7Y291bnR9fSByZWNvcmRzIG9mIHt7dG90YWx9fSBhdmFpbGFibGUgcmVjb3JkcycgfCBlY3NUcmFuc2xhdGU6IHsgY291bnQ6IHRvdGFsUmVjb3JkcywgdG90YWw6IHRvdGFsUmVjb3Jkc05vdEZpbHRlcmVkIH0gfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgIDwvcC10YWJsZT5cclxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJ0cmVlU3RhdGVcIj5cclxuICAgICAgICA8ZGl2ICNwYWdpbmF0b3JDb250YWluZXIgY2xhc3M9XCJlY3MtdHJlZS1wYWdpbmF0b3JcIj5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhYmxlT3B0aW9ucy5sZWdlbmQ/LmNvbnRlbnRcIj5cclxuICAgICAgICAgICAgICAgIDxlY3MtdGFibGUtYnV0dG9uIFtidXR0b25dPVwidGFibGVPcHRpb25zLmxlZ2VuZD8uYnV0dG9uXCIgW3Jvd0RhdGFdPVwibnVsbFwiIFtvdmVycmlkZUFjdGlvbl09XCJ0cmVlTGVnZW5kLnRvZ2dsZS5iaW5kKHRyZWVMZWdlbmQpXCIgPjwvZWNzLXRhYmxlLWJ1dHRvbj5cclxuICAgICAgICAgICAgICAgIDxwLW92ZXJsYXlQYW5lbCAjdHJlZUxlZ2VuZD48ZGl2IFtpbm5lckhUTUxdPVwiKHRhYmxlT3B0aW9ucy5sZWdlbmQ/LmNvbnRlbnQpIHwgZWNzVHJhbnNsYXRlXCI+PC9kaXY+PC9wLW92ZXJsYXlQYW5lbD5cclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDxzcGFuPnt7ICdTaG93aW5nIHt7Y291bnR9fSByb290IG5vZGVzIG9mIHt7dG90YWx9fSBhdmFpbGFibGUgcm9vdCBub2RlcycgfCBlY3NUcmFuc2xhdGU6IHsgY291bnQ6IHRvdGFsUmVjb3JkcywgdG90YWw6IHRvdGFsUmVjb3Jkc05vdEZpbHRlcmVkIH0gfX08L3NwYW4+XHJcbiAgICAgICAgICAgIDxwLXBhZ2luYXRvciBbZmlyc3RdPVwiY3VycmVudFBhZ2UgKiBjdXJyZW50Um93c1BlclBhZ2VcIiBbcm93c109XCJjdXJyZW50Um93c1BlclBhZ2VcIiBbdG90YWxSZWNvcmRzXT1cInRvdGFsUmVjb3Jkc1wiXHJcbiAgICAgICAgICAgICAgICBbcm93c1BlclBhZ2VPcHRpb25zXT1cImFsbG93ZWRSb3dzUGVyUGFnZVwiIGRyb3Bkb3duQXBwZW5kVG89XCJib2R5XCIgKG9uUGFnZUNoYW5nZSk9XCJ0cmVlUGFnZUNoYW5nZSgkZXZlbnQpXCIgPjwvcC1wYWdpbmF0b3I+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuPC9kaXY+XHJcbjxlY3MtY29sdW1uLXNlbGVjdG9yIFt2aXNpYmxlXT1cInNob3dDb2x1bW5TZWxlY3RvclwiIFtjb2x1bW5Nb2RhbERhdGFdPVwiY29sdW1uTW9kYWxEYXRhXCIgW2ZpbHRlcmVkQ29sdW1uRGF0YV09XCJmaWx0ZXJlZENvbHVtbkRhdGFcIiBbb3JkZXJCeUhlYWRlcl09XCJ0YWJsZU9wdGlvbnMuY29sdW1ucz8uc2VsZWN0b3JPcmRlckJ5Q29sdW1uTmFtZSA9PT0gdHJ1ZVwiICh2aXNpYmxlQ2hhbmdlKT1cInNob3dDb2x1bW5TZWxlY3Rvcj1mYWxzZVwiIChhcHBseUNoYW5nZXMpPVwiYXBwbHlDb2x1bW5Nb2RhbENoYW5nZXMoJGV2ZW50KVwiPjwvZWNzLWNvbHVtbi1zZWxlY3Rvcj5cclxuPGVjcy1leHBvcnQtZXhjZWwgW3Zpc2libGVdPVwic2hvd0V4cG9ydE1vZGFsXCIgW3Jvd0NoZWNrYm94U2VsZWN0b3JBY3RpdmVdPVwidGFibGVPcHRpb25zLnJvd3M/LmNoZWNrYm94U2VsZWN0b3I/LmVuYWJsZWQgPz8gZmFsc2VcIiBbZXhjZWxSZXBvcnRUaXRsZV09XCJleGNlbFJlcG9ydFRpdGxlXCIgW2FsbG93VGl0bGVVc2VyRWRpdF09XCJ0YWJsZU9wdGlvbnMuZXhjZWxSZXBvcnQ/LnRpdGxlQWxsb3dVc2VyRWRpdCA/PyBmYWxzZVwiICh2aXNpYmxlQ2hhbmdlKT1cInNob3dFeHBvcnRNb2RhbD1mYWxzZVwiIChleHBvcnRUb0V4Y2VsKT1cImdlbmVyYXRlRXhjZWxSZXBvcnQoJGV2ZW50KVwiPjwvZWNzLWV4cG9ydC1leGNlbD5cclxuPGVjcy12aWV3cy1tYW5hZ2VtZW50IFt2aXNpYmxlXT1cInZpZXdzTW9kYWxTaG93XCIgW3RhYmxlVmlld3NfbWVudUl0ZW1zXT1cInRhYmxlVmlld3NfbWVudUl0ZW1zXCIgXHJcbiAgICAob25WaWV3U2VsZWN0KT1cInZpZXdMb2FkKCRldmVudClcIiAob25WaWV3Q3JlYXRlKT1cInZpZXdDcmVhdGUoJGV2ZW50KVwiIChvblZpZXdEZWxldGUpPVwidmlld0RlbGV0ZSgkZXZlbnQpXCIgKG9uVmlld0VkaXRBbGlhcyk9XCJ2aWV3RWRpdEFsaWFzKCRldmVudClcIiAob25WaWV3VXBkYXRlRGF0YSk9XCJ2aWV3VXBkYXRlRGF0YSgkZXZlbnQpXCIgKG9uVmlld1VwZGF0ZUFjdGl2ZVN0YXJ0dXApPVwidmlld1VwZGF0ZUFjdGl2ZVN0YXJ0dXAoJGV2ZW50KVwiXHJcbiAgICAodmlzaWJsZUNoYW5nZSk9XCJ2aWV3c01vZGFsU2hvdz1mYWxzZVwiPjwvZWNzLXZpZXdzLW1hbmFnZW1lbnQ+XHJcbjwhLS0gQm9keS1sZXZlbCBvdmVybGF5cyBhdm9pZCBjbGlwcGluZyBpbnNpZGUgc2Nyb2xsYWJsZSBhbmQgZnJvemVuIHRhYmxlIGNlbGxzLiAtLT5cclxuPHAtbWVudSAjcmVzcG9uc2l2ZUhlYWRlck1lbnUgW21vZGVsXT1cImhlYWRlck1lbnVJdGVtc1wiIFtwb3B1cF09XCJ0cnVlXCIgYXBwZW5kVG89XCJib2R5XCIgc3R5bGVDbGFzcz1cImVjcy1yZXNwb25zaXZlLW1lbnVcIj48L3AtbWVudT5cclxuPHAtbWVudSAjcmVzcG9uc2l2ZVJvd01lbnUgW21vZGVsXT1cInJvd01lbnVJdGVtc1wiIFtwb3B1cF09XCJ0cnVlXCIgYXBwZW5kVG89XCJib2R5XCIgc3R5bGVDbGFzcz1cImVjcy1yZXNwb25zaXZlLW1lbnVcIj48L3AtbWVudT5cclxuIl19
|