kwikid-forms 0.1.19 → 0.1.21

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.
Files changed (32) hide show
  1. package/bundles/kwikid-forms.umd.js +3672 -2968
  2. package/bundles/kwikid-forms.umd.js.map +1 -1
  3. package/esm2015/lib/builder/builder.component.js +236 -104
  4. package/esm2015/lib/builder/builder.module.js +42 -5
  5. package/esm2015/lib/builder/element-config-editor/editors/basic/radio-config.editor.component.js +302 -0
  6. package/esm2015/lib/builder/element-config-editor/editors/basic/text-config.editor.component.js +135 -0
  7. package/esm2015/lib/builder/element-config-editor/editors/basic-element-config.editor.component.js +542 -0
  8. package/esm2015/lib/builder/element-config-editor/element-config-editor.component.js +89 -0
  9. package/esm2015/lib/builder/shared/elements.js +44 -0
  10. package/esm2015/lib/builder/shared/helpers.js +6 -0
  11. package/esm2015/lib/renderer/config-converter.helper.js +661 -0
  12. package/esm2015/lib/renderer/form-view/definitions/form-view.apis.definition.js +1 -1
  13. package/esm2015/lib/renderer/form-view/form-view.component.js +73 -91
  14. package/esm2015/lib/renderer/form-view/helpers/form-view.apis.helper.js +22 -12
  15. package/esm2015/lib/renderer/form-view/helpers/form-view.fields.helper.js +4 -1
  16. package/esm2015/lib/renderer/renderer.component.js +74 -24
  17. package/fesm2015/kwikid-forms.js +3379 -2071
  18. package/fesm2015/kwikid-forms.js.map +1 -1
  19. package/lib/builder/builder.component.d.ts +21 -53
  20. package/lib/builder/builder.module.d.ts +9 -4
  21. package/lib/builder/element-config-editor/editors/basic/radio-config.editor.component.d.ts +25 -0
  22. package/lib/builder/element-config-editor/editors/basic/text-config.editor.component.d.ts +16 -0
  23. package/lib/builder/element-config-editor/editors/basic-element-config.editor.component.d.ts +20 -0
  24. package/lib/builder/element-config-editor/element-config-editor.component.d.ts +20 -0
  25. package/lib/builder/shared/elements.d.ts +32 -0
  26. package/lib/builder/shared/helpers.d.ts +1 -0
  27. package/lib/renderer/{renderer.config-converter.helper.d.ts → config-converter.helper.d.ts} +2 -0
  28. package/lib/renderer/form-view/definitions/form-view.apis.definition.d.ts +2 -1
  29. package/lib/renderer/form-view/form-view.component.d.ts +8 -5
  30. package/lib/renderer/renderer.component.d.ts +2 -2
  31. package/package.json +3 -3
  32. package/esm2015/lib/renderer/renderer.config-converter.helper.js +0 -641
