@eqproject/eqp-dynamic-module 2.8.22 → 2.8.24

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,491 @@
1
+ import { Component, Input, ViewChild, Output, EventEmitter, } from "@angular/core";
2
+ import { CellAlignmentEnum, NumberColumnPipe, TypeColumn, } from "@eqproject/eqp-table";
3
+ import { FieldTypeEnum } from "../../../../models/baseField.model";
4
+ import { Record } from "../../../../models/record.model";
5
+ import { DateTimeTypeEnum, } from "../../../../models/fields/dateField.model";
6
+ import { UtilityHelperService } from "../../../../services/utilityHelper.services";
7
+ import { DynamicModuleListFormRecordActionsDefault } from "../../../../models/dynamicModuleListFormRecordActionsDefault";
8
+ import { ParamTypeEnum, } from "../../../../models/endPointConfiguration.model";
9
+ import { GlobalService } from "../../../../services/global.service";
10
+ import { ModeEnum } from "tmw-picker";
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "../../../../services/utilityHelper.services";
13
+ import * as i2 from "@angular/material/form-field";
14
+ import * as i3 from "@angular/material/core";
15
+ import * as i4 from "@angular/material/select";
16
+ import * as i5 from "@angular/material/card";
17
+ import * as i6 from "@angular/material/table";
18
+ import * as i7 from "@angular/common";
19
+ import * as i8 from "tmw-picker";
20
+ export class HListFormRecordComponent {
21
+ //#region Constructor
22
+ constructor(utilityHelperService, changeDetector) {
23
+ this.utilityHelperService = utilityHelperService;
24
+ this.changeDetector = changeDetector;
25
+ this.form = null; // boh ma c'era prima
26
+ this.externalButtons = new Array();
27
+ this.defaultListActions = new DynamicModuleListFormRecordActionsDefault();
28
+ this.showTitle = true;
29
+ this.columns = new Array();
30
+ this.loadedFilters = false;
31
+ this.loadedTable = false;
32
+ this.onViewRecord = new EventEmitter();
33
+ this.onAddViewEditRecord = new EventEmitter();
34
+ this.onDeleteRecord = new EventEmitter();
35
+ this.onAfterDeleteRecord = new EventEmitter();
36
+ this.modes = ModeEnum;
37
+ this.minDate = new Date();
38
+ this.maxDate = new Date();
39
+ // le proprietà della risposta da stampare nelle righe
40
+ this.properties = [];
41
+ // le label associate alle proprietà da stampare che condividono lo stesso indice
42
+ this.propertiesLabel = [];
43
+ // Colonne da visualizzare (fissa la prima colonna e genera dinamicamente le altre)
44
+ this.displayedColumns = [];
45
+ // this.propertiesLabel["AnswerDate"] = "Data";
46
+ }
47
+ //#endregion Constructor
48
+ //#region ngOnIntit
49
+ ngOnInit() {
50
+ this.defaultListActions = this.configurations.defaultListActions;
51
+ this.showTitle = this.configurations.showTitle;
52
+ GlobalService.debugLog('list-form-record - ngOnInit - configurations', this.configurations);
53
+ this.getFormByID();
54
+ }
55
+ //#endregion ngOnIntit
56
+ //#region ngOnChanges
57
+ ngOnChanges(changes) {
58
+ GlobalService.debugLog('list-form-record - changes', changes);
59
+ // Se viene modificato il valore di "ngModelInput" allora aggiorna l'input
60
+ // if (changes['configurations'] != undefined && changes['configurations'].firstChange == false) {
61
+ // this.configurations.values = changes['configurations'].currentValue;
62
+ // this.reloadTables();
63
+ // }
64
+ }
65
+ //#endregion ngOnChanges
66
+ //#region getFormByID
67
+ async getFormByID(id = this.formID) {
68
+ GlobalService.debugLog('list-form-record - getFormByID', this.form);
69
+ if (this.form == null) {
70
+ const dynamicModuleParams = new Array();
71
+ dynamicModuleParams.push({
72
+ ParamName: "id",
73
+ ParamValue: id,
74
+ ParamType: ParamTypeEnum["Query param"],
75
+ });
76
+ await this.utilityHelperService.RunEndPointCall(this.endPointConfiguration.Forms.GetByIDEndPoint, dynamicModuleParams, (res) => {
77
+ this.form = res;
78
+ this.configureColumns();
79
+ }, (err) => { });
80
+ }
81
+ else {
82
+ this.configureColumns();
83
+ }
84
+ }
85
+ //#endregion getFormByID
86
+ //#region getRecordsByFormID
87
+ /**
88
+ * Metodo per recuperare tutti i record salvati per una particolare Form.
89
+ * La chiamata viene effettuata solo se è stato configurato l'endPoint da usare.
90
+ * La risposta della chiamata deve essere un array di oggetti di tipo "DynRecord"
91
+ * a partire dai quali vengono ricreati i Record usati nel client.
92
+ */
93
+ async getRecordsByFormID() {
94
+ /**
95
+ * prende le risposte e le rende piatte, adatte a diventare una riga da tabella
96
+ * mette tutte le risposte nelle strutture necessarie per il recupero e la visualizzazione
97
+ * @param answers
98
+ */
99
+ const rearrangeAnswersAndPopulateLists = (answers) => {
100
+ this.configurations.values = new Array();
101
+ answers.forEach((answer) => {
102
+ var tmpRec = new Record();
103
+ tmpRec = JSON.parse(answer.SerializedValues);
104
+ tmpRec.ID = answer.ID;
105
+ tmpRec.EntID = answer.EntID;
106
+ tmpRec.Version = answer.Version;
107
+ tmpRec.userID = answer.userID;
108
+ tmpRec.AnswerDate = answer.AnswerDate;
109
+ this.configurations.values.push(tmpRec);
110
+ });
111
+ };
112
+ /**
113
+ * prepara la lista delle colonne da mostrare (una per ogni risposta, più la colonna delle proprietà)
114
+ * imposta la lista delle risposte da visualizzare
115
+ * libera le variabili di caricamento per mostrare i contenuti della vista
116
+ */
117
+ const nameColumnsAndStartView = () => {
118
+ //destruttura l'array risposte e per ogni risposta genera un elemento col[i]
119
+ this.displayedColumns = ["property", ...this.configurations.values.map((_, i) => `col${i}`)];
120
+ this.filteredAnswers = this.configurations.values;
121
+ this.setMinMaxDates();
122
+ this.loadedFilters = true;
123
+ this.loadedTable = true;
124
+ setTimeout((_) => {
125
+ this.changeDetector.detectChanges();
126
+ }, 0); // refresh ui
127
+ };
128
+ if (this.configurations.values) {
129
+ // vengo da un'altra visualizzazione che ha già recuperato le risposte
130
+ console.log("hList - getRecordsByFormID A", this.configurations);
131
+ nameColumnsAndStartView();
132
+ }
133
+ else {
134
+ // sono in una nuova istanza in cui devo recuperare le risposte
135
+ console.log("hList - getRecordsByFormID B", this.configurations);
136
+ try {
137
+ if (this.endPointConfiguration &&
138
+ this.endPointConfiguration.Records &&
139
+ this.endPointConfiguration.Records.GetByFormIDEndPoint) {
140
+ let dynamicModuleParams = [
141
+ {
142
+ ParamName: "EntID",
143
+ ParamValue: this.form.ID,
144
+ ParamType: ParamTypeEnum["Query param"],
145
+ },
146
+ ];
147
+ if (this.configurations.userID == null) {
148
+ // non ho specificato un utente
149
+ // vedo tutte le risposte del modulo
150
+ await this.utilityHelperService.RunEndPointCall(this.endPointConfiguration.Records.GetByFormIDEndPoint, dynamicModuleParams, (res) => {
151
+ rearrangeAnswersAndPopulateLists(res);
152
+ nameColumnsAndStartView();
153
+ });
154
+ }
155
+ else {
156
+ // conosco l'utente
157
+ // voglio solamente le sue risposte
158
+ dynamicModuleParams.push({
159
+ ParamName: "UserID",
160
+ ParamValue: this.configurations.userID,
161
+ ParamType: ParamTypeEnum["Query param"],
162
+ });
163
+ await this.utilityHelperService.RunEndPointCall(this.endPointConfiguration.Records.GetAllByEntAndUserIDEndPoint, dynamicModuleParams, (res) => {
164
+ rearrangeAnswersAndPopulateLists(res);
165
+ nameColumnsAndStartView();
166
+ });
167
+ }
168
+ }
169
+ }
170
+ catch (e) {
171
+ console.error('exception', e);
172
+ }
173
+ }
174
+ }
175
+ //#endregion getRecordsByFormID
176
+ //#region configureColumns
177
+ /**
178
+ * Metodo per configurare le colonne della eqp-table.
179
+ */
180
+ configureColumns() {
181
+ this.columns = [
182
+ {
183
+ key: "action",
184
+ display: "",
185
+ type: TypeColumn.MenuAction,
186
+ buttonMenuIcon: "more_vert",
187
+ styles: { flex: "0 0 6%" },
188
+ actions: [],
189
+ },
190
+ ];
191
+ if (this.defaultListActions.view == true) {
192
+ this.columns
193
+ .find((c) => c.key === "action")
194
+ .actions.push({
195
+ name: "Visualizza",
196
+ icon: "info",
197
+ fn: (element, index, col) => this.viewRecord(element),
198
+ });
199
+ }
200
+ if (this.defaultListActions.edit == true) {
201
+ this.columns
202
+ .find((c) => c.key === "action")
203
+ .actions.push({
204
+ name: "Modifica",
205
+ icon: "edit",
206
+ fn: (element, index, col) => this.viewOrEditRecord(element, false),
207
+ });
208
+ }
209
+ if (this.defaultListActions.duplicate == true) {
210
+ /*this.columns
211
+ .find((c) => c.key === "action")
212
+ .actions.push({
213
+ name: "Duplica",
214
+ icon: "file_copy",
215
+ fn: (element, index, col) => this.duplicateRecord(element),
216
+ });*/
217
+ }
218
+ if (this.defaultListActions.delete == true) {
219
+ this.columns
220
+ .find((c) => c.key === "action")
221
+ .actions.push({
222
+ name: "Elimina",
223
+ icon: "delete",
224
+ fn: (element, index, col) => this.deleteRecord(element),
225
+ });
226
+ }
227
+ this.externalButtons.forEach((button) => {
228
+ this.columns
229
+ .find((c) => c.key === "action")
230
+ .actions.push({
231
+ name: button.text,
232
+ icon: button.icon,
233
+ fn: (element, index, col) => button.fn(),
234
+ });
235
+ });
236
+ this.createAdditionalActions();
237
+ this.createColumnsFromFormFields();
238
+ this.getRecordsByFormID();
239
+ }
240
+ //#endregion configureColumns
241
+ //#region createAdditionalActions
242
+ /**
243
+ * Metodo per aggiungere nella colonna "action" della eqp-table le azioni sui record
244
+ * definite dall'utente all'interno della Form.
245
+ */
246
+ createAdditionalActions() {
247
+ GlobalService.debugLog('list-form-record - createAdditionalActions', this.form);
248
+ if (this.form.ActionsOnRecord && this.form.ActionsOnRecord.length > 0) {
249
+ this.form.ActionsOnRecord.sort((a, b) => a.OrdinalPosition > b.OrdinalPosition
250
+ ? 1
251
+ : b.OrdinalPosition > a.OrdinalPosition
252
+ ? -1
253
+ : 0).forEach((action) => {
254
+ this.columns
255
+ .find((c) => c.key === "action")
256
+ .actions.push({
257
+ name: action.Name,
258
+ icon: action.Icon,
259
+ fn: (element, index, col) => {
260
+ const rec = element;
261
+ const ctx = UtilityHelperService.context;
262
+ eval(action.Action);
263
+ // TODO: salvare le modifiche
264
+ },
265
+ });
266
+ });
267
+ }
268
+ }
269
+ //#endregion createAdditionalActions
270
+ //#region createColumnsFromFormFields
271
+ /**
272
+ * Metodo per creare la configurazione delle colonne per la eqp-table.
273
+ * Individua i BaseField da mostrare e li usa per creare le ConfigColumn.
274
+ * Le colonne vengono create per i BaseField con il flag InListView a TRUE
275
+ * oppure, nel caso non siano stati specificati i campi da visualizzare,
276
+ * seleziona i primi 6.
277
+ */
278
+ createColumnsFromFormFields() {
279
+ GlobalService.debugLog('list-form-record - createColumnsFromFormFields', this.form);
280
+ var fieldsForColumns;
281
+ fieldsForColumns = this.form.Fields.filter((f) => {
282
+ if (f.AnswerStyle) {
283
+ return f.AnswerStyle.InListView;
284
+ }
285
+ else {
286
+ return f.InListView;
287
+ }
288
+ });
289
+ fieldsForColumns
290
+ .sort((a, b) => a.OrdinalPosition > b.OrdinalPosition
291
+ ? 1
292
+ : b.OrdinalPosition > a.OrdinalPosition
293
+ ? -1
294
+ : 0)
295
+ .forEach((field) => {
296
+ this.columns.push(this.createFieldColumn(field));
297
+ this.properties.push(field.Label);
298
+ this.propertiesLabel[field.Label] = (field.Description);
299
+ });
300
+ this.selectedProperties = this.properties;
301
+ }
302
+ //#endregion createColumnsFromFormFields
303
+ //#region createFieldColumn
304
+ /**
305
+ * Metodo per creare l'oggetto ConfigureColumn che rappresenta il BaseField passato in input.
306
+ * @param field BaseField per cui creare la colonna nella eqp-table
307
+ * @returns Restituisce una ConfigColumn per la eqp-table
308
+ */
309
+ createFieldColumn(field) {
310
+ var column = { key: field.Name, display: field.Label };
311
+ switch (field.FieldType) {
312
+ case FieldTypeEnum["Booleano"]:
313
+ column.type = TypeColumn.Boolean;
314
+ column.booleanValues = {
315
+ false: '<i class="fa fa-times error-color"></i>',
316
+ true: '<i class="fa fa-check success-color"></i>',
317
+ };
318
+ column.styles = {
319
+ flex: "0 0 7%",
320
+ cellAlignment: CellAlignmentEnum.CENTER,
321
+ };
322
+ break;
323
+ case FieldTypeEnum["Data e/o ora"]:
324
+ if (field.IsOnlyDate != DateTimeTypeEnum["Solo orario"]) {
325
+ column.type = TypeColumn.Date;
326
+ if (field.IsOnlyDate == DateTimeTypeEnum["Data e ora"]) {
327
+ column.format = "dd/MM/yyyy HH:mm";
328
+ }
329
+ else if (field.IsOnlyDate == DateTimeTypeEnum["Solo data"]) {
330
+ column.format = field.DateFormat
331
+ ? field.DateFormat.replace("DD", "dd")
332
+ : "dd/MM/yyyy";
333
+ }
334
+ }
335
+ break;
336
+ case FieldTypeEnum["Campo numerico"]:
337
+ if (field.CurrencySymbol) {
338
+ column.numberPipe = NumberColumnPipe.CURRENCY;
339
+ column.currencyPipeCode = field.CurrencySymbol;
340
+ }
341
+ else if (!field.IsInteger) {
342
+ column.numberPipe = NumberColumnPipe.DECIMAL;
343
+ }
344
+ break;
345
+ case FieldTypeEnum["Allegato"]:
346
+ case FieldTypeEnum["Immagine"]:
347
+ /*
348
+ column.value = (element: Record) => {
349
+ if (
350
+ (field as AttachmentField).IsMultiAttach ||
351
+ ((field as ImageField).AttachDefinition &&
352
+ (field as ImageField).AttachDefinition.IsMultiAttach)
353
+ ) {
354
+ return element[field.Name] != null && element[field.Name].length > 0
355
+ ? (element[field.Name] as Array<IAttachmentDTO>)
356
+ .map((a) => a.FileName)
357
+ .join(", ")
358
+ : null;
359
+ } else {
360
+ return element[field.Name] != null && element[field.Name].length > 0
361
+ ? (element[field.Name] as Array<IAttachmentDTO>)[0].FileName
362
+ : null;
363
+ }
364
+ };
365
+ column.isSortable = false;
366
+ column.isSearchable = false;
367
+ */
368
+ break;
369
+ case FieldTypeEnum["Elenco generico"]:
370
+ column.value = (element) => {
371
+ if (field.IsMultiChoiche) {
372
+ if (!element[field.Name] || element[field.Name].length == 0) {
373
+ return null;
374
+ }
375
+ else {
376
+ return Object.keys(field.ValuePairs)
377
+ .filter((k) => element[field.Name].includes(field.ValuePairs[k]))
378
+ .join(", ");
379
+ }
380
+ }
381
+ else {
382
+ return Object.keys(field.ValuePairs).find((k) => field.ValuePairs[k] == element[field.Name]);
383
+ }
384
+ };
385
+ column.isSortable = false;
386
+ column.isSearchable = false;
387
+ break;
388
+ case FieldTypeEnum["Lookup"]:
389
+ // TODO
390
+ break;
391
+ }
392
+ return column;
393
+ }
394
+ //#endregion createFieldColumn
395
+ //#region viewRecord
396
+ viewRecord(record) {
397
+ this.onViewRecord.emit(record);
398
+ }
399
+ //#endregion viewRecord
400
+ /**
401
+ * Metodo che scatena l'evento di Output per mostrare o modificare il record
402
+ * selezionato sulla eqp-table.
403
+ * @param record Record da visualizzare o modificare selezionato sulla eqp-table.
404
+ * @param onlyView Se TRUE viene mostrato il componente add-form-record in sola lettura.
405
+ */
406
+ viewOrEditRecord(record, onlyView) {
407
+ this.onAddViewEditRecord.emit({ record, onlyView });
408
+ }
409
+ /**
410
+ * Metodo per eliminare un record dalla lista.
411
+ * @param record Record da eliminare selezionato sulla eqp-table.
412
+ */
413
+ deleteRecord(record) {
414
+ this.onDeleteRecord.emit(record);
415
+ }
416
+ /**
417
+ * Metodo per ricaricare i dati della eqp-table.
418
+ */
419
+ reloadTables() {
420
+ if (this.tableRecords) {
421
+ this.tableRecords.reloadDatatable();
422
+ }
423
+ }
424
+ //#region onSelectionChange
425
+ /**
426
+ * Funzione che viene chiamata al cambio di selezione dei parametri da mostrare
427
+ * aggiorna la lista delle proprietà selezionate che gestisce le righe mostrate per ogni risposta
428
+ * @param selectedProperties
429
+ */
430
+ onSelectionChange(selectedProperties) {
431
+ console.log(selectedProperties.value);
432
+ if (selectedProperties.value.length > 0) {
433
+ this.selectedProperties = selectedProperties.value;
434
+ }
435
+ else {
436
+ this.selectedProperties = this.properties;
437
+ }
438
+ console.log(this.selectedProperties);
439
+ }
440
+ //#endregion onSelectionChange
441
+ filterDataAnswers() {
442
+ // this.loadedTable = false;
443
+ setTimeout(() => {
444
+ this.filteredAnswers = [];
445
+ this.maxDate.setHours(23, 59, 59, 59);
446
+ this.configurations.values.forEach((value) => {
447
+ if (new Date(value.AnswerDate) >= this.minDate && new Date(value.AnswerDate) <= this.maxDate) {
448
+ this.filteredAnswers.push(value);
449
+ }
450
+ });
451
+ this.displayedColumns = ["property", ...this.filteredAnswers.map((_, i) => `col${i}`)];
452
+ // this.loadedTable = true;
453
+ }, 100);
454
+ }
455
+ // Funzione per ottenere la data più recente e quella più vecchia
456
+ setMinMaxDates() {
457
+ // Converto le date di AnswerDate in oggetti Date e ordino
458
+ const dates = this.configurations.values.map(value => new Date(value.AnswerDate));
459
+ // Trovo la data più recente (max) e la più vecchia (min)
460
+ this.minDate = new Date(Math.min(...dates.map(date => date.getTime())));
461
+ this.maxDate = new Date(Math.max(...dates.map(date => date.getTime())));
462
+ }
463
+ }
464
+ HListFormRecordComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: HListFormRecordComponent, deps: [{ token: i1.UtilityHelperService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
465
+ HListFormRecordComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: HListFormRecordComponent, selector: "hlist-form-record", inputs: { configurations: "configurations", endPointConfiguration: "endPointConfiguration", formID: "formID", form: "form", externalButtons: "externalButtons" }, outputs: { onViewRecord: "onViewRecord", onAddViewEditRecord: "onAddViewEditRecord", onDeleteRecord: "onDeleteRecord", onAfterDeleteRecord: "onAfterDeleteRecord" }, viewQueries: [{ propertyName: "tableRecords", first: true, predicate: ["tableRecords"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: "<mat-card class=\"list-form-record\">\r\n <mat-card-header class=\"align-items-center justify-content-between\">\r\n <mat-card-title *ngIf=\"loadedFilters && showTitle\"\r\n >Elenco {{ form.Name }}</mat-card-title\r\n >\r\n <!-- <mat-card-actions>\r\n <button\r\n class=\"btn btn-primary\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"onAddViewEditRecord.emit(null)\"\r\n >\r\n <mat-icon>add</mat-icon>\r\n <span style=\"margin-left: 10px\">Aggiungi</span>\r\n </button>\r\n </mat-card-actions> -->\r\n </mat-card-header>\r\n <mat-card-content>\r\n <!--#region FILTERS -->\r\n <div class=\"row\" *ngIf=\"loadedFilters\">\r\n <div class=\"col-sm-12 col-md-3\">\r\n <tmw-datetimepicker\r\n class=\"date\"\r\n [placeholder]=\"'Periodo inizio'\"\r\n [label]=\"'Periodo inizio'\"\r\n [(ngModelInput)]=\"minDate\"\r\n (ngModelInputChange)=\"filterDataAnswers()\"\r\n [pickerMode]=\"modes.DATEPICKER\"\r\n [outputFormat]=\"'DD/MM/YYYY'\"\r\n [showSeconds]=\"false\"\r\n >\r\n </tmw-datetimepicker>\r\n </div>\r\n <div class=\"col-sm-12 col-md-3\">\r\n <tmw-datetimepicker\r\n class=\"date\"\r\n [placeholder]=\"'Periodo fine'\"\r\n [label]=\"'Periodo fine'\"\r\n [(ngModelInput)]=\"maxDate\"\r\n (ngModelInputChange)=\"filterDataAnswers()\"\r\n [pickerMode]=\"modes.DATEPICKER\"\r\n [outputFormat]=\"'DD/MM/YYYY'\"\r\n [showSeconds]=\"false\"\r\n >\r\n </tmw-datetimepicker>\r\n </div>\r\n <div class=\"col-sm-12 col-md-3 mt-2\">\r\n <mat-form-field>\r\n <mat-label>Selezione dei campi</mat-label>\r\n <mat-select (selectionChange)=\"onSelectionChange($event)\" multiple>\r\n <mat-option *ngFor=\"let property of properties\" [value]=\"property\">\r\n {{ propertiesLabel[property] }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n <!-- <div class=\"col-sm-12 col-md-3 mt-2\">\r\n <button\r\n [disabled]=\"\r\n selectedProperties == null || selectedProperties.length == 0\r\n \"\r\n class=\"btn btn-graph-generate button-next me-2\"\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"filterDataAnswers()\"\r\n >\r\n Genera\r\n </button>\r\n </div> -->\r\n </div>\r\n <!--#endregion FILTERS -->\r\n\r\n <!--#region TABLE -->\r\n <div class=\"table-container\">\r\n <table\r\n mat-table\r\n [dataSource]=\"selectedProperties\"\r\n class=\"mat-elevation-z8 mat-table-fixed\"\r\n >\r\n <!-- Colonna fissa per le propriet\u00E0 -->\r\n <ng-container matColumnDef=\"property\" sticky>\r\n <th mat-header-cell *matHeaderCellDef class=\"sticky-column\">\r\n Data Inserimento\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let selectedProperties\"\r\n class=\"sticky-column\"\r\n >\r\n {{ propertiesLabel[selectedProperties] }}\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Genera dinamicamente le colonne per ogni risposta -->\r\n <ng-container\r\n *ngFor=\"let value of filteredAnswers; let i = index\"\r\n [matColumnDef]=\"'col' + i\"\r\n >\r\n <th mat-header-cell *matHeaderCellDef>\r\n {{ value.AnswerDate | date : \"dd/MM/yyyy HH:mm\" }}\r\n </th>\r\n <!-- <th mat-header-cell *matHeaderCellDef> {{ value.AnswerDate | date:'dd/MM/yyyy HH:mm' }} </th> -->\r\n <td mat-cell *matCellDef=\"let selectedProperties\">\r\n {{\r\n selectedProperties === \"AnswerDate\"\r\n ? (value.AnswerDate | date : \"dd/MM/yyyy HH:mm\")\r\n : value[selectedProperties] ?? \"N/A\"\r\n }}\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Header della tabella -->\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\r\n\r\n <!-- Righe della tabella -->\r\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\r\n </table>\r\n </div>\r\n <!--#region TABLE -->\r\n </mat-card-content>\r\n <mat-card-footer>\r\n <!-- <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar> -->\r\n </mat-card-footer>\r\n</mat-card>\r\n\r\n<!-- <div class=\"row eqp-dynamic-module-title list-form-record-header\">\r\n <div class=\"col-md-6\">\r\n <h4 *ngIf=\"showTitle\">\r\n <b>Elenco {{ form.Name }}</b>\r\n </h4>\r\n </div>\r\n <div class=\"col-md-6 text-right\" *ngIf=\"defaultListActions.add\">\r\n <button class=\"btn btn-primary\" mat-raised-button color=\"primary\" type=\"button\"\r\n (click)=\"onAddViewEditRecord.emit(null)\">\r\n <mat-icon>add</mat-icon>\r\n <span style=\"margin-left: 10px\">Aggiungi</span>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<eqp-table class=\"list-form-record-table\" #tableRecords *ngIf=\"loader && configurations.values\"\r\n [data]=\"configurations.values\" [columns]=\"columns\"></eqp-table> -->\r\n", styles: ["::ng-deep .error-color{color:var(--danger)}::ng-deep .success-color{color:var(--success)}.table-container{max-width:100%;overflow-x:auto;border:1px solid #ddd}.sticky-column{position:sticky;left:0;background:white;z-index:10;box-shadow:2px 0 5px #0000001a}.mat-table-fixed{width:-moz-max-content;width:max-content;min-width:100%;table-layout:fixed}th,td{text-align:center;padding:10px;min-width:100px;max-width:200px}\n"], dependencies: [{ kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "component", type: i3.MatOption, selector: "mat-option", exportAs: ["matOption"] }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator"], exportAs: ["matSelect"] }, { kind: "component", type: i5.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i5.MatCardContent, selector: "mat-card-content" }, { kind: "directive", type: i5.MatCardFooter, selector: "mat-card-footer" }, { kind: "component", type: i5.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i5.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: i7.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i7.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i8.TmwDateTimePickerComponent, selector: "tmw-datetimepicker", inputs: ["debugMode", "ngModelInput", "formGroupInput", "formControlNameInput", "pickerMode", "timeType", "label", "placeholder", "hint", "minDate", "maxDate", "locale", "inputFormat", "outputFormat", "forSaveLocalOnDB", "disabled", "readonly", "currentDateAsDefault", "showSpinners", "touchUi", "enableMeridian", "hideTime", "stepHour", "showHours", "hourLabel", "stepMinute", "showMinutes", "minuteLabel", "stepSecond", "showSeconds", "secondLabel", "disableMinute", "dayLabel", "monthLabel", "yearLabel", "highLightedDates", "highLightedAriaFormat"], outputs: ["ngModelInputChange"] }, { kind: "pipe", type: i7.DatePipe, name: "date" }] });
466
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: HListFormRecordComponent, decorators: [{
467
+ type: Component,
468
+ args: [{ selector: "hlist-form-record", template: "<mat-card class=\"list-form-record\">\r\n <mat-card-header class=\"align-items-center justify-content-between\">\r\n <mat-card-title *ngIf=\"loadedFilters && showTitle\"\r\n >Elenco {{ form.Name }}</mat-card-title\r\n >\r\n <!-- <mat-card-actions>\r\n <button\r\n class=\"btn btn-primary\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n (click)=\"onAddViewEditRecord.emit(null)\"\r\n >\r\n <mat-icon>add</mat-icon>\r\n <span style=\"margin-left: 10px\">Aggiungi</span>\r\n </button>\r\n </mat-card-actions> -->\r\n </mat-card-header>\r\n <mat-card-content>\r\n <!--#region FILTERS -->\r\n <div class=\"row\" *ngIf=\"loadedFilters\">\r\n <div class=\"col-sm-12 col-md-3\">\r\n <tmw-datetimepicker\r\n class=\"date\"\r\n [placeholder]=\"'Periodo inizio'\"\r\n [label]=\"'Periodo inizio'\"\r\n [(ngModelInput)]=\"minDate\"\r\n (ngModelInputChange)=\"filterDataAnswers()\"\r\n [pickerMode]=\"modes.DATEPICKER\"\r\n [outputFormat]=\"'DD/MM/YYYY'\"\r\n [showSeconds]=\"false\"\r\n >\r\n </tmw-datetimepicker>\r\n </div>\r\n <div class=\"col-sm-12 col-md-3\">\r\n <tmw-datetimepicker\r\n class=\"date\"\r\n [placeholder]=\"'Periodo fine'\"\r\n [label]=\"'Periodo fine'\"\r\n [(ngModelInput)]=\"maxDate\"\r\n (ngModelInputChange)=\"filterDataAnswers()\"\r\n [pickerMode]=\"modes.DATEPICKER\"\r\n [outputFormat]=\"'DD/MM/YYYY'\"\r\n [showSeconds]=\"false\"\r\n >\r\n </tmw-datetimepicker>\r\n </div>\r\n <div class=\"col-sm-12 col-md-3 mt-2\">\r\n <mat-form-field>\r\n <mat-label>Selezione dei campi</mat-label>\r\n <mat-select (selectionChange)=\"onSelectionChange($event)\" multiple>\r\n <mat-option *ngFor=\"let property of properties\" [value]=\"property\">\r\n {{ propertiesLabel[property] }}\r\n </mat-option>\r\n </mat-select>\r\n </mat-form-field>\r\n </div>\r\n <!-- <div class=\"col-sm-12 col-md-3 mt-2\">\r\n <button\r\n [disabled]=\"\r\n selectedProperties == null || selectedProperties.length == 0\r\n \"\r\n class=\"btn btn-graph-generate button-next me-2\"\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"filterDataAnswers()\"\r\n >\r\n Genera\r\n </button>\r\n </div> -->\r\n </div>\r\n <!--#endregion FILTERS -->\r\n\r\n <!--#region TABLE -->\r\n <div class=\"table-container\">\r\n <table\r\n mat-table\r\n [dataSource]=\"selectedProperties\"\r\n class=\"mat-elevation-z8 mat-table-fixed\"\r\n >\r\n <!-- Colonna fissa per le propriet\u00E0 -->\r\n <ng-container matColumnDef=\"property\" sticky>\r\n <th mat-header-cell *matHeaderCellDef class=\"sticky-column\">\r\n Data Inserimento\r\n </th>\r\n <td\r\n mat-cell\r\n *matCellDef=\"let selectedProperties\"\r\n class=\"sticky-column\"\r\n >\r\n {{ propertiesLabel[selectedProperties] }}\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Genera dinamicamente le colonne per ogni risposta -->\r\n <ng-container\r\n *ngFor=\"let value of filteredAnswers; let i = index\"\r\n [matColumnDef]=\"'col' + i\"\r\n >\r\n <th mat-header-cell *matHeaderCellDef>\r\n {{ value.AnswerDate | date : \"dd/MM/yyyy HH:mm\" }}\r\n </th>\r\n <!-- <th mat-header-cell *matHeaderCellDef> {{ value.AnswerDate | date:'dd/MM/yyyy HH:mm' }} </th> -->\r\n <td mat-cell *matCellDef=\"let selectedProperties\">\r\n {{\r\n selectedProperties === \"AnswerDate\"\r\n ? (value.AnswerDate | date : \"dd/MM/yyyy HH:mm\")\r\n : value[selectedProperties] ?? \"N/A\"\r\n }}\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Header della tabella -->\r\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\r\n\r\n <!-- Righe della tabella -->\r\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns\"></tr>\r\n </table>\r\n </div>\r\n <!--#region TABLE -->\r\n </mat-card-content>\r\n <mat-card-footer>\r\n <!-- <mat-progress-bar mode=\"indeterminate\"></mat-progress-bar> -->\r\n </mat-card-footer>\r\n</mat-card>\r\n\r\n<!-- <div class=\"row eqp-dynamic-module-title list-form-record-header\">\r\n <div class=\"col-md-6\">\r\n <h4 *ngIf=\"showTitle\">\r\n <b>Elenco {{ form.Name }}</b>\r\n </h4>\r\n </div>\r\n <div class=\"col-md-6 text-right\" *ngIf=\"defaultListActions.add\">\r\n <button class=\"btn btn-primary\" mat-raised-button color=\"primary\" type=\"button\"\r\n (click)=\"onAddViewEditRecord.emit(null)\">\r\n <mat-icon>add</mat-icon>\r\n <span style=\"margin-left: 10px\">Aggiungi</span>\r\n </button>\r\n </div>\r\n</div>\r\n\r\n<eqp-table class=\"list-form-record-table\" #tableRecords *ngIf=\"loader && configurations.values\"\r\n [data]=\"configurations.values\" [columns]=\"columns\"></eqp-table> -->\r\n", styles: ["::ng-deep .error-color{color:var(--danger)}::ng-deep .success-color{color:var(--success)}.table-container{max-width:100%;overflow-x:auto;border:1px solid #ddd}.sticky-column{position:sticky;left:0;background:white;z-index:10;box-shadow:2px 0 5px #0000001a}.mat-table-fixed{width:-moz-max-content;width:max-content;min-width:100%;table-layout:fixed}th,td{text-align:center;padding:10px;min-width:100px;max-width:200px}\n"] }]
469
+ }], ctorParameters: function () { return [{ type: i1.UtilityHelperService }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { configurations: [{
470
+ type: Input
471
+ }], endPointConfiguration: [{
472
+ type: Input
473
+ }], formID: [{
474
+ type: Input
475
+ }], form: [{
476
+ type: Input
477
+ }], externalButtons: [{
478
+ type: Input
479
+ }], tableRecords: [{
480
+ type: ViewChild,
481
+ args: ["tableRecords", { static: true }]
482
+ }], onViewRecord: [{
483
+ type: Output
484
+ }], onAddViewEditRecord: [{
485
+ type: Output
486
+ }], onDeleteRecord: [{
487
+ type: Output
488
+ }], onAfterDeleteRecord: [{
489
+ type: Output
490
+ }] } });
491
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGxpc3QtZm9ybS1yZWNvcmQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZXFwLWR5bmFtaWMtbW9kdWxlL3NyYy9saWIvY29tcG9uZW50cy9wcml2YXRlL2Zvcm0tcmVjb3Jkcy9obGlzdC1mb3JtLXJlY29yZC9obGlzdC1mb3JtLXJlY29yZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtZHluYW1pYy1tb2R1bGUvc3JjL2xpYi9jb21wb25lbnRzL3ByaXZhdGUvZm9ybS1yZWNvcmRzL2hsaXN0LWZvcm0tcmVjb3JkL2hsaXN0LWZvcm0tcmVjb3JkLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBRVQsS0FBSyxFQUNMLFNBQVMsRUFDVCxNQUFNLEVBQ04sWUFBWSxHQUtiLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFDTCxpQkFBaUIsRUFHakIsZ0JBQWdCLEVBQ2hCLFVBQVUsR0FDWCxNQUFNLHNCQUFzQixDQUFDO0FBRTlCLE9BQU8sRUFBYSxhQUFhLEVBQUUsTUFBTSxvQ0FBb0MsQ0FBQztBQUM5RSxPQUFPLEVBQWEsTUFBTSxFQUFnQixNQUFNLGlDQUFpQyxDQUFDO0FBRWxGLE9BQU8sRUFFTCxnQkFBZ0IsR0FDakIsTUFBTSwyQ0FBMkMsQ0FBQztBQUluRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw2Q0FBNkMsQ0FBQztBQUNuRixPQUFPLEVBQUUseUNBQXlDLEVBQUUsTUFBTSw4REFBOEQsQ0FBQztBQUV6SCxPQUFPLEVBR0wsYUFBYSxHQUNkLE1BQU0sZ0RBQWdELENBQUM7QUFFeEQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxZQUFZLENBQUM7Ozs7Ozs7Ozs7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LENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RSxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzFFLENBQUM7O3NIQTdnQlUsd0JBQXdCOzBHQUF4Qix3QkFBd0IsaWhCQ2pEckMsdXdLQStJQTs0RkQ5RmEsd0JBQXdCO2tCQUxwQyxTQUFTOytCQUNFLG1CQUFtQjsySUFNcEIsY0FBYztzQkFBdEIsS0FBSztnQkFDRyxxQkFBcUI7c0JBQTdCLEtBQUs7Z0JBR0csTUFBTTtzQkFBZCxLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUt1QyxZQUFZO3NCQUF4RCxTQUFTO3VCQUFDLGNBQWMsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBTWpDLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csbUJBQW1CO3NCQUE1QixNQUFNO2dCQUVHLGNBQWM7c0JBQXZCLE1BQU07Z0JBQ0csbUJBQW1CO3NCQUE1QixNQUFNIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcclxuICBDb21wb25lbnQsXHJcbiAgT25Jbml0LFxyXG4gIElucHV0LFxyXG4gIFZpZXdDaGlsZCxcclxuICBPdXRwdXQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIMm1ybVOZ09uQ2hhbmdlc0ZlYXR1cmUsXHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgSUF0dGFjaG1lbnREVE8gfSBmcm9tIFwiQGVxcHJvamVjdC9lcXAtYXR0YWNobWVudHNcIjtcclxuaW1wb3J0IHtcclxuICBDZWxsQWxpZ25tZW50RW51bSxcclxuICBDb25maWdDb2x1bW4sXHJcbiAgRXFwVGFibGVDb21wb25lbnQsXHJcbiAgTnVtYmVyQ29sdW1uUGlwZSxcclxuICBUeXBlQ29sdW1uLFxyXG59IGZyb20gXCJAZXFwcm9qZWN0L2VxcC10YWJsZVwiO1xyXG5pbXBvcnQgeyBGb3JtIH0gZnJvbSBcIi4uLy4uLy4uLy4uL21vZGVscy9mb3JtLm1vZGVsXCI7XHJcbmltcG9ydCB7IEJhc2VGaWVsZCwgRmllbGRUeXBlRW51bSB9IGZyb20gXCIuLi8uLi8uLi8uLi9tb2RlbHMvYmFzZUZpZWxkLm1vZGVsXCI7XHJcbmltcG9ydCB7IER5blJlY29yZCwgUmVjb3JkLCBSZWNvcmRCdXR0b24gfSBmcm9tIFwiLi4vLi4vLi4vLi4vbW9kZWxzL3JlY29yZC5tb2RlbFwiO1xyXG5pbXBvcnQgeyBBdHRhY2htZW50RmllbGQgfSBmcm9tIFwiLi4vLi4vLi4vLi4vbW9kZWxzL2ZpZWxkcy9hdHRhY2htZW50RmllbGQubW9kZWxcIjtcclxuaW1wb3J0IHtcclxuICBEYXRlRmllbGQsXHJcbiAgRGF0ZVRpbWVUeXBlRW51bSxcclxufSBmcm9tIFwiLi4vLi4vLi4vLi4vbW9kZWxzL2ZpZWxkcy9kYXRlRmllbGQubW9kZWxcIjtcclxuaW1wb3J0IHsgSW1hZ2VGaWVsZCB9IGZyb20gXCIuLi8uLi8uLi8uLi9tb2RlbHMvZmllbGRzL2ltYWdlRmllbGQubW9kZWxcIjtcclxuaW1wb3J0IHsgTGlzdFZhbHVlRmllbGQgfSBmcm9tIFwiLi4vLi4vLi4vLi4vbW9kZWxzL2ZpZWxkcy9saXN0VmFsdWVGaWVsZC5tb2RlbFwiO1xyXG5pbXBvcnQgeyBOdW1lcmljRmllbGQgfSBmcm9tIFwiLi4vLi4vLi4vLi4vbW9kZWxzL2ZpZWxkcy9udW1lcmljRmllbGQubW9kZWxcIjtcclxuaW1wb3J0IHsgVXRpbGl0eUhlbHBlclNlcnZpY2UgfSBmcm9tIFwiLi4vLi4vLi4vLi4vc2VydmljZXMvdXRpbGl0eUhlbHBlci5zZXJ2aWNlc1wiO1xyXG5pbXBvcnQgeyBEeW5hbWljTW9kdWxlTGlzdEZvcm1SZWNvcmRBY3Rpb25zRGVmYXVsdCB9IGZyb20gXCIuLi8uLi8uLi8uLi9tb2RlbHMvZHluYW1pY01vZHVsZUxpc3RGb3JtUmVjb3JkQWN0aW9uc0RlZmF1bHRcIjtcclxuaW1wb3J0IHsgRHluYW1pY01vZHVsZUxpc3RDb25maWcgfSBmcm9tIFwiLi4vLi4vLi4vLi4vbW9kZWxzL2R5bmFtaWNNb2R1bGVMaXN0Q29uZmlnLm1vZGVsXCI7XHJcbmltcG9ydCB7XHJcbiAgRW5kUG9pbnRDb25maWd1cmF0aW9uLFxyXG4gIEVuZFBvaW50RGF0YVBhcmFtcyxcclxuICBQYXJhbVR5cGVFbnVtLFxyXG59IGZyb20gXCIuLi8uLi8uLi8uLi9tb2RlbHMvZW5kUG9pbnRDb25maWd1cmF0aW9uLm1vZGVsXCI7XHJcbmltcG9ydCB7IEVxcER5bmFtaWNNb2R1bGVEaWFsb2dTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uLy4uL3NlcnZpY2VzL2VxcC1keW5hbWljLW1vZHVsZS1kaWFsb2cuc2VydmljZVwiO1xyXG5pbXBvcnQgeyBHbG9iYWxTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uLy4uLy4uL3NlcnZpY2VzL2dsb2JhbC5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IE1vZGVFbnVtIH0gZnJvbSBcInRtdy1waWNrZXJcIjtcclxuXHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogXCJobGlzdC1mb3JtLXJlY29yZFwiLFxyXG4gIHRlbXBsYXRlVXJsOiBcImhsaXN0LWZvcm0tcmVjb3JkLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmxzOiBbXCIuL2hsaXN0LWZvcm0tcmVjb3JkLmNvbXBvbmVudC5zY3NzXCJdLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgSExpc3RGb3JtUmVjb3JkQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkNoYW5nZXMge1xyXG5cclxuICBASW5wdXQoKSBjb25maWd1cmF0aW9uczogRHluYW1pY01vZHVsZUxpc3RDb25maWc7XHJcbiAgQElucHV0KCkgZW5kUG9pbnRDb25maWd1cmF0aW9uOiBFbmRQb2ludENvbmZpZ3VyYXRpb247XHJcblxyXG4gIC8vIGwndW5hIG8gbCdhbHRyYSBwZXIgZHVlIG1vZGFsaXTDoCBkJ3Vzb1xyXG4gIEBJbnB1dCgpIGZvcm1JRDogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIGZvcm06IEZvcm0gPSBudWxsOyAvLyBib2ggbWEgYydlcmEgcHJpbWFcclxuICBASW5wdXQoKSBleHRlcm5hbEJ1dHRvbnM6IEFycmF5PFJlY29yZEJ1dHRvbj4gPSBuZXcgQXJyYXk8UmVjb3JkQnV0dG9uPigpO1xyXG5cclxuICBkZWZhdWx0TGlzdEFjdGlvbnM6IER5bmFtaWNNb2R1bGVMaXN0Rm9ybVJlY29yZEFjdGlvbnNEZWZhdWx0ID1cclxuICAgIG5ldyBEeW5hbWljTW9kdWxlTGlzdEZvcm1SZWNvcmRBY3Rpb25zRGVmYXVsdCgpO1xyXG4gIHNob3dUaXRsZSA9IHRydWU7XHJcbiAgQFZpZXdDaGlsZChcInRhYmxlUmVjb3Jkc1wiLCB7IHN0YXRpYzogdHJ1ZSB9KSB0YWJsZVJlY29yZHM6IEVxcFRhYmxlQ29tcG9uZW50O1xyXG5cclxuICBjb2x1bW5zID0gbmV3IEFycmF5PENvbmZpZ0NvbHVtbj4oKTtcclxuICBsb2FkZWRGaWx0ZXJzOiBib29sZWFuID0gZmFsc2U7XHJcbiAgbG9hZGVkVGFibGU6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgQE91dHB1dCgpIG9uVmlld1JlY29yZDogRXZlbnRFbWl0dGVyPFJlY29yZD4gPSBuZXcgRXZlbnRFbWl0dGVyPFJlY29yZD4oKTtcclxuICBAT3V0cHV0KCkgb25BZGRWaWV3RWRpdFJlY29yZDogRXZlbnRFbWl0dGVyPHsgcmVjb3JkOiBSZWNvcmQ7IG9ubHlWaWV3OiBib29sZWFuOyB9PiA9IG5ldyBFdmVudEVtaXR0ZXI8eyByZWNvcmQ6IFJlY29yZDsgb25seVZpZXc6IGJvb2xlYW4gfT4oKTtcclxuXHJcbiAgQE91dHB1dCgpIG9uRGVsZXRlUmVjb3JkOiBFdmVudEVtaXR0ZXI8UmVjb3JkPiA9IG5ldyBFdmVudEVtaXR0ZXI8UmVjb3JkPigpO1xyXG4gIEBPdXRwdXQoKSBvbkFmdGVyRGVsZXRlUmVjb3JkOiBFdmVudEVtaXR0ZXI8UmVjb3JkPiA9IG5ldyBFdmVudEVtaXR0ZXI8UmVjb3JkPigpO1xyXG5cclxuICBtb2RlcyA9IE1vZGVFbnVtO1xyXG4gIG1pbkRhdGUgPSBuZXcgRGF0ZSgpO1xyXG4gIG1heERhdGUgPSBuZXcgRGF0ZSgpO1xyXG5cclxuICAvLyBsZSBwcm9wcmlldMOgIGRlbGxhIHJpc3Bvc3RhIGRhIHN0YW1wYXJlIG5lbGxlIHJpZ2hlXHJcbiAgcHJvcGVydGllczogc3RyaW5nW10gPSBbXTtcclxuICAvLyBsZSBsYWJlbCBhc3NvY2lhdGUgYWxsZSBwcm9wcmlldMOgIGRhIHN0YW1wYXJlIGNoZSBjb25kaXZpZG9ubyBsbyBzdGVzc28gaW5kaWNlXHJcbiAgcHJvcGVydGllc0xhYmVsID0gW107XHJcbiAgc2VsZWN0ZWRQcm9wZXJ0aWVzOiBzdHJpbmdbXTtcclxuXHJcbiAgLy8gaSBkYXRpIGRlbGxlIHJpc3Bvc3RlIGRhIHN0YW1wYXJlXHJcbiAgZmlsdGVyZWRBbnN3ZXJzIC8vbGUgcmlzcG9zdGUgZmlsdHJhdGUgXHJcblxyXG4gIC8vIENvbG9ubmUgZGEgdmlzdWFsaXp6YXJlIChmaXNzYSBsYSBwcmltYSBjb2xvbm5hIGUgZ2VuZXJhIGRpbmFtaWNhbWVudGUgbGUgYWx0cmUpXHJcbiAgZGlzcGxheWVkQ29sdW1ucyA9IFtdO1xyXG5cclxuICAvLyNyZWdpb24gQ29uc3RydWN0b3JcclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgdXRpbGl0eUhlbHBlclNlcnZpY2U6IFV0aWxpdHlIZWxwZXJTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBjaGFuZ2VEZXRlY3RvcjogQ2hhbmdlRGV0ZWN0b3JSZWZcclxuICApIHtcclxuICAgIC8vIHRoaXMucHJvcGVydGllc0xhYmVsW1wiQW5zd2VyRGF0ZVwiXSA9IFwiRGF0YVwiO1xyXG4gIH1cclxuICAvLyNlbmRyZWdpb24gQ29uc3RydWN0b3JcclxuXHJcbiAgLy8jcmVnaW9uIG5nT25JbnRpdFxyXG4gIG5nT25Jbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5kZWZhdWx0TGlzdEFjdGlvbnMgPSB0aGlzLmNvbmZpZ3VyYXRpb25zLmRlZmF1bHRMaXN0QWN0aW9ucztcclxuICAgIHRoaXMuc2hvd1RpdGxlID0gdGhpcy5jb25maWd1cmF0aW9ucy5zaG93VGl0bGU7XHJcbiAgICBHbG9iYWxTZXJ2aWNlLmRlYnVnTG9nKCdsaXN0LWZvcm0tcmVjb3JkIC0gbmdPbkluaXQgLSBjb25maWd1cmF0aW9ucycsIHRoaXMuY29uZmlndXJhdGlvbnMpO1xyXG5cclxuICAgIHRoaXMuZ2V0Rm9ybUJ5SUQoKTtcclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIG5nT25JbnRpdFxyXG5cclxuICAvLyNyZWdpb24gbmdPbkNoYW5nZXNcclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XHJcbiAgICBHbG9iYWxTZXJ2aWNlLmRlYnVnTG9nKCdsaXN0LWZvcm0tcmVjb3JkIC0gY2hhbmdlcycsIGNoYW5nZXMpO1xyXG4gICAgLy8gU2UgdmllbmUgbW9kaWZpY2F0byBpbCB2YWxvcmUgZGkgXCJuZ01vZGVsSW5wdXRcIiBhbGxvcmEgYWdnaW9ybmEgbCdpbnB1dFxyXG4gICAgLy8gaWYgKGNoYW5nZXNbJ2NvbmZpZ3VyYXRpb25zJ10gIT0gdW5kZWZpbmVkICYmIGNoYW5nZXNbJ2NvbmZpZ3VyYXRpb25zJ10uZmlyc3RDaGFuZ2UgPT0gZmFsc2UpIHtcclxuICAgIC8vICAgdGhpcy5jb25maWd1cmF0aW9ucy52YWx1ZXMgPSBjaGFuZ2VzWydjb25maWd1cmF0aW9ucyddLmN1cnJlbnRWYWx1ZTtcclxuICAgIC8vICAgdGhpcy5yZWxvYWRUYWJsZXMoKTtcclxuICAgIC8vIH1cclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIG5nT25DaGFuZ2VzXHJcblxyXG4gIC8vI3JlZ2lvbiBnZXRGb3JtQnlJRFxyXG4gIGFzeW5jIGdldEZvcm1CeUlEKGlkOiBzdHJpbmcgPSB0aGlzLmZvcm1JRCkge1xyXG4gICAgR2xvYmFsU2VydmljZS5kZWJ1Z0xvZygnbGlzdC1mb3JtLXJlY29yZCAtIGdldEZvcm1CeUlEJywgdGhpcy5mb3JtKTtcclxuXHJcbiAgICBpZiAodGhpcy5mb3JtID09IG51bGwpIHtcclxuICAgICAgY29uc3QgZHluYW1pY01vZHVsZVBhcmFtczogQXJyYXk8RW5kUG9pbnREYXRhUGFyYW1zPiA9XHJcbiAgICAgICAgbmV3IEFycmF5PEVuZFBvaW50RGF0YVBhcmFtcz4oKTtcclxuICAgICAgZHluYW1pY01vZHVsZVBhcmFtcy5wdXNoKHtcclxuICAgICAgICBQYXJhbU5hbWU6IFwiaWRcIixcclxuICAgICAgICBQYXJhbVZhbHVlOiBpZCxcclxuICAgICAgICBQYXJhbVR5cGU6IFBhcmFtVHlwZUVudW1bXCJRdWVyeSBwYXJhbVwiXSxcclxuICAgICAgfSk7XHJcbiAgICAgIGF3YWl0IHRoaXMudXRpbGl0eUhlbHBlclNlcnZpY2UuUnVuRW5kUG9pbnRDYWxsKFxyXG4gICAgICAgIHRoaXMuZW5kUG9pbnRDb25maWd1cmF0aW9uLkZvcm1zLkdldEJ5SURFbmRQb2ludCxcclxuICAgICAgICBkeW5hbWljTW9kdWxlUGFyYW1zLFxyXG4gICAgICAgIChyZXM6IEZvcm0pID0+IHtcclxuICAgICAgICAgIHRoaXMuZm9ybSA9IHJlcztcclxuICAgICAgICAgIHRoaXMuY29uZmlndXJlQ29sdW1ucygpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgKGVycikgPT4geyB9XHJcbiAgICAgICk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmNvbmZpZ3VyZUNvbHVtbnMoKTtcclxuICAgIH1cclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIGdldEZvcm1CeUlEXHJcblxyXG4gIC8vI3JlZ2lvbiBnZXRSZWNvcmRzQnlGb3JtSURcclxuICAvKipcclxuICAgKiBNZXRvZG8gcGVyIHJlY3VwZXJhcmUgdHV0dGkgaSByZWNvcmQgc2FsdmF0aSBwZXIgdW5hIHBhcnRpY29sYXJlIEZvcm0uXHJcbiAgICogTGEgY2hpYW1hdGEgdmllbmUgZWZmZXR0dWF0YSBzb2xvIHNlIMOoIHN0YXRvIGNvbmZpZ3VyYXRvIGwnZW5kUG9pbnQgZGEgdXNhcmUuXHJcbiAgICogTGEgcmlzcG9zdGEgZGVsbGEgY2hpYW1hdGEgZGV2ZSBlc3NlcmUgdW4gYXJyYXkgZGkgb2dnZXR0aSBkaSB0aXBvIFwiRHluUmVjb3JkXCJcclxuICAgKiBhIHBhcnRpcmUgZGFpIHF1YWxpIHZlbmdvbm8gcmljcmVhdGkgaSBSZWNvcmQgdXNhdGkgbmVsIGNsaWVudC5cclxuICAgKi9cclxuICBhc3luYyBnZXRSZWNvcmRzQnlGb3JtSUQoKSB7XHJcbiAgICAvKipcclxuICAgICAqIHByZW5kZSBsZSByaXNwb3N0ZSBlIGxlIHJlbmRlIHBpYXR0ZSwgYWRhdHRlIGEgZGl2ZW50YXJlIHVuYSByaWdhIGRhIHRhYmVsbGFcclxuICAgICAqIG1ldHRlIHR1dHRlIGxlIHJpc3Bvc3RlIG5lbGxlIHN0cnV0dHVyZSBuZWNlc3NhcmllIHBlciBpbCByZWN1cGVybyBlIGxhIHZpc3VhbGl6emF6aW9uZVxyXG4gICAgICogQHBhcmFtIGFuc3dlcnMgXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IHJlYXJyYW5nZUFuc3dlcnNBbmRQb3B1bGF0ZUxpc3RzID0gKGFuc3dlcnMpID0+IHtcclxuICAgICAgdGhpcy5jb25maWd1cmF0aW9ucy52YWx1ZXMgPSBuZXcgQXJyYXk8UmVjb3JkPigpO1xyXG4gICAgICBhbnN3ZXJzLmZvckVhY2goKGFuc3dlcikgPT4ge1xyXG4gICAgICAgIHZhciB0bXBSZWM6IFJlY29yZCA9IG5ldyBSZWNvcmQoKTtcclxuICAgICAgICB0bXBSZWMgPSBKU09OLnBhcnNlKGFuc3dlci5TZXJpYWxpemVkVmFsdWVzKTtcclxuICAgICAgICB0bXBSZWMuSUQgPSBhbnN3ZXIuSUQ7XHJcbiAgICAgICAgdG1wUmVjLkVudElEID0gYW5zd2VyLkVudElEO1xyXG4gICAgICAgIHRtcFJlYy5WZXJzaW9uID0gYW5zd2VyLlZlcnNpb247XHJcbiAgICAgICAgdG1wUmVjLnVzZXJJRCA9IGFuc3dlci51c2VySUQ7XHJcbiAgICAgICAgdG1wUmVjLkFuc3dlckRhdGUgPSBhbnN3ZXIuQW5zd2VyRGF0ZTtcclxuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb25zLnZhbHVlcy5wdXNoKHRtcFJlYyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogcHJlcGFyYSBsYSBsaXN0YSBkZWxsZSBjb2xvbm5lIGRhIG1vc3RyYXJlICh1bmEgcGVyIG9nbmkgcmlzcG9zdGEsIHBpw7kgbGEgY29sb25uYSBkZWxsZSBwcm9wcmlldMOgKVxyXG4gICAgICogaW1wb3N0YSBsYSBsaXN0YSBkZWxsZSByaXNwb3N0ZSBkYSB2aXN1YWxpenphcmVcclxuICAgICAqIGxpYmVyYSBsZSB2YXJpYWJpbGkgZGkgY2FyaWNhbWVudG8gcGVyIG1vc3RyYXJlIGkgY29udGVudXRpIGRlbGxhIHZpc3RhXHJcbiAgICAgKi9cclxuICAgIGNvbnN0IG5hbWVDb2x1bW5zQW5kU3RhcnRWaWV3ID0gKCkgPT4ge1xyXG4gICAgICAvL2Rlc3RydXR0dXJhIGwnYXJyYXkgcmlzcG9zdGUgZSBwZXIgb2duaSByaXNwb3N0YSBnZW5lcmEgdW4gZWxlbWVudG8gY29sW2ldXHJcbiAgICAgIHRoaXMuZGlzcGxheWVkQ29sdW1ucyA9IFtcInByb3BlcnR5XCIsIC4uLnRoaXMuY29uZmlndXJhdGlvbnMudmFsdWVzLm1hcCgoXywgaSkgPT4gYGNvbCR7aX1gKV07XHJcbiAgICAgIHRoaXMuZmlsdGVyZWRBbnN3ZXJzID0gdGhpcy5jb25maWd1cmF0aW9ucy52YWx1ZXM7XHJcbiAgICAgIHRoaXMuc2V0TWluTWF4RGF0ZXMoKTtcclxuICAgICAgXHJcbiAgICAgIHRoaXMubG9hZGVkRmlsdGVycyA9IHRydWU7XHJcbiAgICAgIHRoaXMubG9hZGVkVGFibGUgPSB0cnVlO1xyXG4gICAgICBzZXRUaW1lb3V0KChfKSA9PiB7XHJcbiAgICAgICAgdGhpcy5jaGFuZ2VEZXRlY3Rvci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgIH0sIDApOyAvLyByZWZyZXNoIHVpXHJcbiAgICB9XHJcblxyXG4gICAgaWYodGhpcy5jb25maWd1cmF0aW9ucy52YWx1ZXMpe1xyXG4gICAgICAvLyB2ZW5nbyBkYSB1bidhbHRyYSB2aXN1YWxpenphemlvbmUgY2hlIGhhIGdpw6AgcmVjdXBlcmF0byBsZSByaXNwb3N0ZVxyXG4gICAgICBjb25zb2xlLmxvZyhcImhMaXN0IC0gZ2V0UmVjb3Jkc0J5Rm9ybUlEIEFcIiwgdGhpcy5jb25maWd1cmF0aW9ucylcclxuICAgICAgbmFtZUNvbHVtbnNBbmRTdGFydFZpZXcoKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIHNvbm8gaW4gdW5hIG51b3ZhIGlzdGFuemEgaW4gY3VpIGRldm8gcmVjdXBlcmFyZSBsZSByaXNwb3N0ZVxyXG4gICAgICBjb25zb2xlLmxvZyhcImhMaXN0IC0gZ2V0UmVjb3Jkc0J5Rm9ybUlEIEJcIiwgdGhpcy5jb25maWd1cmF0aW9ucylcclxuICAgICAgdHJ5IHtcclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICB0aGlzLmVuZFBvaW50Q29uZmlndXJhdGlvbiAmJlxyXG4gICAgICAgICAgdGhpcy5lbmRQb2ludENvbmZpZ3VyYXRpb24uUmVjb3JkcyAmJlxyXG4gICAgICAgICAgdGhpcy5lbmRQb2ludENvbmZpZ3VyYXRpb24uUmVjb3Jkcy5HZXRCeUZvcm1JREVuZFBvaW50XHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICBsZXQgZHluYW1pY01vZHVsZVBhcmFtcyA9IFtcclxuICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgIFBhcmFtTmFtZTogXCJFbnRJRFwiLFxyXG4gICAgICAgICAgICAgIFBhcmFtVmFsdWU6IHRoaXMuZm9ybS5JRCxcclxuICAgICAgICAgICAgICBQYXJhbVR5cGU6IFBhcmFtVHlwZUVudW1bXCJRdWVyeSBwYXJhbVwiXSxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgIF07XHJcbiAgICAgICAgICBpZiAodGhpcy5jb25maWd1cmF0aW9ucy51c2VySUQgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAvLyBub24gaG8gc3BlY2lmaWNhdG8gdW4gdXRlbnRlXHJcbiAgICAgICAgICAgIC8vIHZlZG8gdHV0dGUgbGUgcmlzcG9zdGUgZGVsIG1vZHVsb1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnV0aWxpdHlIZWxwZXJTZXJ2aWNlLlJ1bkVuZFBvaW50Q2FsbChcclxuICAgICAgICAgICAgICB0aGlzLmVuZFBvaW50Q29uZmlndXJhdGlvbi5SZWNvcmRzLkdldEJ5Rm9ybUlERW5kUG9pbnQsXHJcbiAgICAgICAgICAgICAgZHluYW1pY01vZHVsZVBhcmFtcyxcclxuICAgICAgICAgICAgICAocmVzOiBBcnJheTxEeW5SZWNvcmQ+KSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZWFycmFuZ2VBbnN3ZXJzQW5kUG9wdWxhdGVMaXN0cyhyZXMpO1xyXG4gICAgICAgICAgICAgICAgbmFtZUNvbHVtbnNBbmRTdGFydFZpZXcoKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBjb25vc2NvIGwndXRlbnRlXHJcbiAgICAgICAgICAgIC8vIHZvZ2xpbyBzb2xhbWVudGUgbGUgc3VlIHJpc3Bvc3RlXHJcbiAgICAgICAgICAgIGR5bmFtaWNNb2R1bGVQYXJhbXMucHVzaChcclxuICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICBQYXJhbU5hbWU6IFwiVXNlcklEXCIsXHJcbiAgICAgICAgICAgICAgICBQYXJhbVZhbHVlOiB0aGlzLmNvbmZpZ3VyYXRpb25zLnVzZXJJRCxcclxuICAgICAgICAgICAgICAgIFBhcmFtVHlwZTogUGFyYW1UeXBlRW51bVtcIlF1ZXJ5IHBhcmFtXCJdLFxyXG4gICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnV0aWxpdHlIZWxwZXJTZXJ2aWNlLlJ1bkVuZFBvaW50Q2FsbChcclxuICAgICAgICAgICAgICB0aGlzLmVuZFBvaW50Q29uZmlndXJhdGlvbi5SZWNvcmRzLkdldEFsbEJ5RW50QW5kVXNlcklERW5kUG9pbnQsXHJcbiAgICAgICAgICAgICAgZHluYW1pY01vZHVsZVBhcmFtcyxcclxuICAgICAgICAgICAgICAocmVzOiBBcnJheTxEeW5SZWNvcmQ+KSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZWFycmFuZ2VBbnN3ZXJzQW5kUG9wdWxhdGVMaXN0cyhyZXMpO1xyXG4gICAgICAgICAgICAgICAgbmFtZUNvbHVtbnNBbmRTdGFydFZpZXcoKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcignZXhjZXB0aW9uJywgZSlcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuICAvLyNlbmRyZWdpb24gZ2V0UmVjb3Jkc0J5Rm9ybUlEXHJcblxyXG5cclxuICAvLyNyZWdpb24gY29uZmlndXJlQ29sdW1uc1xyXG4gIC8qKlxyXG4gICAqIE1ldG9kbyBwZXIgY29uZmlndXJhcmUgbGUgY29sb25uZSBkZWxsYSBlcXAtdGFibGUuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjb25maWd1cmVDb2x1bW5zKCkge1xyXG4gICAgdGhpcy5jb2x1bW5zID0gW1xyXG4gICAgICB7XHJcbiAgICAgICAga2V5OiBcImFjdGlvblwiLFxyXG4gICAgICAgIGRpc3BsYXk6IFwiXCIsXHJcbiAgICAgICAgdHlwZTogVHlwZUNvbHVtbi5NZW51QWN0aW9uLFxyXG4gICAgICAgIGJ1dHRvbk1lbnVJY29uOiBcIm1vcmVfdmVydFwiLFxyXG4gICAgICAgIHN0eWxlczogeyBmbGV4OiBcIjAgMCA2JVwiIH0sXHJcbiAgICAgICAgYWN0aW9uczogW10sXHJcbiAgICAgIH0sXHJcbiAgICBdO1xyXG5cclxuICAgIGlmICh0aGlzLmRlZmF1bHRMaXN0QWN0aW9ucy52aWV3ID09IHRydWUpIHtcclxuICAgICAgdGhpcy5jb2x1bW5zXHJcbiAgICAgICAgLmZpbmQoKGMpID0+IGMua2V5ID09PSBcImFjdGlvblwiKVxyXG4gICAgICAgIC5hY3Rpb25zLnB1c2goe1xyXG4gICAgICAgICAgbmFtZTogXCJWaXN1YWxpenphXCIsXHJcbiAgICAgICAgICBpY29uOiBcImluZm9cIixcclxuICAgICAgICAgIGZuOiAoZWxlbWVudCwgaW5kZXgsIGNvbCkgPT4gdGhpcy52aWV3UmVjb3JkKGVsZW1lbnQpLFxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMuZGVmYXVsdExpc3RBY3Rpb25zLmVkaXQgPT0gdHJ1ZSkge1xyXG4gICAgICB0aGlzLmNvbHVtbnNcclxuICAgICAgICAuZmluZCgoYykgPT4gYy5rZXkgPT09IFwiYWN0aW9uXCIpXHJcbiAgICAgICAgLmFjdGlvbnMucHVzaCh7XHJcbiAgICAgICAgICBuYW1lOiBcIk1vZGlmaWNhXCIsXHJcbiAgICAgICAgICBpY29uOiBcImVkaXRcIixcclxuICAgICAgICAgIGZuOiAoZWxlbWVudCwgaW5kZXgsIGNvbCkgPT4gdGhpcy52aWV3T3JFZGl0UmVjb3JkKGVsZW1lbnQsIGZhbHNlKSxcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuICAgIGlmICh0aGlzLmRlZmF1bHRMaXN0QWN0aW9ucy5kdXBsaWNhdGUgPT0gdHJ1ZSkge1xyXG4gICAgICAvKnRoaXMuY29sdW1uc1xyXG4gICAgICAgIC5maW5kKChjKSA9PiBjLmtleSA9PT0gXCJhY3Rpb25cIilcclxuICAgICAgICAuYWN0aW9ucy5wdXNoKHtcclxuICAgICAgICAgIG5hbWU6IFwiRHVwbGljYVwiLFxyXG4gICAgICAgICAgaWNvbjogXCJmaWxlX2NvcHlcIixcclxuICAgICAgICAgIGZuOiAoZWxlbWVudCwgaW5kZXgsIGNvbCkgPT4gdGhpcy5kdXBsaWNhdGVSZWNvcmQoZWxlbWVudCksXHJcbiAgICAgICAgfSk7Ki9cclxuICAgIH1cclxuICAgIGlmICh0aGlzLmRlZmF1bHRMaXN0QWN0aW9ucy5kZWxldGUgPT0gdHJ1ZSkge1xyXG4gICAgICB0aGlzLmNvbHVtbnNcclxuICAgICAgICAuZmluZCgoYykgPT4gYy5rZXkgPT09IFwiYWN0aW9uXCIpXHJcbiAgICAgICAgLmFjdGlvbnMucHVzaCh7XHJcbiAgICAgICAgICBuYW1lOiBcIkVsaW1pbmFcIixcclxuICAgICAgICAgIGljb246IFwiZGVsZXRlXCIsXHJcbiAgICAgICAgICBmbjogKGVsZW1lbnQsIGluZGV4LCBjb2wpID0+IHRoaXMuZGVsZXRlUmVjb3JkKGVsZW1lbnQpLFxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZXh0ZXJuYWxCdXR0b25zLmZvckVhY2goKGJ1dHRvbikgPT4ge1xyXG4gICAgICB0aGlzLmNvbHVtbnNcclxuICAgICAgICAuZmluZCgoYykgPT4gYy5rZXkgPT09IFwiYWN0aW9uXCIpXHJcbiAgICAgICAgLmFjdGlvbnMucHVzaCh7XHJcbiAgICAgICAgICBuYW1lOiBidXR0b24udGV4dCxcclxuICAgICAgICAgIGljb246IGJ1dHRvbi5pY29uLFxyXG4gICAgICAgICAgZm46IChlbGVtZW50LCBpbmRleCwgY29sKSA9PiBidXR0b24uZm4oKSxcclxuICAgICAgICB9KTtcclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuY3JlYXRlQWRkaXRpb25hbEFjdGlvbnMoKTtcclxuICAgIHRoaXMuY3JlYXRlQ29sdW1uc0Zyb21Gb3JtRmllbGRzKCk7XHJcbiAgICB0aGlzLmdldFJlY29yZHNCeUZvcm1JRCgpO1xyXG4gIH1cclxuICAvLyNlbmRyZWdpb24gY29uZmlndXJlQ29sdW1uc1xyXG5cclxuICAvLyNyZWdpb24gY3JlYXRlQWRkaXRpb25hbEFjdGlvbnNcclxuICAvKipcclxuICAgKiBNZXRvZG8gcGVyIGFnZ2l1bmdlcmUgbmVsbGEgY29sb25uYSBcImFjdGlvblwiIGRlbGxhIGVxcC10YWJsZSBsZSBhemlvbmkgc3VpIHJlY29yZFxyXG4gICAqIGRlZmluaXRlIGRhbGwndXRlbnRlIGFsbCdpbnRlcm5vIGRlbGxhIEZvcm0uXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjcmVhdGVBZGRpdGlvbmFsQWN0aW9ucygpIHtcclxuICAgIEdsb2JhbFNlcnZpY2UuZGVidWdMb2coJ2xpc3QtZm9ybS1yZWNvcmQgLSBjcmVhdGVBZGRpdGlvbmFsQWN0aW9ucycsIHRoaXMuZm9ybSk7XHJcblxyXG4gICAgaWYgKHRoaXMuZm9ybS5BY3Rpb25zT25SZWNvcmQgJiYgdGhpcy5mb3JtLkFjdGlvbnNPblJlY29yZC5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuZm9ybS5BY3Rpb25zT25SZWNvcmQuc29ydCgoYSwgYikgPT5cclxuICAgICAgICBhLk9yZGluYWxQb3NpdGlvbiA+IGIuT3JkaW5hbFBvc2l0aW9uXHJcbiAgICAgICAgICA/IDFcclxuICAgICAgICAgIDogYi5PcmRpbmFsUG9zaXRpb24gPiBhLk9yZGluYWxQb3NpdGlvblxyXG4gICAgICAgICAgICA/IC0xXHJcbiAgICAgICAgICAgIDogMFxyXG4gICAgICApLmZvckVhY2goKGFjdGlvbikgPT4ge1xyXG4gICAgICAgIHRoaXMuY29sdW1uc1xyXG4gICAgICAgICAgLmZpbmQoKGMpID0+IGMua2V5ID09PSBcImFjdGlvblwiKVxyXG4gICAgICAgICAgLmFjdGlvbnMucHVzaCh7XHJcbiAgICAgICAgICAgIG5hbWU6IGFjdGlvbi5OYW1lLFxyXG4gICAgICAgICAgICBpY29uOiBhY3Rpb24uSWNvbixcclxuICAgICAgICAgICAgZm46IChlbGVtZW50LCBpbmRleCwgY29sKSA9PiB7XHJcbiAgICAgICAgICAgICAgY29uc3QgcmVjID0gZWxlbWVudDtcclxuICAgICAgICAgICAgICBjb25zdCBjdHggPSBVdGlsaXR5SGVscGVyU2VydmljZS5jb250ZXh0O1xyXG4gICAgICAgICAgICAgIGV2YWwoYWN0aW9uLkFjdGlvbik7XHJcbiAgICAgICAgICAgICAgLy8gVE9ETzogc2FsdmFyZSBsZSBtb2RpZmljaGVcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgIH0pO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIGNyZWF0ZUFkZGl0aW9uYWxBY3Rpb25zXHJcblxyXG5cclxuICAvLyNyZWdpb24gY3JlYXRlQ29sdW1uc0Zyb21Gb3JtRmllbGRzXHJcbiAgLyoqXHJcbiAgICogTWV0b2RvIHBlciBjcmVhcmUgbGEgY29uZmlndXJhemlvbmUgZGVsbGUgY29sb25uZSBwZXIgbGEgZXFwLXRhYmxlLlxyXG4gICAqIEluZGl2aWR1YSBpIEJhc2VGaWVsZCBkYSBtb3N0cmFyZSBlIGxpIHVzYSBwZXIgY3JlYXJlIGxlIENvbmZpZ0NvbHVtbi5cclxuICAgKiBMZSBjb2xvbm5lIHZlbmdvbm8gY3JlYXRlIHBlciBpIEJhc2VGaWVsZCBjb24gaWwgZmxhZyBJbkxpc3RWaWV3IGEgVFJVRVxyXG4gICAqIG9wcHVyZSwgbmVsIGNhc28gbm9uIHNpYW5vIHN0YXRpIHNwZWNpZmljYXRpIGkgY2FtcGkgZGEgdmlzdWFsaXp6YXJlLFxyXG4gICAqIHNlbGV6aW9uYSBpIHByaW1pIDYuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjcmVhdGVDb2x1bW5zRnJvbUZvcm1GaWVsZHMoKSB7XHJcbiAgICBHbG9iYWxTZXJ2aWNlLmRlYnVnTG9nKCdsaXN0LWZvcm0tcmVjb3JkIC0gY3JlYXRlQ29sdW1uc0Zyb21Gb3JtRmllbGRzJywgdGhpcy5mb3JtKTtcclxuXHJcbiAgICB2YXIgZmllbGRzRm9yQ29sdW1uczogQXJyYXk8QmFzZUZpZWxkPjtcclxuICAgIGZpZWxkc0ZvckNvbHVtbnMgPSB0aGlzLmZvcm0uRmllbGRzLmZpbHRlcigoZikgPT4ge1xyXG4gICAgICBpZiAoZi5BbnN3ZXJTdHlsZSl7XHJcbiAgICAgICAgcmV0dXJuIGYuQW5zd2VyU3R5bGUuSW5MaXN0Vmlld1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiBmLkluTGlzdFZpZXc7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgZmllbGRzRm9yQ29sdW1uc1xyXG4gICAgICAuc29ydCgoYSwgYikgPT5cclxuICAgICAgICBhLk9yZGluYWxQb3NpdGlvbiA+IGIuT3JkaW5hbFBvc2l0aW9uXHJcbiAgICAgICAgICA/IDFcclxuICAgICAgICAgIDogYi5PcmRpbmFsUG9zaXRpb24gPiBhLk9yZGluYWxQb3NpdGlvblxyXG4gICAgICAgICAgICA/IC0xXHJcbiAgICAgICAgICAgIDogMFxyXG4gICAgICApXHJcbiAgICAgIC5mb3JFYWNoKChmaWVsZCkgPT4ge1xyXG4gICAgICAgIHRoaXMuY29sdW1ucy5wdXNoKHRoaXMuY3JlYXRlRmllbGRDb2x1bW4oZmllbGQpKTtcclxuICAgICAgICB0aGlzLnByb3BlcnRpZXMucHVzaChmaWVsZC5MYWJlbCk7XHJcbiAgICAgICAgdGhpcy5wcm9wZXJ0aWVzTGFiZWxbZmllbGQuTGFiZWxdID0gKGZpZWxkLkRlc2NyaXB0aW9uKTtcclxuICAgICAgfSk7XHJcbiAgICB0aGlzLnNlbGVjdGVkUHJvcGVydGllcyA9IHRoaXMucHJvcGVydGllcztcclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIGNyZWF0ZUNvbHVtbnNGcm9tRm9ybUZpZWxkc1xyXG5cclxuICAvLyNyZWdpb24gY3JlYXRlRmllbGRDb2x1bW5cclxuICAvKipcclxuICAgKiBNZXRvZG8gcGVyIGNyZWFyZSBsJ29nZ2V0dG8gQ29uZmlndXJlQ29sdW1uIGNoZSByYXBwcmVzZW50YSBpbCBCYXNlRmllbGQgcGFzc2F0byBpbiBpbnB1dC5cclxuICAgKiBAcGFyYW0gZmllbGQgQmFzZUZpZWxkIHBlciBjdWkgY3JlYXJlIGxhIGNvbG9ubmEgbmVsbGEgZXFwLXRhYmxlXHJcbiAgICogQHJldHVybnMgUmVzdGl0dWlzY2UgdW5hIENvbmZpZ0NvbHVtbiBwZXIgbGEgZXFwLXRhYmxlXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjcmVhdGVGaWVsZENvbHVtbihmaWVsZDogQmFzZUZpZWxkKTogQ29uZmlnQ29sdW1uIHtcclxuICAgIHZhciBjb2x1bW46IENvbmZpZ0NvbHVtbiA9IHsga2V5OiBmaWVsZC5OYW1lLCBkaXNwbGF5OiBmaWVsZC5MYWJlbCB9O1xyXG4gICAgc3dpdGNoIChmaWVsZC5GaWVsZFR5cGUpIHtcclxuICAgICAgY2FzZSBGaWVsZFR5cGVFbnVtW1wiQm9vbGVhbm9cIl06XHJcbiAgICAgICAgY29sdW1uLnR5cGUgPSBUeXBlQ29sdW1uLkJvb2xlYW47XHJcbiAgICAgICAgY29sdW1uLmJvb2xlYW5WYWx1ZXMgPSB7XHJcbiAgICAgICAgICBmYWxzZTogJzxpIGNsYXNzPVwiZmEgZmEtdGltZXMgZXJyb3ItY29sb3JcIj48L2k+JyxcclxuICAgICAgICAgIHRydWU6ICc8aSBjbGFzcz1cImZhIGZhLWNoZWNrIHN1Y2Nlc3MtY29sb3JcIj48L2k+JyxcclxuICAgICAgICB9O1xyXG4gICAgICAgIGNvbHVtbi5zdHlsZXMgPSB7XHJcbiAgICAgICAgICBmbGV4OiBcIjAgMCA3JVwiLFxyXG4gICAgICAgICAgY2VsbEFsaWdubWVudDogQ2VsbEFsaWdubWVudEVudW0uQ0VOVEVSLFxyXG4gICAgICAgIH07XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgRmllbGRUeXBlRW51bVtcIkRhdGEgZS9vIG9yYVwiXTpcclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICAoZmllbGQgYXMgRGF0ZUZpZWxkKS5Jc09ubHlEYXRlICE9IERhdGVUaW1lVHlwZUVudW1bXCJTb2xvIG9yYXJpb1wiXVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgY29sdW1uLnR5cGUgPSBUeXBlQ29sdW1uLkRhdGU7XHJcbiAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgIChmaWVsZCBhcyBEYXRlRmllbGQpLklzT25seURhdGUgPT0gRGF0ZVRpbWVUeXBlRW51bVtcIkRhdGEgZSBvcmFcIl1cclxuICAgICAgICAgICkge1xyXG4gICAgICAgICAgICBjb2x1bW4uZm9ybWF0ID0gXCJkZC9NTS95eXl5IEhIOm1tXCI7XHJcbiAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAoZmllbGQgYXMgRGF0ZUZpZWxkKS5Jc09ubHlEYXRlID09IERhdGVUaW1lVHlwZUVudW1bXCJTb2xvIGRhdGFcIl1cclxuICAgICAgICAgICkge1xyXG4gICAgICAgICAgICBjb2x1bW4uZm9ybWF0ID0gKGZpZWxkIGFzIERhdGVGaWVsZCkuRGF0ZUZvcm1hdFxyXG4gICAgICAgICAgICAgID8gKGZpZWxkIGFzIERhdGVGaWVsZCkuRGF0ZUZvcm1hdC5yZXBsYWNlKFwiRERcIiwgXCJkZFwiKVxyXG4gICAgICAgICAgICAgIDogXCJkZC9NTS95eXl5XCI7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIEZpZWxkVHlwZUVudW1bXCJDYW1wbyBudW1lcmljb1wiXTpcclxuICAgICAgICBpZiAoKGZpZWxkIGFzIE51bWVyaWNGaWVsZCkuQ3VycmVuY3lTeW1ib2wpIHtcclxuICAgICAgICAgIGNvbHVtbi5udW1iZXJQaXBlID0gTnVtYmVyQ29sdW1uUGlwZS5DVVJSRU5DWTtcclxuICAgICAgICAgIGNvbHVtbi5jdXJyZW5jeVBpcGVDb2RlID0gKGZpZWxkIGFzIE51bWVyaWNGaWVsZCkuQ3VycmVuY3lTeW1ib2w7XHJcbiAgICAgICAgfSBlbHNlIGlmICghKGZpZWxkIGFzIE51bWVyaWNGaWVsZCkuSXNJbnRlZ2VyKSB7XHJcbiAgICAgICAgICBjb2x1bW4ubnVtYmVyUGlwZSA9IE51bWJlckNvbHVtblBpcGUuREVDSU1BTDtcclxuICAgICAgICB9XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIGNhc2UgRmllbGRUeXBlRW51bVtcIkFsbGVnYXRvXCJdOlxyXG4gICAgICBjYXNlIEZpZWxkVHlwZUVudW1bXCJJbW1hZ2luZVwiXTpcclxuXHJcbiAgICAgICAgLypcclxuICAgICAgICAgIGNvbHVtbi52YWx1ZSA9IChlbGVtZW50OiBSZWNvcmQpID0+IHtcclxuICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgIChmaWVsZCBhcyBBdHRhY2htZW50RmllbGQpLklzTXVsdGlBdHRhY2ggfHxcclxuICAgICAgICAgICAgICAoKGZpZWxkIGFzIEltYWdlRmllbGQpLkF0dGFjaERlZmluaXRpb24gJiZcclxuICAgICAgICAgICAgICAgIChmaWVsZCBhcyBJbWFnZUZpZWxkKS5BdHRhY2hEZWZpbml0aW9uLklzTXVsdGlBdHRhY2gpXHJcbiAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgIHJldHVybiBlbGVtZW50W2ZpZWxkLk5hbWVdICE9IG51bGwgJiYgZWxlbWVudFtmaWVsZC5OYW1lXS5sZW5ndGggPiAwXHJcbiAgICAgICAgICAgICAgICA/IChlbGVtZW50W2ZpZWxkLk5hbWVdIGFzIEFycmF5PElBdHRhY2htZW50RFRPPilcclxuICAgICAgICAgICAgICAgICAgICAubWFwKChhKSA9PiBhLkZpbGVOYW1lKVxyXG4gICAgICAgICAgICAgICAgICAgIC5qb2luKFwiLCBcIilcclxuICAgICAgICAgICAgICAgIDogbnVsbDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICByZXR1cm4gZWxlbWVudFtmaWVsZC5OYW1lXSAhPSBudWxsICYmIGVsZW1lbnRbZmllbGQuTmFtZV0ubGVuZ3RoID4gMFxyXG4gICAgICAgICAgICAgICAgPyAoZWxlbWVudFtmaWVsZC5OYW1lXSBhcyBBcnJheTxJQXR0YWNobWVudERUTz4pWzBdLkZpbGVOYW1lXHJcbiAgICAgICAgICAgICAgICA6IG51bGw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH07XHJcbiAgICAgICAgICBjb2x1bW4uaXNTb3J0YWJsZSA9IGZhbHNlO1xyXG4gICAgICAgICAgY29sdW1uLmlzU2VhcmNoYWJsZSA9IGZhbHNlO1xyXG4gICAgICAgICovXHJcblxyXG4gICAgICAgIGJyZWFrO1xyXG4gICAgICBjYXNlIEZpZWxkVHlwZUVudW1bXCJFbGVuY28gZ2VuZXJpY29cIl06XHJcbiAgICAgICAgY29sdW1uLnZhbHVlID0gKGVsZW1lbnQ6IFJlY29yZCkgPT4ge1xyXG4gICAgICAgICAgaWYgKChmaWVsZCBhcyBMaXN0VmFsdWVGaWVsZCkuSXNNdWx0aUNob2ljaGUpIHtcclxuICAgICAgICAgICAgaWYgKCFlbGVtZW50W2ZpZWxkLk5hbWVdIHx8IGVsZW1lbnRbZmllbGQuTmFtZV0ubGVuZ3RoID09IDApIHtcclxuICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICByZXR1cm4gT2JqZWN0LmtleXMoKGZpZWxkIGFzIExpc3RWYWx1ZUZpZWxkKS5WYWx1ZVBhaXJzKVxyXG4gICAgICAgICAgICAgICAgLmZpbHRlcigoaykgPT5cclxuICAgICAgICAgICAgICAgICAgZWxlbWVudFtmaWVsZC5OYW1lXS5pbmNsdWRlcyhcclxuICAgICAgICAgICAgICAgICAgICAoZmllbGQgYXMgTGlzdFZhbHVlRmllbGQpLlZhbHVlUGFpcnNba11cclxuICAgICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgLmpvaW4oXCIsIFwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKChmaWVsZCBhcyBMaXN0VmFsdWVGaWVsZCkuVmFsdWVQYWlycykuZmluZChcclxuICAgICAgICAgICAgICAoaykgPT5cclxuICAgICAgICAgICAgICAgIChmaWVsZCBhcyBMaXN0VmFsdWVGaWVsZCkuVmFsdWVQYWlyc1trXSA9PSBlbGVtZW50W2ZpZWxkLk5hbWVdXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb2x1bW4uaXNTb3J0YWJsZSA9IGZhbHNlO1xyXG4gICAgICAgIGNvbHVtbi5pc1NlYXJjaGFibGUgPSBmYWxzZTtcclxuICAgICAgICBicmVhaztcclxuICAgICAgY2FzZSBGaWVsZFR5cGVFbnVtW1wiTG9va3VwXCJdOlxyXG4gICAgICAgIC8vIFRPRE9cclxuICAgICAgICBicmVhaztcclxuICAgIH1cclxuICAgIHJldHVybiBjb2x1bW47XHJcbiAgfVxyXG4gIC8vI2VuZHJlZ2lvbiBjcmVhdGVGaWVsZENvbHVtblxyXG5cclxuICAvLyNyZWdpb24gdmlld1JlY29yZFxyXG4gIHZpZXdSZWNvcmQocmVjb3JkOiBSZWNvcmQpIHtcclxuICAgIHRoaXMub25WaWV3UmVjb3JkLmVtaXQocmVjb3JkKTtcclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIHZpZXdSZWNvcmRcclxuXHJcbiAgLyoqXHJcbiAgICogTWV0b2RvIGNoZSBzY2F0ZW5hIGwnZXZlbnRvIGRpIE91dHB1dCBwZXIgbW9zdHJhcmUgbyBtb2RpZmljYXJlIGlsIHJlY29yZFxyXG4gICAqIHNlbGV6aW9uYXRvIHN1bGxhIGVxcC10YWJsZS5cclxuICAgKiBAcGFyYW0gcmVjb3JkIFJlY29yZCBkYSB2aXN1YWxpenphcmUgbyBtb2RpZmljYXJlIHNlbGV6aW9uYXRvIHN1bGxhIGVxcC10YWJsZS5cclxuICAgKiBAcGFyYW0gb25seVZpZXcgU2UgVFJVRSB2aWVuZSBtb3N0cmF0byBpbCBjb21wb25lbnRlIGFkZC1mb3JtLXJlY29yZCBpbiBzb2xhIGxldHR1cmEuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSB2aWV3T3JFZGl0UmVjb3JkKHJlY29yZDogUmVjb3JkLCBvbmx5VmlldzogYm9vbGVhbikge1xyXG4gICAgdGhpcy5vbkFkZFZpZXdFZGl0UmVjb3JkLmVtaXQoeyByZWNvcmQsIG9ubHlWaWV3IH0pO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogTWV0b2RvIHBlciBlbGltaW5hcmUgdW4gcmVjb3JkIGRhbGxhIGxpc3RhLlxyXG4gICAqIEBwYXJhbSByZWNvcmQgUmVjb3JkIGRhIGVsaW1pbmFyZSBzZWxlemlvbmF0byBzdWxsYSBlcXAtdGFibGUuXHJcbiAgICovXHJcbiAgZGVsZXRlUmVjb3JkKHJlY29yZDogUmVjb3JkKSB7XHJcbiAgICB0aGlzLm9uRGVsZXRlUmVjb3JkLmVtaXQocmVjb3JkKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIE1ldG9kbyBwZXIgcmljYXJpY2FyZSBpIGRhdGkgZGVsbGEgZXFwLXRhYmxlLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcmVsb2FkVGFibGVzKCkge1xyXG4gICAgaWYgKHRoaXMudGFibGVSZWNvcmRzKSB7XHJcbiAgICAgIHRoaXMudGFibGVSZWNvcmRzLnJlbG9hZERhdGF0YWJsZSgpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIG9uU2VsZWN0aW9uQ2hhbmdlXHJcbiAgLyoqXHJcbiAgICogRnVuemlvbmUgY2hlIHZpZW5lIGNoaWFtYXRhIGFsIGNhbWJpbyBkaSBzZWxlemlvbmUgZGVpIHBhcmFtZXRyaSBkYSBtb3N0cmFyZVxyXG4gICAqIGFnZ2lvcm5hIGxhIGxpc3RhIGRlbGxlIHByb3ByaWV0w6Agc2VsZXppb25hdGUgY2hlIGdlc3Rpc2NlIGxlIHJpZ2hlIG1vc3RyYXRlIHBlciBvZ25pIHJpc3Bvc3RhXHJcbiAgICogQHBhcmFtIHNlbGVjdGVkUHJvcGVydGllcyBcclxuICAgKi9cclxuICBvblNlbGVjdGlvbkNoYW5nZShzZWxlY3RlZFByb3BlcnRpZXMpIHtcclxuICAgIGNvbnNvbGUubG9nKHNlbGVjdGVkUHJvcGVydGllcy52YWx1ZSk7XHJcbiAgICBpZiAoc2VsZWN0ZWRQcm9wZXJ0aWVzLnZhbHVlLmxlbmd0aCA+IDApIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZFByb3BlcnRpZXMgPSBzZWxlY3RlZFByb3BlcnRpZXMudmFsdWU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkUHJvcGVydGllcyA9IHRoaXMucHJvcGVydGllcztcclxuICAgIH1cclxuICAgIGNvbnNvbGUubG9nKHRoaXMuc2VsZWN0ZWRQcm9wZXJ0aWVzKTtcclxuICB9XHJcbiAgLy8jZW5kcmVnaW9uIG9uU2VsZWN0aW9uQ2hhbmdlXHJcblxyXG4gIGZpbHRlckRhdGFBbnN3ZXJzKCkge1xyXG5cclxuICAgIC8vIHRoaXMubG9hZGVkVGFibGUgPSBmYWxzZTtcclxuXHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy5maWx0ZXJlZEFuc3dlcnMgPSBbXTtcclxuXHJcbiAgICAgIHRoaXMubWF4RGF0ZS5zZXRIb3VycygyMywgNTksIDU5LCA1OSk7XHJcblxyXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb25zLnZhbHVlcy5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIGlmIChuZXcgRGF0ZSh2YWx1ZS5BbnN3ZXJEYXRlKSA+PSB0aGlzLm1pbkRhdGUgJiYgbmV3IERhdGUodmFsdWUuQW5zd2VyRGF0ZSkgPD0gdGhpcy5tYXhEYXRlKSB7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIHRoaXMuZmlsdGVyZWRBbnN3ZXJzLnB1c2godmFsdWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICAgIHRoaXMuZGlzcGxheWVkQ29sdW1ucyA9IFtcInByb3BlcnR5XCIsIC4uLnRoaXMuZmlsdGVyZWRBbnN3ZXJzLm1hcCgoXywgaSkgPT4gYGNvbCR7aX1gKV07XHJcblxyXG4gICAgICAvLyB0aGlzLmxvYWRlZFRhYmxlID0gdHJ1ZTtcclxuXHJcbiAgICB9LCAxMDApO1xyXG4gIH1cclxuXHJcbiAgLy8gRnVuemlvbmUgcGVyIG90dGVuZXJlIGxhIGRhdGEgcGnDuSByZWNlbnRlIGUgcXVlbGxhIHBpw7kgdmVjY2hpYVxyXG4gIHNldE1pbk1heERhdGVzKCkge1xyXG4gICAgLy8gQ29udmVydG8gbGUgZGF0ZSBkaSBBbnN3ZXJEYXRlIGluIG9nZ2V0dGkgRGF0ZSBlIG9yZGlub1xyXG4gICAgY29uc3QgZGF0ZXMgPSB0aGlzLmNvbmZpZ3VyYXRpb25zLnZhbHVlcy5tYXAodmFsdWUgPT4gbmV3IERhdGUodmFsdWUuQW5zd2VyRGF0ZSkpO1xyXG5cclxuICAgIC8vIFRyb3ZvIGxhIGRhdGEgcGnDuSByZWNlbnRlIChtYXgpIGUgbGEgcGnDuSB2ZWNjaGlhIChtaW4pXHJcbiAgICB0aGlzLm1pbkRhdGUgPSBuZXcgRGF0ZShNYXRoLm1pbiguLi5kYXRlcy5tYXAoZGF0ZSA9PiBkYXRlLmdldFRpbWUoKSkpKTtcclxuICAgIHRoaXMubWF4RGF0ZSA9IG5ldyBEYXRlKE1hdGgubWF4KC4uLmRhdGVzLm1hcChkYXRlID0+IGRhdGUuZ2V0VGltZSgpKSkpO1xyXG4gIH1cclxufVxyXG4iLCI8bWF0LWNhcmQgY2xhc3M9XCJsaXN0LWZvcm0tcmVjb3JkXCI+XHJcbiAgPG1hdC1jYXJkLWhlYWRlciBjbGFzcz1cImFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlblwiPlxyXG4gICAgPG1hdC1jYXJkLXRpdGxlICpuZ0lmPVwibG9hZGVkRmlsdGVycyAmJiBzaG93VGl0bGVcIlxyXG4gICAgICA+RWxlbmNvIHt7IGZvcm0uTmFtZSB9fTwvbWF0LWNhcmQtdGl0bGVcclxuICAgID5cclxuICAgIDwhLS0gPG1hdC1jYXJkLWFjdGlvbnM+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeVwiXHJcbiAgICAgICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgIChjbGljayk9XCJvbkFkZFZpZXdFZGl0UmVjb3JkLmVtaXQobnVsbClcIlxyXG4gICAgICA+XHJcbiAgICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+XHJcbiAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkFnZ2l1bmdpPC9zcGFuPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvbWF0LWNhcmQtYWN0aW9ucz4gLS0+XHJcbiAgPC9tYXQtY2FyZC1oZWFkZXI+XHJcbiAgPG1hdC1jYXJkLWNvbnRlbnQ+XHJcbiAgICA8IS0tI3JlZ2lvbiBGSUxURVJTIC0tPlxyXG4gICAgPGRpdiBjbGFzcz1cInJvd1wiICpuZ0lmPVwibG9hZGVkRmlsdGVyc1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEyIGNvbC1tZC0zXCI+XHJcbiAgICAgICAgPHRtdy1kYXRldGltZXBpY2tlclxyXG4gICAgICAgICAgY2xhc3M9XCJkYXRlXCJcclxuICAgICAgICAgIFtwbGFjZWhvbGRlcl09XCInUGVyaW9kbyBpbml6aW8nXCJcclxuICAgICAgICAgIFtsYWJlbF09XCInUGVyaW9kbyBpbml6aW8nXCJcclxuICAgICAgICAgIFsobmdNb2RlbElucHV0KV09XCJtaW5EYXRlXCJcclxuICAgICAgICAgIChuZ01vZGVsSW5wdXRDaGFuZ2UpPVwiZmlsdGVyRGF0YUFuc3dlcnMoKVwiXHJcbiAgICAgICAgICBbcGlja2VyTW9kZV09XCJtb2Rlcy5EQVRFUElDS0VSXCJcclxuICAgICAgICAgIFtvdXRwdXRGb3JtYXRdPVwiJ0REL01NL1lZWVknXCJcclxuICAgICAgICAgIFtzaG93U2Vjb25kc109XCJmYWxzZVwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgIDwvdG13LWRhdGV0aW1lcGlja2VyPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMiBjb2wtbWQtM1wiPlxyXG4gICAgICAgIDx0bXctZGF0ZXRpbWVwaWNrZXJcclxuICAgICAgICAgIGNsYXNzPVwiZGF0ZVwiXHJcbiAgICAgICAgICBbcGxhY2Vob2xkZXJdPVwiJ1BlcmlvZG8gZmluZSdcIlxyXG4gICAgICAgICAgW2xhYmVsXT1cIidQZXJpb2RvIGZpbmUnXCJcclxuICAgICAgICAgIFsobmdNb2RlbElucHV0KV09XCJtYXhEYXRlXCJcclxuICAgICAgICAgIChuZ01vZGVsSW5wdXRDaGFuZ2UpPVwiZmlsdGVyRGF0YUFuc3dlcnMoKVwiXHJcbiAgICAgICAgICBbcGlja2VyTW9kZV09XCJtb2Rlcy5EQVRFUElDS0VSXCJcclxuICAgICAgICAgIFtvdXRwdXRGb3JtYXRdPVwiJ0REL01NL1lZWVknXCJcclxuICAgICAgICAgIFtzaG93U2Vjb25kc109XCJmYWxzZVwiXHJcbiAgICAgICAgPlxyXG4gICAgICAgIDwvdG13LWRhdGV0aW1lcGlja2VyPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMiBjb2wtbWQtMyBtdC0yXCI+XHJcbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5TZWxlemlvbmUgZGVpIGNhbXBpPC9tYXQtbGFiZWw+XHJcbiAgICAgICAgICA8bWF0LXNlbGVjdCAoc2VsZWN0aW9uQ2hhbmdlKT1cIm9uU2VsZWN0aW9uQ2hhbmdlKCRldmVudClcIiBtdWx0aXBsZT5cclxuICAgICAgICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IHByb3BlcnR5IG9mIHByb3BlcnRpZXNcIiBbdmFsdWVdPVwicHJvcGVydHlcIj5cclxuICAgICAgICAgICAgICB7eyBwcm9wZXJ0aWVzTGFiZWxbcHJvcGVydHldIH19XHJcbiAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cclxuICAgICAgICAgIDwvbWF0LXNlbGVjdD5cclxuICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPCEtLSA8ZGl2IGNsYXNzPVwiY29sLXNtLTEyIGNvbC1tZC0zIG10LTJcIj5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwiXHJcbiAgICAgICAgICAgIHNlbGVjdGVkUHJvcGVydGllcyA9PSBudWxsIHx8IHNlbGVjdGVkUHJvcGVydGllcy5sZW5ndGggPT0gMFxyXG4gICAgICAgICAgXCJcclxuICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1ncmFwaC1nZW5lcmF0ZSBidXR0b24tbmV4dCBtZS0yXCJcclxuICAgICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgICAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cImZpbHRlckRhdGFBbnN3ZXJzKClcIlxyXG4gICAgICAgID5cclxuICAgICAgICAgIEdlbmVyYVxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj4gLS0+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0jZW5kcmVnaW9uIEZJTFRFUlMgLS0+XHJcblxyXG4gICAgPCEtLSNyZWdpb24gVEFCTEUgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwidGFibGUtY29udGFpbmVyXCI+XHJcbiAgICAgIDx0YWJsZVxyXG4gICAgICAgIG1hdC10YWJsZVxyXG4gICAgICAgIFtkYXRhU291cmNlXT1cInNlbGVjdGVkUHJvcGVydGllc1wiXHJcbiAgICAgICAgY2xhc3M9XCJtYXQtZWxldmF0aW9uLXo4IG1hdC10YWJsZS1maXhlZFwiXHJcbiAgICAgID5cclxuICAgICAgICA8IS0tIENvbG9ubmEgZmlzc2EgcGVyIGxlIHByb3ByaWV0w6AgLS0+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciBtYXRDb2x1bW5EZWY9XCJwcm9wZXJ0eVwiIHN0aWNreT5cclxuICAgICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWYgY2xhc3M9XCJzdGlja3ktY29sdW1uXCI+XHJcbiAgICAgICAgICAgIERhdGEgSW5zZXJpbWVudG9cclxuICAgICAgICAgIDwvdGg+XHJcbiAgICAgICAgICA8dGRcclxuICAgICAgICAgICAgbWF0LWNlbGxcclxuICAgICAgICAgICAgKm1hdENlbGxEZWY9XCJsZXQgc2VsZWN0ZWRQcm9wZXJ0aWVzXCJcclxuICAgICAgICAgICAgY2xhc3M9XCJzdGlja3ktY29sdW1uXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAge3sgcHJvcGVydGllc0xhYmVsW3NlbGVjdGVkUHJvcGVydGllc10gfX1cclxuICAgICAgICAgIDwvdGQ+XHJcbiAgICAgICAgPC9uZy1jb250YWluZXI+XHJcblxyXG4gICAgICAgIDwhLS0gR2VuZXJhIGRpbmFtaWNhbWVudGUgbGUgY29sb25uZSBwZXIgb2duaSByaXNwb3N0YSAtLT5cclxuICAgICAgICA8bmctY29udGFpbmVyXHJcbiAgICAgICAgICAqbmdGb3I9XCJsZXQgdmFsdWUgb2YgZmlsdGVyZWRBbnN3ZXJzOyBsZXQgaSA9IGluZGV4XCJcclxuICAgICAgICAgIFttYXRDb2x1bW5EZWZdPVwiJ2NvbCcgKyBpXCJcclxuICAgICAgICA+XHJcbiAgICAgICAgICA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPlxyXG4gICAgICAgICAgICB7eyB2YWx1ZS5BbnN3ZXJEYXRlIHwgZGF0ZSA6IFwiZGQvTU0veXl5eSBISDptbVwiIH19XHJcbiAgICAgICAgICA8L3RoPlxyXG4gICAgICAgICAgPCEtLSA8dGggbWF0LWhlYWRlci1jZWxsICptYXRIZWFkZXJDZWxsRGVmPiB7eyB2YWx1ZS5BbnN3ZXJEYXRlIHwgZGF0ZTonZGQvTU0veXl5eSBISDptbScgfX0gPC90aD4gLS0+XHJcbiAgICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgc2VsZWN0ZWRQcm9wZXJ0aWVzXCI+XHJcbiAgICAgICAgICAgIHt7XHJcbiAgICAgICAgICAgICAgc2VsZWN0ZWRQcm9wZXJ0aWVzID09PSBcIkFuc3dlckRhdGVcIlxyXG4gICAgICAgICAgICAgICAgPyAodmFsdWUuQW5zd2VyRGF0ZSB8IGRhdGUgOiBcImRkL01NL3l5eXkgSEg6bW1cIilcclxuICAgICAgICAgICAgICAgIDogdmFsdWVbc2VsZWN0ZWRQcm9wZXJ0aWVzXSA/PyBcIk4vQVwiXHJcbiAgICAgICAgICAgIH19XHJcbiAgICAgICAgICA8L3RkPlxyXG4gICAgICAgIDwvbmctY29udGFpbmVyPlxyXG5cclxuICAgICAgICA8IS0tIEhlYWRlciBkZWxsYSB0YWJlbGxhIC0tPlxyXG4gICAgICAgIDx0ciBtYXQtaGVhZGVyLXJvdyAqbWF0SGVhZGVyUm93RGVmPVwiZGlzcGxheWVkQ29sdW1uc1wiPjwvdHI+XHJcblxyXG4gICAgICAgIDwhLS0gUmlnaGUgZGVsbGEgdGFiZWxsYSAtLT5cclxuICAgICAgICA8dHIgbWF0LXJvdyAqbWF0Um93RGVmPVwibGV0IHJvdzsgY29sdW1uczogZGlzcGxheWVkQ29sdW1uc1wiPjwvdHI+XHJcbiAgICAgIDwvdGFibGU+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0jcmVnaW9uIFRBQkxFIC0tPlxyXG4gIDwvbWF0LWNhcmQtY29udGVudD5cclxuICA8bWF0LWNhcmQtZm9vdGVyPlxyXG4gICAgPCEtLSA8bWF0LXByb2dyZXNzLWJhciBtb2RlPVwiaW5kZXRlcm1pbmF0ZVwiPjwvbWF0LXByb2dyZXNzLWJhcj4gLS0+XHJcbiAgPC9tYXQtY2FyZC1mb290ZXI+XHJcbjwvbWF0LWNhcmQ+XHJcblxyXG48IS0tIDxkaXYgY2xhc3M9XCJyb3cgZXFwLWR5bmFtaWMtbW9kdWxlLXRpdGxlIGxpc3QtZm9ybS1yZWNvcmQtaGVhZGVyXCI+XHJcbiAgPGRpdiBjbGFzcz1cImNvbC1tZC02XCI+XHJcbiAgICA8aDQgKm5nSWY9XCJzaG93VGl0bGVcIj5cclxuICAgICAgPGI+RWxlbmNvIHt7IGZvcm0uTmFtZSB9fTwvYj5cclxuICAgIDwvaDQ+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cImNvbC1tZC02IHRleHQtcmlnaHRcIiAqbmdJZj1cImRlZmF1bHRMaXN0QWN0aW9ucy5hZGRcIj5cclxuICAgIDxidXR0b24gY2xhc3M9XCJidG4gYnRuLXByaW1hcnlcIiBtYXQtcmFpc2VkLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgKGNsaWNrKT1cIm9uQWRkVmlld0VkaXRSZWNvcmQuZW1pdChudWxsKVwiPlxyXG4gICAgICA8bWF0LWljb24+YWRkPC9tYXQtaWNvbj5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkFnZ2l1bmdpPC9zcGFuPlxyXG4gICAgPC9idXR0b24+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuPGVxcC10YWJsZSBjbGFzcz1cImxpc3QtZm9ybS1yZWNvcmQtdGFibGVcIiAjdGFibGVSZWNvcmRzICpuZ0lmPVwibG9hZGVyICYmIGNvbmZpZ3VyYXRpb25zLnZhbHVlc1wiXHJcbiAgW2RhdGFdPVwiY29uZmlndXJhdGlvbnMudmFsdWVzXCIgW2NvbHVtbnNdPVwiY29sdW1uc1wiPjwvZXFwLXRhYmxlPiAtLT5cclxuIl19