@eqproject/eqp-attachments 2.5.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/{esm2022 → esm2020}/eqproject-eqp-attachments.mjs +4 -4
  2. package/esm2020/lib/eqp-attachments.component.mjs +1064 -0
  3. package/{esm2022 → esm2020}/lib/eqp-attachments.module.mjs +43 -43
  4. package/esm2020/lib/helpers/attachment.helper.mjs +66 -0
  5. package/{esm2022 → esm2020}/lib/interfaces/IAttachment.mjs +11 -11
  6. package/{esm2022 → esm2020}/lib/interfaces/IOptions.mjs +1 -1
  7. package/{esm2022 → esm2020}/lib/modules/material.module.mjs +231 -231
  8. package/{esm2022 → esm2020}/lib/services/eqp-attachment-dialog.service.mjs +103 -103
  9. package/{esm2022 → esm2020}/lib/services/eqp-attachment.service.mjs +23 -23
  10. package/{esm2022 → esm2020}/public-api.mjs +9 -9
  11. package/fesm2015/eqproject-eqp-attachments.mjs +1535 -0
  12. package/fesm2015/eqproject-eqp-attachments.mjs.map +1 -0
  13. package/{fesm2022 → fesm2020}/eqproject-eqp-attachments.mjs +1459 -1491
  14. package/{fesm2022 → fesm2020}/eqproject-eqp-attachments.mjs.map +1 -1
  15. package/index.d.ts +5 -5
  16. package/lib/eqp-attachments.component.d.ts +318 -318
  17. package/lib/eqp-attachments.module.d.ts +13 -13
  18. package/lib/helpers/attachment.helper.d.ts +20 -20
  19. package/lib/interfaces/IAttachment.d.ts +21 -21
  20. package/lib/interfaces/IOptions.d.ts +11 -11
  21. package/lib/modules/material.module.d.ts +37 -37
  22. package/lib/services/eqp-attachment-dialog.service.d.ts +31 -31
  23. package/lib/services/eqp-attachment.service.d.ts +7 -7
  24. package/package.json +20 -14
  25. package/public-api.d.ts +6 -6
  26. package/esm2022/lib/eqp-attachments.component.mjs +0 -1096
  27. package/esm2022/lib/helpers/attachment.helper.mjs +0 -66
