@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.
- package/esm2020/lib/components/exported/eqp-dynamic-module/eqp-dynamic-module.component.mjs +11 -10
- package/esm2020/lib/components/private/form-records/hlist-form-record/hlist-form-record.component.mjs +491 -0
- package/esm2020/lib/components/private/form-records/list-view-form-record/list-view-form-record.component.mjs +102 -98
- package/esm2020/lib/eqp-dynamic-module.module.mjs +4 -1
- package/esm2020/lib/models/dynamicModuleViewModeEnum.mjs +2 -1
- package/fesm2015/eqproject-eqp-dynamic-module.mjs +643 -157
- package/fesm2015/eqproject-eqp-dynamic-module.mjs.map +1 -1
- package/fesm2020/eqproject-eqp-dynamic-module.mjs +639 -157
- package/fesm2020/eqproject-eqp-dynamic-module.mjs.map +1 -1
- package/lib/components/private/form-records/hlist-form-record/hlist-form-record.component.d.ts +101 -0
- package/lib/components/private/form-records/list-view-form-record/list-view-form-record.component.d.ts +4 -2
- package/lib/eqp-dynamic-module.module.d.ts +54 -53
- package/lib/models/dynamicModuleViewModeEnum.d.ts +2 -1
- package/package.json +1 -1
|
@@ -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
|