@aquera/ngx-smart-table 0.0.17-alpha → 0.0.19-alpha
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/{fesm2020 → fesm2022}/aquera-ngx-smart-table.mjs +1579 -2101
- package/fesm2022/aquera-ngx-smart-table.mjs.map +1 -0
- package/package.json +8 -16
- package/types/aquera-ngx-smart-table.d.ts +5909 -0
- package/aquera-ngx-smart-table.d.ts +0 -5
- package/esm2020/aquera-ngx-smart-table.mjs +0 -5
- package/esm2020/lib/builder/components/builder-preview/builder-preview.component.mjs +0 -63
- package/esm2020/lib/builder/components/builder-toolbar/builder-toolbar.component.mjs +0 -115
- package/esm2020/lib/builder/components/column-editor/column-editor.component.mjs +0 -206
- package/esm2020/lib/builder/components/column-list/column-list.component.mjs +0 -125
- package/esm2020/lib/builder/components/definition-builder/definition-builder.component.mjs +0 -105
- package/esm2020/lib/builder/components/table-config-editor/table-config-editor.component.mjs +0 -132
- package/esm2020/lib/builder/definition-builder.module.mjs +0 -70
- package/esm2020/lib/builder/models/builder-state.interface.mjs +0 -5
- package/esm2020/lib/builder/services/definition-builder.service.mjs +0 -251
- package/esm2020/lib/builder/services/definition-export.service.mjs +0 -167
- package/esm2020/lib/builder/services/definition-import.service.mjs +0 -193
- package/esm2020/lib/builder/services/sample-data-generator.service.mjs +0 -126
- package/esm2020/lib/builder/utils/config-validator.util.mjs +0 -165
- package/esm2020/lib/builder/utils/typescript-generator.util.mjs +0 -206
- package/esm2020/lib/editors/index.mjs +0 -9
- package/esm2020/lib/editors/nile-autocomplete-editor.mjs +0 -228
- package/esm2020/lib/editors/nile-calendar-editor.mjs +0 -211
- package/esm2020/lib/editors/nile-date-picker-editor.mjs +0 -188
- package/esm2020/lib/editors/nile-input-editor.mjs +0 -235
- package/esm2020/lib/editors/nile-select-editor.mjs +0 -498
- package/esm2020/lib/factories/column-config.factory.mjs +0 -231
- package/esm2020/lib/models/autosave-config.interface.mjs +0 -8
- package/esm2020/lib/models/base-column-config.class.mjs +0 -253
- package/esm2020/lib/models/cell-strategies.interface.mjs +0 -6
- package/esm2020/lib/models/cell-types.mjs +0 -147
- package/esm2020/lib/models/column-action.interface.mjs +0 -6
- package/esm2020/lib/models/column-config.interface.mjs +0 -43
- package/esm2020/lib/models/column-config.utils.mjs +0 -101
- package/esm2020/lib/models/row-action.interface.mjs +0 -5
- package/esm2020/lib/models/row-validator.interface.mjs +0 -2
- package/esm2020/lib/models/schema-validation.interface.mjs +0 -2
- package/esm2020/lib/models/sheet-action.interface.mjs +0 -5
- package/esm2020/lib/models/sheet-config.interface.mjs +0 -5
- package/esm2020/lib/models/table-config.interface.mjs +0 -107
- package/esm2020/lib/models/table-validator.interface.mjs +0 -2
- package/esm2020/lib/models/workbook-action.interface.mjs +0 -5
- package/esm2020/lib/models/workbook-config.interface.mjs +0 -5
- package/esm2020/lib/renderer/components/st-add-column-button/st-add-column-button.component.mjs +0 -24
- package/esm2020/lib/renderer/components/st-cell/st-cell.component.mjs +0 -397
- package/esm2020/lib/renderer/components/st-column-editor-modal/st-column-editor-modal.component.mjs +0 -103
- package/esm2020/lib/renderer/components/st-column-filter/st-column-filter.component.mjs +0 -383
- package/esm2020/lib/renderer/components/st-column-menu/st-column-menu.component.mjs +0 -232
- package/esm2020/lib/renderer/components/st-column-visibility/st-column-visibility.component.mjs +0 -97
- package/esm2020/lib/renderer/components/st-header/st-header.component.mjs +0 -157
- package/esm2020/lib/renderer/components/st-pagination/st-pagination.component.mjs +0 -87
- package/esm2020/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.mjs +0 -167
- package/esm2020/lib/renderer/components/st-sheet/st-sheet.component.mjs +0 -165
- package/esm2020/lib/renderer/components/st-sheet-actions/st-sheet-actions.component.mjs +0 -112
- package/esm2020/lib/renderer/components/st-table/st-table.component.mjs +0 -1453
- package/esm2020/lib/renderer/components/st-table-actions/st-table-actions.component.mjs +0 -169
- package/esm2020/lib/renderer/components/st-workbook/st-workbook.component.mjs +0 -581
- package/esm2020/lib/renderer/directives/click-outside.directive.mjs +0 -28
- package/esm2020/lib/renderer/directives/st-column-resize.directive.mjs +0 -108
- package/esm2020/lib/renderer/directives/st-keyboard-navigation.directive.mjs +0 -83
- package/esm2020/lib/renderer/models/cell-state.interface.mjs +0 -66
- package/esm2020/lib/renderer/models/cell.class.mjs +0 -389
- package/esm2020/lib/renderer/models/row-validation-state.interface.mjs +0 -7
- package/esm2020/lib/renderer/models/sheet-state.class.mjs +0 -90
- package/esm2020/lib/renderer/models/sheet-state.interface.mjs +0 -5
- package/esm2020/lib/renderer/models/table-state.class.mjs +0 -871
- package/esm2020/lib/renderer/models/table-state.interface.mjs +0 -5
- package/esm2020/lib/renderer/models/table-types.mjs +0 -29
- package/esm2020/lib/renderer/models/table-validation-state.interface.mjs +0 -7
- package/esm2020/lib/renderer/models/workbook-state.class.mjs +0 -174
- package/esm2020/lib/renderer/models/workbook-state.interface.mjs +0 -5
- package/esm2020/lib/renderer/models/z-index.enum.mjs +0 -55
- package/esm2020/lib/schemas/table-config.schema.mjs +0 -472
- package/esm2020/lib/services/autosave.service.mjs +0 -92
- package/esm2020/lib/services/custom-validation-rules.util.mjs +0 -124
- package/esm2020/lib/services/json-schema-validator.service.mjs +0 -216
- package/esm2020/lib/services/row-validation.service.mjs +0 -42
- package/esm2020/lib/services/validation-logger.service.mjs +0 -177
- package/esm2020/lib/services/virtual-scroll.service.mjs +0 -52
- package/esm2020/lib/shared/shared-table-components.module.mjs +0 -35
- package/esm2020/lib/smart-table.module.mjs +0 -124
- package/esm2020/lib/strategies/default-editors.mjs +0 -433
- package/esm2020/lib/strategies/default-formatters.mjs +0 -238
- package/esm2020/lib/strategies/default-validators.mjs +0 -327
- package/esm2020/public-api.mjs +0 -146
- package/fesm2015/aquera-ngx-smart-table.mjs +0 -12347
- package/fesm2015/aquera-ngx-smart-table.mjs.map +0 -1
- package/fesm2020/aquera-ngx-smart-table.mjs.map +0 -1
- package/lib/builder/components/builder-preview/builder-preview.component.d.ts +0 -31
- package/lib/builder/components/builder-toolbar/builder-toolbar.component.d.ts +0 -53
- package/lib/builder/components/column-editor/column-editor.component.d.ts +0 -69
- package/lib/builder/components/column-list/column-list.component.d.ts +0 -65
- package/lib/builder/components/definition-builder/definition-builder.component.d.ts +0 -58
- package/lib/builder/components/table-config-editor/table-config-editor.component.d.ts +0 -32
- package/lib/builder/definition-builder.module.d.ts +0 -15
- package/lib/builder/models/builder-state.interface.d.ts +0 -93
- package/lib/builder/services/definition-builder.service.d.ts +0 -80
- package/lib/builder/services/definition-export.service.d.ts +0 -59
- package/lib/builder/services/definition-import.service.d.ts +0 -31
- package/lib/builder/services/sample-data-generator.service.d.ts +0 -41
- package/lib/builder/utils/config-validator.util.d.ts +0 -32
- package/lib/builder/utils/typescript-generator.util.d.ts +0 -29
- package/lib/editors/index.d.ts +0 -8
- package/lib/editors/nile-autocomplete-editor.d.ts +0 -102
- package/lib/editors/nile-calendar-editor.d.ts +0 -88
- package/lib/editors/nile-date-picker-editor.d.ts +0 -97
- package/lib/editors/nile-input-editor.d.ts +0 -67
- package/lib/editors/nile-select-editor.d.ts +0 -113
- package/lib/factories/column-config.factory.d.ts +0 -73
- package/lib/models/autosave-config.interface.d.ts +0 -23
- package/lib/models/base-column-config.class.d.ts +0 -115
- package/lib/models/cell-strategies.interface.d.ts +0 -188
- package/lib/models/cell-types.d.ts +0 -337
- package/lib/models/column-action.interface.d.ts +0 -86
- package/lib/models/column-config.interface.d.ts +0 -272
- package/lib/models/column-config.utils.d.ts +0 -37
- package/lib/models/row-action.interface.d.ts +0 -86
- package/lib/models/row-validator.interface.d.ts +0 -37
- package/lib/models/schema-validation.interface.d.ts +0 -42
- package/lib/models/sheet-action.interface.d.ts +0 -59
- package/lib/models/sheet-config.interface.d.ts +0 -41
- package/lib/models/table-config.interface.d.ts +0 -251
- package/lib/models/table-validator.interface.d.ts +0 -40
- package/lib/models/workbook-action.interface.d.ts +0 -95
- package/lib/models/workbook-config.interface.d.ts +0 -107
- package/lib/renderer/components/st-add-column-button/st-add-column-button.component.d.ts +0 -9
- package/lib/renderer/components/st-cell/st-cell.component.d.ts +0 -69
- package/lib/renderer/components/st-column-editor-modal/st-column-editor-modal.component.d.ts +0 -39
- package/lib/renderer/components/st-column-filter/st-column-filter.component.d.ts +0 -139
- package/lib/renderer/components/st-column-menu/st-column-menu.component.d.ts +0 -81
- package/lib/renderer/components/st-column-visibility/st-column-visibility.component.d.ts +0 -44
- package/lib/renderer/components/st-header/st-header.component.d.ts +0 -93
- package/lib/renderer/components/st-pagination/st-pagination.component.d.ts +0 -42
- package/lib/renderer/components/st-row-actions-dropdown/st-row-actions-dropdown.component.d.ts +0 -67
- package/lib/renderer/components/st-sheet/st-sheet.component.d.ts +0 -98
- package/lib/renderer/components/st-sheet-actions/st-sheet-actions.component.d.ts +0 -58
- package/lib/renderer/components/st-table/st-table.component.d.ts +0 -380
- package/lib/renderer/components/st-table-actions/st-table-actions.component.d.ts +0 -77
- package/lib/renderer/components/st-workbook/st-workbook.component.d.ts +0 -275
- package/lib/renderer/directives/click-outside.directive.d.ts +0 -10
- package/lib/renderer/directives/st-column-resize.directive.d.ts +0 -44
- package/lib/renderer/directives/st-keyboard-navigation.directive.d.ts +0 -19
- package/lib/renderer/models/cell-state.interface.d.ts +0 -118
- package/lib/renderer/models/cell.class.d.ts +0 -174
- package/lib/renderer/models/row-validation-state.interface.d.ts +0 -27
- package/lib/renderer/models/sheet-state.class.d.ts +0 -67
- package/lib/renderer/models/sheet-state.interface.d.ts +0 -55
- package/lib/renderer/models/table-state.class.d.ts +0 -320
- package/lib/renderer/models/table-state.interface.d.ts +0 -18
- package/lib/renderer/models/table-types.d.ts +0 -228
- package/lib/renderer/models/table-validation-state.interface.d.ts +0 -34
- package/lib/renderer/models/workbook-state.class.d.ts +0 -117
- package/lib/renderer/models/workbook-state.interface.d.ts +0 -71
- package/lib/renderer/models/z-index.enum.d.ts +0 -44
- package/lib/schemas/table-config.schema.d.ts +0 -455
- package/lib/services/autosave.service.d.ts +0 -73
- package/lib/services/custom-validation-rules.util.d.ts +0 -12
- package/lib/services/json-schema-validator.service.d.ts +0 -49
- package/lib/services/row-validation.service.d.ts +0 -17
- package/lib/services/validation-logger.service.d.ts +0 -87
- package/lib/services/virtual-scroll.service.d.ts +0 -44
- package/lib/shared/shared-table-components.module.d.ts +0 -9
- package/lib/smart-table.module.d.ts +0 -26
- package/lib/strategies/default-editors.d.ts +0 -109
- package/lib/strategies/default-formatters.d.ts +0 -116
- package/lib/strategies/default-validators.d.ts +0 -113
- package/public-api.d.ts +0 -70
- package/src/lib/builder/README.md +0 -30
- package/src/lib/editors/README.md +0 -303
- package/src/lib/renderer/components/st-column-filter/README.md +0 -286
|
@@ -1,1453 +0,0 @@
|
|
|
1
|
-
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, HostListener } from '@angular/core';
|
|
2
|
-
import { Cell } from '../../models/cell.class';
|
|
3
|
-
import { TableState } from '../../models/table-state.class';
|
|
4
|
-
import { mergeTableConfig } from '../../../models/table-config.interface';
|
|
5
|
-
import { EditMode } from '../../../models/cell-types';
|
|
6
|
-
import { BehaviorSubject } from 'rxjs';
|
|
7
|
-
import { map, distinctUntilChanged } from 'rxjs/operators';
|
|
8
|
-
import { TableZIndex } from '../../models/z-index.enum';
|
|
9
|
-
import { SortDirection } from '../../models/table-types';
|
|
10
|
-
import * as i0 from "@angular/core";
|
|
11
|
-
import * as i1 from "../../../services/json-schema-validator.service";
|
|
12
|
-
import * as i2 from "../../../services/validation-logger.service";
|
|
13
|
-
import * as i3 from "../../../services/virtual-scroll.service";
|
|
14
|
-
import * as i4 from "../st-pagination/st-pagination.component";
|
|
15
|
-
import * as i5 from "../st-column-menu/st-column-menu.component";
|
|
16
|
-
import * as i6 from "../st-row-actions-dropdown/st-row-actions-dropdown.component";
|
|
17
|
-
import * as i7 from "../st-header/st-header.component";
|
|
18
|
-
import * as i8 from "../st-table-actions/st-table-actions.component";
|
|
19
|
-
import * as i9 from "../st-cell/st-cell.component";
|
|
20
|
-
import * as i10 from "@angular/common";
|
|
21
|
-
import * as i11 from "../../directives/st-keyboard-navigation.directive";
|
|
22
|
-
import * as i12 from "../../directives/st-column-resize.directive";
|
|
23
|
-
export class StTableComponent {
|
|
24
|
-
constructor(schemaValidator, logger, virtualScrollService, elementRef) {
|
|
25
|
-
this.schemaValidator = schemaValidator;
|
|
26
|
-
this.logger = logger;
|
|
27
|
-
this.virtualScrollService = virtualScrollService;
|
|
28
|
-
this.elementRef = elementRef;
|
|
29
|
-
// Z-Index constants for template use
|
|
30
|
-
this.ZIndex = TableZIndex;
|
|
31
|
-
// DEPRECATED: Use tableConfig instead
|
|
32
|
-
this.enableSorting = true;
|
|
33
|
-
this.enableFiltering = true;
|
|
34
|
-
// NEW: State change output
|
|
35
|
-
this.stateChange = new EventEmitter();
|
|
36
|
-
// NEW: Data change output (for async data updates)
|
|
37
|
-
this.dataChange = new EventEmitter();
|
|
38
|
-
// EXISTING: Cell and column events
|
|
39
|
-
this.cellEdit = new EventEmitter();
|
|
40
|
-
this.cellSave = new EventEmitter();
|
|
41
|
-
this.cellCancel = new EventEmitter();
|
|
42
|
-
this.cellChange = new EventEmitter();
|
|
43
|
-
this.columnResized = new EventEmitter();
|
|
44
|
-
this.columnMoved = new EventEmitter();
|
|
45
|
-
// NEW: Configuration validation output
|
|
46
|
-
this.configValidationErrors = new EventEmitter();
|
|
47
|
-
// NEW: Column management output
|
|
48
|
-
this.columnAdded = new EventEmitter();
|
|
49
|
-
// NEW: Row action output
|
|
50
|
-
this.rowAction = new EventEmitter();
|
|
51
|
-
// NEW: Validation state change output
|
|
52
|
-
this.validationStateChange = new EventEmitter();
|
|
53
|
-
// NEW: Request to add a new row (emitted when navigating past last row with addRowOnNavigatePastEnd enabled)
|
|
54
|
-
this.requestAddRow = new EventEmitter();
|
|
55
|
-
// NEW: Optional validation flag
|
|
56
|
-
this.validateConfig = false;
|
|
57
|
-
this.internalData$ = new BehaviorSubject([]);
|
|
58
|
-
this.previousData = [];
|
|
59
|
-
// Modal state
|
|
60
|
-
this.showColumnModal = false;
|
|
61
|
-
// Cached visible columns and cell grid to prevent re-creation on every change detection
|
|
62
|
-
this.visibleColumns = [];
|
|
63
|
-
this.visibleCellGrid = [];
|
|
64
|
-
// Row actions dropdown state
|
|
65
|
-
this.dropdownState = {
|
|
66
|
-
isOpen: false,
|
|
67
|
-
position: { x: 0, y: 0 },
|
|
68
|
-
context: null
|
|
69
|
-
};
|
|
70
|
-
// Column menu dropdown state
|
|
71
|
-
this.columnMenuState = {
|
|
72
|
-
isOpen: false,
|
|
73
|
-
position: { x: 0, y: 0 },
|
|
74
|
-
context: null
|
|
75
|
-
};
|
|
76
|
-
this.virtualScrollState$ = new BehaviorSubject(null);
|
|
77
|
-
// Observable streams derived from virtual scroll state
|
|
78
|
-
this.virtualScrollTotalHeight$ = this.virtualScrollState$.pipe(map(state => state?.totalHeight ?? 0), distinctUntilChanged());
|
|
79
|
-
this.virtualScrollOffsetY$ = this.virtualScrollState$.pipe(map(state => state?.offsetY ?? 0), distinctUntilChanged());
|
|
80
|
-
this.virtualScrollOffsetYNeg$ = this.virtualScrollState$.pipe(map(state => Number(state?.offsetY ?? 0) * -1), distinctUntilChanged());
|
|
81
|
-
this.visibleRows$ = this.virtualScrollState$.pipe(map(state => {
|
|
82
|
-
if (!state)
|
|
83
|
-
return this.visibleCellGrid;
|
|
84
|
-
const { startIndex, endIndex } = state;
|
|
85
|
-
return this.visibleCellGrid.slice(startIndex, endIndex);
|
|
86
|
-
}));
|
|
87
|
-
/**
|
|
88
|
-
* TrackBy function for better performance
|
|
89
|
-
*/
|
|
90
|
-
this.trackByRowIndex = (index, row) => {
|
|
91
|
-
return this.getAbsoluteRowIndex(index);
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
ngOnInit() {
|
|
95
|
-
// Validate that at least tableConfig or columns is provided
|
|
96
|
-
if (!this.tableConfig) {
|
|
97
|
-
throw new Error('Either tableConfig or columns must be provided');
|
|
98
|
-
}
|
|
99
|
-
// Merge config with defaults
|
|
100
|
-
if (this.tableConfig) {
|
|
101
|
-
this.mergedConfig = mergeTableConfig(this.tableConfig);
|
|
102
|
-
// Validate configuration if enabled
|
|
103
|
-
if (this.validateConfig) {
|
|
104
|
-
this.validateConfiguration(this.mergedConfig);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
// Create or use TableState
|
|
108
|
-
if (!this.tableState) {
|
|
109
|
-
this.createInternalTableState();
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
// Subscribe to external tableState changes
|
|
113
|
-
this.subscribeToExternalTableState();
|
|
114
|
-
}
|
|
115
|
-
// Setup data source (sync or async)
|
|
116
|
-
this.setupDataSource();
|
|
117
|
-
// Calculate sticky offsets
|
|
118
|
-
const rowNumberWidth = this.mergedConfig.showRowNumber ? 30 : 0;
|
|
119
|
-
const settingsColumnWidth = this.hasRowActions() ? 28 : 0; // Settings column is ~32px wide when visible
|
|
120
|
-
this.getActiveTableState().calculateStickyOffsets(rowNumberWidth, settingsColumnWidth);
|
|
121
|
-
// Initialize visible columns and cell grid
|
|
122
|
-
this.updateVisibleData();
|
|
123
|
-
// Initialize virtual scroll if enabled
|
|
124
|
-
if (this.isVirtualScrollEnabled()) {
|
|
125
|
-
this.initializeVirtualScroll();
|
|
126
|
-
}
|
|
127
|
-
// Initialize keyboard navigation if enabled
|
|
128
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
129
|
-
this.initializeKeyboardNavigation();
|
|
130
|
-
}
|
|
131
|
-
this.skeletonColumns = Array.from({ length: this.mergedConfig.tableSkeleton?.columns ?? 10 }, (_, i) => i);
|
|
132
|
-
this.skeletonRows = Array.from({ length: this.mergedConfig.tableSkeleton?.rows ?? 10 }, (_, i) => i);
|
|
133
|
-
}
|
|
134
|
-
ngAfterViewInit() {
|
|
135
|
-
// Setup virtual scroll after view is ready
|
|
136
|
-
if (this.isVirtualScrollEnabled() && this.scrollViewport) {
|
|
137
|
-
this.setupVirtualScrollListener();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
ngOnChanges(changes) {
|
|
141
|
-
// Validate configuration when tableConfig changes
|
|
142
|
-
if (changes['tableConfig'] && !changes['tableConfig'].firstChange && this.tableConfig) {
|
|
143
|
-
this.mergedConfig = mergeTableConfig(this.tableConfig);
|
|
144
|
-
// Validate configuration if enabled
|
|
145
|
-
if (this.validateConfig) {
|
|
146
|
-
this.validateConfiguration(this.mergedConfig);
|
|
147
|
-
}
|
|
148
|
-
// Update internal table state with new columns if using internal state
|
|
149
|
-
if (this.internalTableState) {
|
|
150
|
-
this.internalTableState.updateColumns(this.mergedConfig.columns);
|
|
151
|
-
}
|
|
152
|
-
// Update visible columns and cell grid
|
|
153
|
-
this.updateVisibleData();
|
|
154
|
-
}
|
|
155
|
-
// Recreate cell grid when data changes (only if not using data$ Observable)
|
|
156
|
-
if (changes['data'] && !changes['data'].firstChange && this.data && !this.data$) {
|
|
157
|
-
this.handleSyncDataChange(changes['data'].previousValue || []);
|
|
158
|
-
}
|
|
159
|
-
// Handle data$ Observable input changes
|
|
160
|
-
if (changes['data$'] && !changes['data$'].firstChange) {
|
|
161
|
-
this.setupDataSource();
|
|
162
|
-
}
|
|
163
|
-
// Recreate cell grid when cellGrid changes
|
|
164
|
-
if (changes['cellGrid'] && !changes['cellGrid'].firstChange) {
|
|
165
|
-
// Cell grid was updated externally, no need to recreate
|
|
166
|
-
// Just recalculate sticky offsets if needed
|
|
167
|
-
if (this.getActiveTableState()) {
|
|
168
|
-
const rowNumberWidth = this.mergedConfig.showRowNumber ? 30 : 0;
|
|
169
|
-
const settingsColumnWidth = this.hasRowActions() ? 32 : 0;
|
|
170
|
-
this.getActiveTableState().calculateStickyOffsets(rowNumberWidth, settingsColumnWidth);
|
|
171
|
-
}
|
|
172
|
-
// Update visible columns and cell grid
|
|
173
|
-
this.updateVisibleData();
|
|
174
|
-
}
|
|
175
|
-
// Handle tableState input changes (when external state is provided, e.g., in workbook)
|
|
176
|
-
if (changes['tableState'] && !changes['tableState'].firstChange && this.tableState) {
|
|
177
|
-
// Unsubscribe from all old tableState observables to prevent memory leaks
|
|
178
|
-
this.stateSubscription?.unsubscribe();
|
|
179
|
-
this.validationSubscription?.unsubscribe();
|
|
180
|
-
this.focusSubscription?.unsubscribe();
|
|
181
|
-
// Resubscribe to new tableState's observables
|
|
182
|
-
this.subscribeToExternalTableState();
|
|
183
|
-
// Reinitialize keyboard navigation with new tableState
|
|
184
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
185
|
-
this.initializeKeyboardNavigation();
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
// Recalculate virtual scroll when data changes
|
|
189
|
-
if ((changes['data'] || changes['cellGrid']) && !changes['data']?.firstChange) {
|
|
190
|
-
if (this.isVirtualScrollEnabled()) {
|
|
191
|
-
const currentState = this.virtualScrollState$.value;
|
|
192
|
-
if (currentState) {
|
|
193
|
-
const newState = this.virtualScrollService.calculateVisibleRange({
|
|
194
|
-
scrollTop: currentState.scrollTop,
|
|
195
|
-
viewportHeight: this.getVirtualScrollViewportHeight(),
|
|
196
|
-
totalItems: this.visibleCellGrid.length,
|
|
197
|
-
itemSize: this.getVirtualScrollItemSize(),
|
|
198
|
-
bufferSize: this.getVirtualScrollBufferSize()
|
|
199
|
-
});
|
|
200
|
-
this.virtualScrollState$.next(newState);
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
// Update keyboard navigation dimensions if enabled
|
|
204
|
-
if (this.isKeyboardNavigationEnabled() && (changes['data'] || changes['cellGrid'])) {
|
|
205
|
-
this.getActiveTableState().setDimensions(this.visibleCellGrid.length, this.visibleColumns.length);
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* Create internal TableState from config
|
|
211
|
-
*/
|
|
212
|
-
createInternalTableState() {
|
|
213
|
-
const columns = this.getActiveColumns();
|
|
214
|
-
this.internalTableState = new TableState(columns, {
|
|
215
|
-
pageSize: this.mergedConfig.pagination?.pageSize,
|
|
216
|
-
initialPage: this.mergedConfig.initialState?.page
|
|
217
|
-
});
|
|
218
|
-
// Set total items if provided in config (for server-side pagination)
|
|
219
|
-
if (this.mergedConfig.pagination?.totalItems !== undefined) {
|
|
220
|
-
this.internalTableState.setTotalItems(this.mergedConfig.pagination.totalItems);
|
|
221
|
-
}
|
|
222
|
-
// Apply initial sort if provided
|
|
223
|
-
if (this.mergedConfig.initialState?.sortBy) {
|
|
224
|
-
this.mergedConfig.initialState.sortBy.forEach(sort => {
|
|
225
|
-
this.internalTableState.addSortToColumn(sort.key, sort.direction);
|
|
226
|
-
});
|
|
227
|
-
}
|
|
228
|
-
// Apply initial filters if provided
|
|
229
|
-
if (this.mergedConfig.initialState?.filters) {
|
|
230
|
-
this.mergedConfig.initialState.filters.forEach(filter => {
|
|
231
|
-
this.internalTableState.setFilterOnColumn(filter.key, filter.operator, filter.value);
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
// Subscribe to internal state changes and re-emit
|
|
235
|
-
this.subscribeToInternalState();
|
|
236
|
-
// Subscribe to validation state changes and re-emit
|
|
237
|
-
this.subscribeToValidationState();
|
|
238
|
-
}
|
|
239
|
-
subscribeToValidationState() {
|
|
240
|
-
if (!this.internalTableState)
|
|
241
|
-
return;
|
|
242
|
-
this.validationSubscription = this.internalTableState.tableValidationState$
|
|
243
|
-
.subscribe(state => {
|
|
244
|
-
this.validationStateChange.emit(state);
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
subscribeToInternalState() {
|
|
248
|
-
if (!this.internalTableState)
|
|
249
|
-
return;
|
|
250
|
-
this.stateSubscription = this.internalTableState?.stateChange$
|
|
251
|
-
.subscribe(event => {
|
|
252
|
-
this.stateChange.emit(event);
|
|
253
|
-
// Update visible columns and cell grid on visibility changes
|
|
254
|
-
if (event.type === 'column-visibility' || event.type === 'column-config') {
|
|
255
|
-
this.updateVisibleData();
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Subscribe to external TableState changes
|
|
261
|
-
*/
|
|
262
|
-
subscribeToExternalTableState() {
|
|
263
|
-
if (!this.tableState)
|
|
264
|
-
return;
|
|
265
|
-
this.stateSubscription = this.tableState.stateChange$
|
|
266
|
-
.subscribe(event => {
|
|
267
|
-
this.stateChange.emit(event);
|
|
268
|
-
// Update visible columns and cell grid on visibility changes
|
|
269
|
-
if (event.type === 'column-visibility' || event.type === 'column-config') {
|
|
270
|
-
this.updateVisibleData();
|
|
271
|
-
}
|
|
272
|
-
});
|
|
273
|
-
// Subscribe to validation state changes and re-emit
|
|
274
|
-
this.subscribeToValidationState();
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Create cell grid from raw data
|
|
278
|
-
*/
|
|
279
|
-
createCellGridFromData() {
|
|
280
|
-
if (!this.data)
|
|
281
|
-
return;
|
|
282
|
-
const columns = this.getActiveColumns();
|
|
283
|
-
this.internalCellGrid = this.data.map((rowData, rowIndex) => columns.map(column => new Cell(column, rowData[column.key], rowData, rowIndex)));
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Setup data source - either sync array or async Observable
|
|
287
|
-
* Handles initialization and subscription to data changes
|
|
288
|
-
*/
|
|
289
|
-
setupDataSource() {
|
|
290
|
-
// Warn if both data and data$ are provided
|
|
291
|
-
if (this.data && this.data$) {
|
|
292
|
-
console.warn('StTableComponent: Both data and data$ inputs are provided. Using data$ (Observable) and ignoring data array.');
|
|
293
|
-
}
|
|
294
|
-
// Clean up existing subscription
|
|
295
|
-
this.dataSubscription?.unsubscribe();
|
|
296
|
-
// Priority: data$ takes precedence over data
|
|
297
|
-
if (this.data$) {
|
|
298
|
-
this.subscribeToDataChanges();
|
|
299
|
-
}
|
|
300
|
-
else if (this.data) {
|
|
301
|
-
// For sync data, emit once through internal observable
|
|
302
|
-
this.previousData = [];
|
|
303
|
-
this.internalData$.next(this.data);
|
|
304
|
-
this.subscribeToDataChanges();
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
// No data provided, emit empty array
|
|
308
|
-
this.previousData = [];
|
|
309
|
-
this.internalData$.next([]);
|
|
310
|
-
this.subscribeToDataChanges();
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Subscribe to data changes (either from data$ input or internal BehaviorSubject)
|
|
315
|
-
*/
|
|
316
|
-
subscribeToDataChanges() {
|
|
317
|
-
const dataSource$ = this.data$ || this.internalData$.asObservable();
|
|
318
|
-
this.dataSubscription = dataSource$.subscribe(newData => {
|
|
319
|
-
this.handleDataChange(newData);
|
|
320
|
-
});
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Handle data change from Observable emission
|
|
324
|
-
*/
|
|
325
|
-
handleDataChange(newData) {
|
|
326
|
-
const timestamp = Date.now();
|
|
327
|
-
const source = this.data$ ? 'async' : 'sync';
|
|
328
|
-
// Emit data change event
|
|
329
|
-
this.dataChange.emit({
|
|
330
|
-
previousData: this.previousData,
|
|
331
|
-
currentData: newData,
|
|
332
|
-
timestamp,
|
|
333
|
-
source
|
|
334
|
-
});
|
|
335
|
-
// Update data reference
|
|
336
|
-
this.data = newData;
|
|
337
|
-
this.previousData = [...newData];
|
|
338
|
-
// Recreate cell grid
|
|
339
|
-
this.createCellGridFromData();
|
|
340
|
-
// Update visible data
|
|
341
|
-
this.updateVisibleData();
|
|
342
|
-
// Recalculate virtual scroll if enabled
|
|
343
|
-
if (this.isVirtualScrollEnabled()) {
|
|
344
|
-
const currentState = this.virtualScrollState$.value;
|
|
345
|
-
if (currentState) {
|
|
346
|
-
const newState = this.virtualScrollService.calculateVisibleRange({
|
|
347
|
-
scrollTop: currentState.scrollTop,
|
|
348
|
-
viewportHeight: this.getVirtualScrollViewportHeight(),
|
|
349
|
-
totalItems: this.visibleCellGrid.length,
|
|
350
|
-
itemSize: this.getVirtualScrollItemSize(),
|
|
351
|
-
bufferSize: this.getVirtualScrollBufferSize()
|
|
352
|
-
});
|
|
353
|
-
this.virtualScrollState$.next(newState);
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
// Update keyboard navigation dimensions if enabled
|
|
357
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
358
|
-
this.getActiveTableState().setDimensions(this.visibleCellGrid.length, this.visibleColumns.length);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
/**
|
|
362
|
-
* Handle sync data change (from @Input() data changes)
|
|
363
|
-
*/
|
|
364
|
-
handleSyncDataChange(previousData) {
|
|
365
|
-
this.previousData = previousData;
|
|
366
|
-
this.internalData$.next(this.data || []);
|
|
367
|
-
}
|
|
368
|
-
/**
|
|
369
|
-
* Get active TableState (provided or internal)
|
|
370
|
-
*/
|
|
371
|
-
getActiveTableState() {
|
|
372
|
-
return this.tableState || this.internalTableState;
|
|
373
|
-
}
|
|
374
|
-
/**
|
|
375
|
-
* Get active cell grid (provided or internal)
|
|
376
|
-
*/
|
|
377
|
-
getActiveCellGrid() {
|
|
378
|
-
return this.internalCellGrid || [];
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Get visible cell grid (filtered to only include visible columns)
|
|
382
|
-
*/
|
|
383
|
-
getVisibleCellGrid() {
|
|
384
|
-
const allColumns = this.getActiveColumns();
|
|
385
|
-
const visibleColumns = this.getVisibleColumns();
|
|
386
|
-
const visibleColumnKeys = new Set(visibleColumns.map(col => col.key));
|
|
387
|
-
// Get column indices for visible columns
|
|
388
|
-
const visibleIndices = allColumns
|
|
389
|
-
.map((col, index) => visibleColumnKeys.has(col.key) ? index : -1)
|
|
390
|
-
.filter(index => index !== -1);
|
|
391
|
-
const fullGrid = this.getActiveCellGrid();
|
|
392
|
-
return fullGrid.map(row => visibleIndices.map(index => row[index]).filter(cell => cell !== undefined));
|
|
393
|
-
}
|
|
394
|
-
/**
|
|
395
|
-
* Update the visible cell grid based on current visibility and column order
|
|
396
|
-
* Called when data, visibility, or column order changes
|
|
397
|
-
*
|
|
398
|
-
* This method properly handles column reordering by mapping cells based on
|
|
399
|
-
* column keys rather than indices, ensuring cells follow their columns.
|
|
400
|
-
*/
|
|
401
|
-
updateVisibleCellGrid() {
|
|
402
|
-
const fullGrid = this.getActiveCellGrid();
|
|
403
|
-
// Handle empty grid
|
|
404
|
-
if (!fullGrid || fullGrid.length === 0) {
|
|
405
|
-
this.visibleCellGrid = [];
|
|
406
|
-
return;
|
|
407
|
-
}
|
|
408
|
-
// Build a map of columnKey → cellIndex for the current grid structure
|
|
409
|
-
// This allows us to find cells by column key regardless of their current position
|
|
410
|
-
const keyToIndexMap = new Map();
|
|
411
|
-
fullGrid[0]?.forEach((cell, index) => {
|
|
412
|
-
if (cell) {
|
|
413
|
-
const columnConfig = cell.getColumnConfig();
|
|
414
|
-
keyToIndexMap.set(columnConfig.key, index);
|
|
415
|
-
}
|
|
416
|
-
});
|
|
417
|
-
// Reorder cells to match the visibleColumns order
|
|
418
|
-
// This ensures that when columns are moved, the cell data follows
|
|
419
|
-
this.visibleCellGrid = fullGrid.map(row => {
|
|
420
|
-
return this.visibleColumns
|
|
421
|
-
.map(col => {
|
|
422
|
-
const cellIndex = keyToIndexMap.get(col.key);
|
|
423
|
-
return cellIndex !== undefined ? row[cellIndex] : undefined;
|
|
424
|
-
})
|
|
425
|
-
.filter((cell) => cell !== undefined);
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Update the visible columns based on current visibility
|
|
430
|
-
* Called only when visibility actually changes
|
|
431
|
-
*/
|
|
432
|
-
updateVisibleColumns() {
|
|
433
|
-
const allColumns = this.getActiveColumns();
|
|
434
|
-
this.visibleColumns = allColumns.filter(col => col.visible !== false);
|
|
435
|
-
// Recalculate sticky offsets for visible columns only
|
|
436
|
-
this.recalculateVisibleStickyOffsets(this.visibleColumns);
|
|
437
|
-
}
|
|
438
|
-
/**
|
|
439
|
-
* Update both visible columns and cell grid
|
|
440
|
-
* Call this whenever data or visibility changes
|
|
441
|
-
*/
|
|
442
|
-
updateVisibleData() {
|
|
443
|
-
this.updateVisibleColumns();
|
|
444
|
-
this.updateVisibleCellGrid();
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Get active columns (from config or legacy input)
|
|
448
|
-
*/
|
|
449
|
-
getActiveColumns() {
|
|
450
|
-
return this.mergedConfig.columns;
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Get visible columns (filtered by visibility property)
|
|
454
|
-
* Also recalculates sticky offsets based on visible columns only
|
|
455
|
-
*/
|
|
456
|
-
getVisibleColumns() {
|
|
457
|
-
const allColumns = this.getActiveColumns();
|
|
458
|
-
const visibleColumns = allColumns.filter(col => col.visible !== false); // Default to true if not set
|
|
459
|
-
// Recalculate sticky offsets for visible columns only
|
|
460
|
-
this.recalculateVisibleStickyOffsets(visibleColumns);
|
|
461
|
-
return visibleColumns;
|
|
462
|
-
}
|
|
463
|
-
/**
|
|
464
|
-
* Recalculate sticky offsets based on visible columns only
|
|
465
|
-
* This ensures correct positioning when columns are hidden
|
|
466
|
-
*/
|
|
467
|
-
recalculateVisibleStickyOffsets(visibleColumns) {
|
|
468
|
-
// Calculate left sticky offsets
|
|
469
|
-
// Account for row number column width if shown
|
|
470
|
-
let leftOffset = this.mergedConfig.showRowNumber ? 30 : 0;
|
|
471
|
-
visibleColumns.forEach(col => {
|
|
472
|
-
if (col.sticky === 'left') {
|
|
473
|
-
col.stickyOffset = leftOffset;
|
|
474
|
-
leftOffset += col.width || 100;
|
|
475
|
-
}
|
|
476
|
-
});
|
|
477
|
-
// Calculate right sticky offsets
|
|
478
|
-
let rightOffset = 0;
|
|
479
|
-
for (let i = visibleColumns.length - 1; i >= 0; i--) {
|
|
480
|
-
const col = visibleColumns[i];
|
|
481
|
-
if (col.sticky === 'right') {
|
|
482
|
-
col.stickyOffset = rightOffset;
|
|
483
|
-
rightOffset += col.width || 100;
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
onCellChange(event) {
|
|
488
|
-
this.cellChange.emit(event);
|
|
489
|
-
}
|
|
490
|
-
onColumnResized(event) {
|
|
491
|
-
// Recalculate sticky offsets after resize
|
|
492
|
-
const rowNumberWidth = this.mergedConfig.showRowNumber ? 30 : 0;
|
|
493
|
-
const settingsColumnWidth = this.hasRowActions() ? 32 : 0;
|
|
494
|
-
this.getActiveTableState().calculateStickyOffsets(rowNumberWidth, settingsColumnWidth);
|
|
495
|
-
// Emit to parent
|
|
496
|
-
this.columnResized.emit(event);
|
|
497
|
-
}
|
|
498
|
-
onColumnMoved(event) {
|
|
499
|
-
const columns = this.getActiveColumns();
|
|
500
|
-
const currentIndex = columns.findIndex(c => c.key === event.columnKey);
|
|
501
|
-
if (currentIndex === -1)
|
|
502
|
-
return;
|
|
503
|
-
// Calculate target index
|
|
504
|
-
const targetIndex = event.direction === 'left'
|
|
505
|
-
? currentIndex - 1
|
|
506
|
-
: currentIndex + 1;
|
|
507
|
-
// Check bounds
|
|
508
|
-
if (targetIndex < 0 || targetIndex >= columns.length) {
|
|
509
|
-
return;
|
|
510
|
-
}
|
|
511
|
-
// Swap columns
|
|
512
|
-
[columns[currentIndex], columns[targetIndex]] =
|
|
513
|
-
[columns[targetIndex], columns[currentIndex]];
|
|
514
|
-
// Update TableState with new column order
|
|
515
|
-
this.getActiveTableState().updateColumns(columns);
|
|
516
|
-
this.columnMoved.emit({
|
|
517
|
-
columnKey: event.columnKey,
|
|
518
|
-
direction: event.direction,
|
|
519
|
-
oldIndex: currentIndex,
|
|
520
|
-
newIndex: targetIndex,
|
|
521
|
-
column: columns[currentIndex]
|
|
522
|
-
});
|
|
523
|
-
// Force virtual scroll to re-render by re-emitting current state
|
|
524
|
-
// This ensures visibleRows$ picks up the updated visibleCellGrid
|
|
525
|
-
if (this.isVirtualScrollEnabled()) {
|
|
526
|
-
const currentState = this.virtualScrollState$.value;
|
|
527
|
-
if (currentState) {
|
|
528
|
-
this.virtualScrollState$.next({ ...currentState });
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
/**
|
|
533
|
-
* Move column to position just before right sticky columns (used when pinning right)
|
|
534
|
-
*/
|
|
535
|
-
moveColumnToEnd(columnKey) {
|
|
536
|
-
const columns = this.getActiveColumns();
|
|
537
|
-
const currentIndex = columns.findIndex(c => c.key === columnKey);
|
|
538
|
-
if (currentIndex === -1)
|
|
539
|
-
return;
|
|
540
|
-
// Find the index of the first right-sticky column
|
|
541
|
-
const firstRightStickyIndex = columns.findIndex(c => c.sticky === 'right');
|
|
542
|
-
// Determine target index: just before first right-sticky, or at end if none exist
|
|
543
|
-
const targetIndex = firstRightStickyIndex !== -1 ? firstRightStickyIndex : columns.length;
|
|
544
|
-
// If already at target position, no need to move
|
|
545
|
-
if (currentIndex === targetIndex || currentIndex === targetIndex - 1)
|
|
546
|
-
return;
|
|
547
|
-
// Remove column from current position
|
|
548
|
-
const [column] = columns.splice(currentIndex, 1);
|
|
549
|
-
// Adjust target index if we removed an element before it
|
|
550
|
-
const adjustedTargetIndex = currentIndex < targetIndex ? targetIndex - 1 : targetIndex;
|
|
551
|
-
// Insert at target position (before first right-sticky column, or at end)
|
|
552
|
-
columns.splice(adjustedTargetIndex, 0, column);
|
|
553
|
-
// Update TableState with new column order
|
|
554
|
-
this.getActiveTableState().updateColumns(columns);
|
|
555
|
-
// Force virtual scroll to re-render
|
|
556
|
-
if (this.isVirtualScrollEnabled()) {
|
|
557
|
-
const currentState = this.virtualScrollState$.value;
|
|
558
|
-
if (currentState) {
|
|
559
|
-
this.virtualScrollState$.next({ ...currentState });
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
/**
|
|
564
|
-
* Get cumulative left offset for a sticky column on the left side
|
|
565
|
-
*/
|
|
566
|
-
getStickyLeftOffset(columnKey) {
|
|
567
|
-
const columns = this.getActiveColumns();
|
|
568
|
-
let offset = 0;
|
|
569
|
-
for (const col of columns) {
|
|
570
|
-
if (col.key === columnKey)
|
|
571
|
-
break;
|
|
572
|
-
if (col.sticky === 'left') {
|
|
573
|
-
offset += col.width || 100;
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
return offset;
|
|
577
|
-
}
|
|
578
|
-
/**
|
|
579
|
-
* Get cumulative right offset for a sticky column on the right side
|
|
580
|
-
*/
|
|
581
|
-
getStickyRightOffset(columnKey) {
|
|
582
|
-
const columns = this.getActiveColumns();
|
|
583
|
-
let offset = 0;
|
|
584
|
-
const colIndex = columns.findIndex(c => c.key === columnKey);
|
|
585
|
-
for (let i = colIndex + 1; i < columns.length; i++) {
|
|
586
|
-
const col = columns[i];
|
|
587
|
-
if (col.sticky === 'right') {
|
|
588
|
-
offset += col.width || 100;
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
return offset;
|
|
592
|
-
}
|
|
593
|
-
/**
|
|
594
|
-
* Check if top pagination should be shown
|
|
595
|
-
*/
|
|
596
|
-
showTopPagination() {
|
|
597
|
-
return this.mergedConfig.pagination?.enabled == true &&
|
|
598
|
-
this.mergedConfig.pagination?.showTopControls === true;
|
|
599
|
-
}
|
|
600
|
-
/**
|
|
601
|
-
* Check if bottom pagination should be shown
|
|
602
|
-
*/
|
|
603
|
-
showBottomPagination() {
|
|
604
|
-
return this.mergedConfig.pagination?.enabled == true &&
|
|
605
|
-
(this.mergedConfig.pagination?.showBottomControls ?? true);
|
|
606
|
-
}
|
|
607
|
-
/**
|
|
608
|
-
* Validate table configuration
|
|
609
|
-
* @param config Table configuration to validate
|
|
610
|
-
*/
|
|
611
|
-
validateConfiguration(config) {
|
|
612
|
-
const result = this.schemaValidator.validate(config, true, false); // Disable logging here, we'll log manually with context
|
|
613
|
-
if (!result.valid && result.errors.length > 0) {
|
|
614
|
-
// Emit validation errors
|
|
615
|
-
this.configValidationErrors.emit(result.errors);
|
|
616
|
-
// Log validation errors with context
|
|
617
|
-
const configSnippet = JSON.stringify(config, null, 2).substring(0, 500); // First 500 chars of config
|
|
618
|
-
this.logger.logValidationErrors(result.errors, 'renderer', {
|
|
619
|
-
configSnippet: configSnippet
|
|
620
|
-
});
|
|
621
|
-
// Log warnings to console (don't break rendering)
|
|
622
|
-
console.warn('Smart Table: Configuration validation errors detected:', result.errors);
|
|
623
|
-
result.errors.forEach(error => {
|
|
624
|
-
console.warn(` - ${error.field || error.path}: ${error.message}`);
|
|
625
|
-
});
|
|
626
|
-
}
|
|
627
|
-
}
|
|
628
|
-
/**
|
|
629
|
-
* Handle add column button click
|
|
630
|
-
*/
|
|
631
|
-
onAddColumnClick() {
|
|
632
|
-
this.showColumnModal = true;
|
|
633
|
-
}
|
|
634
|
-
/**
|
|
635
|
-
* Handle column created from modal
|
|
636
|
-
*/
|
|
637
|
-
onColumnCreated(column) {
|
|
638
|
-
const columns = this.getActiveColumns();
|
|
639
|
-
const addEvent = {
|
|
640
|
-
column: column,
|
|
641
|
-
index: columns.length,
|
|
642
|
-
totalColumns: columns.length + 1
|
|
643
|
-
};
|
|
644
|
-
// Emit the new column to parent component
|
|
645
|
-
this.columnAdded.emit(addEvent);
|
|
646
|
-
// Close the modal
|
|
647
|
-
this.showColumnModal = false;
|
|
648
|
-
}
|
|
649
|
-
/**
|
|
650
|
-
* Handle modal cancelled
|
|
651
|
-
*/
|
|
652
|
-
onModalCancelled() {
|
|
653
|
-
this.showColumnModal = false;
|
|
654
|
-
}
|
|
655
|
-
/**
|
|
656
|
-
* Check if virtual scroll is enabled
|
|
657
|
-
*/
|
|
658
|
-
isVirtualScrollEnabled() {
|
|
659
|
-
return this.mergedConfig.display?.virtualScroll?.enabled ?? false;
|
|
660
|
-
}
|
|
661
|
-
/**
|
|
662
|
-
* Check if column is the first sticky-right column (for shadow styling)
|
|
663
|
-
*/
|
|
664
|
-
isFirstStickyRight(columnKey) {
|
|
665
|
-
const stickyRightColumns = this.visibleColumns.filter(col => col.sticky === 'right' && !col.key.includes('settings'));
|
|
666
|
-
return stickyRightColumns.length > 0 && stickyRightColumns[0].key === columnKey;
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* Get virtual scroll item size
|
|
670
|
-
*/
|
|
671
|
-
getVirtualScrollItemSize() {
|
|
672
|
-
return this.mergedConfig.display?.virtualScroll?.itemSize ?? 48;
|
|
673
|
-
}
|
|
674
|
-
/**
|
|
675
|
-
* Get viewport height
|
|
676
|
-
*/
|
|
677
|
-
getVirtualScrollViewportHeight() {
|
|
678
|
-
return this.mergedConfig.display?.virtualScroll?.viewportHeight ?? 600;
|
|
679
|
-
}
|
|
680
|
-
/**
|
|
681
|
-
* Get buffer size
|
|
682
|
-
*/
|
|
683
|
-
getVirtualScrollBufferSize() {
|
|
684
|
-
return this.mergedConfig.display?.virtualScroll?.bufferSize ?? 5;
|
|
685
|
-
}
|
|
686
|
-
/**
|
|
687
|
-
* Initialize virtual scroll state
|
|
688
|
-
*/
|
|
689
|
-
initializeVirtualScroll() {
|
|
690
|
-
const newState = this.virtualScrollService.calculateVisibleRange({
|
|
691
|
-
scrollTop: 0,
|
|
692
|
-
viewportHeight: this.getVirtualScrollViewportHeight(),
|
|
693
|
-
totalItems: this.visibleCellGrid.length,
|
|
694
|
-
itemSize: this.getVirtualScrollItemSize(),
|
|
695
|
-
bufferSize: this.getVirtualScrollBufferSize()
|
|
696
|
-
});
|
|
697
|
-
this.virtualScrollState$.next(newState);
|
|
698
|
-
}
|
|
699
|
-
/**
|
|
700
|
-
* Setup scroll event listener
|
|
701
|
-
*/
|
|
702
|
-
setupVirtualScrollListener() {
|
|
703
|
-
if (!this.scrollViewport)
|
|
704
|
-
return;
|
|
705
|
-
const element = this.scrollViewport.nativeElement;
|
|
706
|
-
this.scrollContainer = element;
|
|
707
|
-
this.scrollSubscription = this.virtualScrollService
|
|
708
|
-
.createScrollObservable(element)
|
|
709
|
-
.subscribe(scrollTop => this.onVirtualScroll(scrollTop));
|
|
710
|
-
}
|
|
711
|
-
/**
|
|
712
|
-
* Handle virtual scroll event
|
|
713
|
-
*/
|
|
714
|
-
onVirtualScroll(scrollTop) {
|
|
715
|
-
const newState = this.virtualScrollService.calculateVisibleRange({
|
|
716
|
-
scrollTop,
|
|
717
|
-
viewportHeight: this.getVirtualScrollViewportHeight(),
|
|
718
|
-
totalItems: this.visibleCellGrid.length,
|
|
719
|
-
itemSize: this.getVirtualScrollItemSize(),
|
|
720
|
-
bufferSize: this.getVirtualScrollBufferSize()
|
|
721
|
-
});
|
|
722
|
-
this.virtualScrollState$.next(newState);
|
|
723
|
-
}
|
|
724
|
-
/**
|
|
725
|
-
* Get row index for tracking
|
|
726
|
-
*/
|
|
727
|
-
getAbsoluteRowIndex(relativeIndex) {
|
|
728
|
-
const currentState = this.virtualScrollState$.value;
|
|
729
|
-
if (!currentState)
|
|
730
|
-
return relativeIndex;
|
|
731
|
-
return currentState.startIndex + relativeIndex;
|
|
732
|
-
}
|
|
733
|
-
/**
|
|
734
|
-
* Scroll to specific row programmatically
|
|
735
|
-
*/
|
|
736
|
-
scrollToRow(index) {
|
|
737
|
-
if (!this.scrollContainer || !this.isVirtualScrollEnabled())
|
|
738
|
-
return;
|
|
739
|
-
const scrollTop = index * this.getVirtualScrollItemSize();
|
|
740
|
-
this.scrollContainer.scrollTop = scrollTop;
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* Check if row actions are enabled
|
|
744
|
-
*/
|
|
745
|
-
hasRowActions() {
|
|
746
|
-
return !!(this.mergedConfig.features?.rowManagement?.actions &&
|
|
747
|
-
this.mergedConfig.features.rowManagement.actions.length > 0);
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
* Get row actions from config
|
|
751
|
-
*/
|
|
752
|
-
getRowActions() {
|
|
753
|
-
return this.mergedConfig.features?.rowManagement?.actions || [];
|
|
754
|
-
}
|
|
755
|
-
/**
|
|
756
|
-
* Get row data from cell grid
|
|
757
|
-
*/
|
|
758
|
-
getRowData(rowIndex) {
|
|
759
|
-
const cellGrid = this.getActiveCellGrid();
|
|
760
|
-
if (!cellGrid || rowIndex < 0 || rowIndex >= cellGrid.length) {
|
|
761
|
-
return null;
|
|
762
|
-
}
|
|
763
|
-
const row = cellGrid[rowIndex];
|
|
764
|
-
if (!row || row.length === 0) {
|
|
765
|
-
return null;
|
|
766
|
-
}
|
|
767
|
-
// Get raw data from first cell (all cells in a row share the same rowData)
|
|
768
|
-
return row[0]?.getRowData() || null;
|
|
769
|
-
}
|
|
770
|
-
/**
|
|
771
|
-
* Open row actions dropdown
|
|
772
|
-
*/
|
|
773
|
-
openRowActionsDropdown(event, rowData, rowIndex) {
|
|
774
|
-
event.preventDefault();
|
|
775
|
-
event.stopPropagation();
|
|
776
|
-
const target = event.currentTarget;
|
|
777
|
-
const rect = target.getBoundingClientRect();
|
|
778
|
-
// Calculate position (below the button by default)
|
|
779
|
-
const position = {
|
|
780
|
-
x: rect.left,
|
|
781
|
-
y: rect.bottom + 4 // 4px gap
|
|
782
|
-
};
|
|
783
|
-
// Create context
|
|
784
|
-
const context = {
|
|
785
|
-
rowData,
|
|
786
|
-
rowIndex,
|
|
787
|
-
actions: this.getRowActions()
|
|
788
|
-
};
|
|
789
|
-
// Update dropdown state
|
|
790
|
-
this.dropdownState = {
|
|
791
|
-
isOpen: true,
|
|
792
|
-
position,
|
|
793
|
-
context
|
|
794
|
-
};
|
|
795
|
-
// Disable body scroll
|
|
796
|
-
document.body.style.overflow = 'hidden';
|
|
797
|
-
// If virtual scroll is enabled, add scroll listener to close dropdown
|
|
798
|
-
if (this.isVirtualScrollEnabled() && this.scrollContainer) {
|
|
799
|
-
const scrollListener = () => {
|
|
800
|
-
this.closeRowActionsDropdown();
|
|
801
|
-
this.scrollContainer?.removeEventListener('scroll', scrollListener);
|
|
802
|
-
};
|
|
803
|
-
this.scrollContainer.addEventListener('scroll', scrollListener, { once: true });
|
|
804
|
-
}
|
|
805
|
-
}
|
|
806
|
-
/**
|
|
807
|
-
* Close row actions dropdown
|
|
808
|
-
*/
|
|
809
|
-
closeRowActionsDropdown() {
|
|
810
|
-
this.dropdownState = {
|
|
811
|
-
isOpen: false,
|
|
812
|
-
position: { x: 0, y: 0 },
|
|
813
|
-
context: null
|
|
814
|
-
};
|
|
815
|
-
// Re-enable body scroll
|
|
816
|
-
document.body.style.overflow = '';
|
|
817
|
-
}
|
|
818
|
-
/**
|
|
819
|
-
* Handle row action clicked
|
|
820
|
-
*/
|
|
821
|
-
onRowActionClicked(event) {
|
|
822
|
-
// Execute action callback if provided
|
|
823
|
-
if (event.action.action) {
|
|
824
|
-
event.action.action(event.rowData, event.rowIndex);
|
|
825
|
-
}
|
|
826
|
-
// Emit event to parent
|
|
827
|
-
this.rowAction.emit(event);
|
|
828
|
-
// Close dropdown
|
|
829
|
-
this.closeRowActionsDropdown();
|
|
830
|
-
}
|
|
831
|
-
// ============================================================================
|
|
832
|
-
// COLUMN MENU ACTIONS
|
|
833
|
-
// ============================================================================
|
|
834
|
-
/**
|
|
835
|
-
* Open column menu dropdown
|
|
836
|
-
*/
|
|
837
|
-
openColumnMenu(event, column, columnIndex, isFirst, isLast) {
|
|
838
|
-
event.preventDefault();
|
|
839
|
-
event.stopPropagation();
|
|
840
|
-
const target = event.currentTarget;
|
|
841
|
-
const rect = target.getBoundingClientRect();
|
|
842
|
-
// Calculate position (below the button by default)
|
|
843
|
-
const position = {
|
|
844
|
-
x: rect.left,
|
|
845
|
-
y: rect.bottom + 4 // 4px gap
|
|
846
|
-
};
|
|
847
|
-
// Create context
|
|
848
|
-
const context = {
|
|
849
|
-
column,
|
|
850
|
-
columnIndex,
|
|
851
|
-
isFirstColumn: isFirst,
|
|
852
|
-
isLastColumn: isLast,
|
|
853
|
-
tableState: this.getActiveTableState(),
|
|
854
|
-
actions: this.getColumnActions(column, columnIndex, isFirst, isLast)
|
|
855
|
-
};
|
|
856
|
-
// Update column menu state
|
|
857
|
-
this.columnMenuState = {
|
|
858
|
-
isOpen: true,
|
|
859
|
-
position,
|
|
860
|
-
context
|
|
861
|
-
};
|
|
862
|
-
// Disable body scroll
|
|
863
|
-
document.body.style.overflow = 'hidden';
|
|
864
|
-
// If virtual scroll is enabled, add scroll listener to close dropdown
|
|
865
|
-
if (this.isVirtualScrollEnabled() && this.scrollContainer) {
|
|
866
|
-
const scrollListener = () => {
|
|
867
|
-
this.closeColumnMenu();
|
|
868
|
-
this.scrollContainer?.removeEventListener('scroll', scrollListener);
|
|
869
|
-
};
|
|
870
|
-
this.scrollContainer.addEventListener('scroll', scrollListener, { once: true });
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
/**
|
|
874
|
-
* Close column menu dropdown
|
|
875
|
-
*/
|
|
876
|
-
closeColumnMenu() {
|
|
877
|
-
this.columnMenuState = {
|
|
878
|
-
isOpen: false,
|
|
879
|
-
position: { x: 0, y: 0 },
|
|
880
|
-
context: null
|
|
881
|
-
};
|
|
882
|
-
// Re-enable body scroll
|
|
883
|
-
document.body.style.overflow = '';
|
|
884
|
-
}
|
|
885
|
-
/**
|
|
886
|
-
* Handle column action clicked
|
|
887
|
-
*/
|
|
888
|
-
onColumnActionClicked(event) {
|
|
889
|
-
// Execute action callback if provided
|
|
890
|
-
if (event.action.action) {
|
|
891
|
-
event.action.action(event.column, event.columnIndex);
|
|
892
|
-
}
|
|
893
|
-
// Don't close menu if it's a filter action (filter needs menu to stay open)
|
|
894
|
-
if (event.action.id === 'filter') {
|
|
895
|
-
return;
|
|
896
|
-
}
|
|
897
|
-
// Close dropdown for other actions
|
|
898
|
-
this.closeColumnMenu();
|
|
899
|
-
}
|
|
900
|
-
/**
|
|
901
|
-
* Get column actions (built-in + custom)
|
|
902
|
-
*/
|
|
903
|
-
getColumnActions(column, columnIndex, isFirst, isLast) {
|
|
904
|
-
const actions = [];
|
|
905
|
-
// Add built-in actions if enabled (default: true)
|
|
906
|
-
const includeBuiltIn = column.includeBuiltInActions ?? true;
|
|
907
|
-
if (includeBuiltIn) {
|
|
908
|
-
actions.push(...this.getBuiltInColumnActions(column, columnIndex, isFirst, isLast));
|
|
909
|
-
}
|
|
910
|
-
// Add custom column actions from config
|
|
911
|
-
if (column.columnActions && column.columnActions.length > 0) {
|
|
912
|
-
actions.push(...column.columnActions);
|
|
913
|
-
}
|
|
914
|
-
return actions;
|
|
915
|
-
}
|
|
916
|
-
/**
|
|
917
|
-
* Get built-in column actions (sort, filter, pin, move)
|
|
918
|
-
*/
|
|
919
|
-
getBuiltInColumnActions(column, columnIndex, isFirst, isLast) {
|
|
920
|
-
const tableState = this.getActiveTableState();
|
|
921
|
-
const actions = [];
|
|
922
|
-
// Sort ascending
|
|
923
|
-
if (column.sortable !== false) {
|
|
924
|
-
actions.push({
|
|
925
|
-
id: 'sort-asc',
|
|
926
|
-
label: this.getSortLabel(column, 'asc'),
|
|
927
|
-
icon: '↑',
|
|
928
|
-
action: (col) => {
|
|
929
|
-
tableState.addSortToColumn(col.key, SortDirection.ASC);
|
|
930
|
-
}
|
|
931
|
-
});
|
|
932
|
-
}
|
|
933
|
-
// Sort descending
|
|
934
|
-
if (column.sortable !== false) {
|
|
935
|
-
actions.push({
|
|
936
|
-
id: 'sort-desc',
|
|
937
|
-
label: this.getSortLabel(column, 'desc'),
|
|
938
|
-
icon: '↓',
|
|
939
|
-
action: (col) => {
|
|
940
|
-
tableState.addSortToColumn(col.key, SortDirection.DESC);
|
|
941
|
-
}
|
|
942
|
-
});
|
|
943
|
-
}
|
|
944
|
-
// Clear sort (only show if currently sorted)
|
|
945
|
-
if (column.sortable !== false && column.sortDirection && column.sortDirection !== SortDirection.NONE) {
|
|
946
|
-
actions.push({
|
|
947
|
-
id: 'clear-sort',
|
|
948
|
-
label: 'Clear Sort',
|
|
949
|
-
icon: '✕',
|
|
950
|
-
action: (col) => {
|
|
951
|
-
tableState.addSortToColumn(col.key, SortDirection.NONE);
|
|
952
|
-
}
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
// Filter
|
|
956
|
-
if (column.filterable !== false) {
|
|
957
|
-
actions.push({
|
|
958
|
-
id: 'filter',
|
|
959
|
-
label: 'Filter',
|
|
960
|
-
icon: '⚑',
|
|
961
|
-
action: () => {
|
|
962
|
-
// Filter action handled by column menu component
|
|
963
|
-
}
|
|
964
|
-
});
|
|
965
|
-
}
|
|
966
|
-
// Pin Left (if not already pinned)
|
|
967
|
-
if (column.pinnable !== false && column.sticky !== 'left' && column.sticky !== 'right') {
|
|
968
|
-
actions.push({
|
|
969
|
-
id: 'pin-left',
|
|
970
|
-
label: 'Pin Left',
|
|
971
|
-
icon: '📌',
|
|
972
|
-
action: (col) => {
|
|
973
|
-
tableState.setStickyColumn(col.key, 'left');
|
|
974
|
-
}
|
|
975
|
-
});
|
|
976
|
-
}
|
|
977
|
-
// Pin Right (if not already pinned)
|
|
978
|
-
if (column.pinnable !== false && column.sticky !== 'left' && column.sticky !== 'right') {
|
|
979
|
-
actions.push({
|
|
980
|
-
id: 'pin-right',
|
|
981
|
-
label: 'Pin Right',
|
|
982
|
-
icon: '📌',
|
|
983
|
-
action: (col) => {
|
|
984
|
-
this.moveColumnToEnd(col.key);
|
|
985
|
-
tableState.setStickyColumn(col.key, 'right');
|
|
986
|
-
}
|
|
987
|
-
});
|
|
988
|
-
}
|
|
989
|
-
// Unpin (if currently pinned)
|
|
990
|
-
if (column.pinnable !== false && (column.sticky === 'left' || column.sticky === 'right')) {
|
|
991
|
-
actions.push({
|
|
992
|
-
id: 'unpin',
|
|
993
|
-
label: 'Unpin',
|
|
994
|
-
icon: '📍',
|
|
995
|
-
action: (col) => {
|
|
996
|
-
tableState.setStickyColumn(col.key, false);
|
|
997
|
-
}
|
|
998
|
-
});
|
|
999
|
-
}
|
|
1000
|
-
// Move left (only if movable and not pinned)
|
|
1001
|
-
if (!isFirst && column.movable !== false && !column.sticky) {
|
|
1002
|
-
actions.push({
|
|
1003
|
-
id: 'move-left',
|
|
1004
|
-
label: 'Move Left',
|
|
1005
|
-
icon: '←',
|
|
1006
|
-
action: (col) => {
|
|
1007
|
-
this.onColumnMoved({
|
|
1008
|
-
columnKey: col.key,
|
|
1009
|
-
direction: 'left'
|
|
1010
|
-
});
|
|
1011
|
-
}
|
|
1012
|
-
});
|
|
1013
|
-
}
|
|
1014
|
-
// Move right (only if movable and not pinned)
|
|
1015
|
-
if (!isLast && column.movable !== false && !column.sticky) {
|
|
1016
|
-
actions.push({
|
|
1017
|
-
id: 'move-right',
|
|
1018
|
-
label: 'Move Right',
|
|
1019
|
-
icon: '→',
|
|
1020
|
-
action: (col) => {
|
|
1021
|
-
this.onColumnMoved({
|
|
1022
|
-
columnKey: col.key,
|
|
1023
|
-
direction: 'right'
|
|
1024
|
-
});
|
|
1025
|
-
}
|
|
1026
|
-
});
|
|
1027
|
-
}
|
|
1028
|
-
return actions;
|
|
1029
|
-
}
|
|
1030
|
-
/**
|
|
1031
|
-
* Get sort label based on column data type
|
|
1032
|
-
*/
|
|
1033
|
-
getSortLabel(column, direction) {
|
|
1034
|
-
const dataType = column.dataType;
|
|
1035
|
-
if (dataType === 'number') {
|
|
1036
|
-
return direction === 'asc' ? 'Sort 0→9' : 'Sort 9→0';
|
|
1037
|
-
}
|
|
1038
|
-
else if (dataType === 'date') {
|
|
1039
|
-
return direction === 'asc' ? 'Sort Oldest First' : 'Sort Newest First';
|
|
1040
|
-
}
|
|
1041
|
-
else {
|
|
1042
|
-
return direction === 'asc' ? 'Sort A→Z' : 'Sort Z→A';
|
|
1043
|
-
}
|
|
1044
|
-
}
|
|
1045
|
-
// ============================================================================
|
|
1046
|
-
// KEYBOARD NAVIGATION
|
|
1047
|
-
// ============================================================================
|
|
1048
|
-
/**
|
|
1049
|
-
* Initialize keyboard navigation
|
|
1050
|
-
*/
|
|
1051
|
-
initializeKeyboardNavigation() {
|
|
1052
|
-
const tableState = this.getActiveTableState();
|
|
1053
|
-
tableState.setDimensions(this.visibleCellGrid.length, this.visibleColumns.length);
|
|
1054
|
-
// Subscribe to focus position changes
|
|
1055
|
-
this.focusSubscription = tableState.focusedCellPosition$.subscribe(position => {
|
|
1056
|
-
this.updateCellFocusStates(position);
|
|
1057
|
-
});
|
|
1058
|
-
// Subscribe to request add row events (when navigating past last row)
|
|
1059
|
-
this.requestAddRowSubscription = tableState.requestAddRow$.subscribe(event => {
|
|
1060
|
-
this.requestAddRow.emit(event);
|
|
1061
|
-
});
|
|
1062
|
-
// Auto-focus first cell to enable keyboard navigation
|
|
1063
|
-
if (this.visibleCellGrid.length > 0 && this.visibleColumns.length > 0) {
|
|
1064
|
-
setTimeout(() => {
|
|
1065
|
-
tableState.focusCell(0, 0);
|
|
1066
|
-
}, 0);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
/**
|
|
1070
|
-
* Update focus state in all cells
|
|
1071
|
-
*/
|
|
1072
|
-
updateCellFocusStates(position) {
|
|
1073
|
-
if (!this.visibleCellGrid)
|
|
1074
|
-
return;
|
|
1075
|
-
for (let rowIndex = 0; rowIndex < this.visibleCellGrid.length; rowIndex++) {
|
|
1076
|
-
const row = this.visibleCellGrid[rowIndex];
|
|
1077
|
-
for (let colIndex = 0; colIndex < row.length; colIndex++) {
|
|
1078
|
-
const cell = row[colIndex];
|
|
1079
|
-
if (!cell)
|
|
1080
|
-
continue;
|
|
1081
|
-
const shouldFocus = position &&
|
|
1082
|
-
position.rowIndex === rowIndex &&
|
|
1083
|
-
position.columnIndex === colIndex;
|
|
1084
|
-
if (shouldFocus) {
|
|
1085
|
-
cell.focus();
|
|
1086
|
-
// Focus the actual DOM element
|
|
1087
|
-
this.focusTdElement(rowIndex, colIndex);
|
|
1088
|
-
}
|
|
1089
|
-
else {
|
|
1090
|
-
cell.blur();
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
* Focus the TD element in the DOM and scroll it into view,
|
|
1097
|
-
* accounting for sticky columns on left and right
|
|
1098
|
-
*/
|
|
1099
|
-
focusTdElement(rowIndex, colIndex) {
|
|
1100
|
-
// Use setTimeout to ensure DOM has updated
|
|
1101
|
-
setTimeout(() => {
|
|
1102
|
-
// Don't steal focus from editors - if a cell is being edited,
|
|
1103
|
-
// the editor should keep focus
|
|
1104
|
-
const editingPosition = this.getActiveTableState().getEditingPosition();
|
|
1105
|
-
if (editingPosition &&
|
|
1106
|
-
editingPosition.rowIndex === rowIndex &&
|
|
1107
|
-
editingPosition.columnIndex === colIndex) {
|
|
1108
|
-
// Cell is being edited, don't steal focus from the editor
|
|
1109
|
-
return;
|
|
1110
|
-
}
|
|
1111
|
-
// Use absolute row index for virtual scroll compatibility
|
|
1112
|
-
const absoluteRowIndex = this.getAbsoluteRowIndex(rowIndex);
|
|
1113
|
-
// Query within this component's host element to avoid selecting rows from other tables
|
|
1114
|
-
const hostElement = this.elementRef?.nativeElement;
|
|
1115
|
-
if (!hostElement)
|
|
1116
|
-
return;
|
|
1117
|
-
// First, ensure the table container has focus for keyboard navigation
|
|
1118
|
-
// The keyboard navigation directive listens on the .st-table container
|
|
1119
|
-
const tableContainer = hostElement.querySelector('.st-table');
|
|
1120
|
-
if (tableContainer && typeof tableContainer.focus === 'function') {
|
|
1121
|
-
tableContainer.focus({ preventScroll: true });
|
|
1122
|
-
}
|
|
1123
|
-
const tr = hostElement.querySelector(`tr[data-row-index="${absoluteRowIndex}"]`);
|
|
1124
|
-
if (tr) {
|
|
1125
|
-
const cells = tr.querySelectorAll('td:not(.settings-column):not(.row-number-cell)');
|
|
1126
|
-
const targetCell = cells[colIndex];
|
|
1127
|
-
if (targetCell && typeof targetCell.focus === 'function') {
|
|
1128
|
-
targetCell.focus({ preventScroll: true });
|
|
1129
|
-
this.scrollCellIntoView(targetCell, colIndex);
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
}, 0);
|
|
1133
|
-
}
|
|
1134
|
-
/**
|
|
1135
|
-
* Scroll a cell into view, accounting for sticky columns
|
|
1136
|
-
*/
|
|
1137
|
-
scrollCellIntoView(cell, colIndex) {
|
|
1138
|
-
// Find the scroll container
|
|
1139
|
-
const scrollContainer = this.getScrollContainerElement();
|
|
1140
|
-
if (!scrollContainer)
|
|
1141
|
-
return;
|
|
1142
|
-
const cellRect = cell.getBoundingClientRect();
|
|
1143
|
-
const containerRect = scrollContainer.getBoundingClientRect();
|
|
1144
|
-
// Calculate sticky column widths
|
|
1145
|
-
const { leftStickyWidth, rightStickyWidth } = this.calculateStickyWidths();
|
|
1146
|
-
// Calculate visible area (excluding sticky columns)
|
|
1147
|
-
const visibleLeft = containerRect.left + leftStickyWidth;
|
|
1148
|
-
const visibleRight = containerRect.right - rightStickyWidth;
|
|
1149
|
-
const visibleTop = containerRect.top;
|
|
1150
|
-
const visibleBottom = containerRect.bottom;
|
|
1151
|
-
// Check if column is sticky (don't scroll for sticky columns)
|
|
1152
|
-
const column = this.visibleColumns[colIndex];
|
|
1153
|
-
if (column?.sticky) {
|
|
1154
|
-
// Just ensure vertical visibility for sticky columns
|
|
1155
|
-
if (cellRect.top < visibleTop) {
|
|
1156
|
-
scrollContainer.scrollTop -= (visibleTop - cellRect.top);
|
|
1157
|
-
}
|
|
1158
|
-
else if (cellRect.bottom > visibleBottom) {
|
|
1159
|
-
scrollContainer.scrollTop += (cellRect.bottom - visibleBottom);
|
|
1160
|
-
}
|
|
1161
|
-
return;
|
|
1162
|
-
}
|
|
1163
|
-
// Check if cell is already fully visible horizontally (no scroll needed)
|
|
1164
|
-
const isCellFullyVisibleHorizontally = cellRect.left >= visibleLeft && cellRect.right <= visibleRight;
|
|
1165
|
-
// Only scroll horizontally if cell is NOT fully visible
|
|
1166
|
-
if (!isCellFullyVisibleHorizontally) {
|
|
1167
|
-
if (cellRect.left < visibleLeft) {
|
|
1168
|
-
// Cell is hidden behind left sticky columns
|
|
1169
|
-
scrollContainer.scrollLeft -= (visibleLeft - cellRect.left);
|
|
1170
|
-
}
|
|
1171
|
-
else if (cellRect.right > visibleRight) {
|
|
1172
|
-
// Cell is hidden behind right sticky columns
|
|
1173
|
-
scrollContainer.scrollLeft += (cellRect.right - visibleRight);
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
// Vertical scrolling
|
|
1177
|
-
if (cellRect.top < visibleTop) {
|
|
1178
|
-
scrollContainer.scrollTop -= (visibleTop - cellRect.top);
|
|
1179
|
-
}
|
|
1180
|
-
else if (cellRect.bottom > visibleBottom) {
|
|
1181
|
-
scrollContainer.scrollTop += (cellRect.bottom - visibleBottom);
|
|
1182
|
-
}
|
|
1183
|
-
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Scroll to a specific row by index and optionally focus it
|
|
1186
|
-
* @param rowIndex - The index of the row to scroll to
|
|
1187
|
-
* @param focusFirstCell - Whether to focus the first editable cell (default: false)
|
|
1188
|
-
*/
|
|
1189
|
-
scrollToRowAndFocus(rowIndex, focusFirstCell = false) {
|
|
1190
|
-
setTimeout(() => {
|
|
1191
|
-
const hostElement = this.elementRef?.nativeElement;
|
|
1192
|
-
if (!hostElement)
|
|
1193
|
-
return;
|
|
1194
|
-
// Find the target row
|
|
1195
|
-
const rows = hostElement.querySelectorAll('tbody tr');
|
|
1196
|
-
const targetRow = rows[rowIndex];
|
|
1197
|
-
if (targetRow) {
|
|
1198
|
-
// Scroll the row into view
|
|
1199
|
-
targetRow.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
1200
|
-
// Optionally focus the first editable cell
|
|
1201
|
-
if (focusFirstCell) {
|
|
1202
|
-
const cells = targetRow.querySelectorAll('td:not(.settings-column):not(.row-number-cell)');
|
|
1203
|
-
const firstCell = cells[0];
|
|
1204
|
-
if (firstCell && typeof firstCell.focus === 'function') {
|
|
1205
|
-
setTimeout(() => {
|
|
1206
|
-
firstCell.focus();
|
|
1207
|
-
// Update table state focus position
|
|
1208
|
-
if (this.tableState) {
|
|
1209
|
-
this.tableState.focusCell(rowIndex, 0);
|
|
1210
|
-
}
|
|
1211
|
-
}, 100);
|
|
1212
|
-
}
|
|
1213
|
-
}
|
|
1214
|
-
}
|
|
1215
|
-
}, 0);
|
|
1216
|
-
}
|
|
1217
|
-
/**
|
|
1218
|
-
* Scroll to the last row in the table
|
|
1219
|
-
* @param focusFirstCell - Whether to focus the first editable cell (default: true)
|
|
1220
|
-
*/
|
|
1221
|
-
scrollToLastRow(focusFirstCell = true) {
|
|
1222
|
-
const rowCount = this.data?.length || 0;
|
|
1223
|
-
if (rowCount > 0) {
|
|
1224
|
-
this.scrollToRowAndFocus(rowCount - 1, focusFirstCell);
|
|
1225
|
-
}
|
|
1226
|
-
}
|
|
1227
|
-
/**
|
|
1228
|
-
* Get the scroll container element
|
|
1229
|
-
*/
|
|
1230
|
-
getScrollContainerElement() {
|
|
1231
|
-
// Prefer cached container if already resolved
|
|
1232
|
-
if (this.scrollContainer) {
|
|
1233
|
-
return this.scrollContainer;
|
|
1234
|
-
}
|
|
1235
|
-
// Virtual scroll uses scrollViewport
|
|
1236
|
-
if (this.isVirtualScrollEnabled() && this.scrollViewport?.nativeElement) {
|
|
1237
|
-
this.scrollContainer = this.scrollViewport.nativeElement;
|
|
1238
|
-
return this.scrollContainer;
|
|
1239
|
-
}
|
|
1240
|
-
// Standard mode uses .st-table container within THIS component's host element
|
|
1241
|
-
// Use elementRef to query within the component instead of document.querySelector
|
|
1242
|
-
// which would return the first table on the page
|
|
1243
|
-
const hostElement = this.elementRef?.nativeElement;
|
|
1244
|
-
if (hostElement) {
|
|
1245
|
-
const tableContainer = hostElement.querySelector('.st-table');
|
|
1246
|
-
if (tableContainer) {
|
|
1247
|
-
this.scrollContainer = tableContainer;
|
|
1248
|
-
}
|
|
1249
|
-
}
|
|
1250
|
-
return this.scrollContainer || null;
|
|
1251
|
-
}
|
|
1252
|
-
/**
|
|
1253
|
-
* Calculate total width of sticky columns on left and right
|
|
1254
|
-
*/
|
|
1255
|
-
calculateStickyWidths() {
|
|
1256
|
-
let leftStickyWidth = 0;
|
|
1257
|
-
let rightStickyWidth = 0;
|
|
1258
|
-
// Account for row number column if enabled
|
|
1259
|
-
if (this.mergedConfig.showRowNumber) {
|
|
1260
|
-
leftStickyWidth += 30; // Row number column width
|
|
1261
|
-
}
|
|
1262
|
-
// Calculate from column configs
|
|
1263
|
-
for (const col of this.visibleColumns) {
|
|
1264
|
-
if (col.sticky === 'left') {
|
|
1265
|
-
leftStickyWidth += col.width || 100;
|
|
1266
|
-
}
|
|
1267
|
-
else if (col.sticky === 'right') {
|
|
1268
|
-
rightStickyWidth += col.width || 100;
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
// Account for settings column only when row actions are enabled (use consistent width)
|
|
1272
|
-
const settingsColumnWidth = this.hasRowActions() ? 32 : 0;
|
|
1273
|
-
rightStickyWidth += settingsColumnWidth;
|
|
1274
|
-
return { leftStickyWidth, rightStickyWidth };
|
|
1275
|
-
}
|
|
1276
|
-
/**
|
|
1277
|
-
* Handle cell click
|
|
1278
|
-
*/
|
|
1279
|
-
onCellClick(rowIndex, columnIndex) {
|
|
1280
|
-
if (!this.isKeyboardNavigationEnabled())
|
|
1281
|
-
return;
|
|
1282
|
-
this.getActiveTableState().focusCell(rowIndex, columnIndex);
|
|
1283
|
-
}
|
|
1284
|
-
/**
|
|
1285
|
-
* Handle cell entering edit mode
|
|
1286
|
-
*/
|
|
1287
|
-
onCellEdit(event) {
|
|
1288
|
-
this.cellEdit.emit(event);
|
|
1289
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
1290
|
-
const rowIndex = event.cell.getRowIndex();
|
|
1291
|
-
const columnKey = event.columnKey;
|
|
1292
|
-
const columnIndex = this.visibleColumns.findIndex(col => col.key === columnKey);
|
|
1293
|
-
if (rowIndex !== undefined && columnIndex >= 0) {
|
|
1294
|
-
this.getActiveTableState().setEditingCell(rowIndex, columnIndex);
|
|
1295
|
-
}
|
|
1296
|
-
}
|
|
1297
|
-
}
|
|
1298
|
-
/**
|
|
1299
|
-
* Handle cell save
|
|
1300
|
-
*/
|
|
1301
|
-
onCellSave(event) {
|
|
1302
|
-
this.cellSave.emit(event);
|
|
1303
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
1304
|
-
this.getActiveTableState().clearEditingCell();
|
|
1305
|
-
}
|
|
1306
|
-
}
|
|
1307
|
-
/**
|
|
1308
|
-
* Handle cell cancel
|
|
1309
|
-
*/
|
|
1310
|
-
onCellCancel(event) {
|
|
1311
|
-
this.cellCancel.emit(event);
|
|
1312
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
1313
|
-
this.getActiveTableState().clearEditingCell();
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
/**
|
|
1317
|
-
* Handle cell save with navigation (Excel-like behavior)
|
|
1318
|
-
*/
|
|
1319
|
-
onCellSaveAndNavigate(event) {
|
|
1320
|
-
// Navigation is already handled by the directive after save
|
|
1321
|
-
// Just ensure editing state is cleared
|
|
1322
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
1323
|
-
this.getActiveTableState().clearEditingCell();
|
|
1324
|
-
// Move focus in the specified direction
|
|
1325
|
-
setTimeout(() => {
|
|
1326
|
-
this.getActiveTableState().moveFocus(event.direction);
|
|
1327
|
-
}, 0);
|
|
1328
|
-
}
|
|
1329
|
-
}
|
|
1330
|
-
/**
|
|
1331
|
-
* Handle focus on table container - focus first cell if no cell is focused
|
|
1332
|
-
*/
|
|
1333
|
-
onTableContainerFocus(event) {
|
|
1334
|
-
if (!this.isKeyboardNavigationEnabled())
|
|
1335
|
-
return;
|
|
1336
|
-
const tableState = this.getActiveTableState();
|
|
1337
|
-
const currentFocus = tableState.getFocusedPosition();
|
|
1338
|
-
// If no cell is focused, focus the first cell
|
|
1339
|
-
if (!currentFocus && this.visibleCellGrid.length > 0 && this.visibleColumns.length > 0) {
|
|
1340
|
-
tableState.focusCell(0, 0);
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
/**
|
|
1344
|
-
* Check if keyboard navigation is enabled
|
|
1345
|
-
*/
|
|
1346
|
-
isKeyboardNavigationEnabled() {
|
|
1347
|
-
return this.mergedConfig.features?.keyboardNavigation?.enabled ?? false;
|
|
1348
|
-
}
|
|
1349
|
-
/**
|
|
1350
|
-
* Get EditMode enum value for cells
|
|
1351
|
-
* For Excel-like tables with keyboard navigation, use ENTER mode
|
|
1352
|
-
* which allows arrow key navigation without triggering edit.
|
|
1353
|
-
* Double-click will still work to start editing.
|
|
1354
|
-
*/
|
|
1355
|
-
getEditModeForCells() {
|
|
1356
|
-
// If keyboard navigation is enabled, use ENTER mode for Excel-like behavior
|
|
1357
|
-
// Otherwise use CLICK mode for immediate editing
|
|
1358
|
-
if (this.isKeyboardNavigationEnabled()) {
|
|
1359
|
-
return EditMode.ENTER;
|
|
1360
|
-
}
|
|
1361
|
-
return EditMode.CLICK;
|
|
1362
|
-
}
|
|
1363
|
-
/**
|
|
1364
|
-
* Clear focus when clicking outside table
|
|
1365
|
-
*/
|
|
1366
|
-
onDocumentClick(event) {
|
|
1367
|
-
if (!this.isKeyboardNavigationEnabled())
|
|
1368
|
-
return;
|
|
1369
|
-
const target = event.target;
|
|
1370
|
-
const tableElement = target.closest('.st-table');
|
|
1371
|
-
// Also check if click is inside a portal (e.g., nile-select dropdown)
|
|
1372
|
-
// These are rendered outside the table but are part of the editing experience
|
|
1373
|
-
const portalElement = target.closest('.nile-select-portal-append');
|
|
1374
|
-
// Check composedPath for shadow DOM elements (e.g., nile-option, nile-input inside shadow root)
|
|
1375
|
-
const composedPath = event.composedPath?.() || [];
|
|
1376
|
-
const isInsideNileElement = composedPath.some((el) => {
|
|
1377
|
-
if (el instanceof HTMLElement) {
|
|
1378
|
-
const tagName = el.tagName?.toLowerCase();
|
|
1379
|
-
// Check for any nile-* custom elements used in editors
|
|
1380
|
-
return tagName?.startsWith('nile-') ||
|
|
1381
|
-
el.classList?.contains('nile-select-portal-append');
|
|
1382
|
-
}
|
|
1383
|
-
return false;
|
|
1384
|
-
});
|
|
1385
|
-
if (!tableElement && !portalElement && !isInsideNileElement) {
|
|
1386
|
-
this.getActiveTableState().clearFocus();
|
|
1387
|
-
this.getActiveTableState().clearEditingCell();
|
|
1388
|
-
}
|
|
1389
|
-
}
|
|
1390
|
-
ngOnDestroy() {
|
|
1391
|
-
this.stateSubscription?.unsubscribe();
|
|
1392
|
-
this.scrollSubscription?.unsubscribe();
|
|
1393
|
-
this.focusSubscription?.unsubscribe();
|
|
1394
|
-
this.validationSubscription?.unsubscribe();
|
|
1395
|
-
this.dataSubscription?.unsubscribe();
|
|
1396
|
-
this.requestAddRowSubscription?.unsubscribe();
|
|
1397
|
-
this.virtualScrollState$.complete();
|
|
1398
|
-
this.internalData$.complete();
|
|
1399
|
-
}
|
|
1400
|
-
}
|
|
1401
|
-
StTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StTableComponent, deps: [{ token: i1.JsonSchemaValidatorService }, { token: i2.ValidationLoggerService }, { token: i3.VirtualScrollService }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
1402
|
-
StTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: StTableComponent, selector: "st-table", inputs: { tableConfig: "tableConfig", data: "data", data$: "data$", tableState: "tableState", enableSorting: "enableSorting", enableFiltering: "enableFiltering", validateConfig: "validateConfig" }, outputs: { stateChange: "stateChange", dataChange: "dataChange", cellEdit: "cellEdit", cellSave: "cellSave", cellCancel: "cellCancel", cellChange: "cellChange", columnResized: "columnResized", columnMoved: "columnMoved", configValidationErrors: "configValidationErrors", columnAdded: "columnAdded", rowAction: "rowAction", validationStateChange: "validationStateChange", requestAddRow: "requestAddRow" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "scrollViewport", first: true, predicate: ["scrollViewport"], descendants: true, read: ElementRef }], usesOnChanges: true, ngImport: i0, template: "<!-- Top pagination controls -->\n<st-pagination \n *ngIf=\"showTopPagination() && !(mergedConfig.tableSkeleton?.enabled | async)\" \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n position=\"top\">\n</st-pagination>\n\n<div class=\"st-table\" *ngIf=\"!(mergedConfig.tableSkeleton?.enabled | async)\" \n [ngClass]=\"{\n 'virtual-scroll-enabled': isVirtualScrollEnabled(),\n 'keyboard-navigation-enabled': isKeyboardNavigationEnabled()\n }\"\n [ngStyle]=\"{\n 'max-height.px': !isVirtualScrollEnabled() ? mergedConfig.display?.maxHeight : null\n }\"\n stKeyboardNavigation\n [tableState]=\"getActiveTableState()\"\n [addRowOnNavigatePastEnd]=\"mergedConfig.features?.keyboardNavigation?.addRowOnNavigatePastEnd || false\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? 0 : -1\"\n (focus)=\"onTableContainerFocus($event)\"\n [attr.title]=\"isKeyboardNavigationEnabled() ? 'Click a cell or press Tab to start keyboard navigation' : null\">\n <!-- Unified Table Actions Menu -->\n\n <!-- Virtual scroll viewport wrapper -->\n <div class=\"st-scroll-viewport\" #scrollViewport *ngIf=\"isVirtualScrollEnabled()\"\n [ngStyle]=\"{ 'height.px': getVirtualScrollViewportHeight() }\">\n\n <!-- Spacer to create scrollable area -->\n <div class=\"st-scroll-spacer\" [ngStyle]=\"{ 'height.px': virtualScrollTotalHeight$ | async }\">\n </div>\n\n <!-- Table positioner with transform (instead of tbody) -->\n <div class=\"st-table-positioner\" [ngStyle]=\"{ transform: 'translateY(' + (virtualScrollOffsetY$ | async) + 'px)' }\">\n <!-- Table with only visible rows -->\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'virtual',\n theadStyle: { top: (virtualScrollOffsetYNeg$ | async) + 'px' }\n }\"></ng-container>\n </div>\n </div>\n \n <!-- Standard table (when virtual scroll disabled) -->\n <ng-container *ngIf=\"!isVirtualScrollEnabled()\">\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'standard',\n theadStyle: null\n }\"></ng-container>\n </ng-container>\n\n <!-- Shared Column Menu Dropdown -->\n <st-column-menu-dropdown \n [isOpen]=\"columnMenuState.isOpen\"\n [position]=\"columnMenuState.position\"\n [context]=\"columnMenuState.context\"\n (actionClicked)=\"onColumnActionClicked($event)\"\n (closed)=\"closeColumnMenu()\">\n </st-column-menu-dropdown>\n</div>\n\n<ng-container *ngIf=\"(mergedConfig.tableSkeleton?.enabled | async)\">\n <ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container>\n</ng-container>\n\n<!-- Shared Row Actions Dropdown -->\n<st-row-actions-dropdown [isOpen]=\"dropdownState.isOpen\" [position]=\"dropdownState.position\"\n [context]=\"dropdownState.context\" (actionClicked)=\"onRowActionClicked($event)\" (closed)=\"closeRowActionsDropdown()\">\n</st-row-actions-dropdown>\n\n\n<!-- Bottom pagination controls -->\n<st-pagination \n *ngIf=\"showBottomPagination() && !(mergedConfig.tableSkeleton?.enabled | async)\" \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n position=\"bottom\">\n</st-pagination>\n\n\n <!-- ========================================== -->\n <!-- REUSABLE TABLE TEMPLATE -->\n <!-- ========================================== -->\n <ng-template #tableTemplate let-mode=\"mode\" let-theadStyle=\"theadStyle\">\n <table class=\"st-table-element\">\n <!-- TABLE HEADER -->\n <thead [ngClass]=\"{ 'sticky': mergedConfig.display?.stickyHeader }\" [ngStyle]=\"theadStyle\">\n <tr>\n <!-- Row Number Header -->\n <th *ngIf=\"mergedConfig.showRowNumber\" class=\"row-number-header header-cell sticky-left\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'width.px': 30\n }\">\n #\n </th>\n <!-- Column Headers -->\n <th \n *ngFor=\"let column of visibleColumns; let colIndex = index; let isFirst = first; let isLast = last\"\n [ngClass]=\"{\n 'header-cell': mode === 'standard',\n 'sticky-left': column.sticky === 'left',\n 'sticky-right': column.sticky === 'right',\n 'sticky-right-first': column.sticky === 'right' && isFirstStickyRight(column.key),\n 'resizable': column.resizable !== false\n }\"\n [ngStyle]=\"{\n position: column.sticky ? 'sticky' : null,\n 'left.px': column.sticky === 'left' ? (column.stickyOffset || 0) : null,\n 'right.px': column.sticky === 'right' ? (column.stickyOffset || 0) : null,\n 'z-index': column.sticky ? ZIndex.STICKY_HEADER_CELL : null,\n 'width.px': column.width\n }\">\n \n <st-header \n [column]=\"column\"\n [columnIndex]=\"colIndex\"\n [isFirstColumn]=\"isFirst\"\n [isLastColumn]=\"isLast\"\n [tableState]=\"getActiveTableState()\"\n [enableSorting]=\"mergedConfig.sorting?.enabled ?? enableSorting\"\n [enableFiltering]=\"mergedConfig.filtering?.enabled ?? enableFiltering\"\n (columnMoved)=\"onColumnMoved($event)\"\n (menuClick)=\"openColumnMenu($event, column, colIndex, isFirst, isLast)\">\n </st-header>\n\n <div \n class=\"resize-handle\" \n stColumnResize\n [column]=\"column\"\n (columnResized)=\"onColumnResized($event)\"\n *ngIf=\"column.resizable !== false\">\n </div>\n </th>\n \n <!-- Settings Column Header -->\n <th \n class=\"settings-column sticky-right\"\n [ngClass]=\"{ 'header-cell': mode === 'standard' }\"\n [ngStyle]=\"{ 'z-index': ZIndex.STICKY_HEADER_CELL }\">\n <div [ngClass]=\"{ 'flex-center': mode === 'virtual', 'header-content': mode === 'standard' }\">\n <st-table-actions \n [tableState]=\"getActiveTableState()\"\n [allowAddColumn]=\"mergedConfig.features?.columnManagement?.allowAdd || false\"\n (addColumnClicked)=\"onAddColumnClick()\">\n </st-table-actions>\n </div>\n </th>\n </tr>\n </thead>\n\n <!-- TABLE BODY -->\n <tbody>\n <!-- Virtual Scroll Rows -->\n <ng-container *ngIf=\"mode === 'virtual'\">\n <tr *ngFor=\"let row of visibleRows$ | async; let relativeIndex = index; trackBy: trackByRowIndex\"\n [attr.data-row-index]=\"getAbsoluteRowIndex(relativeIndex)\">\n <!-- Row Number Cell -->\n <td *ngIf=\"mergedConfig.showRowNumber\" class=\"row-number-cell\" \n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n 'width.px': 30,\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null\n }\">\n {{getAbsoluteRowIndex(relativeIndex) + 1}}\n </td>\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: getAbsoluteRowIndex(relativeIndex),\n mode: 'virtual',\n relativeIndex: relativeIndex\n }\"></ng-container>\n </tr>\n </ng-container>\n\n <!-- Standard Rows -->\n <ng-container *ngIf=\"mode === 'standard'\">\n <tr *ngFor=\"let row of visibleCellGrid; let rowIndex = index\" [attr.data-row-index]=\"rowIndex\">\n <!-- Row Number Cell -->\n <td *ngIf=\"mergedConfig.showRowNumber\" class=\"row-number-cell\" \n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n 'width.px': 30,\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null\n }\">\n {{rowIndex + 1}}\n </td>\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: rowIndex,\n mode: 'standard'\n }\"></ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </ng-template>\n\n <!-- ========================================== -->\n <!-- REUSABLE BODY CELL TEMPLATE -->\n <!-- ========================================== -->\n <ng-template #bodyCellTemplate let-row=\"row\" let-rowIndex=\"rowIndex\" let-mode=\"mode\" let-relativeIndex=\"relativeIndex\">\n <!-- Data Cells -->\n <td \n *ngFor=\"let cell of row; let colIndex = index\"\n [ngClass]=\"{\n 'sticky-left': visibleColumns[colIndex]?.sticky === 'left',\n 'sticky-right': visibleColumns[colIndex]?.sticky === 'right',\n 'sticky-right-first': visibleColumns[colIndex]?.sticky === 'right' && visibleColumns[colIndex]?.key && isFirstStickyRight(visibleColumns[colIndex].key),\n 'align-center': visibleColumns[colIndex]?.alignment === 'center',\n 'align-right': visibleColumns[colIndex]?.alignment === 'right',\n 'cell-focused': cell.isFocused()\n }\"\n [ngStyle]=\"{\n position: visibleColumns[colIndex]?.sticky ? 'sticky' : null,\n 'left.px': visibleColumns[colIndex]?.sticky === 'left' ? (visibleColumns[colIndex]?.stickyOffset || 0) : null,\n 'right.px': visibleColumns[colIndex]?.sticky === 'right' ? (visibleColumns[colIndex]?.stickyOffset || 0) : null,\n 'z-index': visibleColumns[colIndex]?.sticky ? ZIndex.STICKY_BODY_CELL : null,\n 'width.px': visibleColumns[colIndex]?.width,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null\n }\"\n (click)=\"isKeyboardNavigationEnabled() ? onCellClick(rowIndex, colIndex) : null\">\n \n <!-- Virtual Scroll Cell -->\n <st-cell \n *ngIf=\"mode === 'virtual'\"\n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\" \n [editMode]=\"getEditModeForCells()\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n [columnIndex]=\"colIndex\"\n (cellEdit)=\"onCellEdit($event)\" \n (cellSave)=\"onCellSave($event)\"\n (cellSaveAndNavigate)=\"onCellSaveAndNavigate($event)\" \n (cellCancel)=\"onCellCancel($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n\n <!-- Standard Cell -->\n <st-cell \n *ngIf=\"mode === 'standard'\"\n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n [columnIndex]=\"colIndex\"\n (cellSave)=\"onCellSave($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n </td>\n \n <!-- Row Actions Cell -->\n <td class=\"settings-column\"\n [ngClass]=\"{\n 'has-actions': hasRowActions()\n }\"\n [ngStyle]=\"{\n position: hasRowActions() ? 'sticky' : null,\n 'right.px': hasRowActions() ? 0 : null,\n 'z-index': hasRowActions() ? ZIndex.STICKY_BODY_CELL : null\n }\">\n <button \n *ngIf=\"hasRowActions()\"\n class=\"settings-trigger\"\n (click)=\"openRowActionsDropdown($event, getRowData(rowIndex), rowIndex)\"\n type=\"button\" \n aria-label=\"Row actions\">\n \u22EF\n </button>\n </td>\n </ng-template>\n\n<ng-template #skeletonLoader>\n <div class=\"list-row\" *ngIf=\"(mergedConfig.tableSkeleton?.enabled | async)\">\n <div *ngFor=\"let i of skeletonColumns\" class=\"list-content\">\n <nile-skeleton-loader variant=\"text\" width=\"90%\" height=\"18\" *ngFor=\"let j of skeletonRows\"></nile-skeleton-loader>\n </div>\n </div>\n</ng-template>", styles: [".st-table{width:100%;overflow:auto;position:relative;height:100%;max-height:30rem;border-radius:4px;border:1px solid #E6E9EB}.st-table st-table-actions{position:sticky;right:0}.st-table.keyboard-navigation-enabled{cursor:pointer}.st-table.keyboard-navigation-enabled:focus{outline:none;box-shadow:0 0 0 2px #3b82f64d}.st-table.keyboard-navigation-enabled td.cell-focused{outline:2px solid #4299e1;outline-offset:-1px;position:relative;box-shadow:0 0 0 3px #3182ce1a}.st-table.keyboard-navigation-enabled td.cell-focused:focus{outline:2px solid #4299e1;outline-offset:-1px;box-shadow:0 0 0 3px #3182ce1a}.st-table.keyboard-navigation-enabled td.cell-focused:has(.st-cell.editing){box-shadow:0 0 0 4px #2563eb26}.st-table.virtual-scroll-enabled{overflow-x:visible;margin:0;border:1px solid #E6E9EB;border-collapse:separate;border-spacing:0}.st-table.virtual-scroll-enabled .st-scroll-viewport{position:relative;overflow-y:auto;overflow-x:auto;scroll-behavior:smooth}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-scroll-spacer{position:absolute;top:0;left:0;width:1px;pointer-events:none;z-index:-1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-positioner{position:absolute;top:0;left:0;right:0;will-change:transform}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element{position:relative;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;border:none;background-color:#fff;will-change:top;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:600;font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,.08) 0%,rgba(0,0,0,0) 100%)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.08) 100%)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr{border-bottom:1px solid #E6E9EB;transition:background-color .15s;height:2rem;box-sizing:border-box}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:last-child{border-bottom:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td{padding:0;vertical-align:middle;box-sizing:border-box;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-center{text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-right{text-align:right}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column{width:2rem;text-align:center;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger:focus{outline:2px solid #4299e1;outline-offset:2px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,.08) 0%,rgba(0,0,0,0) 100%)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.08) 100%)}.st-table:not(.virtual-scroll-enabled) .st-table-element{width:100%;height:100%;overflow:auto;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table:not(.virtual-scroll-enabled) .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:600;font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr{height:2rem;box-sizing:border-box}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:last-child{border-bottom:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td{padding:0;vertical-align:middle;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-center{text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-right{text-align:right}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column{position:sticky;right:0;width:2rem;text-align:center;border-right:none;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content{display:flex;height:2rem;align-items:center}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content .table-header-text{flex-grow:1;padding-left:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element .settings-column>.header-content{display:flex;align-items:center;justify-content:center}.flex-center{display:flex;align-items:center;justify-content:center}.list-row{padding:1rem}.list-row .list-content{display:flex;justify-content:space-evenly;gap:4px;margin-bottom:1rem}\n"], components: [{ type: i4.StPaginationComponent, selector: "st-pagination", inputs: ["tableState", "tableConfig", "position"] }, { type: i5.StColumnMenuDropdownComponent, selector: "st-column-menu-dropdown", inputs: ["isOpen", "position", "context"], outputs: ["actionClicked", "closed"] }, { type: i6.StRowActionsDropdownComponent, selector: "st-row-actions-dropdown", inputs: ["isOpen", "position", "context"], outputs: ["actionClicked", "closed"] }, { type: i7.StHeaderComponent, selector: "st-header", inputs: ["column", "columnIndex", "isFirstColumn", "isLastColumn", "tableState", "enableSorting", "enableFiltering"], outputs: ["sortToggle", "filterChange", "columnMoved", "menuClick"] }, { type: i8.StTableActionsComponent, selector: "st-table-actions", inputs: ["tableState", "allowAddColumn"], outputs: ["addColumnClicked"] }, { type: i9.StCellComponent, selector: "st-cell", inputs: ["cell", "editMode", "tableState", "tableConfig", "columnIndex"], outputs: ["cellChange", "cellEdit", "cellSave", "cellCancel", "cellSaveAndNavigate"] }], directives: [{ type: i10.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i11.StKeyboardNavigationDirective, selector: "[stKeyboardNavigation]", inputs: ["tableState", "addRowOnNavigatePastEnd"] }, { type: i10.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { type: i10.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i10.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet"] }, { type: i10.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i12.StColumnResizeDirective, selector: "[stColumnResize]", inputs: ["column"], outputs: ["columnResized"] }], pipes: { "async": i10.AsyncPipe } });
|
|
1403
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: StTableComponent, decorators: [{
|
|
1404
|
-
type: Component,
|
|
1405
|
-
args: [{ selector: 'st-table', template: "<!-- Top pagination controls -->\n<st-pagination \n *ngIf=\"showTopPagination() && !(mergedConfig.tableSkeleton?.enabled | async)\" \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n position=\"top\">\n</st-pagination>\n\n<div class=\"st-table\" *ngIf=\"!(mergedConfig.tableSkeleton?.enabled | async)\" \n [ngClass]=\"{\n 'virtual-scroll-enabled': isVirtualScrollEnabled(),\n 'keyboard-navigation-enabled': isKeyboardNavigationEnabled()\n }\"\n [ngStyle]=\"{\n 'max-height.px': !isVirtualScrollEnabled() ? mergedConfig.display?.maxHeight : null\n }\"\n stKeyboardNavigation\n [tableState]=\"getActiveTableState()\"\n [addRowOnNavigatePastEnd]=\"mergedConfig.features?.keyboardNavigation?.addRowOnNavigatePastEnd || false\"\n [attr.tabindex]=\"isKeyboardNavigationEnabled() ? 0 : -1\"\n (focus)=\"onTableContainerFocus($event)\"\n [attr.title]=\"isKeyboardNavigationEnabled() ? 'Click a cell or press Tab to start keyboard navigation' : null\">\n <!-- Unified Table Actions Menu -->\n\n <!-- Virtual scroll viewport wrapper -->\n <div class=\"st-scroll-viewport\" #scrollViewport *ngIf=\"isVirtualScrollEnabled()\"\n [ngStyle]=\"{ 'height.px': getVirtualScrollViewportHeight() }\">\n\n <!-- Spacer to create scrollable area -->\n <div class=\"st-scroll-spacer\" [ngStyle]=\"{ 'height.px': virtualScrollTotalHeight$ | async }\">\n </div>\n\n <!-- Table positioner with transform (instead of tbody) -->\n <div class=\"st-table-positioner\" [ngStyle]=\"{ transform: 'translateY(' + (virtualScrollOffsetY$ | async) + 'px)' }\">\n <!-- Table with only visible rows -->\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'virtual',\n theadStyle: { top: (virtualScrollOffsetYNeg$ | async) + 'px' }\n }\"></ng-container>\n </div>\n </div>\n \n <!-- Standard table (when virtual scroll disabled) -->\n <ng-container *ngIf=\"!isVirtualScrollEnabled()\">\n <ng-container *ngTemplateOutlet=\"tableTemplate; context: { \n mode: 'standard',\n theadStyle: null\n }\"></ng-container>\n </ng-container>\n\n <!-- Shared Column Menu Dropdown -->\n <st-column-menu-dropdown \n [isOpen]=\"columnMenuState.isOpen\"\n [position]=\"columnMenuState.position\"\n [context]=\"columnMenuState.context\"\n (actionClicked)=\"onColumnActionClicked($event)\"\n (closed)=\"closeColumnMenu()\">\n </st-column-menu-dropdown>\n</div>\n\n<ng-container *ngIf=\"(mergedConfig.tableSkeleton?.enabled | async)\">\n <ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container>\n</ng-container>\n\n<!-- Shared Row Actions Dropdown -->\n<st-row-actions-dropdown [isOpen]=\"dropdownState.isOpen\" [position]=\"dropdownState.position\"\n [context]=\"dropdownState.context\" (actionClicked)=\"onRowActionClicked($event)\" (closed)=\"closeRowActionsDropdown()\">\n</st-row-actions-dropdown>\n\n\n<!-- Bottom pagination controls -->\n<st-pagination \n *ngIf=\"showBottomPagination() && !(mergedConfig.tableSkeleton?.enabled | async)\" \n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n position=\"bottom\">\n</st-pagination>\n\n\n <!-- ========================================== -->\n <!-- REUSABLE TABLE TEMPLATE -->\n <!-- ========================================== -->\n <ng-template #tableTemplate let-mode=\"mode\" let-theadStyle=\"theadStyle\">\n <table class=\"st-table-element\">\n <!-- TABLE HEADER -->\n <thead [ngClass]=\"{ 'sticky': mergedConfig.display?.stickyHeader }\" [ngStyle]=\"theadStyle\">\n <tr>\n <!-- Row Number Header -->\n <th *ngIf=\"mergedConfig.showRowNumber\" class=\"row-number-header header-cell sticky-left\"\n [ngStyle]=\"{\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_HEADER_CELL,\n 'width.px': 30\n }\">\n #\n </th>\n <!-- Column Headers -->\n <th \n *ngFor=\"let column of visibleColumns; let colIndex = index; let isFirst = first; let isLast = last\"\n [ngClass]=\"{\n 'header-cell': mode === 'standard',\n 'sticky-left': column.sticky === 'left',\n 'sticky-right': column.sticky === 'right',\n 'sticky-right-first': column.sticky === 'right' && isFirstStickyRight(column.key),\n 'resizable': column.resizable !== false\n }\"\n [ngStyle]=\"{\n position: column.sticky ? 'sticky' : null,\n 'left.px': column.sticky === 'left' ? (column.stickyOffset || 0) : null,\n 'right.px': column.sticky === 'right' ? (column.stickyOffset || 0) : null,\n 'z-index': column.sticky ? ZIndex.STICKY_HEADER_CELL : null,\n 'width.px': column.width\n }\">\n \n <st-header \n [column]=\"column\"\n [columnIndex]=\"colIndex\"\n [isFirstColumn]=\"isFirst\"\n [isLastColumn]=\"isLast\"\n [tableState]=\"getActiveTableState()\"\n [enableSorting]=\"mergedConfig.sorting?.enabled ?? enableSorting\"\n [enableFiltering]=\"mergedConfig.filtering?.enabled ?? enableFiltering\"\n (columnMoved)=\"onColumnMoved($event)\"\n (menuClick)=\"openColumnMenu($event, column, colIndex, isFirst, isLast)\">\n </st-header>\n\n <div \n class=\"resize-handle\" \n stColumnResize\n [column]=\"column\"\n (columnResized)=\"onColumnResized($event)\"\n *ngIf=\"column.resizable !== false\">\n </div>\n </th>\n \n <!-- Settings Column Header -->\n <th \n class=\"settings-column sticky-right\"\n [ngClass]=\"{ 'header-cell': mode === 'standard' }\"\n [ngStyle]=\"{ 'z-index': ZIndex.STICKY_HEADER_CELL }\">\n <div [ngClass]=\"{ 'flex-center': mode === 'virtual', 'header-content': mode === 'standard' }\">\n <st-table-actions \n [tableState]=\"getActiveTableState()\"\n [allowAddColumn]=\"mergedConfig.features?.columnManagement?.allowAdd || false\"\n (addColumnClicked)=\"onAddColumnClick()\">\n </st-table-actions>\n </div>\n </th>\n </tr>\n </thead>\n\n <!-- TABLE BODY -->\n <tbody>\n <!-- Virtual Scroll Rows -->\n <ng-container *ngIf=\"mode === 'virtual'\">\n <tr *ngFor=\"let row of visibleRows$ | async; let relativeIndex = index; trackBy: trackByRowIndex\"\n [attr.data-row-index]=\"getAbsoluteRowIndex(relativeIndex)\">\n <!-- Row Number Cell -->\n <td *ngIf=\"mergedConfig.showRowNumber\" class=\"row-number-cell\" \n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n 'width.px': 30,\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null\n }\">\n {{getAbsoluteRowIndex(relativeIndex) + 1}}\n </td>\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: getAbsoluteRowIndex(relativeIndex),\n mode: 'virtual',\n relativeIndex: relativeIndex\n }\"></ng-container>\n </tr>\n </ng-container>\n\n <!-- Standard Rows -->\n <ng-container *ngIf=\"mode === 'standard'\">\n <tr *ngFor=\"let row of visibleCellGrid; let rowIndex = index\" [attr.data-row-index]=\"rowIndex\">\n <!-- Row Number Cell -->\n <td *ngIf=\"mergedConfig.showRowNumber\" class=\"row-number-cell\" \n [ngClass]=\"{ 'sticky-left': 'left' }\"\n [ngStyle]=\"{\n 'width.px': 30,\n position: 'sticky',\n 'left.px': 0,\n 'z-index': ZIndex.STICKY_BODY_CELL,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null\n }\">\n {{rowIndex + 1}}\n </td>\n <ng-container *ngTemplateOutlet=\"bodyCellTemplate; context: { \n row: row,\n rowIndex: rowIndex,\n mode: 'standard'\n }\"></ng-container>\n </tr>\n </ng-container>\n </tbody>\n </table>\n </ng-template>\n\n <!-- ========================================== -->\n <!-- REUSABLE BODY CELL TEMPLATE -->\n <!-- ========================================== -->\n <ng-template #bodyCellTemplate let-row=\"row\" let-rowIndex=\"rowIndex\" let-mode=\"mode\" let-relativeIndex=\"relativeIndex\">\n <!-- Data Cells -->\n <td \n *ngFor=\"let cell of row; let colIndex = index\"\n [ngClass]=\"{\n 'sticky-left': visibleColumns[colIndex]?.sticky === 'left',\n 'sticky-right': visibleColumns[colIndex]?.sticky === 'right',\n 'sticky-right-first': visibleColumns[colIndex]?.sticky === 'right' && visibleColumns[colIndex]?.key && isFirstStickyRight(visibleColumns[colIndex].key),\n 'align-center': visibleColumns[colIndex]?.alignment === 'center',\n 'align-right': visibleColumns[colIndex]?.alignment === 'right',\n 'cell-focused': cell.isFocused()\n }\"\n [ngStyle]=\"{\n position: visibleColumns[colIndex]?.sticky ? 'sticky' : null,\n 'left.px': visibleColumns[colIndex]?.sticky === 'left' ? (visibleColumns[colIndex]?.stickyOffset || 0) : null,\n 'right.px': visibleColumns[colIndex]?.sticky === 'right' ? (visibleColumns[colIndex]?.stickyOffset || 0) : null,\n 'z-index': visibleColumns[colIndex]?.sticky ? ZIndex.STICKY_BODY_CELL : null,\n 'width.px': visibleColumns[colIndex]?.width,\n 'height.px': mode === 'virtual' ? getVirtualScrollItemSize() : null\n }\"\n (click)=\"isKeyboardNavigationEnabled() ? onCellClick(rowIndex, colIndex) : null\">\n \n <!-- Virtual Scroll Cell -->\n <st-cell \n *ngIf=\"mode === 'virtual'\"\n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\" \n [editMode]=\"getEditModeForCells()\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n [columnIndex]=\"colIndex\"\n (cellEdit)=\"onCellEdit($event)\" \n (cellSave)=\"onCellSave($event)\"\n (cellSaveAndNavigate)=\"onCellSaveAndNavigate($event)\" \n (cellCancel)=\"onCellCancel($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n\n <!-- Standard Cell -->\n <st-cell \n *ngIf=\"mode === 'standard'\"\n [cell]=\"cell\" \n [attr.tabindex]=\"cell.isFocused() ? 0 : -1\"\n [tableState]=\"getActiveTableState()\"\n [tableConfig]=\"mergedConfig\"\n [columnIndex]=\"colIndex\"\n (cellSave)=\"onCellSave($event)\"\n (cellChange)=\"cellChange.emit($event)\">\n </st-cell>\n </td>\n \n <!-- Row Actions Cell -->\n <td class=\"settings-column\"\n [ngClass]=\"{\n 'has-actions': hasRowActions()\n }\"\n [ngStyle]=\"{\n position: hasRowActions() ? 'sticky' : null,\n 'right.px': hasRowActions() ? 0 : null,\n 'z-index': hasRowActions() ? ZIndex.STICKY_BODY_CELL : null\n }\">\n <button \n *ngIf=\"hasRowActions()\"\n class=\"settings-trigger\"\n (click)=\"openRowActionsDropdown($event, getRowData(rowIndex), rowIndex)\"\n type=\"button\" \n aria-label=\"Row actions\">\n \u22EF\n </button>\n </td>\n </ng-template>\n\n<ng-template #skeletonLoader>\n <div class=\"list-row\" *ngIf=\"(mergedConfig.tableSkeleton?.enabled | async)\">\n <div *ngFor=\"let i of skeletonColumns\" class=\"list-content\">\n <nile-skeleton-loader variant=\"text\" width=\"90%\" height=\"18\" *ngFor=\"let j of skeletonRows\"></nile-skeleton-loader>\n </div>\n </div>\n</ng-template>", styles: [".st-table{width:100%;overflow:auto;position:relative;height:100%;max-height:30rem;border-radius:4px;border:1px solid #E6E9EB}.st-table st-table-actions{position:sticky;right:0}.st-table.keyboard-navigation-enabled{cursor:pointer}.st-table.keyboard-navigation-enabled:focus{outline:none;box-shadow:0 0 0 2px #3b82f64d}.st-table.keyboard-navigation-enabled td.cell-focused{outline:2px solid #4299e1;outline-offset:-1px;position:relative;box-shadow:0 0 0 3px #3182ce1a}.st-table.keyboard-navigation-enabled td.cell-focused:focus{outline:2px solid #4299e1;outline-offset:-1px;box-shadow:0 0 0 3px #3182ce1a}.st-table.keyboard-navigation-enabled td.cell-focused:has(.st-cell.editing){box-shadow:0 0 0 4px #2563eb26}.st-table.virtual-scroll-enabled{overflow-x:visible;margin:0;border:1px solid #E6E9EB;border-collapse:separate;border-spacing:0}.st-table.virtual-scroll-enabled .st-scroll-viewport{position:relative;overflow-y:auto;overflow-x:auto;scroll-behavior:smooth}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-scroll-spacer{position:absolute;top:0;left:0;width:1px;pointer-events:none;z-index:-1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-positioner{position:absolute;top:0;left:0;right:0;will-change:transform}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element{position:relative;width:100%;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;border:none;background-color:#fff;will-change:top;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:600;font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.row-number-header{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,.08) 0%,rgba(0,0,0,0) 100%)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.08) 100%)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr{border-bottom:1px solid #E6E9EB;transition:background-color .15s;height:2rem;box-sizing:border-box}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr:last-child{border-bottom:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td{padding:0;vertical-align:middle;box-sizing:border-box;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-center{text-align:center}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.align-right{text-align:right}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column{width:2rem;text-align:center;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.settings-column .settings-trigger:focus{outline:2px solid #4299e1;outline-offset:2px}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.row-number-cell{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)):after{content:\"\";position:absolute;right:-6px;top:0;bottom:-1px;width:5px;border-left:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,.08) 0%,rgba(0,0,0,0) 100%)}.st-table.virtual-scroll-enabled .st-scroll-viewport .st-table-element tbody tr td.sticky-right-first:before{content:\"\";position:absolute;left:-6px;top:0;bottom:-1px;width:5px;border-right:1px solid var(--borderColor);background:linear-gradient(90deg,rgba(0,0,0,0) 0%,rgba(0,0,0,.08) 100%)}.st-table:not(.virtual-scroll-enabled) .st-table-element{width:100%;height:100%;overflow:auto;border-collapse:separate;border-spacing:0;table-layout:fixed}.st-table:not(.virtual-scroll-enabled) .st-table-element thead{background-color:#fff;border-bottom:1px solid #E6E9EB}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky{position:sticky;top:0;z-index:3;background-color:#fff;will-change:top;backface-visibility:hidden}.st-table:not(.virtual-scroll-enabled) .st-table-element thead.sticky:after{content:\"\";position:absolute;bottom:-2px;left:0;right:0;height:2px;background:linear-gradient(to bottom,rgba(0,0,0,.1),transparent)}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th{padding:0;vertical-align:middle;position:relative;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left{position:sticky;left:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-left:not(:has(~ th.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right{position:sticky;right:0;background-color:#fff;z-index:2;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.settings-column{width:2rem;text-align:center;font-weight:600;font-size:12px;position:sticky;right:0;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle{position:absolute;top:0;right:0;bottom:0;width:8px;cursor:col-resize;z-index:4;pointer-events:auto}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:after{content:\"\";position:absolute;top:50%;right:3px;transform:translateY(-50%);width:2px;height:20px;background-color:#cbd5e0;opacity:0;transition:opacity .2s}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:hover:after,.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.resizable .resize-handle:active:after{opacity:1}.st-table:not(.virtual-scroll-enabled) .st-table-element thead tr th.row-number-header{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody{will-change:transform;position:relative;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr{height:2rem;box-sizing:border-box}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr:last-child{border-bottom:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td{padding:0;vertical-align:middle;height:2rem;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb;border:none}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.row-number-cell{text-align:center;font-weight:300;font-size:12px;background-color:#f8f8f8}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-center{text-align:center}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.align-right{text-align:right}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset -1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-left:not(:has(~ td.sticky-left)):after{content:\"\";position:absolute;right:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to left,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right{position:sticky;z-index:2;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column){position:relative;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.sticky-right-first:not(.settings-column):before{content:\"\";position:absolute;left:-8px;top:0;bottom:0;width:8px;background:linear-gradient(to right,transparent,rgba(0,0,0,.08));pointer-events:none;z-index:1}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column{position:sticky;right:0;width:2rem;text-align:center;border-right:none;background-color:#fff;box-shadow:inset 0 -1px #e6e9eb,inset 1px 0 #e6e9eb;z-index:2}.st-table:not(.virtual-scroll-enabled) .st-table-element tbody tr td.settings-column .settings-trigger{background:none;border:none;font-size:1rem;line-height:1;cursor:pointer;border-radius:4px;transition:all .15s ease}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content{display:flex;height:2rem;align-items:center}.st-table:not(.virtual-scroll-enabled) .st-table-element .header-content .table-header-text{flex-grow:1;padding-left:4px}.st-table:not(.virtual-scroll-enabled) .st-table-element .settings-column>.header-content{display:flex;align-items:center;justify-content:center}.flex-center{display:flex;align-items:center;justify-content:center}.list-row{padding:1rem}.list-row .list-content{display:flex;justify-content:space-evenly;gap:4px;margin-bottom:1rem}\n"] }]
|
|
1406
|
-
}], ctorParameters: function () { return [{ type: i1.JsonSchemaValidatorService }, { type: i2.ValidationLoggerService }, { type: i3.VirtualScrollService }, { type: i0.ElementRef }]; }, propDecorators: { tableConfig: [{
|
|
1407
|
-
type: Input
|
|
1408
|
-
}], data: [{
|
|
1409
|
-
type: Input
|
|
1410
|
-
}], data$: [{
|
|
1411
|
-
type: Input
|
|
1412
|
-
}], tableState: [{
|
|
1413
|
-
type: Input
|
|
1414
|
-
}], enableSorting: [{
|
|
1415
|
-
type: Input
|
|
1416
|
-
}], enableFiltering: [{
|
|
1417
|
-
type: Input
|
|
1418
|
-
}], stateChange: [{
|
|
1419
|
-
type: Output
|
|
1420
|
-
}], dataChange: [{
|
|
1421
|
-
type: Output
|
|
1422
|
-
}], cellEdit: [{
|
|
1423
|
-
type: Output
|
|
1424
|
-
}], cellSave: [{
|
|
1425
|
-
type: Output
|
|
1426
|
-
}], cellCancel: [{
|
|
1427
|
-
type: Output
|
|
1428
|
-
}], cellChange: [{
|
|
1429
|
-
type: Output
|
|
1430
|
-
}], columnResized: [{
|
|
1431
|
-
type: Output
|
|
1432
|
-
}], columnMoved: [{
|
|
1433
|
-
type: Output
|
|
1434
|
-
}], configValidationErrors: [{
|
|
1435
|
-
type: Output
|
|
1436
|
-
}], columnAdded: [{
|
|
1437
|
-
type: Output
|
|
1438
|
-
}], rowAction: [{
|
|
1439
|
-
type: Output
|
|
1440
|
-
}], validationStateChange: [{
|
|
1441
|
-
type: Output
|
|
1442
|
-
}], requestAddRow: [{
|
|
1443
|
-
type: Output
|
|
1444
|
-
}], validateConfig: [{
|
|
1445
|
-
type: Input
|
|
1446
|
-
}], scrollViewport: [{
|
|
1447
|
-
type: ViewChild,
|
|
1448
|
-
args: ['scrollViewport', { read: ElementRef }]
|
|
1449
|
-
}], onDocumentClick: [{
|
|
1450
|
-
type: HostListener,
|
|
1451
|
-
args: ['document:click', ['$event']]
|
|
1452
|
-
}] } });
|
|
1453
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3QtdGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc21hcnQtdGFibGUvc3JjL2xpYi9yZW5kZXJlci9jb21wb25lbnRzL3N0LXRhYmxlL3N0LXRhYmxlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3NtYXJ0LXRhYmxlL3NyYy9saWIvcmVuZGVyZXIvY29tcG9uZW50cy9zdC10YWJsZS9zdC10YWJsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUErQyxTQUFTLEVBQUUsVUFBVSxFQUFpQixZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFeEssT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQy9DLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUM1RCxPQUFPLEVBQWUsZ0JBQWdCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUV2RixPQUFPLEVBQWtFLFFBQVEsRUFBdUIsTUFBTSw0QkFBNEIsQ0FBQztBQUMzSSxPQUFPLEVBQUUsZUFBZSxFQUE0QixNQUFNLE1BQU0sQ0FBQztBQUNqRSxPQUFPLEVBQUUsR0FBRyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFPM0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7QUFRekQsTUFBTSxPQUFPLGdCQUFnQjtJQThIM0IsWUFDVSxlQUEyQyxFQUMzQyxNQUErQixFQUMvQixvQkFBMEMsRUFDMUMsVUFBbUM7UUFIbkMsb0JBQWUsR0FBZixlQUFlLENBQTRCO1FBQzNDLFdBQU0sR0FBTixN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LEVBQUUsQ0FBQztRQUM5QyxJQUFJLENBQUMsbUJBQW1CLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDcEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUNoQyxDQUFDOzs2R0F2bkRVLGdCQUFnQjtpR0FBaEIsZ0JBQWdCLDh5QkE0SFUsVUFBVSxrRENwSmpELGs5WEE4UmM7MkZEdFFELGdCQUFnQjtrQkFMNUIsU0FBUzsrQkFDRSxVQUFVO21OQVNYLFdBQVc7c0JBQW5CLEtBQUs7Z0JBR0csSUFBSTtzQkFBWixLQUFLO2dCQUdHLEtBQUs7c0JBQWIsS0FBSztnQkFFRyxVQUFVO3NCQUFsQixLQUFLO2dCQUdHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFHSSxXQUFXO3NCQUFwQixNQUFNO2dCQUdHLFVBQVU7c0JBQW5CLE1BQU07Z0JBR0csUUFBUTtzQkFBakIsTUFBTTtnQkFDRyxRQUFRO3NCQUFqQixNQUFNO2dCQUNHLFVBQVU7c0JBQW5CLE1BQU07Z0JBQ0csVUFBVTtzQkFBbkIsTUFBTTtnQkFDRyxhQUFhO3NCQUF0QixNQUFNO2dCQUNHLFdBQVc7c0JBQXBCLE1BQU07Z0JBR0csc0JBQXNCO3NCQUEvQixNQUFNO2dCQUdHLFdBQVc7c0JBQXBCLE1BQU07Z0JBR0csU0FBUztzQkFBbEIsTUFBTTtnQkFHRyxxQkFBcUI7c0JBQTlCLE1BQU07Z0JBR0csYUFBYTtzQkFBdEIsTUFBTTtnQkFHRSxjQUFjO3NCQUF0QixLQUFLO2dCQTJFNkMsY0FBYztzQkFBaEUsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBczlDakQsZUFBZTtzQkFEZCxZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgT3V0cHV0LCBFdmVudEVtaXR0ZXIsIE9uSW5pdCwgT25EZXN0cm95LCBPbkNoYW5nZXMsIFNpbXBsZUNoYW5nZXMsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiwgQWZ0ZXJWaWV3SW5pdCwgSG9zdExpc3RlbmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb2x1bW5Db25maWcgfSBmcm9tICcuLi8uLi8uLi9tb2RlbHMvY29sdW1uLWNvbmZpZy5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgQ2VsbCB9IGZyb20gJy4uLy4uL21vZGVscy9jZWxsLmNsYXNzJztcbmltcG9ydCB7IFRhYmxlU3RhdGUgfSBmcm9tICcuLi8uLi9tb2RlbHMvdGFibGUtc3RhdGUuY2xhc3MnO1xuaW1wb3J0IHsgVGFibGVDb25maWcsIG1lcmdlVGFibGVDb25maWcgfSBmcm9tICcuLi8uLi8uLi9tb2RlbHMvdGFibGUtY29uZmlnLmludGVyZmFjZSc7XG5pbXBvcnQgeyBUYWJsZVN0YXRlQ2hhbmdlRXZlbnQsIENvbHVtblJlc2l6ZUV2ZW50LCBDb2x1bW5BZGRFdmVudCwgQ29sdW1uTW92ZUV2ZW50LCBDZWxsRm9jdXNQb3NpdGlvbiwgRGF0YUNoYW5nZUV2ZW50IH0gZnJvbSAnLi4vLi4vbW9kZWxzL3RhYmxlLXR5cGVzJztcbmltcG9ydCB7IENlbGxDaGFuZ2VFdmVudCwgQ2VsbFNhdmVFdmVudCwgQ2VsbEVkaXRFdmVudCwgQ2VsbENhbmNlbEV2ZW50LCBFZGl0TW9kZSwgTmF2aWdhdGlvbkRpcmVjdGlvbiB9IGZyb20gJy4uLy4uLy4uL21vZGVscy9jZWxsLXR5cGVzJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCwgT2JzZXJ2YWJsZSwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBtYXAsIGRpc3RpbmN0VW50aWxDaGFuZ2VkIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgSnNvblNjaGVtYVZhbGlkYXRvclNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9qc29uLXNjaGVtYS12YWxpZGF0b3Iuc2VydmljZSc7XG5pbXBvcnQgeyBTY2hlbWFWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICcuLi8uLi8uLi9tb2RlbHMvc2NoZW1hLXZhbGlkYXRpb24uaW50ZXJmYWNlJztcbmltcG9ydCB7IFZhbGlkYXRpb25Mb2dnZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvdmFsaWRhdGlvbi1sb2dnZXIuc2VydmljZSc7XG5pbXBvcnQgeyBWaXJ0dWFsU2Nyb2xsU2VydmljZSwgVmlydHVhbFNjcm9sbFN0YXRlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvdmlydHVhbC1zY3JvbGwuc2VydmljZSc7XG5pbXBvcnQgeyBSb3dBY3Rpb24sIFJvd0FjdGlvbkNvbnRleHQsIFJvd0FjdGlvbkV2ZW50IH0gZnJvbSAnLi4vLi4vLi4vbW9kZWxzL3Jvdy1hY3Rpb24uaW50ZXJmYWNlJztcbmltcG9ydCB7IENvbHVtbkFjdGlvbiwgQ29sdW1uQWN0aW9uQ29udGV4dCwgQ29sdW1uQWN0aW9uRXZlbnQgfSBmcm9tICcuLi8uLi8uLi9tb2RlbHMvY29sdW1uLWFjdGlvbi5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgVGFibGVaSW5kZXggfSBmcm9tICcuLi8uLi9tb2RlbHMvei1pbmRleC5lbnVtJztcbmltcG9ydCB7IFNvcnREaXJlY3Rpb24gfSBmcm9tICcuLi8uLi9tb2RlbHMvdGFibGUtdHlwZXMnO1xuaW1wb3J0IHsgVGFibGVWYWxpZGF0aW9uU3RhdGUgfSBmcm9tICcuLi8uLi9tb2RlbHMvdGFibGUtdmFsaWRhdGlvbi1zdGF0ZS5pbnRlcmZhY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzdC10YWJsZScsXG4gIHRlbXBsYXRlVXJsOiAnLi9zdC10YWJsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3N0LXRhYmxlLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgU3RUYWJsZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xuICAvLyBaLUluZGV4IGNvbnN0YW50cyBmb3IgdGVtcGxhdGUgdXNlXG4gIHJlYWRvbmx5IFpJbmRleCA9IFRhYmxlWkluZGV4O1xuICBcbiAgLy8gTkVXOiBQcmltYXJ5IGNvbmZpZ3VyYXRpb24gaW5wdXRcbiAgQElucHV0KCkgdGFibGVDb25maWchOiBUYWJsZUNvbmZpZztcbiAgXG4gIC8vIE5FVzogUmF3IGRhdGEgaW5wdXQgKGFsdGVybmF0aXZlIHRvIGNlbGxHcmlkKVxuICBASW5wdXQoKSBkYXRhPzogYW55W107XG4gIFxuICAvLyBORVc6IE9ic2VydmFibGUvQmVoYXZpb3JTdWJqZWN0IGRhdGEgaW5wdXQgKGZvciByZWFjdGl2ZSBkYXRhIHN0cmVhbXMpXG4gIEBJbnB1dCgpIGRhdGEkPzogT2JzZXJ2YWJsZTxhbnlbXT4gfCBCZWhhdmlvclN1YmplY3Q8YW55W10+O1xuICBcbiAgQElucHV0KCkgdGFibGVTdGF0ZT86IFRhYmxlU3RhdGU7XG4gIFxuICAvLyBERVBSRUNBVEVEOiBVc2UgdGFibGVDb25maWcgaW5zdGVhZFxuICBASW5wdXQoKSBlbmFibGVTb3J0aW5nOiBib29sZWFuID0gdHJ1ZTtcbiAgQElucHV0KCkgZW5hYmxlRmlsdGVyaW5nOiBib29sZWFuID0gdHJ1ZTtcbiAgXG4gIC8vIE5FVzogU3RhdGUgY2hhbmdlIG91dHB1dFxuICBAT3V0cHV0KCkgc3RhdGVDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPFRhYmxlU3RhdGVDaGFuZ2VFdmVudD4oKTtcbiAgXG4gIC8vIE5FVzogRGF0YSBjaGFuZ2Ugb3V0cHV0IChmb3IgYXN5bmMgZGF0YSB1cGRhdGVzKVxuICBAT3V0cHV0KCkgZGF0YUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8RGF0YUNoYW5nZUV2ZW50PigpO1xuICBcbiAgLy8gRVhJU1RJTkc6IENlbGwgYW5kIGNvbHVtbiBldmVudHNcbiAgQE91dHB1dCgpIGNlbGxFZGl0ID0gbmV3IEV2ZW50RW1pdHRlcjxDZWxsRWRpdEV2ZW50PigpO1xuICBAT3V0cHV0KCkgY2VsbFNhdmUgPSBuZXcgRXZlbnRFbWl0dGVyPENlbGxTYXZlRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBjZWxsQ2FuY2VsID0gbmV3IEV2ZW50RW1pdHRlcjxDZWxsQ2FuY2VsRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBjZWxsQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxDZWxsQ2hhbmdlRXZlbnQ+KCk7XG4gIEBPdXRwdXQoKSBjb2x1bW5SZXNpemVkID0gbmV3IEV2ZW50RW1pdHRlcjxDb2x1bW5SZXNpemVFdmVudD4oKTtcbiAgQE91dHB1dCgpIGNvbHVtbk1vdmVkID0gbmV3IEV2ZW50RW1pdHRlcjxDb2x1bW5Nb3ZlRXZlbnQ+KCk7XG4gIFxuICAvLyBORVc6IENvbmZpZ3VyYXRpb24gdmFsaWRhdGlvbiBvdXRwdXRcbiAgQE91dHB1dCgpIGNvbmZpZ1ZhbGlkYXRpb25FcnJvcnMgPSBuZXcgRXZlbnRFbWl0dGVyPFNjaGVtYVZhbGlkYXRpb25FcnJvcltdPigpO1xuICBcbiAgLy8gTkVXOiBDb2x1bW4gbWFuYWdlbWVudCBvdXRwdXRcbiAgQE91dHB1dCgpIGNvbHVtbkFkZGVkID0gbmV3IEV2ZW50RW1pdHRlcjxDb2x1bW5BZGRFdmVudD4oKTtcbiAgXG4gIC8vIE5FVzogUm93IGFjdGlvbiBvdXRwdXRcbiAgQE91dHB1dCgpIHJvd0FjdGlvbiA9IG5ldyBFdmVudEVtaXR0ZXI8Um93QWN0aW9uRXZlbnQ+KCk7XG4gIFxuICAvLyBORVc6IFZhbGlkYXRpb24gc3RhdGUgY2hhbmdlIG91dHB1dFxuICBAT3V0cHV0KCkgdmFsaWRhdGlvblN0YXRlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxUYWJsZVZhbGlkYXRpb25TdGF0ZT4oKTtcbiAgXG4gIC8vIE5FVzogUmVxdWVzdCB0byBhZGQgYSBuZXcgcm93IChlbWl0dGVkIHdoZW4gbmF2aWdhdGluZyBwYXN0IGxhc3Qgcm93IHdpdGggYWRkUm93T25OYXZpZ2F0ZVBhc3RFbmQgZW5hYmxlZClcbiAgQE91dHB1dCgpIHJlcXVlc3RBZGRSb3cgPSBuZXcgRXZlbnRFbWl0dGVyPHsgZm9jdXNDb2x1bW4/OiBudW1iZXIgfT4oKTtcbiAgXG4gIC8vIE5FVzogT3B0aW9uYWwgdmFsaWRhdGlvbiBmbGFnXG4gIEBJbnB1dCgpIHZhbGlkYXRlQ29uZmlnOiBib29sZWFuID0gZmFsc2U7XG4gIFxuICAvLyBJbnRlcm5hbCBzdGF0ZVxuICBwcml2YXRlIGludGVybmFsVGFibGVTdGF0ZT86IFRhYmxlU3RhdGU7XG4gIHByaXZhdGUgaW50ZXJuYWxDZWxsR3JpZD86IENlbGw8YW55PltdW107XG4gIHByaXZhdGUgc3RhdGVTdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb247XG4gIHByaXZhdGUgZm9jdXNTdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb247XG4gIHByaXZhdGUgdmFsaWRhdGlvblN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSBkYXRhU3Vic2NyaXB0aW9uPzogU3Vic2NyaXB0aW9uO1xuICBwcml2YXRlIHJlcXVlc3RBZGRSb3dTdWJzY3JpcHRpb24/OiBTdWJzY3JpcHRpb247XG4gIHByaXZhdGUgaW50ZXJuYWxEYXRhJDogQmVoYXZpb3JTdWJqZWN0PGFueVtdPiA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55W10+KFtdKTtcbiAgcHJpdmF0ZSBwcmV2aW91c0RhdGE6IGFueVtdID0gW107XG4gIG1lcmdlZENvbmZpZyE6IFRhYmxlQ29uZmlnO1xuICBcbiAgLy8gTW9kYWwgc3RhdGVcbiAgcHVibGljIHNob3dDb2x1bW5Nb2RhbDogYm9vbGVhbiA9IGZhbHNlO1xuICBcbiAgLy8gQ2FjaGVkIHZpc2libGUgY29sdW1ucyBhbmQgY2VsbCBncmlkIHRvIHByZXZlbnQgcmUtY3JlYXRpb24gb24gZXZlcnkgY2hhbmdlIGRldGVjdGlvblxuICBwdWJsaWMgdmlzaWJsZUNvbHVtbnM6IENvbHVtbkNvbmZpZzxhbnk+W10gPSBbXTtcbiAgcHVibGljIHZpc2libGVDZWxsR3JpZDogQ2VsbDxhbnk+W11bXSA9IFtdO1xuICBcbiAgLy8gUm93IGFjdGlvbnMgZHJvcGRvd24gc3RhdGVcbiAgcHVibGljIGRyb3Bkb3duU3RhdGU6IHtcbiAgICBpc09wZW46IGJvb2xlYW47XG4gICAgcG9zaXRpb246IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfTtcbiAgICBjb250ZXh0OiBSb3dBY3Rpb25Db250ZXh0IHwgbnVsbDtcbiAgfSA9IHtcbiAgICBpc09wZW46IGZhbHNlLFxuICAgIHBvc2l0aW9uOiB7IHg6IDAsIHk6IDAgfSxcbiAgICBjb250ZXh0OiBudWxsXG4gIH07XG4gIFxuICBwdWJsaWMgc2tlbGV0b25Db2x1bW5zPzogbnVtYmVyW107XG4gIHB1YmxpYyBza2VsZXRvblJvd3M/OiBudW1iZXJbXTtcblxuICAvLyBDb2x1bW4gbWVudSBkcm9wZG93biBzdGF0ZVxuICBwdWJsaWMgY29sdW1uTWVudVN0YXRlOiB7XG4gICAgaXNPcGVuOiBib29sZWFuO1xuICAgIHBvc2l0aW9uOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH07XG4gICAgY29udGV4dDogQ29sdW1uQWN0aW9uQ29udGV4dCB8IG51bGw7XG4gIH0gPSB7XG4gICAgaXNPcGVuOiBmYWxzZSxcbiAgICBwb3NpdGlvbjogeyB4OiAwLCB5OiAwIH0sXG4gICAgY29udGV4dDogbnVsbFxuICB9O1xuICBcbiAgLy8gVmlydHVhbCBzY3JvbGwgcHJvcGVydGllc1xuICBwcml2YXRlIHNjcm9sbENvbnRhaW5lcj86IEhUTUxFbGVtZW50O1xuICBwcml2YXRlIHNjcm9sbFN1YnNjcmlwdGlvbj86IFN1YnNjcmlwdGlvbjtcbiAgcHJpdmF0ZSB2aXJ0dWFsU2Nyb2xsU3RhdGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxWaXJ0dWFsU2Nyb2xsU3RhdGUgfCBudWxsPihudWxsKTtcbiAgXG4gIC8vIE9ic2VydmFibGUgc3RyZWFtcyBkZXJpdmVkIGZyb20gdmlydHVhbCBzY3JvbGwgc3RhdGVcbiAgcHVibGljIHZpcnR1YWxTY3JvbGxUb3RhbEhlaWdodCQ6IE9ic2VydmFibGU8bnVtYmVyPiA9IHRoaXMudmlydHVhbFNjcm9sbFN0YXRlJC5waXBlKFxuICAgIG1hcChzdGF0ZSA9PiBzdGF0ZT8udG90YWxIZWlnaHQgPz8gMCksXG4gICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKVxuICApO1xuICBcbiAgcHVibGljIHZpcnR1YWxTY3JvbGxPZmZzZXRZJDogT2JzZXJ2YWJsZTxudW1iZXI+ID0gdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLnBpcGUoXG4gICAgbWFwKHN0YXRlID0+IHN0YXRlPy5vZmZzZXRZID8/IDApLFxuICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKClcbiAgKTtcblxuICBwdWJsaWMgdmlydHVhbFNjcm9sbE9mZnNldFlOZWckOiBPYnNlcnZhYmxlPG51bWJlcj4gPSB0aGlzLnZpcnR1YWxTY3JvbGxTdGF0ZSQucGlwZShcbiAgICBtYXAoc3RhdGUgPT4gTnVtYmVyKHN0YXRlPy5vZmZzZXRZID8/IDApICogLTEgKSxcbiAgICBkaXN0aW5jdFVudGlsQ2hhbmdlZCgpXG4gICk7XG4gIFxuICBwdWJsaWMgdmlzaWJsZVJvd3MkOiBPYnNlcnZhYmxlPENlbGw8YW55PltdW10+ID0gdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLnBpcGUoXG4gICAgbWFwKHN0YXRlID0+IHtcbiAgICAgIGlmICghc3RhdGUpIHJldHVybiB0aGlzLnZpc2libGVDZWxsR3JpZDtcbiAgICAgIGNvbnN0IHsgc3RhcnRJbmRleCwgZW5kSW5kZXggfSA9IHN0YXRlO1xuICAgICAgcmV0dXJuIHRoaXMudmlzaWJsZUNlbGxHcmlkLnNsaWNlKHN0YXJ0SW5kZXgsIGVuZEluZGV4KTtcbiAgICB9KVxuICApO1xuICBcbiAgQFZpZXdDaGlsZCgnc2Nyb2xsVmlld3BvcnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYgfSkgc2Nyb2xsVmlld3BvcnQ/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcbiAgXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgc2NoZW1hVmFsaWRhdG9yOiBKc29uU2NoZW1hVmFsaWRhdG9yU2VydmljZSxcbiAgICBwcml2YXRlIGxvZ2dlcjogVmFsaWRhdGlvbkxvZ2dlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSB2aXJ0dWFsU2Nyb2xsU2VydmljZTogVmlydHVhbFNjcm9sbFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBlbGVtZW50UmVmOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PixcbiAgKSB7fVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIC8vIFZhbGlkYXRlIHRoYXQgYXQgbGVhc3QgdGFibGVDb25maWcgb3IgY29sdW1ucyBpcyBwcm92aWRlZFxuICAgIGlmICghdGhpcy50YWJsZUNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFaXRoZXIgdGFibGVDb25maWcgb3IgY29sdW1ucyBtdXN0IGJlIHByb3ZpZGVkJyk7XG4gICAgfVxuICAgIFxuICAgIC8vIE1lcmdlIGNvbmZpZyB3aXRoIGRlZmF1bHRzXG4gICAgaWYgKHRoaXMudGFibGVDb25maWcpIHtcbiAgICAgIHRoaXMubWVyZ2VkQ29uZmlnID0gbWVyZ2VUYWJsZUNvbmZpZyh0aGlzLnRhYmxlQ29uZmlnKTtcbiAgICAgIFxuICAgICAgLy8gVmFsaWRhdGUgY29uZmlndXJhdGlvbiBpZiBlbmFibGVkXG4gICAgICBpZiAodGhpcy52YWxpZGF0ZUNvbmZpZykge1xuICAgICAgICB0aGlzLnZhbGlkYXRlQ29uZmlndXJhdGlvbih0aGlzLm1lcmdlZENvbmZpZyk7XG4gICAgICB9XG4gICAgfVxuICAgIFxuICAgIC8vIENyZWF0ZSBvciB1c2UgVGFibGVTdGF0ZVxuICAgIGlmICghdGhpcy50YWJsZVN0YXRlKSB7XG4gICAgICB0aGlzLmNyZWF0ZUludGVybmFsVGFibGVTdGF0ZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBTdWJzY3JpYmUgdG8gZXh0ZXJuYWwgdGFibGVTdGF0ZSBjaGFuZ2VzXG4gICAgICB0aGlzLnN1YnNjcmliZVRvRXh0ZXJuYWxUYWJsZVN0YXRlKCk7XG4gICAgfVxuICAgIFxuICAgIC8vIFNldHVwIGRhdGEgc291cmNlIChzeW5jIG9yIGFzeW5jKVxuICAgIHRoaXMuc2V0dXBEYXRhU291cmNlKCk7XG4gICAgXG4gICAgLy8gQ2FsY3VsYXRlIHN0aWNreSBvZmZzZXRzXG4gICAgY29uc3Qgcm93TnVtYmVyV2lkdGggPSB0aGlzLm1lcmdlZENvbmZpZy5zaG93Um93TnVtYmVyID8gMzAgOiAwO1xuICAgIGNvbnN0IHNldHRpbmdzQ29sdW1uV2lkdGggPSB0aGlzLmhhc1Jvd0FjdGlvbnMoKSA/IDI4IDogMDsgLy8gU2V0dGluZ3MgY29sdW1uIGlzIH4zMnB4IHdpZGUgd2hlbiB2aXNpYmxlXG4gICAgdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkuY2FsY3VsYXRlU3RpY2t5T2Zmc2V0cyhyb3dOdW1iZXJXaWR0aCwgc2V0dGluZ3NDb2x1bW5XaWR0aCk7XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSB2aXNpYmxlIGNvbHVtbnMgYW5kIGNlbGwgZ3JpZFxuICAgIHRoaXMudXBkYXRlVmlzaWJsZURhdGEoKTtcbiAgICBcbiAgICAvLyBJbml0aWFsaXplIHZpcnR1YWwgc2Nyb2xsIGlmIGVuYWJsZWRcbiAgICBpZiAodGhpcy5pc1ZpcnR1YWxTY3JvbGxFbmFibGVkKCkpIHtcbiAgICAgIHRoaXMuaW5pdGlhbGl6ZVZpcnR1YWxTY3JvbGwoKTtcbiAgICB9XG4gICAgXG4gICAgLy8gSW5pdGlhbGl6ZSBrZXlib2FyZCBuYXZpZ2F0aW9uIGlmIGVuYWJsZWRcbiAgICBpZiAodGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSkge1xuICAgICAgdGhpcy5pbml0aWFsaXplS2V5Ym9hcmROYXZpZ2F0aW9uKCk7XG4gICAgfVxuXG4gICAgdGhpcy5za2VsZXRvbkNvbHVtbnMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiB0aGlzLm1lcmdlZENvbmZpZy50YWJsZVNrZWxldG9uPy5jb2x1bW5zID8/IDEwIH0sIChfLCBpKSA9PiBpKTtcbiAgICB0aGlzLnNrZWxldG9uUm93cyA9IEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMubWVyZ2VkQ29uZmlnLnRhYmxlU2tlbGV0b24/LnJvd3MgPz8gMTAgfSwgKF8sIGkpID0+IGkpO1xuICB9XG4gIFxuICBuZ0FmdGVyVmlld0luaXQoKTogdm9pZCB7XG4gICAgLy8gU2V0dXAgdmlydHVhbCBzY3JvbGwgYWZ0ZXIgdmlldyBpcyByZWFkeVxuICAgIGlmICh0aGlzLmlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKSAmJiB0aGlzLnNjcm9sbFZpZXdwb3J0KSB7XG4gICAgICB0aGlzLnNldHVwVmlydHVhbFNjcm9sbExpc3RlbmVyKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIC8vIFZhbGlkYXRlIGNvbmZpZ3VyYXRpb24gd2hlbiB0YWJsZUNvbmZpZyBjaGFuZ2VzXG4gICAgaWYgKGNoYW5nZXNbJ3RhYmxlQ29uZmlnJ10gJiYgIWNoYW5nZXNbJ3RhYmxlQ29uZmlnJ10uZmlyc3RDaGFuZ2UgJiYgdGhpcy50YWJsZUNvbmZpZykge1xuICAgICAgdGhpcy5tZXJnZWRDb25maWcgPSBtZXJnZVRhYmxlQ29uZmlnKHRoaXMudGFibGVDb25maWcpO1xuICAgICAgXG4gICAgICAvLyBWYWxpZGF0ZSBjb25maWd1cmF0aW9uIGlmIGVuYWJsZWRcbiAgICAgIGlmICh0aGlzLnZhbGlkYXRlQ29uZmlnKSB7XG4gICAgICAgIHRoaXMudmFsaWRhdGVDb25maWd1cmF0aW9uKHRoaXMubWVyZ2VkQ29uZmlnKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgLy8gVXBkYXRlIGludGVybmFsIHRhYmxlIHN0YXRlIHdpdGggbmV3IGNvbHVtbnMgaWYgdXNpbmcgaW50ZXJuYWwgc3RhdGVcbiAgICAgIGlmICh0aGlzLmludGVybmFsVGFibGVTdGF0ZSkge1xuICAgICAgICB0aGlzLmludGVybmFsVGFibGVTdGF0ZS51cGRhdGVDb2x1bW5zKHRoaXMubWVyZ2VkQ29uZmlnLmNvbHVtbnMpO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBVcGRhdGUgdmlzaWJsZSBjb2x1bW5zIGFuZCBjZWxsIGdyaWRcbiAgICAgIHRoaXMudXBkYXRlVmlzaWJsZURhdGEoKTtcbiAgICB9XG4gICAgXG4gICAgLy8gUmVjcmVhdGUgY2VsbCBncmlkIHdoZW4gZGF0YSBjaGFuZ2VzIChvbmx5IGlmIG5vdCB1c2luZyBkYXRhJCBPYnNlcnZhYmxlKVxuICAgIGlmIChjaGFuZ2VzWydkYXRhJ10gJiYgIWNoYW5nZXNbJ2RhdGEnXS5maXJzdENoYW5nZSAmJiB0aGlzLmRhdGEgJiYgIXRoaXMuZGF0YSQpIHtcbiAgICAgIHRoaXMuaGFuZGxlU3luY0RhdGFDaGFuZ2UoY2hhbmdlc1snZGF0YSddLnByZXZpb3VzVmFsdWUgfHwgW10pO1xuICAgIH1cbiAgICBcbiAgICAvLyBIYW5kbGUgZGF0YSQgT2JzZXJ2YWJsZSBpbnB1dCBjaGFuZ2VzXG4gICAgaWYgKGNoYW5nZXNbJ2RhdGEkJ10gJiYgIWNoYW5nZXNbJ2RhdGEkJ10uZmlyc3RDaGFuZ2UpIHtcbiAgICAgIHRoaXMuc2V0dXBEYXRhU291cmNlKCk7XG4gICAgfVxuICAgIFxuICAgIC8vIFJlY3JlYXRlIGNlbGwgZ3JpZCB3aGVuIGNlbGxHcmlkIGNoYW5nZXNcbiAgICBpZiAoY2hhbmdlc1snY2VsbEdyaWQnXSAmJiAhY2hhbmdlc1snY2VsbEdyaWQnXS5maXJzdENoYW5nZSkge1xuICAgICAgLy8gQ2VsbCBncmlkIHdhcyB1cGRhdGVkIGV4dGVybmFsbHksIG5vIG5lZWQgdG8gcmVjcmVhdGVcbiAgICAgIC8vIEp1c3QgcmVjYWxjdWxhdGUgc3RpY2t5IG9mZnNldHMgaWYgbmVlZGVkXG4gICAgICBpZiAodGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkpIHtcbiAgICAgICAgY29uc3Qgcm93TnVtYmVyV2lkdGggPSB0aGlzLm1lcmdlZENvbmZpZy5zaG93Um93TnVtYmVyID8gMzAgOiAwO1xuICAgICAgICBjb25zdCBzZXR0aW5nc0NvbHVtbldpZHRoID0gdGhpcy5oYXNSb3dBY3Rpb25zKCkgPyAzMiA6IDA7XG4gICAgICAgIHRoaXMuZ2V0QWN0aXZlVGFibGVTdGF0ZSgpLmNhbGN1bGF0ZVN0aWNreU9mZnNldHMocm93TnVtYmVyV2lkdGgsIHNldHRpbmdzQ29sdW1uV2lkdGgpO1xuICAgICAgfVxuICAgICAgLy8gVXBkYXRlIHZpc2libGUgY29sdW1ucyBhbmQgY2VsbCBncmlkXG4gICAgICB0aGlzLnVwZGF0ZVZpc2libGVEYXRhKCk7XG4gICAgfVxuICAgIFxuICAgIC8vIEhhbmRsZSB0YWJsZVN0YXRlIGlucHV0IGNoYW5nZXMgKHdoZW4gZXh0ZXJuYWwgc3RhdGUgaXMgcHJvdmlkZWQsIGUuZy4sIGluIHdvcmtib29rKVxuICAgIGlmIChjaGFuZ2VzWyd0YWJsZVN0YXRlJ10gJiYgIWNoYW5nZXNbJ3RhYmxlU3RhdGUnXS5maXJzdENoYW5nZSAmJiB0aGlzLnRhYmxlU3RhdGUpIHtcbiAgICAgIC8vIFVuc3Vic2NyaWJlIGZyb20gYWxsIG9sZCB0YWJsZVN0YXRlIG9ic2VydmFibGVzIHRvIHByZXZlbnQgbWVtb3J5IGxlYWtzXG4gICAgICB0aGlzLnN0YXRlU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy52YWxpZGF0aW9uU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgICAgdGhpcy5mb2N1c1N1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICAgIFxuICAgICAgLy8gUmVzdWJzY3JpYmUgdG8gbmV3IHRhYmxlU3RhdGUncyBvYnNlcnZhYmxlc1xuICAgICAgdGhpcy5zdWJzY3JpYmVUb0V4dGVybmFsVGFibGVTdGF0ZSgpO1xuICAgICAgXG4gICAgICAvLyBSZWluaXRpYWxpemUga2V5Ym9hcmQgbmF2aWdhdGlvbiB3aXRoIG5ldyB0YWJsZVN0YXRlXG4gICAgICBpZiAodGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSkge1xuICAgICAgICB0aGlzLmluaXRpYWxpemVLZXlib2FyZE5hdmlnYXRpb24oKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gUmVjYWxjdWxhdGUgdmlydHVhbCBzY3JvbGwgd2hlbiBkYXRhIGNoYW5nZXNcbiAgICBpZiAoKGNoYW5nZXNbJ2RhdGEnXSB8fCBjaGFuZ2VzWydjZWxsR3JpZCddKSAmJiAhY2hhbmdlc1snZGF0YSddPy5maXJzdENoYW5nZSkge1xuICAgICAgaWYgKHRoaXMuaXNWaXJ0dWFsU2Nyb2xsRW5hYmxlZCgpKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMudmlydHVhbFNjcm9sbFN0YXRlJC52YWx1ZTtcbiAgICAgICAgaWYgKGN1cnJlbnRTdGF0ZSkge1xuICAgICAgICAgIGNvbnN0IG5ld1N0YXRlID0gdGhpcy52aXJ0dWFsU2Nyb2xsU2VydmljZS5jYWxjdWxhdGVWaXNpYmxlUmFuZ2Uoe1xuICAgICAgICAgICAgc2Nyb2xsVG9wOiBjdXJyZW50U3RhdGUuc2Nyb2xsVG9wLFxuICAgICAgICAgICAgdmlld3BvcnRIZWlnaHQ6IHRoaXMuZ2V0VmlydHVhbFNjcm9sbFZpZXdwb3J0SGVpZ2h0KCksXG4gICAgICAgICAgICB0b3RhbEl0ZW1zOiB0aGlzLnZpc2libGVDZWxsR3JpZC5sZW5ndGgsXG4gICAgICAgICAgICBpdGVtU2l6ZTogdGhpcy5nZXRWaXJ0dWFsU2Nyb2xsSXRlbVNpemUoKSxcbiAgICAgICAgICAgIGJ1ZmZlclNpemU6IHRoaXMuZ2V0VmlydHVhbFNjcm9sbEJ1ZmZlclNpemUoKVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIHRoaXMudmlydHVhbFNjcm9sbFN0YXRlJC5uZXh0KG5ld1N0YXRlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBVcGRhdGUga2V5Ym9hcmQgbmF2aWdhdGlvbiBkaW1lbnNpb25zIGlmIGVuYWJsZWRcbiAgICAgIGlmICh0aGlzLmlzS2V5Ym9hcmROYXZpZ2F0aW9uRW5hYmxlZCgpICYmIChjaGFuZ2VzWydkYXRhJ10gfHwgY2hhbmdlc1snY2VsbEdyaWQnXSkpIHtcbiAgICAgICAgdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkuc2V0RGltZW5zaW9ucyhcbiAgICAgICAgICB0aGlzLnZpc2libGVDZWxsR3JpZC5sZW5ndGgsXG4gICAgICAgICAgdGhpcy52aXNpYmxlQ29sdW1ucy5sZW5ndGhcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGludGVybmFsIFRhYmxlU3RhdGUgZnJvbSBjb25maWdcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlSW50ZXJuYWxUYWJsZVN0YXRlKCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLmdldEFjdGl2ZUNvbHVtbnMoKTtcbiAgICB0aGlzLmludGVybmFsVGFibGVTdGF0ZSA9IG5ldyBUYWJsZVN0YXRlKGNvbHVtbnMsIHtcbiAgICAgIHBhZ2VTaXplOiB0aGlzLm1lcmdlZENvbmZpZy5wYWdpbmF0aW9uPy5wYWdlU2l6ZSxcbiAgICAgIGluaXRpYWxQYWdlOiB0aGlzLm1lcmdlZENvbmZpZy5pbml0aWFsU3RhdGU/LnBhZ2VcbiAgICB9KTtcbiAgICBcbiAgICAvLyBTZXQgdG90YWwgaXRlbXMgaWYgcHJvdmlkZWQgaW4gY29uZmlnIChmb3Igc2VydmVyLXNpZGUgcGFnaW5hdGlvbilcbiAgICBpZiAodGhpcy5tZXJnZWRDb25maWcucGFnaW5hdGlvbj8udG90YWxJdGVtcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmludGVybmFsVGFibGVTdGF0ZS5zZXRUb3RhbEl0ZW1zKHRoaXMubWVyZ2VkQ29uZmlnLnBhZ2luYXRpb24udG90YWxJdGVtcyk7XG4gICAgfVxuICAgIFxuICAgIC8vIEFwcGx5IGluaXRpYWwgc29ydCBpZiBwcm92aWRlZFxuICAgIGlmICh0aGlzLm1lcmdlZENvbmZpZy5pbml0aWFsU3RhdGU/LnNvcnRCeSkge1xuICAgICAgdGhpcy5tZXJnZWRDb25maWcuaW5pdGlhbFN0YXRlLnNvcnRCeS5mb3JFYWNoKHNvcnQgPT4ge1xuICAgICAgICB0aGlzLmludGVybmFsVGFibGVTdGF0ZSEuYWRkU29ydFRvQ29sdW1uKHNvcnQua2V5LCBzb3J0LmRpcmVjdGlvbik7XG4gICAgICB9KTtcbiAgICB9XG4gICAgXG4gICAgLy8gQXBwbHkgaW5pdGlhbCBmaWx0ZXJzIGlmIHByb3ZpZGVkXG4gICAgaWYgKHRoaXMubWVyZ2VkQ29uZmlnLmluaXRpYWxTdGF0ZT8uZmlsdGVycykge1xuICAgICAgdGhpcy5tZXJnZWRDb25maWcuaW5pdGlhbFN0YXRlLmZpbHRlcnMuZm9yRWFjaChmaWx0ZXIgPT4ge1xuICAgICAgICB0aGlzLmludGVybmFsVGFibGVTdGF0ZSEuc2V0RmlsdGVyT25Db2x1bW4oZmlsdGVyLmtleSwgZmlsdGVyLm9wZXJhdG9yLCBmaWx0ZXIudmFsdWUpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIFxuICAgIC8vIFN1YnNjcmliZSB0byBpbnRlcm5hbCBzdGF0ZSBjaGFuZ2VzIGFuZCByZS1lbWl0XG4gICAgdGhpcy5zdWJzY3JpYmVUb0ludGVybmFsU3RhdGUoKTtcbiAgICBcbiAgICAvLyBTdWJzY3JpYmUgdG8gdmFsaWRhdGlvbiBzdGF0ZSBjaGFuZ2VzIGFuZCByZS1lbWl0XG4gICAgdGhpcy5zdWJzY3JpYmVUb1ZhbGlkYXRpb25TdGF0ZSgpO1xuICB9XG4gIFxuICBwcml2YXRlIHN1YnNjcmliZVRvVmFsaWRhdGlvblN0YXRlKCkge1xuICAgIGlmICghdGhpcy5pbnRlcm5hbFRhYmxlU3RhdGUpIHJldHVybjtcbiAgICB0aGlzLnZhbGlkYXRpb25TdWJzY3JpcHRpb24gPSB0aGlzLmludGVybmFsVGFibGVTdGF0ZS50YWJsZVZhbGlkYXRpb25TdGF0ZSRcbiAgICAgIC5zdWJzY3JpYmUoc3RhdGUgPT4ge1xuICAgICAgICB0aGlzLnZhbGlkYXRpb25TdGF0ZUNoYW5nZS5lbWl0KHN0YXRlKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb0ludGVybmFsU3RhdGUoKSB7XG4gICAgaWYgKCF0aGlzLmludGVybmFsVGFibGVTdGF0ZSkgcmV0dXJuO1xuICAgIHRoaXMuc3RhdGVTdWJzY3JpcHRpb24gPSB0aGlzLmludGVybmFsVGFibGVTdGF0ZT8uc3RhdGVDaGFuZ2UkXG4gICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHtcbiAgICAgICAgdGhpcy5zdGF0ZUNoYW5nZS5lbWl0KGV2ZW50KTtcblxuICAgICAgICAvLyBVcGRhdGUgdmlzaWJsZSBjb2x1bW5zIGFuZCBjZWxsIGdyaWQgb24gdmlzaWJpbGl0eSBjaGFuZ2VzXG4gICAgICAgIGlmIChldmVudC50eXBlID09PSAnY29sdW1uLXZpc2liaWxpdHknIHx8IGV2ZW50LnR5cGUgPT09ICdjb2x1bW4tY29uZmlnJykge1xuICAgICAgICAgIHRoaXMudXBkYXRlVmlzaWJsZURhdGEoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlIHRvIGV4dGVybmFsIFRhYmxlU3RhdGUgY2hhbmdlc1xuICAgKi9cbiAgcHJpdmF0ZSBzdWJzY3JpYmVUb0V4dGVybmFsVGFibGVTdGF0ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudGFibGVTdGF0ZSkgcmV0dXJuO1xuICAgIFxuICAgIHRoaXMuc3RhdGVTdWJzY3JpcHRpb24gPSB0aGlzLnRhYmxlU3RhdGUuc3RhdGVDaGFuZ2UkXG4gICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHtcbiAgICAgICAgdGhpcy5zdGF0ZUNoYW5nZS5lbWl0KGV2ZW50KTtcbiAgICAgICAgXG4gICAgICAgIC8vIFVwZGF0ZSB2aXNpYmxlIGNvbHVtbnMgYW5kIGNlbGwgZ3JpZCBvbiB2aXNpYmlsaXR5IGNoYW5nZXNcbiAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09ICdjb2x1bW4tdmlzaWJpbGl0eScgfHwgZXZlbnQudHlwZSA9PT0gJ2NvbHVtbi1jb25maWcnKSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVWaXNpYmxlRGF0YSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICBcbiAgICAvLyBTdWJzY3JpYmUgdG8gdmFsaWRhdGlvbiBzdGF0ZSBjaGFuZ2VzIGFuZCByZS1lbWl0XG4gICB0aGlzLnN1YnNjcmliZVRvVmFsaWRhdGlvblN0YXRlKCk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDcmVhdGUgY2VsbCBncmlkIGZyb20gcmF3IGRhdGFcbiAgICovXG4gIHByaXZhdGUgY3JlYXRlQ2VsbEdyaWRGcm9tRGF0YSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZGF0YSkgcmV0dXJuO1xuICAgIFxuICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLmdldEFjdGl2ZUNvbHVtbnMoKTtcbiAgICB0aGlzLmludGVybmFsQ2VsbEdyaWQgPSB0aGlzLmRhdGEubWFwKChyb3dEYXRhLCByb3dJbmRleCkgPT5cbiAgICAgIGNvbHVtbnMubWFwKGNvbHVtbiA9PiBcbiAgICAgICAgbmV3IENlbGwoY29sdW1uLCByb3dEYXRhW2NvbHVtbi5rZXldLCByb3dEYXRhLCByb3dJbmRleClcbiAgICAgIClcbiAgICApO1xuICB9XG4gIFxuICAvKipcbiAgICogU2V0dXAgZGF0YSBzb3VyY2UgLSBlaXRoZXIgc3luYyBhcnJheSBvciBhc3luYyBPYnNlcnZhYmxlXG4gICAqIEhhbmRsZXMgaW5pdGlhbGl6YXRpb24gYW5kIHN1YnNjcmlwdGlvbiB0byBkYXRhIGNoYW5nZXNcbiAgICovXG4gIHByaXZhdGUgc2V0dXBEYXRhU291cmNlKCk6IHZvaWQge1xuICAgIC8vIFdhcm4gaWYgYm90aCBkYXRhIGFuZCBkYXRhJCBhcmUgcHJvdmlkZWRcbiAgICBpZiAodGhpcy5kYXRhICYmIHRoaXMuZGF0YSQpIHtcbiAgICAgIGNvbnNvbGUud2FybignU3RUYWJsZUNvbXBvbmVudDogQm90aCBkYXRhIGFuZCBkYXRhJCBpbnB1dHMgYXJlIHByb3ZpZGVkLiBVc2luZyBkYXRhJCAoT2JzZXJ2YWJsZSkgYW5kIGlnbm9yaW5nIGRhdGEgYXJyYXkuJyk7XG4gICAgfVxuICAgIFxuICAgIC8vIENsZWFuIHVwIGV4aXN0aW5nIHN1YnNjcmlwdGlvblxuICAgIHRoaXMuZGF0YVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICBcbiAgICAvLyBQcmlvcml0eTogZGF0YSQgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIGRhdGFcbiAgICBpZiAodGhpcy5kYXRhJCkge1xuICAgICAgdGhpcy5zdWJzY3JpYmVUb0RhdGFDaGFuZ2VzKCk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmRhdGEpIHtcbiAgICAgIC8vIEZvciBzeW5jIGRhdGEsIGVtaXQgb25jZSB0aHJvdWdoIGludGVybmFsIG9ic2VydmFibGVcbiAgICAgIHRoaXMucHJldmlvdXNEYXRhID0gW107XG4gICAgICB0aGlzLmludGVybmFsRGF0YSQubmV4dCh0aGlzLmRhdGEpO1xuICAgICAgdGhpcy5zdWJzY3JpYmVUb0RhdGFDaGFuZ2VzKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vIGRhdGEgcHJvdmlkZWQsIGVtaXQgZW1wdHkgYXJyYXlcbiAgICAgIHRoaXMucHJldmlvdXNEYXRhID0gW107XG4gICAgICB0aGlzLmludGVybmFsRGF0YSQubmV4dChbXSk7XG4gICAgICB0aGlzLnN1YnNjcmliZVRvRGF0YUNoYW5nZXMoKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBTdWJzY3JpYmUgdG8gZGF0YSBjaGFuZ2VzIChlaXRoZXIgZnJvbSBkYXRhJCBpbnB1dCBvciBpbnRlcm5hbCBCZWhhdmlvclN1YmplY3QpXG4gICAqL1xuICBwcml2YXRlIHN1YnNjcmliZVRvRGF0YUNoYW5nZXMoKTogdm9pZCB7XG4gICAgY29uc3QgZGF0YVNvdXJjZSQgPSB0aGlzLmRhdGEkIHx8IHRoaXMuaW50ZXJuYWxEYXRhJC5hc09ic2VydmFibGUoKTtcbiAgICBcbiAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24gPSBkYXRhU291cmNlJC5zdWJzY3JpYmUobmV3RGF0YSA9PiB7XG4gICAgICB0aGlzLmhhbmRsZURhdGFDaGFuZ2UobmV3RGF0YSk7XG4gICAgfSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBIYW5kbGUgZGF0YSBjaGFuZ2UgZnJvbSBPYnNlcnZhYmxlIGVtaXNzaW9uXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZURhdGFDaGFuZ2UobmV3RGF0YTogYW55W10pOiB2b2lkIHtcbiAgICBjb25zdCB0aW1lc3RhbXAgPSBEYXRlLm5vdygpO1xuICAgIGNvbnN0IHNvdXJjZTogJ3N5bmMnIHwgJ2FzeW5jJyA9IHRoaXMuZGF0YSQgPyAnYXN5bmMnIDogJ3N5bmMnO1xuICAgIFxuICAgIC8vIEVtaXQgZGF0YSBjaGFuZ2UgZXZlbnRcbiAgICB0aGlzLmRhdGFDaGFuZ2UuZW1pdCh7XG4gICAgICBwcmV2aW91c0RhdGE6IHRoaXMucHJldmlvdXNEYXRhLFxuICAgICAgY3VycmVudERhdGE6IG5ld0RhdGEsXG4gICAgICB0aW1lc3RhbXAsXG4gICAgICBzb3VyY2VcbiAgICB9KTtcbiAgICBcbiAgICAvLyBVcGRhdGUgZGF0YSByZWZlcmVuY2VcbiAgICB0aGlzLmRhdGEgPSBuZXdEYXRhO1xuICAgIHRoaXMucHJldmlvdXNEYXRhID0gWy4uLm5ld0RhdGFdO1xuICAgIFxuICAgIC8vIFJlY3JlYXRlIGNlbGwgZ3JpZFxuICAgIHRoaXMuY3JlYXRlQ2VsbEdyaWRGcm9tRGF0YSgpO1xuICAgIFxuICAgIC8vIFVwZGF0ZSB2aXNpYmxlIGRhdGFcbiAgICB0aGlzLnVwZGF0ZVZpc2libGVEYXRhKCk7XG4gICAgXG4gICAgLy8gUmVjYWxjdWxhdGUgdmlydHVhbCBzY3JvbGwgaWYgZW5hYmxlZFxuICAgIGlmICh0aGlzLmlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKSkge1xuICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLnZhbHVlO1xuICAgICAgaWYgKGN1cnJlbnRTdGF0ZSkge1xuICAgICAgICBjb25zdCBuZXdTdGF0ZSA9IHRoaXMudmlydHVhbFNjcm9sbFNlcnZpY2UuY2FsY3VsYXRlVmlzaWJsZVJhbmdlKHtcbiAgICAgICAgICBzY3JvbGxUb3A6IGN1cnJlbnRTdGF0ZS5zY3JvbGxUb3AsXG4gICAgICAgICAgdmlld3BvcnRIZWlnaHQ6IHRoaXMuZ2V0VmlydHVhbFNjcm9sbFZpZXdwb3J0SGVpZ2h0KCksXG4gICAgICAgICAgdG90YWxJdGVtczogdGhpcy52aXNpYmxlQ2VsbEdyaWQubGVuZ3RoLFxuICAgICAgICAgIGl0ZW1TaXplOiB0aGlzLmdldFZpcnR1YWxTY3JvbGxJdGVtU2l6ZSgpLFxuICAgICAgICAgIGJ1ZmZlclNpemU6IHRoaXMuZ2V0VmlydHVhbFNjcm9sbEJ1ZmZlclNpemUoKVxuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLm5leHQobmV3U3RhdGUpO1xuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICAvLyBVcGRhdGUga2V5Ym9hcmQgbmF2aWdhdGlvbiBkaW1lbnNpb25zIGlmIGVuYWJsZWRcbiAgICBpZiAodGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSkge1xuICAgICAgdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkuc2V0RGltZW5zaW9ucyhcbiAgICAgICAgdGhpcy52aXNpYmxlQ2VsbEdyaWQubGVuZ3RoLFxuICAgICAgICB0aGlzLnZpc2libGVDb2x1bW5zLmxlbmd0aFxuICAgICAgKTtcbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBIYW5kbGUgc3luYyBkYXRhIGNoYW5nZSAoZnJvbSBASW5wdXQoKSBkYXRhIGNoYW5nZXMpXG4gICAqL1xuICBwcml2YXRlIGhhbmRsZVN5bmNEYXRhQ2hhbmdlKHByZXZpb3VzRGF0YTogYW55W10pOiB2b2lkIHtcbiAgICB0aGlzLnByZXZpb3VzRGF0YSA9IHByZXZpb3VzRGF0YTtcbiAgICB0aGlzLmludGVybmFsRGF0YSQubmV4dCh0aGlzLmRhdGEgfHwgW10pO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IGFjdGl2ZSBUYWJsZVN0YXRlIChwcm92aWRlZCBvciBpbnRlcm5hbClcbiAgICovXG4gIGdldEFjdGl2ZVRhYmxlU3RhdGUoKTogVGFibGVTdGF0ZSB7XG4gICAgcmV0dXJuIHRoaXMudGFibGVTdGF0ZSB8fCB0aGlzLmludGVybmFsVGFibGVTdGF0ZSE7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgYWN0aXZlIGNlbGwgZ3JpZCAocHJvdmlkZWQgb3IgaW50ZXJuYWwpXG4gICAqL1xuICBnZXRBY3RpdmVDZWxsR3JpZCgpOiBDZWxsPGFueT5bXVtdIHtcbiAgICByZXR1cm4gdGhpcy5pbnRlcm5hbENlbGxHcmlkIHx8IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB2aXNpYmxlIGNlbGwgZ3JpZCAoZmlsdGVyZWQgdG8gb25seSBpbmNsdWRlIHZpc2libGUgY29sdW1ucylcbiAgICovXG4gIGdldFZpc2libGVDZWxsR3JpZCgpOiBDZWxsPGFueT5bXVtdIHtcbiAgICBjb25zdCBhbGxDb2x1bW5zID0gdGhpcy5nZXRBY3RpdmVDb2x1bW5zKCk7XG4gICAgY29uc3QgdmlzaWJsZUNvbHVtbnMgPSB0aGlzLmdldFZpc2libGVDb2x1bW5zKCk7XG4gICAgY29uc3QgdmlzaWJsZUNvbHVtbktleXMgPSBuZXcgU2V0KHZpc2libGVDb2x1bW5zLm1hcChjb2wgPT4gY29sLmtleSkpO1xuICAgIFxuICAgIC8vIEdldCBjb2x1bW4gaW5kaWNlcyBmb3IgdmlzaWJsZSBjb2x1bW5zXG4gICAgY29uc3QgdmlzaWJsZUluZGljZXMgPSBhbGxDb2x1bW5zXG4gICAgICAubWFwKChjb2wsIGluZGV4KSA9PiB2aXNpYmxlQ29sdW1uS2V5cy5oYXMoY29sLmtleSkgPyBpbmRleCA6IC0xKVxuICAgICAgLmZpbHRlcihpbmRleCA9PiBpbmRleCAhPT0gLTEpO1xuICAgIFxuICAgIGNvbnN0IGZ1bGxHcmlkID0gdGhpcy5nZXRBY3RpdmVDZWxsR3JpZCgpO1xuICAgIHJldHVybiBmdWxsR3JpZC5tYXAocm93ID0+IFxuICAgICAgdmlzaWJsZUluZGljZXMubWFwKGluZGV4ID0+IHJvd1tpbmRleF0pLmZpbHRlcihjZWxsID0+IGNlbGwgIT09IHVuZGVmaW5lZClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgdmlzaWJsZSBjZWxsIGdyaWQgYmFzZWQgb24gY3VycmVudCB2aXNpYmlsaXR5IGFuZCBjb2x1bW4gb3JkZXJcbiAgICogQ2FsbGVkIHdoZW4gZGF0YSwgdmlzaWJpbGl0eSwgb3IgY29sdW1uIG9yZGVyIGNoYW5nZXNcbiAgICogXG4gICAqIFRoaXMgbWV0aG9kIHByb3Blcmx5IGhhbmRsZXMgY29sdW1uIHJlb3JkZXJpbmcgYnkgbWFwcGluZyBjZWxscyBiYXNlZCBvblxuICAgKiBjb2x1bW4ga2V5cyByYXRoZXIgdGhhbiBpbmRpY2VzLCBlbnN1cmluZyBjZWxscyBmb2xsb3cgdGhlaXIgY29sdW1ucy5cbiAgICovXG4gIHByaXZhdGUgdXBkYXRlVmlzaWJsZUNlbGxHcmlkKCk6IHZvaWQge1xuICAgIGNvbnN0IGZ1bGxHcmlkID0gdGhpcy5nZXRBY3RpdmVDZWxsR3JpZCgpO1xuICAgIFxuICAgIC8vIEhhbmRsZSBlbXB0eSBncmlkXG4gICAgaWYgKCFmdWxsR3JpZCB8fCBmdWxsR3JpZC5sZW5ndGggPT09IDApIHtcbiAgICAgIHRoaXMudmlzaWJsZUNlbGxHcmlkID0gW107XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIFxuICAgIC8vIEJ1aWxkIGEgbWFwIG9mIGNvbHVtbktleSDihpIgY2VsbEluZGV4IGZvciB0aGUgY3VycmVudCBncmlkIHN0cnVjdHVyZVxuICAgIC8vIFRoaXMgYWxsb3dzIHVzIHRvIGZpbmQgY2VsbHMgYnkgY29sdW1uIGtleSByZWdhcmRsZXNzIG9mIHRoZWlyIGN1cnJlbnQgcG9zaXRpb25cbiAgICBjb25zdCBrZXlUb0luZGV4TWFwID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgICBmdWxsR3JpZFswXT8uZm9yRWFjaCgoY2VsbCwgaW5kZXgpID0+IHtcbiAgICAgIGlmIChjZWxsKSB7XG4gICAgICAgIGNvbnN0IGNvbHVtbkNvbmZpZyA9IGNlbGwuZ2V0Q29sdW1uQ29uZmlnKCk7XG4gICAgICAgIGtleVRvSW5kZXhNYXAuc2V0KGNvbHVtbkNvbmZpZy5rZXksIGluZGV4KTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBcbiAgICAvLyBSZW9yZGVyIGNlbGxzIHRvIG1hdGNoIHRoZSB2aXNpYmxlQ29sdW1ucyBvcmRlclxuICAgIC8vIFRoaXMgZW5zdXJlcyB0aGF0IHdoZW4gY29sdW1ucyBhcmUgbW92ZWQsIHRoZSBjZWxsIGRhdGEgZm9sbG93c1xuICAgIHRoaXMudmlzaWJsZUNlbGxHcmlkID0gZnVsbEdyaWQubWFwKHJvdyA9PiB7XG4gICAgICByZXR1cm4gdGhpcy52aXNpYmxlQ29sdW1uc1xuICAgICAgICAubWFwKGNvbCA9PiB7XG4gICAgICAgICAgY29uc3QgY2VsbEluZGV4ID0ga2V5VG9JbmRleE1hcC5nZXQoY29sLmtleSk7XG4gICAgICAgICAgcmV0dXJuIGNlbGxJbmRleCAhPT0gdW5kZWZpbmVkID8gcm93W2NlbGxJbmRleF0gOiB1bmRlZmluZWQ7XG4gICAgICAgIH0pXG4gICAgICAgIC5maWx0ZXIoKGNlbGwpOiBjZWxsIGlzIENlbGw8YW55PiA9PiBjZWxsICE9PSB1bmRlZmluZWQpO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSB0aGUgdmlzaWJsZSBjb2x1bW5zIGJhc2VkIG9uIGN1cnJlbnQgdmlzaWJpbGl0eVxuICAgKiBDYWxsZWQgb25seSB3aGVuIHZpc2liaWxpdHkgYWN0dWFsbHkgY2hhbmdlc1xuICAgKi9cbiAgcHJpdmF0ZSB1cGRhdGVWaXNpYmxlQ29sdW1ucygpOiB2b2lkIHtcbiAgICBjb25zdCBhbGxDb2x1bW5zID0gdGhpcy5nZXRBY3RpdmVDb2x1bW5zKCk7XG4gICAgdGhpcy52aXNpYmxlQ29sdW1ucyA9IGFsbENvbHVtbnMuZmlsdGVyKGNvbCA9PiBjb2wudmlzaWJsZSAhPT0gZmFsc2UpO1xuICAgIFxuICAgIC8vIFJlY2FsY3VsYXRlIHN0aWNreSBvZmZzZXRzIGZvciB2aXNpYmxlIGNvbHVtbnMgb25seVxuICAgIHRoaXMucmVjYWxjdWxhdGVWaXNpYmxlU3RpY2t5T2Zmc2V0cyh0aGlzLnZpc2libGVDb2x1bW5zKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYm90aCB2aXNpYmxlIGNvbHVtbnMgYW5kIGNlbGwgZ3JpZFxuICAgKiBDYWxsIHRoaXMgd2hlbmV2ZXIgZGF0YSBvciB2aXNpYmlsaXR5IGNoYW5nZXNcbiAgICovXG4gIHByaXZhdGUgdXBkYXRlVmlzaWJsZURhdGEoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVWaXNpYmxlQ29sdW1ucygpO1xuICAgIHRoaXMudXBkYXRlVmlzaWJsZUNlbGxHcmlkKCk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgYWN0aXZlIGNvbHVtbnMgKGZyb20gY29uZmlnIG9yIGxlZ2FjeSBpbnB1dClcbiAgICovXG4gIGdldEFjdGl2ZUNvbHVtbnMoKTogQ29sdW1uQ29uZmlnPGFueT5bXSB7XG4gICAgcmV0dXJuIHRoaXMubWVyZ2VkQ29uZmlnLmNvbHVtbnM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHZpc2libGUgY29sdW1ucyAoZmlsdGVyZWQgYnkgdmlzaWJpbGl0eSBwcm9wZXJ0eSlcbiAgICogQWxzbyByZWNhbGN1bGF0ZXMgc3RpY2t5IG9mZnNldHMgYmFzZWQgb24gdmlzaWJsZSBjb2x1bW5zIG9ubHlcbiAgICovXG4gIGdldFZpc2libGVDb2x1bW5zKCk6IENvbHVtbkNvbmZpZzxhbnk+W10ge1xuICAgIGNvbnN0IGFsbENvbHVtbnMgPSB0aGlzLmdldEFjdGl2ZUNvbHVtbnMoKTtcbiAgICBjb25zdCB2aXNpYmxlQ29sdW1ucyA9IGFsbENvbHVtbnMuZmlsdGVyKGNvbCA9PiBjb2wudmlzaWJsZSAhPT0gZmFsc2UpOyAvLyBEZWZhdWx0IHRvIHRydWUgaWYgbm90IHNldFxuICAgIFxuICAgIC8vIFJlY2FsY3VsYXRlIHN0aWNreSBvZmZzZXRzIGZvciB2aXNpYmxlIGNvbHVtbnMgb25seVxuICAgIHRoaXMucmVjYWxjdWxhdGVWaXNpYmxlU3RpY2t5T2Zmc2V0cyh2aXNpYmxlQ29sdW1ucyk7XG4gICAgXG4gICAgcmV0dXJuIHZpc2libGVDb2x1bW5zO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlY2FsY3VsYXRlIHN0aWNreSBvZmZzZXRzIGJhc2VkIG9uIHZpc2libGUgY29sdW1ucyBvbmx5XG4gICAqIFRoaXMgZW5zdXJlcyBjb3JyZWN0IHBvc2l0aW9uaW5nIHdoZW4gY29sdW1ucyBhcmUgaGlkZGVuXG4gICAqL1xuICBwcml2YXRlIHJlY2FsY3VsYXRlVmlzaWJsZVN0aWNreU9mZnNldHModmlzaWJsZUNvbHVtbnM6IENvbHVtbkNvbmZpZzxhbnk+W10pOiB2b2lkIHtcbiAgICAvLyBDYWxjdWxhdGUgbGVmdCBzdGlja3kgb2Zmc2V0c1xuICAgIC8vIEFjY291bnQgZm9yIHJvdyBudW1iZXIgY29sdW1uIHdpZHRoIGlmIHNob3duXG4gICAgbGV0IGxlZnRPZmZzZXQgPSB0aGlzLm1lcmdlZENvbmZpZy5zaG93Um93TnVtYmVyID8gMzAgOiAwO1xuICAgIHZpc2libGVDb2x1bW5zLmZvckVhY2goY29sID0+IHtcbiAgICAgIGlmIChjb2wuc3RpY2t5ID09PSAnbGVmdCcpIHtcbiAgICAgICAgKGNvbCBhcyBhbnkpLnN0aWNreU9mZnNldCA9IGxlZnRPZmZzZXQ7XG4gICAgICAgIGxlZnRPZmZzZXQgKz0gKGNvbC53aWR0aCBhcyBudW1iZXIpIHx8IDEwMDtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIENhbGN1bGF0ZSByaWdodCBzdGlja3kgb2Zmc2V0c1xuICAgIGxldCByaWdodE9mZnNldCA9IDA7XG4gICAgZm9yIChsZXQgaSA9IHZpc2libGVDb2x1bW5zLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICBjb25zdCBjb2wgPSB2aXNpYmxlQ29sdW1uc1tpXTtcbiAgICAgIGlmIChjb2wuc3RpY2t5ID09PSAncmlnaHQnKSB7XG4gICAgICAgIChjb2wgYXMgYW55KS5zdGlja3lPZmZzZXQgPSByaWdodE9mZnNldDtcbiAgICAgICAgcmlnaHRPZmZzZXQgKz0gKGNvbC53aWR0aCBhcyBudW1iZXIpIHx8IDEwMDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBvbkNlbGxDaGFuZ2UoZXZlbnQ6IENlbGxDaGFuZ2VFdmVudCk6IHZvaWQge1xuICAgIHRoaXMuY2VsbENoYW5nZS5lbWl0KGV2ZW50KTtcbiAgfVxuXG4gIG9uQ29sdW1uUmVzaXplZChldmVudDogQ29sdW1uUmVzaXplRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBSZWNhbGN1bGF0ZSBzdGlja3kgb2Zmc2V0cyBhZnRlciByZXNpemVcbiAgICBjb25zdCByb3dOdW1iZXJXaWR0aCA9IHRoaXMubWVyZ2VkQ29uZmlnLnNob3dSb3dOdW1iZXIgPyAzMCA6IDA7XG4gICAgY29uc3Qgc2V0dGluZ3NDb2x1bW5XaWR0aCA9IHRoaXMuaGFzUm93QWN0aW9ucygpID8gMzIgOiAwO1xuICAgIHRoaXMuZ2V0QWN0aXZlVGFibGVTdGF0ZSgpLmNhbGN1bGF0ZVN0aWNreU9mZnNldHMocm93TnVtYmVyV2lkdGgsIHNldHRpbmdzQ29sdW1uV2lkdGgpO1xuICAgIFxuICAgIC8vIEVtaXQgdG8gcGFyZW50XG4gICAgdGhpcy5jb2x1bW5SZXNpemVkLmVtaXQoZXZlbnQpO1xuICB9XG5cbiAgb25Db2x1bW5Nb3ZlZChldmVudDoge2NvbHVtbktleTogc3RyaW5nLCBkaXJlY3Rpb246ICdsZWZ0JyB8ICdyaWdodCd9KTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1ucyA9IHRoaXMuZ2V0QWN0aXZlQ29sdW1ucygpO1xuICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IGNvbHVtbnMuZmluZEluZGV4KGMgPT4gYy5rZXkgPT09IGV2ZW50LmNvbHVtbktleSk7XG4gICAgaWYgKGN1cnJlbnRJbmRleCA9PT0gLTEpIHJldHVybjtcbiAgICBcbiAgICAvLyBDYWxjdWxhdGUgdGFyZ2V0IGluZGV4XG4gICAgY29uc3QgdGFyZ2V0SW5kZXggPSBldmVudC5kaXJlY3Rpb24gPT09ICdsZWZ0JyBcbiAgICAgID8gY3VycmVudEluZGV4IC0gMSBcbiAgICAgIDogY3VycmVudEluZGV4ICsgMTtcbiAgICBcbiAgICAvLyBDaGVjayBib3VuZHNcbiAgICBpZiAodGFyZ2V0SW5kZXggPCAwIHx8IHRhcmdldEluZGV4ID49IGNvbHVtbnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIFxuICAgIC8vIFN3YXAgY29sdW1uc1xuICAgIFtjb2x1bW5zW2N1cnJlbnRJbmRleF0sIGNvbHVtbnNbdGFyZ2V0SW5kZXhdXSA9IFxuICAgIFtjb2x1bW5zW3RhcmdldEluZGV4XSwgY29sdW1uc1tjdXJyZW50SW5kZXhdXTtcbiAgICBcbiAgICAvLyBVcGRhdGUgVGFibGVTdGF0ZSB3aXRoIG5ldyBjb2x1bW4gb3JkZXJcbiAgICB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS51cGRhdGVDb2x1bW5zKGNvbHVtbnMpO1xuICAgIHRoaXMuY29sdW1uTW92ZWQuZW1pdCh7XG4gICAgICBjb2x1bW5LZXk6IGV2ZW50LmNvbHVtbktleSxcbiAgICAgIGRpcmVjdGlvbjogZXZlbnQuZGlyZWN0aW9uLFxuICAgICAgb2xkSW5kZXg6IGN1cnJlbnRJbmRleCxcbiAgICAgIG5ld0luZGV4OiB0YXJnZXRJbmRleCxcbiAgICAgIGNvbHVtbjogY29sdW1uc1tjdXJyZW50SW5kZXhdXG4gICAgfSk7XG4gICAgLy8gRm9yY2UgdmlydHVhbCBzY3JvbGwgdG8gcmUtcmVuZGVyIGJ5IHJlLWVtaXR0aW5nIGN1cnJlbnQgc3RhdGVcbiAgICAvLyBUaGlzIGVuc3VyZXMgdmlzaWJsZVJvd3MkIHBpY2tzIHVwIHRoZSB1cGRhdGVkIHZpc2libGVDZWxsR3JpZFxuICAgIGlmICh0aGlzLmlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKSkge1xuICAgICAgY29uc3QgY3VycmVudFN0YXRlID0gdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLnZhbHVlO1xuICAgICAgaWYgKGN1cnJlbnRTdGF0ZSkge1xuICAgICAgICB0aGlzLnZpcnR1YWxTY3JvbGxTdGF0ZSQubmV4dCh7Li4uY3VycmVudFN0YXRlfSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1vdmUgY29sdW1uIHRvIHBvc2l0aW9uIGp1c3QgYmVmb3JlIHJpZ2h0IHN0aWNreSBjb2x1bW5zICh1c2VkIHdoZW4gcGlubmluZyByaWdodClcbiAgICovXG4gIHByaXZhdGUgbW92ZUNvbHVtblRvRW5kKGNvbHVtbktleTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgY29sdW1ucyA9IHRoaXMuZ2V0QWN0aXZlQ29sdW1ucygpO1xuICAgIGNvbnN0IGN1cnJlbnRJbmRleCA9IGNvbHVtbnMuZmluZEluZGV4KGMgPT4gYy5rZXkgPT09IGNvbHVtbktleSk7XG4gICAgaWYgKGN1cnJlbnRJbmRleCA9PT0gLTEpIHJldHVybjtcbiAgICBcbiAgICAvLyBGaW5kIHRoZSBpbmRleCBvZiB0aGUgZmlyc3QgcmlnaHQtc3RpY2t5IGNvbHVtblxuICAgIGNvbnN0IGZpcnN0UmlnaHRTdGlja3lJbmRleCA9IGNvbHVtbnMuZmluZEluZGV4KGMgPT4gYy5zdGlja3kgPT09ICdyaWdodCcpO1xuICAgIFxuICAgIC8vIERldGVybWluZSB0YXJnZXQgaW5kZXg6IGp1c3QgYmVmb3JlIGZpcnN0IHJpZ2h0LXN0aWNreSwgb3IgYXQgZW5kIGlmIG5vbmUgZXhpc3RcbiAgICBjb25zdCB0YXJnZXRJbmRleCA9IGZpcnN0UmlnaHRTdGlja3lJbmRleCAhPT0gLTEgPyBmaXJzdFJpZ2h0U3RpY2t5SW5kZXggOiBjb2x1bW5zLmxlbmd0aDtcbiAgICBcbiAgICAvLyBJZiBhbHJlYWR5IGF0IHRhcmdldCBwb3NpdGlvbiwgbm8gbmVlZCB0byBtb3ZlXG4gICAgaWYgKGN1cnJlbnRJbmRleCA9PT0gdGFyZ2V0SW5kZXggfHwgY3VycmVudEluZGV4ID09PSB0YXJnZXRJbmRleCAtIDEpIHJldHVybjtcbiAgICBcbiAgICAvLyBSZW1vdmUgY29sdW1uIGZyb20gY3VycmVudCBwb3NpdGlvblxuICAgIGNvbnN0IFtjb2x1bW5dID0gY29sdW1ucy5zcGxpY2UoY3VycmVudEluZGV4LCAxKTtcbiAgICBcbiAgICAvLyBBZGp1c3QgdGFyZ2V0IGluZGV4IGlmIHdlIHJlbW92ZWQgYW4gZWxlbWVudCBiZWZvcmUgaXRcbiAgICBjb25zdCBhZGp1c3RlZFRhcmdldEluZGV4ID0gY3VycmVudEluZGV4IDwgdGFyZ2V0SW5kZXggPyB0YXJnZXRJbmRleCAtIDEgOiB0YXJnZXRJbmRleDtcbiAgICBcbiAgICAvLyBJbnNlcnQgYXQgdGFyZ2V0IHBvc2l0aW9uIChiZWZvcmUgZmlyc3QgcmlnaHQtc3RpY2t5IGNvbHVtbiwgb3IgYXQgZW5kKVxuICAgIGNvbHVtbnMuc3BsaWNlKGFkanVzdGVkVGFyZ2V0SW5kZXgsIDAsIGNvbHVtbik7XG4gICAgXG4gICAgLy8gVXBkYXRlIFRhYmxlU3RhdGUgd2l0aCBuZXcgY29sdW1uIG9yZGVyXG4gICAgdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkudXBkYXRlQ29sdW1ucyhjb2x1bW5zKTtcbiAgICBcbiAgICAvLyBGb3JjZSB2aXJ0dWFsIHNjcm9sbCB0byByZS1yZW5kZXJcbiAgICBpZiAodGhpcy5pc1ZpcnR1YWxTY3JvbGxFbmFibGVkKCkpIHtcbiAgICAgIGNvbnN0IGN1cnJlbnRTdGF0ZSA9IHRoaXMudmlydHVhbFNjcm9sbFN0YXRlJC52YWx1ZTtcbiAgICAgIGlmIChjdXJyZW50U3RhdGUpIHtcbiAgICAgICAgdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLm5leHQoey4uLmN1cnJlbnRTdGF0ZX0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY3VtdWxhdGl2ZSBsZWZ0IG9mZnNldCBmb3IgYSBzdGlja3kgY29sdW1uIG9uIHRoZSBsZWZ0IHNpZGVcbiAgICovXG4gIGdldFN0aWNreUxlZnRPZmZzZXQoY29sdW1uS2V5OiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGNvbnN0IGNvbHVtbnMgPSB0aGlzLmdldEFjdGl2ZUNvbHVtbnMoKTtcbiAgICBsZXQgb2Zmc2V0ID0gMDtcbiAgICBmb3IgKGNvbnN0IGNvbCBvZiBjb2x1bW5zKSB7XG4gICAgICBpZiAoY29sLmtleSA9PT0gY29sdW1uS2V5KSBicmVhaztcbiAgICAgIGlmIChjb2wuc3RpY2t5ID09PSAnbGVmdCcpIHtcbiAgICAgICAgb2Zmc2V0ICs9IChjb2wud2lkdGggYXMgbnVtYmVyKSB8fCAxMDA7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvZmZzZXQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGN1bXVsYXRpdmUgcmlnaHQgb2Zmc2V0IGZvciBhIHN0aWNreSBjb2x1bW4gb24gdGhlIHJpZ2h0IHNpZGVcbiAgICovXG4gIGdldFN0aWNreVJpZ2h0T2Zmc2V0KGNvbHVtbktleTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5nZXRBY3RpdmVDb2x1bW5zKCk7XG4gICAgbGV0IG9mZnNldCA9IDA7XG4gICAgY29uc3QgY29sSW5kZXggPSBjb2x1bW5zLmZpbmRJbmRleChjID0+IGMua2V5ID09PSBjb2x1bW5LZXkpO1xuICAgIGZvciAobGV0IGkgPSBjb2xJbmRleCArIDE7IGkgPCBjb2x1bW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBjb2wgPSBjb2x1bW5zW2ldO1xuICAgICAgaWYgKGNvbC5zdGlja3kgPT09ICdyaWdodCcpIHtcbiAgICAgICAgb2Zmc2V0ICs9IChjb2wud2lkdGggYXMgbnVtYmVyKSB8fCAxMDA7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBvZmZzZXQ7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0b3AgcGFnaW5hdGlvbiBzaG91bGQgYmUgc2hvd25cbiAgICovXG4gIHNob3dUb3BQYWdpbmF0aW9uKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1lcmdlZENvbmZpZy5wYWdpbmF0aW9uPy5lbmFibGVkID09IHRydWUgJiZcbiAgICAgICAgICAgdGhpcy5tZXJnZWRDb25maWcucGFnaW5hdGlvbj8uc2hvd1RvcENvbnRyb2xzID09PSB0cnVlO1xuICB9XG4gIFxuICAvKipcbiAgICogQ2hlY2sgaWYgYm90dG9tIHBhZ2luYXRpb24gc2hvdWxkIGJlIHNob3duXG4gICAqL1xuICBzaG93Qm90dG9tUGFnaW5hdGlvbigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tZXJnZWRDb25maWcucGFnaW5hdGlvbj8uZW5hYmxlZCA9PSB0cnVlICYmXG4gICAgICAgICAgICh0aGlzLm1lcmdlZENvbmZpZy5wYWdpbmF0aW9uPy5zaG93Qm90dG9tQ29udHJvbHMgPz8gdHJ1ZSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBWYWxpZGF0ZSB0YWJsZSBjb25maWd1cmF0aW9uXG4gICAqIEBwYXJhbSBjb25maWcgVGFibGUgY29uZmlndXJhdGlvbiB0byB2YWxpZGF0ZVxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZUNvbmZpZ3VyYXRpb24oY29uZmlnOiBUYWJsZUNvbmZpZyk6IHZvaWQge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuc2NoZW1hVmFsaWRhdG9yLnZhbGlkYXRlKGNvbmZpZywgdHJ1ZSwgZmFsc2UpOyAvLyBEaXNhYmxlIGxvZ2dpbmcgaGVyZSwgd2UnbGwgbG9nIG1hbnVhbGx5IHdpdGggY29udGV4dFxuICAgIFxuICAgIGlmICghcmVzdWx0LnZhbGlkICYmIHJlc3VsdC5lcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gRW1pdCB2YWxpZGF0aW9uIGVycm9yc1xuICAgICAgdGhpcy5jb25maWdWYWxpZGF0aW9uRXJyb3JzLmVtaXQocmVzdWx0LmVycm9ycyk7XG4gICAgICBcbiAgICAgIC8vIExvZyB2YWxpZGF0aW9uIGVycm9ycyB3aXRoIGNvbnRleHRcbiAgICAgIGNvbnN0IGNvbmZpZ1NuaXBwZXQgPSBKU09OLnN0cmluZ2lmeShjb25maWcsIG51bGwsIDIpLnN1YnN0cmluZygwLCA1MDApOyAvLyBGaXJzdCA1MDAgY2hhcnMgb2YgY29uZmlnXG4gICAgICB0aGlzLmxvZ2dlci5sb2dWYWxpZGF0aW9uRXJyb3JzKHJlc3VsdC5lcnJvcnMsICdyZW5kZXJlcicsIHtcbiAgICAgICAgY29uZmlnU25pcHBldDogY29uZmlnU25pcHBldFxuICAgICAgfSk7XG4gICAgICBcbiAgICAgIC8vIExvZyB3YXJuaW5ncyB0byBjb25zb2xlIChkb24ndCBicmVhayByZW5kZXJpbmcpXG4gICAgICBjb25zb2xlLndhcm4oJ1NtYXJ0IFRhYmxlOiBDb25maWd1cmF0aW9uIHZhbGlkYXRpb24gZXJyb3JzIGRldGVjdGVkOicsIHJlc3VsdC5lcnJvcnMpO1xuICAgICAgcmVzdWx0LmVycm9ycy5mb3JFYWNoKGVycm9yID0+IHtcbiAgICAgICAgY29uc29sZS53YXJuKGAgIC0gJHtlcnJvci5maWVsZCB8fCBlcnJvci5wYXRofTogJHtlcnJvci5tZXNzYWdlfWApO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogSGFuZGxlIGFkZCBjb2x1bW4gYnV0dG9uIGNsaWNrXG4gICAqL1xuICBvbkFkZENvbHVtbkNsaWNrKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd0NvbHVtbk1vZGFsID0gdHJ1ZTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEhhbmRsZSBjb2x1bW4gY3JlYXRlZCBmcm9tIG1vZGFsXG4gICAqL1xuICBvbkNvbHVtbkNyZWF0ZWQoY29sdW1uOiBDb2x1bW5Db25maWcpOiB2b2lkIHtcbiAgICBjb25zdCBjb2x1bW5zID0gdGhpcy5nZXRBY3RpdmVDb2x1bW5zKCk7XG4gICAgY29uc3QgYWRkRXZlbnQ6IENvbHVtbkFkZEV2ZW50ID0ge1xuICAgICAgY29sdW1uOiBjb2x1bW4sXG4gICAgICBpbmRleDogY29sdW1ucy5sZW5ndGgsXG4gICAgICB0b3RhbENvbHVtbnM6IGNvbHVtbnMubGVuZ3RoICsgMVxuICAgIH07XG4gICAgXG4gICAgLy8gRW1pdCB0aGUgbmV3IGNvbHVtbiB0byBwYXJlbnQgY29tcG9uZW50XG4gICAgdGhpcy5jb2x1bW5BZGRlZC5lbWl0KGFkZEV2ZW50KTtcbiAgICBcbiAgICAvLyBDbG9zZSB0aGUgbW9kYWxcbiAgICB0aGlzLnNob3dDb2x1bW5Nb2RhbCA9IGZhbHNlO1xuICB9XG4gIFxuICAvKipcbiAgICogSGFuZGxlIG1vZGFsIGNhbmNlbGxlZFxuICAgKi9cbiAgb25Nb2RhbENhbmNlbGxlZCgpOiB2b2lkIHtcbiAgICB0aGlzLnNob3dDb2x1bW5Nb2RhbCA9IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHZpcnR1YWwgc2Nyb2xsIGlzIGVuYWJsZWRcbiAgICovXG4gIGlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWVyZ2VkQ29uZmlnLmRpc3BsYXk/LnZpcnR1YWxTY3JvbGw/LmVuYWJsZWQgPz8gZmFsc2U7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDaGVjayBpZiBjb2x1bW4gaXMgdGhlIGZpcnN0IHN0aWNreS1yaWdodCBjb2x1bW4gKGZvciBzaGFkb3cgc3R5bGluZylcbiAgICovXG4gIGlzRmlyc3RTdGlja3lSaWdodChjb2x1bW5LZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHN0aWNreVJpZ2h0Q29sdW1ucyA9IHRoaXMudmlzaWJsZUNvbHVtbnMuZmlsdGVyKGNvbCA9PiBjb2wuc3RpY2t5ID09PSAncmlnaHQnICYmICFjb2wua2V5LmluY2x1ZGVzKCdzZXR0aW5ncycpKTtcbiAgICByZXR1cm4gc3RpY2t5UmlnaHRDb2x1bW5zLmxlbmd0aCA+IDAgJiYgc3RpY2t5UmlnaHRDb2x1bW5zWzBdLmtleSA9PT0gY29sdW1uS2V5O1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHZpcnR1YWwgc2Nyb2xsIGl0ZW0gc2l6ZVxuICAgKi9cbiAgZ2V0VmlydHVhbFNjcm9sbEl0ZW1TaXplKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMubWVyZ2VkQ29uZmlnLmRpc3BsYXk/LnZpcnR1YWxTY3JvbGw/Lml0ZW1TaXplID8/IDQ4O1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHZpZXdwb3J0IGhlaWdodFxuICAgKi9cbiAgZ2V0VmlydHVhbFNjcm9sbFZpZXdwb3J0SGVpZ2h0KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMubWVyZ2VkQ29uZmlnLmRpc3BsYXk/LnZpcnR1YWxTY3JvbGw/LnZpZXdwb3J0SGVpZ2h0ID8/IDYwMDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEdldCBidWZmZXIgc2l6ZVxuICAgKi9cbiAgZ2V0VmlydHVhbFNjcm9sbEJ1ZmZlclNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5tZXJnZWRDb25maWcuZGlzcGxheT8udmlydHVhbFNjcm9sbD8uYnVmZmVyU2l6ZSA/PyA1O1xuICB9XG4gIFxuICAvKipcbiAgICogSW5pdGlhbGl6ZSB2aXJ0dWFsIHNjcm9sbCBzdGF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBpbml0aWFsaXplVmlydHVhbFNjcm9sbCgpOiB2b2lkIHtcbiAgICBjb25zdCBuZXdTdGF0ZSA9IHRoaXMudmlydHVhbFNjcm9sbFNlcnZpY2UuY2FsY3VsYXRlVmlzaWJsZVJhbmdlKHtcbiAgICAgIHNjcm9sbFRvcDogMCxcbiAgICAgIHZpZXdwb3J0SGVpZ2h0OiB0aGlzLmdldFZpcnR1YWxTY3JvbGxWaWV3cG9ydEhlaWdodCgpLFxuICAgICAgdG90YWxJdGVtczogdGhpcy52aXNpYmxlQ2VsbEdyaWQubGVuZ3RoLFxuICAgICAgaXRlbVNpemU6IHRoaXMuZ2V0VmlydHVhbFNjcm9sbEl0ZW1TaXplKCksXG4gICAgICBidWZmZXJTaXplOiB0aGlzLmdldFZpcnR1YWxTY3JvbGxCdWZmZXJTaXplKClcbiAgICB9KTtcbiAgICBcbiAgICB0aGlzLnZpcnR1YWxTY3JvbGxTdGF0ZSQubmV4dChuZXdTdGF0ZSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBTZXR1cCBzY3JvbGwgZXZlbnQgbGlzdGVuZXJcbiAgICovXG4gIHByaXZhdGUgc2V0dXBWaXJ0dWFsU2Nyb2xsTGlzdGVuZXIoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnNjcm9sbFZpZXdwb3J0KSByZXR1cm47XG4gICAgXG4gICAgY29uc3QgZWxlbWVudCA9IHRoaXMuc2Nyb2xsVmlld3BvcnQubmF0aXZlRWxlbWVudDtcbiAgICB0aGlzLnNjcm9sbENvbnRhaW5lciA9IGVsZW1lbnQ7XG4gICAgXG4gICAgdGhpcy5zY3JvbGxTdWJzY3JpcHRpb24gPSB0aGlzLnZpcnR1YWxTY3JvbGxTZXJ2aWNlXG4gICAgICAuY3JlYXRlU2Nyb2xsT2JzZXJ2YWJsZShlbGVtZW50KVxuICAgICAgLnN1YnNjcmliZShzY3JvbGxUb3AgPT4gdGhpcy5vblZpcnR1YWxTY3JvbGwoc2Nyb2xsVG9wKSk7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBIYW5kbGUgdmlydHVhbCBzY3JvbGwgZXZlbnRcbiAgICovXG4gIHByaXZhdGUgb25WaXJ0dWFsU2Nyb2xsKHNjcm9sbFRvcDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgbmV3U3RhdGUgPSB0aGlzLnZpcnR1YWxTY3JvbGxTZXJ2aWNlLmNhbGN1bGF0ZVZpc2libGVSYW5nZSh7XG4gICAgICBzY3JvbGxUb3AsXG4gICAgICB2aWV3cG9ydEhlaWdodDogdGhpcy5nZXRWaXJ0dWFsU2Nyb2xsVmlld3BvcnRIZWlnaHQoKSxcbiAgICAgIHRvdGFsSXRlbXM6IHRoaXMudmlzaWJsZUNlbGxHcmlkLmxlbmd0aCxcbiAgICAgIGl0ZW1TaXplOiB0aGlzLmdldFZpcnR1YWxTY3JvbGxJdGVtU2l6ZSgpLFxuICAgICAgYnVmZmVyU2l6ZTogdGhpcy5nZXRWaXJ0dWFsU2Nyb2xsQnVmZmVyU2l6ZSgpXG4gICAgfSk7XG4gICAgXG4gICAgdGhpcy52aXJ0dWFsU2Nyb2xsU3RhdGUkLm5leHQobmV3U3RhdGUpO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHJvdyBpbmRleCBmb3IgdHJhY2tpbmdcbiAgICovXG4gIGdldEFic29sdXRlUm93SW5kZXgocmVsYXRpdmVJbmRleDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBjdXJyZW50U3RhdGUgPSB0aGlzLnZpcnR1YWxTY3JvbGxTdGF0ZSQudmFsdWU7XG4gICAgaWYgKCFjdXJyZW50U3RhdGUpIHJldHVybiByZWxhdGl2ZUluZGV4O1xuICAgIHJldHVybiBjdXJyZW50U3RhdGUuc3RhcnRJbmRleCArIHJlbGF0aXZlSW5kZXg7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBUcmFja0J5IGZ1bmN0aW9uIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcbiAgICovXG4gIHRyYWNrQnlSb3dJbmRleCA9IChpbmRleDogbnVtYmVyLCByb3c6IENlbGw8YW55PltdKTogbnVtYmVyID0+IHtcbiAgICByZXR1cm4gdGhpcy5nZXRBYnNvbHV0ZVJvd0luZGV4KGluZGV4KTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIFNjcm9sbCB0byBzcGVjaWZpYyByb3cgcHJvZ3JhbW1hdGljYWxseVxuICAgKi9cbiAgc2Nyb2xsVG9Sb3coaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICghdGhpcy5zY3JvbGxDb250YWluZXIgfHwgIXRoaXMuaXNWaXJ0dWFsU2Nyb2xsRW5hYmxlZCgpKSByZXR1cm47XG4gICAgXG4gICAgY29uc3Qgc2Nyb2xsVG9wID0gaW5kZXggKiB0aGlzLmdldFZpcnR1YWxTY3JvbGxJdGVtU2l6ZSgpO1xuICAgIHRoaXMuc2Nyb2xsQ29udGFpbmVyLnNjcm9sbFRvcCA9IHNjcm9sbFRvcDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIENoZWNrIGlmIHJvdyBhY3Rpb25zIGFyZSBlbmFibGVkXG4gICAqL1xuICBoYXNSb3dBY3Rpb25zKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhISh0aGlzLm1lcmdlZENvbmZpZy5mZWF0dXJlcz8ucm93TWFuYWdlbWVudD8uYWN0aW9ucyAmJiBcbiAgICAgICAgICAgICAgdGhpcy5tZXJnZWRDb25maWcuZmVhdHVyZXMucm93TWFuYWdlbWVudC5hY3Rpb25zLmxlbmd0aCA+IDApO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IHJvdyBhY3Rpb25zIGZyb20gY29uZmlnXG4gICAqL1xuICBnZXRSb3dBY3Rpb25zKCk6IFJvd0FjdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5tZXJnZWRDb25maWcuZmVhdHVyZXM/LnJvd01hbmFnZW1lbnQ/LmFjdGlvbnMgfHwgW107XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBHZXQgcm93IGRhdGEgZnJvbSBjZWxsIGdyaWRcbiAgICovXG4gIGdldFJvd0RhdGEocm93SW5kZXg6IG51bWJlcik6IGFueSB7XG4gICAgY29uc3QgY2VsbEdyaWQgPSB0aGlzLmdldEFjdGl2ZUNlbGxHcmlkKCk7XG4gICAgaWYgKCFjZWxsR3JpZCB8fCByb3dJbmRleCA8IDAgfHwgcm93SW5kZXggPj0gY2VsbEdyaWQubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgXG4gICAgY29uc3Qgcm93ID0gY2VsbEdyaWRbcm93SW5kZXhdO1xuICAgIGlmICghcm93IHx8IHJvdy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBcbiAgICAvLyBHZXQgcmF3IGRhdGEgZnJvbSBmaXJzdCBjZWxsIChhbGwgY2VsbHMgaW4gYSByb3cgc2hhcmUgdGhlIHNhbWUgcm93RGF0YSlcbiAgICByZXR1cm4gcm93WzBdPy5nZXRSb3dEYXRhKCkgfHwgbnVsbDtcbiAgfVxuICBcbiAgLyoqXG4gICAqIE9wZW4gcm93IGFjdGlvbnMgZHJvcGRvd25cbiAgICovXG4gIG9wZW5Sb3dBY3Rpb25zRHJvcGRvd24oZXZlbnQ6IE1vdXNlRXZlbnQsIHJvd0RhdGE6IGFueSwgcm93SW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgXG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQuY3VycmVudFRhcmdldCBhcyBIVE1MRWxlbWVudDtcbiAgICBjb25zdCByZWN0ID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIFxuICAgIC8vIENhbGN1bGF0ZSBwb3NpdGlvbiAoYmVsb3cgdGhlIGJ1dHRvbiBieSBkZWZhdWx0KVxuICAgIGNvbnN0IHBvc2l0aW9uID0ge1xuICAgICAgeDogcmVjdC5sZWZ0LFxuICAgICAgeTogcmVjdC5ib3R0b20gKyA0IC8vIDRweCBnYXBcbiAgICB9O1xuICAgIFxuICAgIC8vIENyZWF0ZSBjb250ZXh0XG4gICAgY29uc3QgY29udGV4dDogUm93QWN0aW9uQ29udGV4dCA9IHtcbiAgICAgIHJvd0RhdGEsXG4gICAgICByb3dJbmRleCxcbiAgICAgIGFjdGlvbnM6IHRoaXMuZ2V0Um93QWN0aW9ucygpXG4gICAgfTtcbiAgICBcbiAgICAvLyBVcGRhdGUgZHJvcGRvd24gc3RhdGVcbiAgICB0aGlzLmRyb3Bkb3duU3RhdGUgPSB7XG4gICAgICBpc09wZW46IHRydWUsXG4gICAgICBwb3NpdGlvbixcbiAgICAgIGNvbnRleHRcbiAgICB9O1xuICAgIFxuICAgIC8vIERpc2FibGUgYm9keSBzY3JvbGxcbiAgICBkb2N1bWVudC5ib2R5LnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gICAgXG4gICAgLy8gSWYgdmlydHVhbCBzY3JvbGwgaXMgZW5hYmxlZCwgYWRkIHNjcm9sbCBsaXN0ZW5lciB0byBjbG9zZSBkcm9wZG93blxuICAgIGlmICh0aGlzLmlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKSAmJiB0aGlzLnNjcm9sbENvbnRhaW5lcikge1xuICAgICAgY29uc3Qgc2Nyb2xsTGlzdGVuZXIgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xvc2VSb3dBY3Rpb25zRHJvcGRvd24oKTtcbiAgICAgICAgdGhpcy5zY3JvbGxDb250YWluZXI/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHNjcm9sbExpc3RlbmVyKTtcbiAgICAgIH07XG4gICAgICB0aGlzLnNjcm9sbENvbnRhaW5lci5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzY3JvbGxMaXN0ZW5lciwgeyBvbmNlOiB0cnVlIH0pO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIENsb3NlIHJvdyBhY3Rpb25zIGRyb3Bkb3duXG4gICAqL1xuICBjbG9zZVJvd0FjdGlvbnNEcm9wZG93bigpOiB2b2lkIHtcbiAgICB0aGlzLmRyb3Bkb3duU3RhdGUgPSB7XG4gICAgICBpc09wZW46IGZhbHNlLFxuICAgICAgcG9zaXRpb246IHsgeDogMCwgeTogMCB9LFxuICAgICAgY29udGV4dDogbnVsbFxuICAgIH07XG4gICAgXG4gICAgLy8gUmUtZW5hYmxlIGJvZHkgc2Nyb2xsXG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5vdmVyZmxvdyA9ICcnO1xuICB9XG4gIFxuICAvKipcbiAgICogSGFuZGxlIHJvdyBhY3Rpb24gY2xpY2tlZFxuICAgKi9cbiAgb25Sb3dBY3Rpb25DbGlja2VkKGV2ZW50OiBSb3dBY3Rpb25FdmVudCk6IHZvaWQge1xuICAgIC8vIEV4ZWN1dGUgYWN0aW9uIGNhbGxiYWNrIGlmIHByb3ZpZGVkXG4gICAgaWYgKGV2ZW50LmFjdGlvbi5hY3Rpb24pIHtcbiAgICAgIGV2ZW50LmFjdGlvbi5hY3Rpb24oZXZlbnQucm93RGF0YSwgZXZlbnQucm93SW5kZXgpO1xuICAgIH1cbiAgICBcbiAgICAvLyBFbWl0IGV2ZW50IHRvIHBhcmVudFxuICAgIHRoaXMucm93QWN0aW9uLmVtaXQoZXZlbnQpO1xuICAgIFxuICAgIC8vIENsb3NlIGRyb3Bkb3duXG4gICAgdGhpcy5jbG9zZVJvd0FjdGlvbnNEcm9wZG93bigpO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBDT0xVTU4gTUVOVSBBQ1RJT05TXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogT3BlbiBjb2x1bW4gbWVudSBkcm9wZG93blxuICAgKi9cbiAgb3BlbkNvbHVtbk1lbnUoZXZlbnQ6IE1vdXNlRXZlbnQsIGNvbHVtbjogQ29sdW1uQ29uZmlnPGFueT4sIGNvbHVtbkluZGV4OiBudW1iZXIsIGlzRmlyc3Q6IGJvb2xlYW4sIGlzTGFzdDogYm9vbGVhbik6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBjb25zdCB0YXJnZXQgPSBldmVudC5jdXJyZW50VGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIGNvbnN0IHJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAvLyBDYWxjdWxhdGUgcG9zaXRpb24gKGJlbG93IHRoZSBidXR0b24gYnkgZGVmYXVsdClcbiAgICBjb25zdCBwb3NpdGlvbiA9IHtcbiAgICAgIHg6IHJlY3QubGVmdCxcbiAgICAgIHk6IHJlY3QuYm90dG9tICsgNCAvLyA0cHggZ2FwXG4gICAgfTtcblxuICAgIC8vIENyZWF0ZSBjb250ZXh0XG4gICAgY29uc3QgY29udGV4dDogQ29sdW1uQWN0aW9uQ29udGV4dCA9IHtcbiAgICAgIGNvbHVtbixcbiAgICAgIGNvbHVtbkluZGV4LFxuICAgICAgaXNGaXJzdENvbHVtbjogaXNGaXJzdCxcbiAgICAgIGlzTGFzdENvbHVtbjogaXNMYXN0LFxuICAgICAgdGFibGVTdGF0ZTogdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCksXG4gICAgICBhY3Rpb25zOiB0aGlzLmdldENvbHVtbkFjdGlvbnMoY29sdW1uLCBjb2x1bW5JbmRleCwgaXNGaXJzdCwgaXNMYXN0KVxuICAgIH07XG5cbiAgICAvLyBVcGRhdGUgY29sdW1uIG1lbnUgc3RhdGVcbiAgICB0aGlzLmNvbHVtbk1lbnVTdGF0ZSA9IHtcbiAgICAgIGlzT3BlbjogdHJ1ZSxcbiAgICAgIHBvc2l0aW9uLFxuICAgICAgY29udGV4dFxuICAgIH07XG5cbiAgICAvLyBEaXNhYmxlIGJvZHkgc2Nyb2xsXG4gICAgZG9jdW1lbnQuYm9keS5zdHlsZS5vdmVyZmxvdyA9ICdoaWRkZW4nO1xuXG4gICAgLy8gSWYgdmlydHVhbCBzY3JvbGwgaXMgZW5hYmxlZCwgYWRkIHNjcm9sbCBsaXN0ZW5lciB0byBjbG9zZSBkcm9wZG93blxuICAgIGlmICh0aGlzLmlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKSAmJiB0aGlzLnNjcm9sbENvbnRhaW5lcikge1xuICAgICAgY29uc3Qgc2Nyb2xsTGlzdGVuZXIgPSAoKSA9PiB7XG4gICAgICAgIHRoaXMuY2xvc2VDb2x1bW5NZW51KCk7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udGFpbmVyPy5yZW1vdmVFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBzY3JvbGxMaXN0ZW5lcik7XG4gICAgICB9O1xuICAgICAgdGhpcy5zY3JvbGxDb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc2Nyb2xsTGlzdGVuZXIsIHsgb25jZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2xvc2UgY29sdW1uIG1lbnUgZHJvcGRvd25cbiAgICovXG4gIGNsb3NlQ29sdW1uTWVudSgpOiB2b2lkIHtcbiAgICB0aGlzLmNvbHVtbk1lbnVTdGF0ZSA9IHtcbiAgICAgIGlzT3BlbjogZmFsc2UsXG4gICAgICBwb3NpdGlvbjogeyB4OiAwLCB5OiAwIH0sXG4gICAgICBjb250ZXh0OiBudWxsXG4gICAgfTtcblxuICAgIC8vIFJlLWVuYWJsZSBib2R5IHNjcm9sbFxuICAgIGRvY3VtZW50LmJvZHkuc3R5bGUub3ZlcmZsb3cgPSAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBIYW5kbGUgY29sdW1uIGFjdGlvbiBjbGlja2VkXG4gICAqL1xuICBvbkNvbHVtbkFjdGlvbkNsaWNrZWQoZXZlbnQ6IENvbHVtbkFjdGlvbkV2ZW50KTogdm9pZCB7XG4gICAgLy8gRXhlY3V0ZSBhY3Rpb24gY2FsbGJhY2sgaWYgcHJvdmlkZWRcbiAgICBpZiAoZXZlbnQuYWN0aW9uLmFjdGlvbikge1xuICAgICAgZXZlbnQuYWN0aW9uLmFjdGlvbihldmVudC5jb2x1bW4sIGV2ZW50LmNvbHVtbkluZGV4KTtcbiAgICB9XG5cbiAgICAvLyBEb24ndCBjbG9zZSBtZW51IGlmIGl0J3MgYSBmaWx0ZXIgYWN0aW9uIChmaWx0ZXIgbmVlZHMgbWVudSB0byBzdGF5IG9wZW4pXG4gICAgaWYgKGV2ZW50LmFjdGlvbi5pZCA9PT0gJ2ZpbHRlcicpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDbG9zZSBkcm9wZG93biBmb3Igb3RoZXIgYWN0aW9uc1xuICAgIHRoaXMuY2xvc2VDb2x1bW5NZW51KCk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGNvbHVtbiBhY3Rpb25zIChidWlsdC1pbiArIGN1c3RvbSlcbiAgICovXG4gIHByaXZhdGUgZ2V0Q29sdW1uQWN0aW9ucyhcbiAgICBjb2x1bW46IENvbHVtbkNvbmZpZzxhbnk+LCBcbiAgICBjb2x1bW5JbmRleDogbnVtYmVyLCBcbiAgICBpc0ZpcnN0OiBib29sZWFuLCBcbiAgICBpc0xhc3Q6IGJvb2xlYW5cbiAgKTogQ29sdW1uQWN0aW9uW10ge1xuICAgIGNvbnN0IGFjdGlvbnM6IENvbHVtbkFjdGlvbltdID0gW107XG4gICAgXG4gICAgLy8gQWRkIGJ1aWx0LWluIGFjdGlvbnMgaWYgZW5hYmxlZCAoZGVmYXVsdDogdHJ1ZSlcbiAgICBjb25zdCBpbmNsdWRlQnVpbHRJbiA9IGNvbHVtbi5pbmNsdWRlQnVpbHRJbkFjdGlvbnMgPz8gdHJ1ZTtcbiAgICBpZiAoaW5jbHVkZUJ1aWx0SW4pIHtcbiAgICAgIGFjdGlvbnMucHVzaCguLi50aGlzLmdldEJ1aWx0SW5Db2x1bW5BY3Rpb25zKGNvbHVtbiwgY29sdW1uSW5kZXgsIGlzRmlyc3QsIGlzTGFzdCkpO1xuICAgIH1cbiAgICBcbiAgICAvLyBBZGQgY3VzdG9tIGNvbHVtbiBhY3Rpb25zIGZyb20gY29uZmlnXG4gICAgaWYgKGNvbHVtbi5jb2x1bW5BY3Rpb25zICYmIGNvbHVtbi5jb2x1bW5BY3Rpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIGFjdGlvbnMucHVzaCguLi5jb2x1bW4uY29sdW1uQWN0aW9ucyk7XG4gICAgfVxuICAgIFxuICAgIHJldHVybiBhY3Rpb25zO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBidWlsdC1pbiBjb2x1bW4gYWN0aW9ucyAoc29ydCwgZmlsdGVyLCBwaW4sIG1vdmUpXG4gICAqL1xuICBwcml2YXRlIGdldEJ1aWx0SW5Db2x1bW5BY3Rpb25zKFxuICAgIGNvbHVtbjogQ29sdW1uQ29uZmlnPGFueT4sXG4gICAgY29sdW1uSW5kZXg6IG51bWJlcixcbiAgICBpc0ZpcnN0OiBib29sZWFuLFxuICAgIGlzTGFzdDogYm9vbGVhblxuICApOiBDb2x1bW5BY3Rpb25bXSB7XG4gICAgY29uc3QgdGFibGVTdGF0ZSA9IHRoaXMuZ2V0QWN0aXZlVGFibGVTdGF0ZSgpO1xuICAgIGNvbnN0IGFjdGlvbnM6IENvbHVtbkFjdGlvbltdID0gW107XG5cbiAgICAvLyBTb3J0IGFzY2VuZGluZ1xuICAgIGlmIChjb2x1bW4uc29ydGFibGUgIT09IGZhbHNlKSB7XG4gICAgICBhY3Rpb25zLnB1c2goe1xuICAgICAgICBpZDogJ3NvcnQtYXNjJyxcbiAgICAgICAgbGFiZWw6IHRoaXMuZ2V0U29ydExhYmVsKGNvbHVtbiwgJ2FzYycpLFxuICAgICAgICBpY29uOiAn4oaRJyxcbiAgICAgICAgYWN0aW9uOiAoY29sKSA9PiB7XG4gICAgICAgICAgdGFibGVTdGF0ZS5hZGRTb3J0VG9Db2x1bW4oY29sLmtleSwgU29ydERpcmVjdGlvbi5BU0MpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBTb3J0IGRlc2NlbmRpbmdcbiAgICBpZiAoY29sdW1uLnNvcnRhYmxlICE9PSBmYWxzZSkge1xuICAgICAgYWN0aW9ucy5wdXNoKHtcbiAgICAgICAgaWQ6ICdzb3J0LWRlc2MnLFxuICAgICAgICBsYWJlbDogdGhpcy5nZXRTb3J0TGFiZWwoY29sdW1uLCAnZGVzYycpLFxuICAgICAgICBpY29uOiAn4oaTJyxcbiAgICAgICAgYWN0aW9uOiAoY29sKSA9PiB7XG4gICAgICAgICAgdGFibGVTdGF0ZS5hZGRTb3J0VG9Db2x1bW4oY29sLmtleSwgU29ydERpcmVjdGlvbi5ERVNDKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gQ2xlYXIgc29ydCAob25seSBzaG93IGlmIGN1cnJlbnRseSBzb3J0ZWQpXG4gICAgaWYgKGNvbHVtbi5zb3J0YWJsZSAhPT0gZmFsc2UgJiYgY29sdW1uLnNvcnREaXJlY3Rpb24gJiYgY29sdW1uLnNvcnREaXJlY3Rpb24gIT09IFNvcnREaXJlY3Rpb24uTk9ORSkge1xuICAgICAgYWN0aW9ucy5wdXNoKHtcbiAgICAgICAgaWQ6ICdjbGVhci1zb3J0JyxcbiAgICAgICAgbGFiZWw6ICdDbGVhciBTb3J0JyxcbiAgICAgICAgaWNvbjogJ+KclScsXG4gICAgICAgIGFjdGlvbjogKGNvbCkgPT4ge1xuICAgICAgICAgIHRhYmxlU3RhdGUuYWRkU29ydFRvQ29sdW1uKGNvbC5rZXksIFNvcnREaXJlY3Rpb24uTk9ORSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIEZpbHRlclxuICAgIGlmIChjb2x1bW4uZmlsdGVyYWJsZSAhPT0gZmFsc2UpIHtcbiAgICAgIGFjdGlvbnMucHVzaCh7XG4gICAgICAgIGlkOiAnZmlsdGVyJyxcbiAgICAgICAgbGFiZWw6ICdGaWx0ZXInLFxuICAgICAgICBpY29uOiAn4pqRJyxcbiAgICAgICAgYWN0aW9uOiAoKSA9PiB7XG4gICAgICAgICAgLy8gRmlsdGVyIGFjdGlvbiBoYW5kbGVkIGJ5IGNvbHVtbiBtZW51IGNvbXBvbmVudFxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBQaW4gTGVmdCAoaWYgbm90IGFscmVhZHkgcGlubmVkKVxuICAgIGlmIChjb2x1bW4ucGlubmFibGUgIT09IGZhbHNlICYmIGNvbHVtbi5zdGlja3kgIT09ICdsZWZ0JyAmJiBjb2x1bW4uc3RpY2t5ICE9PSAncmlnaHQnKSB7XG4gICAgICBhY3Rpb25zLnB1c2goe1xuICAgICAgICBpZDogJ3Bpbi1sZWZ0JyxcbiAgICAgICAgbGFiZWw6ICdQaW4gTGVmdCcsXG4gICAgICAgIGljb246ICfwn5OMJyxcbiAgICAgICAgYWN0aW9uOiAoY29sKSA9PiB7XG4gICAgICAgICAgdGFibGVTdGF0ZS5zZXRTdGlja3lDb2x1bW4oY29sLmtleSwgJ2xlZnQnKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gUGluIFJpZ2h0IChpZiBub3QgYWxyZWFkeSBwaW5uZWQpXG4gICAgaWYgKGNvbHVtbi5waW5uYWJsZSAhPT0gZmFsc2UgJiYgY29sdW1uLnN0aWNreSAhPT0gJ2xlZnQnICYmIGNvbHVtbi5zdGlja3kgIT09ICdyaWdodCcpIHtcbiAgICAgIGFjdGlvbnMucHVzaCh7XG4gICAgICAgIGlkOiAncGluLXJpZ2h0JyxcbiAgICAgICAgbGFiZWw6ICdQaW4gUmlnaHQnLFxuICAgICAgICBpY29uOiAn8J+TjCcsXG4gICAgICAgIGFjdGlvbjogKGNvbCkgPT4ge1xuICAgICAgICAgIHRoaXMubW92ZUNvbHVtblRvRW5kKGNvbC5rZXkpO1xuICAgICAgICAgIHRhYmxlU3RhdGUuc2V0U3RpY2t5Q29sdW1uKGNvbC5rZXksICdyaWdodCcpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBVbnBpbiAoaWYgY3VycmVudGx5IHBpbm5lZClcbiAgICBpZiAoY29sdW1uLnBpbm5hYmxlICE9PSBmYWxzZSAmJiAoY29sdW1uLnN0aWNreSA9PT0gJ2xlZnQnIHx8IGNvbHVtbi5zdGlja3kgPT09ICdyaWdodCcpKSB7XG4gICAgICBhY3Rpb25zLnB1c2goe1xuICAgICAgICBpZDogJ3VucGluJyxcbiAgICAgICAgbGFiZWw6ICdVbnBpbicsXG4gICAgICAgIGljb246ICfwn5ONJyxcbiAgICAgICAgYWN0aW9uOiAoY29sKSA9PiB7XG4gICAgICAgICAgdGFibGVTdGF0ZS5zZXRTdGlja3lDb2x1bW4oY29sLmtleSwgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBNb3ZlIGxlZnQgKG9ubHkgaWYgbW92YWJsZSBhbmQgbm90IHBpbm5lZClcbiAgICBpZiAoIWlzRmlyc3QgJiYgY29sdW1uLm1vdmFibGUgIT09IGZhbHNlICYmICFjb2x1bW4uc3RpY2t5KSB7XG4gICAgICBhY3Rpb25zLnB1c2goe1xuICAgICAgICBpZDogJ21vdmUtbGVmdCcsXG4gICAgICAgIGxhYmVsOiAnTW92ZSBMZWZ0JyxcbiAgICAgICAgaWNvbjogJ+KGkCcsXG4gICAgICAgIGFjdGlvbjogKGNvbCkgPT4ge1xuICAgICAgICAgIHRoaXMub25Db2x1bW5Nb3ZlZCh7XG4gICAgICAgICAgICBjb2x1bW5LZXk6IGNvbC5rZXksXG4gICAgICAgICAgICBkaXJlY3Rpb246ICdsZWZ0J1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBNb3ZlIHJpZ2h0IChvbmx5IGlmIG1vdmFibGUgYW5kIG5vdCBwaW5uZWQpXG4gICAgaWYgKCFpc0xhc3QgJiYgY29sdW1uLm1vdmFibGUgIT09IGZhbHNlICYmICFjb2x1bW4uc3RpY2t5KSB7XG4gICAgICBhY3Rpb25zLnB1c2goe1xuICAgICAgICBpZDogJ21vdmUtcmlnaHQnLFxuICAgICAgICBsYWJlbDogJ01vdmUgUmlnaHQnLFxuICAgICAgICBpY29uOiAn4oaSJyxcbiAgICAgICAgYWN0aW9uOiAoY29sKSA9PiB7XG4gICAgICAgICAgdGhpcy5vbkNvbHVtbk1vdmVkKHtcbiAgICAgICAgICAgIGNvbHVtbktleTogY29sLmtleSxcbiAgICAgICAgICAgIGRpcmVjdGlvbjogJ3JpZ2h0J1xuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gYWN0aW9ucztcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgc29ydCBsYWJlbCBiYXNlZCBvbiBjb2x1bW4gZGF0YSB0eXBlXG4gICAqL1xuICBwcml2YXRlIGdldFNvcnRMYWJlbChjb2x1bW46IENvbHVtbkNvbmZpZzxhbnk+LCBkaXJlY3Rpb246ICdhc2MnIHwgJ2Rlc2MnKTogc3RyaW5nIHtcbiAgICBjb25zdCBkYXRhVHlwZSA9IGNvbHVtbi5kYXRhVHlwZTtcblxuICAgIGlmIChkYXRhVHlwZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIHJldHVybiBkaXJlY3Rpb24gPT09ICdhc2MnID8gJ1NvcnQgMOKGkjknIDogJ1NvcnQgOeKGkjAnO1xuICAgIH0gZWxzZSBpZiAoZGF0YVR5cGUgPT09ICdkYXRlJykge1xuICAgICAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gJ2FzYycgPyAnU29ydCBPbGRlc3QgRmlyc3QnIDogJ1NvcnQgTmV3ZXN0IEZpcnN0JztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gJ2FzYycgPyAnU29ydCBB4oaSWicgOiAnU29ydCBa4oaSQSc7XG4gICAgfVxuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvLyBLRVlCT0FSRCBOQVZJR0FUSU9OXG4gIC8vID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogSW5pdGlhbGl6ZSBrZXlib2FyZCBuYXZpZ2F0aW9uXG4gICAqL1xuICBwcml2YXRlIGluaXRpYWxpemVLZXlib2FyZE5hdmlnYXRpb24oKTogdm9pZCB7XG4gICAgY29uc3QgdGFibGVTdGF0ZSA9IHRoaXMuZ2V0QWN0aXZlVGFibGVTdGF0ZSgpO1xuICAgIFxuICAgIHRhYmxlU3RhdGUuc2V0RGltZW5zaW9ucyhcbiAgICAgIHRoaXMudmlzaWJsZUNlbGxHcmlkLmxlbmd0aCxcbiAgICAgIHRoaXMudmlzaWJsZUNvbHVtbnMubGVuZ3RoXG4gICAgKTtcbiAgICBcbiAgICAvLyBTdWJzY3JpYmUgdG8gZm9jdXMgcG9zaXRpb24gY2hhbmdlc1xuICAgIHRoaXMuZm9jdXNTdWJzY3JpcHRpb24gPSB0YWJsZVN0YXRlLmZvY3VzZWRDZWxsUG9zaXRpb24kLnN1YnNjcmliZShwb3NpdGlvbiA9PiB7XG4gICAgICB0aGlzLnVwZGF0ZUNlbGxGb2N1c1N0YXRlcyhwb3NpdGlvbik7XG4gICAgfSk7XG4gICAgXG4gICAgLy8gU3Vic2NyaWJlIHRvIHJlcXVlc3QgYWRkIHJvdyBldmVudHMgKHdoZW4gbmF2aWdhdGluZyBwYXN0IGxhc3Qgcm93KVxuICAgIHRoaXMucmVxdWVzdEFkZFJvd1N1YnNjcmlwdGlvbiA9IHRhYmxlU3RhdGUucmVxdWVzdEFkZFJvdyQuc3Vic2NyaWJlKGV2ZW50ID0+IHtcbiAgICAgIHRoaXMucmVxdWVzdEFkZFJvdy5lbWl0KGV2ZW50KTtcbiAgICB9KTtcbiAgICBcbiAgICAvLyBBdXRvLWZvY3VzIGZpcnN0IGNlbGwgdG8gZW5hYmxlIGtleWJvYXJkIG5hdmlnYXRpb25cbiAgICBpZiAodGhpcy52aXNpYmxlQ2VsbEdyaWQubGVuZ3RoID4gMCAmJiB0aGlzLnZpc2libGVDb2x1bW5zLmxlbmd0aCA+IDApIHtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICB0YWJsZVN0YXRlLmZvY3VzQ2VsbCgwLCAwKTtcbiAgICAgIH0sIDApO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIFVwZGF0ZSBmb2N1cyBzdGF0ZSBpbiBhbGwgY2VsbHNcbiAgICovXG4gIHByaXZhdGUgdXBkYXRlQ2VsbEZvY3VzU3RhdGVzKHBvc2l0aW9uOiBDZWxsRm9jdXNQb3NpdGlvbiB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMudmlzaWJsZUNlbGxHcmlkKSByZXR1cm47XG4gICAgXG4gICAgZm9yIChsZXQgcm93SW5kZXggPSAwOyByb3dJbmRleCA8IHRoaXMudmlzaWJsZUNlbGxHcmlkLmxlbmd0aDsgcm93SW5kZXgrKykge1xuICAgICAgY29uc3Qgcm93ID0gdGhpcy52aXNpYmxlQ2VsbEdyaWRbcm93SW5kZXhdO1xuICAgICAgZm9yIChsZXQgY29sSW5kZXggPSAwOyBjb2xJbmRleCA8IHJvdy5sZW5ndGg7IGNvbEluZGV4KyspIHtcbiAgICAgICAgY29uc3QgY2VsbCA9IHJvd1tjb2xJbmRleF07XG4gICAgICAgIGlmICghY2VsbCkgY29udGludWU7XG4gICAgICAgIFxuICAgICAgICBjb25zdCBzaG91bGRGb2N1cyA9IHBvc2l0aW9uICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24ucm93SW5kZXggPT09IHJvd0luZGV4ICYmIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24uY29sdW1uSW5kZXggPT09IGNvbEluZGV4O1xuICAgICAgICBcbiAgICAgICAgaWYgKHNob3VsZEZvY3VzKSB7XG4gICAgICAgICAgY2VsbC5mb2N1cygpO1xuICAgICAgICAgIC8vIEZvY3VzIHRoZSBhY3R1YWwgRE9NIGVsZW1lbnRcbiAgICAgICAgICB0aGlzLmZvY3VzVGRFbGVtZW50KHJvd0luZGV4LCBjb2xJbmRleCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2VsbC5ibHVyKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBGb2N1cyB0aGUgVEQgZWxlbWVudCBpbiB0aGUgRE9NIGFuZCBzY3JvbGwgaXQgaW50byB2aWV3LFxuICAgKiBhY2NvdW50aW5nIGZvciBzdGlja3kgY29sdW1ucyBvbiBsZWZ0IGFuZCByaWdodFxuICAgKi9cbiAgcHJpdmF0ZSBmb2N1c1RkRWxlbWVudChyb3dJbmRleDogbnVtYmVyLCBjb2xJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgLy8gVXNlIHNldFRpbWVvdXQgdG8gZW5zdXJlIERPTSBoYXMgdXBkYXRlZFxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgLy8gRG9uJ3Qgc3RlYWwgZm9jdXMgZnJvbSBlZGl0b3JzIC0gaWYgYSBjZWxsIGlzIGJlaW5nIGVkaXRlZCwgXG4gICAgICAvLyB0aGUgZWRpdG9yIHNob3VsZCBrZWVwIGZvY3VzXG4gICAgICBjb25zdCBlZGl0aW5nUG9zaXRpb24gPSB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS5nZXRFZGl0aW5nUG9zaXRpb24oKTtcbiAgICAgIGlmIChlZGl0aW5nUG9zaXRpb24gJiYgXG4gICAgICAgICAgZWRpdGluZ1Bvc2l0aW9uLnJvd0luZGV4ID09PSByb3dJbmRleCAmJiBcbiAgICAgICAgICBlZGl0aW5nUG9zaXRpb24uY29sdW1uSW5kZXggPT09IGNvbEluZGV4KSB7XG4gICAgICAgIC8vIENlbGwgaXMgYmVpbmcgZWRpdGVkLCBkb24ndCBzdGVhbCBmb2N1cyBmcm9tIHRoZSBlZGl0b3JcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgXG4gICAgICAvLyBVc2UgYWJzb2x1dGUgcm93IGluZGV4IGZvciB2aXJ0dWFsIHNjcm9sbCBjb21wYXRpYmlsaXR5XG4gICAgICBjb25zdCBhYnNvbHV0ZVJvd0luZGV4ID0gdGhpcy5nZXRBYnNvbHV0ZVJvd0luZGV4KHJvd0luZGV4KTtcbiAgICAgIC8vIFF1ZXJ5IHdpdGhpbiB0aGlzIGNvbXBvbmVudCdzIGhvc3QgZWxlbWVudCB0byBhdm9pZCBzZWxlY3Rpbmcgcm93cyBmcm9tIG90aGVyIHRhYmxlc1xuICAgICAgY29uc3QgaG9zdEVsZW1lbnQgPSB0aGlzLmVsZW1lbnRSZWY/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICBpZiAoIWhvc3RFbGVtZW50KSByZXR1cm47XG4gICAgICBcbiAgICAgIC8vIEZpcnN0LCBlbnN1cmUgdGhlIHRhYmxlIGNvbnRhaW5lciBoYXMgZm9jdXMgZm9yIGtleWJvYXJkIG5hdmlnYXRpb25cbiAgICAgIC8vIFRoZSBrZXlib2FyZCBuYXZpZ2F0aW9uIGRpcmVjdGl2ZSBsaXN0ZW5zIG9uIHRoZSAuc3QtdGFibGUgY29udGFpbmVyXG4gICAgICBjb25zdCB0YWJsZUNvbnRhaW5lciA9IGhvc3RFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5zdC10YWJsZScpIGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICAgIGlmICh0YWJsZUNvbnRhaW5lciAmJiB0eXBlb2YgdGFibGVDb250YWluZXIuZm9jdXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGFibGVDb250YWluZXIuZm9jdXMoeyBwcmV2ZW50U2Nyb2xsOiB0cnVlIH0pO1xuICAgICAgfVxuICAgICAgXG4gICAgICBjb25zdCB0ciA9IGhvc3RFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoYHRyW2RhdGEtcm93LWluZGV4PVwiJHthYnNvbHV0ZVJvd0luZGV4fVwiXWApO1xuICAgICAgaWYgKHRyKSB7XG4gICAgICAgIGNvbnN0IGNlbGxzID0gdHIucXVlcnlTZWxlY3RvckFsbCgndGQ6bm90KC5zZXR0aW5ncy1jb2x1bW4pOm5vdCgucm93LW51bWJlci1jZWxsKScpO1xuICAgICAgICBjb25zdCB0YXJnZXRDZWxsID0gY2VsbHNbY29sSW5kZXhdIGFzIEhUTUxFbGVtZW50IHwgdW5kZWZpbmVkO1xuICAgICAgICBpZiAodGFyZ2V0Q2VsbCAmJiB0eXBlb2YgdGFyZ2V0Q2VsbC5mb2N1cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgIHRhcmdldENlbGwuZm9jdXMoeyBwcmV2ZW50U2Nyb2xsOiB0cnVlIH0pO1xuICAgICAgICAgIHRoaXMuc2Nyb2xsQ2VsbEludG9WaWV3KHRhcmdldENlbGwsIGNvbEluZGV4KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIDApO1xuICB9XG5cbiAgLyoqXG4gICAqIFNjcm9sbCBhIGNlbGwgaW50byB2aWV3LCBhY2NvdW50aW5nIGZvciBzdGlja3kgY29sdW1uc1xuICAgKi9cbiAgcHJpdmF0ZSBzY3JvbGxDZWxsSW50b1ZpZXcoY2VsbDogSFRNTEVsZW1lbnQsIGNvbEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBGaW5kIHRoZSBzY3JvbGwgY29udGFpbmVyXG4gICAgY29uc3Qgc2Nyb2xsQ29udGFpbmVyID0gdGhpcy5nZXRTY3JvbGxDb250YWluZXJFbGVtZW50KCk7XG4gICAgaWYgKCFzY3JvbGxDb250YWluZXIpIHJldHVybjtcblxuICAgIGNvbnN0IGNlbGxSZWN0ID0gY2VsbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBjb250YWluZXJSZWN0ID0gc2Nyb2xsQ29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHN0aWNreSBjb2x1bW4gd2lkdGhzXG4gICAgY29uc3QgeyBsZWZ0U3RpY2t5V2lkdGgsIHJpZ2h0U3RpY2t5V2lkdGggfSA9IHRoaXMuY2FsY3VsYXRlU3RpY2t5V2lkdGhzKCk7XG5cbiAgICAvLyBDYWxjdWxhdGUgdmlzaWJsZSBhcmVhIChleGNsdWRpbmcgc3RpY2t5IGNvbHVtbnMpXG4gICAgY29uc3QgdmlzaWJsZUxlZnQgPSBjb250YWluZXJSZWN0LmxlZnQgKyBsZWZ0U3RpY2t5V2lkdGg7XG4gICAgY29uc3QgdmlzaWJsZVJpZ2h0ID0gY29udGFpbmVyUmVjdC5yaWdodCAtIHJpZ2h0U3RpY2t5V2lkdGg7XG4gICAgY29uc3QgdmlzaWJsZVRvcCA9IGNvbnRhaW5lclJlY3QudG9wO1xuICAgIGNvbnN0IHZpc2libGVCb3R0b20gPSBjb250YWluZXJSZWN0LmJvdHRvbTtcblxuICAgIC8vIENoZWNrIGlmIGNvbHVtbiBpcyBzdGlja3kgKGRvbid0IHNjcm9sbCBmb3Igc3RpY2t5IGNvbHVtbnMpXG4gICAgY29uc3QgY29sdW1uID0gdGhpcy52aXNpYmxlQ29sdW1uc1tjb2xJbmRleF07XG4gICAgaWYgKGNvbHVtbj8uc3RpY2t5KSB7XG4gICAgICAvLyBKdXN0IGVuc3VyZSB2ZXJ0aWNhbCB2aXNpYmlsaXR5IGZvciBzdGlja3kgY29sdW1uc1xuICAgICAgaWYgKGNlbGxSZWN0LnRvcCA8IHZpc2libGVUb3ApIHtcbiAgICAgICAgc2Nyb2xsQ29udGFpbmVyLnNjcm9sbFRvcCAtPSAodmlzaWJsZVRvcCAtIGNlbGxSZWN0LnRvcCk7XG4gICAgICB9IGVsc2UgaWYgKGNlbGxSZWN0LmJvdHRvbSA+IHZpc2libGVCb3R0b20pIHtcbiAgICAgICAgc2Nyb2xsQ29udGFpbmVyLnNjcm9sbFRvcCArPSAoY2VsbFJlY3QuYm90dG9tIC0gdmlzaWJsZUJvdHRvbSk7XG4gICAgICB9XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgY2VsbCBpcyBhbHJlYWR5IGZ1bGx5IHZpc2libGUgaG9yaXpvbnRhbGx5IChubyBzY3JvbGwgbmVlZGVkKVxuICAgIGNvbnN0IGlzQ2VsbEZ1bGx5VmlzaWJsZUhvcml6b250YWxseSA9IGNlbGxSZWN0LmxlZnQgPj0gdmlzaWJsZUxlZnQgJiYgY2VsbFJlY3QucmlnaHQgPD0gdmlzaWJsZVJpZ2h0O1xuICAgIFxuICAgIC8vIE9ubHkgc2Nyb2xsIGhvcml6b250YWxseSBpZiBjZWxsIGlzIE5PVCBmdWxseSB2aXNpYmxlXG4gICAgaWYgKCFpc0NlbGxGdWxseVZpc2libGVIb3Jpem9udGFsbHkpIHtcbiAgICAgIGlmIChjZWxsUmVjdC5sZWZ0IDwgdmlzaWJsZUxlZnQpIHtcbiAgICAgICAgLy8gQ2VsbCBpcyBoaWRkZW4gYmVoaW5kIGxlZnQgc3RpY2t5IGNvbHVtbnNcbiAgICAgICAgc2Nyb2xsQ29udGFpbmVyLnNjcm9sbExlZnQgLT0gKHZpc2libGVMZWZ0IC0gY2VsbFJlY3QubGVmdCk7XG4gICAgICB9IGVsc2UgaWYgKGNlbGxSZWN0LnJpZ2h0ID4gdmlzaWJsZVJpZ2h0KSB7XG4gICAgICAgIC8vIENlbGwgaXMgaGlkZGVuIGJlaGluZCByaWdodCBzdGlja3kgY29sdW1uc1xuICAgICAgICBzY3JvbGxDb250YWluZXIuc2Nyb2xsTGVmdCArPSAoY2VsbFJlY3QucmlnaHQgLSB2aXNpYmxlUmlnaHQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFZlcnRpY2FsIHNjcm9sbGluZ1xuICAgIGlmIChjZWxsUmVjdC50b3AgPCB2aXNpYmxlVG9wKSB7XG4gICAgICBzY3JvbGxDb250YWluZXIuc2Nyb2xsVG9wIC09ICh2aXNpYmxlVG9wIC0gY2VsbFJlY3QudG9wKTtcbiAgICB9IGVsc2UgaWYgKGNlbGxSZWN0LmJvdHRvbSA+IHZpc2libGVCb3R0b20pIHtcbiAgICAgIHNjcm9sbENvbnRhaW5lci5zY3JvbGxUb3AgKz0gKGNlbGxSZWN0LmJvdHRvbSAtIHZpc2libGVCb3R0b20pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTY3JvbGwgdG8gYSBzcGVjaWZpYyByb3cgYnkgaW5kZXggYW5kIG9wdGlvbmFsbHkgZm9jdXMgaXRcbiAgICogQHBhcmFtIHJvd0luZGV4IC0gVGhlIGluZGV4IG9mIHRoZSByb3cgdG8gc2Nyb2xsIHRvXG4gICAqIEBwYXJhbSBmb2N1c0ZpcnN0Q2VsbCAtIFdoZXRoZXIgdG8gZm9jdXMgdGhlIGZpcnN0IGVkaXRhYmxlIGNlbGwgKGRlZmF1bHQ6IGZhbHNlKVxuICAgKi9cbiAgcHVibGljIHNjcm9sbFRvUm93QW5kRm9jdXMocm93SW5kZXg6IG51bWJlciwgZm9jdXNGaXJzdENlbGw6IGJvb2xlYW4gPSBmYWxzZSk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgY29uc3QgaG9zdEVsZW1lbnQgPSB0aGlzLmVsZW1lbnRSZWY/Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICBpZiAoIWhvc3RFbGVtZW50KSByZXR1cm47XG4gICAgICBcbiAgICAgIC8vIEZpbmQgdGhlIHRhcmdldCByb3dcbiAgICAgIGNvbnN0IHJvd3MgPSBob3N0RWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCd0Ym9keSB0cicpO1xuICAgICAgY29uc3QgdGFyZ2V0Um93ID0gcm93c1tyb3dJbmRleF0gYXMgSFRNTEVsZW1lbnQ7XG4gICAgICBcbiAgICAgIGlmICh0YXJnZXRSb3cpIHtcbiAgICAgICAgLy8gU2Nyb2xsIHRoZSByb3cgaW50byB2aWV3XG4gICAgICAgIHRhcmdldFJvdy5zY3JvbGxJbnRvVmlldyh7IGJlaGF2aW9yOiAnc21vb3RoJywgYmxvY2s6ICduZWFyZXN0JyB9KTtcbiAgICAgICAgXG4gICAgICAgIC8vIE9wdGlvbmFsbHkgZm9jdXMgdGhlIGZpcnN0IGVkaXRhYmxlIGNlbGxcbiAgICAgICAgaWYgKGZvY3VzRmlyc3RDZWxsKSB7XG4gICAgICAgICAgY29uc3QgY2VsbHMgPSB0YXJnZXRSb3cucXVlcnlTZWxlY3RvckFsbCgndGQ6bm90KC5zZXR0aW5ncy1jb2x1bW4pOm5vdCgucm93LW51bWJlci1jZWxsKScpO1xuICAgICAgICAgIGNvbnN0IGZpcnN0Q2VsbCA9IGNlbGxzWzBdIGFzIEhUTUxFbGVtZW50O1xuICAgICAgICAgIGlmIChmaXJzdENlbGwgJiYgdHlwZW9mIGZpcnN0Q2VsbC5mb2N1cyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICAgIGZpcnN0Q2VsbC5mb2N1cygpO1xuICAgICAgICAgICAgICAvLyBVcGRhdGUgdGFibGUgc3RhdGUgZm9jdXMgcG9zaXRpb25cbiAgICAgICAgICAgICAgaWYgKHRoaXMudGFibGVTdGF0ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMudGFibGVTdGF0ZS5mb2N1c0NlbGwocm93SW5kZXgsIDApO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LCAxMDApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0sIDApO1xuICB9XG5cbiAgLyoqXG4gICAqIFNjcm9sbCB0byB0aGUgbGFzdCByb3cgaW4gdGhlIHRhYmxlXG4gICAqIEBwYXJhbSBmb2N1c0ZpcnN0Q2VsbCAtIFdoZXRoZXIgdG8gZm9jdXMgdGhlIGZpcnN0IGVkaXRhYmxlIGNlbGwgKGRlZmF1bHQ6IHRydWUpXG4gICAqL1xuICBwdWJsaWMgc2Nyb2xsVG9MYXN0Um93KGZvY3VzRmlyc3RDZWxsOiBib29sZWFuID0gdHJ1ZSk6IHZvaWQge1xuICAgIGNvbnN0IHJvd0NvdW50ID0gdGhpcy5kYXRhPy5sZW5ndGggfHwgMDtcbiAgICBpZiAocm93Q291bnQgPiAwKSB7XG4gICAgICB0aGlzLnNjcm9sbFRvUm93QW5kRm9jdXMocm93Q291bnQgLSAxLCBmb2N1c0ZpcnN0Q2VsbCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgc2Nyb2xsIGNvbnRhaW5lciBlbGVtZW50XG4gICAqL1xuICBwcml2YXRlIGdldFNjcm9sbENvbnRhaW5lckVsZW1lbnQoKTogSFRNTEVsZW1lbnQgfCBudWxsIHtcbiAgICAvLyBQcmVmZXIgY2FjaGVkIGNvbnRhaW5lciBpZiBhbHJlYWR5IHJlc29sdmVkXG4gICAgaWYgKHRoaXMuc2Nyb2xsQ29udGFpbmVyKSB7XG4gICAgICByZXR1cm4gdGhpcy5zY3JvbGxDb250YWluZXI7XG4gICAgfVxuICAgIC8vIFZpcnR1YWwgc2Nyb2xsIHVzZXMgc2Nyb2xsVmlld3BvcnRcbiAgICBpZiAodGhpcy5pc1ZpcnR1YWxTY3JvbGxFbmFibGVkKCkgJiYgdGhpcy5zY3JvbGxWaWV3cG9ydD8ubmF0aXZlRWxlbWVudCkge1xuICAgICAgdGhpcy5zY3JvbGxDb250YWluZXIgPSB0aGlzLnNjcm9sbFZpZXdwb3J0Lm5hdGl2ZUVsZW1lbnQ7XG4gICAgICByZXR1cm4gdGhpcy5zY3JvbGxDb250YWluZXI7XG4gICAgfVxuICAgIC8vIFN0YW5kYXJkIG1vZGUgdXNlcyAuc3QtdGFibGUgY29udGFpbmVyIHdpdGhpbiBUSElTIGNvbXBvbmVudCdzIGhvc3QgZWxlbWVudFxuICAgIC8vIFVzZSBlbGVtZW50UmVmIHRvIHF1ZXJ5IHdpdGhpbiB0aGUgY29tcG9uZW50IGluc3RlYWQgb2YgZG9jdW1lbnQucXVlcnlTZWxlY3RvclxuICAgIC8vIHdoaWNoIHdvdWxkIHJldHVybiB0aGUgZmlyc3QgdGFibGUgb24gdGhlIHBhZ2VcbiAgICBjb25zdCBob3N0RWxlbWVudCA9IHRoaXMuZWxlbWVudFJlZj8ubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoaG9zdEVsZW1lbnQpIHtcbiAgICAgIGNvbnN0IHRhYmxlQ29udGFpbmVyID0gaG9zdEVsZW1lbnQucXVlcnlTZWxlY3RvcignLnN0LXRhYmxlJykgYXMgSFRNTEVsZW1lbnQgfCBudWxsO1xuICAgICAgaWYgKHRhYmxlQ29udGFpbmVyKSB7XG4gICAgICAgIHRoaXMuc2Nyb2xsQ29udGFpbmVyID0gdGFibGVDb250YWluZXI7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzLnNjcm9sbENvbnRhaW5lciB8fCBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZSB0b3RhbCB3aWR0aCBvZiBzdGlja3kgY29sdW1ucyBvbiBsZWZ0IGFuZCByaWdodFxuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVTdGlja3lXaWR0aHMoKTogeyBsZWZ0U3RpY2t5V2lkdGg6IG51bWJlcjsgcmlnaHRTdGlja3lXaWR0aDogbnVtYmVyIH0ge1xuICAgIGxldCBsZWZ0U3RpY2t5V2lkdGggPSAwO1xuICAgIGxldCByaWdodFN0aWNreVdpZHRoID0gMDtcblxuICAgIC8vIEFjY291bnQgZm9yIHJvdyBudW1iZXIgY29sdW1uIGlmIGVuYWJsZWRcbiAgICBpZiAodGhpcy5tZXJnZWRDb25maWcuc2hvd1Jvd051bWJlcikge1xuICAgICAgbGVmdFN0aWNreVdpZHRoICs9IDMwOyAvLyBSb3cgbnVtYmVyIGNvbHVtbiB3aWR0aFxuICAgIH1cblxuICAgIC8vIENhbGN1bGF0ZSBmcm9tIGNvbHVtbiBjb25maWdzXG4gICAgZm9yIChjb25zdCBjb2wgb2YgdGhpcy52aXNpYmxlQ29sdW1ucykge1xuICAgICAgaWYgKGNvbC5zdGlja3kgPT09ICdsZWZ0Jykge1xuICAgICAgICBsZWZ0U3RpY2t5V2lkdGggKz0gKGNvbC53aWR0aCBhcyBudW1iZXIpIHx8IDEwMDtcbiAgICAgIH0gZWxzZSBpZiAoY29sLnN0aWNreSA9PT0gJ3JpZ2h0Jykge1xuICAgICAgICByaWdodFN0aWNreVdpZHRoICs9IChjb2wud2lkdGggYXMgbnVtYmVyKSB8fCAxMDA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gQWNjb3VudCBmb3Igc2V0dGluZ3MgY29sdW1uIG9ubHkgd2hlbiByb3cgYWN0aW9ucyBhcmUgZW5hYmxlZCAodXNlIGNvbnNpc3RlbnQgd2lkdGgpXG4gICAgY29uc3Qgc2V0dGluZ3NDb2x1bW5XaWR0aCA9IHRoaXMuaGFzUm93QWN0aW9ucygpID8gMzIgOiAwO1xuICAgIHJpZ2h0U3RpY2t5V2lkdGggKz0gc2V0dGluZ3NDb2x1bW5XaWR0aDtcblxuICAgIHJldHVybiB7IGxlZnRTdGlja3lXaWR0aCwgcmlnaHRTdGlja3lXaWR0aCB9O1xuICB9XG4gIFxuICAvKipcbiAgICogSGFuZGxlIGNlbGwgY2xpY2tcbiAgICovXG4gIG9uQ2VsbENsaWNrKHJvd0luZGV4OiBudW1iZXIsIGNvbHVtbkluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNLZXlib2FyZE5hdmlnYXRpb25FbmFibGVkKCkpIHJldHVybjtcbiAgICB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS5mb2N1c0NlbGwocm93SW5kZXgsIGNvbHVtbkluZGV4KTtcbiAgfVxuICBcbiAgLyoqXG4gICAqIEhhbmRsZSBjZWxsIGVudGVyaW5nIGVkaXQgbW9kZVxuICAgKi9cbiAgb25DZWxsRWRpdChldmVudDogQ2VsbEVkaXRFdmVudCk6IHZvaWQge1xuICAgIHRoaXMuY2VsbEVkaXQuZW1pdChldmVudCk7XG4gICAgXG4gICAgaWYgKHRoaXMuaXNLZXlib2FyZE5hdmlnYXRpb25FbmFibGVkKCkpIHtcbiAgICAgIGNvbnN0IHJvd0luZGV4ID0gZXZlbnQuY2VsbC5nZXRSb3dJbmRleCgpO1xuICAgICAgY29uc3QgY29sdW1uS2V5ID0gZXZlbnQuY29sdW1uS2V5O1xuICAgICAgY29uc3QgY29sdW1uSW5kZXggPSB0aGlzLnZpc2libGVDb2x1bW5zLmZpbmRJbmRleChjb2wgPT4gY29sLmtleSA9PT0gY29sdW1uS2V5KTtcbiAgICAgIFxuICAgICAgaWYgKHJvd0luZGV4ICE9PSB1bmRlZmluZWQgJiYgY29sdW1uSW5kZXggPj0gMCkge1xuICAgICAgICB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS5zZXRFZGl0aW5nQ2VsbChyb3dJbmRleCwgY29sdW1uSW5kZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEhhbmRsZSBjZWxsIHNhdmVcbiAgICovXG4gIG9uQ2VsbFNhdmUoZXZlbnQ6IENlbGxTYXZlRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmNlbGxTYXZlLmVtaXQoZXZlbnQpO1xuICAgIFxuICAgIGlmICh0aGlzLmlzS2V5Ym9hcmROYXZpZ2F0aW9uRW5hYmxlZCgpKSB7XG4gICAgICB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS5jbGVhckVkaXRpbmdDZWxsKCk7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogSGFuZGxlIGNlbGwgY2FuY2VsXG4gICAqL1xuICBvbkNlbGxDYW5jZWwoZXZlbnQ6IENlbGxDYW5jZWxFdmVudCk6IHZvaWQge1xuICAgIHRoaXMuY2VsbENhbmNlbC5lbWl0KGV2ZW50KTtcbiAgICBcbiAgICBpZiAodGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSkge1xuICAgICAgdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIEhhbmRsZSBjZWxsIHNhdmUgd2l0aCBuYXZpZ2F0aW9uIChFeGNlbC1saWtlIGJlaGF2aW9yKVxuICAgKi9cbiAgb25DZWxsU2F2ZUFuZE5hdmlnYXRlKGV2ZW50OiB7ZXZlbnQ6IEtleWJvYXJkRXZlbnQsIGRpcmVjdGlvbjogTmF2aWdhdGlvbkRpcmVjdGlvbn0pOiB2b2lkIHtcbiAgICAvLyBOYXZpZ2F0aW9uIGlzIGFscmVhZHkgaGFuZGxlZCBieSB0aGUgZGlyZWN0aXZlIGFmdGVyIHNhdmVcbiAgICAvLyBKdXN0IGVuc3VyZSBlZGl0aW5nIHN0YXRlIGlzIGNsZWFyZWRcbiAgICBpZiAodGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSkge1xuICAgICAgdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCkuY2xlYXJFZGl0aW5nQ2VsbCgpO1xuICAgICAgLy8gTW92ZSBmb2N1cyBpbiB0aGUgc3BlY2lmaWVkIGRpcmVjdGlvblxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHRoaXMuZ2V0QWN0aXZlVGFibGVTdGF0ZSgpLm1vdmVGb2N1cyhldmVudC5kaXJlY3Rpb24pO1xuICAgICAgfSwgMCk7XG4gICAgfVxuICB9XG4gIFxuICAvKipcbiAgICogSGFuZGxlIGZvY3VzIG9uIHRhYmxlIGNvbnRhaW5lciAtIGZvY3VzIGZpcnN0IGNlbGwgaWYgbm8gY2VsbCBpcyBmb2N1c2VkXG4gICAqL1xuICBvblRhYmxlQ29udGFpbmVyRm9jdXMoZXZlbnQ6IEZvY3VzRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNLZXlib2FyZE5hdmlnYXRpb25FbmFibGVkKCkpIHJldHVybjtcbiAgICBcbiAgICBjb25zdCB0YWJsZVN0YXRlID0gdGhpcy5nZXRBY3RpdmVUYWJsZVN0YXRlKCk7XG4gICAgY29uc3QgY3VycmVudEZvY3VzID0gdGFibGVTdGF0ZS5nZXRGb2N1c2VkUG9zaXRpb24oKTtcbiAgICBcbiAgICAvLyBJZiBubyBjZWxsIGlzIGZvY3VzZWQsIGZvY3VzIHRoZSBmaXJzdCBjZWxsXG4gICAgaWYgKCFjdXJyZW50Rm9jdXMgJiYgdGhpcy52aXNpYmxlQ2VsbEdyaWQubGVuZ3RoID4gMCAmJiB0aGlzLnZpc2libGVDb2x1bW5zLmxlbmd0aCA+IDApIHtcbiAgICAgIHRhYmxlU3RhdGUuZm9jdXNDZWxsKDAsIDApO1xuICAgIH1cbiAgfVxuICBcbiAgLyoqXG4gICAqIENoZWNrIGlmIGtleWJvYXJkIG5hdmlnYXRpb24gaXMgZW5hYmxlZFxuICAgKi9cbiAgaXNLZXlib2FyZE5hdmlnYXRpb25FbmFibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1lcmdlZENvbmZpZy5mZWF0dXJlcz8ua2V5Ym9hcmROYXZpZ2F0aW9uPy5lbmFibGVkID8/IGZhbHNlO1xuICB9XG4gIFxuICAvKipcbiAgICogR2V0IEVkaXRNb2RlIGVudW0gdmFsdWUgZm9yIGNlbGxzXG4gICAqIEZvciBFeGNlbC1saWtlIHRhYmxlcyB3aXRoIGtleWJvYXJkIG5hdmlnYXRpb24sIHVzZSBFTlRFUiBtb2RlXG4gICAqIHdoaWNoIGFsbG93cyBhcnJvdyBrZXkgbmF2aWdhdGlvbiB3aXRob3V0IHRyaWdnZXJpbmcgZWRpdC5cbiAgICogRG91YmxlLWNsaWNrIHdpbGwgc3RpbGwgd29yayB0byBzdGFydCBlZGl0aW5nLlxuICAgKi9cbiAgZ2V0RWRpdE1vZGVGb3JDZWxscygpOiBFZGl0TW9kZSB7XG4gICAgLy8gSWYga2V5Ym9hcmQgbmF2aWdhdGlvbiBpcyBlbmFibGVkLCB1c2UgRU5URVIgbW9kZSBmb3IgRXhjZWwtbGlrZSBiZWhhdmlvclxuICAgIC8vIE90aGVyd2lzZSB1c2UgQ0xJQ0sgbW9kZSBmb3IgaW1tZWRpYXRlIGVkaXRpbmdcbiAgICBpZiAodGhpcy5pc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSkge1xuICAgICAgcmV0dXJuIEVkaXRNb2RlLkVOVEVSO1xuICAgIH1cbiAgICByZXR1cm4gRWRpdE1vZGUuQ0xJQ0s7XG4gIH1cbiAgXG4gIC8qKlxuICAgKiBDbGVhciBmb2N1cyB3aGVuIGNsaWNraW5nIG91dHNpZGUgdGFibGVcbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcbiAgb25Eb2N1bWVudENsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmlzS2V5Ym9hcmROYXZpZ2F0aW9uRW5hYmxlZCgpKSByZXR1cm47XG4gICAgXG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50O1xuICAgIGNvbnN0IHRhYmxlRWxlbWVudCA9IHRhcmdldC5jbG9zZXN0KCcuc3QtdGFibGUnKTtcbiAgICBcbiAgICAvLyBBbHNvIGNoZWNrIGlmIGNsaWNrIGlzIGluc2lkZSBhIHBvcnRhbCAoZS5nLiwgbmlsZS1zZWxlY3QgZHJvcGRvd24pXG4gICAgLy8gVGhlc2UgYXJlIHJlbmRlcmVkIG91dHNpZGUgdGhlIHRhYmxlIGJ1dCBhcmUgcGFydCBvZiB0aGUgZWRpdGluZyBleHBlcmllbmNlXG4gICAgY29uc3QgcG9ydGFsRWxlbWVudCA9IHRhcmdldC5jbG9zZXN0KCcubmlsZS1zZWxlY3QtcG9ydGFsLWFwcGVuZCcpO1xuICAgIFxuICAgIC8vIENoZWNrIGNvbXBvc2VkUGF0aCBmb3Igc2hhZG93IERPTSBlbGVtZW50cyAoZS5nLiwgbmlsZS1vcHRpb24sIG5pbGUtaW5wdXQgaW5zaWRlIHNoYWRvdyByb290KVxuICAgIGNvbnN0IGNvbXBvc2VkUGF0aCA9IGV2ZW50LmNvbXBvc2VkUGF0aD8uKCkgfHwgW107XG4gICAgY29uc3QgaXNJbnNpZGVOaWxlRWxlbWVudCA9IGNvbXBvc2VkUGF0aC5zb21lKChlbDogRXZlbnRUYXJnZXQpID0+IHtcbiAgICAgIGlmIChlbCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHRhZ05hbWUgPSBlbC50YWdOYW1lPy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAvLyBDaGVjayBmb3IgYW55IG5pbGUtKiBjdXN0b20gZWxlbWVudHMgdXNlZCBpbiBlZGl0b3JzXG4gICAgICAgIHJldHVybiB0YWdOYW1lPy5zdGFydHNXaXRoKCduaWxlLScpIHx8IFxuICAgICAgICAgICAgICAgZWwuY2xhc3NMaXN0Py5jb250YWlucygnbmlsZS1zZWxlY3QtcG9ydGFsLWFwcGVuZCcpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH0pO1xuICAgIFxuICAgIGlmICghdGFibGVFbGVtZW50ICYmICFwb3J0YWxFbGVtZW50ICYmICFpc0luc2lkZU5pbGVFbGVtZW50KSB7XG4gICAgICB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS5jbGVhckZvY3VzKCk7XG4gICAgICB0aGlzLmdldEFjdGl2ZVRhYmxlU3RhdGUoKS5jbGVhckVkaXRpbmdDZWxsKCk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5zdGF0ZVN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLnNjcm9sbFN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLmZvY3VzU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudmFsaWRhdGlvblN1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLmRhdGFTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5yZXF1ZXN0QWRkUm93U3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMudmlydHVhbFNjcm9sbFN0YXRlJC5jb21wbGV0ZSgpO1xuICAgIHRoaXMuaW50ZXJuYWxEYXRhJC5jb21wbGV0ZSgpO1xuICB9XG4gIFxufVxuXG4iLCI8IS0tIFRvcCBwYWdpbmF0aW9uIGNvbnRyb2xzIC0tPlxuPHN0LXBhZ2luYXRpb24gXG4gICpuZ0lmPVwic2hvd1RvcFBhZ2luYXRpb24oKSAmJiAhKG1lcmdlZENvbmZpZy50YWJsZVNrZWxldG9uPy5lbmFibGVkIHwgYXN5bmMpXCIgXG4gIFt0YWJsZVN0YXRlXT1cImdldEFjdGl2ZVRhYmxlU3RhdGUoKVwiXG4gIFt0YWJsZUNvbmZpZ109XCJtZXJnZWRDb25maWdcIlxuICBwb3NpdGlvbj1cInRvcFwiPlxuPC9zdC1wYWdpbmF0aW9uPlxuXG48ZGl2IGNsYXNzPVwic3QtdGFibGVcIiAqbmdJZj1cIiEobWVyZ2VkQ29uZmlnLnRhYmxlU2tlbGV0b24/LmVuYWJsZWQgfCBhc3luYylcIiBcbiAgW25nQ2xhc3NdPVwie1xuICAgICd2aXJ0dWFsLXNjcm9sbC1lbmFibGVkJzogaXNWaXJ0dWFsU2Nyb2xsRW5hYmxlZCgpLFxuICAgICdrZXlib2FyZC1uYXZpZ2F0aW9uLWVuYWJsZWQnOiBpc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKVxuICB9XCJcbiAgW25nU3R5bGVdPVwie1xuICAgICdtYXgtaGVpZ2h0LnB4JzogIWlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKSA/IG1lcmdlZENvbmZpZy5kaXNwbGF5Py5tYXhIZWlnaHQgOiBudWxsXG4gIH1cIlxuICBzdEtleWJvYXJkTmF2aWdhdGlvblxuICBbdGFibGVTdGF0ZV09XCJnZXRBY3RpdmVUYWJsZVN0YXRlKClcIlxuICBbYWRkUm93T25OYXZpZ2F0ZVBhc3RFbmRdPVwibWVyZ2VkQ29uZmlnLmZlYXR1cmVzPy5rZXlib2FyZE5hdmlnYXRpb24/LmFkZFJvd09uTmF2aWdhdGVQYXN0RW5kIHx8IGZhbHNlXCJcbiAgW2F0dHIudGFiaW5kZXhdPVwiaXNLZXlib2FyZE5hdmlnYXRpb25FbmFibGVkKCkgPyAwIDogLTFcIlxuICAoZm9jdXMpPVwib25UYWJsZUNvbnRhaW5lckZvY3VzKCRldmVudClcIlxuICBbYXR0ci50aXRsZV09XCJpc0tleWJvYXJkTmF2aWdhdGlvbkVuYWJsZWQoKSA/ICdDbGljayBhIGNlbGwgb3IgcHJlc3MgVGFiIHRvIHN0YXJ0IGtleWJvYXJkIG5hdmlnYXRpb24nIDogbnVsbFwiPlxuICA8IS0tIFVuaWZpZWQgVGFibGUgQWN0aW9ucyBNZW51IC0tPlxuXG4gIDwhLS0gVmlydHVhbCBzY3JvbGwgdmlld3BvcnQgd3JhcHBlciAtLT5cbiAgPGRpdiBjbGFzcz1cInN0LXNjcm9sbC12aWV3cG9ydFwiICNzY3JvbGxWaWV3cG9ydCAqbmdJZj1cImlzVmlydHVhbFNjcm9sbEVuYWJsZWQoKVwiXG4gICAgW25nU3R5bGVdPVwieyAnaGVpZ2h0LnB4JzogZ2V0VmlydHVhbFNjcm9sbFZpZXdwb3J0SGVpZ2h0KCkgfVwiPlxuXG4gICAgPCEtLSBTcGFjZXIgdG8gY3JlYXRlIHNjcm9sbGFibGUgYXJlYSAtLT5cbiAgICA8ZGl2IGNsYXNzPVwic3Qtc2Nyb2xsLXNwYWNlclwiIFtuZ1N0eWxlXT1cInsgJ2hlaWdodC5weCc6IHZpcnR1YWxTY3JvbGxUb3RhbEhlaWdodCQgfCBhc3luYyB9XCI+XG4gICAgPC9kaXY+XG5cbiAgICA8IS0tIFRhYmxlIHBvc2l0aW9uZXIgd2l0aCB0cmFuc2Zvcm0gKGluc3RlYWQgb2YgdGJvZHkpIC0tPlxuICAgIDxkaXYgY2xhc3M9XCJzdC10YWJsZS1wb3NpdGlvbmVyXCIgW25nU3R5bGVdPVwieyB0cmFuc2Zvcm06ICd0cmFuc2xhdGVZKCcgKyAodmlydHVhbFNjcm9sbE9mZnNldFkkIHwgYXN5bmMpICsgJ3B4KScgfVwiPlxuICAgICAgPCEtLSBUYWJsZSB3aXRoIG9ubHkgdmlzaWJsZSByb3dzIC0tPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRhYmxlVGVtcGxhdGU7IGNvbnRleHQ6IHsgXG4gICAgICAgIG1vZGU6ICd2aXJ0dWFsJyxcbiAgICAgICAgdGhlYWRTdHlsZTogeyB0b3A6ICh2aXJ0dWFsU2Nyb2xsT2Zmc2V0WU5lZyQgfCBhc3luYykgKyAncHgnIH1cbiAgICAgIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIFxuICA8IS0tIFN0YW5kYXJkIHRhYmxlICh3aGVuIHZpcnR1YWwgc2Nyb2xsIGRpc2FibGVkKSAtLT5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFpc1ZpcnR1YWxTY3JvbGxFbmFibGVkKClcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGFibGVUZW1wbGF0ZTsgY29udGV4dDogeyBcbiAgICAgIG1vZGU6ICdzdGFuZGFyZCcsXG4gICAgICB0aGVhZFN0eWxlOiBudWxsXG4gICAgfVwiPjwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cblxuICA8IS0tIFNoYXJlZCBDb2x1bW4gTWVudSBEcm9wZG93biAtLT5cbiAgPHN0LWNvbHVtbi1tZW51LWRyb3Bkb3duIFxuICBbaXNPcGVuXT1cImNvbHVtbk1lbnVTdGF0ZS5pc09wZW5cIlxuICBbcG9zaXRpb25dPVwiY29sdW1uTWVudVN0YXRlLnBvc2l0aW9uXCJcbiAgW2NvbnRleHRdPVwiY29sdW1uTWVudVN0YXRlLmNvbnRleHRcIlxuICAoYWN0aW9uQ2xpY2tlZCk9XCJvbkNvbHVtbkFjdGlvbkNsaWNrZWQoJGV2ZW50KVwiXG4gIChjbG9zZWQpPVwiY2xvc2VDb2x1bW5NZW51KClcIj5cbiAgPC9zdC1jb2x1bW4tbWVudS1kcm9wZG93bj5cbjwvZGl2PlxuXG48bmctY29udGFpbmVyICpuZ0lmPVwiKG1lcmdlZENvbmZpZy50YWJsZVNrZWxldG9uPy5lbmFibGVkIHwgYXN5bmMpXCI+XG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJza2VsZXRvbkxvYWRlclwiPjwvbmctY29udGFpbmVyPlxuPC9uZy1jb250YWluZXI+XG5cbjwhLS0gU2hhcmVkIFJvdyBBY3Rpb25zIERyb3Bkb3duIC0tPlxuPHN0LXJvdy1hY3Rpb25zLWRyb3Bkb3duIFtpc09wZW5dPVwiZHJvcGRvd25TdGF0ZS5pc09wZW5cIiBbcG9zaXRpb25dPVwiZHJvcGRvd25TdGF0ZS5wb3NpdGlvblwiXG4gIFtjb250ZXh0XT1cImRyb3Bkb3duU3RhdGUuY29udGV4dFwiIChhY3Rpb25DbGlja2VkKT1cIm9uUm93QWN0aW9uQ2xpY2tlZCgkZXZlbnQpXCIgKGNsb3NlZCk9XCJjbG9zZVJvd0FjdGlvbnNEcm9wZG93bigpXCI+XG48L3N0LXJvdy1hY3Rpb25zLWRyb3Bkb3duPlxuXG5cbjwhLS0gQm90dG9tIHBhZ2luYXRpb24gY29udHJvbHMgLS0+XG48c3QtcGFnaW5hdGlvbiBcbiAgKm5nSWY9XCJzaG93Qm90dG9tUGFnaW5hdGlvbigpICYmICEobWVyZ2VkQ29uZmlnLnRhYmxlU2tlbGV0b24/LmVuYWJsZWQgfCBhc3luYylcIiBcbiAgW3RhYmxlU3RhdGVdPVwiZ2V0QWN0aXZlVGFibGVTdGF0ZSgpXCJcbiAgW3RhYmxlQ29uZmlnXT1cIm1lcmdlZENvbmZpZ1wiXG4gIHBvc2l0aW9uPVwiYm90dG9tXCI+XG48L3N0LXBhZ2luYXRpb24+XG5cblxuICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAtLT5cbiAgPCEtLSBSRVVTQUJMRSBUQUJMRSBURU1QTEFURSAtLT5cbiAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+XG4gIDxuZy10ZW1wbGF0ZSAjdGFibGVUZW1wbGF0ZSBsZXQtbW9kZT1cIm1vZGVcIiBsZXQtdGhlYWRTdHlsZT1cInRoZWFkU3R5bGVcIj5cbiAgICA8dGFibGUgY2xhc3M9XCJzdC10YWJsZS1lbGVtZW50XCI+XG4gICAgICA8IS0tIFRBQkxFIEhFQURFUiAtLT5cbiAgICAgIDx0aGVhZCBbbmdDbGFzc109XCJ7ICdzdGlja3knOiBtZXJnZWRDb25maWcuZGlzcGxheT8uc3RpY2t5SGVhZGVyIH1cIiBbbmdTdHlsZV09XCJ0aGVhZFN0eWxlXCI+XG4gICAgICAgIDx0cj5cbiAgICAgICAgICA8IS0tIFJvdyBOdW1iZXIgSGVhZGVyIC0tPlxuICAgICAgICAgIDx0aCAqbmdJZj1cIm1lcmdlZENvbmZpZy5zaG93Um93TnVtYmVyXCIgY2xhc3M9XCJyb3ctbnVtYmVyLWhlYWRlciBoZWFkZXItY2VsbCBzdGlja3ktbGVmdFwiXG4gICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogJ3N0aWNreScsXG4gICAgICAgICAgICAgICAgJ2xlZnQucHgnOiAwLFxuICAgICAgICAgICAgICAgICd6LWluZGV4JzogWkluZGV4LlNUSUNLWV9IRUFERVJfQ0VMTCxcbiAgICAgICAgICAgICAgICAnd2lkdGgucHgnOiAzMFxuICAgICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICAjXG4gICAgICAgICAgPC90aD5cbiAgICAgICAgICA8IS0tIENvbHVtbiBIZWFkZXJzIC0tPlxuICAgICAgICAgIDx0aCBcbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgdmlzaWJsZUNvbHVtbnM7IGxldCBjb2xJbmRleCA9IGluZGV4OyBsZXQgaXNGaXJzdCA9IGZpcnN0OyBsZXQgaXNMYXN0ID0gbGFzdFwiXG4gICAgICAgICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICAgICAgICdoZWFkZXItY2VsbCc6IG1vZGUgPT09ICdzdGFuZGFyZCcsXG4gICAgICAgICAgICAgICdzdGlja3ktbGVmdCc6IGNvbHVtbi5zdGlja3kgPT09ICdsZWZ0JyxcbiAgICAgICAgICAgICAgJ3N0aWNreS1yaWdodCc6IGNvbHVtbi5zdGlja3kgPT09ICdyaWdodCcsXG4gICAgICAgICAgICAgICdzdGlja3ktcmlnaHQtZmlyc3QnOiBjb2x1bW4uc3RpY2t5ID09PSAncmlnaHQnICYmIGlzRmlyc3RTdGlja3lSaWdodChjb2x1bW4ua2V5KSxcbiAgICAgICAgICAgICAgJ3Jlc2l6YWJsZSc6IGNvbHVtbi5yZXNpemFibGUgIT09IGZhbHNlXG4gICAgICAgICAgICB9XCJcbiAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgICAgcG9zaXRpb246IGNvbHVtbi5zdGlja3kgPyAnc3RpY2t5JyA6IG51bGwsXG4gICAgICAgICAgICAgICdsZWZ0LnB4JzogY29sdW1uLnN0aWNreSA9PT0gJ2xlZnQnID8gKGNvbHVtbi5zdGlja3lPZmZzZXQgfHwgMCkgOiBudWxsLFxuICAgICAgICAgICAgICAncmlnaHQucHgnOiBjb2x1bW4uc3RpY2t5ID09PSAncmlnaHQnID8gKGNvbHVtbi5zdGlja3lPZmZzZXQgfHwgMCkgOiBudWxsLFxuICAgICAgICAgICAgICAnei1pbmRleCc6IGNvbHVtbi5zdGlja3kgPyBaSW5kZXguU1RJQ0tZX0hFQURFUl9DRUxMIDogbnVsbCxcbiAgICAgICAgICAgICAgJ3dpZHRoLnB4JzogY29sdW1uLndpZHRoXG4gICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICBcbiAgICAgICAgICAgIDxzdC1oZWFkZXIgXG4gICAgICAgICAgICAgIFtjb2x1bW5dPVwiY29sdW1uXCJcbiAgICAgICAgICAgICAgW2NvbHVtbkluZGV4XT1cImNvbEluZGV4XCJcbiAgICAgICAgICAgICAgW2lzRmlyc3RDb2x1bW5dPVwiaXNGaXJzdFwiXG4gICAgICAgICAgICAgIFtpc0xhc3RDb2x1bW5dPVwiaXNMYXN0XCJcbiAgICAgICAgICAgICAgW3RhYmxlU3RhdGVdPVwiZ2V0QWN0aXZlVGFibGVTdGF0ZSgpXCJcbiAgICAgICAgICAgICAgW2VuYWJsZVNvcnRpbmddPVwibWVyZ2VkQ29uZmlnLnNvcnRpbmc/LmVuYWJsZWQgPz8gZW5hYmxlU29ydGluZ1wiXG4gICAgICAgICAgICAgIFtlbmFibGVGaWx0ZXJpbmddPVwibWVyZ2VkQ29uZmlnLmZpbHRlcmluZz8uZW5hYmxlZCA/PyBlbmFibGVGaWx0ZXJpbmdcIlxuICAgICAgICAgICAgICAoY29sdW1uTW92ZWQpPVwib25Db2x1bW5Nb3ZlZCgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgKG1lbnVDbGljayk9XCJvcGVuQ29sdW1uTWVudSgkZXZlbnQsIGNvbHVtbiwgY29sSW5kZXgsIGlzRmlyc3QsIGlzTGFzdClcIj5cbiAgICAgICAgICAgIDwvc3QtaGVhZGVyPlxuXG4gICAgICAgICAgICA8ZGl2IFxuICAgICAgICAgICAgICBjbGFzcz1cInJlc2l6ZS1oYW5kbGVcIiBcbiAgICAgICAgICAgICAgc3RDb2x1bW5SZXNpemVcbiAgICAgICAgICAgICAgW2NvbHVtbl09XCJjb2x1bW5cIlxuICAgICAgICAgICAgICAoY29sdW1uUmVzaXplZCk9XCJvbkNvbHVtblJlc2l6ZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICpuZ0lmPVwiY29sdW1uLnJlc2l6YWJsZSAhPT0gZmFsc2VcIj5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvdGg+XG4gICAgICAgICAgXG4gICAgICAgICAgPCEtLSBTZXR0aW5ncyBDb2x1bW4gSGVhZGVyIC0tPlxuICAgICAgICAgIDx0aCBcbiAgICAgICAgICAgIGNsYXNzPVwic2V0dGluZ3MtY29sdW1uIHN0aWNreS1yaWdodFwiXG4gICAgICAgICAgICBbbmdDbGFzc109XCJ7ICdoZWFkZXItY2VsbCc6IG1vZGUgPT09ICdzdGFuZGFyZCcgfVwiXG4gICAgICAgICAgICBbbmdTdHlsZV09XCJ7ICd6LWluZGV4JzogWkluZGV4LlNUSUNLWV9IRUFERVJfQ0VMTCB9XCI+XG4gICAgICAgICAgICA8ZGl2IFtuZ0NsYXNzXT1cInsgJ2ZsZXgtY2VudGVyJzogbW9kZSA9PT0gJ3ZpcnR1YWwnLCAnaGVhZGVyLWNvbnRlbnQnOiBtb2RlID09PSAnc3RhbmRhcmQnIH1cIj5cbiAgICAgICAgICAgICAgPHN0LXRhYmxlLWFjdGlvbnMgXG4gICAgICAgICAgICAgICAgW3RhYmxlU3RhdGVdPVwiZ2V0QWN0aXZlVGFibGVTdGF0ZSgpXCJcbiAgICAgICAgICAgICAgICBbYWxsb3dBZGRDb2x1bW5dPVwibWVyZ2VkQ29uZmlnLmZlYXR1cmVzPy5jb2x1bW5NYW5hZ2VtZW50Py5hbGxvd0FkZCB8fCBmYWxzZVwiXG4gICAgICAgICAgICAgICAgKGFkZENvbHVtbkNsaWNrZWQpPVwib25BZGRDb2x1bW5DbGljaygpXCI+XG4gICAgICAgICAgICAgIDwvc3QtdGFibGUtYWN0aW9ucz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvdGg+XG4gICAgICAgIDwvdHI+XG4gICAgICA8L3RoZWFkPlxuXG4gICAgICA8IS0tIFRBQkxFIEJPRFkgLS0+XG4gICAgICA8dGJvZHk+XG4gICAgICAgIDwhLS0gVmlydHVhbCBTY3JvbGwgUm93cyAtLT5cbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIm1vZGUgPT09ICd2aXJ0dWFsJ1wiPlxuICAgICAgICAgIDx0ciAqbmdGb3I9XCJsZXQgcm93IG9mIHZpc2libGVSb3dzJCB8IGFzeW5jOyBsZXQgcmVsYXRpdmVJbmRleCA9IGluZGV4OyB0cmFja0J5OiB0cmFja0J5Um93SW5kZXhcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS1yb3ctaW5kZXhdPVwiZ2V0QWJzb2x1dGVSb3dJbmRleChyZWxhdGl2ZUluZGV4KVwiPlxuICAgICAgICAgICAgPCEtLSBSb3cgTnVtYmVyIENlbGwgLS0+XG4gICAgICAgICAgICA8dGQgKm5nSWY9XCJtZXJnZWRDb25maWcuc2hvd1Jvd051bWJlclwiIGNsYXNzPVwicm93LW51bWJlci1jZWxsXCIgXG4gICAgICAgICAgICAgIFtuZ0NsYXNzXT1cInsgJ3N0aWNreS1sZWZ0JzogJ2xlZnQnIH1cIlxuICAgICAgICAgICAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAgICAgICAgICAgJ3dpZHRoLnB4JzogMzAsXG4gICAgICAgICAgICAgICAgcG9zaXRpb246ICdzdGlja3knLFxuICAgICAgICAgICAgICAgICdsZWZ0LnB4JzogMCxcbiAgICAgICAgICAgICAgICAnei1pbmRleCc6IFpJbmRleC5TVElDS1lfQk9EWV9DRUxMLFxuICAgICAgICAgICAgICAgICdoZWlnaHQucHgnOiBtb2RlID09PSAndmlydHVhbCcgPyBnZXRWaXJ0dWFsU2Nyb2xsSXRlbVNpemUoKSA6IG51bGxcbiAgICAgICAgICAgICAgfVwiPlxuICAgICAgICAgICAgICB7e2dldEFic29sdXRlUm93SW5kZXgocmVsYXRpdmVJbmRleCkgKyAxfX1cbiAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYm9keUNlbGxUZW1wbGF0ZTsgY29udGV4dDogeyBcbiAgICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICAgIHJvd0luZGV4OiBnZXRBYnNvbHV0ZVJvd0luZGV4KHJlbGF0aXZlSW5kZXgpLFxuICAgICAgICAgICAgICBtb2RlOiAndmlydHVhbCcsXG4gICAgICAgICAgICAgIHJlbGF0aXZlSW5kZXg6IHJlbGF0aXZlSW5kZXhcbiAgICAgICAgICAgIH1cIj48L25nLWNvbnRhaW5lcj5cbiAgICAgICAgICA8L3RyPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICA8IS0tIFN0YW5kYXJkIFJvd3MgLS0+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJtb2RlID09PSAnc3RhbmRhcmQnXCI+XG4gICAgICAgICAgPHRyICpuZ0Zvcj1cImxldCByb3cgb2YgdmlzaWJsZUNlbGxHcmlkOyBsZXQgcm93SW5kZXggPSBpbmRleFwiIFthdHRyLmRhdGEtcm93LWluZGV4XT1cInJvd0luZGV4XCI+XG4gICAgICAgICAgICA8IS0tIFJvdyBOdW1iZXIgQ2VsbCAtLT5cbiAgICAgICAgICAgIDx0ZCAqbmdJZj1cIm1lcmdlZENvbmZpZy5zaG93Um93TnVtYmVyXCIgY2xhc3M9XCJyb3ctbnVtYmVyLWNlbGxcIiBcbiAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnc3RpY2t5LWxlZnQnOiAnbGVmdCcgfVwiXG4gICAgICAgICAgICAgIFtuZ1N0eWxlXT1cIntcbiAgICAgICAgICAgICAgICAnd2lkdGgucHgnOiAzMCxcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogJ3N0aWNreScsXG4gICAgICAgICAgICAgICAgJ2xlZnQucHgnOiAwLFxuICAgICAgICAgICAgICAgICd6LWluZGV4JzogWkluZGV4LlNUSUNLWV9CT0RZX0NFTEwsXG4gICAgICAgICAgICAgICAgJ2hlaWdodC5weCc6IG1vZGUgPT09ICd2aXJ0dWFsJyA/IGdldFZpcnR1YWxTY3JvbGxJdGVtU2l6ZSgpIDogbnVsbFxuICAgICAgICAgICAgICB9XCI+XG4gICAgICAgICAgICAgIHt7cm93SW5kZXggKyAxfX1cbiAgICAgICAgICAgIDwvdGQ+XG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYm9keUNlbGxUZW1wbGF0ZTsgY29udGV4dDogeyBcbiAgICAgICAgICAgICAgcm93OiByb3csXG4gICAgICAgICAgICAgIHJvd0luZGV4OiByb3dJbmRleCxcbiAgICAgICAgICAgICAgbW9kZTogJ3N0YW5kYXJkJ1xuICAgICAgICAgICAgfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgICAgIDwvdHI+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgPC90Ym9keT5cbiAgICA8L3RhYmxlPlxuICA8L25nLXRlbXBsYXRlPlxuXG4gICAgPCEtLSA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gLS0+XG4gIDwhLS0gUkVVU0FCTEUgQk9EWSBDRUxMIFRFTVBMQVRFIC0tPlxuICA8IS0tID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAtLT5cbiAgPG5nLXRlbXBsYXRlICNib2R5Q2VsbFRlbXBsYXRlIGxldC1yb3c9XCJyb3dcIiBsZXQtcm93SW5kZXg9XCJyb3dJbmRleFwiIGxldC1tb2RlPVwibW9kZVwiIGxldC1yZWxhdGl2ZUluZGV4PVwicmVsYXRpdmVJbmRleFwiPlxuICAgIDwhLS0gRGF0YSBDZWxscyAtLT5cbiAgICA8dGQgXG4gICAgICAqbmdGb3I9XCJsZXQgY2VsbCBvZiByb3c7IGxldCBjb2xJbmRleCA9IGluZGV4XCJcbiAgICAgIFtuZ0NsYXNzXT1cIntcbiAgICAgICAgJ3N0aWNreS1sZWZ0JzogdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy5zdGlja3kgPT09ICdsZWZ0JyxcbiAgICAgICAgJ3N0aWNreS1yaWdodCc6IHZpc2libGVDb2x1bW5zW2NvbEluZGV4XT8uc3RpY2t5ID09PSAncmlnaHQnLFxuICAgICAgICAnc3RpY2t5LXJpZ2h0LWZpcnN0JzogdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy5zdGlja3kgPT09ICdyaWdodCcgJiYgdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy5rZXkgJiYgaXNGaXJzdFN0aWNreVJpZ2h0KHZpc2libGVDb2x1bW5zW2NvbEluZGV4XS5rZXkpLFxuICAgICAgICAnYWxpZ24tY2VudGVyJzogdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy5hbGlnbm1lbnQgPT09ICdjZW50ZXInLFxuICAgICAgICAnYWxpZ24tcmlnaHQnOiB2aXNpYmxlQ29sdW1uc1tjb2xJbmRleF0/LmFsaWdubWVudCA9PT0gJ3JpZ2h0JyxcbiAgICAgICAgJ2NlbGwtZm9jdXNlZCc6IGNlbGwuaXNGb2N1c2VkKClcbiAgICAgIH1cIlxuICAgICAgW25nU3R5bGVdPVwie1xuICAgICAgICBwb3NpdGlvbjogdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy5zdGlja3kgPyAnc3RpY2t5JyA6IG51bGwsXG4gICAgICAgICdsZWZ0LnB4JzogdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy5zdGlja3kgPT09ICdsZWZ0JyA/ICh2aXNpYmxlQ29sdW1uc1tjb2xJbmRleF0/LnN0aWNreU9mZnNldCB8fCAwKSA6IG51bGwsXG4gICAgICAgICdyaWdodC5weCc6IHZpc2libGVDb2x1bW5zW2NvbEluZGV4XT8uc3RpY2t5ID09PSAncmlnaHQnID8gKHZpc2libGVDb2x1bW5zW2NvbEluZGV4XT8uc3RpY2t5T2Zmc2V0IHx8IDApIDogbnVsbCxcbiAgICAgICAgJ3otaW5kZXgnOiB2aXNpYmxlQ29sdW1uc1tjb2xJbmRleF0/LnN0aWNreSA/IFpJbmRleC5TVElDS1lfQk9EWV9DRUxMIDogbnVsbCxcbiAgICAgICAgJ3dpZHRoLnB4JzogdmlzaWJsZUNvbHVtbnNbY29sSW5kZXhdPy53aWR0aCxcbiAgICAgICAgJ2hlaWdodC5weCc6IG1vZGUgPT09ICd2aXJ0dWFsJyA/IGdldFZpcnR1YWxTY3JvbGxJdGVtU2l6ZSgpIDogbnVsbFxuICAgICAgfVwiXG4gICAgICAoY2xpY2spPVwiaXNLZXlib2FyZE5hdmlnYXRpb25FbmFibGVkKCkgPyBvbkNlbGxDbGljayhyb3dJbmRleCwgY29sSW5kZXgpIDogbnVsbFwiPlxuICAgICAgXG4gICAgICA8IS0tIFZpcnR1YWwgU2Nyb2xsIENlbGwgLS0+XG4gICAgICA8c3QtY2VsbCBcbiAgICAgICAgKm5nSWY9XCJtb2RlID09PSAndmlydHVhbCdcIlxuICAgICAgICBbY2VsbF09XCJjZWxsXCIgXG4gICAgICAgIFthdHRyLnRhYmluZGV4XT1cImNlbGwuaXNGb2N1c2VkKCkgPyAwIDogLTFcIiBcbiAgICAgICAgW2VkaXRNb2RlXT1cImdldEVkaXRNb2RlRm9yQ2VsbHMoKVwiXG4gICAgICAgIFt0YWJsZVN0YXRlXT1cImdldEFjdGl2ZVRhYmxlU3RhdGUoKVwiXG4gICAgICAgIFt0YWJsZUNvbmZpZ109XCJtZXJnZWRDb25maWdcIlxuICAgICAgICBbY29sdW1uSW5kZXhdPVwiY29sSW5kZXhcIlxuICAgICAgICAoY2VsbEVkaXQpPVwib25DZWxsRWRpdCgkZXZlbnQpXCIgXG4gICAgICAgIChjZWxsU2F2ZSk9XCJvbkNlbGxTYXZlKCRldmVudClcIlxuICAgICAgICAoY2VsbFNhdmVBbmROYXZpZ2F0ZSk9XCJvbkNlbGxTYXZlQW5kTmF2aWdhdGUoJGV2ZW50KVwiIFxuICAgICAgICAoY2VsbENhbmNlbCk9XCJvbkNlbGxDYW5jZWwoJGV2ZW50KVwiXG4gICAgICAgIChjZWxsQ2hhbmdlKT1cImNlbGxDaGFuZ2UuZW1pdCgkZXZlbnQpXCI+XG4gICAgICA8L3N0LWNlbGw+XG5cbiAgICAgIDwhLS0gU3RhbmRhcmQgQ2VsbCAtLT5cbiAgICAgIDxzdC1jZWxsIFxuICAgICAgICAqbmdJZj1cIm1vZGUgPT09ICdzdGFuZGFyZCdcIlxuICAgICAgICBbY2VsbF09XCJjZWxsXCIgIFxuICAgICAgICBbYXR0ci50YWJpbmRleF09XCJjZWxsLmlzRm9jdXNlZCgpID8gMCA6IC0xXCJcbiAgICAgICAgW3RhYmxlU3RhdGVdPVwiZ2V0QWN0aXZlVGFibGVTdGF0ZSgpXCJcbiAgICAgICAgW3RhYmxlQ29uZmlnXT1cIm1lcmdlZENvbmZpZ1wiXG4gICAgICAgIFtjb2x1bW5JbmRleF09XCJjb2xJbmRleFwiXG4gICAgICAgIChjZWxsU2F2ZSk9XCJvbkNlbGxTYXZlKCRldmVudClcIlxuICAgICAgICAoY2VsbENoYW5nZSk9XCJjZWxsQ2hhbmdlLmVtaXQoJGV2ZW50KVwiPlxuICAgICAgPC9zdC1jZWxsPlxuICAgIDwvdGQ+XG4gICAgXG4gICAgPCEtLSBSb3cgQWN0aW9ucyBDZWxsIC0tPlxuICAgIDx0ZCBjbGFzcz1cInNldHRpbmdzLWNvbHVtblwiXG4gICAgICBbbmdDbGFzc109XCJ7XG4gICAgICAgICdoYXMtYWN0aW9ucyc6IGhhc1Jvd0FjdGlvbnMoKVxuICAgICAgfVwiXG4gICAgICBbbmdTdHlsZV09XCJ7XG4gICAgICAgIHBvc2l0aW9uOiBoYXNSb3dBY3Rpb25zKCkgPyAnc3RpY2t5JyA6IG51bGwsXG4gICAgICAgICdyaWdodC5weCc6IGhhc1Jvd0FjdGlvbnMoKSA/IDAgOiBudWxsLFxuICAgICAgICAnei1pbmRleCc6IGhhc1Jvd0FjdGlvbnMoKSA/IFpJbmRleC5TVElDS1lfQk9EWV9DRUxMIDogbnVsbFxuICAgICAgfVwiPlxuICAgICAgPGJ1dHRvbiBcbiAgICAgICAgKm5nSWY9XCJoYXNSb3dBY3Rpb25zKClcIlxuICAgICAgICBjbGFzcz1cInNldHRpbmdzLXRyaWdnZXJcIlxuICAgICAgICAoY2xpY2spPVwib3BlblJvd0FjdGlvbnNEcm9wZG93bigkZXZlbnQsIGdldFJvd0RhdGEocm93SW5kZXgpLCByb3dJbmRleClcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCIgXG4gICAgICAgIGFyaWEtbGFiZWw9XCJSb3cgYWN0aW9uc1wiPlxuICAgICAgICDii69cbiAgICAgIDwvYnV0dG9uPlxuICAgIDwvdGQ+XG4gIDwvbmctdGVtcGxhdGU+XG5cbjxuZy10ZW1wbGF0ZSAjc2tlbGV0b25Mb2FkZXI+XG4gIDxkaXYgY2xhc3M9XCJsaXN0LXJvd1wiICpuZ0lmPVwiKG1lcmdlZENvbmZpZy50YWJsZVNrZWxldG9uPy5lbmFibGVkIHwgYXN5bmMpXCI+XG4gICAgPGRpdiAqbmdGb3I9XCJsZXQgaSBvZiBza2VsZXRvbkNvbHVtbnNcIiBjbGFzcz1cImxpc3QtY29udGVudFwiPlxuICAgICAgPG5pbGUtc2tlbGV0b24tbG9hZGVyIHZhcmlhbnQ9XCJ0ZXh0XCIgd2lkdGg9XCI5MCVcIiBoZWlnaHQ9XCIxOFwiICpuZ0Zvcj1cImxldCBqIG9mIHNrZWxldG9uUm93c1wiPjwvbmlsZS1za2VsZXRvbi1sb2FkZXI+XG4gICAgPC9kaXY+XG4gIDwvZGl2PlxuPC9uZy10ZW1wbGF0ZT4iXX0=
|