@myrmidon/cadmus-refs-asserted-ids 2.0.0 → 2.1.1

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.
@@ -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
+ gid: this.gid.value || '',
249
+ label: this.label.value || '',
250
+ itemId: pin?.itemId || '',
251
+ partId: pin?.partId || '',
252
+ partTypeId: pin?.partTypeId || '',
253
+ roleId: pin?.roleId || '',
254
+ name: pin?.name || '',
255
+ value: 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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aEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3ZDLENBQUM7OEdBamNVLHdCQUF3QixrQkE4RnpCLHdCQUF3QjtrR0E5RnZCLHdCQUF3Qiw2U0N4RnJDLCs3UUF1UEE7O1NEL0phLHdCQUF3QjsyRkFBeEIsd0JBQXdCO2tCQUxwQyxTQUFTOytCQUNFLDBCQUEwQjs7MEJBa0dqQyxNQUFNOzJCQUFDLHdCQUF3Qjs4TkFuRnZCLGFBQWE7c0JBRHZCLEtBQUs7Z0JBaUJDLGFBQWE7c0JBRG5CLEtBQUs7Z0JBT0MsYUFBYTtzQkFEbkIsS0FBSztnQkFXQyxpQkFBaUI7c0JBRHZCLEtBQUs7Z0JBT0ssTUFBTTtzQkFEaEIsS0FBSztnQkFnQkMsV0FBVztzQkFEakIsTUFBTTtnQkFPQSxZQUFZO3NCQURsQixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIEluamVjdCxcbiAgSW5wdXQsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgRm9ybUJ1aWxkZXIsXG4gIEZvcm1Db250cm9sLFxuICBGb3JtR3JvdXAsXG4gIFZhbGlkYXRvcnMsXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7XG4gIFN1YnNjcmlwdGlvbixcbiAgZGVib3VuY2VUaW1lLFxuICBkaXN0aW5jdFVudGlsQ2hhbmdlZCxcbiAgZm9ya0pvaW4sXG4gIHRha2UsXG59IGZyb20gJ3J4anMnO1xuaW1wb3J0IHsgTWF0U25hY2tCYXIgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9zbmFjay1iYXInO1xuXG5pbXBvcnQgeyBJdGVtU2VydmljZSwgVGhlc2F1cnVzU2VydmljZSB9IGZyb20gJ0BteXJtaWRvbi9jYWRtdXMtYXBpJztcbmltcG9ydCB7XG4gIERhdGFQaW5JbmZvLFxuICBJbmRleExvb2t1cERlZmluaXRpb24sXG4gIEluZGV4TG9va3VwRGVmaW5pdGlvbnMsXG4gIEl0ZW0sXG4gIFBhcnQsXG4gIFRoZXNhdXJ1c0VudHJ5LFxufSBmcm9tICdAbXlybWlkb24vY2FkbXVzLWNvcmUnO1xuXG5pbXBvcnQge1xuICBQaW5SZWZMb29rdXBGaWx0ZXIsXG4gIFBpblJlZkxvb2t1cFNlcnZpY2UsXG59IGZyb20gJy4uL3NlcnZpY2VzL3Bpbi1yZWYtbG9va3VwLnNlcnZpY2UnO1xuaW1wb3J0IHsgSXRlbVJlZkxvb2t1cFNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9pdGVtLXJlZi1sb29rdXAuc2VydmljZSc7XG5cbi8vIGZyb20gQ2FkbXVzIGdlbmVyYWwgcGFydHNcbmNvbnN0IE1FVEFEQVRBX1BBUlRfSUQgPSAnaXQudmVkcGgubWV0YWRhdGEnO1xuaW50ZXJmYWNlIE1ldGFkYXRhUGFydCBleHRlbmRzIFBhcnQge1xuICBtZXRhZGF0YToge1xuICAgIHR5cGU/OiBzdHJpbmc7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIHZhbHVlOiBzdHJpbmc7XG4gIH1bXTtcbn1cblxuLyoqXG4gKiBQaW4gbG9va3VwIGRhdGEgdXNlZCBpbnRlcm5hbGx5IGJ5IHRoZSBjb21wb25lbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUGluTG9va3VwRGF0YSB7XG4gIHBpbjogRGF0YVBpbkluZm87XG4gIGl0ZW0/OiBJdGVtO1xuICBtZXRhUGFydD86IE1ldGFkYXRhUGFydDtcbn1cblxuLyoqXG4gKiBBIHBpbi1iYXNlZCB0YXJnZXQuIFRoaXMgaW5jbHVkZXMgcGluJ3MgbmFtZSBhbmQgdmFsdWUsIGFuZFxuICogdGhlIGl0ZW0ncyBJRCBhbmQgb3B0aW9uYWwgcGFydCBJRHMuIFRoZSBsYWJlbCBpcyBhIHVzZXIgZnJpZW5kbHlcbiAqIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgdGFyZ2V0LCB3aGlsZSB0aGUgZ2lkIGlzIGEgZ2xvYmFsbHlcbiAqIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgdGFyZ2V0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFBpblRhcmdldCB7XG4gIGdpZDogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xuICBpdGVtSWQ/OiBzdHJpbmc7XG4gIHBhcnRJZD86IHN0cmluZztcbiAgcGFydFR5cGVJZD86IHN0cmluZztcbiAgcm9sZUlkPzogc3RyaW5nO1xuICBuYW1lPzogc3RyaW5nO1xuICB2YWx1ZT86IHN0cmluZztcbn1cblxuLypcbiAqIFNjb3BlZCBwaW4tYmFzZWQgbG9va3VwIGNvbXBvbmVudC4gVGhpcyBjb21wb25lbnQgcHJvdmlkZXMgYSBsaXN0XG4gKiBvZiBwaW4tYmFzZWQgc2VhcmNoZXMsIHdpdGggYSBsb29rdXAgY29udHJvbC4gV2hlbmV2ZXIgdGhlIHVzZXJcbiAqIHBpY2tzIGEgcGluIHZhbHVlLCBoZSBnZXRzIHRoZSBkZXRhaWxzIGFib3V0IGl0cyBpdGVtIGFuZCBwYXJ0LCBhbmRcbiAqIGl0ZW0ncyBtZXRhZGF0YSBwYXJ0LCBpZiBhbnkuIEhlIGNhbiB0aGVuIHVzZSB0aGVzZSBkYXRhIHRvIGJ1aWxkXG4gKiBzb21lIEVJRCBieSB2YXJpb3VzbHkgYXNzZW1ibGluZyB0aGVzZSBjb21wb25lbnRzLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdjYWRtdXMtcGluLXRhcmdldC1sb29rdXAnLFxuICB0ZW1wbGF0ZVVybDogJy4vcGluLXRhcmdldC1sb29rdXAuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9waW4tdGFyZ2V0LWxvb2t1cC5jb21wb25lbnQuY3NzJ10sXG59KVxuZXhwb3J0IGNsYXNzIFBpblRhcmdldExvb2t1cENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcbiAgcHJpdmF0ZSBfc3ViczogU3Vic2NyaXB0aW9uW107XG4gIHByaXZhdGUgX3RhcmdldDogUGluVGFyZ2V0IHwgdW5kZWZpbmVkO1xuICBwcml2YXRlIF9ub0Zvcm1VcGRhdGU/OiBib29sZWFuO1xuICBwcml2YXRlIF9zdGFydFdpdGhCeVR5cGVNb2RlPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogVHJ1ZSB3aGVuIHRoZSBieS10eXBlIHBpbiBsb29rdXAgbW9kZSBpcyBhY3RpdmUuXG4gICAqIFVzZXIgY2FuIGNoYW5nZSBtb2RlIHVubGVzcyBtb2RlU3dpdGNoaW5nIGlzIGZhbHNlLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGdldCBwaW5CeVR5cGVNb2RlKCk6IGJvb2xlYW4gfCB1bmRlZmluZWQge1xuICAgIHJldHVybiB0aGlzLmJ5VHlwZU1vZGU/LnZhbHVlO1xuICB9XG4gIHB1YmxpYyBzZXQgcGluQnlUeXBlTW9kZSh2YWx1ZTogYm9vbGVhbiB8IHVuZGVmaW5lZCkge1xuICAgIGlmICghdGhpcy5ieVR5cGVNb2RlKSB7XG4gICAgICB0aGlzLl9zdGFydFdpdGhCeVR5cGVNb2RlID0gdmFsdWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYnlUeXBlTW9kZS5zZXRWYWx1ZSh2YWx1ZSB8fCBmYWxzZSk7XG4gICAgICB0aGlzLmJ5VHlwZU1vZGUudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBUcnVlIHdoZW4gdGhlIHVzZXIgY2FuIHN3aXRjaCBiZXR3ZWVuIGJ5LXR5cGUgYW5kIGJ5LWl0ZW0gbW9kZS5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjYW5Td2l0Y2hNb2RlPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRydWUgd2hlbiB0aGUgdXNlciBjYW4gZWRpdCB0aGUgdGFyZ2V0J3MgZ2lkL2xhYmVsIGZvciBpbnRlcm5hbFxuICAgKiB0YXJnZXRzLlxuICAgKi9cbiAgQElucHV0KClcbiAgcHVibGljIGNhbkVkaXRUYXJnZXQ/OiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIGxvb2t1cCBkZWZpbml0aW9ucyB0byBiZSB1c2VkIGZvciB0aGUgYnktdHlwZSBsb29rdXAuIElmXG4gICAqIG5vdCBzcGVjaWZpZWQsIHRoZSBsb29rdXAgZGVmaW5pdGlvbnMgd2lsbCBiZSBnb3QgdmlhIGluamVjdGlvblxuICAgKiB3aGVuIGF2YWlsYWJsZTsgaWYgdGhlIGluamVjdGVkIGRlZmluaXRpb25zIGFyZSBlbXB0eSwgdGhlXG4gICAqIGxvb2t1cCBkZWZpbml0aW9ucyB3aWxsIGJlIGJ1aWx0IGZyb20gdGhlIG1vZGVsLXR5cGVzIHRoZXNhdXJ1cztcbiAgICogaWYgdGhpcyBpcyBub3QgYXZhaWxhYmxlIGVpdGhlciwgdGhlIGJ5LXR5cGUgbG9va3VwIHdpbGwgYmVcbiAgICogZGlzYWJsZWQuXG4gICAqL1xuICBASW5wdXQoKVxuICBwdWJsaWMgbG9va3VwRGVmaW5pdGlvbnM/OiBJbmRleExvb2t1cERlZmluaXRpb25zO1xuXG4gIC8qKlxuICAgKiBUaGUgdGFyZ2V0IHRvIGJlIGVkaXRlZC5cbiAgICovXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBnZXQgdGFyZ2V0KCk6IFBpblRhcmdldCB8IHVuZGVmaW5lZCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl90YXJnZXQ7XG4gIH1cbiAgcHVibGljIHNldCB0YXJnZXQodmFsdWU6IFBpblRhcmdldCB8IHVuZGVmaW5lZCB8IG51bGwpIHtcbiAgICBpZiAodGhpcy5fdGFyZ2V0ID09PSB2YWx1ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl90YXJnZXQgPSB2YWx1ZSB8fCB1bmRlZmluZWQ7XG4gICAgdGhpcy51cGRhdGVGb3JtKHRoaXMuX3RhcmdldCk7XG4gIH1cblxuICAvKipcbiAgICogRW1pdHRlZCB3aGVuIHVzZXIgY2xvc2VzIHRoZSBlZGl0b3IuXG4gICAqL1xuICBAT3V0cHV0KClcbiAgcHVibGljIGVkaXRvckNsb3NlOiBFdmVudEVtaXR0ZXI8YW55PjtcbiAgLyoqXG4gICAqIEVtaXR0ZWQgd2hlbmV2ZXIgdGhlIHRhcmdldCBjaGFuZ2VzLlxuICAgKiBUaGUgZXZlbnQncyB2YWx1ZSBpcyB0aGUgbmV3IHRhcmdldC5cbiAgICovXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgdGFyZ2V0Q2hhbmdlOiBFdmVudEVtaXR0ZXI8UGluVGFyZ2V0PjtcblxuICAvLyBieSB0eXBlXG4gIHB1YmxpYyBtb2RlbEVudHJpZXM6IFRoZXNhdXJ1c0VudHJ5W107XG4gIHB1YmxpYyBwYXJ0VHlwZUtleXM6IHN0cmluZ1tdO1xuICAvLyBieSBpdGVtXG4gIHB1YmxpYyBpdGVtUGFydHM6IFBhcnRbXTtcbiAgLy8gZm9ybSAtIGJ5IGl0ZW1cbiAgcHVibGljIGl0ZW06IEZvcm1Db250cm9sPEl0ZW0gfCBudWxsPjtcbiAgcHVibGljIGl0ZW1QYXJ0OiBGb3JtQ29udHJvbDxQYXJ0IHwgbnVsbD47XG4gIC8vIGZvcm0gLSBieSB0eXBlXG4gIHB1YmxpYyBwYXJ0VHlwZUtleTogRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD47XG4gIC8vIGZvcm0gLSBib3RoXG4gIHB1YmxpYyBnaWQ6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xuICBwdWJsaWMgbGFiZWw6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xuICBwdWJsaWMgYnlUeXBlTW9kZTogRm9ybUNvbnRyb2w8Ym9vbGVhbj47XG4gIHB1YmxpYyBleHRlcm5hbDogRm9ybUNvbnRyb2w8Ym9vbGVhbj47XG4gIHB1YmxpYyBmb3JtOiBGb3JtR3JvdXA7XG5cbiAgcHVibGljIGZpbHRlcjogUGluUmVmTG9va3VwRmlsdGVyO1xuICBwdWJsaWMgcGluRmlsdGVyT3B0aW9ucz86IEluZGV4TG9va3VwRGVmaW5pdGlvbjtcbiAgcHVibGljIGxvb2t1cERhdGE/OiBQaW5Mb29rdXBEYXRhO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBJbmplY3QoJ2luZGV4TG9va3VwRGVmaW5pdGlvbnMnKVxuICAgIHByaXZhdGUgX3ByZXNldExvb2t1cERlZnM6IEluZGV4TG9va3VwRGVmaW5pdGlvbnMsXG4gICAgcHVibGljIGl0ZW1Mb29rdXBTZXJ2aWNlOiBJdGVtUmVmTG9va3VwU2VydmljZSxcbiAgICBwdWJsaWMgcGluTG9va3VwU2VydmljZTogUGluUmVmTG9va3VwU2VydmljZSxcbiAgICBwcml2YXRlIF9pdGVtU2VydmljZTogSXRlbVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBfdGhlc1NlcnZpY2U6IFRoZXNhdXJ1c1NlcnZpY2UsXG4gICAgcHJpdmF0ZSBfc25hY2tiYXI6IE1hdFNuYWNrQmFyLFxuICAgIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlclxuICApIHtcbiAgICB0aGlzLnBhcnRUeXBlS2V5cyA9IFtdO1xuICAgIHRoaXMuaXRlbVBhcnRzID0gW107XG4gICAgdGhpcy5fc3VicyA9IFtdO1xuICAgIHRoaXMubW9kZWxFbnRyaWVzID0gW107XG4gICAgLy8gdGhpcyBpcyB0aGUgZGVmYXVsdCBmaWx0ZXIgZm9yIHRoZSBwaW4gbG9va3VwLCB3aGljaCB3aWxsXG4gICAgLy8gYmUgbWVyZ2VkIHdpdGggdmFsdWVzIHByb3ZpZGVkIGJ5IHVzZXIgaGVyZVxuICAgIHRoaXMuZmlsdGVyID0ge1xuICAgICAgdGV4dDogJycsXG4gICAgICBsaW1pdDogMTAsXG4gICAgfTtcbiAgICAvLyBmb3JtXG4gICAgdGhpcy5pdGVtID0gZm9ybUJ1aWxkZXIuY29udHJvbChudWxsKTtcbiAgICB0aGlzLml0ZW1QYXJ0ID0gZm9ybUJ1aWxkZXIuY29udHJvbChudWxsKTtcbiAgICB0aGlzLnBhcnRUeXBlS2V5ID0gZm9ybUJ1aWxkZXIuY29udHJvbChudWxsKTtcbiAgICB0aGlzLmdpZCA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCwgW1xuICAgICAgVmFsaWRhdG9ycy5yZXF1aXJlZCxcbiAgICAgIFZhbGlkYXRvcnMubWF4TGVuZ3RoKDMwMCksXG4gICAgXSk7XG4gICAgdGhpcy5sYWJlbCA9IGZvcm1CdWlsZGVyLmNvbnRyb2wobnVsbCwgW1xuICAgICAgVmFsaWRhdG9ycy5yZXF1aXJlZCxcbiAgICAgIFZhbGlkYXRvcnMubWF4TGVuZ3RoKDMwMCksXG4gICAgXSk7XG4gICAgdGhpcy5ieVR5cGVNb2RlID0gZm9ybUJ1aWxkZXIuY29udHJvbChmYWxzZSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcbiAgICB0aGlzLmV4dGVybmFsID0gZm9ybUJ1aWxkZXIuY29udHJvbChmYWxzZSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcbiAgICB0aGlzLmZvcm0gPSBmb3JtQnVpbGRlci5ncm91cCh7XG4gICAgICBpdGVtOiB0aGlzLml0ZW0sXG4gICAgICBpdGVtUGFydDogdGhpcy5pdGVtUGFydCxcbiAgICAgIHBhcnRUeXBlS2V5OiB0aGlzLnBhcnRUeXBlS2V5LFxuICAgICAgZ2lkOiB0aGlzLmdpZCxcbiAgICAgIGxhYmVsOiB0aGlzLmxhYmVsLFxuICAgICAgYnlUeXBlTW9kZTogdGhpcy5ieVR5cGVNb2RlLFxuICAgICAgZXh0ZXJuYWw6IHRoaXMuZXh0ZXJuYWwsXG4gICAgfSk7XG4gICAgLy8gZXZlbnRzXG4gICAgdGhpcy50YXJnZXRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPFBpblRhcmdldD4oKTtcbiAgICB0aGlzLmVkaXRvckNsb3NlID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG4gIH1cblxuICBwcml2YXRlIGZvcmNlQnlJdGVtKCk6IHZvaWQge1xuICAgIHRoaXMucGluQnlUeXBlTW9kZSA9IGZhbHNlO1xuICAgIHRoaXMuY2FuU3dpdGNoTW9kZSA9IGZhbHNlO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXR1cEtleXMoKTogdm9pZCB7XG4gICAgLy8gdXNlIERJIHByZXNldHMgaWYgbm8gbG9va3VwIGRlZmluaXRpb25zXG4gICAgaWYgKCF0aGlzLmxvb2t1cERlZmluaXRpb25zKSB7XG4gICAgICB0aGlzLmxvb2t1cERlZmluaXRpb25zID0gdGhpcy5fcHJlc2V0TG9va3VwRGVmcztcbiAgICB9XG4gICAgLy8ga2V5cyBhcmUgYWxsIHRoZSBkZWZpbmVkIGxvb2t1cCBzZWFyY2hlc1xuICAgIHRoaXMucGFydFR5cGVLZXlzID0gT2JqZWN0LmtleXModGhpcy5sb29rdXBEZWZpbml0aW9ucyk7XG5cbiAgICAvLyBpZiBubyBrZXlzLCBnZXQgdGhlbSBmcm9tIHRoZXNhdXJ1cyBtb2RlbC10eXBlcztcbiAgICAvLyBpZiB0aGlzIGlzIG5vdCBhdmFpbGFibGUsIGp1c3QgZm9yY2UgYnkgaXRlbSBtb2RlLlxuICAgIGlmICghdGhpcy5wYXJ0VHlwZUtleXMubGVuZ3RoKSB7XG4gICAgICBpZiAodGhpcy5tb2RlbEVudHJpZXM/Lmxlbmd0aCkge1xuICAgICAgICAvLyBzZXQgbG9va3VwRGVmaW5pdGlvbnMgZnJvbSB0aGVzYXVydXMgZW50cmllc1xuICAgICAgICB0aGlzLmxvb2t1cERlZmluaXRpb25zID0ge307XG4gICAgICAgIHRoaXMubW9kZWxFbnRyaWVzLmZvckVhY2goKGUpID0+IHtcbiAgICAgICAgICB0aGlzLmxvb2t1cERlZmluaXRpb25zIVtlLnZhbHVlXSA9IHtcbiAgICAgICAgICAgIG5hbWU6IGUudmFsdWUsXG4gICAgICAgICAgICB0eXBlSWQ6IGUuaWQsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICAgIC8vIHNldCB0eXBlIGtleXMgZnJvbSB0aGVzYXVydXMgZW50cmllc1xuICAgICAgICB0aGlzLnBhcnRUeXBlS2V5cyA9IHRoaXMubW9kZWxFbnRyaWVzLm1hcCgoZSkgPT4gZS52YWx1ZSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gaWYgc3RpbGwgbm8ga2V5cywgZm9yY2UgYnkgaXRlbSBtb2RlXG4gICAgaWYgKCF0aGlzLnBhcnRUeXBlS2V5cy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZm9yY2VCeUl0ZW0oKTtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgdGhlcmUgaXMgb25seSBvbmUga2V5LCBzZXQgaXQgYXMgdGhlIGRlZmF1bHRcbiAgICAgIGlmICh0aGlzLnBhcnRUeXBlS2V5cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgdGhpcy5wYXJ0VHlwZUtleS5zZXRWYWx1ZSh0aGlzLnBhcnRUeXBlS2V5c1swXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBjYW5CdWlsZEdpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKCF0aGlzLmV4dGVybmFsLnZhbHVlICYmICF0aGlzLmdpZC52YWx1ZSkgfHwgdGhpcy5naWQucHJpc3RpbmU7XG4gIH1cblxuICBwcml2YXRlIGNhbkJ1aWxkTGFiZWwoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICghdGhpcy5leHRlcm5hbC52YWx1ZSAmJiAhdGhpcy5sYWJlbC52YWx1ZSkgfHwgdGhpcy5sYWJlbC5wcmlzdGluZTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICAvLyBzZXQgc3RhcnQgbW9kZSBpZiByZXF1aXJlZFxuICAgIGlmICh0aGlzLl9zdGFydFdpdGhCeVR5cGVNb2RlKSB7XG4gICAgICB0aGlzLmJ5VHlwZU1vZGUuc2V0VmFsdWUodHJ1ZSk7XG4gICAgfVxuXG4gICAgLy8gd2hlbmV2ZXIgaXRlbSBjaGFuZ2VzLCB1cGRhdGUgaXRlbSdzIHBhcnRzIGFuZCBmaWx0ZXJcbiAgICB0aGlzLl9zdWJzLnB1c2goXG4gICAgICB0aGlzLml0ZW0udmFsdWVDaGFuZ2VzXG4gICAgICAgIC5waXBlKGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksIGRlYm91bmNlVGltZSgzMDApKVxuICAgICAgICAuc3Vic2NyaWJlKChpdGVtKSA9PiB7XG4gICAgICAgICAgdGhpcy5pdGVtUGFydC5zZXRWYWx1ZShudWxsKTtcbiAgICAgICAgICB0aGlzLml0ZW1QYXJ0cyA9IGl0ZW0/LnBhcnRzIHx8IFtdO1xuICAgICAgICAgIHRoaXMuZmlsdGVyID0ge1xuICAgICAgICAgICAgLi4udGhpcy5maWx0ZXIsXG4gICAgICAgICAgICBpdGVtSWQ6IGl0ZW0/LmlkLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIHdoZW5ldmVyIGl0ZW1QYXJ0IGNoYW5nZXMsIHVwZGF0ZSB0YXJnZXQgYW5kIGV2ZW50dWFsbHkgZ2lkXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5pdGVtUGFydC52YWx1ZUNoYW5nZXNcbiAgICAgICAgLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSwgZGVib3VuY2VUaW1lKDMwMCkpXG4gICAgICAgIC5zdWJzY3JpYmUoKHBhcnQpID0+IHtcbiAgICAgICAgICBpZiAoIXRoaXMuZ2lkLnZhbHVlIHx8IHRoaXMuZ2lkLnByaXN0aW5lKSB7XG4gICAgICAgICAgICB0aGlzLmdpZC5zZXRWYWx1ZSh0aGlzLmJ1aWxkR2lkKCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLmZpbHRlciA9IHtcbiAgICAgICAgICAgIC4uLnRoaXMuZmlsdGVyLFxuICAgICAgICAgICAgcGFydElkOiBwYXJ0Py5pZCxcbiAgICAgICAgICB9O1xuICAgICAgICAgIHRoaXMudXBkYXRlVGFyZ2V0KCk7XG4gICAgICAgIH0pXG4gICAgKTtcblxuICAgIC8vIHdoZW5ldmVyIHBhcnRUeXBlS2V5IGNoYW5nZXMsIHVwZGF0ZSBmaWx0ZXIncyBvcHRpb25zXG4gICAgdGhpcy5fc3Vicy5wdXNoKFxuICAgICAgdGhpcy5wYXJ0VHlwZUtleS52YWx1ZUNoYW5nZXNcbiAgICAgICAgLnBpcGUoZGlzdGluY3RVbnRpbENoYW5nZWQoKSwgZGVib3VuY2VUaW1lKDMwMCkpXG4gICAgICAgIC5zdWJzY3JpYmUoKGtleSkgPT4ge1xuICAgICAgICAgIHRoaXMucGluRmlsdGVyT3B0aW9ucyA9IGtleVxuICAgICAgICAgICAgPyB0aGlzLmxvb2t1cERlZmluaXRpb25zIVtrZXldXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgLy8gbG9hZCBtb2RlbC10eXBlcyB0aGVzYXVydXMgZW50cmllc1xuICAgIHRoaXMuX3RoZXNTZXJ2aWNlLmdldFRoZXNhdXJ1cygnbW9kZWwtdHlwZXMnLCB0cnVlKS5zdWJzY3JpYmUoe1xuICAgICAgbmV4dDogKHQpID0+IHtcbiAgICAgICAgdGhpcy5tb2RlbEVudHJpZXMgPSB0LmVudHJpZXMgfHwgW107XG4gICAgICAgIGlmICh0aGlzLm1vZGVsRW50cmllcz8ubGVuZ3RoKSB7XG4gICAgICAgICAgdGhpcy5zZXR1cEtleXMoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLmZvcmNlQnlJdGVtKCk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBlcnJvcjogKCkgPT4ge1xuICAgICAgICB0aGlzLmZvcmNlQnlJdGVtKCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5fc3Vicy5sZW5ndGg7IGkrKykge1xuICAgICAgdGhpcy5fc3Vic1tpXS51bnN1YnNjcmliZSgpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRHaWQoKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgLy8gdGhlIEdJRCBpcyB0aGUgcGFydCBJRCBpZiBhbnksIG9yIHRoZSBpdGVtIElELCBmb2xsb3dlZCBieVxuICAgIC8vIHRoZSBwaW4ncyB2YWx1ZSAoPUVJRClcbiAgICBjb25zdCBwaW4gPSB0aGlzLmxvb2t1cERhdGE/LnBpbjtcbiAgICBpZiAoIXBpbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBwaW4ucGFydElkXG4gICAgICA/IGBQJHtwaW4ucGFydElkfS8ke3Bpbi52YWx1ZX1gXG4gICAgICA6IGBJJHtwaW4uaXRlbUlkfS8ke3Bpbi52YWx1ZX1gO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZExhYmVsKCk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICghdGhpcy5sb29rdXBEYXRhPy5waW4pIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBzYjogc3RyaW5nW10gPSBbXTtcbiAgICAvLyBwaW4gdmFsdWVcbiAgICBzYi5wdXNoKHRoaXMubG9va3VwRGF0YS5waW4udmFsdWUhKTtcbiAgICAvLyBpdGVtIHRpdGxlXG4gICAgc2IucHVzaCgnIHwgJyk7XG4gICAgc2IucHVzaCh0aGlzLmxvb2t1cERhdGEuaXRlbSEudGl0bGUgfHwgdGhpcy5sb29rdXBEYXRhLml0ZW0hLmlkKTtcbiAgICAvLyBwYXJ0IHR5cGUgYW5kIHJvbGVcbiAgICBjb25zdCBlID0gdGhpcy5tb2RlbEVudHJpZXM/LmZpbmQoXG4gICAgICAoZSkgPT4gZS5pZCA9PT0gdGhpcy5sb29rdXBEYXRhIS5waW4ucGFydFR5cGVJZFxuICAgICk7XG4gICAgc2IucHVzaCgnICgnKTtcbiAgICBzYi5wdXNoKGU/LnZhbHVlIHx8IHRoaXMubG9va3VwRGF0YS5waW4ucGFydFR5cGVJZCk7XG4gICAgaWYgKHRoaXMubG9va3VwRGF0YS5waW4ucm9sZUlkKSB7XG4gICAgICBzYi5wdXNoKGAsICR7dGhpcy5sb29rdXBEYXRhLnBpbi5yb2xlSWR9YCk7XG4gICAgfVxuICAgIHNiLnB1c2goJyknKTtcbiAgICByZXR1cm4gc2Iuam9pbignJyk7XG4gIH1cblxuICBwcml2YXRlIGdldFRhcmdldCgpOiBQaW5UYXJnZXQge1xuICAgIGlmICh0aGlzLmV4dGVybmFsLnZhbHVlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBnaWQ6IHRoaXMuZ2lkLnZhbHVlIHx8ICcnLFxuICAgICAgICBsYWJlbDogdGhpcy5sYWJlbC52YWx1ZSB8fCAnJyxcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHBpbiA9IHRoaXMubG9va3VwRGF0YT8ucGluO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgZ2lkOiB0aGlzLmdpZC52YWx1ZSB8fCAnJyxcbiAgICAgICAgbGFiZWw6IHRoaXMubGFiZWwudmFsdWUgfHwgJycsXG4gICAgICAgIGl0ZW1JZDogcGluPy5pdGVtSWQgfHwgJycsXG4gICAgICAgIHBhcnRJZDogcGluPy5wYXJ0SWQgfHwgJycsXG4gICAgICAgIHBhcnRUeXBlSWQ6IHBpbj8ucGFydFR5cGVJZCB8fCAnJyxcbiAgICAgICAgcm9sZUlkOiBwaW4/LnJvbGVJZCB8fCAnJyxcbiAgICAgICAgbmFtZTogcGluPy5uYW1lIHx8ICcnLFxuICAgICAgICB2YWx1ZTogcGluPy52YWx1ZSB8fCAnJyxcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVUYXJnZXQoKTogdm9pZCB7XG4gICAgdGhpcy5fbm9Gb3JtVXBkYXRlID0gdHJ1ZTtcblxuICAgIGlmICh0aGlzLmNhbkJ1aWxkR2lkKCkpIHtcbiAgICAgIHRoaXMuZ2lkLnNldFZhbHVlKHRoaXMuYnVpbGRHaWQoKSk7XG4gICAgICB0aGlzLmdpZC5tYXJrQXNEaXJ0eSgpO1xuICAgIH1cbiAgICBpZiAodGhpcy5jYW5CdWlsZExhYmVsKCkpIHtcbiAgICAgIHRoaXMubGFiZWwuc2V0VmFsdWUodGhpcy5idWlsZExhYmVsKCkpO1xuICAgICAgdGhpcy5sYWJlbC5tYXJrQXNEaXJ0eSgpO1xuICAgIH1cbiAgICB0aGlzLnRhcmdldCA9IHRoaXMuZ2V0VGFyZ2V0KCk7XG5cbiAgICB0aGlzLl9ub0Zvcm1VcGRhdGUgPSBmYWxzZTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRm9ybSh0YXJnZXQ/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