@myrmidon/cadmus-refs-asserted-ids 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -96
- package/esm2022/lib/asserted-composite-id/asserted-composite-id.component.mjs +142 -0
- package/esm2022/lib/asserted-composite-ids/asserted-composite-ids.component.mjs +154 -0
- package/esm2022/lib/asserted-id/asserted-id.component.mjs +3 -3
- package/esm2022/lib/cadmus-refs-asserted-ids.module.mjs +31 -1
- package/esm2022/lib/pin-target-lookup/pin-target-lookup.component.mjs +405 -0
- package/esm2022/lib/scoped-pin-lookup/scoped-pin-lookup.component.mjs +3 -3
- package/esm2022/lib/services/item-ref-lookup.service.mjs +29 -0
- package/esm2022/lib/services/pin-ref-lookup.service.mjs +17 -5
- package/esm2022/public-api.mjs +5 -1
- package/fesm2022/myrmidon-cadmus-refs-asserted-ids.mjs +737 -19
- package/fesm2022/myrmidon-cadmus-refs-asserted-ids.mjs.map +1 -1
- package/lib/asserted-composite-id/asserted-composite-id.component.d.ts +83 -0
- package/lib/asserted-composite-ids/asserted-composite-ids.component.d.ts +67 -0
- package/lib/cadmus-refs-asserted-ids.module.d.ts +21 -15
- package/lib/pin-target-lookup/pin-target-lookup.component.d.ts +139 -0
- package/lib/services/item-ref-lookup.service.d.ts +13 -0
- package/lib/services/pin-ref-lookup.service.d.ts +10 -1
- package/package.json +1 -1
- package/public-api.d.ts +4 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import { Component, EventEmitter, Inject, Input, Output, } from '@angular/core';
|
|
2
|
+
import { Validators, } from '@angular/forms';
|
|
3
|
+
import { debounceTime, distinctUntilChanged, forkJoin, take, } from 'rxjs';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
import * as i1 from "../services/item-ref-lookup.service";
|
|
6
|
+
import * as i2 from "../services/pin-ref-lookup.service";
|
|
7
|
+
import * as i3 from "@myrmidon/cadmus-api";
|
|
8
|
+
import * as i4 from "@angular/material/snack-bar";
|
|
9
|
+
import * as i5 from "@angular/forms";
|
|
10
|
+
import * as i6 from "@angular/common";
|
|
11
|
+
import * as i7 from "@angular/cdk/clipboard";
|
|
12
|
+
import * as i8 from "@angular/material/button";
|
|
13
|
+
import * as i9 from "@angular/material/checkbox";
|
|
14
|
+
import * as i10 from "@angular/material/expansion";
|
|
15
|
+
import * as i11 from "@angular/material/form-field";
|
|
16
|
+
import * as i12 from "@angular/material/icon";
|
|
17
|
+
import * as i13 from "@angular/material/input";
|
|
18
|
+
import * as i14 from "@angular/material/select";
|
|
19
|
+
import * as i15 from "@angular/material/core";
|
|
20
|
+
import * as i16 from "@myrmidon/cadmus-refs-lookup";
|
|
21
|
+
import * as i17 from "@myrmidon/ng-tools";
|
|
22
|
+
// from Cadmus general parts
|
|
23
|
+
const METADATA_PART_ID = 'it.vedph.metadata';
|
|
24
|
+
/*
|
|
25
|
+
* Scoped pin-based lookup component. This component provides a list
|
|
26
|
+
* of pin-based searches, with a lookup control. Whenever the user
|
|
27
|
+
* picks a pin value, he gets the details about its item and part, and
|
|
28
|
+
* item's metadata part, if any. He can then use these data to build
|
|
29
|
+
* some EID by variously assembling these components.
|
|
30
|
+
*/
|
|
31
|
+
class PinTargetLookupComponent {
|
|
32
|
+
/**
|
|
33
|
+
* True when the by-type pin lookup mode is active.
|
|
34
|
+
* User can change mode unless modeSwitching is false.
|
|
35
|
+
*/
|
|
36
|
+
get pinByTypeMode() {
|
|
37
|
+
return this.byTypeMode?.value;
|
|
38
|
+
}
|
|
39
|
+
set pinByTypeMode(value) {
|
|
40
|
+
if (!this.byTypeMode) {
|
|
41
|
+
this._startWithByTypeMode = value;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.byTypeMode.setValue(value || false);
|
|
45
|
+
this.byTypeMode.updateValueAndValidity();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The target to be edited.
|
|
50
|
+
*/
|
|
51
|
+
get target() {
|
|
52
|
+
return this._target;
|
|
53
|
+
}
|
|
54
|
+
set target(value) {
|
|
55
|
+
if (this._target === value) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
this._target = value || undefined;
|
|
59
|
+
this.updateForm(this._target);
|
|
60
|
+
}
|
|
61
|
+
constructor(_presetLookupDefs, itemLookupService, pinLookupService, _itemService, _thesService, _snackbar, formBuilder) {
|
|
62
|
+
this._presetLookupDefs = _presetLookupDefs;
|
|
63
|
+
this.itemLookupService = itemLookupService;
|
|
64
|
+
this.pinLookupService = pinLookupService;
|
|
65
|
+
this._itemService = _itemService;
|
|
66
|
+
this._thesService = _thesService;
|
|
67
|
+
this._snackbar = _snackbar;
|
|
68
|
+
this.partTypeKeys = [];
|
|
69
|
+
this.itemParts = [];
|
|
70
|
+
this._subs = [];
|
|
71
|
+
this.modelEntries = [];
|
|
72
|
+
// this is the default filter for the pin lookup, which will
|
|
73
|
+
// be merged with values provided by user here
|
|
74
|
+
this.filter = {
|
|
75
|
+
text: '',
|
|
76
|
+
limit: 10,
|
|
77
|
+
};
|
|
78
|
+
// form
|
|
79
|
+
this.item = formBuilder.control(null);
|
|
80
|
+
this.itemPart = formBuilder.control(null);
|
|
81
|
+
this.partTypeKey = formBuilder.control(null);
|
|
82
|
+
this.gid = formBuilder.control(null, [
|
|
83
|
+
Validators.required,
|
|
84
|
+
Validators.maxLength(300),
|
|
85
|
+
]);
|
|
86
|
+
this.label = formBuilder.control(null, [
|
|
87
|
+
Validators.required,
|
|
88
|
+
Validators.maxLength(300),
|
|
89
|
+
]);
|
|
90
|
+
this.byTypeMode = formBuilder.control(false, { nonNullable: true });
|
|
91
|
+
this.external = formBuilder.control(false, { nonNullable: true });
|
|
92
|
+
this.form = formBuilder.group({
|
|
93
|
+
item: this.item,
|
|
94
|
+
itemPart: this.itemPart,
|
|
95
|
+
partTypeKey: this.partTypeKey,
|
|
96
|
+
gid: this.gid,
|
|
97
|
+
label: this.label,
|
|
98
|
+
byTypeMode: this.byTypeMode,
|
|
99
|
+
external: this.external,
|
|
100
|
+
});
|
|
101
|
+
// events
|
|
102
|
+
this.targetChange = new EventEmitter();
|
|
103
|
+
this.editorClose = new EventEmitter();
|
|
104
|
+
}
|
|
105
|
+
forceByItem() {
|
|
106
|
+
this.pinByTypeMode = false;
|
|
107
|
+
this.canSwitchMode = false;
|
|
108
|
+
}
|
|
109
|
+
setupKeys() {
|
|
110
|
+
// use DI presets if no lookup definitions
|
|
111
|
+
if (!this.lookupDefinitions) {
|
|
112
|
+
this.lookupDefinitions = this._presetLookupDefs;
|
|
113
|
+
}
|
|
114
|
+
// keys are all the defined lookup searches
|
|
115
|
+
this.partTypeKeys = Object.keys(this.lookupDefinitions);
|
|
116
|
+
// if no keys, get them from thesaurus model-types;
|
|
117
|
+
// if this is not available, just force by item mode.
|
|
118
|
+
if (!this.partTypeKeys.length) {
|
|
119
|
+
if (this.modelEntries?.length) {
|
|
120
|
+
// set lookupDefinitions from thesaurus entries
|
|
121
|
+
this.lookupDefinitions = {};
|
|
122
|
+
this.modelEntries.forEach((e) => {
|
|
123
|
+
this.lookupDefinitions[e.value] = {
|
|
124
|
+
name: e.value,
|
|
125
|
+
typeId: e.id,
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
// set type keys from thesaurus entries
|
|
129
|
+
this.partTypeKeys = this.modelEntries.map((e) => e.value);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// if still no keys, force by item mode
|
|
133
|
+
if (!this.partTypeKeys.length) {
|
|
134
|
+
this.forceByItem();
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
// if there is only one key, set it as the default
|
|
138
|
+
if (this.partTypeKeys.length === 1) {
|
|
139
|
+
this.partTypeKey.setValue(this.partTypeKeys[0]);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
canBuildGid() {
|
|
144
|
+
return (!this.external.value && !this.gid.value) || this.gid.pristine;
|
|
145
|
+
}
|
|
146
|
+
canBuildLabel() {
|
|
147
|
+
return (!this.external.value && !this.label.value) || this.label.pristine;
|
|
148
|
+
}
|
|
149
|
+
ngOnInit() {
|
|
150
|
+
// set start mode if required
|
|
151
|
+
if (this._startWithByTypeMode) {
|
|
152
|
+
this.byTypeMode.setValue(true);
|
|
153
|
+
}
|
|
154
|
+
// whenever item changes, update item's parts and filter
|
|
155
|
+
this._subs.push(this.item.valueChanges
|
|
156
|
+
.pipe(distinctUntilChanged(), debounceTime(300))
|
|
157
|
+
.subscribe((item) => {
|
|
158
|
+
this.itemPart.setValue(null);
|
|
159
|
+
this.itemParts = item?.parts || [];
|
|
160
|
+
this.filter = {
|
|
161
|
+
...this.filter,
|
|
162
|
+
itemId: item?.id,
|
|
163
|
+
};
|
|
164
|
+
}));
|
|
165
|
+
// whenever itemPart changes, update target and eventually gid
|
|
166
|
+
this._subs.push(this.itemPart.valueChanges
|
|
167
|
+
.pipe(distinctUntilChanged(), debounceTime(300))
|
|
168
|
+
.subscribe((part) => {
|
|
169
|
+
if (!this.gid.value || this.gid.pristine) {
|
|
170
|
+
this.gid.setValue(this.buildGid());
|
|
171
|
+
}
|
|
172
|
+
this.filter = {
|
|
173
|
+
...this.filter,
|
|
174
|
+
partId: part?.id,
|
|
175
|
+
};
|
|
176
|
+
this.updateTarget();
|
|
177
|
+
}));
|
|
178
|
+
// whenever partTypeKey changes, update filter's options
|
|
179
|
+
this._subs.push(this.partTypeKey.valueChanges
|
|
180
|
+
.pipe(distinctUntilChanged(), debounceTime(300))
|
|
181
|
+
.subscribe((key) => {
|
|
182
|
+
this.pinFilterOptions = key
|
|
183
|
+
? this.lookupDefinitions[key]
|
|
184
|
+
: undefined;
|
|
185
|
+
}));
|
|
186
|
+
// load model-types thesaurus entries
|
|
187
|
+
this._thesService.getThesaurus('model-types', true).subscribe({
|
|
188
|
+
next: (t) => {
|
|
189
|
+
this.modelEntries = t.entries || [];
|
|
190
|
+
if (this.modelEntries?.length) {
|
|
191
|
+
this.setupKeys();
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
this.forceByItem();
|
|
195
|
+
}
|
|
196
|
+
},
|
|
197
|
+
error: () => {
|
|
198
|
+
this.forceByItem();
|
|
199
|
+
},
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
ngOnDestroy() {
|
|
203
|
+
for (let i = 0; i < this._subs.length; i++) {
|
|
204
|
+
this._subs[i].unsubscribe();
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
buildGid() {
|
|
208
|
+
// the GID is the part ID if any, or the item ID, followed by
|
|
209
|
+
// the pin's value (=EID)
|
|
210
|
+
const pin = this.lookupData?.pin;
|
|
211
|
+
if (!pin) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
return pin.partId
|
|
215
|
+
? `P${pin.partId}/${pin.value}`
|
|
216
|
+
: `I${pin.itemId}/${pin.value}`;
|
|
217
|
+
}
|
|
218
|
+
buildLabel() {
|
|
219
|
+
if (!this.lookupData?.pin) {
|
|
220
|
+
return null;
|
|
221
|
+
}
|
|
222
|
+
const sb = [];
|
|
223
|
+
// pin value
|
|
224
|
+
sb.push(this.lookupData.pin.value);
|
|
225
|
+
// item title
|
|
226
|
+
sb.push(' | ');
|
|
227
|
+
sb.push(this.lookupData.item.title || this.lookupData.item.id);
|
|
228
|
+
// part type and role
|
|
229
|
+
const e = this.modelEntries?.find((e) => e.id === this.lookupData.pin.partTypeId);
|
|
230
|
+
sb.push(' (');
|
|
231
|
+
sb.push(e?.value || this.lookupData.pin.partTypeId);
|
|
232
|
+
if (this.lookupData.pin.roleId) {
|
|
233
|
+
sb.push(`, ${this.lookupData.pin.roleId}`);
|
|
234
|
+
}
|
|
235
|
+
sb.push(')');
|
|
236
|
+
return sb.join('');
|
|
237
|
+
}
|
|
238
|
+
getTarget() {
|
|
239
|
+
if (this.external.value) {
|
|
240
|
+
return {
|
|
241
|
+
gid: this.gid.value || '',
|
|
242
|
+
label: this.label.value || '',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
const pin = this.lookupData?.pin;
|
|
247
|
+
return {
|
|
248
|
+
itemId: pin?.itemId || '',
|
|
249
|
+
partId: pin?.partId || '',
|
|
250
|
+
partTypeId: pin?.partTypeId || '',
|
|
251
|
+
roleId: pin?.roleId || '',
|
|
252
|
+
name: pin?.name || '',
|
|
253
|
+
value: pin?.value || '',
|
|
254
|
+
gid: pin?.value || '',
|
|
255
|
+
label: pin?.value || '',
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
updateTarget() {
|
|
260
|
+
this._noFormUpdate = true;
|
|
261
|
+
if (this.canBuildGid()) {
|
|
262
|
+
this.gid.setValue(this.buildGid());
|
|
263
|
+
this.gid.markAsDirty();
|
|
264
|
+
}
|
|
265
|
+
if (this.canBuildLabel()) {
|
|
266
|
+
this.label.setValue(this.buildLabel());
|
|
267
|
+
this.label.markAsDirty();
|
|
268
|
+
}
|
|
269
|
+
this.target = this.getTarget();
|
|
270
|
+
this._noFormUpdate = false;
|
|
271
|
+
}
|
|
272
|
+
updateForm(target) {
|
|
273
|
+
if (this._noFormUpdate) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
// build pin info from target
|
|
277
|
+
if (!target) {
|
|
278
|
+
this.lookupData = undefined;
|
|
279
|
+
this.form.reset();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
this.external.setValue(!target.name);
|
|
283
|
+
this.lookupData = {
|
|
284
|
+
pin: {
|
|
285
|
+
itemId: target.itemId || '',
|
|
286
|
+
partId: target.partId || '',
|
|
287
|
+
partTypeId: target.partTypeId || '',
|
|
288
|
+
roleId: target.roleId || '',
|
|
289
|
+
name: target.name || '',
|
|
290
|
+
value: target.value || '',
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
// get item
|
|
294
|
+
if (target.itemId) {
|
|
295
|
+
this._itemService.getItem(target.itemId, true).subscribe({
|
|
296
|
+
next: (item) => {
|
|
297
|
+
this.item.setValue(item);
|
|
298
|
+
this.form.markAsPristine();
|
|
299
|
+
},
|
|
300
|
+
error: (error) => {
|
|
301
|
+
if (error) {
|
|
302
|
+
console.error(JSON.stringify(error));
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Called when the item lookup changes (item is looked up
|
|
310
|
+
* by its title).
|
|
311
|
+
*
|
|
312
|
+
* @param item The item got from lookup.
|
|
313
|
+
*/
|
|
314
|
+
onItemLookupChange(item) {
|
|
315
|
+
// load item's parts
|
|
316
|
+
this._itemService.getItem(item.id, true).subscribe({
|
|
317
|
+
next: (i) => {
|
|
318
|
+
// setting the item will trigger its parts update
|
|
319
|
+
this.item.setValue(i);
|
|
320
|
+
this.updateTarget();
|
|
321
|
+
},
|
|
322
|
+
error: (error) => {
|
|
323
|
+
if (error) {
|
|
324
|
+
console.error(JSON.stringify(error));
|
|
325
|
+
}
|
|
326
|
+
this.itemPart.setValue(null);
|
|
327
|
+
this.itemParts = [];
|
|
328
|
+
this.updateTarget();
|
|
329
|
+
},
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
loadItemInfo(pin) {
|
|
333
|
+
forkJoin({
|
|
334
|
+
item: this._itemService.getItem(pin.itemId, false),
|
|
335
|
+
part: this._itemService.getPartFromTypeAndRole(pin.itemId, METADATA_PART_ID),
|
|
336
|
+
})
|
|
337
|
+
.pipe(take(1))
|
|
338
|
+
.subscribe({
|
|
339
|
+
next: (result) => {
|
|
340
|
+
this.lookupData = {
|
|
341
|
+
pin: pin,
|
|
342
|
+
item: result.item,
|
|
343
|
+
metaPart: result.part,
|
|
344
|
+
};
|
|
345
|
+
this.updateTarget();
|
|
346
|
+
},
|
|
347
|
+
error: (error) => {
|
|
348
|
+
this.lookupData = undefined;
|
|
349
|
+
console.error(error ? JSON.stringify(error) : 'Error loading item/metadata');
|
|
350
|
+
},
|
|
351
|
+
});
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Called when the pin lookup change. A pin is looked up by its
|
|
355
|
+
* name and value (=the filter's text), and optionally by:
|
|
356
|
+
* - its index lookup definition (selected by partTypeKey).
|
|
357
|
+
* - its item (defined by item, in filter).
|
|
358
|
+
* - its part (defined by itemPart, in filter).
|
|
359
|
+
*
|
|
360
|
+
* @param info The pin info from pin lookup.
|
|
361
|
+
*/
|
|
362
|
+
onPinLookupChange(info) {
|
|
363
|
+
this.loadItemInfo(info);
|
|
364
|
+
}
|
|
365
|
+
onCopied() {
|
|
366
|
+
this._snackbar.open('Copied to clipboard', 'OK', {
|
|
367
|
+
duration: 1500,
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
close() {
|
|
371
|
+
this.editorClose.emit();
|
|
372
|
+
}
|
|
373
|
+
save() {
|
|
374
|
+
if (this.form.invalid) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
this._target = this.getTarget();
|
|
378
|
+
this.targetChange.emit(this._target);
|
|
379
|
+
}
|
|
380
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: PinTargetLookupComponent, deps: [{ token: 'indexLookupDefinitions' }, { token: i1.ItemRefLookupService }, { token: i2.PinRefLookupService }, { token: i3.ItemService }, { token: i3.ThesaurusService }, { token: i4.MatSnackBar }, { token: i5.FormBuilder }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
381
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.1", type: PinTargetLookupComponent, selector: "cadmus-pin-target-lookup", inputs: { pinByTypeMode: "pinByTypeMode", canSwitchMode: "canSwitchMode", canEditTarget: "canEditTarget", lookupDefinitions: "lookupDefinitions", target: "target" }, outputs: { editorClose: "editorClose", targetChange: "targetChange" }, ngImport: i0, template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n <mat-error\r\n *ngIf=\"$any(label).errors?.required && (label.dirty || label.touched)\"\r\n >label required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"\r\n $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n \"\r\n >label too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div\r\n *ngIf=\"!external.value && !canEditTarget && label.value\"\r\n class=\"info\"\r\n >\r\n <span class=\"label\">label</span>{{ label.value }}\r\n </div>\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.required && (gid.dirty || gid.touched)\"\r\n >GID required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.maxLength && (gid.dirty || gid.touched)\"\r\n >GID too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div *ngIf=\"!external.value && !canEditTarget && gid.value\" class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- BY ITEM -->\r\n <div *ngIf=\"!external.value\">\r\n <fieldset *ngIf=\"!byTypeMode.value\" class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n\r\n <!-- part filter -->\r\n <mat-form-field *ngIf=\"itemParts.length\">\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n <mat-option *ngFor=\"let p of itemParts\" [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </fieldset>\r\n\r\n <!-- BY TYPE -->\r\n <div *ngIf=\"byTypeMode.value\">\r\n <!-- par type filter -->\r\n <mat-form-field *ngIf=\"partTypeKeys?.length\">\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n <mat-option *ngFor=\"let k of partTypeKeys\" [value]=\"k\">{{\r\n k\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- PIN -->\r\n <div class=\"form-row\">\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n <!-- mode switcher -->\r\n <div>\r\n <mat-checkbox [formControl]=\"byTypeMode\" *ngIf=\"canSwitchMode\">\r\n by type</mat-checkbox\r\n >\r\n </div>\r\n </div>\r\n\r\n <!-- data -->\r\n <mat-expansion-panel id=\"data\" *ngIf=\"lookupData?.pin?.name\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n <tr *ngIf=\"lookupData?.pin?.value\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n <!-- item ID -->\r\n <tr *ngIf=\"lookupData?.pin?.itemId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n <!-- item title -->\r\n <tr *ngIf=\"lookupData?.item?.title\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n <!-- part ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n <!-- part type ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partTypeId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n <!-- part role ID -->\r\n <tr *ngIf=\"lookupData?.pin?.roleId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n\r\n <!-- part's metadata -->\r\n <tr\r\n *ngFor=\"\r\n let m of lookupData?.metaPart?.metadata || [];\r\n let i = index\r\n \"\r\n >\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- buttons -->\r\n <div>\r\n <button mat-flat-button type=\"button\" (click)=\"close()\">\r\n <mat-icon color=\"warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon color=\"primary\">check_circle</mat-icon> target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:4px 8px;margin-bottom:8px}legend{color:silver}\n"], dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i5.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i5.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i5.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i5.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i5.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i7.CdkCopyToClipboard, selector: "[cdkCopyToClipboard]", inputs: ["cdkCopyToClipboard", "cdkCopyToClipboardAttempts"], outputs: ["cdkCopyToClipboardCopied"] }, { kind: "component", type: i8.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i8.MatIconButton, selector: "button[mat-icon-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i9.MatCheckbox, selector: "mat-checkbox", inputs: ["disableRipple", "color", "tabIndex"], exportAs: ["matCheckbox"] }, { kind: "component", type: i10.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["disabled", "expanded", "hideToggle", "togglePosition"], outputs: ["opened", "closed", "expandedChange", "afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i10.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["tabIndex", "expandedHeight", "collapsedHeight"] }, { kind: "component", type: i11.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i11.MatLabel, selector: "mat-label" }, { kind: "directive", type: i11.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "component", type: i12.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i13.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i14.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i15.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i16.RefLookupComponent, selector: "cadmus-ref-lookup", inputs: ["label", "limit", "baseFilter", "service", "item", "required", "hasMore", "linkTemplate", "optDialog", "options"], outputs: ["itemChange", "moreRequest"] }, { kind: "pipe", type: i17.FlatLookupPipe, name: "flatLookup" }] }); }
|
|
382
|
+
}
|
|
383
|
+
export { PinTargetLookupComponent };
|
|
384
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: PinTargetLookupComponent, decorators: [{
|
|
385
|
+
type: Component,
|
|
386
|
+
args: [{ selector: 'cadmus-pin-target-lookup', template: "<form [formGroup]=\"form\" (submit)=\"save()\">\r\n <!-- external -->\r\n <mat-checkbox [formControl]=\"external\">external</mat-checkbox>\r\n\r\n <div class=\"form-row\">\r\n <!-- label -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>label</mat-label>\r\n <input matInput [formControl]=\"label\" />\r\n <mat-error\r\n *ngIf=\"$any(label).errors?.required && (label.dirty || label.touched)\"\r\n >label required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"\r\n $any(label).errors?.maxLength && (label.dirty || label.touched)\r\n \"\r\n >label too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div\r\n *ngIf=\"!external.value && !canEditTarget && label.value\"\r\n class=\"info\"\r\n >\r\n <span class=\"label\">label</span>{{ label.value }}\r\n </div>\r\n </div>\r\n\r\n <!-- gid -->\r\n <div>\r\n <mat-form-field *ngIf=\"external.value || canEditTarget\">\r\n <mat-label>GID</mat-label>\r\n <input matInput [formControl]=\"gid\" />\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.required && (gid.dirty || gid.touched)\"\r\n >GID required</mat-error\r\n >\r\n <mat-error\r\n *ngIf=\"$any(gid).errors?.maxLength && (gid.dirty || gid.touched)\"\r\n >GID too long</mat-error\r\n >\r\n </mat-form-field>\r\n <div *ngIf=\"!external.value && !canEditTarget && gid.value\" class=\"info\">\r\n <span class=\"label\">GID</span> <span class=\"gid\">{{ gid.value }}</span>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- BY ITEM -->\r\n <div *ngIf=\"!external.value\">\r\n <fieldset *ngIf=\"!byTypeMode.value\" class=\"form-row\">\r\n <legend>pin filters</legend>\r\n <!-- item filter -->\r\n <cadmus-ref-lookup\r\n [service]=\"itemLookupService\"\r\n label=\"item\"\r\n (itemChange)=\"onItemLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n\r\n <!-- part filter -->\r\n <mat-form-field *ngIf=\"itemParts.length\">\r\n <mat-label>part</mat-label>\r\n <mat-select [formControl]=\"itemPart\">\r\n <mat-option [value]=\"null\">(any)</mat-option>\r\n <mat-option *ngFor=\"let p of itemParts\" [value]=\"p\">{{\r\n p.typeId | flatLookup : modelEntries : \"id\" : \"value\"\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </fieldset>\r\n\r\n <!-- BY TYPE -->\r\n <div *ngIf=\"byTypeMode.value\">\r\n <!-- par type filter -->\r\n <mat-form-field *ngIf=\"partTypeKeys?.length\">\r\n <mat-label>part type</mat-label>\r\n <mat-select [formControl]=\"partTypeKey\">\r\n <mat-option *ngFor=\"let k of partTypeKeys\" [value]=\"k\">{{\r\n k\r\n }}</mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n\r\n <!-- PIN -->\r\n <div class=\"form-row\">\r\n <!-- pin lookup -->\r\n <cadmus-ref-lookup\r\n [service]=\"pinLookupService\"\r\n [baseFilter]=\"filter\"\r\n [options]=\"pinFilterOptions\"\r\n label=\"pin\"\r\n (itemChange)=\"onPinLookupChange($event)\"\r\n ></cadmus-ref-lookup>\r\n <!-- mode switcher -->\r\n <div>\r\n <mat-checkbox [formControl]=\"byTypeMode\" *ngIf=\"canSwitchMode\">\r\n by type</mat-checkbox\r\n >\r\n </div>\r\n </div>\r\n\r\n <!-- data -->\r\n <mat-expansion-panel id=\"data\" *ngIf=\"lookupData?.pin?.name\">\r\n <mat-expansion-panel-header>pin data</mat-expansion-panel-header>\r\n <!-- table -->\r\n <table>\r\n <thead>\r\n <th></th>\r\n <th>source</th>\r\n <th>value</th>\r\n </thead>\r\n <tbody>\r\n <!-- pin -->\r\n <tr *ngIf=\"lookupData?.pin?.value\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>pin</td>\r\n <td>{{ lookupData!.pin.value }}</td>\r\n </tr>\r\n <!-- item ID -->\r\n <tr *ngIf=\"lookupData?.pin?.itemId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.itemId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item ID</td>\r\n <td>{{ lookupData!.pin.itemId }}</td>\r\n </tr>\r\n <!-- item title -->\r\n <tr *ngIf=\"lookupData?.item?.title\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.item!.title\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>item title</td>\r\n <td>{{ lookupData!.item!.title }}</td>\r\n </tr>\r\n <!-- part ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part ID</td>\r\n <td>{{ lookupData!.pin.partId }}</td>\r\n </tr>\r\n <!-- part type ID -->\r\n <tr *ngIf=\"lookupData?.pin?.partTypeId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.partTypeId\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part type ID</td>\r\n <td>{{ lookupData!.pin!.partTypeId }}</td>\r\n </tr>\r\n <!-- part role ID -->\r\n <tr *ngIf=\"lookupData?.pin?.roleId\">\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"lookupData!.pin!.roleId!\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td>part role ID</td>\r\n <td>{{ lookupData!.pin!.roleId }}</td>\r\n </tr>\r\n\r\n <!-- part's metadata -->\r\n <tr\r\n *ngFor=\"\r\n let m of lookupData?.metaPart?.metadata || [];\r\n let i = index\r\n \"\r\n >\r\n <td>\r\n <button\r\n type=\"button\"\r\n mat-icon-button\r\n color=\"primary\"\r\n [cdkCopyToClipboard]=\"m.value\"\r\n (cdkCopyToClipboardCopied)=\"onCopied()\"\r\n >\r\n <mat-icon>content_copy</mat-icon>\r\n </button>\r\n </td>\r\n <td class=\"metadata\">{{ m.name }}</td>\r\n <td class=\"metadata\">{{ m.value }}</td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </mat-expansion-panel>\r\n </div>\r\n\r\n <!-- buttons -->\r\n <div>\r\n <button mat-flat-button type=\"button\" (click)=\"close()\">\r\n <mat-icon color=\"warn\">close</mat-icon>\r\n </button>\r\n <button mat-flat-button type=\"submit\" [disabled]=\"form.invalid\">\r\n <mat-icon color=\"primary\">check_circle</mat-icon> target\r\n </button>\r\n </div>\r\n</form>\r\n", styles: [".metadata{color:#4a3001}.info{border:1px solid silver;border-radius:6px;background-color:silver;color:#fff;padding:4px;margin:8px 0}.info .label{background-color:#fff;color:silver;margin:0 6px}#data{margin:8px 0}table{border:1px solid silver;border-radius:6px;padding:4px;margin-top:8px}tr:nth-child(odd){background-color:#f0f0f0}th{font-weight:400;text-align:left;color:silver}.form-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}.form-row *{flex:0 0 auto}.label{border:1px solid silver;border-radius:6px;padding:4px}fieldset{border:1px solid silver;border-radius:6px;padding:4px 8px;margin-bottom:8px}legend{color:silver}\n"] }]
|
|
387
|
+
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
|
|
388
|
+
type: Inject,
|
|
389
|
+
args: ['indexLookupDefinitions']
|
|
390
|
+
}] }, { type: i1.ItemRefLookupService }, { type: i2.PinRefLookupService }, { type: i3.ItemService }, { type: i3.ThesaurusService }, { type: i4.MatSnackBar }, { type: i5.FormBuilder }]; }, propDecorators: { pinByTypeMode: [{
|
|
391
|
+
type: Input
|
|
392
|
+
}], canSwitchMode: [{
|
|
393
|
+
type: Input
|
|
394
|
+
}], canEditTarget: [{
|
|
395
|
+
type: Input
|
|
396
|
+
}], lookupDefinitions: [{
|
|
397
|
+
type: Input
|
|
398
|
+
}], target: [{
|
|
399
|
+
type: Input
|
|
400
|
+
}], editorClose: [{
|
|
401
|
+
type: Output
|
|
402
|
+
}], targetChange: [{
|
|
403
|
+
type: Output
|
|
404
|
+
}] } });
|
|
405
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbXlybWlkb24vY2FkbXVzLXJlZnMtYXNzZXJ0ZWQtaWRzL3NyYy9saWIvcGluLXRhcmdldC1sb29rdXAvcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbXlybWlkb24vY2FkbXVzLXJlZnMtYXNzZXJ0ZWQtaWRzL3NyYy9saWIvcGluLXRhcmdldC1sb29rdXAvcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osTUFBTSxFQUNOLEtBQUssRUFHTCxNQUFNLEdBQ1AsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUlMLFVBQVUsR0FDWCxNQUFNLGdCQUFnQixDQUFDO0FBQ3hCLE9BQU8sRUFFTCxZQUFZLEVBQ1osb0JBQW9CLEVBQ3BCLFFBQVEsRUFDUixJQUFJLEdBQ0wsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtQmQsNEJBQTRCO0FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsbUJBQW1CLENBQUM7QUFtQzdDOzs7Ozs7R0FNRztBQUNILE1BS2Esd0JBQXdCO0lBTW5DOzs7T0FHRztJQUNILElBQ1csYUFBYTtRQUN0QixPQUFPLElBQUksQ0FBQyxVQUFVLEVBQUUsS0FBSyxDQUFDO0lBQ2hDLENBQUM7SUFDRCxJQUFXLGFBQWEsQ0FBQyxLQUEwQjtRQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNwQixJQUFJLENBQUMsb0JBQW9CLEdBQUcsS0FBSyxDQUFDO1NBQ25DO2FBQU07WUFDTCxJQUFJLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLENBQUM7WUFDekMs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QUMsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN2QyxDQUFDOzhHQWpjVSx3QkFBd0Isa0JBOEZ6Qix3QkFBd0I7a0dBOUZ2Qix3QkFBd0IsNlNDeEZyQywrN1FBdVBBOztTRC9KYSx3QkFBd0I7MkZBQXhCLHdCQUF3QjtrQkFMcEMsU0FBUzsrQkFDRSwwQkFBMEI7OzBCQWtHakMsTUFBTTsyQkFBQyx3QkFBd0I7OE5BbkZ2QixhQUFhO3NCQUR2QixLQUFLO2dCQWlCQyxhQUFhO3NCQURuQixLQUFLO2dCQU9DLGFBQWE7c0JBRG5CLEtBQUs7Z0JBV0MsaUJBQWlCO3NCQUR2QixLQUFLO2dCQU9LLE1BQU07c0JBRGhCLEtBQUs7Z0JBZ0JDLFdBQVc7c0JBRGpCLE1BQU07Z0JBT0EsWUFBWTtzQkFEbEIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7XG4gIEZvcm1CdWlsZGVyLFxuICBGb3JtQ29udHJvbCxcbiAgRm9ybUdyb3VwLFxuICBWYWxpZGF0b3JzLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1xuICBTdWJzY3JpcHRpb24sXG4gIGRlYm91bmNlVGltZSxcbiAgZGlzdGluY3RVbnRpbENoYW5nZWQsXG4gIGZvcmtKb2luLFxuICB0YWtlLFxufSBmcm9tICdyeGpzJztcbmltcG9ydCB7IE1hdFNuYWNrQmFyIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc25hY2stYmFyJztcblxuaW1wb3J0IHsgSXRlbVNlcnZpY2UsIFRoZXNhdXJ1c1NlcnZpY2UgfSBmcm9tICdAbXlybWlkb24vY2FkbXVzLWFwaSc7XG5pbXBvcnQge1xuICBEYXRhUGluSW5mbyxcbiAgSW5kZXhMb29rdXBEZWZpbml0aW9uLFxuICBJbmRleExvb2t1cERlZmluaXRpb25zLFxuICBJdGVtLFxuICBQYXJ0LFxuICBUaGVzYXVydXNFbnRyeSxcbn0gZnJvbSAnQG15cm1pZG9uL2NhZG11cy1jb3JlJztcblxuaW1wb3J0IHtcbiAgUGluUmVmTG9va3VwRmlsdGVyLFxuICBQaW5SZWZMb29rdXBTZXJ2aWNlLFxufSBmcm9tICcuLi9zZXJ2aWNlcy9waW4tcmVmLWxvb2t1cC5zZXJ2aWNlJztcbmltcG9ydCB7IEl0ZW1SZWZMb29rdXBTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvaXRlbS1yZWYtbG9va3VwLnNlcnZpY2UnO1xuXG4vLyBmcm9tIENhZG11cyBnZW5lcmFsIHBhcnRzXG5jb25zdCBNRVRBREFUQV9QQVJUX0lEID0gJ2l0LnZlZHBoLm1ldGFkYXRhJztcbmludGVyZmFjZSBNZXRhZGF0YVBhcnQgZXh0ZW5kcyBQYXJ0IHtcbiAgbWV0YWRhdGE6IHtcbiAgICB0eXBlPzogc3RyaW5nO1xuICAgIG5hbWU6IHN0cmluZztcbiAgICB2YWx1ZTogc3RyaW5nO1xuICB9W107XG59XG5cbi8qKlxuICogUGluIGxvb2t1cCBkYXRhIHVzZWQgaW50ZXJuYWxseSBieSB0aGUgY29tcG9uZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBpbkxvb2t1cERhdGEge1xuICBwaW46IERhdGFQaW5JbmZvO1xuICBpdGVtPzogSXRlbTtcbiAgbWV0YVBhcnQ/OiBNZXRhZGF0YVBhcnQ7XG59XG5cbi8qKlxuICogQSBwaW4tYmFzZWQgdGFyZ2V0LiBUaGlzIGluY2x1ZGVzIHBpbidzIG5hbWUgYW5kIHZhbHVlLCBhbmRcbiAqIHRoZSBpdGVtJ3MgSUQgYW5kIG9wdGlvbmFsIHBhcnQgSURzLiBUaGUgbGFiZWwgaXMgYSB1c2VyIGZyaWVuZGx5XG4gKiBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIHRhcmdldCwgd2hpbGUgdGhlIGdpZCBpcyBhIGdsb2JhbGx5XG4gKiB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHRhcmdldC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBQaW5UYXJnZXQge1xuICBnaWQ6IHN0cmluZztcbiAgbGFiZWw6IHN0cmluZztcbiAgaXRlbUlkPzogc3RyaW5nO1xuICBwYXJ0SWQ/OiBzdHJpbmc7XG4gIHBhcnRUeXBlSWQ/OiBzdHJpbmc7XG4gIHJvbGVJZD86IHN0cmluZztcbiAgbmFtZT86IHN0cmluZztcbiAgdmFsdWU/OiBzdHJpbmc7XG59XG5cbi8qXG4gKiBTY29wZWQgcGluLWJhc2VkIGxvb2t1cCBjb21wb25lbnQuIFRoaXMgY29tcG9uZW50IHByb3ZpZGVzIGEgbGlzdFxuICogb2YgcGluLWJhc2VkIHNlYXJjaGVzLCB3aXRoIGEgbG9va3VwIGNvbnRyb2wuIFdoZW5ldmVyIHRoZSB1c2VyXG4gKiBwaWNrcyBhIHBpbiB2YWx1ZSwgaGUgZ2V0cyB0aGUgZGV0YWlscyBhYm91dCBpdHMgaXRlbSBhbmQgcGFydCwgYW5kXG4gKiBpdGVtJ3MgbWV0YWRhdGEgcGFydCwgaWYgYW55LiBIZSBjYW4gdGhlbiB1c2UgdGhlc2UgZGF0YSB0byBidWlsZFxuICogc29tZSBFSUQgYnkgdmFyaW91c2x5IGFzc2VtYmxpbmcgdGhlc2UgY29tcG9uZW50cy5cbiAqL1xuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnY2FkbXVzLXBpbi10YXJnZXQtbG9va3VwJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3Bpbi10YXJnZXQtbG9va3VwLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50LmNzcyddLFxufSlcbmV4cG9ydCBjbGFzcyBQaW5UYXJnZXRMb29rdXBDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIHByaXZhdGUgX3N1YnM6IFN1YnNjcmlwdGlvbltdO1xuICBwcml2YXRlIF90YXJnZXQ6IFBpblRhcmdldCB8IHVuZGVmaW5lZDtcbiAgcHJpdmF0ZSBfbm9Gb3JtVXBkYXRlPzogYm9vbGVhbjtcbiAgcHJpdmF0ZSBfc3RhcnRXaXRoQnlUeXBlTW9kZT86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRydWUgd2hlbiB0aGUgYnktdHlwZSBwaW4gbG9va3VwIG1vZGUgaXMgYWN0aXZlLlxuICAgKiBVc2VyIGNhbiBjaGFuZ2UgbW9kZSB1bmxlc3MgbW9kZVN3aXRjaGluZyBpcyBmYWxzZS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBnZXQgcGluQnlUeXBlTW9kZSgpOiBib29sZWFuIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5ieVR5cGVNb2RlPy52YWx1ZTtcbiAgfVxuICBwdWJsaWMgc2V0IHBpbkJ5VHlwZU1vZGUodmFsdWU6IGJvb2xlYW4gfCB1bmRlZmluZWQpIHtcbiAgICBpZiAoIXRoaXMuYnlUeXBlTW9kZSkge1xuICAgICAgdGhpcy5fc3RhcnRXaXRoQnlUeXBlTW9kZSA9IHZhbHVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmJ5VHlwZU1vZGUuc2V0VmFsdWUodmFsdWUgfHwgZmFsc2UpO1xuICAgICAgdGhpcy5ieVR5cGVNb2RlLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVHJ1ZSB3aGVuIHRoZSB1c2VyIGNhbiBzd2l0Y2ggYmV0d2VlbiBieS10eXBlIGFuZCBieS1pdGVtIG1vZGUuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgY2FuU3dpdGNoTW9kZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUcnVlIHdoZW4gdGhlIHVzZXIgY2FuIGVkaXQgdGhlIHRhcmdldCdzIGdpZC9sYWJlbCBmb3IgaW50ZXJuYWxcbiAgICogdGFyZ2V0cy5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjYW5FZGl0VGFyZ2V0PzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBsb29rdXAgZGVmaW5pdGlvbnMgdG8gYmUgdXNlZCBmb3IgdGhlIGJ5LXR5cGUgbG9va3VwLiBJZlxuICAgKiBub3Qgc3BlY2lmaWVkLCB0aGUgbG9va3VwIGRlZmluaXRpb25zIHdpbGwgYmUgZ290IHZpYSBpbmplY3Rpb25cbiAgICogd2hlbiBhdmFpbGFibGU7IGlmIHRoZSBpbmplY3RlZCBkZWZpbml0aW9ucyBhcmUgZW1wdHksIHRoZVxuICAgKiBsb29rdXAgZGVmaW5pdGlvbnMgd2lsbCBiZSBidWlsdCBmcm9tIHRoZSBtb2RlbC10eXBlcyB0aGVzYXVydXM7XG4gICAqIGlmIHRoaXMgaXMgbm90IGF2YWlsYWJsZSBlaXRoZXIsIHRoZSBieS10eXBlIGxvb2t1cCB3aWxsIGJlXG4gICAqIGRpc2FibGVkLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGxvb2t1cERlZmluaXRpb25zPzogSW5kZXhMb29rdXBEZWZpbml0aW9ucztcblxuICAvKipcbiAgICogVGhlIHRhcmdldCB0byBiZSBlZGl0ZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IHRhcmdldCgpOiBQaW5UYXJnZXQgfCB1bmRlZmluZWQgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fdGFyZ2V0O1xuICB9XG4gIHB1YmxpYyBzZXQgdGFyZ2V0KHZhbHVlOiBQaW5UYXJnZXQgfCB1bmRlZmluZWQgfCBudWxsKSB7XG4gICAgaWYgKHRoaXMuX3RhcmdldCA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdGhpcy5fdGFyZ2V0ID0gdmFsdWUgfHwgdW5kZWZpbmVkO1xuICAgIHRoaXMudXBkYXRlRm9ybSh0aGlzLl90YXJnZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbiB1c2VyIGNsb3NlcyB0aGUgZWRpdG9yLlxuICAgKi9cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBlZGl0b3JDbG9zZTogRXZlbnRFbWl0dGVyPGFueT47XG4gIC8qKlxuICAgKiBFbWl0dGVkIHdoZW5ldmVyIHRoZSB0YXJnZXQgY2hhbmdlcy5cbiAgICogVGhlIGV2ZW50J3MgdmFsdWUgaXMgdGhlIG5ldyB0YXJnZXQuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgcHVibGljIHRhcmdldENoYW5nZTogRXZlbnRFbWl0dGVyPFBpblRhcmdldD47XG5cbiAgLy8gYnkgdHlwZVxuICBwdWJsaWMgbW9kZWxFbnRyaWVzOiBUaGVzYXVydXNFbnRyeVtdO1xuICBwdWJsaWMgcGFydFR5cGVLZXlzOiBzdHJpbmdbXTtcbiAgLy8gYnkgaXRlbVxuICBwdWJsaWMgaXRlbVBhcnRzOiBQYXJ0W107XG4gIC8vIGZvcm0gLSBieSBpdGVtXG4gIHB1YmxpYyBpdGVtOiBGb3JtQ29udHJvbDxJdGVtIHwgbnVsbD47XG4gIHB1YmxpYyBpdGVtUGFydDogRm9ybUNvbnRyb2w8UGFydCB8IG51bGw+O1xuICAvLyBmb3JtIC0gYnkgdHlwZVxuICBwdWJsaWMgcGFydFR5cGVLZXk6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xuICAvLyBmb3JtIC0gYm90aFxuICBwdWJsaWMgZ2lkOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcbiAgcHVibGljIGxhYmVsOiBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPjtcbiAgcHVibGljIGJ5VHlwZU1vZGU6IEZvcm1Db250cm9sPGJvb2xlYW4+O1xuICBwdWJsaWMgZXh0ZXJuYWw6IEZvcm1Db250cm9sPGJvb2xlYW4+O1xuICBwdWJsaWMgZm9ybTogRm9ybUdyb3VwO1xuXG4gIHB1YmxpYyBmaWx0ZXI6IFBpblJlZkxvb2t1cEZpbHRlcjtcbiAgcHVibGljIHBpbkZpbHRlck9wdGlvbnM/OiBJbmRleExvb2t1cERlZmluaXRpb247XG4gIHB1YmxpYyBsb29rdXBEYXRhPzogUGluTG9va3VwRGF0YTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBASW5qZWN0KCdpbmRleExvb2t1cERlZmluaXRpb25zJylcbiAgICBwcml2YXRlIF9wcmVzZXRMb29rdXBEZWZzOiBJbmRleExvb2t1cERlZmluaXRpb25zLFxuICAgIHB1YmxpYyBpdGVtTG9va3VwU2VydmljZTogSXRlbVJlZkxvb2t1cFNlcnZpY2UsXG4gICAgcHVibGljIHBpbkxvb2t1cFNlcnZpY2U6IFBpblJlZkxvb2t1cFNlcnZpY2UsXG4gICAgcHJpdmF0ZSBfaXRlbVNlcnZpY2U6IEl0ZW1TZXJ2aWNlLFxuICAgIHByaXZhdGUgX3RoZXNTZXJ2aWNlOiBUaGVzYXVydXNTZXJ2aWNlLFxuICAgIHByaXZhdGUgX3NuYWNrYmFyOiBNYXRTbmFja0JhcixcbiAgICBmb3JtQnVpbGRlcjogRm9ybUJ1aWxkZXJcbiAgKSB7XG4gICAgdGhpcy5wYXJ0VHlwZUtleXMgPSBbXTtcbiAgICB0aGlzLml0ZW1QYXJ0cyA9IFtdO1xuICAgIHRoaXMuX3N1YnMgPSBbXTtcbiAgICB0aGlzLm1vZGVsRW50cmllcyA9IFtdO1xuICAgIC8vIHRoaXMgaXMgdGhlIGRlZmF1bHQgZmlsdGVyIGZvciB0aGUgcGluIGxvb2t1cCwgd2hpY2ggd2lsbFxuICAgIC8vIGJlIG1lcmdlZCB3aXRoIHZhbHVlcyBwcm92aWRlZCBieSB1c2VyIGhlcmVcbiAgICB0aGlzLmZpbHRlciA9IHtcbiAgICAgIHRleHQ6ICcnLFxuICAgICAgbGltaXQ6IDEwLFxuICAgIH07XG4gICAgLy8gZm9ybVxuICAgIHRoaXMuaXRlbSA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XG4gICAgdGhpcy5pdGVtUGFydCA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XG4gICAgdGhpcy5wYXJ0VHlwZUtleSA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCk7XG4gICAgdGhpcy5naWQgPSBmb3JtQnVpbGRlci5jb250cm9sKG51bGwsIFtcbiAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICBWYWxpZGF0b3JzLm1heExlbmd0aCgzMDApLFxuICAgIF0pO1xuICAgIHRoaXMubGFiZWwgPSBmb3JtQnVpbGRlci5jb250cm9sKG51bGwsIFtcbiAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWQsXG4gICAgICBWYWxpZGF0b3JzLm1heExlbmd0aCgzMDApLFxuICAgIF0pO1xuICAgIHRoaXMuYnlUeXBlTW9kZSA9IGZvcm1CdWlsZGVyLmNvbnRyb2woZmFsc2UsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XG4gICAgdGhpcy5leHRlcm5hbCA9IGZvcm1CdWlsZGVyLmNvbnRyb2woZmFsc2UsIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XG4gICAgdGhpcy5mb3JtID0gZm9ybUJ1aWxkZXIuZ3JvdXAoe1xuICAgICAgaXRlbTogdGhpcy5pdGVtLFxuICAgICAgaXRlbVBhcnQ6IHRoaXMuaXRlbVBhcnQsXG4gICAgICBwYXJ0VHlwZUtleTogdGhpcy5wYXJ0VHlwZUtleSxcbiAgICAgIGdpZDogdGhpcy5naWQsXG4gICAgICBsYWJlbDogdGhpcy5sYWJlbCxcbiAgICAgIGJ5VHlwZU1vZGU6IHRoaXMuYnlUeXBlTW9kZSxcbiAgICAgIGV4dGVybmFsOiB0aGlzLmV4dGVybmFsLFxuICAgIH0pO1xuICAgIC8vIGV2ZW50c1xuICAgIHRoaXMudGFyZ2V0Q2hhbmdlID0gbmV3IEV2ZW50RW1pdHRlcjxQaW5UYXJnZXQ+KCk7XG4gICAgdGhpcy5lZGl0b3JDbG9zZSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xuICB9XG5cbiAgcHJpdmF0ZSBmb3JjZUJ5SXRlbSgpOiB2b2lkIHtcbiAgICB0aGlzLnBpbkJ5VHlwZU1vZGUgPSBmYWxzZTtcbiAgICB0aGlzLmNhblN3aXRjaE1vZGUgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0dXBLZXlzKCk6IHZvaWQge1xuICAgIC8vIHVzZSBESSBwcmVzZXRzIGlmIG5vIGxvb2t1cCBkZWZpbml0aW9uc1xuICAgIGlmICghdGhpcy5sb29rdXBEZWZpbml0aW9ucykge1xuICAgICAgdGhpcy5sb29rdXBEZWZpbml0aW9ucyA9IHRoaXMuX3ByZXNldExvb2t1cERlZnM7XG4gICAgfVxuICAgIC8vIGtleXMgYXJlIGFsbCB0aGUgZGVmaW5lZCBsb29rdXAgc2VhcmNoZXNcbiAgICB0aGlzLnBhcnRUeXBlS2V5cyA9IE9iamVjdC5rZXlzKHRoaXMubG9va3VwRGVmaW5pdGlvbnMpO1xuXG4gICAgLy8gaWYgbm8ga2V5cywgZ2V0IHRoZW0gZnJvbSB0aGVzYXVydXMgbW9kZWwtdHlwZXM7XG4gICAgLy8gaWYgdGhpcyBpcyBub3QgYXZhaWxhYmxlLCBqdXN0IGZvcmNlIGJ5IGl0ZW0gbW9kZS5cbiAgICBpZiAoIXRoaXMucGFydFR5cGVLZXlzLmxlbmd0aCkge1xuICAgICAgaWYgKHRoaXMubW9kZWxFbnRyaWVzPy5sZW5ndGgpIHtcbiAgICAgICAgLy8gc2V0IGxvb2t1cERlZmluaXRpb25zIGZyb20gdGhlc2F1cnVzIGVudHJpZXNcbiAgICAgICAgdGhpcy5sb29rdXBEZWZpbml0aW9ucyA9IHt9O1xuICAgICAgICB0aGlzLm1vZGVsRW50cmllcy5mb3JFYWNoKChlKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb29rdXBEZWZpbml0aW9ucyFbZS52YWx1ZV0gPSB7XG4gICAgICAgICAgICBuYW1lOiBlLnZhbHVlLFxuICAgICAgICAgICAgdHlwZUlkOiBlLmlkLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgICAgICAvLyBzZXQgdHlwZSBrZXlzIGZyb20gdGhlc2F1cnVzIGVudHJpZXNcbiAgICAgICAgdGhpcy5wYXJ0VHlwZUtleXMgPSB0aGlzLm1vZGVsRW50cmllcy5tYXAoKGUpID0+IGUudmFsdWUpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGlmIHN0aWxsIG5vIGtleXMsIGZvcmNlIGJ5IGl0ZW0gbW9kZVxuICAgIGlmICghdGhpcy5wYXJ0VHlwZUtleXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmZvcmNlQnlJdGVtKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGlmIHRoZXJlIGlzIG9ubHkgb25lIGtleSwgc2V0IGl0IGFzIHRoZSBkZWZhdWx0XG4gICAgICBpZiAodGhpcy5wYXJ0VHlwZUtleXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgIHRoaXMucGFydFR5cGVLZXkuc2V0VmFsdWUodGhpcy5wYXJ0VHlwZUtleXNbMF0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgY2FuQnVpbGRHaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICghdGhpcy5leHRlcm5hbC52YWx1ZSAmJiAhdGhpcy5naWQudmFsdWUpIHx8IHRoaXMuZ2lkLnByaXN0aW5lO1xuICB9XG5cbiAgcHJpdmF0ZSBjYW5CdWlsZExhYmVsKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAoIXRoaXMuZXh0ZXJuYWwudmFsdWUgJiYgIXRoaXMubGFiZWwudmFsdWUpIHx8IHRoaXMubGFiZWwucHJpc3RpbmU7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgLy8gc2V0IHN0YXJ0IG1vZGUgaWYgcmVxdWlyZWRcbiAgICBpZiAodGhpcy5fc3RhcnRXaXRoQnlUeXBlTW9kZSkge1xuICAgICAgdGhpcy5ieVR5cGVNb2RlLnNldFZhbHVlKHRydWUpO1xuICAgIH1cblxuICAgIC8vIHdoZW5ldmVyIGl0ZW0gY2hhbmdlcywgdXBkYXRlIGl0ZW0ncyBwYXJ0cyBhbmQgZmlsdGVyXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5pdGVtLnZhbHVlQ2hhbmdlc1xuICAgICAgICAucGlwZShkaXN0aW5jdFVudGlsQ2hhbmdlZCgpLCBkZWJvdW5jZVRpbWUoMzAwKSlcbiAgICAgICAgLnN1YnNjcmliZSgoaXRlbSkgPT4ge1xuICAgICAgICAgIHRoaXMuaXRlbVBhcnQuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgICAgdGhpcy5pdGVtUGFydHMgPSBpdGVtPy5wYXJ0cyB8fCBbXTtcbiAgICAgICAgICB0aGlzLmZpbHRlciA9IHtcbiAgICAgICAgICAgIC4uLnRoaXMuZmlsdGVyLFxuICAgICAgICAgICAgaXRlbUlkOiBpdGVtPy5pZCxcbiAgICAgICAgICB9O1xuICAgICAgICB9KVxuICAgICk7XG5cbiAgICAvLyB3aGVuZXZlciBpdGVtUGFydCBjaGFuZ2VzLCB1cGRhdGUgdGFyZ2V0IGFuZCBldmVudHVhbGx5IGdpZFxuICAgIHRoaXMuX3N1YnMucHVzaChcbiAgICAgIHRoaXMuaXRlbVBhcnQudmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSgzMDApKVxuICAgICAgICAuc3Vic2NyaWJlKChwYXJ0KSA9PiB7XG4gICAgICAgICAgaWYgKCF0aGlzLmdpZC52YWx1ZSB8fCB0aGlzLmdpZC5wcmlzdGluZSkge1xuICAgICAgICAgICAgdGhpcy5naWQuc2V0VmFsdWUodGhpcy5idWlsZEdpZCgpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5maWx0ZXIgPSB7XG4gICAgICAgICAgICAuLi50aGlzLmZpbHRlcixcbiAgICAgICAgICAgIHBhcnRJZDogcGFydD8uaWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVRhcmdldCgpO1xuICAgICAgICB9KVxuICAgICk7XG5cbiAgICAvLyB3aGVuZXZlciBwYXJ0VHlwZUtleSBjaGFuZ2VzLCB1cGRhdGUgZmlsdGVyJ3Mgb3B0aW9uc1xuICAgIHRoaXMuX3N1YnMucHVzaChcbiAgICAgIHRoaXMucGFydFR5cGVLZXkudmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSgzMDApKVxuICAgICAgICAuc3Vic2NyaWJlKChrZXkpID0+IHtcbiAgICAgICAgICB0aGlzLnBpbkZpbHRlck9wdGlvbnMgPSBrZXlcbiAgICAgICAgICAgID8gdGhpcy5sb29rdXBEZWZpbml0aW9ucyFba2V5XVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIGxvYWQgbW9kZWwtdHlwZXMgdGhlc2F1cnVzIGVudHJpZXNcbiAgICB0aGlzLl90aGVzU2VydmljZS5nZXRUaGVzYXVydXMoJ21vZGVsLXR5cGVzJywgdHJ1ZSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6ICh0KSA9PiB7XG4gICAgICAgIHRoaXMubW9kZWxFbnRyaWVzID0gdC5lbnRyaWVzIHx8IFtdO1xuICAgICAgICBpZiAodGhpcy5tb2RlbEVudHJpZXM/Lmxlbmd0aCkge1xuICAgICAgICAgIHRoaXMuc2V0dXBLZXlzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5mb3JjZUJ5SXRlbSgpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZXJyb3I6ICgpID0+IHtcbiAgICAgICAgdGhpcy5mb3JjZUJ5SXRlbSgpO1xuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuX3N1YnMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHRoaXMuX3N1YnNbaV0udW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkR2lkKCk6IHN0cmluZyB8IG51bGwge1xuICAgIC8vIHRoZSBHSUQgaXMgdGhlIHBhcnQgSUQgaWYgYW55LCBvciB0aGUgaXRlbSBJRCwgZm9sbG93ZWQgYnlcbiAgICAvLyB0aGUgcGluJ3MgdmFsdWUgKD1FSUQpXG4gICAgY29uc3QgcGluID0gdGhpcy5sb29rdXBEYXRhPy5waW47XG4gICAgaWYgKCFwaW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gcGluLnBhcnRJZFxuICAgICAgPyBgUCR7cGluLnBhcnRJZH0vJHtwaW4udmFsdWV9YFxuICAgICAgOiBgSSR7cGluLml0ZW1JZH0vJHtwaW4udmFsdWV9YDtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRMYWJlbCgpOiBzdHJpbmcgfCBudWxsIHtcbiAgICBpZiAoIXRoaXMubG9va3VwRGF0YT8ucGluKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3Qgc2I6IHN0cmluZ1tdID0gW107XG4gICAgLy8gcGluIHZhbHVlXG4gICAgc2IucHVzaCh0aGlzLmxvb2t1cERhdGEucGluLnZhbHVlISk7XG4gICAgLy8gaXRlbSB0aXRsZVxuICAgIHNiLnB1c2goJyB8ICcpO1xuICAgIHNiLnB1c2godGhpcy5sb29rdXBEYXRhLml0ZW0hLnRpdGxlIHx8IHRoaXMubG9va3VwRGF0YS5pdGVtIS5pZCk7XG4gICAgLy8gcGFydCB0eXBlIGFuZCByb2xlXG4gICAgY29uc3QgZSA9IHRoaXMubW9kZWxFbnRyaWVzPy5maW5kKFxuICAgICAgKGUpID0+IGUuaWQgPT09IHRoaXMubG9va3VwRGF0YSEucGluLnBhcnRUeXBlSWRcbiAgICApO1xuICAgIHNiLnB1c2goJyAoJyk7XG4gICAgc2IucHVzaChlPy52YWx1ZSB8fCB0aGlzLmxvb2t1cERhdGEucGluLnBhcnRUeXBlSWQpO1xuICAgIGlmICh0aGlzLmxvb2t1cERhdGEucGluLnJvbGVJZCkge1xuICAgICAgc2IucHVzaChgLCAke3RoaXMubG9va3VwRGF0YS5waW4ucm9sZUlkfWApO1xuICAgIH1cbiAgICBzYi5wdXNoKCcpJyk7XG4gICAgcmV0dXJuIHNiLmpvaW4oJycpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRUYXJnZXQoKTogUGluVGFyZ2V0IHtcbiAgICBpZiAodGhpcy5leHRlcm5hbC52YWx1ZSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZ2lkOiB0aGlzLmdpZC52YWx1ZSB8fCAnJyxcbiAgICAgICAgbGFiZWw6IHRoaXMubGFiZWwudmFsdWUgfHwgJycsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBwaW4gPSB0aGlzLmxvb2t1cERhdGE/LnBpbjtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGl0ZW1JZDogcGluPy5pdGVtSWQgfHwgJycsXG4gICAgICAgIHBhcnRJZDogcGluPy5wYXJ0SWQgfHwgJycsXG4gICAgICAgIHBhcnRUeXBlSWQ6IHBpbj8ucGFydFR5cGVJZCB8fCAnJyxcbiAgICAgICAgcm9sZUlkOiBwaW4/LnJvbGVJZCB8fCAnJyxcbiAgICAgICAgbmFtZTogcGluPy5uYW1lIHx8ICcnLFxuICAgICAgICB2YWx1ZTogcGluPy52YWx1ZSB8fCAnJyxcbiAgICAgICAgZ2lkOiBwaW4/LnZhbHVlIHx8ICcnLFxuICAgICAgICBsYWJlbDogcGluPy52YWx1ZSB8fCAnJyxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVUYXJnZXQoKTogdm9pZCB7XG4gICAgdGhpcy5fbm9Gb3JtVXBkYXRlID0gdHJ1ZTtcblxuICAgIGlmICh0aGlzLmNhbkJ1aWxkR2lkKCkpIHtcbiAgICAgIHRoaXMuZ2lkLnNldFZhbHVlKHRoaXMuYnVpbGRHaWQoKSk7XG4gICAgICB0aGlzLmdpZC5tYXJrQXNEaXJ0eSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jYW5CdWlsZExhYmVsKCkpIHtcbiAgICAgIHRoaXMubGFiZWwuc2V0VmFsdWUodGhpcy5idWlsZExhYmVsKCkpO1xuICAgICAgdGhpcy5sYWJlbC5tYXJrQXNEaXJ0eSgpO1xuICAgIH1cbiAgICB0aGlzLnRhcmdldCA9IHRoaXMuZ2V0VGFyZ2V0KCk7XG5cbiAgICB0aGlzLl9ub0Zvcm1VcGRhdGUgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRm9ybSh0YXJnZXQ/OiBQaW5UYXJnZXQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fbm9Gb3JtVXBkYXRlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIC8vIGJ1aWxkIHBpbiBpbmZvIGZyb20gdGFyZ2V0XG4gICAgaWYgKCF0YXJnZXQpIHtcbiAgICAgIHRoaXMubG9va3VwRGF0YSA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuZm9ybS5yZXNldCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmV4dGVybmFsLnNldFZhbHVlKCF0YXJnZXQubmFtZSk7XG4gICAgdGhpcy5sb29rdXBEYXRhID0ge1xuICAgICAgcGluOiB7XG4gICAgICAgIGl0ZW1JZDogdGFyZ2V0Lml0ZW1JZCB8fCAnJyxcbiAgICAgICAgcGFydElkOiB0YXJnZXQucGFydElkIHx8ICcnLFxuICAgICAgICBwYXJ0VHlwZUlkOiB0YXJnZXQucGFydFR5cGVJZCB8fCAnJyxcbiAgICAgICAgcm9sZUlkOiB0YXJnZXQucm9sZUlkIHx8ICcnLFxuICAgICAgICBuYW1lOiB0YXJnZXQubmFtZSB8fCAnJyxcbiAgICAgICAgdmFsdWU6IHRhcmdldC52YWx1ZSB8fCAnJyxcbiAgICAgIH0sXG4gICAgfTtcbiAgICAvLyBnZXQgaXRlbVxuICAgIGlmICh0YXJnZXQuaXRlbUlkKSB7XG4gICAgICB0aGlzLl9pdGVtU2VydmljZS5nZXRJdGVtKHRhcmdldC5pdGVtSWQsIHRydWUpLnN1YnNjcmliZSh7XG4gICAgICAgIG5leHQ6IChpdGVtKSA9PiB7XG4gICAgICAgICAgdGhpcy5pdGVtLnNldFZhbHVlKGl0ZW0pO1xuICAgICAgICAgIHRoaXMuZm9ybS5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBpdGVtIGxvb2t1cCBjaGFuZ2VzIChpdGVtIGlzIGxvb2tlZCB1cFxuICAgKiBieSBpdHMgdGl0bGUpLlxuICAgKlxuICAgKiBAcGFyYW0gaXRlbSBUaGUgaXRlbSBnb3QgZnJvbSBsb29rdXAuXG4gICAqL1xuICBwdWJsaWMgb25JdGVtTG9va3VwQ2hhbmdlKGl0ZW06IEl0ZW0pOiB2b2lkIHtcbiAgICAvLyBsb2FkIGl0ZW0ncyBwYXJ0c1xuICAgIHRoaXMuX2l0ZW1TZXJ2aWNlLmdldEl0ZW0oaXRlbS5pZCwgdHJ1ZSkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IChpKSA9PiB7XG4gICAgICAgIC8vIHNldHRpbmcgdGhlIGl0ZW0gd2lsbCB0cmlnZ2VyIGl0cyBwYXJ0cyB1cGRhdGVcbiAgICAgICAgdGhpcy5pdGVtLnNldFZhbHVlKGkpO1xuICAgICAgICB0aGlzLnVwZGF0ZVRhcmdldCgpO1xuICAgICAgfSxcbiAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcbiAgICAgICAgaWYgKGVycm9yKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihKU09OLnN0cmluZ2lmeShlcnJvcikpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuaXRlbVBhcnQuc2V0VmFsdWUobnVsbCk7XG4gICAgICAgIHRoaXMuaXRlbVBhcnRzID0gW107XG4gICAgICAgIHRoaXMudXBkYXRlVGFyZ2V0KCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBsb2FkSXRlbUluZm8ocGluOiBEYXRhUGluSW5mbyk6IHZvaWQge1xuICAgIGZvcmtKb2luKHtcbiAgICAgIGl0ZW06IHRoaXMuX2l0ZW1TZXJ2aWNlLmdldEl0ZW0ocGluLml0ZW1JZCwgZmFsc2UpLFxuICAgICAgcGFydDogdGhpcy5faXRlbVNlcnZpY2UuZ2V0UGFydEZyb21UeXBlQW5kUm9sZShcbiAgICAgICAgcGluLml0ZW1JZCxcbiAgICAgICAgTUVUQURBVEFfUEFSVF9JRFxuICAgICAgKSxcbiAgICB9KVxuICAgICAgLnBpcGUodGFrZSgxKSlcbiAgICAgIC5zdWJzY3JpYmUoe1xuICAgICAgICBuZXh0OiAocmVzdWx0KSA9PiB7XG4gICAgICAgICAgdGhpcy5sb29rdXBEYXRhID0ge1xuICAgICAgICAgICAgcGluOiBwaW4sXG4gICAgICAgICAgICBpdGVtOiByZXN1bHQuaXRlbSxcbiAgICAgICAgICAgIG1ldGFQYXJ0OiByZXN1bHQucGFydCBhcyBNZXRhZGF0YVBhcnQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVRhcmdldCgpO1xuICAgICAgICB9LFxuICAgICAgICBlcnJvcjogKGVycm9yKSA9PiB7XG4gICAgICAgICAgdGhpcy5sb29rdXBEYXRhID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgICAgICBlcnJvciA/IEpTT04uc3RyaW5naWZ5KGVycm9yKSA6ICdFcnJvciBsb2FkaW5nIGl0ZW0vbWV0YWRhdGEnXG4gICAgICAgICAgKTtcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIHRoZSBwaW4gbG9va3VwIGNoYW5nZS4gQSBwaW4gaXMgbG9va2VkIHVwIGJ5IGl0c1xuICAgKiBuYW1lIGFuZCB2YWx1ZSAoPXRoZSBmaWx0ZXIncyB0ZXh0KSwgYW5kIG9wdGlvbmFsbHkgYnk6XG4gICAqIC0gaXRzIGluZGV4IGxvb2t1cCBkZWZpbml0aW9uIChzZWxlY3RlZCBieSBwYXJ0VHlwZUtleSkuXG4gICAqIC0gaXRzIGl0ZW0gKGRlZmluZWQgYnkgaXRlbSwgaW4gZmlsdGVyKS5cbiAgICogLSBpdHMgcGFydCAoZGVmaW5lZCBieSBpdGVtUGFydCwgaW4gZmlsdGVyKS5cbiAgICpcbiAgICogQHBhcmFtIGluZm8gVGhlIHBpbiBpbmZvIGZyb20gcGluIGxvb2t1cC5cbiAgICovXG4gIHB1YmxpYyBvblBpbkxvb2t1cENoYW5nZShpbmZvOiBEYXRhUGluSW5mbyk6IHZvaWQge1xuICAgIHRoaXMubG9hZEl0ZW1JbmZvKGluZm8pO1xuICB9XG5cbiAgcHVibGljIG9uQ29waWVkKCk6IHZvaWQge1xuICAgIHRoaXMuX3NuYWNrYmFyLm9wZW4oJ0NvcGllZCB0byBjbGlwYm9hcmQnLCAnT0snLCB7XG4gICAgICBkdXJhdGlvbjogMTUwMCxcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBjbG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLmVkaXRvckNsb3NlLmVtaXQoKTtcbiAgfVxuXG4gIHB1YmxpYyBzYXZlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmZvcm0uaW52YWxpZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl90YXJnZXQgPSB0aGlzLmdldFRhcmdldCgpO1xuICAgIHRoaXMudGFyZ2V0Q2hhbmdlLmVtaXQodGhpcy5fdGFyZ2V0KTtcbiAgfVxufVxuIiwiPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCIgKHN1Ym1pdCk9XCJzYXZlKClcIj5cclxuICA8IS0tIGV4dGVybmFsIC0tPlxyXG4gIDxtYXQtY2hlY2tib3ggW2Zvcm1Db250cm9sXT1cImV4dGVybmFsXCI+ZXh0ZXJuYWw8L21hdC1jaGVja2JveD5cclxuXHJcbiAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICA8IS0tIGxhYmVsIC0tPlxyXG4gICAgPGRpdj5cclxuICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiZXh0ZXJuYWwudmFsdWUgfHwgY2FuRWRpdFRhcmdldFwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+bGFiZWw8L21hdC1sYWJlbD5cclxuICAgICAgICA8aW5wdXQgbWF0SW5wdXQgW2Zvcm1Db250cm9sXT1cImxhYmVsXCIgLz5cclxuICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAqbmdJZj1cIiRhbnkobGFiZWwpLmVycm9ycz8ucmVxdWlyZWQgJiYgKGxhYmVsLmRpcnR5IHx8IGxhYmVsLnRvdWNoZWQpXCJcclxuICAgICAgICAgID5sYWJlbCByZXF1aXJlZDwvbWF0LWVycm9yXHJcbiAgICAgICAgPlxyXG4gICAgICAgIDxtYXQtZXJyb3JcclxuICAgICAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgICAgICRhbnkobGFiZWwpLmVycm9ycz8ubWF4TGVuZ3RoICYmIChsYWJlbC5kaXJ0eSB8fCBsYWJlbC50b3VjaGVkKVxyXG4gICAgICAgICAgXCJcclxuICAgICAgICAgID5sYWJlbCB0b28gbG9uZzwvbWF0LWVycm9yXHJcbiAgICAgICAgPlxyXG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICA8ZGl2XHJcbiAgICAgICAgKm5nSWY9XCIhZXh0ZXJuYWwudmFsdWUgJiYgIWNhbkVkaXRUYXJnZXQgJiYgbGFiZWwudmFsdWVcIlxyXG4gICAgICAgIGNsYXNzPVwiaW5mb1wiXHJcbiAgICAgID5cclxuICAgICAgICA8c3BhbiBjbGFzcz1cImxhYmVsXCI+bGFiZWw8L3NwYW4+e3sgbGFiZWwudmFsdWUgfX1cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIGdpZCAtLT5cclxuICAgIDxkaXY+XHJcbiAgICAgIDxtYXQtZm9ybS1maWVsZCAqbmdJZj1cImV4dGVybmFsLnZhbHVlIHx8IGNhbkVkaXRUYXJnZXRcIj5cclxuICAgICAgICA8bWF0LWxhYmVsPkdJRDwvbWF0LWxhYmVsPlxyXG4gICAgICAgIDxpbnB1dCBtYXRJbnB1dCBbZm9ybUNvbnRyb2xdPVwiZ2lkXCIgLz5cclxuICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAqbmdJZj1cIiRhbnkoZ2lkKS5lcnJvcnM/LnJlcXVpcmVkICYmIChnaWQuZGlydHkgfHwgZ2lkLnRvdWNoZWQpXCJcclxuICAgICAgICAgID5HSUQgcmVxdWlyZWQ8L21hdC1lcnJvclxyXG4gICAgICAgID5cclxuICAgICAgICA8bWF0LWVycm9yXHJcbiAgICAgICAgICAqbmdJZj1cIiRhbnkoZ2lkKS5lcnJvcnM/Lm1heExlbmd0aCAmJiAoZ2lkLmRpcnR5IHx8IGdpZC50b3VjaGVkKVwiXHJcbiAgICAgICAgICA+R0lEIHRvbyBsb25nPC9tYXQtZXJyb3JcclxuICAgICAgICA+XHJcbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICAgIDxkaXYgKm5nSWY9XCIhZXh0ZXJuYWwudmFsdWUgJiYgIWNhbkVkaXRUYXJnZXQgJiYgZ2lkLnZhbHVlXCIgY2xhc3M9XCJpbmZvXCI+XHJcbiAgICAgICAgPHNwYW4gY2xhc3M9XCJsYWJlbFwiPkdJRDwvc3Bhbj4gPHNwYW4gY2xhc3M9XCJnaWRcIj57eyBnaWQudmFsdWUgfX08L3NwYW4+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcblxyXG4gIDwhLS0gQlkgSVRFTSAtLT5cclxuICA8ZGl2ICpuZ0lmPVwiIWV4dGVybmFsLnZhbHVlXCI+XHJcbiAgICA8ZmllbGRzZXQgKm5nSWY9XCIhYnlUeXBlTW9kZS52YWx1ZVwiIGNsYXNzPVwiZm9ybS1yb3dcIj5cclxuICAgICAgPGxlZ2VuZD5waW4gZmlsdGVyczwvbGVnZW5kPlxyXG4gICAgICA8IS0tIGl0ZW0gZmlsdGVyIC0tPlxyXG4gICAgICA8Y2FkbXVzLXJlZi1sb29rdXBcclxuICAgICAgICBbc2VydmljZV09XCJpdGVtTG9va3VwU2VydmljZVwiXHJcbiAgICAgICAgbGFiZWw9XCJpdGVtXCJcclxuICAgICAgICAoaXRlbUNoYW5nZSk9XCJvbkl0ZW1Mb29rdXBDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgID48L2NhZG11cy1yZWYtbG9va3VwPlxyXG5cclxuICAgICAgPCEtLSBwYXJ0IGZpbHRlciAtLT5cclxuICAgICAgPG1hdC1mb3JtLWZpZWxkICpuZ0lmPVwiaXRlbVBhcnRzLmxlbmd0aFwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+cGFydDwvbWF0LWxhYmVsPlxyXG4gICAgICAgIDxtYXQtc2VsZWN0IFtmb3JtQ29udHJvbF09XCJpdGVtUGFydFwiPlxyXG4gICAgICAgICAgPG1hdC1vcHRpb24gW3ZhbHVlXT1cIm51bGxcIj4oYW55KTwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgIDxtYXQtb3B0aW9uICpuZ0Zvcj1cImxldCBwIG9mIGl0ZW1QYXJ0c1wiIFt2YWx1ZV09XCJwXCI+e3tcclxuICAgICAgICAgICAgcC50eXBlSWQgfCBmbGF0TG9va3VwIDogbW9kZWxFbnRyaWVzIDogXCJpZFwiIDogXCJ2YWx1ZVwiXHJcbiAgICAgICAgICB9fTwvbWF0LW9wdGlvbj5cclxuICAgICAgICA8L21hdC1zZWxlY3Q+XHJcbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICA8L2ZpZWxkc2V0PlxyXG5cclxuICAgIDwhLS0gQlkgVFlQRSAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCJieVR5cGVNb2RlLnZhbHVlXCI+XHJcbiAgICAgIDwhLS0gcGFyIHR5cGUgZmlsdGVyIC0tPlxyXG4gICAgICA8bWF0LWZvcm0tZmllbGQgKm5nSWY9XCJwYXJ0VHlwZUtleXM/Lmxlbmd0aFwiPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+cGFydCB0eXBlPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgPG1hdC1zZWxlY3QgW2Zvcm1Db250cm9sXT1cInBhcnRUeXBlS2V5XCI+XHJcbiAgICAgICAgICA8bWF0LW9wdGlvbiAqbmdGb3I9XCJsZXQgayBvZiBwYXJ0VHlwZUtleXNcIiBbdmFsdWVdPVwia1wiPnt7XHJcbiAgICAgICAgICAgIGtcclxuICAgICAgICAgIH19PC9tYXQtb3B0aW9uPlxyXG4gICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gUElOIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cImZvcm0tcm93XCI+XHJcbiAgICAgIDwhLS0gcGluIGxvb2t1cCAtLT5cclxuICAgICAgPGNhZG11cy1yZWYtbG9va3VwXHJcbiAgICAgICAgW3NlcnZpY2VdPVwicGluTG9va3VwU2VydmljZVwiXHJcbiAgICAgICAgW2Jhc2VGaWx0ZXJdPVwiZmlsdGVyXCJcclxuICAgICAgICBbb3B0aW9uc109XCJwaW5GaWx0ZXJPcHRpb25zXCJcclxuICAgICAgICBsYWJlbD1cInBpblwiXHJcbiAgICAgICAgKGl0ZW1DaGFuZ2UpPVwib25QaW5Mb29rdXBDaGFuZ2UoJGV2ZW50KVwiXHJcbiAgICAgID48L2NhZG11cy1yZWYtbG9va3VwPlxyXG4gICAgICA8IS0tIG1vZGUgc3dpdGNoZXIgLS0+XHJcbiAgICAgIDxkaXY+XHJcbiAgICAgICAgPG1hdC1jaGVja2JveCBbZm9ybUNvbnRyb2xdPVwiYnlUeXBlTW9kZVwiICpuZ0lmPVwiY2FuU3dpdGNoTW9kZVwiPlxyXG4gICAgICAgICAgYnkgdHlwZTwvbWF0LWNoZWNrYm94XHJcbiAgICAgICAgPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDwhLS0gZGF0YSAtLT5cclxuICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsIGlkPVwiZGF0YVwiICpuZ0lmPVwibG9va3VwRGF0YT8ucGluPy5uYW1lXCI+XHJcbiAgICAgIDxtYXQtZXhwYW5zaW9uLXBhbmVsLWhlYWRlcj5waW4gZGF0YTwvbWF0LWV4cGFuc2lvbi1wYW5lbC1oZWFkZXI+XHJcbiAgICAgIDwhLS0gdGFibGUgLS0+XHJcbiAgICAgIDx0YWJsZT5cclxuICAgICAgICA8dGhlYWQ+XHJcbiAgICAgICAgICA8dGg+PC90aD5cclxuICAgICAgICAgIDx0aD5zb3VyY2U8L3RoPlxyXG4gICAgICAgICAgPHRoPnZhbHVlPC90aD5cclxuICAgICAgICA8L3RoZWFkPlxyXG4gICAgICAgIDx0Ym9keT5cclxuICAgICAgICAgIDwhLS0gcGluIC0tPlxyXG4gICAgICAgICAgPHRyICpuZ0lmPVwibG9va3VwRGF0YT8ucGluPy52YWx1ZVwiPlxyXG4gICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cImxvb2t1cERhdGEhLnBpbiEudmFsdWVcIlxyXG4gICAgICAgICAgICAgICAgKGNka0NvcHlUb0NsaXBib2FyZENvcGllZCk9XCJvbkNvcGllZCgpXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y29udGVudF9jb3B5PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkPnBpbjwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBsb29rdXBEYXRhIS5waW4udmFsdWUgfX08L3RkPlxyXG4gICAgICAgICAgPC90cj5cclxuICAgICAgICAgIDwhLS0gaXRlbSBJRCAtLT5cclxuICAgICAgICAgIDx0ciAqbmdJZj1cImxvb2t1cERhdGE/LnBpbj8uaXRlbUlkXCI+XHJcbiAgICAgICAgICAgIDx0ZD5cclxuICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgIG1hdC1pY29uLWJ1dHRvblxyXG4gICAgICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgICAgIFtjZGtDb3B5VG9DbGlwYm9hcmRdPVwibG9va3VwRGF0YSEucGluIS5pdGVtSWRcIlxyXG4gICAgICAgICAgICAgICAgKGNka0NvcHlUb0NsaXBib2FyZENvcGllZCk9XCJvbkNvcGllZCgpXCJcclxuICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICA8bWF0LWljb24+Y29udGVudF9jb3B5PC9tYXQtaWNvbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC90ZD5cclxuICAgICAgICAgICAgPHRkPml0ZW0gSUQ8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+e3sgbG9va3VwRGF0YSEucGluLml0ZW1JZCB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPCEtLSBpdGVtIHRpdGxlIC0tPlxyXG4gICAgICAgICAgPHRyICpuZ0lmPVwibG9va3VwRGF0YT8uaXRlbT8udGl0bGVcIj5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgW2Nka0NvcHlUb0NsaXBib2FyZF09XCJsb29rdXBEYXRhIS5pdGVtIS50aXRsZVwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+aXRlbSB0aXRsZTwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBsb29rdXBEYXRhIS5pdGVtIS50aXRsZSB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPCEtLSBwYXJ0IElEIC0tPlxyXG4gICAgICAgICAgPHRyICpuZ0lmPVwibG9va3VwRGF0YT8ucGluPy5wYXJ0SWRcIj5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgW2Nka0NvcHlUb0NsaXBib2FyZF09XCJsb29rdXBEYXRhIS5waW4hLnBhcnRJZFwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+cGFydCBJRDwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZD57eyBsb29rdXBEYXRhIS5waW4ucGFydElkIH19PC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgICA8IS0tIHBhcnQgdHlwZSBJRCAtLT5cclxuICAgICAgICAgIDx0ciAqbmdJZj1cImxvb2t1cERhdGE/LnBpbj8ucGFydFR5cGVJZFwiPlxyXG4gICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cImxvb2t1cERhdGEhLnBpbiEucGFydFR5cGVJZFwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+cGFydCB0eXBlIElEPC90ZD5cclxuICAgICAgICAgICAgPHRkPnt7IGxvb2t1cERhdGEhLnBpbiEucGFydFR5cGVJZCB9fTwvdGQ+XHJcbiAgICAgICAgICA8L3RyPlxyXG4gICAgICAgICAgPCEtLSBwYXJ0IHJvbGUgSUQgLS0+XHJcbiAgICAgICAgICA8dHIgKm5nSWY9XCJsb29rdXBEYXRhPy5waW4/LnJvbGVJZFwiPlxyXG4gICAgICAgICAgICA8dGQ+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICBtYXQtaWNvbi1idXR0b25cclxuICAgICAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgICAgICBbY2RrQ29weVRvQ2xpcGJvYXJkXT1cImxvb2t1cERhdGEhLnBpbiEucm9sZUlkIVwiXHJcbiAgICAgICAgICAgICAgICAoY2RrQ29weVRvQ2xpcGJvYXJkQ29waWVkKT1cIm9uQ29waWVkKClcIlxyXG4gICAgICAgICAgICAgID5cclxuICAgICAgICAgICAgICAgIDxtYXQtaWNvbj5jb250ZW50X2NvcHk8L21hdC1pY29uPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8L3RkPlxyXG4gICAgICAgICAgICA8dGQ+cGFydCByb2xlIElEPC90ZD5cclxuICAgICAgICAgICAgPHRkPnt7IGxvb2t1cERhdGEhLnBpbiEucm9sZUlkIH19PC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcblxyXG4gICAgICAgICAgPCEtLSBwYXJ0J3MgbWV0YWRhdGEgLS0+XHJcbiAgICAgICAgICA8dHJcclxuICAgICAgICAgICAgKm5nRm9yPVwiXHJcbiAgICAgICAgICAgICAgbGV0IG0gb2YgbG9va3VwRGF0YT8ubWV0YVBhcnQ/Lm1ldGFkYXRhIHx8IFtdO1xyXG4gICAgICAgICAgICAgIGxldCBpID0gaW5kZXhcclxuICAgICAgICAgICAgXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPHRkPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAgICAgbWF0LWljb24tYnV0dG9uXHJcbiAgICAgICAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgICAgICAgW2Nka0NvcHlUb0NsaXBib2FyZF09XCJtLnZhbHVlXCJcclxuICAgICAgICAgICAgICAgIChjZGtDb3B5VG9DbGlwYm9hcmRDb3BpZWQpPVwib25Db3BpZWQoKVwiXHJcbiAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgPG1hdC1pY29uPmNvbnRlbnRfY29weTwvbWF0LWljb24+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgICAgIDx0ZCBjbGFzcz1cIm1ldGFkYXRhXCI+e3sgbS5uYW1lIH19PC90ZD5cclxuICAgICAgICAgICAgPHRkIGNsYXNzPVwibWV0YWRhdGFcIj57eyBtLnZhbHVlIH19PC90ZD5cclxuICAgICAgICAgIDwvdHI+XHJcbiAgICAgICAgPC90Ym9keT5cclxuICAgICAgPC90YWJsZT5cclxuICAgIDwvbWF0LWV4cGFuc2lvbi1wYW5lbD5cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBidXR0b25zIC0tPlxyXG4gIDxkaXY+XHJcbiAgICA8YnV0dG9uIG1hdC1mbGF0LWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImNsb3NlKClcIj5cclxuICAgICAgPG1hdC1pY29uIGNvbG9yPVwid2FyblwiPmNsb3NlPC9tYXQtaWNvbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPGJ1dHRvbiBtYXQtZmxhdC1idXR0b24gdHlwZT1cInN1Ym1pdFwiIFtkaXNhYmxlZF09XCJmb3JtLmludmFsaWRcIj5cclxuICAgICAgPG1hdC1pY29uIGNvbG9yPVwicHJpbWFyeVwiPmNoZWNrX2NpcmNsZTwvbWF0LWljb24+IHRhcmdldFxyXG4gICAgPC9idXR0b24+XHJcbiAgPC9kaXY+XHJcbjwvZm9ybT5cclxuIl19
|