@@ -0,0 +1,1064 @@
1
+ import { Component, EventEmitter, Input, Output, ViewChild } from "@angular/core";
2
+ import { Validators } from "@angular/forms";
3
+ import { TooltipPositionType, TypeColumn } from "@eqproject/eqp-table";
4
+ import imageCompression from "browser-image-compression";
5
+ import { base64ToFile, ImageCropperComponent } from "ngx-image-cropper";
6
+ import { AttachmentHelperService } from "./helpers/attachment.helper";
7
+ import { AttachmentType } from "./interfaces/IAttachment";
8
+ import { EqpAttachmentDialogService } from "./services/eqp-attachment-dialog.service";
9
+ import { concatMap, from, Observable } from "rxjs";
10
+ import * as i0 from "@angular/core";
11
+ import * as i1 from "@angular/material/dialog";
12
+ import * as i2 from "@angular/forms";
13
+ import * as i3 from "@angular/platform-browser";
14
+ import * as i4 from "@angular/common/http";
15
+ import * as i5 from "./services/eqp-attachment.service";
16
+ import * as i6 from "@angular/material/button";
17
+ import * as i7 from "@angular/material/input";
18
+ import * as i8 from "@angular/material/form-field";
19
+ import * as i9 from "@angular/material/menu";
20
+ import * as i10 from "@angular/material/card";
21
+ import * as i11 from "@angular/material/icon";
22
+ import * as i12 from "@angular/material/tooltip";
23
+ import * as i13 from "@angular/common";
24
+ import * as i14 from "ngx-image-cropper";
25
+ import * as i15 from "@eqproject/eqp-table";
26
+ import * as i16 from "ngx-file-drop";
27
+ const toBase64 = (file) => new Promise((resolve, reject) => {
28
+ const reader = new FileReader();
29
+ reader.readAsDataURL(file);
30
+ reader.onload = () => resolve(reader.result.toString());
31
+ reader.onerror = (error) => reject(error);
32
+ });
33
+ export class EqpAttachmentsComponent {
34
+ constructor(dialog, formBuilder, sanitizer, http, cd, eqpAttachmentService) {
35
+ this.dialog = dialog;
36
+ this.formBuilder = formBuilder;
37
+ this.sanitizer = sanitizer;
38
+ this.http = http;
39
+ this.cd = cd;
40
+ this.eqpAttachmentService = eqpAttachmentService;
41
+ //#region @Input del componente
42
+ /**
43
+ * Se TRUE allora nasconde la colonna per le azioni sull'allegato (nel caso "multipleAttachment" è TRUE).
44
+ */
45
+ this.disableAction = false;
46
+ /**
47
+ * Se TRUE mostra il titolo nell'header nel caso in cui "multipleAttachment" è TRUE ("Elenco allegati" di default).
48
+ */
49
+ this.showHeader = true;
50
+ /**
51
+ * Titolo da visualizzare se il parametro "showHeader" è TRUE. Di devault viene visualizzato "Elenco allegati".
52
+ */
53
+ this.headerTitle = "Elenco allegati";
54
+ /**
55
+ * Sorgente dati da visualizzare. Nel caso si vuole gestire un singolo allegato va passato in ogni caso come Array.
56
+ */
57
+ this.attachmentsList = null;
58
+ /**
59
+ * Se TRUE non mostra la MatCard (nel caso in cui "multipleAttachment" è TRUE).
60
+ */
61
+ this.showMatCard = true;
62
+ /**
63
+ * Se FALSE allora il componente mostra solo il pulsante di caricamento di un singolo file, una volta caricato il file invoca l'evento di output "localEditedAttachments".
64
+ * Se TRUE allora il componente mostra l'elenco di tutti gli allegati ricevuto nel parametro "attachmentsList".
65
+ */
66
+ this.multipleAttachment = true;
67
+ /**
68
+ * Se assume il valore TRUE allora sarà possibile caricare più file per volta. Questa funzionalità è attiva
69
+ * SOLO se si gestiscono allegati multipli, quindi se l'input 'multipleAttachment' assume il valore TRUE, altrimenti è sempre disabilitata.
70
+ */
71
+ this.loadMultipleFiles = false;
72
+ /**
73
+ * Configurazione delle colonne della eqp-table per la visualizzazione degli allegati (caso "multipleAttachment" è TRUE).
74
+ */
75
+ this.attachmentsColumns = null;
76
+ /**
77
+ * Imposta il messaggio da visualizzare nel caso in cui la tabella degli allegati (nel caso in cui "multipleAttachment" è TRUE) è vuota.
78
+ */
79
+ this.emptyTableMessage = "Nessun dato trovato";
80
+ /**
81
+ * Se TRUE allora permette di selezionare soltanto file di tipo immagine, avente uno dei mimetype
82
+ * specificati dentro AttachmentHelperService.
83
+ * Se FALSE permette di selezionare qualsiasi tipo di file
84
+ */
85
+ this.allowOnlyImages = false;
86
+ /**
87
+ * Se TRUE disabilita il pulsante di Aggiunta allegato (a prescindere dal valore del parametro "multipleAttachment").
88
+ */
89
+ this.isDisabled = false;
90
+ /**
91
+ * Mostra/nasconde la colonna per visualizzare l'anteprima dei file nella tabella (caso multipleAtatchments = true).
92
+ */
93
+ this.showInlinePreview = false;
94
+ /**
95
+ * Endpoint da chiamare per recueprare l'IAttachmentDTO completo da vedere nell'anteprima. La chiamata sarà in POST e nel body
96
+ * conterrà l'IAttachmentDTO selezionato dall'utente.
97
+ * La chiamata viene eseguita solo per l'anteprima delle immagini essendo necessario il base64 completo dell'immagine a dimensione reale.
98
+ * Per documenti/link basta che sia popolata la proprietà FilePath di IAttachmentDTO.
99
+ */
100
+ this.getAttachmentEndpoint = null;
101
+ /**
102
+ * Hostname dell'ambiente di produzione dell'applicativo. Necessario per visualizzare l'anteprima dei documenti
103
+ * tramite il viewer di google.
104
+ * NOTA: Per visualizzare l'anteprima è necessario che la prorietà FilePath dell'IAttachmentDTO sia popolata e che
105
+ * sia abilitato l'accesso alla cartella sul server tramite hostname.
106
+ */
107
+ this.productionBaseUrl = null;
108
+ /**
109
+ * Opzioni per la compressione delle immagini caricate.
110
+ */
111
+ this.compressionOptions = {
112
+ maxSizeMB: 0.5,
113
+ maxWidthOrHeight: 1920,
114
+ useWebWorker: true
115
+ };
116
+ /**
117
+ * Array di AttachmentType che si possono aggiungere
118
+ */
119
+ this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK];
120
+ /**
121
+ * Permette di stabilire se la eqp-table contenente l'elenco degli allegati utilizza
122
+ * il multilingua oppure no
123
+ */
124
+ this.isEqpTableMultiLanguage = false;
125
+ /**
126
+ * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
127
+ * degli allegati deve essere paginata oppure no
128
+ */
129
+ this.tablePaginatorVisible = true;
130
+ /**
131
+ * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
132
+ * degli allegati deve contenere il campo di ricerca oppure no
133
+ */
134
+ this.isTableSearcheable = true;
135
+ /**
136
+ * In caso di gestione allegati multipli, permette di stabilire la dimensione pagina di default
137
+ * per la tabella contenente l'elenco degli allegati
138
+ */
139
+ this.tablePaginatorSize = null;
140
+ /**
141
+ * Permette di scegliere il modo in cui i file devono essere caricati
142
+ */
143
+ // @Input("uploadType") uploadType: UploadTypeEnum = UploadTypeEnum.FILE_AND_LINK;
144
+ /**
145
+ * Permette di stabilire se i pulsanti per il caricamento dei file sono separati o in un menù a tendina
146
+ */
147
+ this.separatedUploadButtons = false;
148
+ /**
149
+ * Permette di scegliere se dare la possibilità di vedere o no l'anteprima
150
+ */
151
+ this.showPreview = true;
152
+ /**
153
+ * In caso di allegato singolo, permette di scegliere se aggiungere file tramite drag and drop
154
+ */
155
+ this.singleAttachmentDragAndDrop = false;
156
+ /**
157
+ * Array di opzioni che si possono utilizzare per il crop
158
+ */
159
+ this.cropOptions = [];
160
+ /**
161
+ * Input per definire le label da usare nel componente
162
+ */
163
+ this.downloadTooltipPosition = TooltipPositionType.Below;
164
+ this.openLinkLabel = "Apri link";
165
+ this.addButtonLabel = "Aggiungi";
166
+ this.downloadLabel = "Download";
167
+ this.deleteLabel = "Elimina";
168
+ this.fileNameLabel = "Nome file";
169
+ this.previewLabel = "Anteprima";
170
+ this.uploadFileLabel = "Carica file";
171
+ this.confirmLabel = "Conferma";
172
+ this.abortLabel = "Annulla";
173
+ this.saveLabel = "Salva";
174
+ this.exitLabel = "Esci";
175
+ this.uploadWithDropboxLabel = "Carica con Dropbox";
176
+ this.cropLabel = "Scegli le dimensioni dell'immagine";
177
+ this.eqpTableSearchText = "Cerca";
178
+ this.deleteDialogTitle = null;
179
+ this.deleteDialogMessage = "Sei sicuro di voler cancellare quest'allegato?";
180
+ this.noImageSelectedErrorMessage = "Non è possibile selezionare un file che non sia un'immagine.";
181
+ this.wrongTypeSelectedErrorMessage = "Non è possibile caricare il file selezionato.";
182
+ this.videoPreviewErrorMessage = "Impossibile aprire l'anteprima di un file video.";
183
+ this.audioPreviewErrorMessage = "Impossibile aprire l'anteprima di un file audio.";
184
+ this.flipHorinzontalLabel = "Capovolgi orizzontalmente";
185
+ this.flipVerticalLabel = "Capovolgi verticalmente";
186
+ this.rotateRightLabel = "Ruota a destra";
187
+ this.rotateLeftLabel = "Ruota a sinistra";
188
+ //#endregion
189
+ //#region @Output del componente
190
+ /**
191
+ * Restituisce la lista aggiornata degli allegati.
192
+ */
193
+ this.localEditedAttachments = new EventEmitter();
194
+ /**
195
+ * Evento scatenato alla pressione del pulsante ESCI della modale di caricamento file.
196
+ */
197
+ this.abortAddAttachment = new EventEmitter();
198
+ /**
199
+ * Evento di output che restituisce l'IAttachmentDTO selezionato per il download nel caso FileDataBase64, FileContentType o FileName non fossero specificati.
200
+ */
201
+ this.downloadAttachment = new EventEmitter();
202
+ /**
203
+ * Evento di output che restituisce l'elemento eliminato prima che questo venga effettivamente rismosso dalla lista.
204
+ */
205
+ this.onDeleteAttachment = new EventEmitter();
206
+ //#endregion
207
+ //#region Proprietà per gestione caricamento nuovo allegato
208
+ this.newAttachment = {};
209
+ this.newMultipleAttachments = [];
210
+ this.attachmentType = AttachmentType;
211
+ this.selectedFile = null;
212
+ this.selectedFiles = null;
213
+ this.showCropImage = false;
214
+ //#endregion
215
+ //#region Proprietà per gestione ridimensionamento file di tipo image
216
+ this.imageChangedEvent = "";
217
+ this.croppedImage = "";
218
+ this.transform = {};
219
+ this.canvasRotation = 0;
220
+ //#endregion
221
+ this.AttachmentType = AttachmentType;
222
+ this.addingLinkMode = false;
223
+ }
224
+ async ngOnInit() {
225
+ //Se è stata richiesta la gestione delle sole immagini allora imposta il filtro per le estensioni possibili da caricare
226
+ if (!this.acceptedFileTypes)
227
+ if (this.allowOnlyImages == true)
228
+ this.acceptedFileTypes = "image/*";
229
+ else
230
+ this.acceptedFileTypes = "*";
231
+ // Se non sono stati specificati i tipi da gestire ma è stato passato null o un array vuoto imposto i tipi di default.
232
+ if (!this.allowedTypes || this.allowedTypes.length == 0)
233
+ this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK, AttachmentType.DROPBOX];
234
+ else if (this.allowedTypes.find((t) => t != AttachmentType.FILE && t != AttachmentType.LINK && t != AttachmentType.DROPBOX)) {
235
+ EqpAttachmentDialogService.Warning('Almeno uno degli AttachmentType selezionati nel parametro "allowedTypes" non esiste.');
236
+ this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK, AttachmentType.DROPBOX];
237
+ }
238
+ //Se è stata richiesta la gestione multipla degli allegati allora configura l'eqp-table
239
+ if (this.multipleAttachment == true && (!this.attachmentsColumns || this.attachmentsColumns.length == 0)) {
240
+ this.configureColumns();
241
+ }
242
+ if (this.attachmentsList == null)
243
+ this.attachmentsList = new Array();
244
+ this.checkAttachmentImage();
245
+ if (this.allowedTypes.includes(3)) {
246
+ this.eqpAttachmentService.loadDropboxScript();
247
+ }
248
+ }
249
+ reloadData() {
250
+ if (this.attachmentTable)
251
+ this.attachmentTable.reloadDatatable();
252
+ }
253
+ checkAttachmentImage() {
254
+ this.attachmentsList.forEach((a) => {
255
+ a.IsImage = AttachmentHelperService.checkImageFromMimeType(a.FileContentType);
256
+ });
257
+ }
258
+ //#region Gestione elenco allegati
259
+ /**
260
+ * Configura le colonne per l'eqp-table nel caso in cui il parametro "multipleAttachments" è TRUE.
261
+ */
262
+ configureColumns() {
263
+ this.attachmentsColumns = [];
264
+ if (this.disableAction != true) {
265
+ this.attachmentsColumns.push({
266
+ key: "action",
267
+ display: "",
268
+ type: TypeColumn.MenuAction,
269
+ buttonMenuIcon: "more_vert",
270
+ styles: { flex: "0 0 6%" },
271
+ actions: [
272
+ { name: this.deleteLabel, icon: "delete", fn: (element, index, col) => this.deleteAttachment(element) }
273
+ ]
274
+ });
275
+ }
276
+ let downloadColumn = {
277
+ key: "attachment",
278
+ display: "",
279
+ type: TypeColumn.SimpleAction,
280
+ styles: { flex: "0 0 6%" },
281
+ actions: [
282
+ {
283
+ name: "",
284
+ fontawesome: true,
285
+ icon: (element) => {
286
+ return this.showInlinePreview
287
+ ? element.AttachmentType == AttachmentType.FILE
288
+ ? "fas fa-cloud-download-alt"
289
+ : "fas fa-external-link-alt"
290
+ : this.getAttachmentIcon(element);
291
+ },
292
+ fn: (element, col, elementIndex) => this.viewAttachment(element),
293
+ tooltip: {
294
+ tooltipText: (element) => {
295
+ return element.AttachmentType == AttachmentType.FILE ? this.downloadLabel : this.openLinkLabel;
296
+ },
297
+ tooltipPosition: this.downloadTooltipPosition
298
+ }
299
+ }
300
+ ]
301
+ };
302
+ let inlinePreviewColumn = {
303
+ key: "InlinePreview",
304
+ display: this.previewLabel,
305
+ type: TypeColumn.ExternalTemplate,
306
+ externalTemplate: this.inlinePreviewTemplate,
307
+ styles: { flex: "0 0 10%" }
308
+ };
309
+ let fileNameColumn = { key: "FileName", display: this.fileNameLabel };
310
+ if (this.showInlinePreview) {
311
+ this.attachmentsColumns.push(inlinePreviewColumn);
312
+ this.attachmentsColumns.push(fileNameColumn);
313
+ this.attachmentsColumns.push(downloadColumn);
314
+ }
315
+ else {
316
+ this.attachmentsColumns.push(downloadColumn);
317
+ this.attachmentsColumns.push(fileNameColumn);
318
+ }
319
+ }
320
+ /**
321
+ * Elimina un allegato eliminando anche il file presente nello storage di archiviazione utilizzato (AWS o cartella progetto)
322
+ * @param element IAttachmentDTO da cancellare
323
+ */
324
+ deleteAttachment(element) {
325
+ EqpAttachmentDialogService.Confirm(this.deleteDialogMessage, () => {
326
+ this.removeAttachmentFromList(this.attachmentsList.indexOf(element));
327
+ }, true, this.deleteDialogTitle);
328
+ }
329
+ /**
330
+ * Rimuove l'allegato selezionato dalla lista "attachmentsList" e invoca l'evento di output che restituisce la lista aggiornata.
331
+ * @param attachmentIndex Indice dell'attachment da rimuovere
332
+ */
333
+ removeAttachmentFromList(attachmentIndex) {
334
+ this.onDeleteAttachment.emit(this.attachmentsList[attachmentIndex]);
335
+ this.attachmentsList.splice(attachmentIndex, 1);
336
+ if (this.attachmentTable)
337
+ this.attachmentTable.reloadDatatable();
338
+ this.localEditedAttachments.emit(this.attachmentsList);
339
+ }
340
+ /**
341
+ * Scarica l'allegato o apre il link
342
+ * @param element Allegato da mostrare
343
+ */
344
+ viewAttachment(attachment) {
345
+ if (attachment.AttachmentType == AttachmentType.LINK) {
346
+ window.open(attachment.FilePath, "_blank");
347
+ return;
348
+ }
349
+ if (attachment.FileDataBase64 && attachment.FileContentType && attachment.FileName) {
350
+ let source = `data:${attachment.FileContentType};base64,${attachment.FileDataBase64}`;
351
+ const link = document.createElement("a");
352
+ link.href = source;
353
+ link.download = `${attachment.FileName}`;
354
+ link.click();
355
+ }
356
+ else {
357
+ this.downloadAttachment.emit(attachment);
358
+ }
359
+ }
360
+ /**
361
+ * Ridefinisce l'icona da mostrare nella colonna dell'eqp-table per ogni file.
362
+ * L'icona varia in base all'estensione del file
363
+ * @param attachment
364
+ */
365
+ getAttachmentIcon(attachment) {
366
+ if (attachment.AttachmentType == AttachmentType.LINK)
367
+ return "fas fa-link";
368
+ else
369
+ return AttachmentHelperService.getIconFromFileExtensione(attachment.FileExtension);
370
+ }
371
+ //#endregion
372
+ /**
373
+ * In caso di allegato singolo, sceglie quale metodo richiamare in base al tipo di allegato
374
+ */
375
+ addFile(attachmentType, imageInput = null) {
376
+ if (attachmentType == AttachmentType.LINK) {
377
+ this.switchToAddingLinkMode();
378
+ }
379
+ else if (attachmentType == AttachmentType.FILE) {
380
+ imageInput.click();
381
+ }
382
+ else {
383
+ this.chooseDropboxFile();
384
+ }
385
+ }
386
+ createAttachmentForm() {
387
+ //Crea la form per la validazione dei campi
388
+ this.newAttachmentForm = this.formBuilder.group({
389
+ type: [this.newAttachment.AttachmentType, Validators.required],
390
+ name: [this.newAttachment.FileName],
391
+ path: [this.newAttachment.FilePath],
392
+ customHeight: [this.customHeight],
393
+ customWidth: [this.customWidth]
394
+ });
395
+ }
396
+ close(emitCloseEvent = true) {
397
+ this.newAttachment = {};
398
+ this.newMultipleAttachments = new Array();
399
+ this.abortFile();
400
+ if (this.newAttachmentForm)
401
+ this.newAttachmentForm.reset();
402
+ this.dialogRefCropImage.close();
403
+ this.restoreOriginalDimensions();
404
+ if (emitCloseEvent == true && this.abortAddAttachment)
405
+ this.abortAddAttachment.emit();
406
+ }
407
+ /**
408
+ * In base al tipo di allegato controlla se disabilitare o meno il pulsante per salvare.
409
+ * Funzione usata nel [disable] del pulsante "Salva" del dialog per l'aggiunta di un allegato.
410
+ * @returns
411
+ */
412
+ disableSave() {
413
+ if (this.loadMultipleFiles != true) {
414
+ if (this.newAttachment.AttachmentType == AttachmentType.FILE) {
415
+ return !this.newAttachment.FileDataBase64;
416
+ }
417
+ else {
418
+ return !this.newAttachment.FilePath;
419
+ }
420
+ }
421
+ else {
422
+ return (this.newMultipleAttachments.filter((p) => (p.AttachmentType == AttachmentType.FILE && !p.FileDataBase64) ||
423
+ (p.AttachmentType == AttachmentType.LINK && !p.FilePath)).length > 0);
424
+ }
425
+ }
426
+ confirmAddAttachment() {
427
+ if (this.newAttachment.IsImage) {
428
+ this.newAttachment.FileDataBase64 = this.imageCropper.crop().base64.split(";base64,")[1];
429
+ }
430
+ if (this.loadMultipleFiles != true) {
431
+ if (this.newAttachment.AttachmentType == AttachmentType.LINK && !this.newAttachment.FileName)
432
+ this.newAttachment.FileName = this.newAttachment.FilePath;
433
+ if (this.attachmentsList == null)
434
+ this.attachmentsList = new Array();
435
+ this.attachmentsList.push(this.newAttachment);
436
+ }
437
+ else {
438
+ if (this.newMultipleAttachments == null || this.newMultipleAttachments.length == 0)
439
+ return;
440
+ if (this.attachmentsList == null)
441
+ this.attachmentsList = new Array();
442
+ this.attachmentsList = this.attachmentsList.concat(this.newMultipleAttachments);
443
+ }
444
+ if (this.attachmentTable)
445
+ this.attachmentTable.reloadDatatable();
446
+ this.localEditedAttachments.emit(this.attachmentsList);
447
+ if (this.newAttachment.IsImage) {
448
+ this.dialogRefCropImage.close();
449
+ this.restoreOriginalDimensions();
450
+ }
451
+ }
452
+ /**
453
+ * Apre il dialog per l'anteprima dell'allegato selezionato.
454
+ * @param row
455
+ * @returns
456
+ */
457
+ async openPreviewDialog(row) {
458
+ this.selectedAttachment = JSON.parse(JSON.stringify(row));
459
+ if (this.selectedAttachment.AttachmentType == AttachmentType.FILE) {
460
+ if (this.selectedAttachment.FileContentType.startsWith("video")) {
461
+ EqpAttachmentDialogService.Warning(this.videoPreviewErrorMessage);
462
+ return;
463
+ }
464
+ else if (this.selectedAttachment.FileContentType.startsWith("audio")) {
465
+ EqpAttachmentDialogService.Warning(this.audioPreviewErrorMessage);
466
+ return;
467
+ }
468
+ }
469
+ if (this.getAttachmentEndpoint && this.selectedAttachment.IsImage && !this.selectedAttachment.FileDataBase64) {
470
+ await this.getAttachmentByID()
471
+ .then((res) => {
472
+ this.selectedAttachment.FileDataBase64 = res.FileDataBase64;
473
+ })
474
+ .catch((err) => {
475
+ EqpAttachmentDialogService.Error(err);
476
+ });
477
+ }
478
+ if (this.selectedAttachment.AttachmentType == AttachmentType.LINK) {
479
+ this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.selectedAttachment.FilePath);
480
+ }
481
+ else if (this.selectedAttachment.IsImage &&
482
+ !this.selectedAttachment.FileDataBase64 &&
483
+ !this.selectedAttachment.FileThumbnailBase64) {
484
+ EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima dell'allegato, file mancante.");
485
+ return;
486
+ }
487
+ else if (!this.selectedAttachment.IsImage) {
488
+ if (this.selectedAttachment.FilePath && this.productionBaseUrl) {
489
+ this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://docs.google.com/gview?url=" +
490
+ this.productionBaseUrl +
491
+ "/" +
492
+ this.selectedAttachment.FilePath +
493
+ "&embedded=true");
494
+ }
495
+ else {
496
+ EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima del documento!");
497
+ return;
498
+ }
499
+ }
500
+ this.dialog.open(this.dialogPreview, {
501
+ disableClose: true,
502
+ hasBackdrop: true
503
+ });
504
+ }
505
+ async getAttachmentByID() {
506
+ return this.http.post(this.getAttachmentEndpoint, this.selectedAttachment).toPromise();
507
+ }
508
+ //#region Gestione caricamento file
509
+ /**
510
+ * Evento scatenato alla selezione del file (o dei file).
511
+ * Se il caricamento è SINGOLO o se comunque è stato selezionato un solo file allora si occupa di controllare se si tratta di un immagine in modo da
512
+ * mostrare le funzionalità del croppie (per ritagliare l'immagine) oppure no.
513
+ * Se il file caricato non è un immagine allora genera direttamente il base64 e lo associa all'allegato da salvare.
514
+ * Se invece il caricamento dei file è MULTIPLO e sono presenti più file allora esegue le stesse operazioni ignorando però il contrllo
515
+ * immagine per il croppie (in caso di caricamento multiplo le funzionalità del croppie sono disabilitate).
516
+ */
517
+ async onFileAdded(event, isFileDropped = false) {
518
+ this.showCropImage = false;
519
+ let filesOnInput = isFileDropped ? event : event.target.files;
520
+ //Se è stato richiesto il caricamento SINGOLO oppure se il caricamento è MULTIPLO ma è stato selezionato un solo file
521
+ //allora verifica se il file è un immagine (per mostrare il CROPPIE)
522
+ if ([...filesOnInput].length == 1 || this.loadMultipleFiles != true) {
523
+ this.selectedFile = filesOnInput[0];
524
+ this.selectedFiles = filesOnInput;
525
+ if (!this.selectedFile)
526
+ return;
527
+ //Memorizza i dati per l'allegato
528
+ this.newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFile, false);
529
+ this.newMultipleAttachments = new Array();
530
+ this.newMultipleAttachments.push(this.newAttachment);
531
+ //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
532
+ let checkOnlyImage = this.checkAllowOnlyImageFile(this.newAttachment);
533
+ if (checkOnlyImage == false)
534
+ return;
535
+ this.createAttachmentForm();
536
+ //Verifica se il file caricato è un'immagine oppure no. Se è un immagine, prima di caricarla mostra il croppie per il resize.
537
+ //Se non è un immagine allora genera il Base64
538
+ if (this.newAttachment.IsImage == true) {
539
+ this.getImageDimensions(filesOnInput[0]);
540
+ //Mostra il croppie e disabilita la form finchè non termina la modifica dell'immagine
541
+ this.newAttachmentForm.disable();
542
+ this.newAttachmentForm.controls["customWidth"].enable();
543
+ this.newAttachmentForm.controls["customHeight"].enable();
544
+ this.showCropImage = true;
545
+ this.imageFile = event;
546
+ this.dialogRefCropImage = this.dialog.open(this.dialogCropImage, {
547
+ disableClose: true,
548
+ hasBackdrop: true,
549
+ width: "60%",
550
+ maxHeight: "80%",
551
+ maxWidth: "70vh"
552
+ });
553
+ }
554
+ else {
555
+ this.showCropImage = false;
556
+ let base64Result = await this.getBase64FromFile(this.selectedFile);
557
+ this.newAttachment.FileDataBase64 = base64Result.Base64File;
558
+ this.newAttachment.FileContentType = base64Result.ContentType;
559
+ this.confirmAddAttachment();
560
+ }
561
+ }
562
+ else {
563
+ this.selectedFiles = filesOnInput;
564
+ if (!this.selectedFiles || this.selectedFiles.length == 0)
565
+ return;
566
+ this.newMultipleAttachments = new Array();
567
+ for (let i = 0; i < this.selectedFiles.length; i++) {
568
+ let newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFiles[i], true, true);
569
+ //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
570
+ let checkOnlyImage = this.checkAllowOnlyImageFile(newAttachment);
571
+ if (checkOnlyImage == false)
572
+ return;
573
+ this.newMultipleAttachments.push(newAttachment);
574
+ }
575
+ this.confirmAddAttachment();
576
+ }
577
+ //Resetto il valore del file input in modo da scatenare il change anche se si dovesse caricare lo stesso file
578
+ if (!isFileDropped)
579
+ event.target.value = "";
580
+ }
581
+ /**
582
+ * A partire dal FILE ricevuto in input ricostruisce l'oggetto IAttachmentDTO e lo restituisce.
583
+ * Se il parametro getBase64 viene passato a TRUE allora, sempre a partire dal file,genera il base64 e
584
+ * ricava il ContentType da associare all'oggetto IAttachmentDTO da restituire
585
+ * @param currentFile Oggetto FILE da processare
586
+ * @param getBase64 Se TRUE allora calcola base64 e ContentType del file passato in input
587
+ * @returns Restituisce un oggetto di tipo IAttachmentDTO
588
+ */
589
+ async createAttachmentFromUploadedFile(currentFile, getBase64 = true, cropFile = false) {
590
+ let newAttachment = {};
591
+ //Memorizza i dati per l'allegato
592
+ newAttachment.AttachmentType = AttachmentType.FILE;
593
+ newAttachment.FileContentType = currentFile.type;
594
+ newAttachment.FileName = currentFile.name;
595
+ newAttachment.FileExtension = currentFile.name.substr(currentFile.name.lastIndexOf(".") + 1);
596
+ newAttachment.IsImage = AttachmentHelperService.checkImageFromMimeType(currentFile.type);
597
+ if (getBase64 == true) {
598
+ let base64Result = await this.getBase64FromFile(currentFile);
599
+ newAttachment.FileDataBase64 = base64Result.Base64File;
600
+ newAttachment.FileContentType = base64Result.ContentType;
601
+ if (newAttachment.IsImage && newAttachment.FileDataBase64 && cropFile) {
602
+ this.getCroppedAndUpload(`data:${base64Result.ContentType};base64,${base64Result.Base64File}`, newAttachment);
603
+ }
604
+ }
605
+ return newAttachment;
606
+ }
607
+ /**
608
+ * A partire dal file passato in input restituisce un oggetto
609
+ * contenente il base64 del file e il suo contentType
610
+ * @param currentFile Oggetto File da cui estrapolare base64 e contentType
611
+ * @returns Restituisce un oggetto avente le proprietà Base64File e ContentType
612
+ */
613
+ async getBase64FromFile(currentFile) {
614
+ let base64File = await toBase64(currentFile);
615
+ let contentType = null;
616
+ if (base64File) {
617
+ // Loris 20/01/2022: PROBLEMA - Quando eseguo l'upload di un file .sql non viene salvato/scaricato correttamente.
618
+ // Questo succede perchè non viene popolato il FileContentType. Per risolvere il problema
619
+ // faccio un controllo e se non esiste il FileContentType allora lo recupero dal base64 ottenuto.
620
+ contentType = base64File.split(",")[0].split(":")[1].split(";")[0];
621
+ // Un altro metodo per leggere il ccontent type del file è tramite una regular expression:
622
+ base64File = base64File.split(",")[1];
623
+ }
624
+ let result = {
625
+ Base64File: base64File,
626
+ ContentType: contentType
627
+ };
628
+ return result;
629
+ }
630
+ /**
631
+ * Controlla se il file che si sta caricando è supportato dal sistema.
632
+ * @returns
633
+ */
634
+ checkAcceptedFiles() {
635
+ if ((this.loadMultipleFiles != true && this.selectedFile.type.startsWith("video")) ||
636
+ (this.loadMultipleFiles == true && [...this.selectedFiles].filter((p) => p.type.startsWith("video")).length > 0))
637
+ return false;
638
+ if (this.acceptedFileTypes == "*")
639
+ return true;
640
+ //Verifica che i tipi del file (o dei file) caricati siano coerenti con quelli accettati dalla direttiva
641
+ let accepted = true;
642
+ if (this.loadMultipleFiles != true)
643
+ accepted = this.acceptedFileTypes.includes(this.selectedFile.type);
644
+ else {
645
+ let uploadedFileTypes = [...this.selectedFiles].map((p) => p.type);
646
+ uploadedFileTypes.forEach((type) => {
647
+ if (!this.acceptedFileTypes.includes(type))
648
+ accepted = false;
649
+ });
650
+ }
651
+ //Questo controllo permette di gestire le casistiche per cui vengono indicati come tipi validi, ad esempio, 'image/*'
652
+ if (!accepted && this.loadMultipleFiles != true) {
653
+ for (let t of this.acceptedFileTypes.split(",").filter((t) => t.includes("*"))) {
654
+ accepted = this.selectedFile.type.startsWith(t.split("*")[0]);
655
+ if (accepted)
656
+ break;
657
+ }
658
+ }
659
+ return accepted;
660
+ }
661
+ /**
662
+ * Se eqp-attachments è stata configurata per il caricamento delle sole immagini allora verifica che il file passato in
663
+ * input sia effettivamente un immagine o no.
664
+ * Se il controllo va a buon fine restituisce TRUE altrimenti mostra un messaggio d'errore e restituisce FALSE
665
+ */
666
+ checkAllowOnlyImageFile(newAttachment) {
667
+ if (this.allowOnlyImages == true && newAttachment.IsImage != true) {
668
+ EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage);
669
+ this.abortFile();
670
+ return false;
671
+ }
672
+ else if (!this.checkAcceptedFiles()) {
673
+ EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage);
674
+ this.abortFile();
675
+ return false;
676
+ }
677
+ return true;
678
+ }
679
+ //#region Gestione crop file
680
+ getImageDimensions(img) {
681
+ const reader = new FileReader();
682
+ reader.onload = (e) => {
683
+ const image = new Image();
684
+ image.src = e.target.result;
685
+ image.onload = (rs) => {
686
+ this.originalHeight = rs.currentTarget["height"];
687
+ this.originalWidth = rs.currentTarget["width"];
688
+ if (this.originalWidth > 1280) {
689
+ this.customWidth = 1280;
690
+ this.customHeight = Math.round((1280 * this.originalHeight) / this.originalWidth);
691
+ }
692
+ else {
693
+ this.customHeight = rs.currentTarget["height"];
694
+ this.customWidth = rs.currentTarget["width"];
695
+ }
696
+ };
697
+ };
698
+ reader.readAsDataURL(img);
699
+ }
700
+ restoreOriginalDimensions() {
701
+ this.customWidth = this.originalWidth;
702
+ this.customHeight = this.originalHeight;
703
+ this.canvasRotation = 0;
704
+ this.transform = {};
705
+ }
706
+ onDimensionsChange(dimension) {
707
+ if (dimension == "H") {
708
+ this.customWidth = Math.round((this.customHeight * this.originalWidth) / this.originalHeight);
709
+ }
710
+ else if (dimension == "W") {
711
+ this.customHeight = Math.round((this.customWidth * this.originalHeight) / this.originalWidth);
712
+ }
713
+ }
714
+ imageCropped(event) {
715
+ this.croppedImage = event.base64;
716
+ this.getCroppedAndUpload(this.croppedImage, this.newAttachment);
717
+ }
718
+ getCroppedAndUpload(file, newAttachment) {
719
+ var self = this;
720
+ var file = base64ToFile(file);
721
+ const options = this.compressionOptions;
722
+ /**
723
+ * Comprime l'immagine passando come parametri le options create nell'oggetto sopra, e il file dal reader principale
724
+ */
725
+ imageCompression(file, options).then((fileCompressed) => {
726
+ let fileReader = new FileReader();
727
+ //Faccio la push di ogni file all'interno dell'array di file dell'item da mandare al server
728
+ fileReader.onload = function () {
729
+ let resultReader = fileReader.result;
730
+ var marker = ";base64,";
731
+ newAttachment.FileDataBase64 = resultReader.substring(resultReader.indexOf(marker) + marker.length);
732
+ self.showCropImage = false;
733
+ if (self.newAttachmentForm) {
734
+ self.newAttachmentForm.enable();
735
+ }
736
+ };
737
+ fileReader.readAsDataURL(fileCompressed);
738
+ });
739
+ }
740
+ // confirmCrop() {
741
+ // this.imageCropper.crop();
742
+ // this.dialogRefCropImage.close();
743
+ // this.restoreOriginalDimensions();
744
+ // }
745
+ rotateLeft() {
746
+ this.canvasRotation--;
747
+ this.flipAfterRotate();
748
+ }
749
+ rotateRight() {
750
+ this.canvasRotation++;
751
+ this.flipAfterRotate();
752
+ }
753
+ flipAfterRotate() {
754
+ const flippedH = this.transform.flipH;
755
+ const flippedV = this.transform.flipV;
756
+ this.transform = {
757
+ ...this.transform,
758
+ flipH: flippedV,
759
+ flipV: flippedH
760
+ };
761
+ }
762
+ flipHorizontal() {
763
+ this.transform = {
764
+ ...this.transform,
765
+ flipH: !this.transform.flipH
766
+ };
767
+ }
768
+ flipVertical() {
769
+ this.transform = {
770
+ ...this.transform,
771
+ flipV: !this.transform.flipV
772
+ };
773
+ }
774
+ //#endregion
775
+ /**
776
+ * Annulla la selezione del file, svuotando l'input e resettando tutte le proprietà dell'IAttachmentDTO
777
+ */
778
+ abortFile() {
779
+ if (this.imageInput)
780
+ this.imageInput.nativeElement.value = "";
781
+ this.selectedFile = null;
782
+ this.selectedFiles = null;
783
+ this.showCropImage = false;
784
+ this.newAttachment.IsImage = false;
785
+ this.newAttachment.FileDataBase64 = null;
786
+ this.newAttachment.FileName = null;
787
+ this.newAttachment.FileExtension = null;
788
+ this.newAttachment.FileContentType = null;
789
+ this.newMultipleAttachments = new Array();
790
+ this.customHeight = null;
791
+ this.customWidth = null;
792
+ this.originalHeight = null;
793
+ this.originalWidth = null;
794
+ this.dialogRefCropImage.close();
795
+ this.restoreOriginalDimensions();
796
+ }
797
+ //#endregion
798
+ // Viene creato un'array observables per memorizzare tutti gli observable creati dalle chiamate a fileEntry.file().
799
+ // Dopo che tutti gli observables sono stati completati, viene utilizzato il metodo subscribe() per eseguire la funzione onFileAdded().
800
+ fileDropped(files) {
801
+ let filesDropped = [];
802
+ const observables = [];
803
+ for (let i = 0; i < files.length; i++) {
804
+ if (files[i].fileEntry.isFile) {
805
+ const fileEntry = files[i].fileEntry;
806
+ const observable = new Observable((observer) => {
807
+ fileEntry.file((file) => {
808
+ filesDropped.push(file);
809
+ observer.next();
810
+ observer.complete();
811
+ });
812
+ });
813
+ observables.push(observable);
814
+ }
815
+ else {
816
+ const fileEntry = files[i].fileEntry;
817
+ console.log(files[i].relativePath, fileEntry);
818
+ }
819
+ }
820
+ from(observables)
821
+ .pipe(concatMap((observable) => observable))
822
+ .subscribe({
823
+ complete: () => {
824
+ this.onFileAdded(filesDropped, true);
825
+ }
826
+ });
827
+ }
828
+ // Se il caricamento del file dropbox va a buon fine, la funzione di callback restituisce un array di oggetti.
829
+ // Viene poi fatta una XMLHttpRequest con responseType 'blob' per convertire il primo elemento della response in un Blob.
830
+ chooseDropboxFile() {
831
+ var options = {
832
+ success: (files) => {
833
+ const xhr = new XMLHttpRequest();
834
+ xhr.open("GET", files[0].link);
835
+ xhr.setRequestHeader("Authorization", `Bearer ${AttachmentHelperService.dropboxCredentials.accessToken}`);
836
+ xhr.responseType = "blob";
837
+ xhr.onload = () => {
838
+ const blob = xhr.response;
839
+ const file = new File([blob], files[0].name, { type: blob.type });
840
+ let filesAdded = [file];
841
+ this.onFileAdded(filesAdded, true);
842
+ };
843
+ xhr.send();
844
+ },
845
+ linkType: "direct",
846
+ multiselect: false,
847
+ extensions: [".jpg", ".png", ".pdf", ".doc", ".docx", ".txt"]
848
+ };
849
+ Dropbox.choose(options);
850
+ }
851
+ // Workaround dropzone: disabilito il click degli elementi inclusi nella dropzone per evitare di cliccare due volte
852
+ onSelectFile(event, fileInput) {
853
+ if (event.target.tagName === "BUTTON" ||
854
+ event.target.tagName === "INPUT" ||
855
+ this.addingLinkMode == true) {
856
+ return;
857
+ }
858
+ fileInput.click();
859
+ }
860
+ // Metodo per visualizzare la form di aggiunta di un link
861
+ switchToAddingLinkMode() {
862
+ this.addingLinkMode = true;
863
+ this.newAttachment = {};
864
+ this.newAttachment.IsImage = false;
865
+ this.newAttachment.AttachmentType = this.attachmentType.LINK;
866
+ this.newMultipleAttachments = new Array();
867
+ this.newMultipleAttachments.push(this.newAttachment);
868
+ this.createAttachmentForm();
869
+ }
870
+ }
871
+ EqpAttachmentsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EqpAttachmentsComponent, deps: [{ token: i1.MatDialog }, { token: i2.FormBuilder }, { token: i3.DomSanitizer }, { token: i4.HttpClient }, { token: i0.ChangeDetectorRef }, { token: i5.EqpAttachmentService }], target: i0.ɵɵFactoryTarget.Component });
872
+ EqpAttachmentsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.10", type: EqpAttachmentsComponent, selector: "eqp-attachments", inputs: { disableAction: "disableAction", showHeader: "showHeader", headerTitle: "headerTitle", attachmentsList: "attachmentsList", showMatCard: "showMatCard", multipleAttachment: "multipleAttachment", loadMultipleFiles: "loadMultipleFiles", attachmentsColumns: "attachmentsColumns", emptyTableMessage: "emptyTableMessage", allowOnlyImages: "allowOnlyImages", acceptedFileTypes: "acceptedFileTypes", isDisabled: "isDisabled", showInlinePreview: "showInlinePreview", getAttachmentEndpoint: "getAttachmentEndpoint", productionBaseUrl: "productionBaseUrl", compressionOptions: "compressionOptions", allowedTypes: "allowedTypes", isEqpTableMultiLanguage: "isEqpTableMultiLanguage", tablePaginatorVisible: "tablePaginatorVisible", isTableSearcheable: "isTableSearcheable", tablePaginatorSize: "tablePaginatorSize", separatedUploadButtons: "separatedUploadButtons", showPreview: "showPreview", singleAttachmentDragAndDrop: "singleAttachmentDragAndDrop", cropOptions: "cropOptions", cropDialogClass: "cropDialogClass", downloadTooltipPosition: "downloadTooltipPosition", openLinkLabel: "openLinkLabel", addButtonLabel: "addButtonLabel", downloadLabel: "downloadLabel", deleteLabel: "deleteLabel", fileNameLabel: "fileNameLabel", previewLabel: "previewLabel", uploadFileLabel: "uploadFileLabel", confirmLabel: "confirmLabel", abortLabel: "abortLabel", saveLabel: "saveLabel", exitLabel: "exitLabel", uploadWithDropboxLabel: "uploadWithDropboxLabel", cropLabel: "cropLabel", eqpTableSearchText: "eqpTableSearchText", deleteDialogTitle: "deleteDialogTitle", deleteDialogMessage: "deleteDialogMessage", noImageSelectedErrorMessage: "noImageSelectedErrorMessage", wrongTypeSelectedErrorMessage: "wrongTypeSelectedErrorMessage", videoPreviewErrorMessage: "videoPreviewErrorMessage", audioPreviewErrorMessage: ["videoPreviewErrorMessage", "audioPreviewErrorMessage"], flipHorinzontalLabel: "flipHorinzontalLabel", flipVerticalLabel: "flipVerticalLabel", rotateRightLabel: "rotateRightLabel", rotateLeftLabel: "rotateLeftLabel" }, outputs: { localEditedAttachments: "localEditedAttachments", abortAddAttachment: "abortAddAttachment", downloadAttachment: "downloadAttachment", onDeleteAttachment: "onDeleteAttachment" }, viewQueries: [{ propertyName: "dialogAddAttachment", first: true, predicate: ["dialogAddAttachment"], descendants: true, static: true }, { propertyName: "dialogAddMultipleAttachment", first: true, predicate: ["dialogAddMultipleAttachment"], descendants: true, static: true }, { propertyName: "dialogCropImage", first: true, predicate: ["dialogCropImage"], descendants: true, static: true }, { propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true }, { propertyName: "attachmentTable", first: true, predicate: ["attachmentTable"], descendants: true }, { propertyName: "inlinePreviewTemplate", first: true, predicate: ["inlinePreviewTemplate"], descendants: true, static: true }, { propertyName: "dialogPreview", first: true, predicate: ["dialogPreview"], descendants: true, static: true }], ngImport: i0, template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n<div *ngIf=\"multipleAttachment != true\">\r\n <div *ngIf=\"!singleAttachmentDragAndDrop\">\r\n <!-- Template del button per l'aggiunta di un allegato -->\r\n <div *ngIf=\"!addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addAttachmentButton\"></ng-container>\r\n </div>\r\n <!-- Template della form per l'aggiunta di un link -->\r\n <div *ngIf=\"addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </div>\r\n </div>\r\n <div *ngIf=\"singleAttachmentDragAndDrop\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop\r\n (onFileDrop)=\"fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.includes(1) &&\r\n (!attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n </div>\r\n <div class=\"text-center\">\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-download-btn\"\r\n (click)=\"viewAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n color=\"primary\">\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType == AttachmentType.FILE\">download</mat-icon>\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType != AttachmentType.FILE\">open_in_new</mat-icon>\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-preview-btn\"\r\n (click)=\"openPreviewDialog(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"primary\"\r\n *ngIf=\"\r\n showPreview &&\r\n attachmentsList &&\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n (!attachmentsList[0].FileContentType ||\r\n (!attachmentsList[0].FileContentType.startsWith('video') &&\r\n !attachmentsList[0].FileContentType.startsWith('audio'))) &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n </div>\r\n <div\r\n class=\"row\"\r\n style=\"margin-top: 10px\"\r\n *ngIf=\"\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n attachmentsList[0].FileDataBase64 &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <div class=\"col-sm-12 d-flex justify-content-center\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{ attachmentsList[0].FileDataBase64 }}\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\" *ngIf=\"attachmentsList.length > 0 && attachmentsList[0] && attachmentsList[0].IsImage != true\">\r\n <div class=\"col-sm-12\">\r\n <mat-form-field>\r\n <mat-label>{{ fileNameLabel }}</mat-label>\r\n <input readonly matInput [(ngModel)]=\"attachmentsList[0].FileName\" />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"multipleAttachment == true\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop (onFileDrop)=\"fileDropped($event)\" (click)=\"onSelectFile($event, fileInput)\">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n <div class=\"mt-2\">\r\n <eqp-table\r\n #attachmentTable\r\n [createMatCard]=\"false\"\r\n #table\r\n [columns]=\"attachmentsColumns\"\r\n [isMultiLanguage]=\"isEqpTableMultiLanguage\"\r\n [data]=\"attachmentsList\"\r\n [paginatorVisible]=\"tablePaginatorVisible\"\r\n [matPaginatorSize]=\"tablePaginatorSize\"\r\n [emptyTableMessage]=\"emptyTableMessage\"\r\n [searchText]=\"eqpTableSearchText\"\r\n [isTableSearcheable]=\"isTableSearcheable\">\r\n </eqp-table>\r\n </div>\r\n</div>\r\n\r\n<ng-template #dialogCropImage>\r\n <!-- Richiama il template per le funzionalit\u00E0 del CROPPIE -->\r\n <div style=\"overflow-x: hidden\" [ngClass]=\"cropDialogClass\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"croppieTemplate\"\r\n [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\"\r\n *ngIf=\"showCropImage == true\"></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <img src=\"data:image/png;base64,{{ row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64 }}\" />\r\n </div>\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && !row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #dialogPreview>\r\n <mat-card class=\"example-card\" *ngIf=\"selectedAttachment\">\r\n <mat-card-content>\r\n <div class=\"row\">\r\n <div class=\"header-title-standard\">\r\n {{ previewLabel }} {{ selectedAttachment?.AttachmentType == attachmentType.FILE ? \"File\" : \"Link\" }}\r\n <button\r\n type=\"button\"\r\n class=\"btn-close closeButton\"\r\n mat-dialog-close\r\n (click)=\"selectedAttachment = null\"></button>\r\n </div>\r\n </div>\r\n <div class=\"row mt-2\">\r\n <!-- ANTEPRIMA IMMAGINE -->\r\n <div class=\"col-12 text-center preview-container\" *ngIf=\"selectedAttachment.IsImage\">\r\n <img\r\n class=\"image-preview\"\r\n src=\"data:image/png;base64,{{\r\n selectedAttachment.FileDataBase64\r\n ? selectedAttachment.FileDataBase64\r\n : selectedAttachment.FileThumbnailBase64\r\n }}\" />\r\n </div>\r\n\r\n <!-- ANTEPRIMA LINK -->\r\n <div class=\"col-12 preview-container\" *ngIf=\"!selectedAttachment.IsImage\">\r\n <iframe\r\n class=\"link-preview\"\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n </div>\r\n <div class=\"row mt-3\">\r\n <div class=\"col-sm-12 text-center\">\r\n <button\r\n mat-mini-fab\r\n color=\"primary\"\r\n matTooltip=\"Download\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n *ngIf=\"selectedAttachment.AttachmentType != AttachmentType.LINK\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <!--\r\n Pulsanti per l'aggiunta di un file o un link. Ne viene visualizzato uno se:\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di pi\u00F9 allegati (multipleAttachment == true)\r\n OPPURE\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di un singolo allegato (multipleAttachment == true) e non ne \u00E8 ancora stato selezionato uno (ovvero attachmentsList non esiste o non ha elementi)\r\n -->\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.length == 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\"\r\n [disabled]=\"isDisabled\">\r\n <!-- Per l'aggiunta dei file mostro un'icona diversa dall'aggiunta dei link -->\r\n <mat-icon *ngIf=\"allowedTypes[0] == 1\">cloud_upload</mat-icon>\r\n <i class=\"fas fa-link\" *ngIf=\"allowedTypes[0] == 2\"></i>\r\n <i class=\"fa-brands fa-dropbox\" *ngIf=\"allowedTypes[0] == 3\"></i>\r\n <span style=\"margin-left: 10px\">\r\n {{\r\n allowedTypes[0] == 1\r\n ? addButtonLabel + \" file\"\r\n : allowedTypes[0] == 2\r\n ? addButtonLabel + \" link\"\r\n : uploadWithDropboxLabel\r\n }}</span\r\n >\r\n </button>\r\n\r\n <!-- Pulsante per aprire il menu per la scelta del tipo di Attachment da creare -->\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"\r\n [disabled]=\"isDisabled\"\r\n *ngIf=\"\r\n !separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <mat-icon *ngIf=\"multipleAttachment != true\">cloud_upload</mat-icon>\r\n <mat-icon *ngIf=\"multipleAttachment == true\">add</mat-icon>\r\n <span style=\"margin-left: 0px\"> {{ addButtonLabel }} </span>\r\n </button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"imageInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n\r\n <div\r\n *ngIf=\"\r\n separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <div class=\"btn-group\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n (click)=\"imageInput.click()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"row m-3\">\r\n <h4>{{ cropLabel }}</h4>\r\n </div>\r\n <div class=\"row m-2 crop-large\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n [matTooltip]=\"rotateLeftLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateLeft()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_left</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"rotateRightLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateRight()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_right</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipHorinzontalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipHorizontal()\">\r\n <mat-icon style=\"vertical-align: middle\">flip_horizontal</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipVerticalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipVertical()\">\r\n <div style=\"transform: rotate(90deg)\"><mat-icon style=\"vertical-align: middle\">flip_vertical</mat-icon></div>\r\n </button>\r\n <button\r\n [matTooltip]=\"'Reset'\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"restoreOriginalDimensions()\">\r\n <mat-icon style=\"vertical-align: middle\">replay</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row m-2 crop-small\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <mat-icon *ngIf=\"cropOptions.includes(1)\" style=\"font-size: 27px; vertical-align: middle\" (click)=\"rotateLeft()\"\r\n >rotate_left</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"rotateRight()\"\r\n >rotate_right</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipHorizontal()\"\r\n >flip_horizontal</mat-icon\r\n >\r\n <div class=\"ms-3\" style=\"transform: rotate(90deg)\">\r\n <mat-icon\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipVertical()\"\r\n >flip_vertical</mat-icon\r\n >\r\n </div>\r\n <mat-icon class=\"ms-3\" (click)=\"restoreOriginalDimensions()\" style=\"font-size: 27px; vertical-align: middle\"\r\n >replay</mat-icon\r\n >\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <div class=\"crop-container\">\r\n <image-cropper\r\n [imageFile]=\"selectedFile\"\r\n [maintainAspectRatio]=\"false\"\r\n [autoCrop]=\"false\"\r\n [containWithinAspectRatio]=\"false\"\r\n [aspectRatio]=\"4 / 3\"\r\n [cropperMinWidth]=\"128\"\r\n [onlyScaleDown]=\"true\"\r\n [roundCropper]=\"false\"\r\n [canvasRotation]=\"0\"\r\n [transform]=\"transform\"\r\n [alignImage]=\"'left'\"\r\n format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\"\r\n [canvasRotation]=\"canvasRotation\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-large\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button eqp-attachments-confirm-btn me-2\"\r\n type=\"button\"\r\n (click)=\"confirmAddAttachment()\">\r\n {{ confirmLabel }}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-abort-btn\" type=\"button\" (click)=\"abortFile()\">\r\n {{ abortLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-small\">\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-times\" (click)=\"abortFile()\"></i>\r\n </div>\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-check\" (click)=\"confirmAddAttachment()\"></i>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <span class=\"mb-1\" style=\"font-size: 20px\"><i class=\"fa fa-link\"></i>Inserisci l'URL</span>\r\n <form [formGroup]=\"newAttachmentForm\" *ngIf=\"newAttachmentForm\">\r\n <div class=\"row mb-2\" style=\"height: 80px\">\r\n <div class=\"col-6 d-grid gap-2 mx-auto\">\r\n <div class=\"input-group mb-1\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"{{ fileNameLabel }}\"\r\n formControlName=\"name\"\r\n [(ngModel)]=\"newAttachment.FileName\" />\r\n </div>\r\n </div>\r\n <div class=\"col-12 d-grid gap-2\">\r\n <div class=\"input-group\">\r\n <input\r\n required\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Link\"\r\n formControlName=\"path\"\r\n [(ngModel)]=\"newAttachment.FilePath\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-secondary mat-raised-button\"\r\n (click)=\"selectedAttachment = null; addingLinkMode = false\"\r\n type=\"button\">\r\n {{ exitLabel }}\r\n </button>\r\n </div>\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button\"\r\n type=\"submit\"\r\n (click)=\"confirmAddAttachment(); selectedAttachment = null; addingLinkMode = false\">\r\n {{ saveLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n</ng-template>\r\n", styles: ["ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone{min-height:30vh;border-radius:5px!important;background-color:#e4e6ea!important;cursor:pointer;font-size:17px!important;border:dotted!important;padding-top:7vh}ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone .ngx-file-drop__content{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#73777a!important;margin:auto}.custom-height .mat-form-field-wrapper{height:20px}.eqp-attachments-header-title{font-weight:700;font-size:19px;line-height:24px;margin-bottom:auto}.single-attachment-inline-preview-container{max-height:400px;max-width:400px;display:flex;align-items:center}.single-attachment-inline-preview-container img{max-width:100%;max-height:120px}.inline-preview-container{max-height:100px;max-width:100px;display:flex;align-items:center;justify-content:center;width:100%;cursor:pointer}.inline-preview-container img{max-width:100%;max-height:100px}.inline-preview-container i{font-size:25px;margin:auto}.preview-container{max-height:60vh;max-width:100%}.preview-container .image-preview{max-width:100%;max-height:100%}.preview-container .link-preview{width:70vw;height:55vh}.closeButton{float:right}@media (max-width: 768px){.crop-large{display:none}}@media (min-width: 768px){.crop-small{display:none}}@media (max-width: 768px){.crop-container{max-width:55%}}@media (min-width: 768px){.crop-container{max-width:35%}}\n"], dependencies: [{ kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i6.MatMiniFabButton, selector: "button[mat-mini-fab]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["disabled", "disableRipple", "role"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", exportAs: ["matMenuTrigger"] }, { kind: "component", type: i10.MatCard, selector: "mat-card", inputs: ["appearance"], exportAs: ["matCard"] }, { kind: "directive", type: i10.MatCardContent, selector: "mat-card-content" }, { kind: "component", type: i11.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i13.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i13.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i13.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i14.ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "cropperFrameAriaLabel", "output", "format", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "autoCrop", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "cropper", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange"] }, { kind: "component", type: i15.EqpTableComponent, selector: "eqp-table" }, { kind: "component", type: i16.NgxFileDropComponent, selector: "ngx-file-drop", inputs: ["accept", "directory", "multiple", "dropZoneLabel", "dropZoneClassName", "useDragEnter", "contentClassName", "showBrowseBtn", "browseBtnClassName", "browseBtnLabel", "disabled"], outputs: ["onFileDrop", "onFileOver", "onFileLeave"] }, { kind: "directive", type: i16.NgxFileDropContentTemplateDirective, selector: "[ngx-file-drop-content-tmp]" }] });
873
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EqpAttachmentsComponent, decorators: [{
874
+ type: Component,
875
+ args: [{ selector: "eqp-attachments", template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n<div *ngIf=\"multipleAttachment != true\">\r\n <div *ngIf=\"!singleAttachmentDragAndDrop\">\r\n <!-- Template del button per l'aggiunta di un allegato -->\r\n <div *ngIf=\"!addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addAttachmentButton\"></ng-container>\r\n </div>\r\n <!-- Template della form per l'aggiunta di un link -->\r\n <div *ngIf=\"addingLinkMode\" class=\"text-center\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </div>\r\n </div>\r\n <div *ngIf=\"singleAttachmentDragAndDrop\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop\r\n (onFileDrop)=\"fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.includes(1) &&\r\n (!attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n </div>\r\n <div class=\"text-center\">\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-download-btn\"\r\n (click)=\"viewAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n color=\"primary\">\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType == AttachmentType.FILE\">download</mat-icon>\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType != AttachmentType.FILE\">open_in_new</mat-icon>\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 me-2 eqp-attachments-preview-btn\"\r\n (click)=\"openPreviewDialog(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n color=\"primary\"\r\n *ngIf=\"\r\n showPreview &&\r\n attachmentsList &&\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n (!attachmentsList[0].FileContentType ||\r\n (!attachmentsList[0].FileContentType.startsWith('video') &&\r\n !attachmentsList[0].FileContentType.startsWith('audio'))) &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n <button\r\n class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\"\r\n type=\"button\"\r\n mat-raised-button\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n </div>\r\n <div\r\n class=\"row\"\r\n style=\"margin-top: 10px\"\r\n *ngIf=\"\r\n attachmentsList.length > 0 &&\r\n attachmentsList[0] &&\r\n attachmentsList[0].FileDataBase64 &&\r\n attachmentsList[0].IsImage == true\r\n \">\r\n <div class=\"col-sm-12 d-flex justify-content-center\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{ attachmentsList[0].FileDataBase64 }}\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\" *ngIf=\"attachmentsList.length > 0 && attachmentsList[0] && attachmentsList[0].IsImage != true\">\r\n <div class=\"col-sm-12\">\r\n <mat-form-field>\r\n <mat-label>{{ fileNameLabel }}</mat-label>\r\n <input readonly matInput [(ngModel)]=\"attachmentsList[0].FileName\" />\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n<div *ngIf=\"multipleAttachment == true\">\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <ngx-file-drop (onFileDrop)=\"fileDropped($event)\" (click)=\"onSelectFile($event, fileInput)\">\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"!addingLinkMode\">\r\n <i class=\"fa-solid fa-cloud-upload-alt fa-3x mt-3\"></i>\r\n Trascina i file qui\r\n <div class=\"btn-group mt-1\" role=\"group\">\r\n <button type=\"button\" class=\"btn btn-light border-end\" (click)=\"fileInput.click()\">Scegli un file</button>\r\n <div class=\"btn-group\" role=\"group\">\r\n <button\r\n type=\"button\"\r\n class=\"btn btn-light border-start dropdown-toggle\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"></button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"fileInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n </div>\r\n </div>\r\n </ng-template>\r\n <ng-template ngx-file-drop-content-tmp *ngIf=\"addingLinkMode\">\r\n <ng-container *ngTemplateOutlet=\"addingLinkTemplate\"></ng-container>\r\n </ng-template>\r\n </ngx-file-drop>\r\n <div class=\"mt-2\">\r\n <eqp-table\r\n #attachmentTable\r\n [createMatCard]=\"false\"\r\n #table\r\n [columns]=\"attachmentsColumns\"\r\n [isMultiLanguage]=\"isEqpTableMultiLanguage\"\r\n [data]=\"attachmentsList\"\r\n [paginatorVisible]=\"tablePaginatorVisible\"\r\n [matPaginatorSize]=\"tablePaginatorSize\"\r\n [emptyTableMessage]=\"emptyTableMessage\"\r\n [searchText]=\"eqpTableSearchText\"\r\n [isTableSearcheable]=\"isTableSearcheable\">\r\n </eqp-table>\r\n </div>\r\n</div>\r\n\r\n<ng-template #dialogCropImage>\r\n <!-- Richiama il template per le funzionalit\u00E0 del CROPPIE -->\r\n <div style=\"overflow-x: hidden\" [ngClass]=\"cropDialogClass\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"croppieTemplate\"\r\n [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\"\r\n *ngIf=\"showCropImage == true\"></ng-container>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <img src=\"data:image/png;base64,{{ row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64 }}\" />\r\n </div>\r\n <div\r\n class=\"inline-preview-container\"\r\n *ngIf=\"row.AttachmentType != AttachmentType.LINK && !row.IsImage\"\r\n (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #dialogPreview>\r\n <mat-card class=\"example-card\" *ngIf=\"selectedAttachment\">\r\n <mat-card-content>\r\n <div class=\"row\">\r\n <div class=\"header-title-standard\">\r\n {{ previewLabel }} {{ selectedAttachment?.AttachmentType == attachmentType.FILE ? \"File\" : \"Link\" }}\r\n <button\r\n type=\"button\"\r\n class=\"btn-close closeButton\"\r\n mat-dialog-close\r\n (click)=\"selectedAttachment = null\"></button>\r\n </div>\r\n </div>\r\n <div class=\"row mt-2\">\r\n <!-- ANTEPRIMA IMMAGINE -->\r\n <div class=\"col-12 text-center preview-container\" *ngIf=\"selectedAttachment.IsImage\">\r\n <img\r\n class=\"image-preview\"\r\n src=\"data:image/png;base64,{{\r\n selectedAttachment.FileDataBase64\r\n ? selectedAttachment.FileDataBase64\r\n : selectedAttachment.FileThumbnailBase64\r\n }}\" />\r\n </div>\r\n\r\n <!-- ANTEPRIMA LINK -->\r\n <div class=\"col-12 preview-container\" *ngIf=\"!selectedAttachment.IsImage\">\r\n <iframe\r\n class=\"link-preview\"\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n </div>\r\n <div class=\"row mt-3\">\r\n <div class=\"col-sm-12 text-center\">\r\n <button\r\n mat-mini-fab\r\n color=\"primary\"\r\n matTooltip=\"Download\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n *ngIf=\"selectedAttachment.AttachmentType != AttachmentType.LINK\">\r\n <mat-icon>download</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n </mat-card-content>\r\n </mat-card>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <!--\r\n Pulsanti per l'aggiunta di un file o un link. Ne viene visualizzato uno se:\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di pi\u00F9 allegati (multipleAttachment == true)\r\n OPPURE\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK)\r\n e sono nella gestione di un singolo allegato (multipleAttachment == true) e non ne \u00E8 ancora stato selezionato uno (ovvero attachmentsList non esiste o non ha elementi)\r\n -->\r\n <input\r\n #fileInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n *ngIf=\"\r\n allowedTypes &&\r\n allowedTypes.length == 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\"\r\n [disabled]=\"isDisabled\">\r\n <!-- Per l'aggiunta dei file mostro un'icona diversa dall'aggiunta dei link -->\r\n <mat-icon *ngIf=\"allowedTypes[0] == 1\">cloud_upload</mat-icon>\r\n <i class=\"fas fa-link\" *ngIf=\"allowedTypes[0] == 2\"></i>\r\n <i class=\"fa-brands fa-dropbox\" *ngIf=\"allowedTypes[0] == 3\"></i>\r\n <span style=\"margin-left: 10px\">\r\n {{\r\n allowedTypes[0] == 1\r\n ? addButtonLabel + \" file\"\r\n : allowedTypes[0] == 2\r\n ? addButtonLabel + \" link\"\r\n : uploadWithDropboxLabel\r\n }}</span\r\n >\r\n </button>\r\n\r\n <!-- Pulsante per aprire il menu per la scelta del tipo di Attachment da creare -->\r\n <button\r\n class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"primary\"\r\n type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\"\r\n [disabled]=\"isDisabled\"\r\n *ngIf=\"\r\n !separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <mat-icon *ngIf=\"multipleAttachment != true\">cloud_upload</mat-icon>\r\n <mat-icon *ngIf=\"multipleAttachment == true\">add</mat-icon>\r\n <span style=\"margin-left: 0px\"> {{ addButtonLabel }} </span>\r\n </button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n mat-menu-item\r\n (click)=\"imageInput.click()\"\r\n class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n mat-menu-item\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n\r\n <div\r\n *ngIf=\"\r\n separatedUploadButtons &&\r\n allowedTypes &&\r\n allowedTypes.length > 1 &&\r\n (multipleAttachment == true ||\r\n !attachmentsList ||\r\n attachmentsList.length == 0 ||\r\n (attachmentsList.length > 0 && !attachmentsList[0]))\r\n \">\r\n <div class=\"btn-group\">\r\n <button\r\n *ngIf=\"allowedTypes.includes(1)\"\r\n (click)=\"imageInput.click()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n <input\r\n #imageInput\r\n style=\"display: none\"\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles\" />\r\n <button\r\n *ngIf=\"allowedTypes.includes(2)\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n <button\r\n *ngIf=\"allowedTypes.includes(3)\"\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"btn btn-secondary eqp-attachments-add-btn\"\r\n mat-raised-button\r\n color=\"secondary\"\r\n type=\"button\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"row m-3\">\r\n <h4>{{ cropLabel }}</h4>\r\n </div>\r\n <div class=\"row m-2 crop-large\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n [matTooltip]=\"rotateLeftLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateLeft()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_left</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"rotateRightLabel\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"rotateRight()\">\r\n <mat-icon style=\"vertical-align: middle\">rotate_right</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipHorinzontalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipHorizontal()\">\r\n <mat-icon style=\"vertical-align: middle\">flip_horizontal</mat-icon>\r\n </button>\r\n <button\r\n [matTooltip]=\"flipVerticalLabel\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"flipVertical()\">\r\n <div style=\"transform: rotate(90deg)\"><mat-icon style=\"vertical-align: middle\">flip_vertical</mat-icon></div>\r\n </button>\r\n <button\r\n [matTooltip]=\"'Reset'\"\r\n class=\"btn btn-primary mat-raised-button ms-2\"\r\n (click)=\"restoreOriginalDimensions()\">\r\n <mat-icon style=\"vertical-align: middle\">replay</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row m-2 crop-small\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <mat-icon *ngIf=\"cropOptions.includes(1)\" style=\"font-size: 27px; vertical-align: middle\" (click)=\"rotateLeft()\"\r\n >rotate_left</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(1)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"rotateRight()\"\r\n >rotate_right</mat-icon\r\n >\r\n <mat-icon\r\n class=\"ms-3\"\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipHorizontal()\"\r\n >flip_horizontal</mat-icon\r\n >\r\n <div class=\"ms-3\" style=\"transform: rotate(90deg)\">\r\n <mat-icon\r\n *ngIf=\"cropOptions.includes(2)\"\r\n style=\"font-size: 27px; vertical-align: middle\"\r\n (click)=\"flipVertical()\"\r\n >flip_vertical</mat-icon\r\n >\r\n </div>\r\n <mat-icon class=\"ms-3\" (click)=\"restoreOriginalDimensions()\" style=\"font-size: 27px; vertical-align: middle\"\r\n >replay</mat-icon\r\n >\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <div class=\"crop-container\">\r\n <image-cropper\r\n [imageFile]=\"selectedFile\"\r\n [maintainAspectRatio]=\"false\"\r\n [autoCrop]=\"false\"\r\n [containWithinAspectRatio]=\"false\"\r\n [aspectRatio]=\"4 / 3\"\r\n [cropperMinWidth]=\"128\"\r\n [onlyScaleDown]=\"true\"\r\n [roundCropper]=\"false\"\r\n [canvasRotation]=\"0\"\r\n [transform]=\"transform\"\r\n [alignImage]=\"'left'\"\r\n format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\"\r\n [canvasRotation]=\"canvasRotation\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-large\">\r\n <div class=\"col-12 d-flex align-items-center justify-content-center\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button eqp-attachments-confirm-btn me-2\"\r\n type=\"button\"\r\n (click)=\"confirmAddAttachment()\">\r\n {{ confirmLabel }}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-abort-btn\" type=\"button\" (click)=\"abortFile()\">\r\n {{ abortLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2 mb-2 crop-small\">\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-times\" (click)=\"abortFile()\"></i>\r\n </div>\r\n <div class=\"col-6 d-flex align-items-center justify-content-center\" style=\"font-size: 20px\">\r\n <i class=\"fa fa-check\" (click)=\"confirmAddAttachment()\"></i>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <span class=\"mb-1\" style=\"font-size: 20px\"><i class=\"fa fa-link\"></i>Inserisci l'URL</span>\r\n <form [formGroup]=\"newAttachmentForm\" *ngIf=\"newAttachmentForm\">\r\n <div class=\"row mb-2\" style=\"height: 80px\">\r\n <div class=\"col-6 d-grid gap-2 mx-auto\">\r\n <div class=\"input-group mb-1\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"{{ fileNameLabel }}\"\r\n formControlName=\"name\"\r\n [(ngModel)]=\"newAttachment.FileName\" />\r\n </div>\r\n </div>\r\n <div class=\"col-12 d-grid gap-2\">\r\n <div class=\"input-group\">\r\n <input\r\n required\r\n type=\"text\"\r\n class=\"form-control\"\r\n placeholder=\"Link\"\r\n formControlName=\"path\"\r\n [(ngModel)]=\"newAttachment.FilePath\" />\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-secondary mat-raised-button\"\r\n (click)=\"selectedAttachment = null; addingLinkMode = false\"\r\n type=\"button\">\r\n {{ exitLabel }}\r\n </button>\r\n </div>\r\n <div class=\"col-6 d-grid gap-2\">\r\n <button\r\n class=\"btn btn-primary mat-raised-button\"\r\n type=\"submit\"\r\n (click)=\"confirmAddAttachment(); selectedAttachment = null; addingLinkMode = false\">\r\n {{ saveLabel }}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n</ng-template>\r\n", styles: ["ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone{min-height:30vh;border-radius:5px!important;background-color:#e4e6ea!important;cursor:pointer;font-size:17px!important;border:dotted!important;padding-top:7vh}ngx-file-drop ::ng-deep .ngx-file-drop__drop-zone .ngx-file-drop__content{display:flex;flex-direction:column;align-items:center;justify-content:center;color:#73777a!important;margin:auto}.custom-height .mat-form-field-wrapper{height:20px}.eqp-attachments-header-title{font-weight:700;font-size:19px;line-height:24px;margin-bottom:auto}.single-attachment-inline-preview-container{max-height:400px;max-width:400px;display:flex;align-items:center}.single-attachment-inline-preview-container img{max-width:100%;max-height:120px}.inline-preview-container{max-height:100px;max-width:100px;display:flex;align-items:center;justify-content:center;width:100%;cursor:pointer}.inline-preview-container img{max-width:100%;max-height:100px}.inline-preview-container i{font-size:25px;margin:auto}.preview-container{max-height:60vh;max-width:100%}.preview-container .image-preview{max-width:100%;max-height:100%}.preview-container .link-preview{width:70vw;height:55vh}.closeButton{float:right}@media (max-width: 768px){.crop-large{display:none}}@media (min-width: 768px){.crop-small{display:none}}@media (max-width: 768px){.crop-container{max-width:55%}}@media (min-width: 768px){.crop-container{max-width:35%}}\n"] }]
876
+ }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.FormBuilder }, { type: i3.DomSanitizer }, { type: i4.HttpClient }, { type: i0.ChangeDetectorRef }, { type: i5.EqpAttachmentService }]; }, propDecorators: { disableAction: [{
877
+ type: Input,
878
+ args: ["disableAction"]
879
+ }], showHeader: [{
880
+ type: Input,
881
+ args: ["showHeader"]
882
+ }], headerTitle: [{
883
+ type: Input,
884
+ args: ["headerTitle"]
885
+ }], attachmentsList: [{
886
+ type: Input,
887
+ args: ["attachmentsList"]
888
+ }], showMatCard: [{
889
+ type: Input,
890
+ args: ["showMatCard"]
891
+ }], multipleAttachment: [{
892
+ type: Input,
893
+ args: ["multipleAttachment"]
894
+ }], loadMultipleFiles: [{
895
+ type: Input,
896
+ args: ["loadMultipleFiles"]
897
+ }], attachmentsColumns: [{
898
+ type: Input,
899
+ args: ["attachmentsColumns"]
900
+ }], emptyTableMessage: [{
901
+ type: Input,
902
+ args: ["emptyTableMessage"]
903
+ }], allowOnlyImages: [{
904
+ type: Input,
905
+ args: ["allowOnlyImages"]
906
+ }], acceptedFileTypes: [{
907
+ type: Input,
908
+ args: ["acceptedFileTypes"]
909
+ }], isDisabled: [{
910
+ type: Input,
911
+ args: ["isDisabled"]
912
+ }], showInlinePreview: [{
913
+ type: Input,
914
+ args: ["showInlinePreview"]
915
+ }], getAttachmentEndpoint: [{
916
+ type: Input,
917
+ args: ["getAttachmentEndpoint"]
918
+ }], productionBaseUrl: [{
919
+ type: Input,
920
+ args: ["productionBaseUrl"]
921
+ }], compressionOptions: [{
922
+ type: Input,
923
+ args: ["compressionOptions"]
924
+ }], allowedTypes: [{
925
+ type: Input,
926
+ args: ["allowedTypes"]
927
+ }], isEqpTableMultiLanguage: [{
928
+ type: Input,
929
+ args: ["isEqpTableMultiLanguage"]
930
+ }], tablePaginatorVisible: [{
931
+ type: Input,
932
+ args: ["tablePaginatorVisible"]
933
+ }], isTableSearcheable: [{
934
+ type: Input,
935
+ args: ["isTableSearcheable"]
936
+ }], tablePaginatorSize: [{
937
+ type: Input,
938
+ args: ["tablePaginatorSize"]
939
+ }], separatedUploadButtons: [{
940
+ type: Input,
941
+ args: ["separatedUploadButtons"]
942
+ }], showPreview: [{
943
+ type: Input,
944
+ args: ["showPreview"]
945
+ }], singleAttachmentDragAndDrop: [{
946
+ type: Input,
947
+ args: ["singleAttachmentDragAndDrop"]
948
+ }], cropOptions: [{
949
+ type: Input,
950
+ args: ["cropOptions"]
951
+ }], cropDialogClass: [{
952
+ type: Input,
953
+ args: ["cropDialogClass"]
954
+ }], downloadTooltipPosition: [{
955
+ type: Input,
956
+ args: ["downloadTooltipPosition"]
957
+ }], openLinkLabel: [{
958
+ type: Input,
959
+ args: ["openLinkLabel"]
960
+ }], addButtonLabel: [{
961
+ type: Input,
962
+ args: ["addButtonLabel"]
963
+ }], downloadLabel: [{
964
+ type: Input,
965
+ args: ["downloadLabel"]
966
+ }], deleteLabel: [{
967
+ type: Input,
968
+ args: ["deleteLabel"]
969
+ }], fileNameLabel: [{
970
+ type: Input,
971
+ args: ["fileNameLabel"]
972
+ }], previewLabel: [{
973
+ type: Input,
974
+ args: ["previewLabel"]
975
+ }], uploadFileLabel: [{
976
+ type: Input,
977
+ args: ["uploadFileLabel"]
978
+ }], confirmLabel: [{
979
+ type: Input,
980
+ args: ["confirmLabel"]
981
+ }], abortLabel: [{
982
+ type: Input,
983
+ args: ["abortLabel"]
984
+ }], saveLabel: [{
985
+ type: Input,
986
+ args: ["saveLabel"]
987
+ }], exitLabel: [{
988
+ type: Input,
989
+ args: ["exitLabel"]
990
+ }], uploadWithDropboxLabel: [{
991
+ type: Input,
992
+ args: ["uploadWithDropboxLabel"]
993
+ }], cropLabel: [{
994
+ type: Input,
995
+ args: ["cropLabel"]
996
+ }], eqpTableSearchText: [{
997
+ type: Input,
998
+ args: ["eqpTableSearchText"]
999
+ }], deleteDialogTitle: [{
1000
+ type: Input,
1001
+ args: ["deleteDialogTitle"]
1002
+ }], deleteDialogMessage: [{
1003
+ type: Input,
1004
+ args: ["deleteDialogMessage"]
1005
+ }], noImageSelectedErrorMessage: [{
1006
+ type: Input,
1007
+ args: ["noImageSelectedErrorMessage"]
1008
+ }], wrongTypeSelectedErrorMessage: [{
1009
+ type: Input,
1010
+ args: ["wrongTypeSelectedErrorMessage"]
1011
+ }], videoPreviewErrorMessage: [{
1012
+ type: Input,
1013
+ args: ["videoPreviewErrorMessage"]
1014
+ }], audioPreviewErrorMessage: [{
1015
+ type: Input,
1016
+ args: ["videoPreviewErrorMessage"]
1017
+ }], flipHorinzontalLabel: [{
1018
+ type: Input,
1019
+ args: ["flipHorinzontalLabel"]
1020
+ }], flipVerticalLabel: [{
1021
+ type: Input,
1022
+ args: ["flipVerticalLabel"]
1023
+ }], rotateRightLabel: [{
1024
+ type: Input,
1025
+ args: ["rotateRightLabel"]
1026
+ }], rotateLeftLabel: [{
1027
+ type: Input,
1028
+ args: ["rotateLeftLabel"]
1029
+ }], localEditedAttachments: [{
1030
+ type: Output
1031
+ }], abortAddAttachment: [{
1032
+ type: Output
1033
+ }], downloadAttachment: [{
1034
+ type: Output,
1035
+ args: ["downloadAttachment"]
1036
+ }], onDeleteAttachment: [{
1037
+ type: Output,
1038
+ args: ["onDeleteAttachment"]
1039
+ }], dialogAddAttachment: [{
1040
+ type: ViewChild,
1041
+ args: ["dialogAddAttachment", { static: true }]
1042
+ }], dialogAddMultipleAttachment: [{
1043
+ type: ViewChild,
1044
+ args: ["dialogAddMultipleAttachment", { static: true }]
1045
+ }], dialogCropImage: [{
1046
+ type: ViewChild,
1047
+ args: ["dialogCropImage", { static: true }]
1048
+ }], imageCropper: [{
1049
+ type: ViewChild,
1050
+ args: [ImageCropperComponent]
1051
+ }], imageInput: [{
1052
+ type: ViewChild,
1053
+ args: ["imageInput"]
1054
+ }], attachmentTable: [{
1055
+ type: ViewChild,
1056
+ args: ["attachmentTable", { static: false }]
1057
+ }], inlinePreviewTemplate: [{
1058
+ type: ViewChild,
1059
+ args: ["inlinePreviewTemplate", { static: true }]
1060
+ }], dialogPreview: [{
1061
+ type: ViewChild,
1062
+ args: ["dialogPreview", { static: true }]
1063
+ }] } });
1064
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2VxcC1hdHRhY2htZW50cy9zcmMvbGliL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtYXR0YWNobWVudHMvc3JjL2xpYi9lcXAtYXR0YWNobWVudHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUVMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFTixTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUEwQixVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdwRSxPQUFPLEVBQW1DLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3hHLE9BQU8sZ0JBQWdCLE1BQU0sMkJBQTJCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBcUIscUJBQXFCLEVBQWtCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0csT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGNBQWMsRUFBa0MsTUFBTSwwQkFBMEIsQ0FBQztBQUUxRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUl0RixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUduRCxNQUFNLFFBQVEsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQ3hCLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBQ3RDLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7SUFDaEMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJ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a0JBQWtCO2dCQUNDLGVBQWU7c0JBQXhDLEtBQUs7dUJBQUMsaUJBQWlCO2dCQVFkLHNCQUFzQjtzQkFBL0IsTUFBTTtnQkFLRyxrQkFBa0I7c0JBQTNCLE1BQU07Z0JBS3VCLGtCQUFrQjtzQkFBL0MsTUFBTTt1QkFBQyxvQkFBb0I7Z0JBS0Usa0JBQWtCO3NCQUEvQyxNQUFNO3VCQUFDLG9CQUFvQjtnQkFhd0IsbUJBQW1CO3NCQUF0RSxTQUFTO3VCQUFDLHFCQUFxQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFFVSwyQkFBMkI7c0JBQXRGLFNBQVM7dUJBQUMsNkJBQTZCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUVWLGVBQWU7c0JBQTlELFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQVFaLFlBQVk7c0JBQTdDLFNBQVM7dUJBQUMscUJBQXFCO2dCQUNQLFVBQVU7c0JBQWxDLFNBQVM7dUJBQUMsWUFBWTtnQkFXMEIsZUFBZTtzQkFBL0QsU0FBUzt1QkFBQyxpQkFBaUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBQ08scUJBQXFCO3NCQUExRSxTQUFTO3VCQUFDLHVCQUF1QixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDTixhQUFhO3NCQUExRCxTQUFTO3VCQUFDLGVBQWUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vbi9odHRwXCI7XHJcbmltcG9ydCB7XHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgQ29tcG9uZW50LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBJbnB1dCxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDaGlsZFxyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IEZvcm1CdWlsZGVyLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcclxuaW1wb3J0IHsgTWF0RGlhbG9nLCBNYXREaWFsb2dSZWYgfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nXCI7XHJcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gXCJAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyXCI7XHJcbmltcG9ydCB7IENvbmZpZ0NvbHVtbiwgRXFwVGFibGVDb21wb25lbnQsIFRvb2x0aXBQb3NpdGlvblR5cGUsIFR5cGVDb2x1bW4gfSBmcm9tIFwiQGVxcHJvamVjdC9lcXAtdGFibGVcIjtcclxuaW1wb3J0IGltYWdlQ29tcHJlc3Npb24gZnJvbSBcImJyb3dzZXItaW1hZ2UtY29tcHJlc3Npb25cIjtcclxuaW1wb3J0IHsgYmFzZTY0VG9GaWxlLCBJbWFnZUNyb3BwZWRFdmVudCwgSW1hZ2VDcm9wcGVyQ29tcG9uZW50LCBJbWFnZVRyYW5zZm9ybSB9IGZyb20gXCJuZ3gtaW1hZ2UtY3JvcHBlclwiO1xyXG5pbXBvcnQgeyBBdHRhY2htZW50SGVscGVyU2VydmljZSB9IGZyb20gXCIuL2hlbHBlcnMvYXR0YWNobWVudC5oZWxwZXJcIjtcclxuaW1wb3J0IHsgQXR0YWNobWVudFR5cGUsIENyb3BPcHRpb25FbnVtLCBJQXR0YWNobWVudERUTyB9IGZyb20gXCIuL2ludGVyZmFjZXMvSUF0dGFjaG1lbnRcIjtcclxuaW1wb3J0IHsgSU9wdGlvbnMgfSBmcm9tIFwiLi9pbnRlcmZhY2VzL0lPcHRpb25zXCI7XHJcbmltcG9ydCB7IEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvZXFwLWF0dGFjaG1lbnQtZGlhbG9nLnNlcnZpY2VcIjtcclxuXHJcbmRlY2xhcmUgdmFyIERyb3Bib3g6IGFueTtcclxuXHJcbmltcG9ydCB7IGNvbmNhdE1hcCwgZnJvbSwgT2JzZXJ2YWJsZSB9IGZyb20gXCJyeGpzXCI7XHJcbmltcG9ydCB7IEVxcEF0dGFjaG1lbnRTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvZXFwLWF0dGFjaG1lbnQuc2VydmljZVwiO1xyXG5cclxuY29uc3QgdG9CYXNlNjQgPSAoZmlsZSkgPT5cclxuICBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcclxuICAgIHJlYWRlci5vbmxvYWQgPSAoKSA9PiByZXNvbHZlKHJlYWRlci5yZXN1bHQudG9TdHJpbmcoKSk7XHJcbiAgICByZWFkZXIub25lcnJvciA9IChlcnJvcikgPT4gcmVqZWN0KGVycm9yKTtcclxuICB9KTtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiBcImVxcC1hdHRhY2htZW50c1wiLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmxzOiBbXCIuL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQuc2Nzc1wiXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRXFwQXR0YWNobWVudHNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gIC8vI3JlZ2lvbiBASW5wdXQgZGVsIGNvbXBvbmVudGVcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgbmFzY29uZGUgbGEgY29sb25uYSBwZXIgbGUgYXppb25pIHN1bGwnYWxsZWdhdG8gKG5lbCBjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZGlzYWJsZUFjdGlvblwiKSBkaXNhYmxlQWN0aW9uOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgbW9zdHJhIGlsIHRpdG9sbyBuZWxsJ2hlYWRlciBuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFIChcIkVsZW5jbyBhbGxlZ2F0aVwiIGRpIGRlZmF1bHQpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dIZWFkZXJcIikgc2hvd0hlYWRlcjogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRpdG9sbyBkYSB2aXN1YWxpenphcmUgc2UgaWwgcGFyYW1ldHJvIFwic2hvd0hlYWRlclwiIMOoIFRSVUUuIERpIGRldmF1bHQgdmllbmUgdmlzdWFsaXp6YXRvIFwiRWxlbmNvIGFsbGVnYXRpXCIuXHJcbiAgICovXHJcbiAgQElucHV0KFwiaGVhZGVyVGl0bGVcIikgaGVhZGVyVGl0bGU6IHN0cmluZyA9IFwiRWxlbmNvIGFsbGVnYXRpXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNvcmdlbnRlIGRhdGkgZGEgdmlzdWFsaXp6YXJlLiBOZWwgY2FzbyBzaSB2dW9sZSBnZXN0aXJlIHVuIHNpbmdvbG8gYWxsZWdhdG8gdmEgcGFzc2F0byBpbiBvZ25pIGNhc28gY29tZSBBcnJheS5cclxuICAgKi9cclxuICBASW5wdXQoXCJhdHRhY2htZW50c0xpc3RcIikgYXR0YWNobWVudHNMaXN0OiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIG5vbiBtb3N0cmEgbGEgTWF0Q2FyZCAobmVsIGNhc28gaW4gY3VpIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwic2hvd01hdENhcmRcIikgc2hvd01hdENhcmQ6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBGQUxTRSBhbGxvcmEgaWwgY29tcG9uZW50ZSBtb3N0cmEgc29sbyBpbCBwdWxzYW50ZSBkaSBjYXJpY2FtZW50byBkaSB1biBzaW5nb2xvIGZpbGUsIHVuYSB2b2x0YSBjYXJpY2F0byBpbCBmaWxlIGludm9jYSBsJ2V2ZW50byBkaSBvdXRwdXQgXCJsb2NhbEVkaXRlZEF0dGFjaG1lbnRzXCIuXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgaWwgY29tcG9uZW50ZSBtb3N0cmEgbCdlbGVuY28gZGkgdHV0dGkgZ2xpIGFsbGVnYXRpIHJpY2V2dXRvIG5lbCBwYXJhbWV0cm8gXCJhdHRhY2htZW50c0xpc3RcIi5cclxuICAgKi9cclxuICBASW5wdXQoXCJtdWx0aXBsZUF0dGFjaG1lbnRcIikgbXVsdGlwbGVBdHRhY2htZW50OiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgYXNzdW1lIGlsIHZhbG9yZSBUUlVFIGFsbG9yYSBzYXLDoCBwb3NzaWJpbGUgY2FyaWNhcmUgcGnDuSBmaWxlIHBlciB2b2x0YS4gUXVlc3RhIGZ1bnppb25hbGl0w6Agw6ggYXR0aXZhXHJcbiAgICogU09MTyBzZSBzaSBnZXN0aXNjb25vIGFsbGVnYXRpIG11bHRpcGxpLCBxdWluZGkgc2UgbCdpbnB1dCAnbXVsdGlwbGVBdHRhY2htZW50JyBhc3N1bWUgaWwgdmFsb3JlIFRSVUUsIGFsdHJpbWVudGkgw6ggc2VtcHJlIGRpc2FiaWxpdGF0YS5cclxuICAgKi9cclxuICBASW5wdXQoXCJsb2FkTXVsdGlwbGVGaWxlc1wiKSBsb2FkTXVsdGlwbGVGaWxlczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBDb25maWd1cmF6aW9uZSBkZWxsZSBjb2xvbm5lIGRlbGxhIGVxcC10YWJsZSBwZXIgbGEgdmlzdWFsaXp6YXppb25lIGRlZ2xpIGFsbGVnYXRpIChjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiYXR0YWNobWVudHNDb2x1bW5zXCIpIGF0dGFjaG1lbnRzQ29sdW1uczogQXJyYXk8Q29uZmlnQ29sdW1uPiA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIEltcG9zdGEgaWwgbWVzc2FnZ2lvIGRhIHZpc3VhbGl6emFyZSBuZWwgY2FzbyBpbiBjdWkgbGEgdGFiZWxsYSBkZWdsaSBhbGxlZ2F0aSAobmVsIGNhc28gaW4gY3VpIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkgw6ggdnVvdGEuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZW1wdHlUYWJsZU1lc3NhZ2VcIikgZW1wdHlUYWJsZU1lc3NhZ2U6IHN0cmluZyA9IFwiTmVzc3VuIGRhdG8gdHJvdmF0b1wiO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIGFsbG9yYSBwZXJtZXR0ZSBkaSBzZWxlemlvbmFyZSBzb2x0YW50byBmaWxlIGRpIHRpcG8gaW1tYWdpbmUsIGF2ZW50ZSB1bm8gZGVpIG1pbWV0eXBlXHJcbiAgICogc3BlY2lmaWNhdGkgZGVudHJvIEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLlxyXG4gICAqIFNlIEZBTFNFIHBlcm1ldHRlIGRpIHNlbGV6aW9uYXJlIHF1YWxzaWFzaSB0aXBvIGRpIGZpbGVcclxuICAgKi9cclxuICBASW5wdXQoXCJhbGxvd09ubHlJbWFnZXNcIikgYWxsb3dPbmx5SW1hZ2VzOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNwZWNpZmljYSBpIHRpcGkgZGkgZmlsZSBjaGUgw6ggcG9zc2liaWxlIGNhcmljYXJlXHJcbiAgICovXHJcbiAgQElucHV0KFwiYWNjZXB0ZWRGaWxlVHlwZXNcIikgYWNjZXB0ZWRGaWxlVHlwZXM6IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBkaXNhYmlsaXRhIGlsIHB1bHNhbnRlIGRpIEFnZ2l1bnRhIGFsbGVnYXRvIChhIHByZXNjaW5kZXJlIGRhbCB2YWxvcmUgZGVsIHBhcmFtZXRybyBcIm11bHRpcGxlQXR0YWNobWVudFwiKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJpc0Rpc2FibGVkXCIpIGlzRGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogTW9zdHJhL25hc2NvbmRlIGxhIGNvbG9ubmEgcGVyIHZpc3VhbGl6emFyZSBsJ2FudGVwcmltYSBkZWkgZmlsZSBuZWxsYSB0YWJlbGxhIChjYXNvIG11bHRpcGxlQXRhdGNobWVudHMgPSB0cnVlKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJzaG93SW5saW5lUHJldmlld1wiKSBzaG93SW5saW5lUHJldmlldzogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBFbmRwb2ludCBkYSBjaGlhbWFyZSBwZXIgcmVjdWVwcmFyZSBsJ0lBdHRhY2htZW50RFRPIGNvbXBsZXRvIGRhIHZlZGVyZSBuZWxsJ2FudGVwcmltYS4gTGEgY2hpYW1hdGEgc2Fyw6AgaW4gUE9TVCBlIG5lbCBib2R5XHJcbiAgICogY29udGVycsOgIGwnSUF0dGFjaG1lbnREVE8gc2VsZXppb25hdG8gZGFsbCd1dGVudGUuXHJcbiAgICogTGEgY2hpYW1hdGEgdmllbmUgZXNlZ3VpdGEgc29sbyBwZXIgbCdhbnRlcHJpbWEgZGVsbGUgaW1tYWdpbmkgZXNzZW5kbyBuZWNlc3NhcmlvIGlsIGJhc2U2NCBjb21wbGV0byBkZWxsJ2ltbWFnaW5lIGEgZGltZW5zaW9uZSByZWFsZS5cclxuICAgKiBQZXIgZG9jdW1lbnRpL2xpbmsgYmFzdGEgY2hlIHNpYSBwb3BvbGF0YSBsYSBwcm9wcmlldMOgIEZpbGVQYXRoIGRpIElBdHRhY2htZW50RFRPLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImdldEF0dGFjaG1lbnRFbmRwb2ludFwiKSBnZXRBdHRhY2htZW50RW5kcG9pbnQ6IHN0cmluZyA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIEhvc3RuYW1lIGRlbGwnYW1iaWVudGUgZGkgcHJvZHV6aW9uZSBkZWxsJ2FwcGxpY2F0aXZvLiBOZWNlc3NhcmlvIHBlciB2aXN1YWxpenphcmUgbCdhbnRlcHJpbWEgZGVpIGRvY3VtZW50aVxyXG4gICAqIHRyYW1pdGUgaWwgdmlld2VyIGRpIGdvb2dsZS5cclxuICAgKiBOT1RBOiBQZXIgdmlzdWFsaXp6YXJlIGwnYW50ZXByaW1hIMOoIG5lY2Vzc2FyaW8gY2hlIGxhIHByb3JpZXTDoCBGaWxlUGF0aCBkZWxsJ0lBdHRhY2htZW50RFRPIHNpYSBwb3BvbGF0YSBlIGNoZVxyXG4gICAqIHNpYSBhYmlsaXRhdG8gbCdhY2Nlc3NvIGFsbGEgY2FydGVsbGEgc3VsIHNlcnZlciB0cmFtaXRlIGhvc3RuYW1lLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInByb2R1Y3Rpb25CYXNlVXJsXCIpIHByb2R1Y3Rpb25CYXNlVXJsOiBzdHJpbmcgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBPcHppb25pIHBlciBsYSBjb21wcmVzc2lvbmUgZGVsbGUgaW1tYWdpbmkgY2FyaWNhdGUuXHJcbiAgICovXHJcbiAgQElucHV0KFwiY29tcHJlc3Npb25PcHRpb25zXCIpIGNvbXByZXNzaW9uT3B0aW9uczogSU9wdGlvbnMgPSB7XHJcbiAgICBtYXhTaXplTUI6IDAuNSxcclxuICAgIG1heFdpZHRoT3JIZWlnaHQ6IDE5MjAsXHJcbiAgICB1c2VXZWJXb3JrZXI6IHRydWVcclxuICB9O1xyXG5cclxuICAvKipcclxuICAgKiBBcnJheSBkaSBBdHRhY2htZW50VHlwZSBjaGUgc2kgcG9zc29ubyBhZ2dpdW5nZXJlXHJcbiAgICovXHJcbiAgQElucHV0KFwiYWxsb3dlZFR5cGVzXCIpIGFsbG93ZWRUeXBlczogQXJyYXk8QXR0YWNobWVudFR5cGU+ID0gW0F0dGFjaG1lbnRUeXBlLkZJTEUsIEF0dGFjaG1lbnRUeXBlLkxJTktdO1xyXG5cclxuICAvKipcclxuICAgKiBQZXJtZXR0ZSBkaSBzdGFiaWxpcmUgc2UgbGEgZXFwLXRhYmxlIGNvbnRlbmVudGUgbCdlbGVuY28gZGVnbGkgYWxsZWdhdGkgdXRpbGl6emFcclxuICAgKiBpbCBtdWx0aWxpbmd1YSBvcHB1cmUgbm9cclxuICAgKi9cclxuICBASW5wdXQoXCJpc0VxcFRhYmxlTXVsdGlMYW5ndWFnZVwiKSBpc0VxcFRhYmxlTXVsdGlMYW5ndWFnZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBQZXJtZXR0ZSBkaSBzdGFiaWxpcmUsIGluIGNhc28gZGkgZ2VzdGlvbmUgYWxsZWdhdGkgbXVsdGlwbGksIHNlIGxhIHRhYmVsbGEgY29udGVuZW50ZSBsJ2VsZW5jb1xyXG4gICAqIGRlZ2xpIGFsbGVnYXRpIGRldmUgZXNzZXJlIHBhZ2luYXRhIG9wcHVyZSBub1xyXG4gICAqL1xyXG4gIEBJbnB1dChcInRhYmxlUGFnaW5hdG9yVmlzaWJsZVwiKSB0YWJsZVBhZ2luYXRvclZpc2libGU6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBQZXJtZXR0ZSBkaSBzdGFiaWxpcmUsIGluIGNhc28gZGkgZ2VzdGlvbmUgYWxsZWdhdGkgbXVsdGlwbGksIHNlIGxhIHRhYmVsbGEgY29udGVuZW50ZSBsJ2VsZW5jb1xyXG4gICAqIGRlZ2xpIGFsbGVnYXRpIGRldmUgY29udGVuZXJlIGlsIGNhbXBvIGRpIHJpY2VyY2Egb3BwdXJlIG5vXHJcbiAgICovXHJcbiAgQElucHV0KFwiaXNUYWJsZVNlYXJjaGVhYmxlXCIpIGlzVGFibGVTZWFyY2hlYWJsZTogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGNhc28gZGkgZ2VzdGlvbmUgYWxsZWdhdGkgbXVsdGlwbGksIHBlcm1ldHRlIGRpIHN0YWJpbGlyZSBsYSBkaW1lbnNpb25lIHBhZ2luYSBkaSBkZWZhdWx0XHJcbiAgICogcGVyIGxhIHRhYmVsbGEgY29udGVuZW50ZSBsJ2VsZW5jbyBkZWdsaSBhbGxlZ2F0aVxyXG4gICAqL1xyXG4gIEBJbnB1dChcInRhYmxlUGFnaW5hdG9yU2l6ZVwiKSB0YWJsZVBhZ2luYXRvclNpemU6IG51bWJlciA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHNjZWdsaWVyZSBpbCBtb2RvIGluIGN1aSBpIGZpbGUgZGV2b25vIGVzc2VyZSBjYXJpY2F0aVxyXG4gICAqL1xyXG4gIC8vIEBJbnB1dChcInVwbG9hZFR5cGVcIikgdXBsb2FkVHlwZTogVXBsb2FkVHlwZUVudW0gPSBVcGxvYWRUeXBlRW51bS5GSUxFX0FORF9MSU5LO1xyXG5cclxuICAvKipcclxuICAgKiBQZXJtZXR0ZSBkaSBzdGFiaWxpcmUgc2UgaSBwdWxzYW50aSBwZXIgaWwgY2FyaWNhbWVudG8gZGVpIGZpbGUgc29ubyBzZXBhcmF0aSBvIGluIHVuIG1lbsO5IGEgdGVuZGluYVxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNlcGFyYXRlZFVwbG9hZEJ1dHRvbnNcIikgc2VwYXJhdGVkVXBsb2FkQnV0dG9uczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBQZXJtZXR0ZSBkaSBzY2VnbGllcmUgc2UgZGFyZSBsYSBwb3NzaWJpbGl0w6AgZGkgdmVkZXJlIG8gbm8gbCdhbnRlcHJpbWFcclxuICAgKi9cclxuICBASW5wdXQoXCJzaG93UHJldmlld1wiKSBzaG93UHJldmlldzogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGNhc28gZGkgYWxsZWdhdG8gc2luZ29sbywgcGVybWV0dGUgZGkgc2NlZ2xpZXJlIHNlIGFnZ2l1bmdlcmUgZmlsZSB0cmFtaXRlIGRyYWcgYW5kIGRyb3BcclxuICAgKi9cclxuICBASW5wdXQoXCJzaW5nbGVBdHRhY2htZW50RHJhZ0FuZERyb3BcIikgc2luZ2xlQXR0YWNobWVudERyYWdBbmREcm9wOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IGRpIG9wemlvbmkgY2hlIHNpIHBvc3Nvbm8gdXRpbGl6emFyZSBwZXIgaWwgY3JvcFxyXG4gICAqL1xyXG4gIEBJbnB1dChcImNyb3BPcHRpb25zXCIpIGNyb3BPcHRpb25zOiBBcnJheTxDcm9wT3B0aW9uRW51bT4gPSBbXTtcclxuXHJcbiAgLyoqXHJcbiAgICogQ2xhc3NlIGN1c3RvbSBkYSBhc3NlZ25hcmUgYWwgZGlhbG9nIGRlbCBjcm9wIGltbWFnaW5pXHJcbiAgICovXHJcbiAgQElucHV0KFwiY3JvcERpYWxvZ0NsYXNzXCIpIGNyb3BEaWFsb2dDbGFzczogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBJbnB1dCBwZXIgZGVmaW5pcmUgbGUgbGFiZWwgZGEgdXNhcmUgbmVsIGNvbXBvbmVudGVcclxuICAgKi9cclxuICBASW5wdXQoXCJkb3dubG9hZFRvb2x0aXBQb3NpdGlvblwiKSBkb3dubG9hZFRvb2x0aXBQb3NpdGlvbjogVG9vbHRpcFBvc2l0aW9uVHlwZSA9IFRvb2x0aXBQb3NpdGlvblR5cGUuQmVsb3c7XHJcbiAgQElucHV0KFwib3BlbkxpbmtMYWJlbFwiKSBvcGVuTGlua0xhYmVsOiBzdHJpbmcgPSBcIkFwcmkgbGlua1wiO1xyXG4gIEBJbnB1dChcImFkZEJ1dHRvbkxhYmVsXCIpIGFkZEJ1dHRvbkxhYmVsOiBzdHJpbmcgPSBcIkFnZ2l1bmdpXCI7XHJcbiAgQElucHV0KFwiZG93bmxvYWRMYWJlbFwiKSBkb3dubG9hZExhYmVsOiBzdHJpbmcgPSBcIkRvd25sb2FkXCI7XHJcbiAgQElucHV0KFwiZGVsZXRlTGFiZWxcIikgZGVsZXRlTGFiZWw6IHN0cmluZyA9IFwiRWxpbWluYVwiO1xyXG4gIEBJbnB1dChcImZpbGVOYW1lTGFiZWxcIikgZmlsZU5hbWVMYWJlbDogc3RyaW5nID0gXCJOb21lIGZpbGVcIjtcclxuICBASW5wdXQoXCJwcmV2aWV3TGFiZWxcIikgcHJldmlld0xhYmVsOiBzdHJpbmcgPSBcIkFudGVwcmltYVwiO1xyXG4gIEBJbnB1dChcInVwbG9hZEZpbGVMYWJlbFwiKSB1cGxvYWRGaWxlTGFiZWw6IHN0cmluZyA9IFwiQ2FyaWNhIGZpbGVcIjtcclxuICBASW5wdXQoXCJjb25maXJtTGFiZWxcIikgY29uZmlybUxhYmVsOiBzdHJpbmcgPSBcIkNvbmZlcm1hXCI7XHJcbiAgQElucHV0KFwiYWJvcnRMYWJlbFwiKSBhYm9ydExhYmVsOiBzdHJpbmcgPSBcIkFubnVsbGFcIjtcclxuICBASW5wdXQoXCJzYXZlTGFiZWxcIikgc2F2ZUxhYmVsOiBzdHJpbmcgPSBcIlNhbHZhXCI7XHJcbiAgQElucHV0KFwiZXhpdExhYmVsXCIpIGV4aXRMYWJlbDogc3RyaW5nID0gXCJFc2NpXCI7XHJcbiAgQElucHV0KFwidXBsb2FkV2l0aERyb3Bib3hMYWJlbFwiKSB1cGxvYWRXaXRoRHJvcGJveExhYmVsOiBzdHJpbmcgPSBcIkNhcmljYSBjb24gRHJvcGJveFwiO1xyXG4gIEBJbnB1dChcImNyb3BMYWJlbFwiKSBjcm9wTGFiZWw6IHN0cmluZyA9IFwiU2NlZ2xpIGxlIGRpbWVuc2lvbmkgZGVsbCdpbW1hZ2luZVwiO1xyXG4gIEBJbnB1dChcImVxcFRhYmxlU2VhcmNoVGV4dFwiKSBlcXBUYWJsZVNlYXJjaFRleHQ6IHN0cmluZyA9IFwiQ2VyY2FcIjtcclxuICBASW5wdXQoXCJkZWxldGVEaWFsb2dUaXRsZVwiKSBkZWxldGVEaWFsb2dUaXRsZTogc3RyaW5nID0gbnVsbDtcclxuICBASW5wdXQoXCJkZWxldGVEaWFsb2dNZXNzYWdlXCIpIGRlbGV0ZURpYWxvZ01lc3NhZ2U6IHN0cmluZyA9IFwiU2VpIHNpY3VybyBkaSB2b2xlciBjYW5jZWxsYXJlIHF1ZXN0J2FsbGVnYXRvP1wiO1xyXG4gIEBJbnB1dChcIm5vSW1hZ2VTZWxlY3RlZEVycm9yTWVzc2FnZVwiKSBub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIk5vbiDDqCBwb3NzaWJpbGUgc2VsZXppb25hcmUgdW4gZmlsZSBjaGUgbm9uIHNpYSB1bidpbW1hZ2luZS5cIjtcclxuICBASW5wdXQoXCJ3cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZVwiKSB3cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZTogc3RyaW5nID1cclxuICAgIFwiTm9uIMOoIHBvc3NpYmlsZSBjYXJpY2FyZSBpbCBmaWxlIHNlbGV6aW9uYXRvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSB2aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkaSB1biBmaWxlIHZpZGVvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSBhdWRpb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkaSB1biBmaWxlIGF1ZGlvLlwiO1xyXG4gIEBJbnB1dChcImZsaXBIb3JpbnpvbnRhbExhYmVsXCIpIGZsaXBIb3JpbnpvbnRhbExhYmVsOiBzdHJpbmcgPSBcIkNhcG92b2xnaSBvcml6em9udGFsbWVudGVcIjtcclxuICBASW5wdXQoXCJmbGlwVmVydGljYWxMYWJlbFwiKSBmbGlwVmVydGljYWxMYWJlbDogc3RyaW5nID0gXCJDYXBvdm9sZ2kgdmVydGljYWxtZW50ZVwiO1xyXG4gIEBJbnB1dChcInJvdGF0ZVJpZ2h0TGFiZWxcIikgcm90YXRlUmlnaHRMYWJlbDogc3RyaW5nID0gXCJSdW90YSBhIGRlc3RyYVwiO1xyXG4gIEBJbnB1dChcInJvdGF0ZUxlZnRMYWJlbFwiKSByb3RhdGVMZWZ0TGFiZWw6IHN0cmluZyA9IFwiUnVvdGEgYSBzaW5pc3RyYVwiO1xyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvLyNyZWdpb24gQE91dHB1dCBkZWwgY29tcG9uZW50ZVxyXG5cclxuICAvKipcclxuICAgKiBSZXN0aXR1aXNjZSBsYSBsaXN0YSBhZ2dpb3JuYXRhIGRlZ2xpIGFsbGVnYXRpLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBsb2NhbEVkaXRlZEF0dGFjaG1lbnRzOiBFdmVudEVtaXR0ZXI8QXJyYXk8SUF0dGFjaG1lbnREVE8+PiA9IG5ldyBFdmVudEVtaXR0ZXI8QXJyYXk8SUF0dGFjaG1lbnREVE8+PigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gc2NhdGVuYXRvIGFsbGEgcHJlc3Npb25lIGRlbCBwdWxzYW50ZSBFU0NJIGRlbGxhIG1vZGFsZSBkaSBjYXJpY2FtZW50byBmaWxlLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBhYm9ydEFkZEF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGwnSUF0dGFjaG1lbnREVE8gc2VsZXppb25hdG8gcGVyIGlsIGRvd25sb2FkIG5lbCBjYXNvIEZpbGVEYXRhQmFzZTY0LCBGaWxlQ29udGVudFR5cGUgbyBGaWxlTmFtZSBub24gZm9zc2VybyBzcGVjaWZpY2F0aS5cclxuICAgKi9cclxuICBAT3V0cHV0KFwiZG93bmxvYWRBdHRhY2htZW50XCIpIGRvd25sb2FkQXR0YWNobWVudDogRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPiA9IG5ldyBFdmVudEVtaXR0ZXI8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGwnZWxlbWVudG8gZWxpbWluYXRvIHByaW1hIGNoZSBxdWVzdG8gdmVuZ2EgZWZmZXR0aXZhbWVudGUgcmlzbW9zc28gZGFsbGEgbGlzdGEuXHJcbiAgICovXHJcbiAgQE91dHB1dChcIm9uRGVsZXRlQXR0YWNobWVudFwiKSBvbkRlbGV0ZUF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4gPSBuZXcgRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIFByb3ByaWV0w6AgcGVyIGdlc3Rpb25lIGNhcmljYW1lbnRvIG51b3ZvIGFsbGVnYXRvXHJcbiAgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8gPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICBuZXdNdWx0aXBsZUF0dGFjaG1lbnRzOiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBbXTtcclxuICBhdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlO1xyXG4gIC8vIHVwbG9hZFR5cGVFbnVtID0gVXBsb2FkVHlwZUVudW07XHJcbiAgbmV3QXR0YWNobWVudEZvcm06IEZvcm1Hcm91cDtcclxuICBzZWxlY3RlZEZpbGU6IEZpbGUgPSBudWxsO1xyXG4gIHNlbGVjdGVkRmlsZXM6IEFycmF5PEZpbGU+ID0gbnVsbDtcclxuICBzaG93Q3JvcEltYWdlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0FkZEF0dGFjaG1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nQWRkQXR0YWNobWVudDogVGVtcGxhdGVSZWY8YW55PjtcclxuICBkaWFsb2dSZWZBZGRBdHRhY2htZW50OiBNYXREaWFsb2dSZWY8VGVtcGxhdGVSZWY8YW55Pj47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0FkZE11bHRpcGxlQXR0YWNobWVudFwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dBZGRNdWx0aXBsZUF0dGFjaG1lbnQ6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgZGlhbG9nUmVmQ3JvcEltYWdlOiBNYXREaWFsb2dSZWY8VGVtcGxhdGVSZWY8YW55Pj47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0Nyb3BJbWFnZVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dDcm9wSW1hZ2U6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8vI3JlZ2lvbiBQcm9wcmlldMOgIHBlciBnZXN0aW9uZSByaWRpbWVuc2lvbmFtZW50byBmaWxlIGRpIHRpcG8gaW1hZ2VcclxuICBpbWFnZUNoYW5nZWRFdmVudDogYW55ID0gXCJcIjtcclxuICBjcm9wcGVkSW1hZ2U6IGFueSA9IFwiXCI7XHJcbiAgdHJhbnNmb3JtOiBJbWFnZVRyYW5zZm9ybSA9IHt9O1xyXG4gIGNhbnZhc1JvdGF0aW9uID0gMDtcclxuICBAVmlld0NoaWxkKEltYWdlQ3JvcHBlckNvbXBvbmVudCkgaW1hZ2VDcm9wcGVyOiBJbWFnZUNyb3BwZXJDb21wb25lbnQ7XHJcbiAgQFZpZXdDaGlsZChcImltYWdlSW5wdXRcIikgaW1hZ2VJbnB1dDogYW55O1xyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICBBdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlO1xyXG4gIHNlbGVjdGVkQXR0YWNobWVudDogSUF0dGFjaG1lbnREVE87XHJcblxyXG4gIG9yaWdpbmFsV2lkdGg6IG51bWJlcjtcclxuICBvcmlnaW5hbEhlaWdodDogbnVtYmVyO1xyXG4gIGN1c3RvbVdpZHRoOiBudW1iZXI7XHJcbiAgY3VzdG9tSGVpZ2h0OiBudW1iZXI7XHJcblxyXG4gIEBWaWV3Q2hpbGQoXCJhdHRhY2htZW50VGFibGVcIiwgeyBzdGF0aWM6IGZhbHNlIH0pIGF0dGFjaG1lbnRUYWJsZTogRXFwVGFibGVDb21wb25lbnQ7XHJcbiAgQFZpZXdDaGlsZChcImlubGluZVByZXZpZXdUZW1wbGF0ZVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBpbmxpbmVQcmV2aWV3VGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ1ByZXZpZXdcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nUHJldmlldzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgaW1hZ2VGaWxlOiBGaWxlO1xyXG5cclxuICBhZGRpbmdMaW5rTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgZGlhbG9nOiBNYXREaWFsb2csXHJcbiAgICBwcml2YXRlIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcclxuICAgIHByaXZhdGUgc2FuaXRpemVyOiBEb21TYW5pdGl6ZXIsXHJcbiAgICBwcml2YXRlIGh0dHA6IEh0dHBDbGllbnQsXHJcbiAgICBwcml2YXRlIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgIHByaXZhdGUgZXFwQXR0YWNobWVudFNlcnZpY2U6IEVxcEF0dGFjaG1lbnRTZXJ2aWNlXHJcbiAgKSB7fVxyXG5cclxuICBhc3luYyBuZ09uSW5pdCgpIHtcclxuICAgIC8vU2Ugw6ggc3RhdGEgcmljaGllc3RhIGxhIGdlc3Rpb25lIGRlbGxlIHNvbGUgaW1tYWdpbmkgYWxsb3JhIGltcG9zdGEgaWwgZmlsdHJvIHBlciBsZSBlc3RlbnNpb25pIHBvc3NpYmlsaSBkYSBjYXJpY2FyZVxyXG4gICAgaWYgKCF0aGlzLmFjY2VwdGVkRmlsZVR5cGVzKVxyXG4gICAgICBpZiAodGhpcy5hbGxvd09ubHlJbWFnZXMgPT0gdHJ1ZSkgdGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9IFwiaW1hZ2UvKlwiO1xyXG4gICAgICBlbHNlIHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMgPSBcIipcIjtcclxuXHJcbiAgICAvLyBTZSBub24gc29ubyBzdGF0aSBzcGVjaWZpY2F0aSBpIHRpcGkgZGEgZ2VzdGlyZSBtYSDDqCBzdGF0byBwYXNzYXRvIG51bGwgbyB1biBhcnJheSB2dW90byBpbXBvc3RvIGkgdGlwaSBkaSBkZWZhdWx0LlxyXG4gICAgaWYgKCF0aGlzLmFsbG93ZWRUeXBlcyB8fCB0aGlzLmFsbG93ZWRUeXBlcy5sZW5ndGggPT0gMClcclxuICAgICAgdGhpcy5hbGxvd2VkVHlwZXMgPSBbQXR0YWNobWVudFR5cGUuRklMRSwgQXR0YWNobWVudFR5cGUuTElOSywgQXR0YWNobWVudFR5cGUuRFJPUEJPWF07XHJcbiAgICBlbHNlIGlmIChcclxuICAgICAgdGhpcy5hbGxvd2VkVHlwZXMuZmluZCgodCkgPT4gdCAhPSBBdHRhY2htZW50VHlwZS5GSUxFICYmIHQgIT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiB0ICE9IEF0dGFjaG1lbnRUeXBlLkRST1BCT1gpXHJcbiAgICApIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuV2FybmluZyhcclxuICAgICAgICAnQWxtZW5vIHVubyBkZWdsaSBBdHRhY2htZW50VHlwZSBzZWxlemlvbmF0aSBuZWwgcGFyYW1ldHJvIFwiYWxsb3dlZFR5cGVzXCIgbm9uIGVzaXN0ZS4nXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzID0gW0F0dGFjaG1lbnRUeXBlLkZJTEUsIEF0dGFjaG1lbnRUeXBlLkxJTkssIEF0dGFjaG1lbnRUeXBlLkRST1BCT1hdO1xyXG4gICAgfVxyXG5cclxuICAgIC8vU2Ugw6ggc3RhdGEgcmljaGllc3RhIGxhIGdlc3Rpb25lIG11bHRpcGxhIGRlZ2xpIGFsbGVnYXRpIGFsbG9yYSBjb25maWd1cmEgbCdlcXAtdGFibGVcclxuICAgIGlmICh0aGlzLm11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlICYmICghdGhpcy5hdHRhY2htZW50c0NvbHVtbnMgfHwgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMubGVuZ3RoID09IDApKSB7XHJcbiAgICAgIHRoaXMuY29uZmlndXJlQ29sdW1ucygpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKSB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICB0aGlzLmNoZWNrQXR0YWNobWVudEltYWdlKCk7XHJcblxyXG4gICAgaWYgKHRoaXMuYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpKSB7XHJcbiAgICAgIHRoaXMuZXFwQXR0YWNobWVudFNlcnZpY2UubG9hZERyb3Bib3hTY3JpcHQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyByZWxvYWREYXRhKCkge1xyXG4gICAgaWYgKHRoaXMuYXR0YWNobWVudFRhYmxlKSB0aGlzLmF0dGFjaG1lbnRUYWJsZS5yZWxvYWREYXRhdGFibGUoKTtcclxuICB9XHJcblxyXG4gIGNoZWNrQXR0YWNobWVudEltYWdlKCkge1xyXG4gICAgdGhpcy5hdHRhY2htZW50c0xpc3QuZm9yRWFjaCgoYSkgPT4ge1xyXG4gICAgICBhLklzSW1hZ2UgPSBBdHRhY2htZW50SGVscGVyU2VydmljZS5jaGVja0ltYWdlRnJvbU1pbWVUeXBlKGEuRmlsZUNvbnRlbnRUeXBlKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIEdlc3Rpb25lIGVsZW5jbyBhbGxlZ2F0aVxyXG5cclxuICAvKipcclxuICAgKiBDb25maWd1cmEgbGUgY29sb25uZSBwZXIgbCdlcXAtdGFibGUgbmVsIGNhc28gaW4gY3VpIGlsIHBhcmFtZXRybyBcIm11bHRpcGxlQXR0YWNobWVudHNcIiDDqCBUUlVFLlxyXG4gICAqL1xyXG4gIGNvbmZpZ3VyZUNvbHVtbnMoKSB7XHJcbiAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucyA9IFtdO1xyXG4gICAgaWYgKHRoaXMuZGlzYWJsZUFjdGlvbiAhPSB0cnVlKSB7XHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLnB1c2goe1xyXG4gICAgICAgIGtleTogXCJhY3Rpb25cIixcclxuICAgICAgICBkaXNwbGF5OiBcIlwiLFxyXG4gICAgICAgIHR5cGU6IFR5cGVDb2x1bW4uTWVudUFjdGlvbixcclxuICAgICAgICBidXR0b25NZW51SWNvbjogXCJtb3JlX3ZlcnRcIixcclxuICAgICAgICBzdHlsZXM6IHsgZmxleDogXCIwIDAgNiVcIiB9LFxyXG4gICAgICAgIGFjdGlvbnM6IFtcclxuICAgICAgICAgIHsgbmFtZTogdGhpcy5kZWxldGVMYWJlbCwgaWNvbjogXCJkZWxldGVcIiwgZm46IChlbGVtZW50LCBpbmRleCwgY29sKSA9PiB0aGlzLmRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudCkgfVxyXG4gICAgICAgIF1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGRvd25sb2FkQ29sdW1uID0ge1xyXG4gICAgICBrZXk6IFwiYXR0YWNobWVudFwiLFxyXG4gICAgICBkaXNwbGF5OiBcIlwiLFxyXG4gICAgICB0eXBlOiBUeXBlQ29sdW1uLlNpbXBsZUFjdGlvbixcclxuICAgICAgc3R5bGVzOiB7IGZsZXg6IFwiMCAwIDYlXCIgfSxcclxuICAgICAgYWN0aW9uczogW1xyXG4gICAgICAgIHtcclxuICAgICAgICAgIG5hbWU6IFwiXCIsXHJcbiAgICAgICAgICBmb250YXdlc29tZTogdHJ1ZSxcclxuICAgICAgICAgIGljb246IChlbGVtZW50KSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNob3dJbmxpbmVQcmV2aWV3XHJcbiAgICAgICAgICAgICAgPyBlbGVtZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEVcclxuICAgICAgICAgICAgICAgID8gXCJmYXMgZmEtY2xvdWQtZG93bmxvYWQtYWx0XCJcclxuICAgICAgICAgICAgICAgIDogXCJmYXMgZmEtZXh0ZXJuYWwtbGluay1hbHRcIlxyXG4gICAgICAgICAgICAgIDogdGhpcy5nZXRBdHRhY2htZW50SWNvbihlbGVtZW50KTtcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBmbjogKGVsZW1lbnQsIGNvbCwgZWxlbWVudEluZGV4KSA9PiB0aGlzLnZpZXdBdHRhY2htZW50KGVsZW1lbnQpLFxyXG4gICAgICAgICAgdG9vbHRpcDoge1xyXG4gICAgICAgICAgICB0b29sdGlwVGV4dDogKGVsZW1lbnQpID0+IHtcclxuICAgICAgICAgICAgICByZXR1cm4gZWxlbWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFID8gdGhpcy5kb3dubG9hZExhYmVsIDogdGhpcy5vcGVuTGlua0xhYmVsO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICB0b29sdGlwUG9zaXRpb246IHRoaXMuZG93bmxvYWRUb29sdGlwUG9zaXRpb25cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIF1cclxuICAgIH07XHJcblxyXG4gICAgbGV0IGlubGluZVByZXZpZXdDb2x1bW4gPSB7XHJcbiAgICAgIGtleTogXCJJbmxpbmVQcmV2aWV3XCIsXHJcbiAgICAgIGRpc3BsYXk6IHRoaXMucHJldmlld0xhYmVsLFxyXG4gICAgICB0eXBlOiBUeXBlQ29sdW1uLkV4dGVybmFsVGVtcGxhdGUsXHJcbiAgICAgIGV4dGVybmFsVGVtcGxhdGU6IHRoaXMuaW5saW5lUHJldmlld1RlbXBsYXRlLFxyXG4gICAgICBzdHlsZXM6IHsgZmxleDogXCIwIDAgMTAlXCIgfVxyXG4gICAgfTtcclxuXHJcbiAgICBsZXQgZmlsZU5hbWVDb2x1bW4gPSB7IGtleTogXCJGaWxlTmFtZVwiLCBkaXNwbGF5OiB0aGlzLmZpbGVOYW1lTGFiZWwgfTtcclxuXHJcbiAgICBpZiAodGhpcy5zaG93SW5saW5lUHJldmlldykge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGlubGluZVByZXZpZXdDb2x1bW4pO1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGZpbGVOYW1lQ29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChkb3dubG9hZENvbHVtbik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGRvd25sb2FkQ29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChmaWxlTmFtZUNvbHVtbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbGltaW5hIHVuIGFsbGVnYXRvIGVsaW1pbmFuZG8gYW5jaGUgaWwgZmlsZSBwcmVzZW50ZSBuZWxsbyBzdG9yYWdlIGRpIGFyY2hpdmlhemlvbmUgdXRpbGl6emF0byAoQVdTIG8gY2FydGVsbGEgcHJvZ2V0dG8pXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgSUF0dGFjaG1lbnREVE8gZGEgY2FuY2VsbGFyZVxyXG4gICAqL1xyXG4gIGRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkNvbmZpcm0oXHJcbiAgICAgIHRoaXMuZGVsZXRlRGlhbG9nTWVzc2FnZSxcclxuICAgICAgKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVtb3ZlQXR0YWNobWVudEZyb21MaXN0KHRoaXMuYXR0YWNobWVudHNMaXN0LmluZGV4T2YoZWxlbWVudCkpO1xyXG4gICAgICB9LFxyXG4gICAgICB0cnVlLFxyXG4gICAgICB0aGlzLmRlbGV0ZURpYWxvZ1RpdGxlXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmltdW92ZSBsJ2FsbGVnYXRvIHNlbGV6aW9uYXRvIGRhbGxhIGxpc3RhIFwiYXR0YWNobWVudHNMaXN0XCIgZSBpbnZvY2EgbCdldmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsYSBsaXN0YSBhZ2dpb3JuYXRhLlxyXG4gICAqIEBwYXJhbSBhdHRhY2htZW50SW5kZXggSW5kaWNlIGRlbGwnYXR0YWNobWVudCBkYSByaW11b3ZlcmVcclxuICAgKi9cclxuICByZW1vdmVBdHRhY2htZW50RnJvbUxpc3QoYXR0YWNobWVudEluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMub25EZWxldGVBdHRhY2htZW50LmVtaXQodGhpcy5hdHRhY2htZW50c0xpc3RbYXR0YWNobWVudEluZGV4XSk7XHJcblxyXG4gICAgdGhpcy5hdHRhY2htZW50c0xpc3Quc3BsaWNlKGF0dGFjaG1lbnRJbmRleCwgMSk7XHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50VGFibGUpIHRoaXMuYXR0YWNobWVudFRhYmxlLnJlbG9hZERhdGF0YWJsZSgpO1xyXG4gICAgdGhpcy5sb2NhbEVkaXRlZEF0dGFjaG1lbnRzLmVtaXQodGhpcy5hdHRhY2htZW50c0xpc3QpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2NhcmljYSBsJ2FsbGVnYXRvIG8gYXByZSBpbCBsaW5rXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgQWxsZWdhdG8gZGEgbW9zdHJhcmVcclxuICAgKi9cclxuICB2aWV3QXR0YWNobWVudChhdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgaWYgKGF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICB3aW5kb3cub3BlbihhdHRhY2htZW50LkZpbGVQYXRoLCBcIl9ibGFua1wiKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChhdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ICYmIGF0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlICYmIGF0dGFjaG1lbnQuRmlsZU5hbWUpIHtcclxuICAgICAgbGV0IHNvdXJjZSA9IGBkYXRhOiR7YXR0YWNobWVudC5GaWxlQ29udGVudFR5cGV9O2Jhc2U2NCwke2F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjR9YDtcclxuICAgICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xyXG4gICAgICBsaW5rLmhyZWYgPSBzb3VyY2U7XHJcbiAgICAgIGxpbmsuZG93bmxvYWQgPSBgJHthdHRhY2htZW50LkZpbGVOYW1lfWA7XHJcbiAgICAgIGxpbmsuY2xpY2soKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZG93bmxvYWRBdHRhY2htZW50LmVtaXQoYXR0YWNobWVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSaWRlZmluaXNjZSBsJ2ljb25hIGRhIG1vc3RyYXJlIG5lbGxhIGNvbG9ubmEgZGVsbCdlcXAtdGFibGUgcGVyIG9nbmkgZmlsZS5cclxuICAgKiBMJ2ljb25hIHZhcmlhIGluIGJhc2UgYWxsJ2VzdGVuc2lvbmUgZGVsIGZpbGVcclxuICAgKiBAcGFyYW0gYXR0YWNobWVudFxyXG4gICAqL1xyXG4gIGdldEF0dGFjaG1lbnRJY29uKGF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPKSB7XHJcbiAgICBpZiAoYXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKSByZXR1cm4gXCJmYXMgZmEtbGlua1wiO1xyXG4gICAgZWxzZSByZXR1cm4gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuZ2V0SWNvbkZyb21GaWxlRXh0ZW5zaW9uZShhdHRhY2htZW50LkZpbGVFeHRlbnNpb24pO1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGNhc28gZGkgYWxsZWdhdG8gc2luZ29sbywgc2NlZ2xpZSBxdWFsZSBtZXRvZG8gcmljaGlhbWFyZSBpbiBiYXNlIGFsIHRpcG8gZGkgYWxsZWdhdG9cclxuICAgKi9cclxuICBhZGRGaWxlKGF0dGFjaG1lbnRUeXBlOiBBdHRhY2htZW50VHlwZSwgaW1hZ2VJbnB1dCA9IG51bGwpIHtcclxuICAgIGlmIChhdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKSB7XHJcbiAgICAgIHRoaXMuc3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpO1xyXG4gICAgfSBlbHNlIGlmIChhdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFKSB7XHJcbiAgICAgIGltYWdlSW5wdXQuY2xpY2soKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuY2hvb3NlRHJvcGJveEZpbGUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNyZWF0ZUF0dGFjaG1lbnRGb3JtKCkge1xyXG4gICAgLy9DcmVhIGxhIGZvcm0gcGVyIGxhIHZhbGlkYXppb25lIGRlaSBjYW1waVxyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybSA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoe1xyXG4gICAgICB0eXBlOiBbdGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcclxuICAgICAgbmFtZTogW3RoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZV0sXHJcbiAgICAgIHBhdGg6IFt0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZVBhdGhdLFxyXG4gICAgICBjdXN0b21IZWlnaHQ6IFt0aGlzLmN1c3RvbUhlaWdodF0sXHJcbiAgICAgIGN1c3RvbVdpZHRoOiBbdGhpcy5jdXN0b21XaWR0aF1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgY2xvc2UoZW1pdENsb3NlRXZlbnQgPSB0cnVlKSB7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQgPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50Rm9ybSkgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5yZXNldCgpO1xyXG5cclxuICAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgICB0aGlzLnJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKTtcclxuXHJcbiAgICBpZiAoZW1pdENsb3NlRXZlbnQgPT0gdHJ1ZSAmJiB0aGlzLmFib3J0QWRkQXR0YWNobWVudCkgdGhpcy5hYm9ydEFkZEF0dGFjaG1lbnQuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW4gYmFzZSBhbCB0aXBvIGRpIGFsbGVnYXRvIGNvbnRyb2xsYSBzZSBkaXNhYmlsaXRhcmUgbyBtZW5vIGlsIHB1bHNhbnRlIHBlciBzYWx2YXJlLlxyXG4gICAqIEZ1bnppb25lIHVzYXRhIG5lbCBbZGlzYWJsZV0gZGVsIHB1bHNhbnRlIFwiU2FsdmFcIiBkZWwgZGlhbG9nIHBlciBsJ2FnZ2l1bnRhIGRpIHVuIGFsbGVnYXRvLlxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgZGlzYWJsZVNhdmUoKSB7XHJcbiAgICBpZiAodGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSB7XHJcbiAgICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSkge1xyXG4gICAgICAgIHJldHVybiAhdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiAhdGhpcy5uZXdBdHRhY2htZW50LkZpbGVQYXRoO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gKFxyXG4gICAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5maWx0ZXIoXHJcbiAgICAgICAgICAocCkgPT5cclxuICAgICAgICAgICAgKHAuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSAmJiAhcC5GaWxlRGF0YUJhc2U2NCkgfHxcclxuICAgICAgICAgICAgKHAuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiAhcC5GaWxlUGF0aClcclxuICAgICAgICApLmxlbmd0aCA+IDBcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbmZpcm1BZGRBdHRhY2htZW50KCkge1xyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IHRoaXMuaW1hZ2VDcm9wcGVyLmNyb3AoKS5iYXNlNjQuc3BsaXQoXCI7YmFzZTY0LFwiKVsxXTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSB7XHJcbiAgICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiAhdGhpcy5uZXdBdHRhY2htZW50LkZpbGVOYW1lKVxyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZSA9IHRoaXMubmV3QXR0YWNobWVudC5GaWxlUGF0aDtcclxuXHJcbiAgICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKSB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNMaXN0LnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPT0gbnVsbCB8fCB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMubGVuZ3RoID09IDApIHJldHVybjtcclxuXHJcbiAgICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKSB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNMaXN0ID0gdGhpcy5hdHRhY2htZW50c0xpc3QuY29uY2F0KHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuYXR0YWNobWVudFRhYmxlKSB0aGlzLmF0dGFjaG1lbnRUYWJsZS5yZWxvYWREYXRhdGFibGUoKTtcclxuXHJcbiAgICB0aGlzLmxvY2FsRWRpdGVkQXR0YWNobWVudHMuZW1pdCh0aGlzLmF0dGFjaG1lbnRzTGlzdCk7XHJcblxyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgICAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXByZSBpbCBkaWFsb2cgcGVyIGwnYW50ZXByaW1hIGRlbGwnYWxsZWdhdG8gc2VsZXppb25hdG8uXHJcbiAgICogQHBhcmFtIHJvd1xyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgYXN5bmMgb3BlblByZXZpZXdEaWFsb2cocm93OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHJvdykpO1xyXG5cclxuICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFKSB7XHJcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUuc3RhcnRzV2l0aChcInZpZGVvXCIpKSB7XHJcbiAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuV2FybmluZyh0aGlzLnZpZGVvUHJldmlld0Vycm9yTWVzc2FnZSk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZS5zdGFydHNXaXRoKFwiYXVkaW9cIikpIHtcclxuICAgICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5XYXJuaW5nKHRoaXMuYXVkaW9QcmV2aWV3RXJyb3JNZXNzYWdlKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5nZXRBdHRhY2htZW50RW5kcG9pbnQgJiYgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuSXNJbWFnZSAmJiAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQpIHtcclxuICAgICAgYXdhaXQgdGhpcy5nZXRBdHRhY2htZW50QnlJRCgpXHJcbiAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xyXG4gICAgICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSByZXMuRmlsZURhdGFCYXNlNjQ7XHJcbiAgICAgICAgfSlcclxuICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xyXG4gICAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IoZXJyKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFJlc291cmNlVXJsKFxyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVQYXRoXHJcbiAgICAgICk7XHJcbiAgICB9IGVsc2UgaWYgKFxyXG4gICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlICYmXHJcbiAgICAgICF0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJlxyXG4gICAgICAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVRodW1ibmFpbEJhc2U2NFxyXG4gICAgKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkluZm8oXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGVsbCdhbGxlZ2F0bywgZmlsZSBtYW5jYW50ZS5cIik7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2UpIHtcclxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVQYXRoICYmIHRoaXMucHJvZHVjdGlvbkJhc2VVcmwpIHtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFJlc291cmNlVXJsKFxyXG4gICAgICAgICAgXCJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9ndmlldz91cmw9XCIgK1xyXG4gICAgICAgICAgICB0aGlzLnByb2R1Y3Rpb25CYXNlVXJsICtcclxuICAgICAgICAgICAgXCIvXCIgK1xyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aCArXHJcbiAgICAgICAgICAgIFwiJmVtYmVkZGVkPXRydWVcIlxyXG4gICAgICAgICk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuSW5mbyhcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkZWwgZG9jdW1lbnRvIVwiKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmRpYWxvZy5vcGVuKHRoaXMuZGlhbG9nUHJldmlldywge1xyXG4gICAgICBkaXNhYmxlQ2xvc2U6IHRydWUsXHJcbiAgICAgIGhhc0JhY2tkcm9wOiB0cnVlXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGdldEF0dGFjaG1lbnRCeUlEKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0PElBdHRhY2htZW50RFRPPih0aGlzLmdldEF0dGFjaG1lbnRFbmRwb2ludCwgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQpLnRvUHJvbWlzZSgpO1xyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIEdlc3Rpb25lIGNhcmljYW1lbnRvIGZpbGVcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnRvIHNjYXRlbmF0byBhbGxhIHNlbGV6aW9uZSBkZWwgZmlsZSAobyBkZWkgZmlsZSkuXHJcbiAgICogU2UgaWwgY2FyaWNhbWVudG8gw6ggU0lOR09MTyBvIHNlIGNvbXVucXVlIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIHNvbG8gZmlsZSBhbGxvcmEgc2kgb2NjdXBhIGRpIGNvbnRyb2xsYXJlIHNlIHNpIHRyYXR0YSBkaSB1biBpbW1hZ2luZSBpbiBtb2RvIGRhXHJcbiAgICogbW9zdHJhcmUgbGUgZnVuemlvbmFsaXTDoCBkZWwgY3JvcHBpZSAocGVyIHJpdGFnbGlhcmUgbCdpbW1hZ2luZSkgb3BwdXJlIG5vLlxyXG4gICAqIFNlIGlsIGZpbGUgY2FyaWNhdG8gbm9uIMOoIHVuIGltbWFnaW5lIGFsbG9yYSBnZW5lcmEgZGlyZXR0YW1lbnRlIGlsIGJhc2U2NCBlIGxvIGFzc29jaWEgYWxsJ2FsbGVnYXRvIGRhIHNhbHZhcmUuXHJcbiAgICogU2UgaW52ZWNlIGlsIGNhcmljYW1lbnRvIGRlaSBmaWxlIMOoIE1VTFRJUExPIGUgc29ubyBwcmVzZW50aSBwacO5IGZpbGUgYWxsb3JhIGVzZWd1ZSBsZSBzdGVzc2Ugb3BlcmF6aW9uaSBpZ25vcmFuZG8gcGVyw7IgaWwgY29udHJsbG9cclxuICAgKiBpbW1hZ2luZSBwZXIgaWwgY3JvcHBpZSAoaW4gY2FzbyBkaSBjYXJpY2FtZW50byBtdWx0aXBsbyBsZSBmdW56aW9uYWxpdMOgIGRlbCBjcm9wcGllIHNvbm8gZGlzYWJpbGl0YXRlKS5cclxuICAgKi9cclxuICBhc3luYyBvbkZpbGVBZGRlZChldmVudCwgaXNGaWxlRHJvcHBlZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgIGxldCBmaWxlc09uSW5wdXQgPSBpc0ZpbGVEcm9wcGVkID8gZXZlbnQgOiBldmVudC50YXJnZXQuZmlsZXM7XHJcblxyXG4gICAgLy9TZSDDqCBzdGF0byByaWNoaWVzdG8gaWwgY2FyaWNhbWVudG8gU0lOR09MTyBvcHB1cmUgc2UgaWwgY2FyaWNhbWVudG8gw6ggTVVMVElQTE8gbWEgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gc29sbyBmaWxlXHJcbiAgICAvL2FsbG9yYSB2ZXJpZmljYSBzZSBpbCBmaWxlIMOoIHVuIGltbWFnaW5lIChwZXIgbW9zdHJhcmUgaWwgQ1JPUFBJRSlcclxuICAgIGlmIChbLi4uZmlsZXNPbklucHV0XS5sZW5ndGggPT0gMSB8fCB0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBmaWxlc09uSW5wdXRbMF07XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IGZpbGVzT25JbnB1dDtcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZSkgcmV0dXJuO1xyXG5cclxuICAgICAgLy9NZW1vcml6emEgaSBkYXRpIHBlciBsJ2FsbGVnYXRvXHJcbiAgICAgIHRoaXMubmV3QXR0YWNobWVudCA9IGF3YWl0IHRoaXMuY3JlYXRlQXR0YWNobWVudEZyb21VcGxvYWRlZEZpbGUodGhpcy5zZWxlY3RlZEZpbGUsIGZhbHNlKTtcclxuICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG4gICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMucHVzaCh0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG5cclxuICAgICAgLy9TZSDDqCBzdGF0YSByaWNoaWVzdGEgbGEgZ2VzdGlvbmUgZGVsbGUgc29sZSBpbW1hZ2luaSBtYSBwZXIgZXJyb3JlIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIGZpbGUgY2hlIG5vbiDDqCB1biBpbW1hZ2luZVxyXG4gICAgICBsZXQgY2hlY2tPbmx5SW1hZ2UgPSB0aGlzLmNoZWNrQWxsb3dPbmx5SW1hZ2VGaWxlKHRoaXMubmV3QXR0YWNobWVudCk7XHJcbiAgICAgIGlmIChjaGVja09ubHlJbWFnZSA9PSBmYWxzZSkgcmV0dXJuO1xyXG5cclxuICAgICAgdGhpcy5jcmVhdGVBdHRhY2htZW50Rm9ybSgpO1xyXG5cclxuICAgICAgLy9WZXJpZmljYSBzZSBpbCBmaWxlIGNhcmljYXRvIMOoIHVuJ2ltbWFnaW5lIG9wcHVyZSBuby4gU2Ugw6ggdW4gaW1tYWdpbmUsIHByaW1hIGRpIGNhcmljYXJsYSBtb3N0cmEgaWwgY3JvcHBpZSBwZXIgaWwgcmVzaXplLlxyXG4gICAgICAvL1NlIG5vbiDDqCB1biBpbW1hZ2luZSBhbGxvcmEgZ2VuZXJhIGlsIEJhc2U2NFxyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LklzSW1hZ2UgPT0gdHJ1ZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0SW1hZ2VEaW1lbnNpb25zKGZpbGVzT25JbnB1dFswXSk7XHJcblxyXG4gICAgICAgIC8vTW9zdHJhIGlsIGNyb3BwaWUgZSBkaXNhYmlsaXRhIGxhIGZvcm0gZmluY2jDqCBub24gdGVybWluYSBsYSBtb2RpZmljYSBkZWxsJ2ltbWFnaW5lXHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5kaXNhYmxlKCk7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5jb250cm9sc1tcImN1c3RvbVdpZHRoXCJdLmVuYWJsZSgpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0uY29udHJvbHNbXCJjdXN0b21IZWlnaHRcIl0uZW5hYmxlKCk7XHJcbiAgICAgICAgdGhpcy5zaG93Q3JvcEltYWdlID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmltYWdlRmlsZSA9IGV2ZW50O1xyXG5cclxuICAgICAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZSA9IHRoaXMuZGlhbG9nLm9wZW4odGhpcy5kaWFsb2dDcm9wSW1hZ2UsIHtcclxuICAgICAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcclxuICAgICAgICAgIGhhc0JhY2tkcm9wOiB0cnVlLFxyXG4gICAgICAgICAgd2lkdGg6IFwiNjAlXCIsXHJcbiAgICAgICAgICBtYXhIZWlnaHQ6IFwiODAlXCIsXHJcbiAgICAgICAgICBtYXhXaWR0aDogXCI3MHZoXCJcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgICAgICBsZXQgYmFzZTY0UmVzdWx0ID0gYXdhaXQgdGhpcy5nZXRCYXNlNjRGcm9tRmlsZSh0aGlzLnNlbGVjdGVkRmlsZSk7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gYmFzZTY0UmVzdWx0LkJhc2U2NEZpbGU7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IGJhc2U2NFJlc3VsdC5Db250ZW50VHlwZTtcclxuICAgICAgICB0aGlzLmNvbmZpcm1BZGRBdHRhY2htZW50KCk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IGZpbGVzT25JbnB1dDtcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZXMgfHwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aCA9PSAwKSByZXR1cm47XHJcblxyXG4gICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgbGV0IG5ld0F0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0gYXdhaXQgdGhpcy5jcmVhdGVBdHRhY2htZW50RnJvbVVwbG9hZGVkRmlsZShcclxuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlc1tpXSxcclxuICAgICAgICAgIHRydWUsXHJcbiAgICAgICAgICB0cnVlXHJcbiAgICAgICAgKTtcclxuICAgICAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIG1hIHBlciBlcnJvcmUgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gZmlsZSBjaGUgbm9uIMOoIHVuIGltbWFnaW5lXHJcbiAgICAgICAgbGV0IGNoZWNrT25seUltYWdlID0gdGhpcy5jaGVja0FsbG93T25seUltYWdlRmlsZShuZXdBdHRhY2htZW50KTtcclxuICAgICAgICBpZiAoY2hlY2tPbmx5SW1hZ2UgPT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2gobmV3QXR0YWNobWVudCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5jb25maXJtQWRkQXR0YWNobWVudCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vUmVzZXR0byBpbCB2YWxvcmUgZGVsIGZpbGUgaW5wdXQgaW4gbW9kbyBkYSBzY2F0ZW5hcmUgaWwgY2hhbmdlIGFuY2hlIHNlIHNpIGRvdmVzc2UgY2FyaWNhcmUgbG8gc3Rlc3NvIGZpbGVcclxuICAgIGlmICghaXNGaWxlRHJvcHBlZCkgZXZlbnQudGFyZ2V0LnZhbHVlID0gXCJcIjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgcGFydGlyZSBkYWwgRklMRSByaWNldnV0byBpbiBpbnB1dCByaWNvc3RydWlzY2UgbCdvZ2dldHRvIElBdHRhY2htZW50RFRPIGUgbG8gcmVzdGl0dWlzY2UuXHJcbiAgICogU2UgaWwgcGFyYW1ldHJvIGdldEJhc2U2NCB2aWVuZSBwYXNzYXRvIGEgVFJVRSBhbGxvcmEsIHNlbXByZSBhIHBhcnRpcmUgZGFsIGZpbGUsZ2VuZXJhIGlsIGJhc2U2NCBlXHJcbiAgICogcmljYXZhIGlsIENvbnRlbnRUeXBlIGRhIGFzc29jaWFyZSBhbGwnb2dnZXR0byBJQXR0YWNobWVudERUTyBkYSByZXN0aXR1aXJlXHJcbiAgICogQHBhcmFtIGN1cnJlbnRGaWxlIE9nZ2V0dG8gRklMRSBkYSBwcm9jZXNzYXJlXHJcbiAgICogQHBhcmFtIGdldEJhc2U2NCBTZSBUUlVFIGFsbG9yYSBjYWxjb2xhIGJhc2U2NCBlIENvbnRlbnRUeXBlIGRlbCBmaWxlIHBhc3NhdG8gaW4gaW5wdXRcclxuICAgKiBAcmV0dXJucyBSZXN0aXR1aXNjZSB1biBvZ2dldHRvIGRpIHRpcG8gSUF0dGFjaG1lbnREVE9cclxuICAgKi9cclxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZUF0dGFjaG1lbnRGcm9tVXBsb2FkZWRGaWxlKFxyXG4gICAgY3VycmVudEZpbGU6IEZpbGUsXHJcbiAgICBnZXRCYXNlNjQ6IGJvb2xlYW4gPSB0cnVlLFxyXG4gICAgY3JvcEZpbGU6IGJvb2xlYW4gPSBmYWxzZVxyXG4gICk6IFByb21pc2U8SUF0dGFjaG1lbnREVE8+IHtcclxuICAgIGxldCBuZXdBdHRhY2htZW50OiBJQXR0YWNobWVudERUTyA9IHt9IGFzIElBdHRhY2htZW50RFRPO1xyXG4gICAgLy9NZW1vcml6emEgaSBkYXRpIHBlciBsJ2FsbGVnYXRvXHJcbiAgICBuZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID0gQXR0YWNobWVudFR5cGUuRklMRTtcclxuICAgIG5ld0F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlID0gY3VycmVudEZpbGUudHlwZTtcclxuICAgIG5ld0F0dGFjaG1lbnQuRmlsZU5hbWUgPSBjdXJyZW50RmlsZS5uYW1lO1xyXG4gICAgbmV3QXR0YWNobWVudC5GaWxlRXh0ZW5zaW9uID0gY3VycmVudEZpbGUubmFtZS5zdWJzdHIoY3VycmVudEZpbGUubmFtZS5sYXN0SW5kZXhPZihcIi5cIikgKyAxKTtcclxuICAgIG5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9IEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmNoZWNrSW1hZ2VGcm9tTWltZVR5cGUoY3VycmVudEZpbGUudHlwZSk7XHJcblxyXG4gICAgaWYgKGdldEJhc2U2NCA9PSB0cnVlKSB7XHJcbiAgICAgIGxldCBiYXNlNjRSZXN1bHQgPSBhd2FpdCB0aGlzLmdldEJhc2U2NEZyb21GaWxlKGN1cnJlbnRGaWxlKTtcclxuICAgICAgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IGJhc2U2NFJlc3VsdC5CYXNlNjRGaWxlO1xyXG4gICAgICBuZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IGJhc2U2NFJlc3VsdC5Db250ZW50VHlwZTtcclxuXHJcbiAgICAgIGlmIChuZXdBdHRhY2htZW50LklzSW1hZ2UgJiYgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiBjcm9wRmlsZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0Q3JvcHBlZEFuZFVwbG9hZChgZGF0YToke2Jhc2U2NFJlc3VsdC5Db250ZW50VHlwZX07YmFzZTY0LCR7YmFzZTY0UmVzdWx0LkJhc2U2NEZpbGV9YCwgbmV3QXR0YWNobWVudCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbmV3QXR0YWNobWVudDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgcGFydGlyZSBkYWwgZmlsZSBwYXNzYXRvIGluIGlucHV0IHJlc3RpdHVpc2NlIHVuIG9nZ2V0dG9cclxuICAgKiBjb250ZW5lbnRlIGlsIGJhc2U2NCBkZWwgZmlsZSBlIGlsIHN1byBjb250ZW50VHlwZVxyXG4gICAqIEBwYXJhbSBjdXJyZW50RmlsZSBPZ2dldHRvIEZpbGUgZGEgY3VpIGVzdHJhcG9sYXJlIGJhc2U2NCBlIGNvbnRlbnRUeXBlXHJcbiAgICogQHJldHVybnMgUmVzdGl0dWlzY2UgdW4gb2dnZXR0byBhdmVudGUgbGUgcHJvcHJpZXTDoCBCYXNlNjRGaWxlIGUgQ29udGVudFR5cGVcclxuICAgKi9cclxuICBwcml2YXRlIGFzeW5jIGdldEJhc2U2NEZyb21GaWxlKGN1cnJlbnRGaWxlOiBGaWxlKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGxldCBiYXNlNjRGaWxlID0gYXdhaXQgdG9CYXNlNjQoY3VycmVudEZpbGUpO1xyXG4gICAgbGV0IGNvbnRlbnRUeXBlOiBzdHJpbmcgPSBudWxsO1xyXG4gICAgaWYgKGJhc2U2NEZpbGUpIHtcclxuICAgICAgLy8gTG9yaXMgMjAvMDEvMjAyMjogUFJPQkxFTUEgLSBRdWFuZG8gZXNlZ3VvIGwndXBsb2FkIGRpIHVuIGZpbGUgLnNxbCBub24gdmllbmUgc2FsdmF0by9zY2FyaWNhdG8gY29ycmV0dGFtZW50ZS5cclxuICAgICAgLy8gICAgICAgICAgICAgICAgICAgUXVlc3RvIHN1Y2NlZGUgcGVyY2jDqCBub24gdmllbmUgcG9wb2xhdG8gaWwgRmlsZUNvbnRlbnRUeXBlLiBQZXIgcmlzb2x2ZXJlIGlsIHByb2JsZW1hXHJcbiAgICAgIC8vICAgICAgICAgICAgICAgICAgIGZhY2NpbyB1biBjb250cm9sbG8gZSBzZSBub24gZXNpc3RlIGlsIEZpbGVDb250ZW50VHlwZSBhbGxvcmEgbG8gcmVjdXBlcm8gZGFsIGJhc2U2NCBvdHRlbnV0by5cclxuICAgICAgY29udGVudFR5cGUgPSBiYXNlNjRGaWxlLnNwbGl0KFwiLFwiKVswXS5zcGxpdChcIjpcIilbMV0uc3BsaXQoXCI7XCIpWzBdO1xyXG4gICAgICAvLyBVbiBhbHRybyBtZXRvZG8gcGVyIGxlZ2dlcmUgaWwgY2NvbnRlbnQgdHlwZSBkZWwgZmlsZSDDqCB0cmFtaXRlIHVuYSByZWd1bGFyIGV4cHJlc3Npb246XHJcbiAgICAgIGJhc2U2NEZpbGUgPSBiYXNlNjRGaWxlLnNwbGl0KFwiLFwiKVsxXTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcmVzdWx0ID0ge1xyXG4gICAgICBCYXNlNjRGaWxlOiBiYXNlNjRGaWxlLFxyXG4gICAgICBDb250ZW50VHlwZTogY29udGVudFR5cGVcclxuICAgIH07XHJcblxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnRyb2xsYSBzZSBpbCBmaWxlIGNoZSBzaSBzdGEgY2FyaWNhbmRvIMOoIHN1cHBvcnRhdG8gZGFsIHNpc3RlbWEuXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBwcml2YXRlIGNoZWNrQWNjZXB0ZWRGaWxlcygpOiBib29sZWFuIHtcclxuICAgIGlmIChcclxuICAgICAgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSAmJiB0aGlzLnNlbGVjdGVkRmlsZS50eXBlLnN0YXJ0c1dpdGgoXCJ2aWRlb1wiKSkgfHxcclxuICAgICAgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgPT0gdHJ1ZSAmJiBbLi4udGhpcy5zZWxlY3RlZEZpbGVzXS5maWx0ZXIoKHApID0+IHAudHlwZS5zdGFydHNXaXRoKFwidmlkZW9cIikpLmxlbmd0aCA+IDApXHJcbiAgICApXHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICBpZiAodGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9PSBcIipcIikgcmV0dXJuIHRydWU7XHJcblxyXG4gICAgLy9WZXJpZmljYSBjaGUgaSB0aXBpIGRlbCBmaWxlIChvIGRlaSBmaWxlKSBjYXJpY2F0aSBzaWFubyBjb2VyZW50aSBjb24gcXVlbGxpIGFjY2V0dGF0aSBkYWxsYSBkaXJldHRpdmFcclxuICAgIGxldCBhY2NlcHRlZDogYm9vbGVhbiA9IHRydWU7XHJcbiAgICBpZiAodGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSBhY2NlcHRlZCA9IHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMuaW5jbHVkZXModGhpcy5zZWxlY3RlZEZpbGUudHlwZSk7XHJcbiAgICBlbHNlIHtcclxuICAgICAgbGV0IHVwbG9hZGVkRmlsZVR5cGVzOiBzdHJpbmdbXSA9IFsuLi50aGlzLnNlbGVjdGVkRmlsZXNdLm1hcCgocCkgPT4gcC50eXBlKTtcclxuICAgICAgdXBsb2FkZWRGaWxlVHlwZXMuZm9yRWFjaCgodHlwZSkgPT4ge1xyXG4gICAgICAgIGlmICghdGhpcy5hY2NlcHRlZEZpbGVUeXBlcy5pbmNsdWRlcyh0eXBlKSkgYWNjZXB0ZWQgPSBmYWxzZTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy9RdWVzdG8gY29udHJvbGxvIHBlcm1ldHRlIGRpIGdlc3RpcmUgbGUgY2FzaXN0aWNoZSBwZXIgY3VpIHZlbmdvbm8gaW5kaWNhdGkgY29tZSB0aXBpIHZhbGlkaSwgYWQgZXNlbXBpbywgJ2ltYWdlLyonXHJcbiAgICBpZiAoIWFjY2VwdGVkICYmIHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBmb3IgKGxldCB0IG9mIHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMuc3BsaXQoXCIsXCIpLmZpbHRlcigodCkgPT4gdC5pbmNsdWRlcyhcIipcIikpKSB7XHJcbiAgICAgICAgYWNjZXB0ZWQgPSB0aGlzLnNlbGVjdGVkRmlsZS50eXBlLnN0YXJ0c1dpdGgodC5zcGxpdChcIipcIilbMF0pO1xyXG4gICAgICAgIGlmIChhY2NlcHRlZCkgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBhY2NlcHRlZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIGVxcC1hdHRhY2htZW50cyDDqCBzdGF0YSBjb25maWd1cmF0YSBwZXIgaWwgY2FyaWNhbWVudG8gZGVsbGUgc29sZSBpbW1hZ2luaSBhbGxvcmEgdmVyaWZpY2EgY2hlIGlsIGZpbGUgcGFzc2F0byBpblxyXG4gICAqIGlucHV0IHNpYSBlZmZldHRpdmFtZW50ZSB1biBpbW1hZ2luZSBvIG5vLlxyXG4gICAqIFNlIGlsIGNvbnRyb2xsbyB2YSBhIGJ1b24gZmluZSByZXN0aXR1aXNjZSBUUlVFIGFsdHJpbWVudGkgbW9zdHJhIHVuIG1lc3NhZ2dpbyBkJ2Vycm9yZSBlIHJlc3RpdHVpc2NlIEZBTFNFXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjaGVja0FsbG93T25seUltYWdlRmlsZShuZXdBdHRhY2htZW50KTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5hbGxvd09ubHlJbWFnZXMgPT0gdHJ1ZSAmJiBuZXdBdHRhY2htZW50LklzSW1hZ2UgIT0gdHJ1ZSkge1xyXG4gICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5FcnJvcih0aGlzLm5vSW1hZ2VTZWxlY3RlZEVycm9yTWVzc2FnZSk7XHJcbiAgICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuY2hlY2tBY2NlcHRlZEZpbGVzKCkpIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IodGhpcy53cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZSk7XHJcbiAgICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIC8vI3JlZ2lvbiBHZXN0aW9uZSBjcm9wIGZpbGVcclxuXHJcbiAgZ2V0SW1hZ2VEaW1lbnNpb25zKGltZzogYW55KSB7XHJcbiAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG4gICAgcmVhZGVyLm9ubG9hZCA9IChlOiBhbnkpID0+IHtcclxuICAgICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcclxuICAgICAgaW1hZ2Uuc3JjID0gZS50YXJnZXQucmVzdWx0O1xyXG4gICAgICBpbWFnZS5vbmxvYWQgPSAocnMpID0+IHtcclxuICAgICAgICB0aGlzLm9yaWdpbmFsSGVpZ2h0ID0gcnMuY3VycmVudFRhcmdldFtcImhlaWdodFwiXTtcclxuICAgICAgICB0aGlzLm9yaWdpbmFsV2lkdGggPSBycy5jdXJyZW50VGFyZ2V0W1wid2lkdGhcIl07XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9yaWdpbmFsV2lkdGggPiAxMjgwKSB7XHJcbiAgICAgICAgICB0aGlzLmN1c3RvbVdpZHRoID0gMTI4MDtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gTWF0aC5yb3VuZCgoMTI4MCAqIHRoaXMub3JpZ2luYWxIZWlnaHQpIC8gdGhpcy5vcmlnaW5hbFdpZHRoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21IZWlnaHQgPSBycy5jdXJyZW50VGFyZ2V0W1wiaGVpZ2h0XCJdO1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21XaWR0aCA9IHJzLmN1cnJlbnRUYXJnZXRbXCJ3aWR0aFwiXTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcbiAgICB9O1xyXG4gICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoaW1nKTtcclxuICB9XHJcblxyXG4gIHJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKSB7XHJcbiAgICB0aGlzLmN1c3RvbVdpZHRoID0gdGhpcy5vcmlnaW5hbFdpZHRoO1xyXG4gICAgdGhpcy5jdXN0b21IZWlnaHQgPSB0aGlzLm9yaWdpbmFsSGVpZ2h0O1xyXG4gICAgdGhpcy5jYW52YXNSb3RhdGlvbiA9IDA7XHJcbiAgICB0aGlzLnRyYW5zZm9ybSA9IHt9O1xyXG4gIH1cclxuXHJcbiAgb25EaW1lbnNpb25zQ2hhbmdlKGRpbWVuc2lvbjogc3RyaW5nKSB7XHJcbiAgICBpZiAoZGltZW5zaW9uID09IFwiSFwiKSB7XHJcbiAgICAgIHRoaXMuY3VzdG9tV2lkdGggPSBNYXRoLnJvdW5kKCh0aGlzLmN1c3RvbUhlaWdodCAqIHRoaXMub3JpZ2luYWxXaWR0aCkgLyB0aGlzLm9yaWdpbmFsSGVpZ2h0KTtcclxuICAgIH0gZWxzZSBpZiAoZGltZW5zaW9uID09IFwiV1wiKSB7XHJcbiAgICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gTWF0aC5yb3VuZCgodGhpcy5jdXN0b21XaWR0aCAqIHRoaXMub3JpZ2luYWxIZWlnaHQpIC8gdGhpcy5vcmlnaW5hbFdpZHRoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGltYWdlQ3JvcHBlZChldmVudDogSW1hZ2VDcm9wcGVkRXZlbnQpIHtcclxuICAgIHRoaXMuY3JvcHBlZEltYWdlID0gZXZlbnQuYmFzZTY0O1xyXG4gICAgdGhpcy5nZXRDcm9wcGVkQW5kVXBsb2FkKHRoaXMuY3JvcHBlZEltYWdlLCB0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q3JvcHBlZEFuZFVwbG9hZChmaWxlLCBuZXdBdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xyXG5cclxuICAgIHZhciBmaWxlOiBhbnkgPSBiYXNlNjRUb0ZpbGUoZmlsZSk7XHJcblxyXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuY29tcHJlc3Npb25PcHRpb25zO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcHJpbWUgbCdpbW1hZ2luZSBwYXNzYW5kbyBjb21lIHBhcmFtZXRyaSBsZSBvcHRpb25zIGNyZWF0ZSBuZWxsJ29nZ2V0dG8gc29wcmEsIGUgaWwgZmlsZSBkYWwgcmVhZGVyIHByaW5jaXBhbGVcclxuICAgICAqL1xyXG4gICAgaW1hZ2VDb21wcmVzc2lvbihmaWxlLCBvcHRpb25zKS50aGVuKChmaWxlQ29tcHJlc3NlZCkgPT4ge1xyXG4gICAgICBsZXQgZmlsZVJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcblxyXG4gICAgICAvL0ZhY2NpbyBsYSBwdXNoIGRpIG9nbmkgZmlsZSBhbGwnaW50ZXJubyBkZWxsJ2FycmF5IGRpIGZpbGUgZGVsbCdpdGVtIGRhIG1hbmRhcmUgYWwgc2VydmVyXHJcbiAgICAgIGZpbGVSZWFkZXIub25sb2FkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGxldCByZXN1bHRSZWFkZXIgPSA8c3RyaW5nPmZpbGVSZWFkZXIucmVzdWx0O1xyXG4gICAgICAgIHZhciBtYXJrZXIgPSBcIjtiYXNlNjQsXCI7XHJcbiAgICAgICAgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IHJlc3VsdFJlYWRlci5zdWJzdHJpbmcocmVzdWx0UmVhZGVyLmluZGV4T2YobWFya2VyKSArIG1hcmtlci5sZW5ndGgpO1xyXG4gICAgICAgIHNlbGYuc2hvd0Nyb3BJbWFnZSA9IGZhbHNlO1xyXG4gICAgICAgIGlmIChzZWxmLm5ld0F0dGFjaG1lbnRGb3JtKSB7XHJcbiAgICAgICAgICBzZWxmLm5ld0F0dGFjaG1lbnRGb3JtLmVuYWJsZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuXHJcbiAgICAgIGZpbGVSZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlQ29tcHJlc3NlZCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIGNvbmZpcm1Dcm9wKCkge1xyXG4gIC8vICAgdGhpcy5pbWFnZUNyb3BwZXIuY3JvcCgpO1xyXG4gIC8vICAgdGhpcy5kaWFsb2dSZWZDcm9wSW1hZ2UuY2xvc2UoKTtcclxuICAvLyAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gIC8vIH1cclxuXHJcbiAgcm90YXRlTGVmdCgpIHtcclxuICAgIHRoaXMuY2FudmFzUm90YXRpb24tLTtcclxuICAgIHRoaXMuZmxpcEFmdGVyUm90YXRlKCk7XHJcbiAgfVxyXG5cclxuICByb3RhdGVSaWdodCgpIHtcclxuICAgIHRoaXMuY2FudmFzUm90YXRpb24rKztcclxuICAgIHRoaXMuZmxpcEFmdGVyUm90YXRlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZsaXBBZnRlclJvdGF0ZSgpIHtcclxuICAgIGNvbnN0IGZsaXBwZWRIID0gdGhpcy50cmFuc2Zvcm0uZmxpcEg7XHJcbiAgICBjb25zdCBmbGlwcGVkViA9IHRoaXMudHJhbnNmb3JtLmZsaXBWO1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7XHJcbiAgICAgIC4uLnRoaXMudHJhbnNmb3JtLFxyXG4gICAgICBmbGlwSDogZmxpcHBlZFYsXHJcbiAgICAgIGZsaXBWOiBmbGlwcGVkSFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGZsaXBIb3Jpem9udGFsKCkge1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7XHJcbiAgICAgIC4uLnRoaXMudHJhbnNmb3JtLFxyXG4gICAgICBmbGlwSDogIXRoaXMudHJhbnNmb3JtLmZsaXBIXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgZmxpcFZlcnRpY2FsKCkge1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7XHJcbiAgICAgIC4uLnRoaXMudHJhbnNmb3JtLFxyXG4gICAgICBmbGlwVjogIXRoaXMudHJhbnNmb3JtLmZsaXBWXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8qKlxyXG4gICAqIEFubnVsbGEgbGEgc2VsZXppb25lIGRlbCBmaWxlLCBzdnVvdGFuZG8gbCdpbnB1dCBlIHJlc2V0dGFuZG8gdHV0dGUgbGUgcHJvcHJpZXTDoCBkZWxsJ0lBdHRhY2htZW50RFRPXHJcbiAgICovXHJcbiAgYWJvcnRGaWxlKCkge1xyXG4gICAgaWYgKHRoaXMuaW1hZ2VJbnB1dCkgdGhpcy5pbWFnZUlucHV0Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSBcIlwiO1xyXG5cclxuICAgIHRoaXMuc2VsZWN0ZWRGaWxlID0gbnVsbDtcclxuICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IG51bGw7XHJcbiAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuXHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gbnVsbDtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZSA9IG51bGw7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZUV4dGVuc2lvbiA9IG51bGw7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlID0gbnVsbDtcclxuXHJcbiAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgdGhpcy5jdXN0b21IZWlnaHQgPSBudWxsO1xyXG4gICAgdGhpcy5jdXN0b21XaWR0aCA9IG51bGw7XHJcbiAgICB0aGlzLm9yaWdpbmFsSGVpZ2h0ID0gbnVsbDtcclxuICAgIHRoaXMub3JpZ2luYWxXaWR0aCA9IG51bGw7XHJcblxyXG4gICAgdGhpcy5kaWFsb2dSZWZDcm9wSW1hZ2UuY2xvc2UoKTtcclxuICAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8vIFZpZW5lIGNyZWF0byB1bidhcnJheSBvYnNlcnZhYmxlcyBwZXIgbWVtb3JpenphcmUgdHV0dGkgZ2xpIG9ic2VydmFibGUgY3JlYXRpIGRhbGxlIGNoaWFtYXRlIGEgZmlsZUVudHJ5LmZpbGUoKS5cclxuICAvLyBEb3BvIGNoZSB0dXR0aSBnbGkgb2JzZXJ2YWJsZXMgc29ubyBzdGF0aSBjb21wbGV0YXRpLCB2aWVuZSB1dGlsaXp6YXRvIGlsIG1ldG9kbyBzdWJzY3JpYmUoKSBwZXIgZXNlZ3VpcmUgbGEgZnVuemlvbmUgb25GaWxlQWRkZWQoKS5cclxuICBmaWxlRHJvcHBlZChmaWxlcykge1xyXG4gICAgbGV0IGZpbGVzRHJvcHBlZCA9IFtdO1xyXG5cclxuICAgIGNvbnN0IG9ic2VydmFibGVzOiBPYnNlcnZhYmxlPGFueT5bXSA9IFtdO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAoZmlsZXNbaV0uZmlsZUVudHJ5LmlzRmlsZSkge1xyXG4gICAgICAgIGNvbnN0IGZpbGVFbnRyeSA9IGZpbGVzW2ldLmZpbGVFbnRyeSBhcyBGaWxlU3lzdGVtRmlsZUVudHJ5O1xyXG4gICAgICAgIGNvbnN0IG9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcclxuICAgICAgICAgIGZpbGVFbnRyeS5maWxlKChmaWxlOiBGaWxlKSA9PiB7XHJcbiAgICAgICAgICAgIGZpbGVzRHJvcHBlZC5wdXNoKGZpbGUpO1xyXG5cclxuICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCgpO1xyXG4gICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgb2JzZXJ2YWJsZXMucHVzaChvYnNlcnZhYmxlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCBmaWxlRW50cnkgPSBmaWxlc1tpXS5maWxlRW50cnkgYXMgRmlsZVN5c3RlbURpcmVjdG9yeUVudHJ5O1xyXG4gICAgICAgIGNvbnNvbGUubG9nKGZpbGVzW2ldLnJlbGF0aXZlUGF0aCwgZmlsZUVudHJ5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZyb20ob2JzZXJ2YWJsZXMpXHJcbiAgICAgIC5waXBlKGNvbmNhdE1hcCgob2JzZXJ2YWJsZSkgPT4gb2JzZXJ2YWJsZSkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLm9uRmlsZUFkZGVkKGZpbGVzRHJvcHBlZCwgdHJ1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIFNlIGlsIGNhcmljYW1lbnRvIGRlbCBmaWxlIGRyb3Bib3ggdmEgYSBidW9uIGZpbmUsIGxhIGZ1bnppb25lIGRpIGNhbGxiYWNrIHJlc3RpdHVpc2NlIHVuIGFycmF5IGRpIG9nZ2V0dGkuXHJcbiAgLy8gVmllbmUgcG9pIGZhdHRhIHVuYSBYTUxIdHRwUmVxdWVzdCBjb24gcmVzcG9uc2VUeXBlICdibG9iJyBwZXIgY29udmVydGlyZSBpbCBwcmltbyBlbGVtZW50byBkZWxsYSByZXNwb25zZSBpbiB1biBCbG9iLlxyXG4gIGNob29zZURyb3Bib3hGaWxlKCkge1xyXG4gICAgdmFyIG9wdGlvbnMgPSB7XHJcbiAgICAgIHN1Y2Nlc3M6IChmaWxlczogYW55W10pID0+IHtcclxuICAgICAgICBjb25zdCB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcclxuICAgICAgICB4aHIub3BlbihcIkdFVFwiLCBmaWxlc1swXS5saW5rKTtcclxuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihcIkF1dGhvcml6YXRpb25cIiwgYEJlYXJlciAke0F0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmRyb3Bib3hDcmVkZW50aWFscy5hY2Nlc3NUb2tlbn1gKTtcclxuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gXCJibG9iXCI7XHJcblxyXG4gICAgICAgIHhoci5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBibG9iID0geGhyLnJlc3BvbnNlO1xyXG4gICAgICAgICAgY29uc3QgZmlsZSA9IG5ldyBGaWxlKFtibG9iXSwgZmlsZXNbMF0ubmFtZSwgeyB0eXBlOiBibG9iLnR5cGUgfSk7XHJcbiAgICAgICAgICBsZXQgZmlsZXNBZGRlZCA9IFtmaWxlXTtcclxuICAgICAgICAgIHRoaXMub25GaWxlQWRkZWQoZmlsZXNBZGRlZCwgdHJ1ZSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgeGhyLnNlbmQoKTtcclxuICAgICAgfSxcclxuICAgICAgbGlua1R5cGU6IFwiZGlyZWN0XCIsXHJcbiAgICAgIG11bHRpc2VsZWN0OiBmYWxzZSxcclxuICAgICAgZXh0ZW5zaW9uczogW1wiLmpwZ1wiLCBcIi5wbmdcIiwgXCIucGRmXCIsIFwiLmRvY1wiLCBcIi5kb2N4XCIsIFwiLnR4dFwiXVxyXG4gICAgfTtcclxuICAgIERyb3Bib3guY2hvb3NlKG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLy8gV29ya2Fyb3VuZCBkcm9wem9uZTogZGlzYWJpbGl0byBpbCBjbGljayBkZWdsaSBlbGVtZW50aSBpbmNsdXNpIG5lbGxhIGRyb3B6b25lIHBlciBldml0YXJlIGRpIGNsaWNjYXJlIGR1ZSB2b2x0ZVxyXG4gIG9uU2VsZWN0RmlsZShldmVudCwgZmlsZUlucHV0KSB7XHJcbiAgICBpZiAoXHJcbiAgICAgIChldmVudC50YXJnZXQgYXMgSFRNTEJ1dHRvbkVsZW1lbnQpLnRhZ05hbWUgPT09IFwiQlVUVE9OXCIgfHxcclxuICAgICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MQnV0dG9uRWxlbWVudCkudGFnTmFtZSA9PT0gXCJJTlBVVFwiIHx8XHJcbiAgICAgIHRoaXMuYWRkaW5nTGlua01vZGUgPT0gdHJ1ZVxyXG4gICAgKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGZpbGVJbnB1dC5jbGljaygpO1xyXG4gIH1cclxuXHJcbiAgLy8gTWV0b2RvIHBlciB2aXN1YWxpenphcmUgbGEgZm9ybSBkaSBhZ2dpdW50YSBkaSB1biBsaW5rXHJcbiAgc3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpIHtcclxuICAgIHRoaXMuYWRkaW5nTGlua01vZGUgPSB0cnVlO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50ID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID0gdGhpcy5hdHRhY2htZW50VHlwZS5MSU5LO1xyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuXHJcbiAgICB0aGlzLmNyZWF0ZUF0dGFjaG1lbnRGb3JtKCk7XHJcbiAgfVxyXG59XHJcbiIsIjwhLS0gU2UgcmljaGllc3RhIGxhIGdlc3Rpb25lIHNpbmdvbGEgbW9zdHJhIGlsIHB1bHNhbnRlIGRpIGNhcmljYW1lbnRvIGRpIHVuIHNpbmdvbG8gZmlsZSAtLT5cclxuPGRpdiAqbmdJZj1cIm11bHRpcGxlQXR0YWNobWVudCAhPSB0cnVlXCI+XHJcbiAgPGRpdiAqbmdJZj1cIiFzaW5nbGVBdHRhY2htZW50RHJhZ0FuZERyb3BcIj5cclxuICAgIDwhLS0gVGVtcGxhdGUgZGVsIGJ1dHRvbiBwZXIgbCdhZ2dpdW50YSBkaSB1biBhbGxlZ2F0byAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCIhYWRkaW5nTGlua01vZGVcIiBjbGFzcz1cInRleHQtY2VudGVyXCI+XHJcbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhZGRBdHRhY2htZW50QnV0dG9uXCI+PC9uZy1jb250YWluZXI+XHJcbiAgICA8L2Rpdj5cclxuICAgIDwhLS0gVGVtcGxhdGUgZGVsbGEgZm9ybSBwZXIgbCdhZ2dpdW50YSBkaSB1biBsaW5rIC0tPlxyXG4gICAgPGRpdiAqbmdJZj1cImFkZGluZ0xpbmtNb2RlXCIgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxyXG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiYWRkaW5nTGlua1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuICA8ZGl2ICpuZ0lmPVwic2luZ2xlQXR0YWNobWVudERyYWdBbmREcm9wXCI+XHJcbiAgICA8aW5wdXRcclxuICAgICAgI2ZpbGVJbnB1dFxyXG4gICAgICBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIlxyXG4gICAgICBpZD1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICAgIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgICB0eXBlPVwiZmlsZVwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiXHJcbiAgICAgIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxyXG4gICAgICBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gICAgPG5neC1maWxlLWRyb3BcclxuICAgICAgKG9uRmlsZURyb3ApPVwiZmlsZURyb3BwZWQoJGV2ZW50KVwiXHJcbiAgICAgIChjbGljayk9XCJvblNlbGVjdEZpbGUoJGV2ZW50LCBmaWxlSW5wdXQpXCJcclxuICAgICAgKm5nSWY9XCJcclxuICAgICAgICBhbGxvd2VkVHlwZXMgJiZcclxuICAgICAgICBhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSkgJiZcclxuICAgICAgICAoIWF0dGFjaG1lbnRzTGlzdCB8fCBhdHRhY2htZW50c0xpc3QubGVuZ3RoID09IDAgfHwgKGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmICFhdHRhY2htZW50c0xpc3RbMF0pKVxyXG4gICAgICBcIj5cclxuICAgICAgPG5nLXRlbXBsYXRlIG5neC1maWxlLWRyb3AtY29udGVudC10bXAgKm5nSWY9XCIhYWRkaW5nTGlua01vZGVcIj5cclxuICAgICAgICA8aSBjbGFzcz1cImZhLXNvbGlkIGZhLWNsb3VkLXVwbG9hZC1hbHQgZmEtM3ggbXQtM1wiPjwvaT5cclxuICAgICAgICBUcmFzY2luYSBpIGZpbGUgcXVpXHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBtdC0xXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tbGlnaHQgYm9yZGVyLWVuZFwiIChjbGljayk9XCJmaWxlSW5wdXQuY2xpY2soKVwiPlNjZWdsaSB1biBmaWxlPC9idXR0b24+XHJcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImJ0biBidG4tbGlnaHQgYm9yZGVyLXN0YXJ0IGRyb3Bkb3duLXRvZ2dsZVwiXHJcbiAgICAgICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImF0dGFjaG1lbnRUeXBlTWVudVwiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8bWF0LW1lbnUgI2F0dGFjaG1lbnRUeXBlTWVudT1cIm1hdE1lbnVcIj5cclxuICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKVwiXHJcbiAgICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtZmlsZS1idG5cIj5cclxuICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWZpbGVcIj48L2k+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RmlsZTwvc3Bhbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygyKVwiXHJcbiAgICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCJcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1saW5rXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkxpbms8L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMylcIlxyXG4gICAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImNob29zZURyb3Bib3hGaWxlKClcIlxyXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmEtYnJhbmRzIGZhLWRyb3Bib3hcIj48L2k+XHJcbiAgICAgICAgICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RHJvcGJveDwvc3Bhbj5cclxuICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPC9tYXQtbWVudT5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICA8bmctdGVtcGxhdGUgbmd4LWZpbGUtZHJvcC1jb250ZW50LXRtcCAqbmdJZj1cImFkZGluZ0xpbmtNb2RlXCI+XHJcbiAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImFkZGluZ0xpbmtUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgPC9uZ3gtZmlsZS1kcm9wPlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICBjbGFzcz1cIm1iLTIgbWUtMiBlcXAtYXR0YWNobWVudHMtZG93bmxvYWQtYnRuXCJcclxuICAgICAgKGNsaWNrKT1cInZpZXdBdHRhY2htZW50KGF0dGFjaG1lbnRzTGlzdFswXSlcIlxyXG4gICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgICAgKm5nSWY9XCJhdHRhY2htZW50c0xpc3QgJiYgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiYgYXR0YWNobWVudHNMaXN0WzBdXCJcclxuICAgICAgY29sb3I9XCJwcmltYXJ5XCI+XHJcbiAgICAgIDxtYXQtaWNvbiAqbmdJZj1cImF0dGFjaG1lbnRzTGlzdFswXS5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFXCI+ZG93bmxvYWQ8L21hdC1pY29uPlxyXG4gICAgICA8bWF0LWljb24gKm5nSWY9XCJhdHRhY2htZW50c0xpc3RbMF0uQXR0YWNobWVudFR5cGUgIT0gQXR0YWNobWVudFR5cGUuRklMRVwiPm9wZW5faW5fbmV3PC9tYXQtaWNvbj5cclxuICAgICAge3sgYXR0YWNobWVudHNMaXN0WzBdLkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUgPyBkb3dubG9hZExhYmVsIDogb3BlbkxpbmtMYWJlbCB9fVxyXG4gICAgPC9idXR0b24+XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgIGNsYXNzPVwibWItMiBtZS0yIGVxcC1hdHRhY2htZW50cy1wcmV2aWV3LWJ0blwiXHJcbiAgICAgIChjbGljayk9XCJvcGVuUHJldmlld0RpYWxvZyhhdHRhY2htZW50c0xpc3RbMF0pXCJcclxuICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgc2hvd1ByZXZpZXcgJiZcclxuICAgICAgICBhdHRhY2htZW50c0xpc3QgJiZcclxuICAgICAgICBhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJlxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdFswXSAmJlxyXG4gICAgICAgICghYXR0YWNobWVudHNMaXN0WzBdLkZpbGVDb250ZW50VHlwZSB8fFxyXG4gICAgICAgICAgKCFhdHRhY2htZW50c0xpc3RbMF0uRmlsZUNvbnRlbnRUeXBlLnN0YXJ0c1dpdGgoJ3ZpZGVvJykgJiZcclxuICAgICAgICAgICAgIWF0dGFjaG1lbnRzTGlzdFswXS5GaWxlQ29udGVudFR5cGUuc3RhcnRzV2l0aCgnYXVkaW8nKSkpICYmXHJcbiAgICAgICAgYXR0YWNobWVudHNMaXN0WzBdLklzSW1hZ2UgPT0gdHJ1ZVxyXG4gICAgICBcIj5cclxuICAgICAgPG1hdC1pY29uPnZpc2liaWxpdHk8L21hdC1pY29uPiB7eyBwcmV2aWV3TGFiZWwgfX1cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICBjbGFzcz1cIm1iLTIgZXFwLWF0dGFjaG1lbnRzLWRlbGV0ZS1idG5cIlxyXG4gICAgICAoY2xpY2spPVwiZGVsZXRlQXR0YWNobWVudChhdHRhY2htZW50c0xpc3RbMF0pXCJcclxuICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgICpuZ0lmPVwiYXR0YWNobWVudHNMaXN0ICYmIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmIGF0dGFjaG1lbnRzTGlzdFswXVwiXHJcbiAgICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCI+XHJcbiAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPiB7eyBkZWxldGVMYWJlbCB9fVxyXG4gICAgPC9idXR0b24+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdlxyXG4gICAgY2xhc3M9XCJyb3dcIlxyXG4gICAgc3R5bGU9XCJtYXJnaW4tdG9wOiAxMHB4XCJcclxuICAgICpuZ0lmPVwiXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdFswXSAmJlxyXG4gICAgICBhdHRhY2htZW50c0xpc3RbMF0uRmlsZURhdGFCYXNlNjQgJiZcclxuICAgICAgYXR0YWNobWVudHNMaXN0WzBdLklzSW1hZ2UgPT0gdHJ1ZVxyXG4gICAgXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEyIGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJzaW5nbGUtYXR0YWNobWVudC1pbmxpbmUtcHJldmlldy1jb250YWluZXJcIj5cclxuICAgICAgICA8aW1nIHNyYz1cImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCx7eyBhdHRhY2htZW50c0xpc3RbMF0uRmlsZURhdGFCYXNlNjQgfX1cIiAvPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJyb3dcIiAqbmdJZj1cImF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmIGF0dGFjaG1lbnRzTGlzdFswXSAmJiBhdHRhY2htZW50c0xpc3RbMF0uSXNJbWFnZSAhPSB0cnVlXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLXNtLTEyXCI+XHJcbiAgICAgIDxtYXQtZm9ybS1maWVsZD5cclxuICAgICAgICA8bWF0LWxhYmVsPnt7IGZpbGVOYW1lTGFiZWwgfX08L21hdC1sYWJlbD5cclxuICAgICAgICA8aW5wdXQgcmVhZG9ubHkgbWF0SW5wdXQgWyhuZ01vZGVsKV09XCJhdHRhY2htZW50c0xpc3RbMF0uRmlsZU5hbWVcIiAvPlxyXG4gICAgICA8L21hdC1mb3JtLWZpZWxkPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuPGRpdiAqbmdJZj1cIm11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlXCI+XHJcbiAgPGlucHV0XHJcbiAgICAjZmlsZUlucHV0XHJcbiAgICBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIlxyXG4gICAgaWQ9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgbmFtZT1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICB0eXBlPVwiZmlsZVwiXHJcbiAgICAoY2hhbmdlKT1cIm9uRmlsZUFkZGVkKCRldmVudClcIlxyXG4gICAgW2FjY2VwdF09XCJhY2NlcHRlZEZpbGVUeXBlc1wiXHJcbiAgICBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gIDxuZ3gtZmlsZS1kcm9wIChvbkZpbGVEcm9wKT1cImZpbGVEcm9wcGVkKCRldmVudClcIiAoY2xpY2spPVwib25TZWxlY3RGaWxlKCRldmVudCwgZmlsZUlucHV0KVwiPlxyXG4gICAgPG5nLXRlbXBsYXRlIG5neC1maWxlLWRyb3AtY29udGVudC10bXAgKm5nSWY9XCIhYWRkaW5nTGlua01vZGVcIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1jbG91ZC11cGxvYWQtYWx0IGZhLTN4IG10LTNcIj48L2k+XHJcbiAgICAgIFRyYXNjaW5hIGkgZmlsZSBxdWlcclxuICAgICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cCBtdC0xXCIgcm9sZT1cImdyb3VwXCI+XHJcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IGJvcmRlci1lbmRcIiAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIj5TY2VnbGkgdW4gZmlsZTwvYnV0dG9uPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXBcIiByb2xlPVwiZ3JvdXBcIj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1saWdodCBib3JkZXItc3RhcnQgZHJvcGRvd24tdG9nZ2xlXCJcclxuICAgICAgICAgICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImF0dGFjaG1lbnRUeXBlTWVudVwiPjwvYnV0dG9uPlxyXG4gICAgICAgICAgPG1hdC1tZW51ICNhdHRhY2htZW50VHlwZU1lbnU9XCJtYXRNZW51XCI+XHJcbiAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKVwiXHJcbiAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgIChjbGljayk9XCJmaWxlSW5wdXQuY2xpY2soKVwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtZmlsZS1idG5cIj5cclxuICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1maWxlXCI+PC9pPlxyXG4gICAgICAgICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5GaWxlPC9zcGFuPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpXCJcclxuICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1saW5rXCI+PC9pPlxyXG4gICAgICAgICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5MaW5rPC9zcGFuPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpXCJcclxuICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImNob29zZURyb3Bib3hGaWxlKClcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYS1icmFuZHMgZmEtZHJvcGJveFwiPjwvaT5cclxuICAgICAgICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RHJvcGJveDwvc3Bhbj5cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICA8L21hdC1tZW51PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICA8bmctdGVtcGxhdGUgbmd4LWZpbGUtZHJvcC1jb250ZW50LXRtcCAqbmdJZj1cImFkZGluZ0xpbmtNb2RlXCI+XHJcbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhZGRpbmdMaW5rVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cclxuICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgPC9uZ3gtZmlsZS1kcm9wPlxyXG4gIDxkaXYgY2xhc3M9XCJtdC0yXCI+XHJcbiAgICA8ZXFwLXRhYmxlXHJcbiAgICAgICNhdHRhY2htZW50VGFibGVcclxuICAgICAgW2NyZWF0ZU1hdENhcmRdPVwiZmFsc2VcIlxyXG4gICAgICAjdGFibGVcclxuICAgICAgW2NvbHVtbnNdPVwiYXR0YWNobWVudHNDb2x1bW5zXCJcclxuICAgICAgW2lzTXVsdGlMYW5ndWFnZV09XCJpc0VxcFRhYmxlTXVsdGlMYW5ndWFnZVwiXHJcbiAgICAgIFtkYXRhXT1cImF0dGFjaG1lbnRzTGlzdFwiXHJcbiAgICAgIFtwYWdpbmF0b3JWaXNpYmxlXT1cInRhYmxlUGFnaW5hdG9yVmlzaWJsZVwiXHJcbiAgICAgIFttYXRQYWdpbmF0b3JTaXplXT1cInRhYmxlUGFnaW5hdG9yU2l6ZVwiXHJcbiAgICAgIFtlbXB0eVRhYmxlTWVzc2FnZV09XCJlbXB0eVRhYmxlTWVzc2FnZVwiXHJcbiAgICAgIFtzZWFyY2hUZXh0XT1cImVxcFRhYmxlU2VhcmNoVGV4dFwiXHJcbiAgICAgIFtpc1RhYmxlU2VhcmNoZWFibGVdPVwiaXNUYWJsZVNlYXJjaGVhYmxlXCI+XHJcbiAgICA8L2VxcC10YWJsZT5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48bmctdGVtcGxhdGUgI2RpYWxvZ0Nyb3BJbWFnZT5cclxuICA8IS0tIFJpY2hpYW1hIGlsIHRlbXBsYXRlIHBlciBsZSBmdW56aW9uYWxpdMOgIGRlbCBDUk9QUElFIC0tPlxyXG4gIDxkaXYgc3R5bGU9XCJvdmVyZmxvdy14OiBoaWRkZW5cIiBbbmdDbGFzc109XCJjcm9wRGlhbG9nQ2xhc3NcIj5cclxuICAgIDxuZy1jb250YWluZXJcclxuICAgICAgW25nVGVtcGxhdGVPdXRsZXRdPVwiY3JvcHBpZVRlbXBsYXRlXCJcclxuICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgZm9ybTogbmV3QXR0YWNobWVudEZvcm0gfVwiXHJcbiAgICAgICpuZ0lmPVwic2hvd0Nyb3BJbWFnZSA9PSB0cnVlXCI+PC9uZy1jb250YWluZXI+XHJcbiAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG48bmctdGVtcGxhdGUgI2lubGluZVByZXZpZXdUZW1wbGF0ZSBsZXQtcm93PVwicm93XCI+XHJcbiAgPGRpdlxyXG4gICAgY2xhc3M9XCJpbmxpbmUtcHJldmlldy1jb250YWluZXJcIlxyXG4gICAgKm5nSWY9XCJyb3cuQXR0YWNobWVudFR5cGUgIT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiByb3cuSXNJbWFnZVwiXHJcbiAgICAoY2xpY2spPVwib3BlblByZXZpZXdEaWFsb2cocm93KVwiPlxyXG4gICAgPGltZyBzcmM9XCJkYXRhOmltYWdlL3BuZztiYXNlNjQse3sgcm93LkZpbGVUaHVtYm5haWxCYXNlNjQgPyByb3cuRmlsZVRodW1ibmFpbEJhc2U2NCA6IHJvdy5GaWxlRGF0YUJhc2U2NCB9fVwiIC8+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdlxyXG4gICAgY2xhc3M9XCJpbmxpbmUtcHJldmlldy1jb250YWluZXJcIlxyXG4gICAgKm5nSWY9XCJyb3cuQXR0YWNobWVudFR5cGUgIT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiAhcm93LklzSW1hZ2VcIlxyXG4gICAgKGNsaWNrKT1cIm9wZW5QcmV2aWV3RGlhbG9nKHJvdylcIj5cclxuICAgIDxpIFtuZ0NsYXNzXT1cImdldEF0dGFjaG1lbnRJY29uKHJvdylcIj48L2k+XHJcbiAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG48bmctdGVtcGxhdGUgI2RpYWxvZ1ByZXZpZXc+XHJcbiAgPG1hdC1jYXJkIGNsYXNzPVwiZXhhbXBsZS1jYXJkXCIgKm5nSWY9XCJzZWxlY3RlZEF0dGFjaG1lbnRcIj5cclxuICAgIDxtYXQtY2FyZC1jb250ZW50PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicm93XCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci10aXRsZS1zdGFuZGFyZFwiPlxyXG4gICAgICAgICAge3sgcHJldmlld0xhYmVsIH19IHt7IHNlbGVjdGVkQXR0YWNobWVudD8uQXR0YWNobWVudFR5cGUgPT0gYXR0YWNobWVudFR5cGUuRklMRSA/IFwiRmlsZVwiIDogXCJMaW5rXCIgfX1cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiYnRuLWNsb3NlIGNsb3NlQnV0dG9uXCJcclxuICAgICAgICAgICAgbWF0LWRpYWxvZy1jbG9zZVxyXG4gICAgICAgICAgICAoY2xpY2spPVwic2VsZWN0ZWRBdHRhY2htZW50ID0gbnVsbFwiPjwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cInJvdyBtdC0yXCI+XHJcbiAgICAgICAgPCEtLSBBTlRFUFJJTUEgSU1NQUdJTkUgLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMiB0ZXh0LWNlbnRlciBwcmV2aWV3LWNvbnRhaW5lclwiICpuZ0lmPVwic2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2VcIj5cclxuICAgICAgICAgIDxpbWdcclxuICAgICAgICAgICAgY2xhc3M9XCJpbWFnZS1wcmV2aWV3XCJcclxuICAgICAgICAgICAgc3JjPVwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LHt7XHJcbiAgICAgICAgICAgICAgc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0XHJcbiAgICAgICAgICAgICAgICA/IHNlbGVjdGVkQXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NFxyXG4gICAgICAgICAgICAgICAgOiBzZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVRodW1ibmFpbEJhc2U2NFxyXG4gICAgICAgICAgICB9fVwiIC8+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDwhLS0gQU5URVBSSU1BIExJTksgLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMiBwcmV2aWV3LWNvbnRhaW5lclwiICpuZ0lmPVwiIXNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlXCI+XHJcbiAgICAgICAgICA8aWZyYW1lXHJcbiAgICAgICAgICAgIGNsYXNzPVwibGluay1wcmV2aWV3XCJcclxuICAgICAgICAgICAgW3NyY109XCJzZWxlY3RlZEF0dGFjaG1lbnQuVHJ1c3RlZFVybFwiXHJcbiAgICAgICAgICAgIFt0aXRsZV09XCJzZWxlY3RlZEF0dGFjaG1lbnQuRmlsZU5hbWVcIj48L2lmcmFtZT5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJyb3cgbXQtM1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTIgdGV4dC1jZW50ZXJcIj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgbWF0LW1pbmktZmFiXHJcbiAgICAgICAgICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICAgICAgICAgIG1hdFRvb2x0aXA9XCJEb3dubG9hZFwiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJ2aWV3QXR0YWNobWVudChzZWxlY3RlZEF0dGFjaG1lbnQpXCJcclxuICAgICAgICAgICAgKm5nSWY9XCJzZWxlY3RlZEF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgIT0gQXR0YWNobWVudFR5cGUuTElOS1wiPlxyXG4gICAgICAgICAgICA8bWF0LWljb24+ZG93bmxvYWQ8L21hdC1pY29uPlxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9tYXQtY2FyZC1jb250ZW50PlxyXG4gIDwvbWF0LWNhcmQ+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG48IS0tIFRFTVBMQVRFIFBFUiBJTCBQVUxTQU5URSBESSBBR0dJVU5UQSBOVU9WTyBBTExFR0FUTyAtLT5cclxuPG5nLXRlbXBsYXRlICNhZGRBdHRhY2htZW50QnV0dG9uPlxyXG4gIDwhLS1cclxuICAgICAgICBQdWxzYW50aSBwZXIgbCdhZ2dpdW50YSBkaSB1biBmaWxlIG8gdW4gbGluay4gTmUgdmllbmUgdmlzdWFsaXp6YXRvIHVubyBzZTpcclxuICAgICAgICAtIGdsaSBhbGxvd2VkVHlwZXMgc29ubyBzdGF0aSBzcGVjaWZpY2F0aSwgbmVsbCdhcnJheSBuZSDDqCBwcmVzZW50ZSB1bm8gc29sbywgcXVlbGxvIGluc2VyaXRvIMOoIEF0dGFjaG1lbnRUeXBlLkZJTEUgKG8gQXR0YWNobWVudFR5cGUuTElOSylcclxuICAgICAgICBlIHNvbm8gbmVsbGEgZ2VzdGlvbmUgZGkgcGnDuSBhbGxlZ2F0aSAobXVsdGlwbGVBdHRhY2htZW50ID09IHRydWUpXHJcbiAgICAgICAgT1BQVVJFXHJcbiAgICAgICAgLSBnbGkgYWxsb3dlZFR5cGVzIHNvbm8gc3RhdGkgc3BlY2lmaWNhdGksIG5lbGwnYXJyYXkgbmUgw6ggcHJlc2VudGUgdW5vIHNvbG8sIHF1ZWxsbyBpbnNlcml0byDDqCBBdHRhY2htZW50VHlwZS5GSUxFIChvIEF0dGFjaG1lbnRUeXBlLkxJTkspXHJcbiAgICAgICAgZSBzb25vIG5lbGxhIGdlc3Rpb25lIGRpIHVuIHNpbmdvbG8gYWxsZWdhdG8gKG11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlKSBlIG5vbiBuZSDDqCBhbmNvcmEgc3RhdG8gc2VsZXppb25hdG8gdW5vIChvdnZlcm8gYXR0YWNobWVudHNMaXN0IG5vbiBlc2lzdGUgbyBub24gaGEgZWxlbWVudGkpXHJcbiAgICAtLT5cclxuICA8aW5wdXRcclxuICAgICNmaWxlSW5wdXRcclxuICAgIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiXHJcbiAgICBpZD1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICBuYW1lPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgIHR5cGU9XCJmaWxlXCJcclxuICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiXHJcbiAgICBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCJcclxuICAgIFttdWx0aXBsZV09XCJsb2FkTXVsdGlwbGVGaWxlc1wiIC8+XHJcbiAgPGJ1dHRvblxyXG4gICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWItNCBtZS01IGVxcC1hdHRhY2htZW50cy1hZGQtYnRuXCJcclxuICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICBhbGxvd2VkVHlwZXMgJiZcclxuICAgICAgYWxsb3dlZFR5cGVzLmxlbmd0aCA9PSAxICYmXHJcbiAgICAgIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSB8fFxyXG4gICAgICAgICFhdHRhY2htZW50c0xpc3QgfHxcclxuICAgICAgICBhdHRhY2htZW50c0xpc3QubGVuZ3RoID09IDAgfHxcclxuICAgICAgICAoYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiYgIWF0dGFjaG1lbnRzTGlzdFswXSkpXHJcbiAgICBcIlxyXG4gICAgKGNsaWNrKT1cImFkZEZpbGUoYWxsb3dlZFR5cGVzWzBdLCBmaWxlSW5wdXQpXCJcclxuICAgIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCI+XHJcbiAgICA8IS0tIFBlciBsJ2FnZ2l1bnRhIGRlaSBmaWxlIG1vc3RybyB1bidpY29uYSBkaXZlcnNhIGRhbGwnYWdnaXVudGEgZGVpIGxpbmsgLS0+XHJcbiAgICA8bWF0LWljb24gKm5nSWY9XCJhbGxvd2VkVHlwZXNbMF0gPT0gMVwiPmNsb3VkX3VwbG9hZDwvbWF0LWljb24+XHJcbiAgICA8aSBjbGFzcz1cImZhcyBmYS1saW5rXCIgKm5nSWY9XCJhbGxvd2VkVHlwZXNbMF0gPT0gMlwiPjwvaT5cclxuICAgIDxpIGNsYXNzPVwiZmEtYnJhbmRzIGZhLWRyb3Bib3hcIiAqbmdJZj1cImFsbG93ZWRUeXBlc1swXSA9PSAzXCI+PC9pPlxyXG4gICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPlxyXG4gICAgICB7e1xyXG4gICAgICAgIGFsbG93ZWRUeXBlc1swXSA9PSAxXHJcbiAgICAgICAgICA/IGFkZEJ1dHRvbkxhYmVsICsgXCIgZmlsZVwiXHJcbiAgICAgICAgICA6IGFsbG93ZWRUeXBlc1swXSA9PSAyXHJcbiAgICAgICAgICA/IGFkZEJ1dHRvbkxhYmVsICsgXCIgbGlua1wiXHJcbiAgICAgICAgICA6IHVwbG9hZFdpdGhEcm9wYm94TGFiZWxcclxuICAgICAgfX08L3NwYW5cclxuICAgID5cclxuICA8L2J1dHRvbj5cclxuXHJcbiAgPCEtLSBQdWxzYW50ZSBwZXIgYXByaXJlIGlsIG1lbnUgcGVyIGxhIHNjZWx0YSBkZWwgdGlwbyBkaSBBdHRhY2htZW50IGRhIGNyZWFyZSAtLT5cclxuICA8YnV0dG9uXHJcbiAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBtYi00IG1lLTUgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIlxyXG4gICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgIFttYXRNZW51VHJpZ2dlckZvcl09XCJhdHRhY2htZW50VHlwZU1lbnVcIlxyXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIlxyXG4gICAgKm5nSWY9XCJcclxuICAgICAgIXNlcGFyYXRlZFVwbG9hZEJ1dHRvbnMgJiZcclxuICAgICAgYWxsb3dlZFR5cGVzICYmXHJcbiAgICAgIGFsbG93ZWRUeXBlcy5sZW5ndGggPiAxICYmXHJcbiAgICAgIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSB8fFxyXG4gICAgICAgICFhdHRhY2htZW50c0xpc3QgfHxcclxuICAgICAgICBhdHRhY2htZW50c0xpc3QubGVuZ3RoID09IDAgfHxcclxuICAgICAgICAoYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiYgIWF0dGFjaG1lbnRzTGlzdFswXSkpXHJcbiAgICBcIj5cclxuICAgIDxtYXQtaWNvbiAqbmdJZj1cIm11bHRpcGxlQXR0YWNobWVudCAhPSB0cnVlXCI+Y2xvdWRfdXBsb2FkPC9tYXQtaWNvbj5cclxuICAgIDxtYXQtaWNvbiAqbmdJZj1cIm11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlXCI+YWRkPC9tYXQtaWNvbj5cclxuICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDBweFwiPiB7eyBhZGRCdXR0b25MYWJlbCB9fSA8L3NwYW4+XHJcbiAgPC9idXR0b24+XHJcbiAgPG1hdC1tZW51ICNhdHRhY2htZW50VHlwZU1lbnU9XCJtYXRNZW51XCI+XHJcbiAgICA8aW5wdXRcclxuICAgICAgI2ltYWdlSW5wdXRcclxuICAgICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgICAgaWQ9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgICBuYW1lPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgICAgdHlwZT1cImZpbGVcIlxyXG4gICAgICAoY2hhbmdlKT1cIm9uRmlsZUFkZGVkKCRldmVudClcIlxyXG4gICAgICBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCJcclxuICAgICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICAgIDxidXR0b25cclxuICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgIChjbGljayk9XCJpbWFnZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1maWxlLWJ0blwiPlxyXG4gICAgICA8aSBjbGFzcz1cImZhcyBmYS1maWxlXCI+PC9pPlxyXG4gICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RmlsZTwvc3Bhbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygyKVwiXHJcbiAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgKGNsaWNrKT1cInN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiXHJcbiAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxpbmtcIj48L2k+XHJcbiAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5MaW5rPC9zcGFuPlxyXG4gICAgPC9idXR0b24+XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpXCJcclxuICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAoY2xpY2spPVwiY2hvb3NlRHJvcGJveEZpbGUoKVwiXHJcbiAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmEtYnJhbmRzIGZhLWRyb3Bib3hcIj48L2k+XHJcbiAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5Ecm9wYm94PC9zcGFuPlxyXG4gICAgPC9idXR0b24+XHJcbiAgPC9tYXQtbWVudT5cclxuXHJcbiAgPGRpdlxyXG4gICAgKm5nSWY9XCJcclxuICAgICAgc2VwYXJhdGVkVXBsb2FkQnV0dG9ucyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMgJiZcclxuICAgICAgYWxsb3dlZFR5cGVzLmxlbmd0aCA+IDEgJiZcclxuICAgICAgKG11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlIHx8XHJcbiAgICAgICAgIWF0dGFjaG1lbnRzTGlzdCB8fFxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCB8fFxyXG4gICAgICAgIChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgIFwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgIChjbGljayk9XCJpbWFnZUlucHV0LmNsaWNrKClcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zZWNvbmRhcnkgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIlxyXG4gICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgICAgY29sb3I9XCJzZWNvbmRhcnlcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIj5cclxuICAgICAgICA8aSBjbGFzcz1cImZhLXNvbGlkIGZhLWNsb3VkLXVwbG9hZFwiPjwvaT5cclxuICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RmlsZTwvc3Bhbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxpbnB1dFxyXG4gICAgICAgICNpbWFnZUlucHV0XHJcbiAgICAgICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgICAgICBpZD1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICAgICAgbmFtZT1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICAgICAgdHlwZT1cImZpbGVcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiXHJcbiAgICAgICAgW2FjY2VwdF09XCJhY2NlcHRlZEZpbGVUeXBlc1wiXHJcbiAgICAgICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpXCJcclxuICAgICAgICAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCJcclxuICAgICAgICBjbGFzcz1cImJ0biBidG4tc2Vjb25kYXJ5IGVxcC1hdHRhY2htZW50cy1hZGQtYnRuXCJcclxuICAgICAgICBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgICAgIGNvbG9yPVwic2Vjb25kYXJ5XCJcclxuICAgICAgICB0eXBlPVwiYnV0dG9uXCI+XHJcbiAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+TGluazwvc3Bhbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKVwiXHJcbiAgICAgICAgKGNsaWNrKT1cImNob29zZURyb3Bib3hGaWxlKClcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1zZWNvbmRhcnkgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIlxyXG4gICAgICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgICAgY29sb3I9XCJzZWNvbmRhcnlcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIj5cclxuICAgICAgICA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPlxyXG4gICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5Ecm9wYm94PC9zcGFuPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG48L25nLXRlbXBsYXRlPlxyXG5cclxuPG5nLXRlbXBsYXRlICNjcm9wcGllVGVtcGxhdGU+XHJcbiAgPGRpdiBjbGFzcz1cInJvdyBtLTNcIj5cclxuICAgIDxoND57eyBjcm9wTGFiZWwgfX08L2g0PlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJyb3cgbS0yIGNyb3AtbGFyZ2VcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMTIgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICBbbWF0VG9vbHRpcF09XCJyb3RhdGVMZWZ0TGFiZWxcIlxyXG4gICAgICAgICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1hdC1yYWlzZWQtYnV0dG9uIG1zLTJcIlxyXG4gICAgICAgIChjbGljayk9XCJyb3RhdGVMZWZ0KClcIj5cclxuICAgICAgICA8bWF0LWljb24gc3R5bGU9XCJ2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCI+cm90YXRlX2xlZnQ8L21hdC1pY29uPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvblxyXG4gICAgICAgIFttYXRUb29sdGlwXT1cInJvdGF0ZVJpZ2h0TGFiZWxcIlxyXG4gICAgICAgICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1hdC1yYWlzZWQtYnV0dG9uIG1zLTJcIlxyXG4gICAgICAgIChjbGljayk9XCJyb3RhdGVSaWdodCgpXCI+XHJcbiAgICAgICAgPG1hdC1pY29uIHN0eWxlPVwidmVydGljYWwtYWxpZ246IG1pZGRsZVwiPnJvdGF0ZV9yaWdodDwvbWF0LWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgW21hdFRvb2x0aXBdPVwiZmxpcEhvcmluem9udGFsTGFiZWxcIlxyXG4gICAgICAgICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1hdC1yYWlzZWQtYnV0dG9uIG1zLTJcIlxyXG4gICAgICAgIChjbGljayk9XCJmbGlwSG9yaXpvbnRhbCgpXCI+XHJcbiAgICAgICAgPG1hdC1pY29uIHN0eWxlPVwidmVydGljYWwtYWxpZ246IG1pZGRsZVwiPmZsaXBfaG9yaXpvbnRhbDwvbWF0LWljb24+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgW21hdFRvb2x0aXBdPVwiZmxpcFZlcnRpY2FsTGFiZWxcIlxyXG4gICAgICAgICpuZ0lmPVwiY3JvcE9wdGlvbnMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1hdC1yYWlzZWQtYnV0dG9uIG1zLTJcIlxyXG4gICAgICAgIChjbGljayk9XCJmbGlwVmVydGljYWwoKVwiPlxyXG4gICAgICAgIDxkaXYgc3R5bGU9XCJ0cmFuc2Zvcm06IHJvdGF0ZSg5MGRlZylcIj48bWF0LWljb24gc3R5bGU9XCJ2ZXJ0aWNhbC1hbGlnbjogbWlkZGxlXCI+ZmxpcF92ZXJ0aWNhbDwvbWF0LWljb24+PC9kaXY+XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgW21hdFRvb2x0aXBdPVwiJ1Jlc2V0J1wiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWF0LXJhaXNlZC1idXR0b24gbXMtMlwiXHJcbiAgICAgICAgKGNsaWNrKT1cInJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKVwiPlxyXG4gICAgICAgIDxtYXQtaWNvbiBzdHlsZT1cInZlcnRpY2FsLWFsaWduOiBtaWRkbGVcIj5yZXBsYXk8L21hdC1pY29uPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJyb3cgbS0yIGNyb3Atc21hbGxcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtMTIgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICAgIDxtYXQtaWNvbiAqbmdJZj1cImNyb3BPcHRpb25zLmluY2x1ZGVzKDEpXCIgc3R5bGU9XCJmb250LXNpemU6IDI3cHg7IHZlcnRpY2FsLWFsaWduOiBtaWRkbGVcIiAoY2xpY2spPVwicm90YXRlTGVmdCgpXCJcclxuICAgICAgICA+cm90YXRlX2xlZnQ8L21hdC1pY29uXHJcbiAgICAgID5cclxuICAgICAgPG1hdC1pY29uXHJcbiAgICAgICAgY2xhc3M9XCJtcy0zXCJcclxuICAgICAgICAqbmdJZj1cImNyb3BPcHRpb25zLmluY2x1ZGVzKDEpXCJcclxuICAgICAgICBzdHlsZT1cImZvbnQtc2l6ZTogMjdweDsgdmVydGljYWwtYWxpZ246IG1pZGRsZVwiXHJcbiAgICAgICAgKGNsaWNrKT1cInJvdGF0ZVJpZ2h0KClcIlxyXG4gICAgICAgID5yb3RhdGVfcmlnaHQ8L21hdC1pY29uXHJcbiAgICAgID5cclxuICAgICAgPG1hdC1pY29uXHJcbiAgICAgICAgY2xhc3M9XCJtcy0zXCJcclxuICAgICAgICAqbmdJZj1cImNyb3BPcHRpb25zLmluY2x1ZGVzKDIpXCJcclxuICAgICAgICBzdHlsZT1cImZvbnQtc2l6ZTogMjdweDsgdmVydGljYWwtYWxpZ246IG1pZGRsZVwiXHJcbiAgICAgICAgKGNsaWNrKT1cImZsaXBIb3Jpem9udGFsKClcIlxyXG4gICAgICAgID5mbGlwX2hvcml6b250YWw8L21hdC1pY29uXHJcbiAgICAgID5cclxuICAgICAgPGRpdiBjbGFzcz1cIm1zLTNcIiBzdHlsZT1cInRyYW5zZm9ybTogcm90YXRlKDkwZGVnKVwiPlxyXG4gICAgICAgIDxtYXQtaWNvblxyXG4gICAgICAgICAgKm5nSWY9XCJjcm9wT3B0aW9ucy5pbmNsdWRlcygyKVwiXHJcbiAgICAgICAgICBzdHlsZT1cImZvbnQtc2l6ZTogMjdweDsgdmVydGljYWwtYWxpZ246IG1pZGRsZVwiXHJcbiAgICAgICAgICAoY2xpY2spPVwiZmxpcFZlcnRpY2FsKClcIlxyXG4gICAgICAgICAgPmZsaXBfdmVydGljYWw8L21hdC1pY29uXHJcbiAgICAgICAgPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPG1hdC1pY29uIGNsYXNzPVwibXMtM1wiIChjbGljayk9XCJyZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKClcIiBzdHlsZT1cImZvbnQtc2l6ZTogMjdweDsgdmVydGljYWwtYWxpZ246IG1pZGRsZVwiXHJcbiAgICAgICAgPnJlcGxheTwvbWF0LWljb25cclxuICAgICAgPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cInJvdyBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIganVzdGlmeS1jb250ZW50LWNlbnRlclwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiY3JvcC1jb250YWluZXJcIj5cclxuICAgICAgICA8aW1hZ2UtY3JvcHBlclxyXG4gICAgICAgICAgW2ltYWdlRmlsZV09XCJzZWxlY3RlZEZpbGVcIlxyXG4gICAgICAgICAgW21haW50YWluQXNwZWN0UmF0aW9dPVwiZmFsc2VcIlxyXG4gICAgICAgICAgW2F1dG9Dcm9wXT1cImZhbHNlXCJcclxuICAgICAgICAgIFtjb250YWluV2l0aGluQXNwZWN0UmF0aW9dPVwiZmFsc2VcIlxyXG4gICAgICAgICAgW2FzcGVjdFJhdGlvXT1cIjQgLyAzXCJcclxuICAgICAgICAgIFtjcm9wcGVyTWluV2lkdGhdPVwiMTI4XCJcclxuICAgICAgICAgIFtvbmx5U2NhbGVEb3duXT1cInRydWVcIlxyXG4gICAgICAgICAgW3JvdW5kQ3JvcHBlcl09XCJmYWxzZVwiXHJcbiAgICAgICAgICBbY2FudmFzUm90YXRpb25dPVwiMFwiXHJcbiAgICAgICAgICBbdHJhbnNmb3JtXT1cInRyYW5zZm9ybVwiXHJcbiAgICAgICAgICBbYWxpZ25JbWFnZV09XCInbGVmdCdcIlxyXG4gICAgICAgICAgZm9ybWF0PVwicG5nXCJcclxuICAgICAgICAgIChpbWFnZUNyb3BwZWQpPVwiaW1hZ2VDcm9wcGVkKCRldmVudClcIlxyXG4gICAgICAgICAgW3Jlc2l6ZVRvV2lkdGhdPVwiY3VzdG9tV2lkdGhcIlxyXG4gICAgICAgICAgW3Jlc2l6ZVRvSGVpZ2h0XT1cImN1c3RvbUhlaWdodFwiXHJcbiAgICAgICAgICBbY2FudmFzUm90YXRpb25dPVwiY2FudmFzUm90YXRpb25cIj5cclxuICAgICAgICA8L2ltYWdlLWNyb3BwZXI+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cInJvdyBqdXN0aWZ5LWNvbnRlbnQtY2VudGVyIG10LTIgbWItMiBjcm9wLWxhcmdlXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIganVzdGlmeS1jb250ZW50LWNlbnRlclwiPlxyXG4gICAgICA8YnV0dG9uXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgbWF0LXJhaXNlZC1idXR0b24gZXFwLWF0dGFjaG1lbnRzLWNvbmZpcm0tYnRuIG1lLTJcIlxyXG4gICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgIChjbGljayk9XCJjb25maXJtQWRkQXR0YWNobWVudCgpXCI+XHJcbiAgICAgICAge3sgY29uZmlybUxhYmVsIH19XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuIG1hdC1yYWlzZWQtYnV0dG9uIGVxcC1hdHRhY2htZW50cy1hYm9ydC1idG5cIiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImFib3J0RmlsZSgpXCI+XHJcbiAgICAgICAge3sgYWJvcnRMYWJlbCB9fVxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJyb3cganVzdGlmeS1jb250ZW50LWNlbnRlciBtdC0yIG1iLTIgY3JvcC1zbWFsbFwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbC02IGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIganVzdGlmeS1jb250ZW50LWNlbnRlclwiIHN0eWxlPVwiZm9udC1zaXplOiAyMHB4XCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmEgZmEtdGltZXNcIiAoY2xpY2spPVwiYWJvcnRGaWxlKClcIj48L2k+XHJcbiAgICA8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtNiBkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyIGp1c3RpZnktY29udGVudC1jZW50ZXJcIiBzdHlsZT1cImZvbnQtc2l6ZTogMjBweFwiPlxyXG4gICAgICA8aSBjbGFzcz1cImZhIGZhLWNoZWNrXCIgKGNsaWNrKT1cImNvbmZpcm1BZGRBdHRhY2htZW50KClcIj48L2k+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjwhLS0gVEVNUExBVEUgUEVSIEZPUk0gREkgQUdHSVVOVEEgREkgVU4gTElOSyAtLT5cclxuPG5nLXRlbXBsYXRlICNhZGRpbmdMaW5rVGVtcGxhdGU+XHJcbiAgPHNwYW4gY2xhc3M9XCJtYi0xXCIgc3R5bGU9XCJmb250LXNpemU6IDIwcHhcIj48aSBjbGFzcz1cImZhIGZhLWxpbmtcIj48L2k+SW5zZXJpc2NpIGwnVVJMPC9zcGFuPlxyXG4gIDxmb3JtIFtmb3JtR3JvdXBdPVwibmV3QXR0YWNobWVudEZvcm1cIiAqbmdJZj1cIm5ld0F0dGFjaG1lbnRGb3JtXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwicm93IG1iLTJcIiBzdHlsZT1cImhlaWdodDogODBweFwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLTYgZC1ncmlkIGdhcC0yIG14LWF1dG9cIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiaW5wdXQtZ3JvdXAgbWItMVwiPlxyXG4gICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcclxuICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxyXG4gICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7IGZpbGVOYW1lTGFiZWwgfX1cIlxyXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCJcclxuICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJuZXdBdHRhY2htZW50LkZpbGVOYW1lXCIgLz5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgZC1ncmlkIGdhcC0yXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImlucHV0LWdyb3VwXCI+XHJcbiAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgcmVxdWlyZWRcclxuICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiTGlua1wiXHJcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBhdGhcIlxyXG4gICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm5ld0F0dGFjaG1lbnQuRmlsZVBhdGhcIiAvPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gICAgPGRpdiBjbGFzcz1cInJvd1wiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiY29sLTYgZC1ncmlkIGdhcC0yXCI+XHJcbiAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBtYXQtcmFpc2VkLWJ1dHRvblwiXHJcbiAgICAgICAgICAoY2xpY2spPVwic2VsZWN0ZWRBdHRhY2htZW50ID0gbnVsbDsgYWRkaW5nTGlua01vZGUgPSBmYWxzZVwiXHJcbiAgICAgICAgICB0eXBlPVwiYnV0dG9uXCI+XHJcbiAgICAgICAgICB7eyBleGl0TGFiZWwgfX1cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtNiBkLWdyaWQgZ2FwLTJcIj5cclxuICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBtYXQtcmFpc2VkLWJ1dHRvblwiXHJcbiAgICAgICAgICB0eXBlPVwic3VibWl0XCJcclxuICAgICAgICAgIChjbGljayk9XCJjb25maXJtQWRkQXR0YWNobWVudCgpOyBzZWxlY3RlZEF0dGFjaG1lbnQgPSBudWxsOyBhZGRpbmdMaW5rTW9kZSA9IGZhbHNlXCI+XHJcbiAgICAgICAgICB7eyBzYXZlTGFiZWwgfX1cclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Zvcm0+XHJcbjwvbmctdGVtcGxhdGU+XHJcbiJdfQ==