@@ -0,0 +1,542 @@
1
+ import { __decorate } from "tslib";
2
+ import { Component, EventEmitter, Input, Output } from "@angular/core";
3
+ import { FormControl, FormGroup } from "@angular/forms";
4
+ import { logMethod } from "kwikid-toolkit";
5
+ import _ from "lodash";
6
+ import * as i0 from "@angular/core";
7
+ import * as i1 from "./basic/text-config.editor.component";
8
+ import * as i2 from "./basic/radio-config.editor.component";
9
+ import * as i3 from "@angular/common";
10
+ import * as i4 from "@angular/forms";
11
+ export class BasicElementConfigEditor {
12
+ constructor() {
13
+ this.saveClickCounter = 0;
14
+ this.elementConfig = {
15
+ label: "",
16
+ key: "",
17
+ disabled: false,
18
+ default: {
19
+ value: true
20
+ },
21
+ validators: {
22
+ min: null,
23
+ max: null,
24
+ minLength: null,
25
+ maxLength: null,
26
+ required: true
27
+ },
28
+ properties: {
29
+ placeholder: "",
30
+ readOnly: false
31
+ }
32
+ };
33
+ this.updateElement = new EventEmitter();
34
+ this.elementType = "";
35
+ this.saveBasicClickCounter = 0;
36
+ this.basicFormGroup = undefined;
37
+ }
38
+ ngOnInit() {
39
+ this.assignVariables();
40
+ this.createBasicFormGroup();
41
+ }
42
+ ngOnChanges(changes) {
43
+ const verifyChange = (key) => {
44
+ return changes.hasOwnProperty(key) && !changes[key].firstChange;
45
+ };
46
+ if (verifyChange("elementConfig")) {
47
+ this.elementConfig = changes.elementConfig.currentValue;
48
+ this.assignVariables();
49
+ this.createBasicFormGroup();
50
+ }
51
+ if (verifyChange("saveClickCounter")) {
52
+ if (changes.saveClickCounter.previousValue !==
53
+ changes.saveClickCounter.currentValue) {
54
+ this.saveClickCounter = changes.saveClickCounter.currentValue;
55
+ this.handleOnSave();
56
+ }
57
+ }
58
+ }
59
+ assignVariables() {
60
+ this.elementType = this.elementConfig.elementType;
61
+ }
62
+ createBasicFormGroup() {
63
+ this.basicFormGroup = new FormGroup({
64
+ label: new FormControl(this.elementConfig.label),
65
+ key: new FormControl(this.elementConfig.key),
66
+ disabled: new FormControl(this.elementConfig.disabled),
67
+ default: new FormGroup({
68
+ value: new FormControl(this.elementConfig.default.value, {
69
+ updateOn: "change"
70
+ })
71
+ }),
72
+ validators: new FormGroup({
73
+ min: new FormControl(this.elementConfig.validators.min, {
74
+ updateOn: "change"
75
+ }),
76
+ minLength: new FormControl(this.elementConfig.validators.minLength, {
77
+ updateOn: "change"
78
+ }),
79
+ max: new FormControl(this.elementConfig.validators.max, {
80
+ updateOn: "change"
81
+ }),
82
+ maxLength: new FormControl(this.elementConfig.validators.maxLength, {
83
+ updateOn: "change"
84
+ }),
85
+ required: new FormControl(this.elementConfig.validators.required, {
86
+ updateOn: "change"
87
+ })
88
+ }),
89
+ properties: new FormGroup({
90
+ placeholder: new FormControl(this.elementConfig.properties.placeholder, {
91
+ updateOn: "change"
92
+ }),
93
+ readOnly: new FormControl(this.elementConfig.properties.readOnly, {
94
+ updateOn: "change"
95
+ })
96
+ })
97
+ });
98
+ this.basicFormGroup.updateValueAndValidity();
99
+ }
100
+ handleOnSaveUpdateElement(event) {
101
+ // Get Common Config
102
+ let basicElementCommonConfig = this.basicFormGroup.getRawValue();
103
+ basicElementCommonConfig.key = basicElementCommonConfig.key.replace(/\s/g, "_");
104
+ // Get Basic Element Config
105
+ const basicElementConfig = event.basicElementConfig;
106
+ this.elementConfig = _.merge(this.elementConfig, basicElementCommonConfig, basicElementConfig);
107
+ this.updateElement.emit({ elementConfig: this.elementConfig });
108
+ }
109
+ handleOnSave() {
110
+ this.saveBasicClickCounter++;
111
+ }
112
+ }
113
+ /** @nocollapse */ BasicElementConfigEditor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: BasicElementConfigEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
114
+ /** @nocollapse */ BasicElementConfigEditor.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.17", type: BasicElementConfigEditor, selector: "basic-element-config-editor", inputs: { saveClickCounter: "saveClickCounter", elementConfig: "elementConfig" }, outputs: { updateElement: "updateElement" }, usesOnChanges: true, ngImport: i0, template: `
115
+ <ng-container *ngIf="elementConfig !== undefined">
116
+ <table>
117
+ <tr>
118
+ <td>Id</td>
119
+ <td>{{ elementConfig.elementId }}</td>
120
+ </tr>
121
+ <tr>
122
+ <td>Type</td>
123
+ <td>{{ elementConfig.elementType }}</td>
124
+ </tr>
125
+ <tr>
126
+ <td>Category</td>
127
+ <td>{{ elementConfig.elementCategory }}</td>
128
+ </tr>
129
+ </table>
130
+ </ng-container>
131
+ <form [formGroup]="basicFormGroup">
132
+ <fieldset>
133
+ <legend>Standard</legend>
134
+ <div class="form-group">
135
+ <label for="basic-field-label">Label</label>
136
+ <input
137
+ type="text"
138
+ class="form-control"
139
+ id="basic-field-label"
140
+ formControlName="label"
141
+ required
142
+ />
143
+ </div>
144
+ <div class="form-group">
145
+ <label for="basic-field-key">Key</label>
146
+ <input
147
+ type="text"
148
+ class="form-control"
149
+ id="basic-field-key"
150
+ formControlName="key"
151
+ required
152
+ />
153
+ </div>
154
+ <div class="form-group">
155
+ <label for="basic-input-property-disabled">disabled</label>
156
+ <select
157
+ class="form-control"
158
+ formControlName="disabled"
159
+ id="basic-input-property-disabled"
160
+ >
161
+ <option
162
+ [ngValue]="null"
163
+ disabled
164
+ >Select either true or false</option
165
+ >
166
+ <option
167
+ *ngFor="let disabled of [true, false]"
168
+ [ngValue]="disabled"
169
+ >
170
+ {{ disabled }}
171
+ </option>
172
+ </select>
173
+ </div>
174
+ </fieldset>
175
+ <fieldset formGroupName="default">
176
+ <legend>Default</legend>
177
+ <div class="form-group">
178
+ <label for="basic-input-property-value">value</label>
179
+ <select
180
+ class="form-control"
181
+ formControlName="value"
182
+ id="basic-input-property-value"
183
+ >
184
+ <option
185
+ [ngValue]="null"
186
+ value
187
+ >Select either true or false</option
188
+ >
189
+ <option
190
+ *ngFor="let value of [true, false]"
191
+ [ngValue]="value"
192
+ >
193
+ {{ value }}
194
+ </option>
195
+ </select>
196
+ </div>
197
+ </fieldset>
198
+ <fieldset formGroupName="validators">
199
+ <legend>Validators</legend>
200
+ <div class="form-group">
201
+ <label for="basic-input-validators-min">min</label>
202
+ <input
203
+ class="form-control"
204
+ formControlName="min"
205
+ id="basic-input-validators-min"
206
+ type="number"
207
+ />
208
+ </div>
209
+ <div class="form-group">
210
+ <label for="basic-input-validators-max">max</label>
211
+ <input
212
+ class="form-control"
213
+ formControlName="max"
214
+ id="basic-input-validators-max"
215
+ type="number"
216
+ />
217
+ </div>
218
+ <div class="form-group">
219
+ <label for="basic-input-validators-minLength">minLength</label>
220
+ <input
221
+ class="form-control"
222
+ formControlName="minLength"
223
+ id="basic-input-validators-minLength"
224
+ type="number"
225
+ />
226
+ </div>
227
+ <div class="form-group">
228
+ <label for="basic-input-validators-maxLength">maxLength</label>
229
+ <input
230
+ class="form-control"
231
+ formControlName="maxLength"
232
+ id="basic-input-validators-maxLength"
233
+ type="number"
234
+ />
235
+ </div>
236
+ <div class="form-group">
237
+ <label for="basic-input-property-required">required</label>
238
+ <select
239
+ class="form-control"
240
+ formControlName="required"
241
+ id="basic-input-property-required"
242
+ >
243
+ <option
244
+ [ngValue]="null"
245
+ disabled
246
+ >Select either true or false</option
247
+ >
248
+ <option
249
+ *ngFor="let required of [true, false]"
250
+ [ngValue]="required"
251
+ >
252
+ {{ required }}
253
+ </option>
254
+ </select>
255
+ </div>
256
+ </fieldset>
257
+ <fieldset formGroupName="properties">
258
+ <legend>Properties</legend>
259
+ <div class="form-group">
260
+ <label for="basic-input-property-placeholder">Placeholder</label>
261
+ <input
262
+ class="form-control"
263
+ formControlName="placeholder"
264
+ id="basic-input-property-placeholder"
265
+ type="text"
266
+ />
267
+ </div>
268
+ <div class="form-group">
269
+ <label for="basic-input-property-readonly">readOnly</label>
270
+ <select
271
+ class="form-control"
272
+ formControlName="readOnly"
273
+ id="basic-input-property-readonly"
274
+ >
275
+ <option
276
+ [ngValue]="null"
277
+ disabled
278
+ >Select either true or false</option
279
+ >
280
+ <option
281
+ *ngFor="let readonly of [true, false]"
282
+ [ngValue]="readonly"
283
+ >
284
+ {{ readonly }}
285
+ </option>
286
+ </select>
287
+ </div>
288
+ </fieldset>
289
+ <ng-container [ngSwitch]="elementType">
290
+ <ng-container *ngSwitchCase="'text'">
291
+ <basic-text-config-editor
292
+ [saveBasicClickCounter]="saveBasicClickCounter"
293
+ [elementConfig]="elementConfig"
294
+ (updateElement)="handleOnSaveUpdateElement($event)"
295
+ ></basic-text-config-editor>
296
+ </ng-container>
297
+ <ng-container *ngSwitchCase="'radio'">
298
+ <basic-radio-config-editor
299
+ [saveBasicClickCounter]="saveBasicClickCounter"
300
+ [elementConfig]="elementConfig"
301
+ (updateElement)="handleOnSaveUpdateElement($event)"
302
+ ></basic-radio-config-editor>
303
+ </ng-container>
304
+ </ng-container>
305
+ </form>
306
+ `, isInline: true, styles: ["\n :host {\n display: flex;\n flex-direction: column;\n align-content: center;\n justify-content: flex-start;\n align-items: stretch;\n gap: 1rem;\n }\n "], components: [{ type: i1.BasicTextConfigEditor, selector: "basic-text-config-editor", inputs: ["saveBasicClickCounter", "elementConfig"], outputs: ["updateElement"] }, { type: i2.BasicRadioConfigEditor, selector: "basic-radio-config-editor", inputs: ["saveBasicClickCounter", "elementConfig"], outputs: ["updateElement"] }], directives: [{ type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i4.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { type: i4.FormControlName, selector: "[formControlName]", inputs: ["disabled", "formControlName", "ngModel"], outputs: ["ngModelChange"] }, { type: i4.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { type: i4.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { type: i4.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i4.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { type: i4.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { type: i4.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { type: i3.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { type: i3.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }] });
307
+ __decorate([
308
+ logMethod
309
+ ], BasicElementConfigEditor.prototype, "ngOnInit", null);
310
+ __decorate([
311
+ logMethod
312
+ ], BasicElementConfigEditor.prototype, "ngOnChanges", null);
313
+ __decorate([
314
+ logMethod
315
+ ], BasicElementConfigEditor.prototype, "assignVariables", null);
316
+ __decorate([
317
+ logMethod
318
+ ], BasicElementConfigEditor.prototype, "createBasicFormGroup", null);
319
+ __decorate([
320
+ logMethod
321
+ ], BasicElementConfigEditor.prototype, "handleOnSaveUpdateElement", null);
322
+ __decorate([
323
+ logMethod
324
+ ], BasicElementConfigEditor.prototype, "handleOnSave", null);
325
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.17", ngImport: i0, type: BasicElementConfigEditor, decorators: [{
326
+ type: Component,
327
+ args: [{
328
+ selector: "basic-element-config-editor",
329
+ template: `
330
+ <ng-container *ngIf="elementConfig !== undefined">
331
+ <table>
332
+ <tr>
333
+ <td>Id</td>
334
+ <td>{{ elementConfig.elementId }}</td>
335
+ </tr>
336
+ <tr>
337
+ <td>Type</td>
338
+ <td>{{ elementConfig.elementType }}</td>
339
+ </tr>
340
+ <tr>
341
+ <td>Category</td>
342
+ <td>{{ elementConfig.elementCategory }}</td>
343
+ </tr>
344
+ </table>
345
+ </ng-container>
346
+ <form [formGroup]="basicFormGroup">
347
+ <fieldset>
348
+ <legend>Standard</legend>
349
+ <div class="form-group">
350
+ <label for="basic-field-label">Label</label>
351
+ <input
352
+ type="text"
353
+ class="form-control"
354
+ id="basic-field-label"
355
+ formControlName="label"
356
+ required
357
+ />
358
+ </div>
359
+ <div class="form-group">
360
+ <label for="basic-field-key">Key</label>
361
+ <input
362
+ type="text"
363
+ class="form-control"
364
+ id="basic-field-key"
365
+ formControlName="key"
366
+ required
367
+ />
368
+ </div>
369
+ <div class="form-group">
370
+ <label for="basic-input-property-disabled">disabled</label>
371
+ <select
372
+ class="form-control"
373
+ formControlName="disabled"
374
+ id="basic-input-property-disabled"
375
+ >
376
+ <option
377
+ [ngValue]="null"
378
+ disabled
379
+ >Select either true or false</option
380
+ >
381
+ <option
382
+ *ngFor="let disabled of [true, false]"
383
+ [ngValue]="disabled"
384
+ >
385
+ {{ disabled }}
386
+ </option>
387
+ </select>
388
+ </div>
389
+ </fieldset>
390
+ <fieldset formGroupName="default">
391
+ <legend>Default</legend>
392
+ <div class="form-group">
393
+ <label for="basic-input-property-value">value</label>
394
+ <select
395
+ class="form-control"
396
+ formControlName="value"
397
+ id="basic-input-property-value"
398
+ >
399
+ <option
400
+ [ngValue]="null"
401
+ value
402
+ >Select either true or false</option
403
+ >
404
+ <option
405
+ *ngFor="let value of [true, false]"
406
+ [ngValue]="value"
407
+ >
408
+ {{ value }}
409
+ </option>
410
+ </select>
411
+ </div>
412
+ </fieldset>
413
+ <fieldset formGroupName="validators">
414
+ <legend>Validators</legend>
415
+ <div class="form-group">
416
+ <label for="basic-input-validators-min">min</label>
417
+ <input
418
+ class="form-control"
419
+ formControlName="min"
420
+ id="basic-input-validators-min"
421
+ type="number"
422
+ />
423
+ </div>
424
+ <div class="form-group">
425
+ <label for="basic-input-validators-max">max</label>
426
+ <input
427
+ class="form-control"
428
+ formControlName="max"
429
+ id="basic-input-validators-max"
430
+ type="number"
431
+ />
432
+ </div>
433
+ <div class="form-group">
434
+ <label for="basic-input-validators-minLength">minLength</label>
435
+ <input
436
+ class="form-control"
437
+ formControlName="minLength"
438
+ id="basic-input-validators-minLength"
439
+ type="number"
440
+ />
441
+ </div>
442
+ <div class="form-group">
443
+ <label for="basic-input-validators-maxLength">maxLength</label>
444
+ <input
445
+ class="form-control"
446
+ formControlName="maxLength"
447
+ id="basic-input-validators-maxLength"
448
+ type="number"
449
+ />
450
+ </div>
451
+ <div class="form-group">
452
+ <label for="basic-input-property-required">required</label>
453
+ <select
454
+ class="form-control"
455
+ formControlName="required"
456
+ id="basic-input-property-required"
457
+ >
458
+ <option
459
+ [ngValue]="null"
460
+ disabled
461
+ >Select either true or false</option
462
+ >
463
+ <option
464
+ *ngFor="let required of [true, false]"
465
+ [ngValue]="required"
466
+ >
467
+ {{ required }}
468
+ </option>
469
+ </select>
470
+ </div>
471
+ </fieldset>
472
+ <fieldset formGroupName="properties">
473
+ <legend>Properties</legend>
474
+ <div class="form-group">
475
+ <label for="basic-input-property-placeholder">Placeholder</label>
476
+ <input
477
+ class="form-control"
478
+ formControlName="placeholder"
479
+ id="basic-input-property-placeholder"
480
+ type="text"
481
+ />
482
+ </div>
483
+ <div class="form-group">
484
+ <label for="basic-input-property-readonly">readOnly</label>
485
+ <select
486
+ class="form-control"
487
+ formControlName="readOnly"
488
+ id="basic-input-property-readonly"
489
+ >
490
+ <option
491
+ [ngValue]="null"
492
+ disabled
493
+ >Select either true or false</option
494
+ >
495
+ <option
496
+ *ngFor="let readonly of [true, false]"
497
+ [ngValue]="readonly"
498
+ >
499
+ {{ readonly }}
500
+ </option>
501
+ </select>
502
+ </div>
503
+ </fieldset>
504
+ <ng-container [ngSwitch]="elementType">
505
+ <ng-container *ngSwitchCase="'text'">
506
+ <basic-text-config-editor
507
+ [saveBasicClickCounter]="saveBasicClickCounter"
508
+ [elementConfig]="elementConfig"
509
+ (updateElement)="handleOnSaveUpdateElement($event)"
510
+ ></basic-text-config-editor>
511
+ </ng-container>
512
+ <ng-container *ngSwitchCase="'radio'">
513
+ <basic-radio-config-editor
514
+ [saveBasicClickCounter]="saveBasicClickCounter"
515
+ [elementConfig]="elementConfig"
516
+ (updateElement)="handleOnSaveUpdateElement($event)"
517
+ ></basic-radio-config-editor>
518
+ </ng-container>
519
+ </ng-container>
520
+ </form>
521
+ `,
522
+ styles: [
523
+ `
524
+ :host {
525
+ display: flex;
526
+ flex-direction: column;
527
+ align-content: center;
528
+ justify-content: flex-start;
529
+ align-items: stretch;
530
+ gap: 1rem;
531
+ }
532
+ `
533
+ ]
534
+ }]
535
+ }], ctorParameters: function () { return []; }, propDecorators: { saveClickCounter: [{
536
+ type: Input
537
+ }], elementConfig: [{
538
+ type: Input
539
+ }], updateElement: [{
540
+ type: Output
541
+ }], ngOnInit: [], ngOnChanges: [], assignVariables: [], createBasicFormGroup: [], handleOnSaveUpdateElement: [], handleOnSave: [] } });
542
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFzaWMtZWxlbWVudC1jb25maWcuZWRpdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2t3aWtpZC1mb3Jtcy9zcmMvbGliL2J1aWxkZXIvZWxlbWVudC1jb25maWctZWRpdG9yL2VkaXRvcnMvYmFzaWMtZWxlbWVudC1jb25maWcuZWRpdG9yLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMzQyxPQUFPLENBQUMsTUFBTSxRQUFRLENBQUM7Ozs7OztBQWtOdkIsTUFBTSxPQUFPLHdCQUF3QjtJQWlDbkM7UUEvQkEscUJBQWdCLEdBQVcsQ0FBQyxDQUFDO1FBRzdCLGtCQUFhLEdBQVE7WUFDbkIsS0FBSyxFQUFFLEVBQUU7WUFDVCxHQUFHLEVBQUUsRUFBRTtZQUNQLFFBQVEsRUFBRSxLQUFLO1lBQ2YsT0FBTyxFQUFFO2dCQUNQLEtBQUssRUFBRSxJQUFJO2FBQ1o7WUFDRCxVQUFVLEVBQUU7Z0JBQ1YsR0FBRyxFQUFFLElBQUk7Z0JBQ1QsR0FBRyxFQUFFLElBQUk7Z0JBQ1QsU0FBUyxFQUFFLElBQUk7Z0JBQ2YsU0FBUyxFQUFFLElBQUk7Z0JBQ2YsUUFBUSxFQUFFLElBQUk7YUFDZjtZQUNELFVBQVUsRUFBRTtnQkFDVixXQUFXLEVBQUUsRUFBRTtnQkFDZixRQUFRLEVBQUUsS0FBSzthQUNoQjtTQUNGLENBQUM7UUFHRixrQkFBYSxHQUFHLElBQUksWUFBWSxFQUFPLENBQUM7UUFFeEMsZ0JBQVcsR0FBVyxFQUFFLENBQUM7UUFDekIsMEJBQXFC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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWdNVDtBQWtERDtJQURDLFNBQVM7d0RBSVQ7QUFHRDtJQURDLFNBQVM7MkRBc0JUO0FBR0Q7SUFEQyxTQUFTOytEQUdUO0FBR0Q7SUFEQyxTQUFTO29FQXlDVDtBQUdEO0lBREMsU0FBUzt5RUFtQlQ7QUFHRDtJQURDLFNBQVM7NERBR1Q7NEZBeklVLHdCQUF3QjtrQkFoTnBDLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLDZCQUE2QjtvQkFDdkMsUUFBUSxFQUFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnTVQ7b0JBQ0QsTUFBTSxFQUFFO3dCQUNOOzs7Ozs7Ozs7S0FTQztxQkFDRjtpQkFDRjswRUFHQyxnQkFBZ0I7c0JBRGYsS0FBSztnQkFJTixhQUFhO3NCQURaLEtBQUs7Z0JBc0JOLGFBQWE7c0JBRFosTUFBTTtnQkFXUCxRQUFRLE1BTVIsV0FBVyxNQXdCWCxlQUFlLE1BS2Ysb0JBQW9CLE1BMkNwQix5QkFBeUIsTUFxQnpCLFlBQVkiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEV2ZW50RW1pdHRlcixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBTaW1wbGVDaGFuZ2VzXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUdyb3VwIH0gZnJvbSBcIkBhbmd1bGFyL2Zvcm1zXCI7XG5pbXBvcnQgeyBsb2dNZXRob2QgfSBmcm9tIFwia3dpa2lkLXRvb2xraXRcIjtcbmltcG9ydCBfIGZyb20gXCJsb2Rhc2hcIjtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiBcImJhc2ljLWVsZW1lbnQtY29uZmlnLWVkaXRvclwiLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJlbGVtZW50Q29uZmlnICE9PSB1bmRlZmluZWRcIj5cbiAgICAgIDx0YWJsZT5cbiAgICAgICAgPHRyPlxuICAgICAgICAgIDx0ZD5JZDwvdGQ+XG4gICAgICAgICAgPHRkPnt7IGVsZW1lbnRDb25maWcuZWxlbWVudElkIH19PC90ZD5cbiAgICAgICAgPC90cj5cbiAgICAgICAgPHRyPlxuICAgICAgICAgIDx0ZD5UeXBlPC90ZD5cbiAgICAgICAgICA8dGQ+e3sgZWxlbWVudENvbmZpZy5lbGVtZW50VHlwZSB9fTwvdGQ+XG4gICAgICAgIDwvdHI+XG4gICAgICAgIDx0cj5cbiAgICAgICAgICA8dGQ+Q2F0ZWdvcnk8L3RkPlxuICAgICAgICAgIDx0ZD57eyBlbGVtZW50Q29uZmlnLmVsZW1lbnRDYXRlZ29yeSB9fTwvdGQ+XG4gICAgICAgIDwvdHI+XG4gICAgICA8L3RhYmxlPlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiYmFzaWNGb3JtR3JvdXBcIj5cbiAgICAgIDxmaWVsZHNldD5cbiAgICAgICAgPGxlZ2VuZD5TdGFuZGFyZDwvbGVnZW5kPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBmb3I9XCJiYXNpYy1maWVsZC1sYWJlbFwiPkxhYmVsPC9sYWJlbD5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgIGlkPVwiYmFzaWMtZmllbGQtbGFiZWxcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibGFiZWxcIlxuICAgICAgICAgICAgcmVxdWlyZWRcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwiYmFzaWMtZmllbGQta2V5XCI+S2V5PC9sYWJlbD5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgIGlkPVwiYmFzaWMtZmllbGQta2V5XCJcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImtleVwiXG4gICAgICAgICAgICByZXF1aXJlZFxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBmb3I9XCJiYXNpYy1pbnB1dC1wcm9wZXJ0eS1kaXNhYmxlZFwiPmRpc2FibGVkPC9sYWJlbD5cbiAgICAgICAgICA8c2VsZWN0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBpZD1cImJhc2ljLWlucHV0LXByb3BlcnR5LWRpc2FibGVkXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8b3B0aW9uXG4gICAgICAgICAgICAgIFtuZ1ZhbHVlXT1cIm51bGxcIlxuICAgICAgICAgICAgICBkaXNhYmxlZFxuICAgICAgICAgICAgICA+U2VsZWN0IGVpdGhlciB0cnVlIG9yIGZhbHNlPC9vcHRpb25cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgIDxvcHRpb25cbiAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IGRpc2FibGVkIG9mIFt0cnVlLCBmYWxzZV1cIlxuICAgICAgICAgICAgICBbbmdWYWx1ZV09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IGRpc2FibGVkIH19XG4gICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2ZpZWxkc2V0PlxuICAgICAgPGZpZWxkc2V0IGZvcm1Hcm91cE5hbWU9XCJkZWZhdWx0XCI+XG4gICAgICAgIDxsZWdlbmQ+RGVmYXVsdDwvbGVnZW5kPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBmb3I9XCJiYXNpYy1pbnB1dC1wcm9wZXJ0eS12YWx1ZVwiPnZhbHVlPC9sYWJlbD5cbiAgICAgICAgICA8c2VsZWN0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ2YWx1ZVwiXG4gICAgICAgICAgICBpZD1cImJhc2ljLWlucHV0LXByb3BlcnR5LXZhbHVlXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICA8b3B0aW9uXG4gICAgICAgICAgICAgIFtuZ1ZhbHVlXT1cIm51bGxcIlxuICAgICAgICAgICAgICB2YWx1ZVxuICAgICAgICAgICAgICA+U2VsZWN0IGVpdGhlciB0cnVlIG9yIGZhbHNlPC9vcHRpb25cbiAgICAgICAgICAgID5cbiAgICAgICAgICAgIDxvcHRpb25cbiAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IHZhbHVlIG9mIFt0cnVlLCBmYWxzZV1cIlxuICAgICAgICAgICAgICBbbmdWYWx1ZV09XCJ2YWx1ZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIHt7IHZhbHVlIH19XG4gICAgICAgICAgICA8L29wdGlvbj5cbiAgICAgICAgICA8L3NlbGVjdD5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2ZpZWxkc2V0PlxuICAgICAgPGZpZWxkc2V0IGZvcm1Hcm91cE5hbWU9XCJ2YWxpZGF0b3JzXCI+XG4gICAgICAgIDxsZWdlbmQ+VmFsaWRhdG9yczwvbGVnZW5kPlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBmb3I9XCJiYXNpYy1pbnB1dC12YWxpZGF0b3JzLW1pblwiPm1pbjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJtaW5cIlxuICAgICAgICAgICAgaWQ9XCJiYXNpYy1pbnB1dC12YWxpZGF0b3JzLW1pblwiXG4gICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwiYmFzaWMtaW5wdXQtdmFsaWRhdG9ycy1tYXhcIj5tYXg8L2xhYmVsPlxuICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibWF4XCJcbiAgICAgICAgICAgIGlkPVwiYmFzaWMtaW5wdXQtdmFsaWRhdG9ycy1tYXhcIlxuICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXG4gICAgICAgICAgLz5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLWdyb3VwXCI+XG4gICAgICAgICAgPGxhYmVsIGZvcj1cImJhc2ljLWlucHV0LXZhbGlkYXRvcnMtbWluTGVuZ3RoXCI+bWluTGVuZ3RoPC9sYWJlbD5cbiAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIm1pbkxlbmd0aFwiXG4gICAgICAgICAgICBpZD1cImJhc2ljLWlucHV0LXZhbGlkYXRvcnMtbWluTGVuZ3RoXCJcbiAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1ncm91cFwiPlxuICAgICAgICAgIDxsYWJlbCBmb3I9XCJiYXNpYy1pbnB1dC12YWxpZGF0b3JzLW1heExlbmd0aFwiPm1heExlbmd0aDwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJtYXhMZW5ndGhcIlxuICAgICAgICAgICAgaWQ9XCJiYXNpYy1pbnB1dC12YWxpZGF0b3JzLW1heExlbmd0aFwiXG4gICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwiYmFzaWMtaW5wdXQtcHJvcGVydHktcmVxdWlyZWRcIj5yZXF1aXJlZDwvbGFiZWw+XG4gICAgICAgICAgPHNlbGVjdFxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVxdWlyZWRcIlxuICAgICAgICAgICAgaWQ9XCJiYXNpYy1pbnB1dC1wcm9wZXJ0eS1yZXF1aXJlZFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG9wdGlvblxuICAgICAgICAgICAgICBbbmdWYWx1ZV09XCJudWxsXCJcbiAgICAgICAgICAgICAgZGlzYWJsZWRcbiAgICAgICAgICAgICAgPlNlbGVjdCBlaXRoZXIgdHJ1ZSBvciBmYWxzZTwvb3B0aW9uXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8b3B0aW9uXG4gICAgICAgICAgICAgICpuZ0Zvcj1cImxldCByZXF1aXJlZCBvZiBbdHJ1ZSwgZmFsc2VdXCJcbiAgICAgICAgICAgICAgW25nVmFsdWVdPVwicmVxdWlyZWRcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyByZXF1aXJlZCB9fVxuICAgICAgICAgICAgPC9vcHRpb24+XG4gICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9maWVsZHNldD5cbiAgICAgIDxmaWVsZHNldCBmb3JtR3JvdXBOYW1lPVwicHJvcGVydGllc1wiPlxuICAgICAgICA8bGVnZW5kPlByb3BlcnRpZXM8L2xlZ2VuZD5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwiYmFzaWMtaW5wdXQtcHJvcGVydHktcGxhY2Vob2xkZXJcIj5QbGFjZWhvbGRlcjwvbGFiZWw+XG4gICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJwbGFjZWhvbGRlclwiXG4gICAgICAgICAgICBpZD1cImJhc2ljLWlucHV0LXByb3BlcnR5LXBsYWNlaG9sZGVyXCJcbiAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAvPlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZvcm0tZ3JvdXBcIj5cbiAgICAgICAgICA8bGFiZWwgZm9yPVwiYmFzaWMtaW5wdXQtcHJvcGVydHktcmVhZG9ubHlcIj5yZWFkT25seTwvbGFiZWw+XG4gICAgICAgICAgPHNlbGVjdFxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmVhZE9ubHlcIlxuICAgICAgICAgICAgaWQ9XCJiYXNpYy1pbnB1dC1wcm9wZXJ0eS1yZWFkb25seVwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgPG9wdGlvblxuICAgICAgICAgICAgICBbbmdWYWx1ZV09XCJudWxsXCJcbiAgICAgICAgICAgICAgZGlzYWJsZWRcbiAgICAgICAgICAgICAgPlNlbGVjdCBlaXRoZXIgdHJ1ZSBvciBmYWxzZTwvb3B0aW9uXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8b3B0aW9uXG4gICAgICAgICAgICAgICpuZ0Zvcj1cImxldCByZWFkb25seSBvZiBbdHJ1ZSwgZmFsc2VdXCJcbiAgICAgICAgICAgICAgW25nVmFsdWVdPVwicmVhZG9ubHlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyByZWFkb25seSB9fVxuICAgICAgICAgICAgPC9vcHRpb24+XG4gICAgICAgICAgPC9zZWxlY3Q+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9maWVsZHNldD5cbiAgICAgIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cImVsZW1lbnRUeXBlXCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIid0ZXh0J1wiPlxuICAgICAgICAgIDxiYXNpYy10ZXh0LWNvbmZpZy1lZGl0b3JcbiAgICAgICAgICAgIFtzYXZlQmFzaWNDbGlja0NvdW50ZXJdPVwic2F2ZUJhc2ljQ2xpY2tDb3VudGVyXCJcbiAgICAgICAgICAgIFtlbGVtZW50Q29uZmlnXT1cImVsZW1lbnRDb25maWdcIlxuICAgICAgICAgICAgKHVwZGF0ZUVsZW1lbnQpPVwiaGFuZGxlT25TYXZlVXBkYXRlRWxlbWVudCgkZXZlbnQpXCJcbiAgICAgICAgICA+PC9iYXNpYy10ZXh0LWNvbmZpZy1lZGl0b3I+XG4gICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCIncmFkaW8nXCI+XG4gICAgICAgICAgPGJhc2ljLXJhZGlvLWNvbmZpZy1lZGl0b3JcbiAgICAgICAgICAgIFtzYXZlQmFzaWNDbGlja0NvdW50ZXJdPVwic2F2ZUJhc2ljQ2xpY2tDb3VudGVyXCJcbiAgICAgICAgICAgIFtlbGVtZW50Q29uZmlnXT1cImVsZW1lbnRDb25maWdcIlxuICAgICAgICAgICAgKHVwZGF0ZUVsZW1lbnQpPVwiaGFuZGxlT25TYXZlVXBkYXRlRWxlbWVudCgkZXZlbnQpXCJcbiAgICAgICAgICA+PC9iYXNpYy1yYWRpby1jb25maWctZWRpdG9yPlxuICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwvZm9ybT5cbiAgYCxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgOmhvc3Qge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBhbGlnbi1jb250ZW50OiBjZW50ZXI7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogZmxleC1zdGFydDtcbiAgICAgICAgYWxpZ24taXRlbXM6IHN0cmV0Y2g7XG4gICAgICAgIGdhcDogMXJlbTtcbiAgICAgIH1cbiAgICBgXG4gIF1cbn0pXG5leHBvcnQgY2xhc3MgQmFzaWNFbGVtZW50Q29uZmlnRWRpdG9yIGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KClcbiAgc2F2ZUNsaWNrQ291bnRlcjogbnVtYmVyID0gMDtcblxuICBASW5wdXQoKVxuICBlbGVtZW50Q29uZmlnOiBhbnkgPSB7XG4gICAgbGFiZWw6IFwiXCIsXG4gICAga2V5OiBcIlwiLFxuICAgIGRpc2FibGVkOiBmYWxzZSxcbiAgICBkZWZhdWx0OiB7XG4gICAgICB2YWx1ZTogdHJ1ZVxuICAgIH0sXG4gICAgdmFsaWRhdG9yczoge1xuICAgICAgbWluOiBudWxsLFxuICAgICAgbWF4OiBudWxsLFxuICAgICAgbWluTGVuZ3RoOiBudWxsLFxuICAgICAgbWF4TGVuZ3RoOiBudWxsLFxuICAgICAgcmVxdWlyZWQ6IHRydWVcbiAgICB9LFxuICAgIHByb3BlcnRpZXM6IHtcbiAgICAgIHBsYWNlaG9sZGVyOiBcIlwiLFxuICAgICAgcmVhZE9ubHk6IGZhbHNlXG4gICAgfVxuICB9O1xuXG4gIEBPdXRwdXQoKVxuICB1cGRhdGVFbGVtZW50ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XG5cbiAgZWxlbWVudFR5cGU6IHN0cmluZyA9IFwiXCI7XG4gIHNhdmVCYXNpY0NsaWNrQ291bnRlcjogbnVtYmVyID0gMDtcblxuICBiYXNpY0Zvcm1Hcm91cDogRm9ybUdyb3VwID0gdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKCkge31cblxuICBAbG9nTWV0aG9kXG4gIG5nT25Jbml0KCkge1xuICAgIHRoaXMuYXNzaWduVmFyaWFibGVzKCk7XG4gICAgdGhpcy5jcmVhdGVCYXNpY0Zvcm1Hcm91cCgpO1xuICB9XG5cbiAgQGxvZ01ldGhvZFxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgY29uc3QgdmVyaWZ5Q2hhbmdlID0gKGtleTogc3RyaW5nKSA9PiB7XG4gICAgICByZXR1cm4gY2hhbmdlcy5oYXNPd25Qcm9wZXJ0eShrZXkpICYmICFjaGFuZ2VzW2tleV0uZmlyc3RDaGFuZ2U7XG4gICAgfTtcblxuICAgIGlmICh2ZXJpZnlDaGFuZ2UoXCJlbGVtZW50Q29uZmlnXCIpKSB7XG4gICAgICB0aGlzLmVsZW1lbnRDb25maWcgPSBjaGFuZ2VzLmVsZW1lbnRDb25maWcuY3VycmVudFZhbHVlO1xuICAgICAgdGhpcy5hc3NpZ25WYXJpYWJsZXMoKTtcbiAgICAgIHRoaXMuY3JlYXRlQmFzaWNGb3JtR3JvdXAoKTtcbiAgICB9XG5cbiAgICBpZiAodmVyaWZ5Q2hhbmdlKFwic2F2ZUNsaWNrQ291bnRlclwiKSkge1xuICAgICAgaWYgKFxuICAgICAgICBjaGFuZ2VzLnNhdmVDbGlja0NvdW50ZXIucHJldmlvdXNWYWx1ZSAhPT1cbiAgICAgICAgY2hhbmdlcy5zYXZlQ2xpY2tDb3VudGVyLmN1cnJlbnRWYWx1ZVxuICAgICAgKSB7XG4gICAgICAgIHRoaXMuc2F2ZUNsaWNrQ291bnRlciA9IGNoYW5nZXMuc2F2ZUNsaWNrQ291bnRlci5jdXJyZW50VmFsdWU7XG5cbiAgICAgICAgdGhpcy5oYW5kbGVPblNhdmUoKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBAbG9nTWV0aG9kXG4gIGFzc2lnblZhcmlhYmxlcygpIHtcbiAgICB0aGlzLmVsZW1lbnRUeXBlID0gdGhpcy5lbGVtZW50Q29uZmlnLmVsZW1lbnRUeXBlO1xuICB9XG5cbiAgQGxvZ01ldGhvZFxuICBjcmVhdGVCYXNpY0Zvcm1Hcm91cCgpIHtcbiAgICB0aGlzLmJhc2ljRm9ybUdyb3VwID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgICBsYWJlbDogbmV3IEZvcm1Db250cm9sKHRoaXMuZWxlbWVudENvbmZpZy5sYWJlbCksXG4gICAgICBrZXk6IG5ldyBGb3JtQ29udHJvbCh0aGlzLmVsZW1lbnRDb25maWcua2V5KSxcbiAgICAgIGRpc2FibGVkOiBuZXcgRm9ybUNvbnRyb2wodGhpcy5lbGVtZW50Q29uZmlnLmRpc2FibGVkKSxcbiAgICAgIGRlZmF1bHQ6IG5ldyBGb3JtR3JvdXAoe1xuICAgICAgICB2YWx1ZTogbmV3IEZvcm1Db250cm9sKHRoaXMuZWxlbWVudENvbmZpZy5kZWZhdWx0LnZhbHVlLCB7XG4gICAgICAgICAgdXBkYXRlT246IFwiY2hhbmdlXCJcbiAgICAgICAgfSlcbiAgICAgIH0pLFxuICAgICAgdmFsaWRhdG9yczogbmV3IEZvcm1Hcm91cCh7XG4gICAgICAgIG1pbjogbmV3IEZvcm1Db250cm9sKHRoaXMuZWxlbWVudENvbmZpZy52YWxpZGF0b3JzLm1pbiwge1xuICAgICAgICAgIHVwZGF0ZU9uOiBcImNoYW5nZVwiXG4gICAgICAgIH0pLFxuICAgICAgICBtaW5MZW5ndGg6IG5ldyBGb3JtQ29udHJvbCh0aGlzLmVsZW1lbnRDb25maWcudmFsaWRhdG9ycy5taW5MZW5ndGgsIHtcbiAgICAgICAgICB1cGRhdGVPbjogXCJjaGFuZ2VcIlxuICAgICAgICB9KSxcbiAgICAgICAgbWF4OiBuZXcgRm9ybUNvbnRyb2wodGhpcy5lbGVtZW50Q29uZmlnLnZhbGlkYXRvcnMubWF4LCB7XG4gICAgICAgICAgdXBkYXRlT246IFwiY2hhbmdlXCJcbiAgICAgICAgfSksXG4gICAgICAgIG1heExlbmd0aDogbmV3IEZvcm1Db250cm9sKHRoaXMuZWxlbWVudENvbmZpZy52YWxpZGF0b3JzLm1heExlbmd0aCwge1xuICAgICAgICAgIHVwZGF0ZU9uOiBcImNoYW5nZVwiXG4gICAgICAgIH0pLFxuICAgICAgICByZXF1aXJlZDogbmV3IEZvcm1Db250cm9sKHRoaXMuZWxlbWVudENvbmZpZy52YWxpZGF0b3JzLnJlcXVpcmVkLCB7XG4gICAgICAgICAgdXBkYXRlT246IFwiY2hhbmdlXCJcbiAgICAgICAgfSlcbiAgICAgIH0pLFxuICAgICAgcHJvcGVydGllczogbmV3IEZvcm1Hcm91cCh7XG4gICAgICAgIHBsYWNlaG9sZGVyOiBuZXcgRm9ybUNvbnRyb2woXG4gICAgICAgICAgdGhpcy5lbGVtZW50Q29uZmlnLnByb3BlcnRpZXMucGxhY2Vob2xkZXIsXG4gICAgICAgICAge1xuICAgICAgICAgICAgdXBkYXRlT246IFwiY2hhbmdlXCJcbiAgICAgICAgICB9XG4gICAgICAgICksXG4gICAgICAgIHJlYWRPbmx5OiBuZXcgRm9ybUNvbnRyb2wodGhpcy5lbGVtZW50Q29uZmlnLnByb3BlcnRpZXMucmVhZE9ubHksIHtcbiAgICAgICAgICB1cGRhdGVPbjogXCJjaGFuZ2VcIlxuICAgICAgICB9KVxuICAgICAgfSlcbiAgICB9KTtcbiAgICB0aGlzLmJhc2ljRm9ybUdyb3VwLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcbiAgfVxuXG4gIEBsb2dNZXRob2RcbiAgaGFuZGxlT25TYXZlVXBkYXRlRWxlbWVudChldmVudDogYW55KSB7XG4gICAgLy8gR2V0IENvbW1vbiBDb25maWdcbiAgICBsZXQgYmFzaWNFbGVtZW50Q29tbW9uQ29uZmlnID0gdGhpcy5iYXNpY0Zvcm1Hcm91cC5nZXRSYXdWYWx1ZSgpO1xuICAgIGJhc2ljRWxlbWVudENvbW1vbkNvbmZpZy5rZXkgPSBiYXNpY0VsZW1lbnRDb21tb25Db25maWcua2V5LnJlcGxhY2UoXG4gICAgICAvXFxzL2csXG4gICAgICBcIl9cIlxuICAgICk7XG5cbiAgICAvLyBHZXQgQmFzaWMgRWxlbWVudCBDb25maWdcbiAgICBjb25zdCBiYXNpY0VsZW1lbnRDb25maWcgPSBldmVudC5iYXNpY0VsZW1lbnRDb25maWc7XG5cbiAgICB0aGlzLmVsZW1lbnRDb25maWcgPSBfLm1lcmdlKFxuICAgICAgdGhpcy5lbGVtZW50Q29uZmlnLFxuICAgICAgYmFzaWNFbGVtZW50Q29tbW9uQ29uZmlnLFxuICAgICAgYmFzaWNFbGVtZW50Q29uZmlnXG4gICAgKTtcblxuICAgIHRoaXMudXBkYXRlRWxlbWVudC5lbWl0KHsgZWxlbWVudENvbmZpZzogdGhpcy5lbGVtZW50Q29uZmlnIH0pO1xuICB9XG5cbiAgQGxvZ01ldGhvZFxuICBoYW5kbGVPblNhdmUoKSB7XG4gICAgdGhpcy5zYXZlQmFzaWNDbGlja0NvdW50ZXIrKztcbiAgfVxufVxuIl19