@cqa-lib/cqa-ui 1.1.269 → 1.1.271
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/esm2020/lib/dashboards/dashboard-header/dashboard-header.component.mjs +38 -19
- package/esm2020/lib/dashboards/workspace-selector/workspace-selector.component.mjs +499 -0
- package/esm2020/lib/execution-screen/api-step/api-step.component.mjs +31 -1
- package/esm2020/lib/execution-screen/basic-step/basic-step.component.mjs +31 -1
- package/esm2020/lib/execution-screen/db-verification-step/db-verification-step.component.mjs +31 -1
- package/esm2020/lib/execution-screen/live-execution-step/live-execution-step.component.mjs +31 -1
- package/esm2020/lib/execution-screen/loop-step/loop-step.component.mjs +31 -1
- package/esm2020/lib/ui-kit.module.mjs +6 -1
- package/esm2020/public-api.mjs +2 -1
- package/fesm2015/cqa-lib-cqa-ui.mjs +738 -42
- package/fesm2015/cqa-lib-cqa-ui.mjs.map +1 -1
- package/fesm2020/cqa-lib-cqa-ui.mjs +708 -42
- package/fesm2020/cqa-lib-cqa-ui.mjs.map +1 -1
- package/lib/dashboards/dashboard-header/dashboard-header.component.d.ts +20 -6
- package/lib/dashboards/workspace-selector/workspace-selector.component.d.ts +118 -0
- package/lib/execution-screen/api-step/api-step.component.d.ts +1 -0
- package/lib/execution-screen/basic-step/basic-step.component.d.ts +1 -0
- package/lib/execution-screen/db-verification-step/db-verification-step.component.d.ts +1 -0
- package/lib/execution-screen/live-execution-step/live-execution-step.component.d.ts +1 -0
- package/lib/execution-screen/loop-step/loop-step.component.d.ts +1 -0
- package/lib/ui-kit.module.d.ts +130 -129
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
- package/styles.css +1 -1
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, Input, ViewChild, ElementRef, HostListener, Output, EventEmitter } from '@angular/core';
|
|
2
|
+
import { FormGroup, FormControl } from '@angular/forms';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
import * as i1 from "@angular/cdk/scrolling";
|
|
5
|
+
import * as i2 from "@angular/forms";
|
|
6
|
+
import * as i3 from "@angular/common";
|
|
7
|
+
export class WorkspaceSelectorComponent {
|
|
8
|
+
constructor() {
|
|
9
|
+
/** Emits the selected workspace object when selection changes */
|
|
10
|
+
this.valueChange = new EventEmitter();
|
|
11
|
+
this.selectionChange = new EventEmitter();
|
|
12
|
+
this.selectClick = new EventEmitter();
|
|
13
|
+
/** Emits when user types in search box (useful for server search) */
|
|
14
|
+
this.searchChange = new EventEmitter();
|
|
15
|
+
/** Emits when the component requests more data for the current query */
|
|
16
|
+
this.loadMore = new EventEmitter();
|
|
17
|
+
this.searchText = '';
|
|
18
|
+
this.isOpen = false;
|
|
19
|
+
this.loadingMore = false;
|
|
20
|
+
this.lastOptionsLength = 0;
|
|
21
|
+
this.hasScrolledSinceOpen = false;
|
|
22
|
+
this.onPanelScroll = () => {
|
|
23
|
+
this.hasScrolledSinceOpen = true;
|
|
24
|
+
if (!this.config?.hasMore || this.loadingMore)
|
|
25
|
+
return;
|
|
26
|
+
const el = this.panelScrollEl;
|
|
27
|
+
if (!el)
|
|
28
|
+
return;
|
|
29
|
+
const nearBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - 48;
|
|
30
|
+
if (nearBottom) {
|
|
31
|
+
this.loadingMore = true;
|
|
32
|
+
const key = this.config?.key || '';
|
|
33
|
+
const q = this.searchText || '';
|
|
34
|
+
this.loadMore.emit({ key, query: q });
|
|
35
|
+
try {
|
|
36
|
+
this.config.onLoadMore?.(q);
|
|
37
|
+
}
|
|
38
|
+
catch { }
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
this.trackByOption = (index, opt) => {
|
|
42
|
+
if (!opt)
|
|
43
|
+
return `index-${index}`;
|
|
44
|
+
// Use a simple identifier that doesn't require calling methods
|
|
45
|
+
return opt.id ?? opt.value ?? `option-${index}`;
|
|
46
|
+
};
|
|
47
|
+
this.internalControl = new FormControl();
|
|
48
|
+
this.internalForm = new FormGroup({
|
|
49
|
+
value: this.internalControl
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
ngOnInit() {
|
|
53
|
+
if (!this.config) {
|
|
54
|
+
throw new Error('cqa-workspace-selector: input "config" is required.');
|
|
55
|
+
}
|
|
56
|
+
this.syncValueFromInput();
|
|
57
|
+
this.applySelectedValueIfNeeded();
|
|
58
|
+
this.syncDisabledState();
|
|
59
|
+
this.lastOptionsLength = (this.config?.options || []).length;
|
|
60
|
+
}
|
|
61
|
+
ngOnChanges(changes) {
|
|
62
|
+
if ('config' in changes || 'form' in changes || 'value' in changes) {
|
|
63
|
+
this.syncDisabledState();
|
|
64
|
+
}
|
|
65
|
+
if ('value' in changes && !this.form) {
|
|
66
|
+
// Sync internal control when value changes (for direct binding mode)
|
|
67
|
+
this.syncValueFromInput();
|
|
68
|
+
}
|
|
69
|
+
if ('config' in changes) {
|
|
70
|
+
this.syncControlValueForMultipleMode();
|
|
71
|
+
this.applySelectedValueIfNeeded();
|
|
72
|
+
if (this.config?.isLoading !== undefined) {
|
|
73
|
+
this.loadingMore = this.config.isLoading;
|
|
74
|
+
}
|
|
75
|
+
const len = (this.config?.options || []).length;
|
|
76
|
+
if (len > this.lastOptionsLength) {
|
|
77
|
+
if (this.config?.isLoading === false) {
|
|
78
|
+
this.loadingMore = false;
|
|
79
|
+
}
|
|
80
|
+
else if (this.config?.isLoading === undefined) {
|
|
81
|
+
this.loadingMore = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
this.lastOptionsLength = len;
|
|
85
|
+
if (!this.config?.hasMore) {
|
|
86
|
+
if (this.config?.isLoading === false) {
|
|
87
|
+
this.loadingMore = false;
|
|
88
|
+
}
|
|
89
|
+
else if (this.config?.isLoading === undefined) {
|
|
90
|
+
this.loadingMore = false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if ('form' in changes && !changes['form'].firstChange) {
|
|
95
|
+
this.applySelectedValueIfNeeded();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
syncValueFromInput() {
|
|
99
|
+
if (!this.form && this.value !== undefined) {
|
|
100
|
+
// Sync the internal control with the direct value binding
|
|
101
|
+
// Ensure value is not an array (single selection only)
|
|
102
|
+
if (Array.isArray(this.value)) {
|
|
103
|
+
this.value = this.value.length ? this.value[0] : null;
|
|
104
|
+
}
|
|
105
|
+
this.internalControl.setValue(this.value ?? null, { emitEvent: false });
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
get currentForm() {
|
|
109
|
+
return this.form || this.internalForm;
|
|
110
|
+
}
|
|
111
|
+
get controlKey() {
|
|
112
|
+
return this.config?.key || 'value';
|
|
113
|
+
}
|
|
114
|
+
get currentControl() {
|
|
115
|
+
return this.currentForm.get(this.controlKey) || this.internalControl;
|
|
116
|
+
}
|
|
117
|
+
/** Get current value - from form control if form provided, otherwise from direct value binding */
|
|
118
|
+
get currentValue() {
|
|
119
|
+
if (this.form) {
|
|
120
|
+
return this.currentControl.value;
|
|
121
|
+
}
|
|
122
|
+
// Ensure value is not an array (single selection only)
|
|
123
|
+
if (Array.isArray(this.value)) {
|
|
124
|
+
return this.value.length ? this.value[0] : null;
|
|
125
|
+
}
|
|
126
|
+
return this.value ?? null;
|
|
127
|
+
}
|
|
128
|
+
/** Set current value - to form control if form provided, otherwise update direct value */
|
|
129
|
+
set currentValue(val) {
|
|
130
|
+
if (this.form) {
|
|
131
|
+
this.currentControl.setValue(val, { emitEvent: false });
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Ensure value is not an array (single selection only)
|
|
135
|
+
this.value = Array.isArray(val) ? (val.length ? val[0] : null) : val;
|
|
136
|
+
// Sync internal control for display purposes
|
|
137
|
+
this.internalControl.setValue(this.value, { emitEvent: false });
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
get isDisabled() {
|
|
141
|
+
return this.toBoolean(this.config?.disabled);
|
|
142
|
+
}
|
|
143
|
+
get displayPlaceholder() {
|
|
144
|
+
const currentVal = this.currentValue;
|
|
145
|
+
return this.hasExistingValue(currentVal) ? undefined : (this.config?.placeholder || 'Select...');
|
|
146
|
+
}
|
|
147
|
+
get displayValue() {
|
|
148
|
+
const value = this.currentValue;
|
|
149
|
+
if (value == null)
|
|
150
|
+
return '';
|
|
151
|
+
// If value is already a SelectOption-like object with name/label, use it directly
|
|
152
|
+
if (typeof value === 'object' && value !== null) {
|
|
153
|
+
const workspaceObj = value;
|
|
154
|
+
if (workspaceObj.name || workspaceObj.label) {
|
|
155
|
+
return workspaceObj.name ?? workspaceObj.label ?? String(workspaceObj.value ?? workspaceObj.id ?? '');
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// Otherwise, look up the value in options list
|
|
159
|
+
const option = this.config?.options?.find(opt => this.getOptionValue(opt) === value);
|
|
160
|
+
return option ? this.getOptionLabel(option) : String(value);
|
|
161
|
+
}
|
|
162
|
+
get itemSize() {
|
|
163
|
+
return this.config?.itemSize || 35;
|
|
164
|
+
}
|
|
165
|
+
get viewportHeight() {
|
|
166
|
+
// If viewportHeight is explicitly set in config, use it
|
|
167
|
+
if (this.config?.viewportHeight !== undefined) {
|
|
168
|
+
return this.config.viewportHeight;
|
|
169
|
+
}
|
|
170
|
+
// Otherwise, calculate based on number of options
|
|
171
|
+
const optionCount = this.displayedOptions.length;
|
|
172
|
+
const maxHeight = 300; // Maximum height
|
|
173
|
+
const minHeight = 100; // Minimum height
|
|
174
|
+
const calculatedHeight = optionCount * this.itemSize;
|
|
175
|
+
// Return calculated height, but clamp between min and max
|
|
176
|
+
return Math.min(Math.max(calculatedHeight, minHeight), maxHeight);
|
|
177
|
+
}
|
|
178
|
+
get displayedOptions() {
|
|
179
|
+
return this.filteredOptions();
|
|
180
|
+
}
|
|
181
|
+
toBoolean(value) {
|
|
182
|
+
if (typeof value === 'string') {
|
|
183
|
+
const v = value.trim().toLowerCase();
|
|
184
|
+
if (v === 'true' || v === '1')
|
|
185
|
+
return true;
|
|
186
|
+
if (v === 'false' || v === '0' || v === '')
|
|
187
|
+
return false;
|
|
188
|
+
return true;
|
|
189
|
+
}
|
|
190
|
+
if (typeof value === 'number') {
|
|
191
|
+
return value !== 0;
|
|
192
|
+
}
|
|
193
|
+
return !!value;
|
|
194
|
+
}
|
|
195
|
+
getOptionValue(opt) {
|
|
196
|
+
if (!opt)
|
|
197
|
+
return undefined;
|
|
198
|
+
if (this.config?.valueBy) {
|
|
199
|
+
return opt[this.config.valueBy];
|
|
200
|
+
}
|
|
201
|
+
return opt.id ?? opt.value;
|
|
202
|
+
}
|
|
203
|
+
getOptionLabel(opt) {
|
|
204
|
+
return opt.name ?? opt.label ?? opt.value ?? '';
|
|
205
|
+
}
|
|
206
|
+
syncDisabledState() {
|
|
207
|
+
const shouldDisable = this.toBoolean(this.config?.disabled);
|
|
208
|
+
if (this.form) {
|
|
209
|
+
if (shouldDisable) {
|
|
210
|
+
this.currentControl.disable({ emitEvent: false });
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
this.currentControl.enable({ emitEvent: false });
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// For direct value binding, disabled state is handled via [disabled] binding in template
|
|
217
|
+
}
|
|
218
|
+
syncControlValueForMultipleMode() {
|
|
219
|
+
// No longer needed - single selection only
|
|
220
|
+
const currentVal = this.currentValue;
|
|
221
|
+
if (Array.isArray(currentVal)) {
|
|
222
|
+
this.currentValue = currentVal.length ? currentVal[0] : null;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
applySelectedValueIfNeeded() {
|
|
226
|
+
const currentVal = this.currentValue;
|
|
227
|
+
if (this.hasExistingValue(currentVal)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
// Check both config.selectedValue and direct value input
|
|
231
|
+
const selectedValue = this.value !== undefined ? this.value : this.config?.selectedValue;
|
|
232
|
+
if (selectedValue === undefined || selectedValue === null) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
// Ensure selectedValue is not an array (single selection only)
|
|
236
|
+
const normalized = Array.isArray(selectedValue)
|
|
237
|
+
? (selectedValue.length ? selectedValue[0] : undefined)
|
|
238
|
+
: selectedValue;
|
|
239
|
+
if (normalized === undefined)
|
|
240
|
+
return;
|
|
241
|
+
this.currentValue = normalized;
|
|
242
|
+
}
|
|
243
|
+
hasExistingValue(value) {
|
|
244
|
+
if (value === null || value === undefined) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
if (Array.isArray(value)) {
|
|
248
|
+
return value.some((val) => val !== null && val !== undefined && val !== '');
|
|
249
|
+
}
|
|
250
|
+
if (typeof value === 'string') {
|
|
251
|
+
return value.trim().length > 0;
|
|
252
|
+
}
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
isOptionSelected(opt) {
|
|
256
|
+
const currentVal = this.currentValue;
|
|
257
|
+
if (currentVal == null)
|
|
258
|
+
return false;
|
|
259
|
+
const optionValue = this.getOptionValue(opt);
|
|
260
|
+
// If currentVal is an object with id/value, extract it for comparison
|
|
261
|
+
if (typeof currentVal === 'object' && currentVal !== null) {
|
|
262
|
+
const workspaceObj = currentVal;
|
|
263
|
+
const currentId = this.config?.valueBy
|
|
264
|
+
? workspaceObj[this.config.valueBy]
|
|
265
|
+
: (workspaceObj.id ?? workspaceObj.value);
|
|
266
|
+
return currentId === optionValue;
|
|
267
|
+
}
|
|
268
|
+
// Otherwise, compare directly
|
|
269
|
+
return currentVal === optionValue;
|
|
270
|
+
}
|
|
271
|
+
filteredOptions() {
|
|
272
|
+
const t = this.searchText.toLowerCase().trim();
|
|
273
|
+
const allOptions = this.config.options || [];
|
|
274
|
+
if (this.config?.serverSearch) {
|
|
275
|
+
// For server search, return all options as-is (server handles filtering)
|
|
276
|
+
return allOptions;
|
|
277
|
+
}
|
|
278
|
+
if (!t) {
|
|
279
|
+
// No search - return all options
|
|
280
|
+
return allOptions;
|
|
281
|
+
}
|
|
282
|
+
// Local search - filter options by search text only
|
|
283
|
+
return allOptions.filter((opt) => {
|
|
284
|
+
const text = this.getOptionLabel(opt).toLowerCase();
|
|
285
|
+
return text.includes(t);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
getSelectedIds() {
|
|
289
|
+
const value = this.currentValue;
|
|
290
|
+
return value !== undefined && value !== null ? [value] : [];
|
|
291
|
+
}
|
|
292
|
+
onOptionClick(opt) {
|
|
293
|
+
if (this.isDisabled)
|
|
294
|
+
return;
|
|
295
|
+
// Emit the full option object (with name, id, etc.) instead of just the value
|
|
296
|
+
// This allows the parent to receive the complete workspace object
|
|
297
|
+
const newValue = opt;
|
|
298
|
+
const selectedOption = opt;
|
|
299
|
+
// Close dropdown after selection (unless closeOnSelect is false)
|
|
300
|
+
if (this.config?.closeOnSelect !== false) {
|
|
301
|
+
this.closeDropdown();
|
|
302
|
+
}
|
|
303
|
+
// Update value
|
|
304
|
+
if (this.form) {
|
|
305
|
+
this.currentControl.setValue(newValue, { emitEvent: true });
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
this.value = newValue;
|
|
309
|
+
this.syncValueFromInput();
|
|
310
|
+
}
|
|
311
|
+
this.onSelectionChange(newValue, selectedOption);
|
|
312
|
+
}
|
|
313
|
+
onSelectionChange(newValue, selectedOption) {
|
|
314
|
+
const value = newValue !== undefined ? newValue : this.currentValue;
|
|
315
|
+
// Emit valueChange for two-way binding
|
|
316
|
+
this.valueChange.emit(value);
|
|
317
|
+
if (typeof this.config?.onChange === 'function') {
|
|
318
|
+
try {
|
|
319
|
+
this.config.onChange(value);
|
|
320
|
+
}
|
|
321
|
+
catch (error) {
|
|
322
|
+
console.error('cqa-workspace-selector onChange handler error:', error);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
this.selectionChange.emit({
|
|
326
|
+
key: this.config?.key || '',
|
|
327
|
+
value,
|
|
328
|
+
option: selectedOption,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
onSearchInput(value) {
|
|
332
|
+
this.searchText = value ?? '';
|
|
333
|
+
if (this.config?.serverSearch) {
|
|
334
|
+
try {
|
|
335
|
+
this.config.onSearch?.(value ?? '');
|
|
336
|
+
}
|
|
337
|
+
catch { }
|
|
338
|
+
this.searchChange.emit({ key: this.config?.key || '', query: value ?? '' });
|
|
339
|
+
this.loadingMore = false;
|
|
340
|
+
this.lastOptionsLength = (this.config?.options || []).length;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
toggleDropdown() {
|
|
344
|
+
if (this.isDisabled)
|
|
345
|
+
return;
|
|
346
|
+
if (this.isOpen) {
|
|
347
|
+
this.closeDropdown();
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
this.openDropdown();
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
openDropdown() {
|
|
354
|
+
if (this.isDisabled)
|
|
355
|
+
return;
|
|
356
|
+
this.isOpen = true;
|
|
357
|
+
this.selectClick.emit();
|
|
358
|
+
this.hasScrolledSinceOpen = false;
|
|
359
|
+
if ((this.config?.options || []).length > 0) {
|
|
360
|
+
this.loadingMore = false;
|
|
361
|
+
}
|
|
362
|
+
if (this.config?.serverSearch && this.toBoolean(this.config?.initialFetchOnOpen)) {
|
|
363
|
+
const q = this.searchText || '';
|
|
364
|
+
try {
|
|
365
|
+
this.config.onSearch?.(q);
|
|
366
|
+
}
|
|
367
|
+
catch { }
|
|
368
|
+
this.searchChange.emit({ key: this.config?.key || '', query: q });
|
|
369
|
+
}
|
|
370
|
+
setTimeout(() => {
|
|
371
|
+
this.setupScrollListener();
|
|
372
|
+
if (this.config?.searchable) {
|
|
373
|
+
const input = this.dropdownPanel?.nativeElement?.querySelector('.workspace-search-input');
|
|
374
|
+
input?.focus();
|
|
375
|
+
}
|
|
376
|
+
}, 0);
|
|
377
|
+
}
|
|
378
|
+
closeDropdown() {
|
|
379
|
+
this.isOpen = false;
|
|
380
|
+
this.searchText = '';
|
|
381
|
+
if (this.panelScrollEl) {
|
|
382
|
+
try {
|
|
383
|
+
this.panelScrollEl.removeEventListener('scroll', this.onPanelScroll);
|
|
384
|
+
}
|
|
385
|
+
catch { }
|
|
386
|
+
this.panelScrollEl = undefined;
|
|
387
|
+
}
|
|
388
|
+
this.loadingMore = false;
|
|
389
|
+
}
|
|
390
|
+
setupScrollListener() {
|
|
391
|
+
if (!this.config?.hasMore)
|
|
392
|
+
return;
|
|
393
|
+
const panel = this.dropdownPanel?.nativeElement?.querySelector('.workspace-options-container');
|
|
394
|
+
if (panel) {
|
|
395
|
+
this.panelScrollEl = panel;
|
|
396
|
+
panel.addEventListener('scroll', this.onPanelScroll, { passive: true });
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
onScrolledIndexChange(index) {
|
|
400
|
+
this.hasScrolledSinceOpen = true;
|
|
401
|
+
if (!this.config?.hasMore || this.loadingMore)
|
|
402
|
+
return;
|
|
403
|
+
const viewport = this.viewport?.elementRef?.nativeElement;
|
|
404
|
+
if (!viewport)
|
|
405
|
+
return;
|
|
406
|
+
const itemCount = this.displayedOptions.length;
|
|
407
|
+
const visibleItems = Math.ceil(viewport.clientHeight / this.itemSize);
|
|
408
|
+
if (index + visibleItems >= itemCount - 1) {
|
|
409
|
+
this.loadingMore = true;
|
|
410
|
+
const key = this.config?.key || '';
|
|
411
|
+
const q = this.searchText || '';
|
|
412
|
+
this.loadMore.emit({ key, query: q });
|
|
413
|
+
try {
|
|
414
|
+
this.config.onLoadMore?.(q);
|
|
415
|
+
}
|
|
416
|
+
catch { }
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
highlightText(text) {
|
|
420
|
+
if (!text || !this.config?.highlightPattern) {
|
|
421
|
+
return this.escapeHtml(text);
|
|
422
|
+
}
|
|
423
|
+
const pattern = this.config.highlightPattern;
|
|
424
|
+
if (typeof pattern === 'function') {
|
|
425
|
+
return pattern(text);
|
|
426
|
+
}
|
|
427
|
+
let regex;
|
|
428
|
+
if (typeof pattern === 'string') {
|
|
429
|
+
try {
|
|
430
|
+
regex = new RegExp(pattern, 'gi');
|
|
431
|
+
}
|
|
432
|
+
catch (e) {
|
|
433
|
+
console.warn('Invalid highlight pattern:', pattern);
|
|
434
|
+
return this.escapeHtml(text);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
else {
|
|
438
|
+
regex = pattern;
|
|
439
|
+
}
|
|
440
|
+
const escaped = this.escapeHtml(text);
|
|
441
|
+
return escaped.replace(regex, (match) => `<span class="cqa-text-primary">${match}</span>`);
|
|
442
|
+
}
|
|
443
|
+
escapeHtml(text) {
|
|
444
|
+
if (!text)
|
|
445
|
+
return '';
|
|
446
|
+
const div = document.createElement('div');
|
|
447
|
+
div.textContent = text;
|
|
448
|
+
return div.innerHTML;
|
|
449
|
+
}
|
|
450
|
+
get hasHighlighting() {
|
|
451
|
+
return !!this.config?.highlightPattern;
|
|
452
|
+
}
|
|
453
|
+
handleDocumentClick(event) {
|
|
454
|
+
if (!this.isOpen)
|
|
455
|
+
return;
|
|
456
|
+
const target = event.target;
|
|
457
|
+
if (!target)
|
|
458
|
+
return;
|
|
459
|
+
if (this.hostEl?.nativeElement && this.hostEl.nativeElement.contains(target)) {
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
this.closeDropdown();
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
WorkspaceSelectorComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: WorkspaceSelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
466
|
+
WorkspaceSelectorComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.4.0", type: WorkspaceSelectorComponent, selector: "cqa-workspace-selector", inputs: { form: "form", config: "config", value: "value" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange", selectClick: "selectClick", searchChange: "searchChange", loadMore: "loadMore" }, host: { listeners: { "document:click": "handleDocumentClick($event)" }, classAttribute: "cqa-ui-root" }, viewQueries: [{ propertyName: "hostEl", first: true, predicate: ["host"], descendants: true, read: ElementRef }, { propertyName: "dropdownPanel", first: true, predicate: ["dropdownPanel"], descendants: true }, { propertyName: "viewport", first: true, predicate: ["viewport"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cqa-ui-root\" #host>\n <ng-container [formGroup]=\"currentForm\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n \n <div class=\"workspace-selector-wrapper cqa-relative cqa-w-full\">\n <!-- Trigger Button -->\n <button\n type=\"button\"\n class=\"workspace-selector-trigger cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-px-4 cqa-py-2 cqa-border-solid cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-bg-white cqa-text-left cqa-cursor-pointer hover:cqa-border-[#9CA3AF] focus:cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#4F46E5] focus:cqa-ring-offset-1 disabled:cqa-opacity-50 disabled:cqa-cursor-not-allowed\"\n [disabled]=\"isDisabled\"\n (click)=\"toggleDropdown()\"\n [attr.aria-expanded]=\"isOpen\"\n aria-haspopup=\"listbox\">\n <span class=\"cqa-flex-1 cqa-truncate cqa-text-[14px] cqa-text-[#0A0A0A]\"\n [class.cqa-text-[#9CA3AF]]=\"!displayValue\">\n {{ displayValue || displayPlaceholder }}\n </span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-shrink-0\">\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-animate-spin\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n [class.cqa-rotate-180]=\"isOpen\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Panel -->\n <div\n #dropdownPanel\n *ngIf=\"isOpen\"\n class=\"workspace-selector-panel cqa-absolute cqa-z-50 cqa-w-full cqa-mt-1 cqa-bg-white cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-shadow-lg cqa-overflow-hidden\">\n \n <!-- Search Input -->\n <div *ngIf=\"config.searchable\" class=\"workspace-search-container cqa-p-2 cqa-border-b cqa-border-[#E5E7EB]\">\n <input\n type=\"text\"\n class=\"workspace-search-input cqa-w-full cqa-px-3 cqa-py-2 cqa-border cqa-border-[#D1D5DB] cqa-rounded-[6px] cqa-text-[14px] cqa-text-[#0A0A0A] focus:cqa-outline-none\"\n placeholder=\"Search...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" />\n </div>\n\n <!-- Options Container with Virtual Scroll -->\n <div class=\"workspace-options-container\">\n <!-- No results state -->\n <div *ngIf=\"displayedOptions.length === 0 && !(config?.isLoading || loadingMore)\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#9CA3AF] cqa-text-center\">\n No results\n </div>\n\n <cdk-virtual-scroll-viewport\n *ngIf=\"displayedOptions.length > 0\"\n #viewport\n [itemSize]=\"itemSize\"\n minBufferPx=\"200\"\n maxBufferPx=\"400\"\n [style.height.px]=\"viewportHeight\"\n style=\"width: 100%; display: block; overflow: auto;\"\n (scrolledIndexChange)=\"onScrolledIndexChange($event)\">\n \n <div\n *cdkVirtualFor=\"let opt of displayedOptions; trackBy: trackByOption\"\n class=\"workspace-option cqa-px-4 cqa-py-3 cqa-cursor-pointer hover:cqa-bg-[#F3F4F6] cqa-border-b cqa-border-[#E5E7EB] last:cqa-border-b-0\"\n [style.height.px]=\"itemSize\"\n [style.display]=\"'flex'\"\n [style.align-items]=\"'center'\"\n [class.cqa-bg-[#F3F4F6]]=\"isOptionSelected(opt)\"\n [class.cqa-bg-[#EEF2FF]]=\"isOptionSelected(opt)\"\n (click)=\"onOptionClick(opt)\">\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"hasHighlighting\"\n [innerHTML]=\"highlightText(getOptionLabel(opt))\"></span>\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"!hasHighlighting\">\n {{ getOptionLabel(opt) }}\n </span>\n </div>\n </cdk-virtual-scroll-viewport>\n\n <!-- Loading more indicator -->\n <div *ngIf=\"config?.hasMore && (loadingMore || config?.isLoading) && displayedOptions.length > 0\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#6B7280] cqa-text-center cqa-border-t cqa-border-[#E5E7EB]\">\n Loading...\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</div>\n\n", components: [{ type: i1.CdkVirtualScrollViewport, selector: "cdk-virtual-scroll-viewport", inputs: ["orientation", "appendOnly"], outputs: ["scrolledIndexChange"] }], directives: [{ type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i1.CdkFixedSizeVirtualScroll, selector: "cdk-virtual-scroll-viewport[itemSize]", inputs: ["itemSize", "minBufferPx", "maxBufferPx"] }, { type: i1.CdkVirtualForOf, selector: "[cdkVirtualFor][cdkVirtualForOf]", inputs: ["cdkVirtualForOf", "cdkVirtualForTrackBy", "cdkVirtualForTemplate", "cdkVirtualForTemplateCacheSize"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
467
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.4.0", ngImport: i0, type: WorkspaceSelectorComponent, decorators: [{
|
|
468
|
+
type: Component,
|
|
469
|
+
args: [{ selector: 'cqa-workspace-selector', changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cqa-ui-root' }, template: "<div class=\"cqa-ui-root\" #host>\n <ng-container [formGroup]=\"currentForm\">\n <label *ngIf=\"config.label\"\n class=\"form-label cqa-text-[#374151] cqa-text-[14px] cqa-font-medium cqa-block cqa-leading-[1.4] cqa-mb-2\">{{\n config.label }}</label>\n \n <div class=\"workspace-selector-wrapper cqa-relative cqa-w-full\">\n <!-- Trigger Button -->\n <button\n type=\"button\"\n class=\"workspace-selector-trigger cqa-w-full cqa-flex cqa-items-center cqa-justify-between cqa-px-4 cqa-py-2 cqa-border-solid cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-bg-white cqa-text-left cqa-cursor-pointer hover:cqa-border-[#9CA3AF] focus:cqa-outline-none focus:cqa-ring-2 focus:cqa-ring-[#4F46E5] focus:cqa-ring-offset-1 disabled:cqa-opacity-50 disabled:cqa-cursor-not-allowed\"\n [disabled]=\"isDisabled\"\n (click)=\"toggleDropdown()\"\n [attr.aria-expanded]=\"isOpen\"\n aria-haspopup=\"listbox\">\n <span class=\"cqa-flex-1 cqa-truncate cqa-text-[14px] cqa-text-[#0A0A0A]\"\n [class.cqa-text-[#9CA3AF]]=\"!displayValue\">\n {{ displayValue || displayPlaceholder }}\n </span>\n <div class=\"cqa-flex cqa-items-center cqa-gap-2 cqa-flex-shrink-0\">\n <svg *ngIf=\"loadingMore || config?.isLoading\" width=\"16\" height=\"16\" viewBox=\"0 0 50 50\" aria-label=\"loading\"\n xmlns=\"http://www.w3.org/2000/svg\" class=\"cqa-animate-spin\">\n <circle cx=\"25\" cy=\"25\" r=\"20\" stroke=\"#E5E7EB\" stroke-width=\"6\" fill=\"none\"/>\n <path d=\"M45 25a20 20 0 0 0-20-20\" stroke=\"#4F46E5\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\">\n <animateTransform attributeName=\"transform\" type=\"rotate\" from=\"0 25 25\" to=\"360 25 25\"\n dur=\"0.8s\" repeatCount=\"indefinite\"/>\n </path>\n </svg>\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\n [class.cqa-rotate-180]=\"isOpen\">\n <path d=\"M4 6L8 10L12 6\" stroke=\"#0A0A0A\" stroke-width=\"1.33333\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\" />\n </svg>\n </div>\n </button>\n\n <!-- Dropdown Panel -->\n <div\n #dropdownPanel\n *ngIf=\"isOpen\"\n class=\"workspace-selector-panel cqa-absolute cqa-z-50 cqa-w-full cqa-mt-1 cqa-bg-white cqa-border cqa-border-[#D1D5DB] cqa-rounded-[8px] cqa-shadow-lg cqa-overflow-hidden\">\n \n <!-- Search Input -->\n <div *ngIf=\"config.searchable\" class=\"workspace-search-container cqa-p-2 cqa-border-b cqa-border-[#E5E7EB]\">\n <input\n type=\"text\"\n class=\"workspace-search-input cqa-w-full cqa-px-3 cqa-py-2 cqa-border cqa-border-[#D1D5DB] cqa-rounded-[6px] cqa-text-[14px] cqa-text-[#0A0A0A] focus:cqa-outline-none\"\n placeholder=\"Search...\"\n [value]=\"searchText\"\n (input)=\"onSearchInput($any($event.target).value)\"\n (click)=\"$event.stopPropagation()\"\n (mousedown)=\"$event.stopPropagation()\"\n (keydown)=\"$event.stopPropagation()\" />\n </div>\n\n <!-- Options Container with Virtual Scroll -->\n <div class=\"workspace-options-container\">\n <!-- No results state -->\n <div *ngIf=\"displayedOptions.length === 0 && !(config?.isLoading || loadingMore)\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#9CA3AF] cqa-text-center\">\n No results\n </div>\n\n <cdk-virtual-scroll-viewport\n *ngIf=\"displayedOptions.length > 0\"\n #viewport\n [itemSize]=\"itemSize\"\n minBufferPx=\"200\"\n maxBufferPx=\"400\"\n [style.height.px]=\"viewportHeight\"\n style=\"width: 100%; display: block; overflow: auto;\"\n (scrolledIndexChange)=\"onScrolledIndexChange($event)\">\n \n <div\n *cdkVirtualFor=\"let opt of displayedOptions; trackBy: trackByOption\"\n class=\"workspace-option cqa-px-4 cqa-py-3 cqa-cursor-pointer hover:cqa-bg-[#F3F4F6] cqa-border-b cqa-border-[#E5E7EB] last:cqa-border-b-0\"\n [style.height.px]=\"itemSize\"\n [style.display]=\"'flex'\"\n [style.align-items]=\"'center'\"\n [class.cqa-bg-[#F3F4F6]]=\"isOptionSelected(opt)\"\n [class.cqa-bg-[#EEF2FF]]=\"isOptionSelected(opt)\"\n (click)=\"onOptionClick(opt)\">\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"hasHighlighting\"\n [innerHTML]=\"highlightText(getOptionLabel(opt))\"></span>\n <span class=\"cqa-text-[14px] cqa-text-[#0A0A0A]\"\n *ngIf=\"!hasHighlighting\">\n {{ getOptionLabel(opt) }}\n </span>\n </div>\n </cdk-virtual-scroll-viewport>\n\n <!-- Loading more indicator -->\n <div *ngIf=\"config?.hasMore && (loadingMore || config?.isLoading) && displayedOptions.length > 0\"\n class=\"cqa-px-4 cqa-py-3 cqa-text-[14px] cqa-text-[#6B7280] cqa-text-center cqa-border-t cqa-border-[#E5E7EB]\">\n Loading...\n </div>\n </div>\n </div>\n </div>\n </ng-container>\n</div>\n\n" }]
|
|
470
|
+
}], ctorParameters: function () { return []; }, propDecorators: { form: [{
|
|
471
|
+
type: Input
|
|
472
|
+
}], config: [{
|
|
473
|
+
type: Input
|
|
474
|
+
}], value: [{
|
|
475
|
+
type: Input
|
|
476
|
+
}], valueChange: [{
|
|
477
|
+
type: Output
|
|
478
|
+
}], selectionChange: [{
|
|
479
|
+
type: Output
|
|
480
|
+
}], selectClick: [{
|
|
481
|
+
type: Output
|
|
482
|
+
}], searchChange: [{
|
|
483
|
+
type: Output
|
|
484
|
+
}], loadMore: [{
|
|
485
|
+
type: Output
|
|
486
|
+
}], hostEl: [{
|
|
487
|
+
type: ViewChild,
|
|
488
|
+
args: ['host', { static: false, read: ElementRef }]
|
|
489
|
+
}], dropdownPanel: [{
|
|
490
|
+
type: ViewChild,
|
|
491
|
+
args: ['dropdownPanel', { static: false }]
|
|
492
|
+
}], viewport: [{
|
|
493
|
+
type: ViewChild,
|
|
494
|
+
args: ['viewport', { static: false }]
|
|
495
|
+
}], handleDocumentClick: [{
|
|
496
|
+
type: HostListener,
|
|
497
|
+
args: ['document:click', ['$event']]
|
|
498
|
+
}] } });
|
|
499
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvZGFzaGJvYXJkcy93b3Jrc3BhY2Utc2VsZWN0b3Ivd29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvZGFzaGJvYXJkcy93b3Jrc3BhY2Utc2VsZWN0b3Ivd29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFvQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZLLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7O0FBOEN4RCxNQUFNLE9BQU8sMEJBQTBCO0lBNENyQztRQXZDQSxpRUFBaUU7UUFDdkQsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO1FBQ3RDLG9CQUFlLEdBQUcsSUFBSSxZQUFZLEVBQXNELENBQUM7UUFDekYsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBUSxDQUFDO1FBQ2pELHFFQUFxRTtRQUMzRCxpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFrQyxDQUFDO1FBQzVFLHdFQUF3RTtRQUM5RCxhQUFRLEdBQUcsSUFBSSxZQUFZLEVBQWtDLENBQUM7UUFVeEUsZUFBVSxHQUFXLEVBQUUsQ0FBQztRQUN4QixXQUFNLEdBQVksS0FBSyxDQUFDO1FBQ3hCLGdCQUFXLEdBQUcsS0FBSyxDQUFDO1FBQ1osc0JBQWlCLEdBQUcsQ0FBQyxDQUFDO1FBQ3RCLHlCQUFvQixHQUFHLEtBQUssQ0FBQztRQUc3QixrQkFBYSxHQUFHLEdBQUcsRUFBRTtZQUMzQixJQUFJLENBQUMsb0JBQW9CLEdB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LFlBQVk7c0JBQXJCLE1BQU07Z0JBRUcsUUFBUTtzQkFBakIsTUFBTTtnQkFFaUQsTUFBTTtzQkFBN0QsU0FBUzt1QkFBQyxNQUFNLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7Z0JBQ1AsYUFBYTtzQkFBM0QsU0FBUzt1QkFBQyxlQUFlLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUNILFFBQVE7c0JBQWpELFNBQVM7dUJBQUMsVUFBVSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFvZHhDLG1CQUFtQjtzQkFEbEIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIElucHV0LCBPbkluaXQsIE9uQ2hhbmdlcywgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkLCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIE91dHB1dCwgRXZlbnRFbWl0dGVyIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtR3JvdXAsIEZvcm1Db250cm9sIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgU2VsZWN0T3B0aW9uIH0gZnJvbSAnLi4vLi4vZHluYW1pYy1zZWxlY3QvZHluYW1pYy1zZWxlY3QtZmllbGQuY29tcG9uZW50JztcblxuZXhwb3J0IGludGVyZmFjZSBXb3Jrc3BhY2VTZWxlY3RvckNvbmZpZyB7XG4gIGtleT86IHN0cmluZztcbiAgbGFiZWw/OiBzdHJpbmc7XG4gIHBsYWNlaG9sZGVyPzogc3RyaW5nO1xuICBkaXNhYmxlZD86IGJvb2xlYW47XG4gIHNlYXJjaGFibGU/OiBib29sZWFuO1xuICAvKiogSWYgdHJ1ZSwgY2xvc2UgdGhlIHBhbmVsIHdoZW4gYW4gb3B0aW9uIGlzIHNlbGVjdGVkLiAqL1xuICBjbG9zZU9uU2VsZWN0PzogYm9vbGVhbjtcbiAgLyoqIFByb3ZpZGUgYSBkZWZhdWx0IHNlbGVjdGVkIHZhbHVlIGlmIHRoZSBjb250cm9sIGhhcyBubyB2YWx1ZSB5ZXQuICovXG4gIHNlbGVjdGVkVmFsdWU/OiBhbnk7XG4gIC8qKiBPcHRpb25hbCBjYWxsYmFjayBpbnZva2VkIHdoZW5ldmVyIHRoZSBzZWxlY3Rpb24gY2hhbmdlcy4gKi9cbiAgb25DaGFuZ2U/OiAodmFsdWU6IGFueSkgPT4gdm9pZDtcbiAgLyoqIEVuYWJsZSBzZXJ2ZXItc2lkZSBzZWFyY2ggbW9kZTsgY29tcG9uZW50IHdpbGwgZW1pdCBzZWFyY2ggaW5zdGVhZCBvZiBsb2NhbCBmaWx0ZXJpbmcuICovXG4gIHNlcnZlclNlYXJjaD86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGVuIHRydWUsIHRyaWdnZXJzIGFuIGluaXRpYWwgc2VhcmNoIGVtaXQgb24gcGFuZWwgb3BlbiAoc2VydmVyU2VhcmNoIG1vZGUgb25seSkuXG4gICAqIERlZmF1bHRzIHRvIGZhbHNlIHNvIG9wZW5pbmcgdGhlIGRyb3Bkb3duIGRvZXMgTk9UIGNhbGwgdGhlIEFQSS5cbiAgICovXG4gIGluaXRpYWxGZXRjaE9uT3Blbj86IGJvb2xlYW47XG4gIC8qKiBJbmRpY2F0ZXMgbW9yZSByZXN1bHRzIGFyZSBhdmFpbGFibGUgZm9yIGluZmluaXRlIHNjcm9sbC4gKi9cbiAgaGFzTW9yZT86IGJvb2xlYW47XG4gIC8qKiBPcHRpb25hbCBsb2FkaW5nIGZsYWcgY29udHJvbGxlZCBieSBjb25zdW1lciB0byBzaG93IGxvYWRpbmcgc3RhdGUuICovXG4gIGlzTG9hZGluZz86IGJvb2xlYW47XG4gIC8qKiBPcHRpb25hbCBjYWxsYmFjayBmb3Igc2VydmVyLXNpZGUgc2VhcmNoIHdoZW4gcXVlcnkgY2hhbmdlcy4gKi9cbiAgb25TZWFyY2g/OiAocXVlcnk6IHN0cmluZykgPT4gdm9pZDtcbiAgLyoqIE9wdGlvbmFsIGNhbGxiYWNrIHdoZW4gbW9yZSBkYXRhIGlzIHJlcXVlc3RlZCAoaW5maW5pdGUgc2Nyb2xsKS4gKi9cbiAgb25Mb2FkTW9yZT86IChxdWVyeT86IHN0cmluZykgPT4gdm9pZDtcbiAgLyoqIE9wdGlvbmFsIHJlZ2V4IHBhdHRlcm4gb3IgZnVuY3Rpb24gdG8gaGlnaGxpZ2h0IHBhcnRzIG9mIG9wdGlvbiB0ZXh0LiAqL1xuICBoaWdobGlnaHRQYXR0ZXJuPzogUmVnRXhwIHwgc3RyaW5nIHwgKCh0ZXh0OiBzdHJpbmcpID0+IHN0cmluZyk7XG4gIG9wdGlvbnM6IFNlbGVjdE9wdGlvbltdO1xuICB2YWx1ZUJ5Pzogc3RyaW5nO1xuICAvKiogSXRlbSBzaXplIGZvciB2aXJ0dWFsIHNjcm9sbCAoZGVmYXVsdDogNDgpICovXG4gIGl0ZW1TaXplPzogbnVtYmVyO1xuICAvKiogVmlld3BvcnQgaGVpZ2h0IGZvciB2aXJ0dWFsIHNjcm9sbCBpbiBwaXhlbHMgKGRlZmF1bHQ6IDMwMCkgKi9cbiAgdmlld3BvcnRIZWlnaHQ/OiBudW1iZXI7XG59XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2NxYS13b3Jrc3BhY2Utc2VsZWN0b3InLFxuICB0ZW1wbGF0ZVVybDogJy4vd29ya3NwYWNlLXNlbGVjdG9yLmNvbXBvbmVudC5odG1sJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHsgY2xhc3M6ICdjcWEtdWktcm9vdCcgfVxufSlcbmV4cG9ydCBjbGFzcyBXb3Jrc3BhY2VTZWxlY3RvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzIHtcbiAgQElucHV0KCkgZm9ybT86IEZvcm1Hcm91cDtcbiAgQElucHV0KCkgY29uZmlnITogV29ya3NwYWNlU2VsZWN0b3JDb25maWc7XG4gIC8qKiBEaXJlY3QgdmFsdWUgYmluZGluZyAtIHNlbGVjdGVkIHdvcmtzcGFjZSBvYmplY3QuIFVzZSB0aGlzIGluc3RlYWQgb2YgZm9ybSBjb250cm9sLiAqL1xuICBASW5wdXQoKSB2YWx1ZT86IGFueTtcbiAgLyoqIEVtaXRzIHRoZSBzZWxlY3RlZCB3b3Jrc3BhY2Ugb2JqZWN0IHdoZW4gc2VsZWN0aW9uIGNoYW5nZXMgKi9cbiAgQE91dHB1dCgpIHZhbHVlQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIEBPdXRwdXQoKSBzZWxlY3Rpb25DaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHsga2V5OiBzdHJpbmc7IHZhbHVlOiBhbnk7IG9wdGlvbj86IFNlbGVjdE9wdGlvbiB9PigpO1xuICBAT3V0cHV0KCkgc2VsZWN0Q2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG4gIC8qKiBFbWl0cyB3aGVuIHVzZXIgdHlwZXMgaW4gc2VhcmNoIGJveCAodXNlZnVsIGZvciBzZXJ2ZXIgc2VhcmNoKSAqL1xuICBAT3V0cHV0KCkgc2VhcmNoQ2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjx7IGtleTogc3RyaW5nOyBxdWVyeTogc3RyaW5nIH0+KCk7XG4gIC8qKiBFbWl0cyB3aGVuIHRoZSBjb21wb25lbnQgcmVxdWVzdHMgbW9yZSBkYXRhIGZvciB0aGUgY3VycmVudCBxdWVyeSAqL1xuICBAT3V0cHV0KCkgbG9hZE1vcmUgPSBuZXcgRXZlbnRFbWl0dGVyPHsga2V5OiBzdHJpbmc7IHF1ZXJ5OiBzdHJpbmcgfT4oKTtcblxuICBAVmlld0NoaWxkKCdob3N0JywgeyBzdGF0aWM6IGZhbHNlLCByZWFkOiBFbGVtZW50UmVmIH0pIGhvc3RFbD86IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuICBAVmlld0NoaWxkKCdkcm9wZG93blBhbmVsJywgeyBzdGF0aWM6IGZhbHNlIH0pIGRyb3Bkb3duUGFuZWw/OiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcbiAgQFZpZXdDaGlsZCgndmlld3BvcnQnLCB7IHN0YXRpYzogZmFsc2UgfSkgdmlld3BvcnQ/OiBhbnk7XG5cbiAgLy8gSW50ZXJuYWwgZm9ybSBjb250cm9sIGlmIG5vIGZvcm0gaXMgcHJvdmlkZWRcbiAgaW50ZXJuYWxGb3JtOiBGb3JtR3JvdXA7XG4gIGludGVybmFsQ29udHJvbDogRm9ybUNvbnRyb2w7XG5cbiAgc2VhcmNoVGV4dDogc3RyaW5nID0gJyc7XG4gIGlzT3BlbjogYm9vbGVhbiA9IGZhbHNlO1xuICBsb2FkaW5nTW9yZSA9IGZhbHNlO1xuICBwcml2YXRlIGxhc3RPcHRpb25zTGVuZ3RoID0gMDtcbiAgcHJpdmF0ZSBoYXNTY3JvbGxlZFNpbmNlT3BlbiA9IGZhbHNlO1xuICBwcml2YXRlIHBhbmVsU2Nyb2xsRWw/OiBIVE1MRWxlbWVudDtcblxuICBwcml2YXRlIG9uUGFuZWxTY3JvbGwgPSAoKSA9PiB7XG4gICAgdGhpcy5oYXNTY3JvbGxlZFNpbmNlT3BlbiA9IHRydWU7XG4gICAgaWYgKCF0aGlzLmNvbmZpZz8uaGFzTW9yZSB8fCB0aGlzLmxvYWRpbmdNb3JlKSByZXR1cm47XG4gICAgY29uc3QgZWwgPSB0aGlzLnBhbmVsU2Nyb2xsRWw7XG4gICAgaWYgKCFlbCkgcmV0dXJuO1xuICAgIGNvbnN0IG5lYXJCb3R0b20gPSBlbC5zY3JvbGxUb3AgKyBlbC5jbGllbnRIZWlnaHQgPj0gZWwuc2Nyb2xsSGVpZ2h0IC0gNDg7XG4gICAgaWYgKG5lYXJCb3R0b20pIHtcbiAgICAgIHRoaXMubG9hZGluZ01vcmUgPSB0cnVlO1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5jb25maWc/LmtleSB8fCAnJztcbiAgICAgIGNvbnN0IHEgPSB0aGlzLnNlYXJjaFRleHQgfHwgJyc7XG4gICAgICB0aGlzLmxvYWRNb3JlLmVtaXQoeyBrZXksIHF1ZXJ5OiBxIH0pO1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25Mb2FkTW9yZT8uKHEpOyB9IGNhdGNoIHt9XG4gICAgfVxuICB9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuaW50ZXJuYWxDb250cm9sID0gbmV3IEZvcm1Db250cm9sKCk7XG4gICAgdGhpcy5pbnRlcm5hbEZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgIHZhbHVlOiB0aGlzLmludGVybmFsQ29udHJvbFxuICAgIH0pO1xuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjcWEtd29ya3NwYWNlLXNlbGVjdG9yOiBpbnB1dCBcImNvbmZpZ1wiIGlzIHJlcXVpcmVkLicpO1xuICAgIH1cbiAgICB0aGlzLnN5bmNWYWx1ZUZyb21JbnB1dCgpO1xuICAgIHRoaXMuYXBwbHlTZWxlY3RlZFZhbHVlSWZOZWVkZWQoKTtcbiAgICB0aGlzLnN5bmNEaXNhYmxlZFN0YXRlKCk7XG4gICAgdGhpcy5sYXN0T3B0aW9uc0xlbmd0aCA9ICh0aGlzLmNvbmZpZz8ub3B0aW9ucyB8fCBbXSkubGVuZ3RoO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIGlmICgnY29uZmlnJyBpbiBjaGFuZ2VzIHx8ICdmb3JtJyBpbiBjaGFuZ2VzIHx8ICd2YWx1ZScgaW4gY2hhbmdlcykge1xuICAgICAgdGhpcy5zeW5jRGlzYWJsZWRTdGF0ZSgpO1xuICAgIH1cbiAgICBpZiAoJ3ZhbHVlJyBpbiBjaGFuZ2VzICYmICF0aGlzLmZvcm0pIHtcbiAgICAgIC8vIFN5bmMgaW50ZXJuYWwgY29udHJvbCB3aGVuIHZhbHVlIGNoYW5nZXMgKGZvciBkaXJlY3QgYmluZGluZyBtb2RlKVxuICAgICAgdGhpcy5zeW5jVmFsdWVGcm9tSW5wdXQoKTtcbiAgICB9XG4gICAgaWYgKCdjb25maWcnIGluIGNoYW5nZXMpIHtcbiAgICAgIHRoaXMuc3luY0NvbnRyb2xWYWx1ZUZvck11bHRpcGxlTW9kZSgpO1xuICAgICAgdGhpcy5hcHBseVNlbGVjdGVkVmFsdWVJZk5lZWRlZCgpO1xuICAgICAgaWYgKHRoaXMuY29uZmlnPy5pc0xvYWRpbmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLmxvYWRpbmdNb3JlID0gdGhpcy5jb25maWcuaXNMb2FkaW5nO1xuICAgICAgfVxuICAgICAgY29uc3QgbGVuID0gKHRoaXMuY29uZmlnPy5vcHRpb25zIHx8IFtdKS5sZW5ndGg7XG4gICAgICBpZiAobGVuID4gdGhpcy5sYXN0T3B0aW9uc0xlbmd0aCkge1xuICAgICAgICBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmdNb3JlID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICB0aGlzLmxhc3RPcHRpb25zTGVuZ3RoID0gbGVuO1xuICAgICAgaWYgKCF0aGlzLmNvbmZpZz8uaGFzTW9yZSkge1xuICAgICAgICBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gZmFsc2UpIHtcbiAgICAgICAgICB0aGlzLmxvYWRpbmdNb3JlID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5jb25maWc/LmlzTG9hZGluZyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGlmICgnZm9ybScgaW4gY2hhbmdlcyAmJiAhY2hhbmdlc1snZm9ybSddLmZpcnN0Q2hhbmdlKSB7XG4gICAgICB0aGlzLmFwcGx5U2VsZWN0ZWRWYWx1ZUlmTmVlZGVkKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzeW5jVmFsdWVGcm9tSW5wdXQoKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmZvcm0gJiYgdGhpcy52YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAvLyBTeW5jIHRoZSBpbnRlcm5hbCBjb250cm9sIHdpdGggdGhlIGRpcmVjdCB2YWx1ZSBiaW5kaW5nXG4gICAgICAvLyBFbnN1cmUgdmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh0aGlzLnZhbHVlKSkge1xuICAgICAgICB0aGlzLnZhbHVlID0gdGhpcy52YWx1ZS5sZW5ndGggPyB0aGlzLnZhbHVlWzBdIDogbnVsbDtcbiAgICAgIH1cbiAgICAgIHRoaXMuaW50ZXJuYWxDb250cm9sLnNldFZhbHVlKHRoaXMudmFsdWUgPz8gbnVsbCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH1cbiAgfVxuXG4gIGdldCBjdXJyZW50Rm9ybSgpOiBGb3JtR3JvdXAge1xuICAgIHJldHVybiB0aGlzLmZvcm0gfHwgdGhpcy5pbnRlcm5hbEZvcm07XG4gIH1cblxuICBnZXQgY29udHJvbEtleSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNvbmZpZz8ua2V5IHx8ICd2YWx1ZSc7XG4gIH1cblxuICBnZXQgY3VycmVudENvbnRyb2woKTogRm9ybUNvbnRyb2wge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRGb3JtLmdldCh0aGlzLmNvbnRyb2xLZXkpIGFzIEZvcm1Db250cm9sIHx8IHRoaXMuaW50ZXJuYWxDb250cm9sO1xuICB9XG5cbiAgLyoqIEdldCBjdXJyZW50IHZhbHVlIC0gZnJvbSBmb3JtIGNvbnRyb2wgaWYgZm9ybSBwcm92aWRlZCwgb3RoZXJ3aXNlIGZyb20gZGlyZWN0IHZhbHVlIGJpbmRpbmcgKi9cbiAgZ2V0IGN1cnJlbnRWYWx1ZSgpOiBhbnkge1xuICAgIGlmICh0aGlzLmZvcm0pIHtcbiAgICAgIHJldHVybiB0aGlzLmN1cnJlbnRDb250cm9sLnZhbHVlO1xuICAgIH1cbiAgICAvLyBFbnN1cmUgdmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy52YWx1ZSkpIHtcbiAgICAgIHJldHVybiB0aGlzLnZhbHVlLmxlbmd0aCA/IHRoaXMudmFsdWVbMF0gOiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy52YWx1ZSA/PyBudWxsO1xuICB9XG5cbiAgLyoqIFNldCBjdXJyZW50IHZhbHVlIC0gdG8gZm9ybSBjb250cm9sIGlmIGZvcm0gcHJvdmlkZWQsIG90aGVyd2lzZSB1cGRhdGUgZGlyZWN0IHZhbHVlICovXG4gIHNldCBjdXJyZW50VmFsdWUodmFsOiBhbnkpIHtcbiAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICB0aGlzLmN1cnJlbnRDb250cm9sLnNldFZhbHVlKHZhbCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFbnN1cmUgdmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgICB0aGlzLnZhbHVlID0gQXJyYXkuaXNBcnJheSh2YWwpID8gKHZhbC5sZW5ndGggPyB2YWxbMF0gOiBudWxsKSA6IHZhbDtcbiAgICAgIC8vIFN5bmMgaW50ZXJuYWwgY29udHJvbCBmb3IgZGlzcGxheSBwdXJwb3Nlc1xuICAgICAgdGhpcy5pbnRlcm5hbENvbnRyb2wuc2V0VmFsdWUodGhpcy52YWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgIH1cbiAgfVxuXG4gIGdldCBpc0Rpc2FibGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnRvQm9vbGVhbih0aGlzLmNvbmZpZz8uZGlzYWJsZWQpO1xuICB9XG5cbiAgZ2V0IGRpc3BsYXlQbGFjZWhvbGRlcigpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGN1cnJlbnRWYWwgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICByZXR1cm4gdGhpcy5oYXNFeGlzdGluZ1ZhbHVlKGN1cnJlbnRWYWwpID8gdW5kZWZpbmVkIDogKHRoaXMuY29uZmlnPy5wbGFjZWhvbGRlciB8fCAnU2VsZWN0Li4uJyk7XG4gIH1cblxuICBnZXQgZGlzcGxheVZhbHVlKCk6IHN0cmluZyB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuICcnO1xuICAgIFxuICAgIC8vIElmIHZhbHVlIGlzIGFscmVhZHkgYSBTZWxlY3RPcHRpb24tbGlrZSBvYmplY3Qgd2l0aCBuYW1lL2xhYmVsLCB1c2UgaXQgZGlyZWN0bHlcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCkge1xuICAgICAgY29uc3Qgd29ya3NwYWNlT2JqID0gdmFsdWUgYXMgYW55O1xuICAgICAgaWYgKHdvcmtzcGFjZU9iai5uYW1lIHx8IHdvcmtzcGFjZU9iai5sYWJlbCkge1xuICAgICAgICByZXR1cm4gd29ya3NwYWNlT2JqLm5hbWUgPz8gd29ya3NwYWNlT2JqLmxhYmVsID8/IFN0cmluZyh3b3Jrc3BhY2VPYmoudmFsdWUgPz8gd29ya3NwYWNlT2JqLmlkID8/ICcnKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgLy8gT3RoZXJ3aXNlLCBsb29rIHVwIHRoZSB2YWx1ZSBpbiBvcHRpb25zIGxpc3RcbiAgICBjb25zdCBvcHRpb24gPSB0aGlzLmNvbmZpZz8ub3B0aW9ucz8uZmluZChvcHQgPT4gdGhpcy5nZXRPcHRpb25WYWx1ZShvcHQpID09PSB2YWx1ZSk7XG4gICAgcmV0dXJuIG9wdGlvbiA/IHRoaXMuZ2V0T3B0aW9uTGFiZWwob3B0aW9uKSA6IFN0cmluZyh2YWx1ZSk7XG4gIH1cblxuICBnZXQgaXRlbVNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5jb25maWc/Lml0ZW1TaXplIHx8IDM1O1xuICB9XG5cbiAgZ2V0IHZpZXdwb3J0SGVpZ2h0KCk6IG51bWJlciB7XG4gICAgLy8gSWYgdmlld3BvcnRIZWlnaHQgaXMgZXhwbGljaXRseSBzZXQgaW4gY29uZmlnLCB1c2UgaXRcbiAgICBpZiAodGhpcy5jb25maWc/LnZpZXdwb3J0SGVpZ2h0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmNvbmZpZy52aWV3cG9ydEhlaWdodDtcbiAgICB9XG4gICAgXG4gICAgLy8gT3RoZXJ3aXNlLCBjYWxjdWxhdGUgYmFzZWQgb24gbnVtYmVyIG9mIG9wdGlvbnNcbiAgICBjb25zdCBvcHRpb25Db3VudCA9IHRoaXMuZGlzcGxheWVkT3B0aW9ucy5sZW5ndGg7XG4gICAgY29uc3QgbWF4SGVpZ2h0ID0gMzAwOyAvLyBNYXhpbXVtIGhlaWdodFxuICAgIGNvbnN0IG1pbkhlaWdodCA9IDEwMDsgLy8gTWluaW11bSBoZWlnaHRcbiAgICBjb25zdCBjYWxjdWxhdGVkSGVpZ2h0ID0gb3B0aW9uQ291bnQgKiB0aGlzLml0ZW1TaXplO1xuICAgIFxuICAgIC8vIFJldHVybiBjYWxjdWxhdGVkIGhlaWdodCwgYnV0IGNsYW1wIGJldHdlZW4gbWluIGFuZCBtYXhcbiAgICByZXR1cm4gTWF0aC5taW4oTWF0aC5tYXgoY2FsY3VsYXRlZEhlaWdodCwgbWluSGVpZ2h0KSwgbWF4SGVpZ2h0KTtcbiAgfVxuXG4gIGdldCBkaXNwbGF5ZWRPcHRpb25zKCk6IFNlbGVjdE9wdGlvbltdIHtcbiAgICByZXR1cm4gdGhpcy5maWx0ZXJlZE9wdGlvbnMoKTtcbiAgfVxuXG4gIHByaXZhdGUgdG9Cb29sZWFuKHZhbHVlOiB1bmtub3duKTogYm9vbGVhbiB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGNvbnN0IHYgPSB2YWx1ZS50cmltKCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIGlmICh2ID09PSAndHJ1ZScgfHwgdiA9PT0gJzEnKSByZXR1cm4gdHJ1ZTtcbiAgICAgIGlmICh2ID09PSAnZmFsc2UnIHx8IHYgPT09ICcwJyB8fCB2ID09PSAnJykgcmV0dXJuIGZhbHNlO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICByZXR1cm4gdmFsdWUgIT09IDA7XG4gICAgfVxuICAgIHJldHVybiAhIXZhbHVlO1xuICB9XG5cbiAgZ2V0T3B0aW9uVmFsdWUob3B0OiBTZWxlY3RPcHRpb24gfCBudWxsIHwgdW5kZWZpbmVkKTogYW55IHtcbiAgICBpZiAoIW9wdCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5jb25maWc/LnZhbHVlQnkpIHtcbiAgICAgIHJldHVybiAob3B0IGFzIGFueSlbdGhpcy5jb25maWcudmFsdWVCeV07XG4gICAgfVxuICAgIHJldHVybiBvcHQuaWQgPz8gb3B0LnZhbHVlO1xuICB9XG5cbiAgZ2V0T3B0aW9uTGFiZWwob3B0OiBTZWxlY3RPcHRpb24pOiBzdHJpbmcge1xuICAgIHJldHVybiBvcHQubmFtZSA/PyBvcHQubGFiZWwgPz8gb3B0LnZhbHVlID8/ICcnO1xuICB9XG5cbiAgcHJpdmF0ZSBzeW5jRGlzYWJsZWRTdGF0ZSgpOiB2b2lkIHtcbiAgICBjb25zdCBzaG91bGREaXNhYmxlID0gdGhpcy50b0Jvb2xlYW4odGhpcy5jb25maWc/LmRpc2FibGVkKTtcbiAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICBpZiAoc2hvdWxkRGlzYWJsZSkge1xuICAgICAgICB0aGlzLmN1cnJlbnRDb250cm9sLmRpc2FibGUoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5jdXJyZW50Q29udHJvbC5lbmFibGUoeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBGb3IgZGlyZWN0IHZhbHVlIGJpbmRpbmcsIGRpc2FibGVkIHN0YXRlIGlzIGhhbmRsZWQgdmlhIFtkaXNhYmxlZF0gYmluZGluZyBpbiB0ZW1wbGF0ZVxuICB9XG5cbiAgcHJpdmF0ZSBzeW5jQ29udHJvbFZhbHVlRm9yTXVsdGlwbGVNb2RlKCk6IHZvaWQge1xuICAgIC8vIE5vIGxvbmdlciBuZWVkZWQgLSBzaW5nbGUgc2VsZWN0aW9uIG9ubHlcbiAgICBjb25zdCBjdXJyZW50VmFsID0gdGhpcy5jdXJyZW50VmFsdWU7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkoY3VycmVudFZhbCkpIHtcbiAgICAgIHRoaXMuY3VycmVudFZhbHVlID0gY3VycmVudFZhbC5sZW5ndGggPyBjdXJyZW50VmFsWzBdIDogbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFwcGx5U2VsZWN0ZWRWYWx1ZUlmTmVlZGVkKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1cnJlbnRWYWwgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICBpZiAodGhpcy5oYXNFeGlzdGluZ1ZhbHVlKGN1cnJlbnRWYWwpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIENoZWNrIGJvdGggY29uZmlnLnNlbGVjdGVkVmFsdWUgYW5kIGRpcmVjdCB2YWx1ZSBpbnB1dFxuICAgIGNvbnN0IHNlbGVjdGVkVmFsdWUgPSB0aGlzLnZhbHVlICE9PSB1bmRlZmluZWQgPyB0aGlzLnZhbHVlIDogdGhpcy5jb25maWc/LnNlbGVjdGVkVmFsdWU7XG4gICAgaWYgKHNlbGVjdGVkVmFsdWUgPT09IHVuZGVmaW5lZCB8fCBzZWxlY3RlZFZhbHVlID09PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRW5zdXJlIHNlbGVjdGVkVmFsdWUgaXMgbm90IGFuIGFycmF5IChzaW5nbGUgc2VsZWN0aW9uIG9ubHkpXG4gICAgY29uc3Qgbm9ybWFsaXplZCA9IEFycmF5LmlzQXJyYXkoc2VsZWN0ZWRWYWx1ZSlcbiAgICAgID8gKHNlbGVjdGVkVmFsdWUubGVuZ3RoID8gc2VsZWN0ZWRWYWx1ZVswXSA6IHVuZGVmaW5lZClcbiAgICAgIDogc2VsZWN0ZWRWYWx1ZTtcbiAgICBpZiAobm9ybWFsaXplZCA9PT0gdW5kZWZpbmVkKSByZXR1cm47XG4gICAgdGhpcy5jdXJyZW50VmFsdWUgPSBub3JtYWxpemVkO1xuICB9XG5cbiAgcHJpdmF0ZSBoYXNFeGlzdGluZ1ZhbHVlKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiB2YWx1ZS5zb21lKCh2YWwpID0+IHZhbCAhPT0gbnVsbCAmJiB2YWwgIT09IHVuZGVmaW5lZCAmJiB2YWwgIT09ICcnKTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHJldHVybiB2YWx1ZS50cmltKCkubGVuZ3RoID4gMDtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpc09wdGlvblNlbGVjdGVkKG9wdDogU2VsZWN0T3B0aW9uKTogYm9vbGVhbiB7XG4gICAgY29uc3QgY3VycmVudFZhbCA9IHRoaXMuY3VycmVudFZhbHVlO1xuICAgIGlmIChjdXJyZW50VmFsID09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgICBcbiAgICBjb25zdCBvcHRpb25WYWx1ZSA9IHRoaXMuZ2V0T3B0aW9uVmFsdWUob3B0KTtcbiAgICBcbiAgICAvLyBJZiBjdXJyZW50VmFsIGlzIGFuIG9iamVjdCB3aXRoIGlkL3ZhbHVlLCBleHRyYWN0IGl0IGZvciBjb21wYXJpc29uXG4gICAgaWYgKHR5cGVvZiBjdXJyZW50VmFsID09PSAnb2JqZWN0JyAmJiBjdXJyZW50VmFsICE9PSBudWxsKSB7XG4gICAgICBjb25zdCB3b3Jrc3BhY2VPYmogPSBjdXJyZW50VmFsIGFzIGFueTtcbiAgICAgIGNvbnN0IGN1cnJlbnRJZCA9IHRoaXMuY29uZmlnPy52YWx1ZUJ5IFxuICAgICAgICA/IHdvcmtzcGFjZU9ialt0aGlzLmNvbmZpZy52YWx1ZUJ5XVxuICAgICAgICA6ICh3b3Jrc3BhY2VPYmouaWQgPz8gd29ya3NwYWNlT2JqLnZhbHVlKTtcbiAgICAgIHJldHVybiBjdXJyZW50SWQgPT09IG9wdGlvblZhbHVlO1xuICAgIH1cbiAgICBcbiAgICAvLyBPdGhlcndpc2UsIGNvbXBhcmUgZGlyZWN0bHlcbiAgICByZXR1cm4gY3VycmVudFZhbCA9PT0gb3B0aW9uVmFsdWU7XG4gIH1cblxuICBmaWx0ZXJlZE9wdGlvbnMoKTogU2VsZWN0T3B0aW9uW10ge1xuICAgIGNvbnN0IHQgPSB0aGlzLnNlYXJjaFRleHQudG9Mb3dlckNhc2UoKS50cmltKCk7XG4gICAgY29uc3QgYWxsT3B0aW9ucyA9IHRoaXMuY29uZmlnLm9wdGlvbnMgfHwgW107XG5cbiAgICBpZiAodGhpcy5jb25maWc/LnNlcnZlclNlYXJjaCkge1xuICAgICAgLy8gRm9yIHNlcnZlciBzZWFyY2gsIHJldHVybiBhbGwgb3B0aW9ucyBhcy1pcyAoc2VydmVyIGhhbmRsZXMgZmlsdGVyaW5nKVxuICAgICAgcmV0dXJuIGFsbE9wdGlvbnM7XG4gICAgfVxuICAgIFxuICAgIGlmICghdCkge1xuICAgICAgLy8gTm8gc2VhcmNoIC0gcmV0dXJuIGFsbCBvcHRpb25zXG4gICAgICByZXR1cm4gYWxsT3B0aW9ucztcbiAgICB9XG5cbiAgICAvLyBMb2NhbCBzZWFyY2ggLSBmaWx0ZXIgb3B0aW9ucyBieSBzZWFyY2ggdGV4dCBvbmx5XG4gICAgcmV0dXJuIGFsbE9wdGlvbnMuZmlsdGVyKChvcHQpID0+IHtcbiAgICAgIGNvbnN0IHRleHQgPSB0aGlzLmdldE9wdGlvbkxhYmVsKG9wdCkudG9Mb3dlckNhc2UoKTtcbiAgICAgIHJldHVybiB0ZXh0LmluY2x1ZGVzKHQpO1xuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTZWxlY3RlZElkcygpOiBhbnlbXSB7XG4gICAgY29uc3QgdmFsdWUgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcbiAgICByZXR1cm4gdmFsdWUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZSAhPT0gbnVsbCA/IFt2YWx1ZV0gOiBbXTtcbiAgfVxuXG4gIG9uT3B0aW9uQ2xpY2sob3B0OiBTZWxlY3RPcHRpb24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKSByZXR1cm47XG4gICAgXG4gICAgLy8gRW1pdCB0aGUgZnVsbCBvcHRpb24gb2JqZWN0ICh3aXRoIG5hbWUsIGlkLCBldGMuKSBpbnN0ZWFkIG9mIGp1c3QgdGhlIHZhbHVlXG4gICAgLy8gVGhpcyBhbGxvd3MgdGhlIHBhcmVudCB0byByZWNlaXZlIHRoZSBjb21wbGV0ZSB3b3Jrc3BhY2Ugb2JqZWN0XG4gICAgY29uc3QgbmV3VmFsdWUgPSBvcHQ7XG4gICAgY29uc3Qgc2VsZWN0ZWRPcHRpb24gPSBvcHQ7XG4gICAgXG4gICAgLy8gQ2xvc2UgZHJvcGRvd24gYWZ0ZXIgc2VsZWN0aW9uICh1bmxlc3MgY2xvc2VPblNlbGVjdCBpcyBmYWxzZSlcbiAgICBpZiAodGhpcy5jb25maWc/LmNsb3NlT25TZWxlY3QgIT09IGZhbHNlKSB7XG4gICAgICB0aGlzLmNsb3NlRHJvcGRvd24oKTtcbiAgICB9XG4gICAgXG4gICAgLy8gVXBkYXRlIHZhbHVlXG4gICAgaWYgKHRoaXMuZm9ybSkge1xuICAgICAgdGhpcy5jdXJyZW50Q29udHJvbC5zZXRWYWx1ZShuZXdWYWx1ZSwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudmFsdWUgPSBuZXdWYWx1ZTtcbiAgICAgIHRoaXMuc3luY1ZhbHVlRnJvbUlucHV0KCk7XG4gICAgfVxuICAgIFxuICAgIHRoaXMub25TZWxlY3Rpb25DaGFuZ2UobmV3VmFsdWUsIHNlbGVjdGVkT3B0aW9uKTtcbiAgfVxuXG4gIG9uU2VsZWN0aW9uQ2hhbmdlKG5ld1ZhbHVlPzogYW55LCBzZWxlY3RlZE9wdGlvbj86IFNlbGVjdE9wdGlvbik6IHZvaWQge1xuICAgIGNvbnN0IHZhbHVlID0gbmV3VmFsdWUgIT09IHVuZGVmaW5lZCA/IG5ld1ZhbHVlIDogdGhpcy5jdXJyZW50VmFsdWU7XG4gICAgXG4gICAgLy8gRW1pdCB2YWx1ZUNoYW5nZSBmb3IgdHdvLXdheSBiaW5kaW5nXG4gICAgdGhpcy52YWx1ZUNoYW5nZS5lbWl0KHZhbHVlKTtcbiAgICBcbiAgICBpZiAodHlwZW9mIHRoaXMuY29uZmlnPy5vbkNoYW5nZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgdGhpcy5jb25maWcub25DaGFuZ2UodmFsdWUpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcignY3FhLXdvcmtzcGFjZS1zZWxlY3RvciBvbkNoYW5nZSBoYW5kbGVyIGVycm9yOicsIGVycm9yKTtcbiAgICAgIH1cbiAgICB9XG4gICAgXG4gICAgdGhpcy5zZWxlY3Rpb25DaGFuZ2UuZW1pdCh7XG4gICAgICBrZXk6IHRoaXMuY29uZmlnPy5rZXkgfHwgJycsXG4gICAgICB2YWx1ZSxcbiAgICAgIG9wdGlvbjogc2VsZWN0ZWRPcHRpb24sXG4gICAgfSk7XG4gIH1cblxuICBvblNlYXJjaElucHV0KHZhbHVlOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLnNlYXJjaFRleHQgPSB2YWx1ZSA/PyAnJztcbiAgICBpZiAodGhpcy5jb25maWc/LnNlcnZlclNlYXJjaCkge1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25TZWFyY2g/Lih2YWx1ZSA/PyAnJyk7IH0gY2F0Y2gge31cbiAgICAgIHRoaXMuc2VhcmNoQ2hhbmdlLmVtaXQoeyBrZXk6IHRoaXMuY29uZmlnPy5rZXkgfHwgJycsIHF1ZXJ5OiB2YWx1ZSA/PyAnJyB9KTtcbiAgICAgIHRoaXMubG9hZGluZ01vcmUgPSBmYWxzZTtcbiAgICAgIHRoaXMubGFzdE9wdGlvbnNMZW5ndGggPSAodGhpcy5jb25maWc/Lm9wdGlvbnMgfHwgW10pLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICB0b2dnbGVEcm9wZG93bigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0Rpc2FibGVkKSByZXR1cm47XG4gICAgaWYgKHRoaXMuaXNPcGVuKSB7XG4gICAgICB0aGlzLmNsb3NlRHJvcGRvd24oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vcGVuRHJvcGRvd24oKTtcbiAgICB9XG4gIH1cblxuICBvcGVuRHJvcGRvd24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaXNEaXNhYmxlZCkgcmV0dXJuO1xuICAgIHRoaXMuaXNPcGVuID0gdHJ1ZTtcbiAgICB0aGlzLnNlbGVjdENsaWNrLmVtaXQoKTtcbiAgICB0aGlzLmhhc1Njcm9sbGVkU2luY2VPcGVuID0gZmFsc2U7XG4gICAgXG4gICAgaWYgKCh0aGlzLmNvbmZpZz8ub3B0aW9ucyB8fCBbXSkubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmNvbmZpZz8uc2VydmVyU2VhcmNoICYmIHRoaXMudG9Cb29sZWFuKHRoaXMuY29uZmlnPy5pbml0aWFsRmV0Y2hPbk9wZW4pKSB7XG4gICAgICBjb25zdCBxID0gdGhpcy5zZWFyY2hUZXh0IHx8ICcnO1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25TZWFyY2g/LihxKTsgfSBjYXRjaCB7fVxuICAgICAgdGhpcy5zZWFyY2hDaGFuZ2UuZW1pdCh7IGtleTogdGhpcy5jb25maWc/LmtleSB8fCAnJywgcXVlcnk6IHEgfSk7XG4gICAgfVxuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnNldHVwU2Nyb2xsTGlzdGVuZXIoKTtcbiAgICAgIGlmICh0aGlzLmNvbmZpZz8uc2VhcmNoYWJsZSkge1xuICAgICAgICBjb25zdCBpbnB1dCA9IHRoaXMuZHJvcGRvd25QYW5lbD8ubmF0aXZlRWxlbWVudD8ucXVlcnlTZWxlY3RvcjxIVE1MSW5wdXRFbGVtZW50PignLndvcmtzcGFjZS1zZWFyY2gtaW5wdXQnKTtcbiAgICAgICAgaW5wdXQ/LmZvY3VzKCk7XG4gICAgICB9XG4gICAgfSwgMCk7XG4gIH1cblxuICBjbG9zZURyb3Bkb3duKCk6IHZvaWQge1xuICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XG4gICAgdGhpcy5zZWFyY2hUZXh0ID0gJyc7XG4gICAgaWYgKHRoaXMucGFuZWxTY3JvbGxFbCkge1xuICAgICAgdHJ5IHsgdGhpcy5wYW5lbFNjcm9sbEVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIHRoaXMub25QYW5lbFNjcm9sbCk7IH0gY2F0Y2gge31cbiAgICAgIHRoaXMucGFuZWxTY3JvbGxFbCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgdGhpcy5sb2FkaW5nTW9yZSA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cFNjcm9sbExpc3RlbmVyKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5jb25maWc/Lmhhc01vcmUpIHJldHVybjtcbiAgICBjb25zdCBwYW5lbCA9IHRoaXMuZHJvcGRvd25QYW5lbD8ubmF0aXZlRWxlbWVudD8ucXVlcnlTZWxlY3RvcignLndvcmtzcGFjZS1vcHRpb25zLWNvbnRhaW5lcicpIGFzIEhUTUxFbGVtZW50O1xuICAgIGlmIChwYW5lbCkge1xuICAgICAgdGhpcy5wYW5lbFNjcm9sbEVsID0gcGFuZWw7XG4gICAgICBwYW5lbC5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCB0aGlzLm9uUGFuZWxTY3JvbGwsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcbiAgICB9XG4gIH1cblxuICBvblNjcm9sbGVkSW5kZXhDaGFuZ2UoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuaGFzU2Nyb2xsZWRTaW5jZU9wZW4gPSB0cnVlO1xuICAgIGlmICghdGhpcy5jb25maWc/Lmhhc01vcmUgfHwgdGhpcy5sb2FkaW5nTW9yZSkgcmV0dXJuO1xuICAgIGNvbnN0IHZpZXdwb3J0ID0gdGhpcy52aWV3cG9ydD8uZWxlbWVudFJlZj8ubmF0aXZlRWxlbWVudDtcbiAgICBpZiAoIXZpZXdwb3J0KSByZXR1cm47XG4gICAgY29uc3QgaXRlbUNvdW50ID0gdGhpcy5kaXNwbGF5ZWRPcHRpb25zLmxlbmd0aDtcbiAgICBjb25zdCB2aXNpYmxlSXRlbXMgPSBNYXRoLmNlaWwodmlld3BvcnQuY2xpZW50SGVpZ2h0IC8gdGhpcy5pdGVtU2l6ZSk7XG4gICAgaWYgKGluZGV4ICsgdmlzaWJsZUl0ZW1zID49IGl0ZW1Db3VudCAtIDEpIHtcbiAgICAgIHRoaXMubG9hZGluZ01vcmUgPSB0cnVlO1xuICAgICAgY29uc3Qga2V5ID0gdGhpcy5jb25maWc/LmtleSB8fCAnJztcbiAgICAgIGNvbnN0IHEgPSB0aGlzLnNlYXJjaFRleHQgfHwgJyc7XG4gICAgICB0aGlzLmxvYWRNb3JlLmVtaXQoeyBrZXksIHF1ZXJ5OiBxIH0pO1xuICAgICAgdHJ5IHsgdGhpcy5jb25maWcub25Mb2FkTW9yZT8uKHEpOyB9IGNhdGNoIHt9XG4gICAgfVxuICB9XG5cbiAgdHJhY2tCeU9wdGlvbiA9IChpbmRleDogbnVtYmVyLCBvcHQ6IFNlbGVjdE9wdGlvbiB8IG51bGwgfCB1bmRlZmluZWQpOiBhbnkgPT4ge1xuICAgIGlmICghb3B0KSByZXR1cm4gYGluZGV4LSR7aW5kZXh9YDtcbiAgICAvLyBVc2UgYSBzaW1wbGUgaWRlbnRpZmllciB0aGF0IGRvZXNuJ3QgcmVxdWlyZSBjYWxsaW5nIG1ldGhvZHNcbiAgICByZXR1cm4gb3B0LmlkID8/IG9wdC52YWx1ZSA/PyBgb3B0aW9uLSR7aW5kZXh9YDtcbiAgfVxuXG4gIGhpZ2hsaWdodFRleHQodGV4dDogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAoIXRleHQgfHwgIXRoaXMuY29uZmlnPy5oaWdobGlnaHRQYXR0ZXJuKSB7XG4gICAgICByZXR1cm4gdGhpcy5lc2NhcGVIdG1sKHRleHQpO1xuICAgIH1cblxuICAgIGNvbnN0IHBhdHRlcm4gPSB0aGlzLmNvbmZpZy5oaWdobGlnaHRQYXR0ZXJuO1xuICAgIGlmICh0eXBlb2YgcGF0dGVybiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHBhdHRlcm4odGV4dCk7XG4gICAgfVxuXG4gICAgbGV0IHJlZ2V4OiBSZWdFeHA7XG4gICAgaWYgKHR5cGVvZiBwYXR0ZXJuID09PSAnc3RyaW5nJykge1xuICAgICAgdHJ5IHtcbiAgICAgICAgcmVnZXggPSBuZXcgUmVnRXhwKHBhdHRlcm4sICdnaScpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0ludmFsaWQgaGlnaGxpZ2h0IHBhdHRlcm46JywgcGF0dGVybik7XG4gICAgICAgIHJldHVybiB0aGlzLmVzY2FwZUh0bWwodGV4dCk7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlZ2V4ID0gcGF0dGVybjtcbiAgICB9XG5cbiAgICBjb25zdCBlc2NhcGVkID0gdGhpcy5lc2NhcGVIdG1sKHRleHQpO1xuICAgIHJldHVybiBlc2NhcGVkLnJlcGxhY2UocmVnZXgsIChtYXRjaCkgPT4gYDxzcGFuIGNsYXNzPVwiY3FhLXRleHQtcHJpbWFyeVwiPiR7bWF0Y2h9PC9zcGFuPmApO1xuICB9XG5cbiAgcHJpdmF0ZSBlc2NhcGVIdG1sKHRleHQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCF0ZXh0KSByZXR1cm4gJyc7XG4gICAgY29uc3QgZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZGl2LnRleHRDb250ZW50ID0gdGV4dDtcbiAgICByZXR1cm4gZGl2LmlubmVySFRNTDtcbiAgfVxuXG4gIGdldCBoYXNIaWdobGlnaHRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5jb25maWc/LmhpZ2hsaWdodFBhdHRlcm47XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycsIFsnJGV2ZW50J10pXG4gIGhhbmRsZURvY3VtZW50Q2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuaXNPcGVuKSByZXR1cm47XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxFbGVtZW50IHwgbnVsbDtcbiAgICBpZiAoIXRhcmdldCkgcmV0dXJuO1xuICAgIGlmICh0aGlzLmhvc3RFbD8ubmF0aXZlRWxlbWVudCAmJiB0aGlzLmhvc3RFbC5uYXRpdmVFbGVtZW50LmNvbnRhaW5zKHRhcmdldCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5jbG9zZURyb3Bkb3duKCk7XG4gIH1cbn1cblxuIiwiPGRpdiBjbGFzcz1cImNxYS11aS1yb290XCIgI2hvc3Q+XG4gIDxuZy1jb250YWluZXIgW2Zvcm1Hcm91cF09XCJjdXJyZW50Rm9ybVwiPlxuICAgIDxsYWJlbCAqbmdJZj1cImNvbmZpZy5sYWJlbFwiXG4gICAgICBjbGFzcz1cImZvcm0tbGFiZWwgY3FhLXRleHQtWyMzNzQxNTFdIGNxYS10ZXh0LVsxNHB4XSBjcWEtZm9udC1tZWRpdW0gY3FhLWJsb2NrIGNxYS1sZWFkaW5nLVsxLjRdIGNxYS1tYi0yXCI+e3tcbiAgICAgIGNvbmZpZy5sYWJlbCB9fTwvbGFiZWw+XG4gICAgXG4gICAgPGRpdiBjbGFzcz1cIndvcmtzcGFjZS1zZWxlY3Rvci13cmFwcGVyIGNxYS1yZWxhdGl2ZSBjcWEtdy1mdWxsXCI+XG4gICAgICA8IS0tIFRyaWdnZXIgQnV0dG9uIC0tPlxuICAgICAgPGJ1dHRvblxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VsZWN0b3ItdHJpZ2dlciBjcWEtdy1mdWxsIGNxYS1mbGV4IGNxYS1pdGVtcy1jZW50ZXIgY3FhLWp1c3RpZnktYmV0d2VlbiBjcWEtcHgtNCBjcWEtcHktMiBjcWEtYm9yZGVyLXNvbGlkIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1bI0QxRDVEQl0gY3FhLXJvdW5kZWQtWzhweF0gY3FhLWJnLXdoaXRlIGNxYS10ZXh0LWxlZnQgY3FhLWN1cnNvci1wb2ludGVyIGhvdmVyOmNxYS1ib3JkZXItWyM5Q0EzQUZdIGZvY3VzOmNxYS1vdXRsaW5lLW5vbmUgZm9jdXM6Y3FhLXJpbmctMiBmb2N1czpjcWEtcmluZy1bIzRGNDZFNV0gZm9jdXM6Y3FhLXJpbmctb2Zmc2V0LTEgZGlzYWJsZWQ6Y3FhLW9wYWNpdHktNTAgZGlzYWJsZWQ6Y3FhLWN1cnNvci1ub3QtYWxsb3dlZFwiXG4gICAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcbiAgICAgICAgKGNsaWNrKT1cInRvZ2dsZURyb3Bkb3duKClcIlxuICAgICAgICBbYXR0ci5hcmlhLWV4cGFuZGVkXT1cImlzT3BlblwiXG4gICAgICAgIGFyaWEtaGFzcG9wdXA9XCJsaXN0Ym94XCI+XG4gICAgICAgIDxzcGFuIGNsYXNzPVwiY3FhLWZsZXgtMSBjcWEtdHJ1bmNhdGUgY3FhLXRleHQtWzE0cHhdIGNxYS10ZXh0LVsjMEEwQTBBXVwiXG4gICAgICAgICAgW2NsYXNzLmNxYS10ZXh0LVsjOUNBM0FGXV09XCIhZGlzcGxheVZhbHVlXCI+XG4gICAgICAgICAge3sgZGlzcGxheVZhbHVlIHx8IGRpc3BsYXlQbGFjZWhvbGRlciB9fVxuICAgICAgICA8L3NwYW4+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcWEtZmxleCBjcWEtaXRlbXMtY2VudGVyIGNxYS1nYXAtMiBjcWEtZmxleC1zaHJpbmstMFwiPlxuICAgICAgICAgIDxzdmcgKm5nSWY9XCJsb2FkaW5nTW9yZSB8fCBjb25maWc/LmlzTG9hZGluZ1wiIHdpZHRoPVwiMTZcIiBoZWlnaHQ9XCIxNlwiIHZpZXdCb3g9XCIwIDAgNTAgNTBcIiBhcmlhLWxhYmVsPVwibG9hZGluZ1wiXG4gICAgICAgICAgICAgICB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgY2xhc3M9XCJjcWEtYW5pbWF0ZS1zcGluXCI+XG4gICAgICAgICAgICA8Y2lyY2xlIGN4PVwiMjVcIiBjeT1cIjI1XCIgcj1cIjIwXCIgc3Ryb2tlPVwiI0U1RTdFQlwiIHN0cm9rZS13aWR0aD1cIjZcIiBmaWxsPVwibm9uZVwiLz5cbiAgICAgICAgICAgIDxwYXRoIGQ9XCJNNDUgMjVhMjAgMjAgMCAwIDAtMjAtMjBcIiBzdHJva2U9XCIjNEY0NkU1XCIgc3Ryb2tlLXdpZHRoPVwiNlwiIGZpbGw9XCJub25lXCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiPlxuICAgICAgICAgICAgICA8YW5pbWF0ZVRyYW5zZm9ybSBhdHRyaWJ1dGVOYW1lPVwidHJhbnNmb3JtXCIgdHlwZT1cInJvdGF0ZVwiIGZyb209XCIwIDI1IDI1XCIgdG89XCIzNjAgMjUgMjVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdXI9XCIwLjhzXCIgcmVwZWF0Q291bnQ9XCJpbmRlZmluaXRlXCIvPlxuICAgICAgICAgICAgPC9wYXRoPlxuICAgICAgICAgIDwvc3ZnPlxuICAgICAgICAgIDxzdmcgd2lkdGg9XCIxNlwiIGhlaWdodD1cIjE2XCIgdmlld0JveD1cIjAgMCAxNiAxNlwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiXG4gICAgICAgICAgICAgICBbY2xhc3MuY3FhLXJvdGF0ZS0xODBdPVwiaXNPcGVuXCI+XG4gICAgICAgICAgICA8cGF0aCBkPVwiTTQgNkw4IDEwTDEyIDZcIiBzdHJva2U9XCIjMEEwQTBBXCIgc3Ryb2tlLXdpZHRoPVwiMS4zMzMzM1wiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIlxuICAgICAgICAgICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9idXR0b24+XG5cbiAgICAgIDwhLS0gRHJvcGRvd24gUGFuZWwgLS0+XG4gICAgICA8ZGl2XG4gICAgICAgICNkcm9wZG93blBhbmVsXG4gICAgICAgICpuZ0lmPVwiaXNPcGVuXCJcbiAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VsZWN0b3ItcGFuZWwgY3FhLWFic29sdXRlIGNxYS16LTUwIGNxYS13LWZ1bGwgY3FhLW10LTEgY3FhLWJnLXdoaXRlIGNxYS1ib3JkZXIgY3FhLWJvcmRlci1bI0QxRDVEQl0gY3FhLXJvdW5kZWQtWzhweF0gY3FhLXNoYWRvdy1sZyBjcWEtb3ZlcmZsb3ctaGlkZGVuXCI+XG4gICAgICAgIFxuICAgICAgICA8IS0tIFNlYXJjaCBJbnB1dCAtLT5cbiAgICAgICAgPGRpdiAqbmdJZj1cImNvbmZpZy5zZWFyY2hhYmxlXCIgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VhcmNoLWNvbnRhaW5lciBjcWEtcC0yIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLVsjRTVFN0VCXVwiPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxuICAgICAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utc2VhcmNoLWlucHV0IGNxYS13LWZ1bGwgY3FhLXB4LTMgY3FhLXB5LTIgY3FhLWJvcmRlciBjcWEtYm9yZGVyLVsjRDFENURCXSBjcWEtcm91bmRlZC1bNnB4XSBjcWEtdGV4dC1bMTRweF0gY3FhLXRleHQtWyMwQTBBMEFdIGZvY3VzOmNxYS1vdXRsaW5lLW5vbmVcIlxuICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2guLi5cIlxuICAgICAgICAgICAgW3ZhbHVlXT1cInNlYXJjaFRleHRcIlxuICAgICAgICAgICAgKGlucHV0KT1cIm9uU2VhcmNoSW5wdXQoJGFueSgkZXZlbnQudGFyZ2V0KS52YWx1ZSlcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAobW91c2Vkb3duKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXG4gICAgICAgICAgICAoa2V5ZG93bik9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIiAvPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIE9wdGlvbnMgQ29udGFpbmVyIHdpdGggVmlydHVhbCBTY3JvbGwgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJ3b3Jrc3BhY2Utb3B0aW9ucy1jb250YWluZXJcIj5cbiAgICAgICAgICA8IS0tIE5vIHJlc3VsdHMgc3RhdGUgLS0+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cImRpc3BsYXllZE9wdGlvbnMubGVuZ3RoID09PSAwICYmICEoY29uZmlnPy5pc0xvYWRpbmcgfHwgbG9hZGluZ01vcmUpXCJcbiAgICAgICAgICAgIGNsYXNzPVwiY3FhLXB4LTQgY3FhLXB5LTMgY3FhLXRleHQtWzE0cHhdIGNxYS10ZXh0LVsjOUNBM0FGXSBjcWEtdGV4dC1jZW50ZXJcIj5cbiAgICAgICAgICAgIE5vIHJlc3VsdHNcbiAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgIDxjZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnRcbiAgICAgICAgICAgICpuZ0lmPVwiZGlzcGxheWVkT3B0aW9ucy5sZW5ndGggPiAwXCJcbiAgICAgICAgICAgICN2aWV3cG9ydFxuICAgICAgICAgICAgW2l0ZW1TaXplXT1cIml0ZW1TaXplXCJcbiAgICAgICAgICAgIG1pbkJ1ZmZlclB4PVwiMjAwXCJcbiAgICAgICAgICAgIG1heEJ1ZmZlclB4PVwiNDAwXCJcbiAgICAgICAgICAgIFtzdHlsZS5oZWlnaHQucHhdPVwidmlld3BvcnRIZWlnaHRcIlxuICAgICAgICAgICAgc3R5bGU9XCJ3aWR0aDogMTAwJTsgZGlzcGxheTogYmxvY2s7IG92ZXJmbG93OiBhdXRvO1wiXG4gICAgICAgICAgICAoc2Nyb2xsZWRJbmRleENoYW5nZSk9XCJvblNjcm9sbGVkSW5kZXhDaGFuZ2UoJGV2ZW50KVwiPlxuICAgICAgICAgICAgXG4gICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICpjZGtWaXJ0dWFsRm9yPVwibGV0IG9wdCBvZiBkaXNwbGF5ZWRPcHRpb25zOyB0cmFja0J5OiB0cmFja0J5T3B0aW9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ3b3Jrc3BhY2Utb3B0aW9uIGNxYS1weC00IGNxYS1weS0zIGNxYS1jdXJzb3ItcG9pbnRlciBob3ZlcjpjcWEtYmctWyNGM0Y0RjZdIGNxYS1ib3JkZXItYiBjcWEtYm9yZGVyLVsjRTVFN0VCXSBsYXN0OmNxYS1ib3JkZXItYi0wXCJcbiAgICAgICAgICAgICAgW3N0eWxlLmhlaWdodC5weF09XCJpdGVtU2l6ZVwiXG4gICAgICAgICAgICAgIFtzdHlsZS5kaXNwbGF5XT1cIidmbGV4J1wiXG4gICAgICAgICAgICAgIFtzdHlsZS5hbGlnbi1pdGVtc109XCInY2VudGVyJ1wiXG4gICAgICAgICAgICAgIFtjbGFzcy5jcWEtYmctWyNGM0Y0RjZdXT1cImlzT3B0aW9uU2VsZWN0ZWQob3B0KVwiXG4gICAgICAgICAgICAgIFtjbGFzcy5jcWEtYmctWyNFRUYyRkZdXT1cImlzT3B0aW9uU2VsZWN0ZWQob3B0KVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJvbk9wdGlvbkNsaWNrKG9wdClcIj5cbiAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJjcWEtdGV4dC1bMTRweF0gY3FhLXRleHQtWyMwQTBBMEFdXCJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImhhc0hpZ2hsaWdodGluZ1wiXG4gICAgICAgICAgICAgICAgW2lubmVySFRNTF09XCJoaWdobGlnaHRUZXh0KGdldE9wdGlvbkxhYmVsKG9wdCkpXCI+PC9zcGFuPlxuICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImNxYS10ZXh0LVsxNHB4XSBjcWEtdGV4dC1bIzBBMEEwQV1cIlxuICAgICAgICAgICAgICAgICpuZ0lmPVwiIWhhc0hpZ2hsaWdodGluZ1wiPlxuICAgICAgICAgICAgICAgIHt7IGdldE9wdGlvbkxhYmVsKG9wdCkgfX1cbiAgICAgICAgICAgICAgPC9zcGFuPlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPC9jZGstdmlydHVhbC1zY3JvbGwtdmlld3BvcnQ+XG5cbiAgICAgICAgICA8IS0tIExvYWRpbmcgbW9yZSBpbmRpY2F0b3IgLS0+XG4gICAgICAgICAgPGRpdiAqbmdJZj1cImNvbmZpZz8uaGFzTW9yZSAmJiAobG9hZGluZ01vcmUgfHwgY29uZmlnPy5pc0xvYWRpbmcpICYmIGRpc3BsYXllZE9wdGlvbnMubGVuZ3RoID4gMFwiXG4gICAgICAgICAgICBjbGFzcz1cImNxYS1weC00IGNxYS1weS0zIGNxYS10ZXh0LVsxNHB4XSBjcWEtdGV4dC1bIzZCNzI4MF0gY3FhLXRleHQtY2VudGVyIGNxYS1ib3JkZXItdCBjcWEtYm9yZGVyLVsjRTVFN0VCXVwiPlxuICAgICAgICAgICAgTG9hZGluZy4uLlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICA8L25nLWNvbnRhaW5lcj5cbjwvZGl2PlxuXG4iXX0=
|