@eqproject/eqp-attachments 2.10.0 → 3.0.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 (30) hide show
  1. package/README.md +1 -0
  2. package/{esm2020 → esm2022}/eqproject-eqp-attachments.mjs +4 -4
  3. package/esm2022/lib/eqp-attachments.component.mjs +1096 -0
  4. package/{esm2020 → esm2022}/lib/eqp-attachments.module.mjs +43 -43
  5. package/esm2022/lib/helpers/attachment.helper.mjs +66 -0
  6. package/{esm2020 → esm2022}/lib/interfaces/IAttachment.mjs +11 -11
  7. package/{esm2020 → esm2022}/lib/interfaces/IOptions.mjs +1 -1
  8. package/{esm2020 → esm2022}/lib/modules/material.module.mjs +231 -231
  9. package/{esm2020 → esm2022}/lib/services/eqp-attachment-dialog.service.mjs +103 -103
  10. package/{esm2020 → esm2022}/lib/services/eqp-attachment.service.mjs +23 -23
  11. package/{esm2020 → esm2022}/public-api.mjs +9 -9
  12. package/fesm2022/eqproject-eqp-attachments.mjs +1565 -0
  13. package/fesm2022/eqproject-eqp-attachments.mjs.map +1 -0
  14. package/index.d.ts +5 -5
  15. package/lib/eqp-attachments.component.d.ts +319 -314
  16. package/lib/eqp-attachments.module.d.ts +13 -13
  17. package/lib/helpers/attachment.helper.d.ts +20 -20
  18. package/lib/interfaces/IAttachment.d.ts +21 -21
  19. package/lib/interfaces/IOptions.d.ts +11 -11
  20. package/lib/modules/material.module.d.ts +37 -37
  21. package/lib/services/eqp-attachment-dialog.service.d.ts +31 -31
  22. package/lib/services/eqp-attachment.service.d.ts +7 -7
  23. package/package.json +15 -20
  24. package/public-api.d.ts +6 -6
  25. package/esm2020/lib/eqp-attachments.component.mjs +0 -1060
  26. package/esm2020/lib/helpers/attachment.helper.mjs +0 -66
  27. package/fesm2015/eqproject-eqp-attachments.mjs +0 -1531
  28. package/fesm2015/eqproject-eqp-attachments.mjs.map +0 -1
  29. package/fesm2020/eqproject-eqp-attachments.mjs +0 -1528
  30. package/fesm2020/eqproject-eqp-attachments.mjs.map +0 -1
@@ -1,1060 +0,0 @@
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
- });
552
- }
553
- else {
554
- this.showCropImage = false;
555
- let base64Result = await this.getBase64FromFile(this.selectedFile);
556
- this.newAttachment.FileDataBase64 = base64Result.Base64File;
557
- this.newAttachment.FileContentType = base64Result.ContentType;
558
- this.confirmAddAttachment();
559
- }
560
- }
561
- else {
562
- this.selectedFiles = filesOnInput;
563
- if (!this.selectedFiles || this.selectedFiles.length == 0)
564
- return;
565
- this.newMultipleAttachments = new Array();
566
- for (let i = 0; i < this.selectedFiles.length; i++) {
567
- let newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFiles[i], true, true);
568
- //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
569
- let checkOnlyImage = this.checkAllowOnlyImageFile(newAttachment);
570
- if (checkOnlyImage == false)
571
- return;
572
- this.newMultipleAttachments.push(newAttachment);
573
- }
574
- this.confirmAddAttachment();
575
- }
576
- //Resetto il valore del file input in modo da scatenare il change anche se si dovesse caricare lo stesso file
577
- if (!isFileDropped)
578
- event.target.value = "";
579
- }
580
- /**
581
- * A partire dal FILE ricevuto in input ricostruisce l'oggetto IAttachmentDTO e lo restituisce.
582
- * Se il parametro getBase64 viene passato a TRUE allora, sempre a partire dal file,genera il base64 e
583
- * ricava il ContentType da associare all'oggetto IAttachmentDTO da restituire
584
- * @param currentFile Oggetto FILE da processare
585
- * @param getBase64 Se TRUE allora calcola base64 e ContentType del file passato in input
586
- * @returns Restituisce un oggetto di tipo IAttachmentDTO
587
- */
588
- async createAttachmentFromUploadedFile(currentFile, getBase64 = true, cropFile = false) {
589
- let newAttachment = {};
590
- //Memorizza i dati per l'allegato
591
- newAttachment.AttachmentType = AttachmentType.FILE;
592
- newAttachment.FileContentType = currentFile.type;
593
- newAttachment.FileName = currentFile.name;
594
- newAttachment.FileExtension = currentFile.name.substr(currentFile.name.lastIndexOf(".") + 1);
595
- newAttachment.IsImage = AttachmentHelperService.checkImageFromMimeType(currentFile.type);
596
- if (getBase64 == true) {
597
- let base64Result = await this.getBase64FromFile(currentFile);
598
- newAttachment.FileDataBase64 = base64Result.Base64File;
599
- newAttachment.FileContentType = base64Result.ContentType;
600
- if (newAttachment.IsImage && newAttachment.FileDataBase64 && cropFile) {
601
- this.getCroppedAndUpload(`data:${base64Result.ContentType};base64,${base64Result.Base64File}`, newAttachment);
602
- }
603
- }
604
- return newAttachment;
605
- }
606
- /**
607
- * A partire dal file passato in input restituisce un oggetto
608
- * contenente il base64 del file e il suo contentType
609
- * @param currentFile Oggetto File da cui estrapolare base64 e contentType
610
- * @returns Restituisce un oggetto avente le proprietà Base64File e ContentType
611
- */
612
- async getBase64FromFile(currentFile) {
613
- let base64File = await toBase64(currentFile);
614
- let contentType = null;
615
- if (base64File) {
616
- // Loris 20/01/2022: PROBLEMA - Quando eseguo l'upload di un file .sql non viene salvato/scaricato correttamente.
617
- // Questo succede perchè non viene popolato il FileContentType. Per risolvere il problema
618
- // faccio un controllo e se non esiste il FileContentType allora lo recupero dal base64 ottenuto.
619
- contentType = base64File.split(",")[0].split(":")[1].split(";")[0];
620
- // Un altro metodo per leggere il ccontent type del file è tramite una regular expression:
621
- base64File = base64File.split(",")[1];
622
- }
623
- let result = {
624
- Base64File: base64File,
625
- ContentType: contentType
626
- };
627
- return result;
628
- }
629
- /**
630
- * Controlla se il file che si sta caricando è supportato dal sistema.
631
- * @returns
632
- */
633
- checkAcceptedFiles() {
634
- if ((this.loadMultipleFiles != true && this.selectedFile.type.startsWith("video")) ||
635
- (this.loadMultipleFiles == true && [...this.selectedFiles].filter((p) => p.type.startsWith("video")).length > 0))
636
- return false;
637
- if (this.acceptedFileTypes == "*")
638
- return true;
639
- //Verifica che i tipi del file (o dei file) caricati siano coerenti con quelli accettati dalla direttiva
640
- let accepted = true;
641
- if (this.loadMultipleFiles != true)
642
- accepted = this.acceptedFileTypes.includes(this.selectedFile.type);
643
- else {
644
- let uploadedFileTypes = [...this.selectedFiles].map((p) => p.type);
645
- uploadedFileTypes.forEach((type) => {
646
- if (!this.acceptedFileTypes.includes(type))
647
- accepted = false;
648
- });
649
- }
650
- //Questo controllo permette di gestire le casistiche per cui vengono indicati come tipi validi, ad esempio, 'image/*'
651
- if (!accepted && this.loadMultipleFiles != true) {
652
- for (let t of this.acceptedFileTypes.split(",").filter((t) => t.includes("*"))) {
653
- accepted = this.selectedFile.type.startsWith(t.split("*")[0]);
654
- if (accepted)
655
- break;
656
- }
657
- }
658
- return accepted;
659
- }
660
- /**
661
- * Se eqp-attachments è stata configurata per il caricamento delle sole immagini allora verifica che il file passato in
662
- * input sia effettivamente un immagine o no.
663
- * Se il controllo va a buon fine restituisce TRUE altrimenti mostra un messaggio d'errore e restituisce FALSE
664
- */
665
- checkAllowOnlyImageFile(newAttachment) {
666
- if (this.allowOnlyImages == true && newAttachment.IsImage != true) {
667
- EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage);
668
- this.abortFile();
669
- return false;
670
- }
671
- else if (!this.checkAcceptedFiles()) {
672
- EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage);
673
- this.abortFile();
674
- return false;
675
- }
676
- return true;
677
- }
678
- //#region Gestione crop file
679
- getImageDimensions(img) {
680
- const reader = new FileReader();
681
- reader.onload = (e) => {
682
- const image = new Image();
683
- image.src = e.target.result;
684
- image.onload = (rs) => {
685
- this.originalHeight = rs.currentTarget["height"];
686
- this.originalWidth = rs.currentTarget["width"];
687
- if (this.originalWidth > 1280) {
688
- this.customWidth = 1280;
689
- this.customHeight = Math.round((1280 * this.originalHeight) / this.originalWidth);
690
- }
691
- else {
692
- this.customHeight = rs.currentTarget["height"];
693
- this.customWidth = rs.currentTarget["width"];
694
- }
695
- };
696
- };
697
- reader.readAsDataURL(img);
698
- }
699
- restoreOriginalDimensions() {
700
- this.customWidth = this.originalWidth;
701
- this.customHeight = this.originalHeight;
702
- this.canvasRotation = 0;
703
- this.transform = {};
704
- }
705
- onDimensionsChange(dimension) {
706
- if (dimension == "H") {
707
- this.customWidth = Math.round((this.customHeight * this.originalWidth) / this.originalHeight);
708
- }
709
- else if (dimension == "W") {
710
- this.customHeight = Math.round((this.customWidth * this.originalHeight) / this.originalWidth);
711
- }
712
- }
713
- imageCropped(event) {
714
- this.croppedImage = event.base64;
715
- this.getCroppedAndUpload(this.croppedImage, this.newAttachment);
716
- }
717
- getCroppedAndUpload(file, newAttachment) {
718
- var self = this;
719
- var file = base64ToFile(file);
720
- const options = this.compressionOptions;
721
- /**
722
- * Comprime l'immagine passando come parametri le options create nell'oggetto sopra, e il file dal reader principale
723
- */
724
- imageCompression(file, options).then((fileCompressed) => {
725
- let fileReader = new FileReader();
726
- //Faccio la push di ogni file all'interno dell'array di file dell'item da mandare al server
727
- fileReader.onload = function () {
728
- let resultReader = fileReader.result;
729
- var marker = ";base64,";
730
- newAttachment.FileDataBase64 = resultReader.substring(resultReader.indexOf(marker) + marker.length);
731
- self.showCropImage = false;
732
- if (self.newAttachmentForm) {
733
- self.newAttachmentForm.enable();
734
- }
735
- };
736
- fileReader.readAsDataURL(fileCompressed);
737
- });
738
- }
739
- // confirmCrop() {
740
- // this.imageCropper.crop();
741
- // this.dialogRefCropImage.close();
742
- // this.restoreOriginalDimensions();
743
- // }
744
- rotateLeft() {
745
- this.canvasRotation--;
746
- this.flipAfterRotate();
747
- }
748
- rotateRight() {
749
- this.canvasRotation++;
750
- this.flipAfterRotate();
751
- }
752
- flipAfterRotate() {
753
- const flippedH = this.transform.flipH;
754
- const flippedV = this.transform.flipV;
755
- this.transform = {
756
- ...this.transform,
757
- flipH: flippedV,
758
- flipV: flippedH
759
- };
760
- }
761
- flipHorizontal() {
762
- this.transform = {
763
- ...this.transform,
764
- flipH: !this.transform.flipH
765
- };
766
- }
767
- flipVertical() {
768
- this.transform = {
769
- ...this.transform,
770
- flipV: !this.transform.flipV
771
- };
772
- }
773
- //#endregion
774
- /**
775
- * Annulla la selezione del file, svuotando l'input e resettando tutte le proprietà dell'IAttachmentDTO
776
- */
777
- abortFile() {
778
- if (this.imageInput)
779
- this.imageInput.nativeElement.value = "";
780
- this.selectedFile = null;
781
- this.selectedFiles = null;
782
- this.showCropImage = false;
783
- this.newAttachment.IsImage = false;
784
- this.newAttachment.FileDataBase64 = null;
785
- this.newAttachment.FileName = null;
786
- this.newAttachment.FileExtension = null;
787
- this.newAttachment.FileContentType = null;
788
- this.newMultipleAttachments = new Array();
789
- this.customHeight = null;
790
- this.customWidth = null;
791
- this.originalHeight = null;
792
- this.originalWidth = null;
793
- this.dialogRefCropImage.close();
794
- this.restoreOriginalDimensions();
795
- }
796
- //#endregion
797
- // Viene creato un'array observables per memorizzare tutti gli observable creati dalle chiamate a fileEntry.file().
798
- // Dopo che tutti gli observables sono stati completati, viene utilizzato il metodo subscribe() per eseguire la funzione onFileAdded().
799
- fileDropped(files) {
800
- let filesDropped = [];
801
- const observables = [];
802
- for (let i = 0; i < files.length; i++) {
803
- if (files[i].fileEntry.isFile) {
804
- const fileEntry = files[i].fileEntry;
805
- const observable = new Observable((observer) => {
806
- fileEntry.file((file) => {
807
- filesDropped.push(file);
808
- observer.next();
809
- observer.complete();
810
- });
811
- });
812
- observables.push(observable);
813
- }
814
- else {
815
- const fileEntry = files[i].fileEntry;
816
- console.log(files[i].relativePath, fileEntry);
817
- }
818
- }
819
- from(observables)
820
- .pipe(concatMap((observable) => observable))
821
- .subscribe({
822
- complete: () => {
823
- this.onFileAdded(filesDropped, true);
824
- }
825
- });
826
- }
827
- // Se il caricamento del file dropbox va a buon fine, la funzione di callback restituisce un array di oggetti.
828
- // Viene poi fatta una XMLHttpRequest con responseType 'blob' per convertire il primo elemento della response in un Blob.
829
- chooseDropboxFile() {
830
- var options = {
831
- success: (files) => {
832
- const xhr = new XMLHttpRequest();
833
- xhr.open("GET", files[0].link);
834
- xhr.setRequestHeader("Authorization", `Bearer ${AttachmentHelperService.dropboxCredentials.accessToken}`);
835
- xhr.responseType = "blob";
836
- xhr.onload = () => {
837
- const blob = xhr.response;
838
- const file = new File([blob], files[0].name, { type: blob.type });
839
- let filesAdded = [file];
840
- this.onFileAdded(filesAdded, true);
841
- };
842
- xhr.send();
843
- },
844
- linkType: "direct",
845
- multiselect: false,
846
- extensions: [".jpg", ".png", ".pdf", ".doc", ".docx", ".txt"]
847
- };
848
- Dropbox.choose(options);
849
- }
850
- // Workaround dropzone: disabilito il click degli elementi inclusi nella dropzone per evitare di cliccare due volte
851
- onSelectFile(event, fileInput) {
852
- if (event.target.tagName === "BUTTON" ||
853
- event.target.tagName === "INPUT" ||
854
- this.addingLinkMode == true) {
855
- return;
856
- }
857
- fileInput.click();
858
- }
859
- // Metodo per visualizzare la form di aggiunta di un link
860
- switchToAddingLinkMode() {
861
- this.addingLinkMode = true;
862
- this.newAttachment = {};
863
- this.newAttachment.IsImage = false;
864
- this.newAttachment.AttachmentType = this.attachmentType.LINK;
865
- this.newMultipleAttachments = new Array();
866
- this.newMultipleAttachments.push(this.newAttachment);
867
- this.createAttachmentForm();
868
- }
869
- }
870
- 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 });
871
- 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", 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\">\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\">\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\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\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\">\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 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\">\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=\"fas 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", "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]" }] });
872
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.10", ngImport: i0, type: EqpAttachmentsComponent, decorators: [{
873
- type: Component,
874
- 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\">\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\">\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\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\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\">\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 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\">\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=\"fas 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"] }]
875
- }], ctorParameters: function () { return [{ type: i1.MatDialog }, { type: i2.FormBuilder }, { type: i3.DomSanitizer }, { type: i4.HttpClient }, { type: i0.ChangeDetectorRef }, { type: i5.EqpAttachmentService }]; }, propDecorators: { disableAction: [{
876
- type: Input,
877
- args: ["disableAction"]
878
- }], showHeader: [{
879
- type: Input,
880
- args: ["showHeader"]
881
- }], headerTitle: [{
882
- type: Input,
883
- args: ["headerTitle"]
884
- }], attachmentsList: [{
885
- type: Input,
886
- args: ["attachmentsList"]
887
- }], showMatCard: [{
888
- type: Input,
889
- args: ["showMatCard"]
890
- }], multipleAttachment: [{
891
- type: Input,
892
- args: ["multipleAttachment"]
893
- }], loadMultipleFiles: [{
894
- type: Input,
895
- args: ["loadMultipleFiles"]
896
- }], attachmentsColumns: [{
897
- type: Input,
898
- args: ["attachmentsColumns"]
899
- }], emptyTableMessage: [{
900
- type: Input,
901
- args: ["emptyTableMessage"]
902
- }], allowOnlyImages: [{
903
- type: Input,
904
- args: ["allowOnlyImages"]
905
- }], acceptedFileTypes: [{
906
- type: Input,
907
- args: ["acceptedFileTypes"]
908
- }], isDisabled: [{
909
- type: Input,
910
- args: ["isDisabled"]
911
- }], showInlinePreview: [{
912
- type: Input,
913
- args: ["showInlinePreview"]
914
- }], getAttachmentEndpoint: [{
915
- type: Input,
916
- args: ["getAttachmentEndpoint"]
917
- }], productionBaseUrl: [{
918
- type: Input,
919
- args: ["productionBaseUrl"]
920
- }], compressionOptions: [{
921
- type: Input,
922
- args: ["compressionOptions"]
923
- }], allowedTypes: [{
924
- type: Input,
925
- args: ["allowedTypes"]
926
- }], isEqpTableMultiLanguage: [{
927
- type: Input,
928
- args: ["isEqpTableMultiLanguage"]
929
- }], tablePaginatorVisible: [{
930
- type: Input,
931
- args: ["tablePaginatorVisible"]
932
- }], isTableSearcheable: [{
933
- type: Input,
934
- args: ["isTableSearcheable"]
935
- }], tablePaginatorSize: [{
936
- type: Input,
937
- args: ["tablePaginatorSize"]
938
- }], separatedUploadButtons: [{
939
- type: Input,
940
- args: ["separatedUploadButtons"]
941
- }], showPreview: [{
942
- type: Input,
943
- args: ["showPreview"]
944
- }], singleAttachmentDragAndDrop: [{
945
- type: Input,
946
- args: ["singleAttachmentDragAndDrop"]
947
- }], cropOptions: [{
948
- type: Input,
949
- args: ["cropOptions"]
950
- }], downloadTooltipPosition: [{
951
- type: Input,
952
- args: ["downloadTooltipPosition"]
953
- }], openLinkLabel: [{
954
- type: Input,
955
- args: ["openLinkLabel"]
956
- }], addButtonLabel: [{
957
- type: Input,
958
- args: ["addButtonLabel"]
959
- }], downloadLabel: [{
960
- type: Input,
961
- args: ["downloadLabel"]
962
- }], deleteLabel: [{
963
- type: Input,
964
- args: ["deleteLabel"]
965
- }], fileNameLabel: [{
966
- type: Input,
967
- args: ["fileNameLabel"]
968
- }], previewLabel: [{
969
- type: Input,
970
- args: ["previewLabel"]
971
- }], uploadFileLabel: [{
972
- type: Input,
973
- args: ["uploadFileLabel"]
974
- }], confirmLabel: [{
975
- type: Input,
976
- args: ["confirmLabel"]
977
- }], abortLabel: [{
978
- type: Input,
979
- args: ["abortLabel"]
980
- }], saveLabel: [{
981
- type: Input,
982
- args: ["saveLabel"]
983
- }], exitLabel: [{
984
- type: Input,
985
- args: ["exitLabel"]
986
- }], uploadWithDropboxLabel: [{
987
- type: Input,
988
- args: ["uploadWithDropboxLabel"]
989
- }], cropLabel: [{
990
- type: Input,
991
- args: ["cropLabel"]
992
- }], eqpTableSearchText: [{
993
- type: Input,
994
- args: ["eqpTableSearchText"]
995
- }], deleteDialogTitle: [{
996
- type: Input,
997
- args: ["deleteDialogTitle"]
998
- }], deleteDialogMessage: [{
999
- type: Input,
1000
- args: ["deleteDialogMessage"]
1001
- }], noImageSelectedErrorMessage: [{
1002
- type: Input,
1003
- args: ["noImageSelectedErrorMessage"]
1004
- }], wrongTypeSelectedErrorMessage: [{
1005
- type: Input,
1006
- args: ["wrongTypeSelectedErrorMessage"]
1007
- }], videoPreviewErrorMessage: [{
1008
- type: Input,
1009
- args: ["videoPreviewErrorMessage"]
1010
- }], audioPreviewErrorMessage: [{
1011
- type: Input,
1012
- args: ["videoPreviewErrorMessage"]
1013
- }], flipHorinzontalLabel: [{
1014
- type: Input,
1015
- args: ["flipHorinzontalLabel"]
1016
- }], flipVerticalLabel: [{
1017
- type: Input,
1018
- args: ["flipVerticalLabel"]
1019
- }], rotateRightLabel: [{
1020
- type: Input,
1021
- args: ["rotateRightLabel"]
1022
- }], rotateLeftLabel: [{
1023
- type: Input,
1024
- args: ["rotateLeftLabel"]
1025
- }], localEditedAttachments: [{
1026
- type: Output
1027
- }], abortAddAttachment: [{
1028
- type: Output
1029
- }], downloadAttachment: [{
1030
- type: Output,
1031
- args: ["downloadAttachment"]
1032
- }], onDeleteAttachment: [{
1033
- type: Output,
1034
- args: ["onDeleteAttachment"]
1035
- }], dialogAddAttachment: [{
1036
- type: ViewChild,
1037
- args: ["dialogAddAttachment", { static: true }]
1038
- }], dialogAddMultipleAttachment: [{
1039
- type: ViewChild,
1040
- args: ["dialogAddMultipleAttachment", { static: true }]
1041
- }], dialogCropImage: [{
1042
- type: ViewChild,
1043
- args: ["dialogCropImage", { static: true }]
1044
- }], imageCropper: [{
1045
- type: ViewChild,
1046
- args: [ImageCropperComponent]
1047
- }], imageInput: [{
1048
- type: ViewChild,
1049
- args: ["imageInput"]
1050
- }], attachmentTable: [{
1051
- type: ViewChild,
1052
- args: ["attachmentTable", { static: false }]
1053
- }], inlinePreviewTemplate: [{
1054
- type: ViewChild,
1055
- args: ["inlinePreviewTemplate", { static: true }]
1056
- }], dialogPreview: [{
1057
- type: ViewChild,
1058
- args: ["dialogPreview", { static: true }]
1059
- }] } });
1060
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2VxcC1hdHRhY2htZW50cy9zcmMvbGliL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtYXR0YWNobWVudHMvc3JjL2xpYi9lcXAtYXR0YWNobWVudHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUVMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFTixTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUEwQixVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdwRSxPQUFPLEVBQW1DLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3hHLE9BQU8sZ0JBQWdCLE1BQU0sMkJBQTJCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBcUIscUJBQXFCLEVBQWtCLE1BQU0sbUJBQW1CLENBQUM7QUFDM0csT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdEUsT0FBTyxFQUFFLGNBQWMsRUFBa0MsTUFBTSwwQkFBMEIsQ0FBQztBQUUxRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSwwQ0FBMEMsQ0FBQztBQUl0RixPQUFPLEVBQUUsU0FBUyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxNQUFNLENBQUM7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUduRCxNQUFNLFFBQVEsR0FBRyxDQUFDLElBQUksRUFBRSxFQUFFLENBQ3hCLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBQ3RDLE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxFQUFFLENBQUM7SUFDaEMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJ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QUEvQixNQUFNO2dCQUtHLGtCQUFrQjtzQkFBM0IsTUFBTTtnQkFLdUIsa0JBQWtCO3NCQUEvQyxNQUFNO3VCQUFDLG9CQUFvQjtnQkFLRSxrQkFBa0I7c0JBQS9DLE1BQU07dUJBQUMsb0JBQW9CO2dCQWF3QixtQkFBbUI7c0JBQXRFLFNBQVM7dUJBQUMscUJBQXFCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUVVLDJCQUEyQjtzQkFBdEYsU0FBUzt1QkFBQyw2QkFBNkIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRVYsZUFBZTtzQkFBOUQsU0FBUzt1QkFBQyxpQkFBaUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBUVosWUFBWTtzQkFBN0MsU0FBUzt1QkFBQyxxQkFBcUI7Z0JBQ1AsVUFBVTtzQkFBbEMsU0FBUzt1QkFBQyxZQUFZO2dCQVcwQixlQUFlO3NCQUEvRCxTQUFTO3VCQUFDLGlCQUFpQixFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFDTyxxQkFBcUI7c0JBQTFFLFNBQVM7dUJBQUMsdUJBQXVCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNOLGFBQWE7c0JBQTFELFNBQVM7dUJBQUMsZUFBZSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEh0dHBDbGllbnQgfSBmcm9tIFwiQGFuZ3VsYXIvY29tbW9uL2h0dHBcIjtcclxuaW1wb3J0IHtcclxuICBDaGFuZ2VEZXRlY3RvclJlZixcclxuICBDb21wb25lbnQsXHJcbiAgRXZlbnRFbWl0dGVyLFxyXG4gIElucHV0LFxyXG4gIE9uSW5pdCxcclxuICBPdXRwdXQsXHJcbiAgVGVtcGxhdGVSZWYsXHJcbiAgVmlld0NoaWxkXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgRm9ybUJ1aWxkZXIsIEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gXCJAYW5ndWxhci9mb3Jtc1wiO1xyXG5pbXBvcnQgeyBNYXREaWFsb2csIE1hdERpYWxvZ1JlZiB9IGZyb20gXCJAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2dcIjtcclxuaW1wb3J0IHsgRG9tU2FuaXRpemVyIH0gZnJvbSBcIkBhbmd1bGFyL3BsYXRmb3JtLWJyb3dzZXJcIjtcclxuaW1wb3J0IHsgQ29uZmlnQ29sdW1uLCBFcXBUYWJsZUNvbXBvbmVudCwgVG9vbHRpcFBvc2l0aW9uVHlwZSwgVHlwZUNvbHVtbiB9IGZyb20gXCJAZXFwcm9qZWN0L2VxcC10YWJsZVwiO1xyXG5pbXBvcnQgaW1hZ2VDb21wcmVzc2lvbiBmcm9tIFwiYnJvd3Nlci1pbWFnZS1jb21wcmVzc2lvblwiO1xyXG5pbXBvcnQgeyBiYXNlNjRUb0ZpbGUsIEltYWdlQ3JvcHBlZEV2ZW50LCBJbWFnZUNyb3BwZXJDb21wb25lbnQsIEltYWdlVHJhbnNmb3JtIH0gZnJvbSBcIm5neC1pbWFnZS1jcm9wcGVyXCI7XHJcbmltcG9ydCB7IEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlIH0gZnJvbSBcIi4vaGVscGVycy9hdHRhY2htZW50LmhlbHBlclwiO1xyXG5pbXBvcnQgeyBBdHRhY2htZW50VHlwZSwgQ3JvcE9wdGlvbkVudW0sIElBdHRhY2htZW50RFRPIH0gZnJvbSBcIi4vaW50ZXJmYWNlcy9JQXR0YWNobWVudFwiO1xyXG5pbXBvcnQgeyBJT3B0aW9ucyB9IGZyb20gXCIuL2ludGVyZmFjZXMvSU9wdGlvbnNcIjtcclxuaW1wb3J0IHsgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9lcXAtYXR0YWNobWVudC1kaWFsb2cuc2VydmljZVwiO1xyXG5cclxuZGVjbGFyZSB2YXIgRHJvcGJveDogYW55O1xyXG5cclxuaW1wb3J0IHsgY29uY2F0TWFwLCBmcm9tLCBPYnNlcnZhYmxlIH0gZnJvbSBcInJ4anNcIjtcclxuaW1wb3J0IHsgRXFwQXR0YWNobWVudFNlcnZpY2UgfSBmcm9tIFwiLi9zZXJ2aWNlcy9lcXAtYXR0YWNobWVudC5zZXJ2aWNlXCI7XHJcblxyXG5jb25zdCB0b0Jhc2U2NCA9IChmaWxlKSA9PlxyXG4gIG5ldyBQcm9taXNlPHN0cmluZz4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGUpO1xyXG4gICAgcmVhZGVyLm9ubG9hZCA9ICgpID0+IHJlc29sdmUocmVhZGVyLnJlc3VsdC50b1N0cmluZygpKTtcclxuICAgIHJlYWRlci5vbmVycm9yID0gKGVycm9yKSA9PiByZWplY3QoZXJyb3IpO1xyXG4gIH0pO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6IFwiZXFwLWF0dGFjaG1lbnRzXCIsXHJcbiAgdGVtcGxhdGVVcmw6IFwiLi9lcXAtYXR0YWNobWVudHMuY29tcG9uZW50Lmh0bWxcIixcclxuICBzdHlsZVVybHM6IFtcIi4vZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5zY3NzXCJdXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBFcXBBdHRhY2htZW50c0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgLy8jcmVnaW9uIEBJbnB1dCBkZWwgY29tcG9uZW50ZVxyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIGFsbG9yYSBuYXNjb25kZSBsYSBjb2xvbm5hIHBlciBsZSBhemlvbmkgc3VsbCdhbGxlZ2F0byAobmVsIGNhc28gXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJkaXNhYmxlQWN0aW9uXCIpIGRpc2FibGVBY3Rpb246IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBtb3N0cmEgaWwgdGl0b2xvIG5lbGwnaGVhZGVyIG5lbCBjYXNvIGluIGN1aSBcIm11bHRpcGxlQXR0YWNobWVudFwiIMOoIFRSVUUgKFwiRWxlbmNvIGFsbGVnYXRpXCIgZGkgZGVmYXVsdCkuXHJcbiAgICovXHJcbiAgQElucHV0KFwic2hvd0hlYWRlclwiKSBzaG93SGVhZGVyOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogVGl0b2xvIGRhIHZpc3VhbGl6emFyZSBzZSBpbCBwYXJhbWV0cm8gXCJzaG93SGVhZGVyXCIgw6ggVFJVRS4gRGkgZGV2YXVsdCB2aWVuZSB2aXN1YWxpenphdG8gXCJFbGVuY28gYWxsZWdhdGlcIi5cclxuICAgKi9cclxuICBASW5wdXQoXCJoZWFkZXJUaXRsZVwiKSBoZWFkZXJUaXRsZTogc3RyaW5nID0gXCJFbGVuY28gYWxsZWdhdGlcIjtcclxuXHJcbiAgLyoqXHJcbiAgICogU29yZ2VudGUgZGF0aSBkYSB2aXN1YWxpenphcmUuIE5lbCBjYXNvIHNpIHZ1b2xlIGdlc3RpcmUgdW4gc2luZ29sbyBhbGxlZ2F0byB2YSBwYXNzYXRvIGluIG9nbmkgY2FzbyBjb21lIEFycmF5LlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImF0dGFjaG1lbnRzTGlzdFwiKSBhdHRhY2htZW50c0xpc3Q6IEFycmF5PElBdHRhY2htZW50RFRPPiA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgbm9uIG1vc3RyYSBsYSBNYXRDYXJkIChuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJzaG93TWF0Q2FyZFwiKSBzaG93TWF0Q2FyZDogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIEZBTFNFIGFsbG9yYSBpbCBjb21wb25lbnRlIG1vc3RyYSBzb2xvIGlsIHB1bHNhbnRlIGRpIGNhcmljYW1lbnRvIGRpIHVuIHNpbmdvbG8gZmlsZSwgdW5hIHZvbHRhIGNhcmljYXRvIGlsIGZpbGUgaW52b2NhIGwnZXZlbnRvIGRpIG91dHB1dCBcImxvY2FsRWRpdGVkQXR0YWNobWVudHNcIi5cclxuICAgKiBTZSBUUlVFIGFsbG9yYSBpbCBjb21wb25lbnRlIG1vc3RyYSBsJ2VsZW5jbyBkaSB0dXR0aSBnbGkgYWxsZWdhdGkgcmljZXZ1dG8gbmVsIHBhcmFtZXRybyBcImF0dGFjaG1lbnRzTGlzdFwiLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcIm11bHRpcGxlQXR0YWNobWVudFwiKSBtdWx0aXBsZUF0dGFjaG1lbnQ6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBhc3N1bWUgaWwgdmFsb3JlIFRSVUUgYWxsb3JhIHNhcsOgIHBvc3NpYmlsZSBjYXJpY2FyZSBwacO5IGZpbGUgcGVyIHZvbHRhLiBRdWVzdGEgZnVuemlvbmFsaXTDoCDDqCBhdHRpdmFcclxuICAgKiBTT0xPIHNlIHNpIGdlc3Rpc2Nvbm8gYWxsZWdhdGkgbXVsdGlwbGksIHF1aW5kaSBzZSBsJ2lucHV0ICdtdWx0aXBsZUF0dGFjaG1lbnQnIGFzc3VtZSBpbCB2YWxvcmUgVFJVRSwgYWx0cmltZW50aSDDqCBzZW1wcmUgZGlzYWJpbGl0YXRhLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImxvYWRNdWx0aXBsZUZpbGVzXCIpIGxvYWRNdWx0aXBsZUZpbGVzOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbmZpZ3VyYXppb25lIGRlbGxlIGNvbG9ubmUgZGVsbGEgZXFwLXRhYmxlIHBlciBsYSB2aXN1YWxpenphemlvbmUgZGVnbGkgYWxsZWdhdGkgKGNhc28gXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJhdHRhY2htZW50c0NvbHVtbnNcIikgYXR0YWNobWVudHNDb2x1bW5zOiBBcnJheTxDb25maWdDb2x1bW4+ID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogSW1wb3N0YSBpbCBtZXNzYWdnaW8gZGEgdmlzdWFsaXp6YXJlIG5lbCBjYXNvIGluIGN1aSBsYSB0YWJlbGxhIGRlZ2xpIGFsbGVnYXRpIChuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFKSDDqCB2dW90YS5cclxuICAgKi9cclxuICBASW5wdXQoXCJlbXB0eVRhYmxlTWVzc2FnZVwiKSBlbXB0eVRhYmxlTWVzc2FnZTogc3RyaW5nID0gXCJOZXNzdW4gZGF0byB0cm92YXRvXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgYWxsb3JhIHBlcm1ldHRlIGRpIHNlbGV6aW9uYXJlIHNvbHRhbnRvIGZpbGUgZGkgdGlwbyBpbW1hZ2luZSwgYXZlbnRlIHVubyBkZWkgbWltZXR5cGVcclxuICAgKiBzcGVjaWZpY2F0aSBkZW50cm8gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuXHJcbiAgICogU2UgRkFMU0UgcGVybWV0dGUgZGkgc2VsZXppb25hcmUgcXVhbHNpYXNpIHRpcG8gZGkgZmlsZVxyXG4gICAqL1xyXG4gIEBJbnB1dChcImFsbG93T25seUltYWdlc1wiKSBhbGxvd09ubHlJbWFnZXM6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU3BlY2lmaWNhIGkgdGlwaSBkaSBmaWxlIGNoZSDDqCBwb3NzaWJpbGUgY2FyaWNhcmVcclxuICAgKi9cclxuICBASW5wdXQoXCJhY2NlcHRlZEZpbGVUeXBlc1wiKSBhY2NlcHRlZEZpbGVUeXBlczogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIGRpc2FiaWxpdGEgaWwgcHVsc2FudGUgZGkgQWdnaXVudGEgYWxsZWdhdG8gKGEgcHJlc2NpbmRlcmUgZGFsIHZhbG9yZSBkZWwgcGFyYW1ldHJvIFwibXVsdGlwbGVBdHRhY2htZW50XCIpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImlzRGlzYWJsZWRcIikgaXNEaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBNb3N0cmEvbmFzY29uZGUgbGEgY29sb25uYSBwZXIgdmlzdWFsaXp6YXJlIGwnYW50ZXByaW1hIGRlaSBmaWxlIG5lbGxhIHRhYmVsbGEgKGNhc28gbXVsdGlwbGVBdGF0Y2htZW50cyA9IHRydWUpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dJbmxpbmVQcmV2aWV3XCIpIHNob3dJbmxpbmVQcmV2aWV3OiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIEVuZHBvaW50IGRhIGNoaWFtYXJlIHBlciByZWN1ZXByYXJlIGwnSUF0dGFjaG1lbnREVE8gY29tcGxldG8gZGEgdmVkZXJlIG5lbGwnYW50ZXByaW1hLiBMYSBjaGlhbWF0YSBzYXLDoCBpbiBQT1NUIGUgbmVsIGJvZHlcclxuICAgKiBjb250ZXJyw6AgbCdJQXR0YWNobWVudERUTyBzZWxlemlvbmF0byBkYWxsJ3V0ZW50ZS5cclxuICAgKiBMYSBjaGlhbWF0YSB2aWVuZSBlc2VndWl0YSBzb2xvIHBlciBsJ2FudGVwcmltYSBkZWxsZSBpbW1hZ2luaSBlc3NlbmRvIG5lY2Vzc2FyaW8gaWwgYmFzZTY0IGNvbXBsZXRvIGRlbGwnaW1tYWdpbmUgYSBkaW1lbnNpb25lIHJlYWxlLlxyXG4gICAqIFBlciBkb2N1bWVudGkvbGluayBiYXN0YSBjaGUgc2lhIHBvcG9sYXRhIGxhIHByb3ByaWV0w6AgRmlsZVBhdGggZGkgSUF0dGFjaG1lbnREVE8uXHJcbiAgICovXHJcbiAgQElucHV0KFwiZ2V0QXR0YWNobWVudEVuZHBvaW50XCIpIGdldEF0dGFjaG1lbnRFbmRwb2ludDogc3RyaW5nID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogSG9zdG5hbWUgZGVsbCdhbWJpZW50ZSBkaSBwcm9kdXppb25lIGRlbGwnYXBwbGljYXRpdm8uIE5lY2Vzc2FyaW8gcGVyIHZpc3VhbGl6emFyZSBsJ2FudGVwcmltYSBkZWkgZG9jdW1lbnRpXHJcbiAgICogdHJhbWl0ZSBpbCB2aWV3ZXIgZGkgZ29vZ2xlLlxyXG4gICAqIE5PVEE6IFBlciB2aXN1YWxpenphcmUgbCdhbnRlcHJpbWEgw6ggbmVjZXNzYXJpbyBjaGUgbGEgcHJvcmlldMOgIEZpbGVQYXRoIGRlbGwnSUF0dGFjaG1lbnREVE8gc2lhIHBvcG9sYXRhIGUgY2hlXHJcbiAgICogc2lhIGFiaWxpdGF0byBsJ2FjY2Vzc28gYWxsYSBjYXJ0ZWxsYSBzdWwgc2VydmVyIHRyYW1pdGUgaG9zdG5hbWUuXHJcbiAgICovXHJcbiAgQElucHV0KFwicHJvZHVjdGlvbkJhc2VVcmxcIikgcHJvZHVjdGlvbkJhc2VVcmw6IHN0cmluZyA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIE9wemlvbmkgcGVyIGxhIGNvbXByZXNzaW9uZSBkZWxsZSBpbW1hZ2luaSBjYXJpY2F0ZS5cclxuICAgKi9cclxuICBASW5wdXQoXCJjb21wcmVzc2lvbk9wdGlvbnNcIikgY29tcHJlc3Npb25PcHRpb25zOiBJT3B0aW9ucyA9IHtcclxuICAgIG1heFNpemVNQjogMC41LFxyXG4gICAgbWF4V2lkdGhPckhlaWdodDogMTkyMCxcclxuICAgIHVzZVdlYldvcmtlcjogdHJ1ZVxyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IGRpIEF0dGFjaG1lbnRUeXBlIGNoZSBzaSBwb3Nzb25vIGFnZ2l1bmdlcmVcclxuICAgKi9cclxuICBASW5wdXQoXCJhbGxvd2VkVHlwZXNcIikgYWxsb3dlZFR5cGVzOiBBcnJheTxBdHRhY2htZW50VHlwZT4gPSBbQXR0YWNobWVudFR5cGUuRklMRSwgQXR0YWNobWVudFR5cGUuTElOS107XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSBzZSBsYSBlcXAtdGFibGUgY29udGVuZW50ZSBsJ2VsZW5jbyBkZWdsaSBhbGxlZ2F0aSB1dGlsaXp6YVxyXG4gICAqIGlsIG11bHRpbGluZ3VhIG9wcHVyZSBub1xyXG4gICAqL1xyXG4gIEBJbnB1dChcImlzRXFwVGFibGVNdWx0aUxhbmd1YWdlXCIpIGlzRXFwVGFibGVNdWx0aUxhbmd1YWdlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSwgaW4gY2FzbyBkaSBnZXN0aW9uZSBhbGxlZ2F0aSBtdWx0aXBsaSwgc2UgbGEgdGFiZWxsYSBjb250ZW5lbnRlIGwnZWxlbmNvXHJcbiAgICogZGVnbGkgYWxsZWdhdGkgZGV2ZSBlc3NlcmUgcGFnaW5hdGEgb3BwdXJlIG5vXHJcbiAgICovXHJcbiAgQElucHV0KFwidGFibGVQYWdpbmF0b3JWaXNpYmxlXCIpIHRhYmxlUGFnaW5hdG9yVmlzaWJsZTogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSwgaW4gY2FzbyBkaSBnZXN0aW9uZSBhbGxlZ2F0aSBtdWx0aXBsaSwgc2UgbGEgdGFiZWxsYSBjb250ZW5lbnRlIGwnZWxlbmNvXHJcbiAgICogZGVnbGkgYWxsZWdhdGkgZGV2ZSBjb250ZW5lcmUgaWwgY2FtcG8gZGkgcmljZXJjYSBvcHB1cmUgbm9cclxuICAgKi9cclxuICBASW5wdXQoXCJpc1RhYmxlU2VhcmNoZWFibGVcIikgaXNUYWJsZVNlYXJjaGVhYmxlOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW4gY2FzbyBkaSBnZXN0aW9uZSBhbGxlZ2F0aSBtdWx0aXBsaSwgcGVybWV0dGUgZGkgc3RhYmlsaXJlIGxhIGRpbWVuc2lvbmUgcGFnaW5hIGRpIGRlZmF1bHRcclxuICAgKiBwZXIgbGEgdGFiZWxsYSBjb250ZW5lbnRlIGwnZWxlbmNvIGRlZ2xpIGFsbGVnYXRpXHJcbiAgICovXHJcbiAgQElucHV0KFwidGFibGVQYWdpbmF0b3JTaXplXCIpIHRhYmxlUGFnaW5hdG9yU2l6ZTogbnVtYmVyID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc2NlZ2xpZXJlIGlsIG1vZG8gaW4gY3VpIGkgZmlsZSBkZXZvbm8gZXNzZXJlIGNhcmljYXRpXHJcbiAgICovXHJcbiAgLy8gQElucHV0KFwidXBsb2FkVHlwZVwiKSB1cGxvYWRUeXBlOiBVcGxvYWRUeXBlRW51bSA9IFVwbG9hZFR5cGVFbnVtLkZJTEVfQU5EX0xJTks7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSBzZSBpIHB1bHNhbnRpIHBlciBpbCBjYXJpY2FtZW50byBkZWkgZmlsZSBzb25vIHNlcGFyYXRpIG8gaW4gdW4gbWVuw7kgYSB0ZW5kaW5hXHJcbiAgICovXHJcbiAgQElucHV0KFwic2VwYXJhdGVkVXBsb2FkQnV0dG9uc1wiKSBzZXBhcmF0ZWRVcGxvYWRCdXR0b25zOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHNjZWdsaWVyZSBzZSBkYXJlIGxhIHBvc3NpYmlsaXTDoCBkaSB2ZWRlcmUgbyBubyBsJ2FudGVwcmltYVxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dQcmV2aWV3XCIpIHNob3dQcmV2aWV3OiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW4gY2FzbyBkaSBhbGxlZ2F0byBzaW5nb2xvLCBwZXJtZXR0ZSBkaSBzY2VnbGllcmUgc2UgYWdnaXVuZ2VyZSBmaWxlIHRyYW1pdGUgZHJhZyBhbmQgZHJvcFxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNpbmdsZUF0dGFjaG1lbnREcmFnQW5kRHJvcFwiKSBzaW5nbGVBdHRhY2htZW50RHJhZ0FuZERyb3A6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogQXJyYXkgZGkgb3B6aW9uaSBjaGUgc2kgcG9zc29ubyB1dGlsaXp6YXJlIHBlciBpbCBjcm9wXHJcbiAgICovXHJcbiAgQElucHV0KFwiY3JvcE9wdGlvbnNcIikgY3JvcE9wdGlvbnM6IEFycmF5PENyb3BPcHRpb25FbnVtPiA9IFtdO1xyXG5cclxuICAvKipcclxuICAgKiBJbnB1dCBwZXIgZGVmaW5pcmUgbGUgbGFiZWwgZGEgdXNhcmUgbmVsIGNvbXBvbmVudGVcclxuICAgKi9cclxuICBASW5wdXQoXCJkb3dubG9hZFRvb2x0aXBQb3NpdGlvblwiKSBkb3dubG9hZFRvb2x0aXBQb3NpdGlvbjogVG9vbHRpcFBvc2l0aW9uVHlwZSA9IFRvb2x0aXBQb3NpdGlvblR5cGUuQmVsb3c7XHJcbiAgQElucHV0KFwib3BlbkxpbmtMYWJlbFwiKSBvcGVuTGlua0xhYmVsOiBzdHJpbmcgPSBcIkFwcmkgbGlua1wiO1xyXG4gIEBJbnB1dChcImFkZEJ1dHRvbkxhYmVsXCIpIGFkZEJ1dHRvbkxhYmVsOiBzdHJpbmcgPSBcIkFnZ2l1bmdpXCI7XHJcbiAgQElucHV0KFwiZG93bmxvYWRMYWJlbFwiKSBkb3dubG9hZExhYmVsOiBzdHJpbmcgPSBcIkRvd25sb2FkXCI7XHJcbiAgQElucHV0KFwiZGVsZXRlTGFiZWxcIikgZGVsZXRlTGFiZWw6IHN0cmluZyA9IFwiRWxpbWluYVwiO1xyXG4gIEBJbnB1dChcImZpbGVOYW1lTGFiZWxcIikgZmlsZU5hbWVMYWJlbDogc3RyaW5nID0gXCJOb21lIGZpbGVcIjtcclxuICBASW5wdXQoXCJwcmV2aWV3TGFiZWxcIikgcHJldmlld0xhYmVsOiBzdHJpbmcgPSBcIkFudGVwcmltYVwiO1xyXG4gIEBJbnB1dChcInVwbG9hZEZpbGVMYWJlbFwiKSB1cGxvYWRGaWxlTGFiZWw6IHN0cmluZyA9IFwiQ2FyaWNhIGZpbGVcIjtcclxuICBASW5wdXQoXCJjb25maXJtTGFiZWxcIikgY29uZmlybUxhYmVsOiBzdHJpbmcgPSBcIkNvbmZlcm1hXCI7XHJcbiAgQElucHV0KFwiYWJvcnRMYWJlbFwiKSBhYm9ydExhYmVsOiBzdHJpbmcgPSBcIkFubnVsbGFcIjtcclxuICBASW5wdXQoXCJzYXZlTGFiZWxcIikgc2F2ZUxhYmVsOiBzdHJpbmcgPSBcIlNhbHZhXCI7XHJcbiAgQElucHV0KFwiZXhpdExhYmVsXCIpIGV4aXRMYWJlbDogc3RyaW5nID0gXCJFc2NpXCI7XHJcbiAgQElucHV0KFwidXBsb2FkV2l0aERyb3Bib3hMYWJlbFwiKSB1cGxvYWRXaXRoRHJvcGJveExhYmVsOiBzdHJpbmcgPSBcIkNhcmljYSBjb24gRHJvcGJveFwiO1xyXG4gIEBJbnB1dChcImNyb3BMYWJlbFwiKSBjcm9wTGFiZWw6IHN0cmluZyA9IFwiU2NlZ2xpIGxlIGRpbWVuc2lvbmkgZGVsbCdpbW1hZ2luZVwiO1xyXG4gIEBJbnB1dChcImVxcFRhYmxlU2VhcmNoVGV4dFwiKSBlcXBUYWJsZVNlYXJjaFRleHQ6IHN0cmluZyA9IFwiQ2VyY2FcIjtcclxuICBASW5wdXQoXCJkZWxldGVEaWFsb2dUaXRsZVwiKSBkZWxldGVEaWFsb2dUaXRsZTogc3RyaW5nID0gbnVsbDtcclxuICBASW5wdXQoXCJkZWxldGVEaWFsb2dNZXNzYWdlXCIpIGRlbGV0ZURpYWxvZ01lc3NhZ2U6IHN0cmluZyA9IFwiU2VpIHNpY3VybyBkaSB2b2xlciBjYW5jZWxsYXJlIHF1ZXN0J2FsbGVnYXRvP1wiO1xyXG4gIEBJbnB1dChcIm5vSW1hZ2VTZWxlY3RlZEVycm9yTWVzc2FnZVwiKSBub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIk5vbiDDqCBwb3NzaWJpbGUgc2VsZXppb25hcmUgdW4gZmlsZSBjaGUgbm9uIHNpYSB1bidpbW1hZ2luZS5cIjtcclxuICBASW5wdXQoXCJ3cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZVwiKSB3cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZTogc3RyaW5nID1cclxuICAgIFwiTm9uIMOoIHBvc3NpYmlsZSBjYXJpY2FyZSBpbCBmaWxlIHNlbGV6aW9uYXRvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSB2aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkaSB1biBmaWxlIHZpZGVvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSBhdWRpb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkaSB1biBmaWxlIGF1ZGlvLlwiO1xyXG4gIEBJbnB1dChcImZsaXBIb3JpbnpvbnRhbExhYmVsXCIpIGZsaXBIb3JpbnpvbnRhbExhYmVsOiBzdHJpbmcgPSBcIkNhcG92b2xnaSBvcml6em9udGFsbWVudGVcIjtcclxuICBASW5wdXQoXCJmbGlwVmVydGljYWxMYWJlbFwiKSBmbGlwVmVydGljYWxMYWJlbDogc3RyaW5nID0gXCJDYXBvdm9sZ2kgdmVydGljYWxtZW50ZVwiO1xyXG4gIEBJbnB1dChcInJvdGF0ZVJpZ2h0TGFiZWxcIikgcm90YXRlUmlnaHRMYWJlbDogc3RyaW5nID0gXCJSdW90YSBhIGRlc3RyYVwiO1xyXG4gIEBJbnB1dChcInJvdGF0ZUxlZnRMYWJlbFwiKSByb3RhdGVMZWZ0TGFiZWw6IHN0cmluZyA9IFwiUnVvdGEgYSBzaW5pc3RyYVwiO1xyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvLyNyZWdpb24gQE91dHB1dCBkZWwgY29tcG9uZW50ZVxyXG5cclxuICAvKipcclxuICAgKiBSZXN0aXR1aXNjZSBsYSBsaXN0YSBhZ2dpb3JuYXRhIGRlZ2xpIGFsbGVnYXRpLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBsb2NhbEVkaXRlZEF0dGFjaG1lbnRzOiBFdmVudEVtaXR0ZXI8QXJyYXk8SUF0dGFjaG1lbnREVE8+PiA9IG5ldyBFdmVudEVtaXR0ZXI8QXJyYXk8SUF0dGFjaG1lbnREVE8+PigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gc2NhdGVuYXRvIGFsbGEgcHJlc3Npb25lIGRlbCBwdWxzYW50ZSBFU0NJIGRlbGxhIG1vZGFsZSBkaSBjYXJpY2FtZW50byBmaWxlLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBhYm9ydEFkZEF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGwnSUF0dGFjaG1lbnREVE8gc2VsZXppb25hdG8gcGVyIGlsIGRvd25sb2FkIG5lbCBjYXNvIEZpbGVEYXRhQmFzZTY0LCBGaWxlQ29udGVudFR5cGUgbyBGaWxlTmFtZSBub24gZm9zc2VybyBzcGVjaWZpY2F0aS5cclxuICAgKi9cclxuICBAT3V0cHV0KFwiZG93bmxvYWRBdHRhY2htZW50XCIpIGRvd25sb2FkQXR0YWNobWVudDogRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPiA9IG5ldyBFdmVudEVtaXR0ZXI8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGwnZWxlbWVudG8gZWxpbWluYXRvIHByaW1hIGNoZSBxdWVzdG8gdmVuZ2EgZWZmZXR0aXZhbWVudGUgcmlzbW9zc28gZGFsbGEgbGlzdGEuXHJcbiAgICovXHJcbiAgQE91dHB1dChcIm9uRGVsZXRlQXR0YWNobWVudFwiKSBvbkRlbGV0ZUF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4gPSBuZXcgRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIFByb3ByaWV0w6AgcGVyIGdlc3Rpb25lIGNhcmljYW1lbnRvIG51b3ZvIGFsbGVnYXRvXHJcbiAgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8gPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICBuZXdNdWx0aXBsZUF0dGFjaG1lbnRzOiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBbXTtcclxuICBhdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlO1xyXG4gIC8vIHVwbG9hZFR5cGVFbnVtID0gVXBsb2FkVHlwZUVudW07XHJcbiAgbmV3QXR0YWNobWVudEZvcm06IEZvcm1Hcm91cDtcclxuICBzZWxlY3RlZEZpbGU6IEZpbGUgPSBudWxsO1xyXG4gIHNlbGVjdGVkRmlsZXM6IEFycmF5PEZpbGU+ID0gbnVsbDtcclxuICBzaG93Q3JvcEltYWdlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0FkZEF0dGFjaG1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nQWRkQXR0YWNobWVudDogVGVtcGxhdGVSZWY8YW55PjtcclxuICBkaWFsb2dSZWZBZGRBdHRhY2htZW50OiBNYXREaWFsb2dSZWY8VGVtcGxhdGVSZWY8YW55Pj47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0FkZE11bHRpcGxlQXR0YWNobWVudFwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dBZGRNdWx0aXBsZUF0dGFjaG1lbnQ6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgZGlhbG9nUmVmQ3JvcEltYWdlOiBNYXREaWFsb2dSZWY8VGVtcGxhdGVSZWY8YW55Pj47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0Nyb3BJbWFnZVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dDcm9wSW1hZ2U6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8vI3JlZ2lvbiBQcm9wcmlldMOgIHBlciBnZXN0aW9uZSByaWRpbWVuc2lvbmFtZW50byBmaWxlIGRpIHRpcG8gaW1hZ2VcclxuICBpbWFnZUNoYW5nZWRFdmVudDogYW55ID0gXCJcIjtcclxuICBjcm9wcGVkSW1hZ2U6IGFueSA9IFwiXCI7XHJcbiAgdHJhbnNmb3JtOiBJbWFnZVRyYW5zZm9ybSA9IHt9O1xyXG4gIGNhbnZhc1JvdGF0aW9uID0gMDtcclxuICBAVmlld0NoaWxkKEltYWdlQ3JvcHBlckNvbXBvbmVudCkgaW1hZ2VDcm9wcGVyOiBJbWFnZUNyb3BwZXJDb21wb25lbnQ7XHJcbiAgQFZpZXdDaGlsZChcImltYWdlSW5wdXRcIikgaW1hZ2VJbnB1dDogYW55O1xyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICBBdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlO1xyXG4gIHNlbGVjdGVkQXR0YWNobWVudDogSUF0dGFjaG1lbnREVE87XHJcblxyXG4gIG9yaWdpbmFsV2lkdGg6IG51bWJlcjtcclxuICBvcmlnaW5hbEhlaWdodDogbnVtYmVyO1xyXG4gIGN1c3RvbVdpZHRoOiBudW1iZXI7XHJcbiAgY3VzdG9tSGVpZ2h0OiBudW1iZXI7XHJcblxyXG4gIEBWaWV3Q2hpbGQoXCJhdHRhY2htZW50VGFibGVcIiwgeyBzdGF0aWM6IGZhbHNlIH0pIGF0dGFjaG1lbnRUYWJsZTogRXFwVGFibGVDb21wb25lbnQ7XHJcbiAgQFZpZXdDaGlsZChcImlubGluZVByZXZpZXdUZW1wbGF0ZVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBpbmxpbmVQcmV2aWV3VGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ1ByZXZpZXdcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nUHJldmlldzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgaW1hZ2VGaWxlOiBGaWxlO1xyXG5cclxuICBhZGRpbmdMaW5rTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgZGlhbG9nOiBNYXREaWFsb2csXHJcbiAgICBwcml2YXRlIGZvcm1CdWlsZGVyOiBGb3JtQnVpbGRlcixcclxuICAgIHByaXZhdGUgc2FuaXRpemVyOiBEb21TYW5pdGl6ZXIsXHJcbiAgICBwcml2YXRlIGh0dHA6IEh0dHBDbGllbnQsXHJcbiAgICBwcml2YXRlIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgIHByaXZhdGUgZXFwQXR0YWNobWVudFNlcnZpY2U6IEVxcEF0dGFjaG1lbnRTZXJ2aWNlXHJcbiAgKSB7fVxyXG5cclxuICBhc3luYyBuZ09uSW5pdCgpIHtcclxuICAgIC8vU2Ugw6ggc3RhdGEgcmljaGllc3RhIGxhIGdlc3Rpb25lIGRlbGxlIHNvbGUgaW1tYWdpbmkgYWxsb3JhIGltcG9zdGEgaWwgZmlsdHJvIHBlciBsZSBlc3RlbnNpb25pIHBvc3NpYmlsaSBkYSBjYXJpY2FyZVxyXG4gICAgaWYgKCF0aGlzLmFjY2VwdGVkRmlsZVR5cGVzKVxyXG4gICAgICBpZiAodGhpcy5hbGxvd09ubHlJbWFnZXMgPT0gdHJ1ZSkgdGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9IFwiaW1hZ2UvKlwiO1xyXG4gICAgICBlbHNlIHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMgPSBcIipcIjtcclxuXHJcbiAgICAvLyBTZSBub24gc29ubyBzdGF0aSBzcGVjaWZpY2F0aSBpIHRpcGkgZGEgZ2VzdGlyZSBtYSDDqCBzdGF0byBwYXNzYXRvIG51bGwgbyB1biBhcnJheSB2dW90byBpbXBvc3RvIGkgdGlwaSBkaSBkZWZhdWx0LlxyXG4gICAgaWYgKCF0aGlzLmFsbG93ZWRUeXBlcyB8fCB0aGlzLmFsbG93ZWRUeXBlcy5sZW5ndGggPT0gMClcclxuICAgICAgdGhpcy5hbGxvd2VkVHlwZXMgPSBbQXR0YWNobWVudFR5cGUuRklMRSwgQXR0YWNobWVudFR5cGUuTElOSywgQXR0YWNobWVudFR5cGUuRFJPUEJPWF07XHJcbiAgICBlbHNlIGlmIChcclxuICAgICAgdGhpcy5hbGxvd2VkVHlwZXMuZmluZCgodCkgPT4gdCAhPSBBdHRhY2htZW50VHlwZS5GSUxFICYmIHQgIT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiB0ICE9IEF0dGFjaG1lbnRUeXBlLkRST1BCT1gpXHJcbiAgICApIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuV2FybmluZyhcclxuICAgICAgICAnQWxtZW5vIHVubyBkZWdsaSBBdHRhY2htZW50VHlwZSBzZWxlemlvbmF0aSBuZWwgcGFyYW1ldHJvIFwiYWxsb3dlZFR5cGVzXCIgbm9uIGVzaXN0ZS4nXHJcbiAgICAgICk7XHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzID0gW0F0dGFjaG1lbnRUeXBlLkZJTEUsIEF0dGFjaG1lbnRUeXBlLkxJTkssIEF0dGFjaG1lbnRUeXBlLkRST1BCT1hdO1xyXG4gICAgfVxyXG5cclxuICAgIC8vU2Ugw6ggc3RhdGEgcmljaGllc3RhIGxhIGdlc3Rpb25lIG11bHRpcGxhIGRlZ2xpIGFsbGVnYXRpIGFsbG9yYSBjb25maWd1cmEgbCdlcXAtdGFibGVcclxuICAgIGlmICh0aGlzLm11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlICYmICghdGhpcy5hdHRhY2htZW50c0NvbHVtbnMgfHwgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMubGVuZ3RoID09IDApKSB7XHJcbiAgICAgIHRoaXMuY29uZmlndXJlQ29sdW1ucygpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKSB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICB0aGlzLmNoZWNrQXR0YWNobWVudEltYWdlKCk7XHJcblxyXG4gICAgaWYgKHRoaXMuYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpKSB7XHJcbiAgICAgIHRoaXMuZXFwQXR0YWNobWVudFNlcnZpY2UubG9hZERyb3Bib3hTY3JpcHQoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHB1YmxpYyByZWxvYWREYXRhKCkge1xyXG4gICAgaWYgKHRoaXMuYXR0YWNobWVudFRhYmxlKSB0aGlzLmF0dGFjaG1lbnRUYWJsZS5yZWxvYWREYXRhdGFibGUoKTtcclxuICB9XHJcblxyXG4gIGNoZWNrQXR0YWNobWVudEltYWdlKCkge1xyXG4gICAgdGhpcy5hdHRhY2htZW50c0xpc3QuZm9yRWFjaCgoYSkgPT4ge1xyXG4gICAgICBhLklzSW1hZ2UgPSBBdHRhY2htZW50SGVscGVyU2VydmljZS5jaGVja0ltYWdlRnJvbU1pbWVUeXBlKGEuRmlsZUNvbnRlbnRUeXBlKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIEdlc3Rpb25lIGVsZW5jbyBhbGxlZ2F0aVxyXG5cclxuICAvKipcclxuICAgKiBDb25maWd1cmEgbGUgY29sb25uZSBwZXIgbCdlcXAtdGFibGUgbmVsIGNhc28gaW4gY3VpIGlsIHBhcmFtZXRybyBcIm11bHRpcGxlQXR0YWNobWVudHNcIiDDqCBUUlVFLlxyXG4gICAqL1xyXG4gIGNvbmZpZ3VyZUNvbHVtbnMoKSB7XHJcbiAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucyA9IFtdO1xyXG4gICAgaWYgKHRoaXMuZGlzYWJsZUFjdGlvbiAhPSB0cnVlKSB7XHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLnB1c2goe1xyXG4gICAgICAgIGtleTogXCJhY3Rpb25cIixcclxuICAgICAgICBkaXNwbGF5OiBcIlwiLFxyXG4gICAgICAgIHR5cGU6IFR5cGVDb2x1bW4uTWVudUFjdGlvbixcclxuICAgICAgICBidXR0b25NZW51SWNvbjogXCJtb3JlX3ZlcnRcIixcclxuICAgICAgICBzdHlsZXM6IHsgZmxleDogXCIwIDAgNiVcIiB9LFxyXG4gICAgICAgIGFjdGlvbnM6IFtcclxuICAgICAgICAgIHsgbmFtZTogdGhpcy5kZWxldGVMYWJlbCwgaWNvbjogXCJkZWxldGVcIiwgZm46IChlbGVtZW50LCBpbmRleCwgY29sKSA9PiB0aGlzLmRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudCkgfVxyXG4gICAgICAgIF1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGRvd25sb2FkQ29sdW1uID0ge1xyXG4gICAgICBrZXk6IFwiYXR0YWNobWVudFwiLFxyXG4gICAgICBkaXNwbGF5OiBcIlwiLFxyXG4gICAgICB0eXBlOiBUeXBlQ29sdW1uLlNpbXBsZUFjdGlvbixcclxuICAgICAgc3R5bGVzOiB7IGZsZXg6IFwiMCAwIDYlXCIgfSxcclxuICAgICAgYWN0aW9uczogW1xyXG4gICAgICAgIHtcclxuICAgICAgICAgIG5hbWU6IFwiXCIsXHJcbiAgICAgICAgICBmb250YXdlc29tZTogdHJ1ZSxcclxuICAgICAgICAgIGljb246IChlbGVtZW50KSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnNob3dJbmxpbmVQcmV2aWV3XHJcbiAgICAgICAgICAgICAgPyBlbGVtZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEVcclxuICAgICAgICAgICAgICAgID8gXCJmYXMgZmEtY2xvdWQtZG93bmxvYWQtYWx0XCJcclxuICAgICAgICAgICAgICAgIDogXCJmYXMgZmEtZXh0ZXJuYWwtbGluay1hbHRcIlxyXG4gICAgICAgICAgICAgIDogdGhpcy5nZXRBdHRhY2htZW50SWNvbihlbGVtZW50KTtcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgICBmbjogKGVsZW1lbnQsIGNvbCwgZWxlbWVudEluZGV4KSA9PiB0aGlzLnZpZXdBdHRhY2htZW50KGVsZW1lbnQpLFxyXG4gICAgICAgICAgdG9vbHRpcDoge1xyXG4gICAgICAgICAgICB0b29sdGlwVGV4dDogKGVsZW1lbnQpID0+IHtcclxuICAgICAgICAgICAgICByZXR1cm4gZWxlbWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFID8gdGhpcy5kb3dubG9hZExhYmVsIDogdGhpcy5vcGVuTGlua0xhYmVsO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICB0b29sdGlwUG9zaXRpb246IHRoaXMuZG93bmxvYWRUb29sdGlwUG9zaXRpb25cclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIF1cclxuICAgIH07XHJcblxyXG4gICAgbGV0IGlubGluZVByZXZpZXdDb2x1bW4gPSB7XHJcbiAgICAgIGtleTogXCJJbmxpbmVQcmV2aWV3XCIsXHJcbiAgICAgIGRpc3BsYXk6IHRoaXMucHJldmlld0xhYmVsLFxyXG4gICAgICB0eXBlOiBUeXBlQ29sdW1uLkV4dGVybmFsVGVtcGxhdGUsXHJcbiAgICAgIGV4dGVybmFsVGVtcGxhdGU6IHRoaXMuaW5saW5lUHJldmlld1RlbXBsYXRlLFxyXG4gICAgICBzdHlsZXM6IHsgZmxleDogXCIwIDAgMTAlXCIgfVxyXG4gICAgfTtcclxuXHJcbiAgICBsZXQgZmlsZU5hbWVDb2x1bW4gPSB7IGtleTogXCJGaWxlTmFtZVwiLCBkaXNwbGF5OiB0aGlzLmZpbGVOYW1lTGFiZWwgfTtcclxuXHJcbiAgICBpZiAodGhpcy5zaG93SW5saW5lUHJldmlldykge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGlubGluZVByZXZpZXdDb2x1bW4pO1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGZpbGVOYW1lQ29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChkb3dubG9hZENvbHVtbik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGRvd25sb2FkQ29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChmaWxlTmFtZUNvbHVtbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbGltaW5hIHVuIGFsbGVnYXRvIGVsaW1pbmFuZG8gYW5jaGUgaWwgZmlsZSBwcmVzZW50ZSBuZWxsbyBzdG9yYWdlIGRpIGFyY2hpdmlhemlvbmUgdXRpbGl6emF0byAoQVdTIG8gY2FydGVsbGEgcHJvZ2V0dG8pXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgSUF0dGFjaG1lbnREVE8gZGEgY2FuY2VsbGFyZVxyXG4gICAqL1xyXG4gIGRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkNvbmZpcm0oXHJcbiAgICAgIHRoaXMuZGVsZXRlRGlhbG9nTWVzc2FnZSxcclxuICAgICAgKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVtb3ZlQXR0YWNobWVudEZyb21MaXN0KHRoaXMuYXR0YWNobWVudHNMaXN0LmluZGV4T2YoZWxlbWVudCkpO1xyXG4gICAgICB9LFxyXG4gICAgICB0cnVlLFxyXG4gICAgICB0aGlzLmRlbGV0ZURpYWxvZ1RpdGxlXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmltdW92ZSBsJ2FsbGVnYXRvIHNlbGV6aW9uYXRvIGRhbGxhIGxpc3RhIFwiYXR0YWNobWVudHNMaXN0XCIgZSBpbnZvY2EgbCdldmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsYSBsaXN0YSBhZ2dpb3JuYXRhLlxyXG4gICAqIEBwYXJhbSBhdHRhY2htZW50SW5kZXggSW5kaWNlIGRlbGwnYXR0YWNobWVudCBkYSByaW11b3ZlcmVcclxuICAgKi9cclxuICByZW1vdmVBdHRhY2htZW50RnJvbUxpc3QoYXR0YWNobWVudEluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMub25EZWxldGVBdHRhY2htZW50LmVtaXQodGhpcy5hdHRhY2htZW50c0xpc3RbYXR0YWNobWVudEluZGV4XSk7XHJcblxyXG4gICAgdGhpcy5hdHRhY2htZW50c0xpc3Quc3BsaWNlKGF0dGFjaG1lbnRJbmRleCwgMSk7XHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50VGFibGUpIHRoaXMuYXR0YWNobWVudFRhYmxlLnJlbG9hZERhdGF0YWJsZSgpO1xyXG4gICAgdGhpcy5sb2NhbEVkaXRlZEF0dGFjaG1lbnRzLmVtaXQodGhpcy5hdHRhY2htZW50c0xpc3QpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogU2NhcmljYSBsJ2FsbGVnYXRvIG8gYXByZSBpbCBsaW5rXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgQWxsZWdhdG8gZGEgbW9zdHJhcmVcclxuICAgKi9cclxuICB2aWV3QXR0YWNobWVudChhdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgaWYgKGF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICB3aW5kb3cub3BlbihhdHRhY2htZW50LkZpbGVQYXRoLCBcIl9ibGFua1wiKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChhdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ICYmIGF0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlICYmIGF0dGFjaG1lbnQuRmlsZU5hbWUpIHtcclxuICAgICAgbGV0IHNvdXJjZSA9IGBkYXRhOiR7YXR0YWNobWVudC5GaWxlQ29udGVudFR5cGV9O2Jhc2U2NCwke2F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjR9YDtcclxuICAgICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xyXG4gICAgICBsaW5rLmhyZWYgPSBzb3VyY2U7XHJcbiAgICAgIGxpbmsuZG93bmxvYWQgPSBgJHthdHRhY2htZW50LkZpbGVOYW1lfWA7XHJcbiAgICAgIGxpbmsuY2xpY2soKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuZG93bmxvYWRBdHRhY2htZW50LmVtaXQoYXR0YWNobWVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSaWRlZmluaXNjZSBsJ2ljb25hIGRhIG1vc3RyYXJlIG5lbGxhIGNvbG9ubmEgZGVsbCdlcXAtdGFibGUgcGVyIG9nbmkgZmlsZS5cclxuICAgKiBMJ2ljb25hIHZhcmlhIGluIGJhc2UgYWxsJ2VzdGVuc2lvbmUgZGVsIGZpbGVcclxuICAgKiBAcGFyYW0gYXR0YWNobWVudFxyXG4gICAqL1xyXG4gIGdldEF0dGFjaG1lbnRJY29uKGF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPKSB7XHJcbiAgICBpZiAoYXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKSByZXR1cm4gXCJmYXMgZmEtbGlua1wiO1xyXG4gICAgZWxzZSByZXR1cm4gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuZ2V0SWNvbkZyb21GaWxlRXh0ZW5zaW9uZShhdHRhY2htZW50LkZpbGVFeHRlbnNpb24pO1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGNhc28gZGkgYWxsZWdhdG8gc2luZ29sbywgc2NlZ2xpZSBxdWFsZSBtZXRvZG8gcmljaGlhbWFyZSBpbiBiYXNlIGFsIHRpcG8gZGkgYWxsZWdhdG9cclxuICAgKi9cclxuICBhZGRGaWxlKGF0dGFjaG1lbnRUeXBlOiBBdHRhY2htZW50VHlwZSwgaW1hZ2VJbnB1dCA9IG51bGwpIHtcclxuICAgIGlmIChhdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKSB7XHJcbiAgICAgIHRoaXMuc3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpO1xyXG4gICAgfSBlbHNlIGlmIChhdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFKSB7XHJcbiAgICAgIGltYWdlSW5wdXQuY2xpY2soKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuY2hvb3NlRHJvcGJveEZpbGUoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNyZWF0ZUF0dGFjaG1lbnRGb3JtKCkge1xyXG4gICAgLy9DcmVhIGxhIGZvcm0gcGVyIGxhIHZhbGlkYXppb25lIGRlaSBjYW1waVxyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybSA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoe1xyXG4gICAgICB0eXBlOiBbdGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcclxuICAgICAgbmFtZTogW3RoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZV0sXHJcbiAgICAgIHBhdGg6IFt0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZVBhdGhdLFxyXG4gICAgICBjdXN0b21IZWlnaHQ6IFt0aGlzLmN1c3RvbUhlaWdodF0sXHJcbiAgICAgIGN1c3RvbVdpZHRoOiBbdGhpcy5jdXN0b21XaWR0aF1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgY2xvc2UoZW1pdENsb3NlRXZlbnQgPSB0cnVlKSB7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQgPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50Rm9ybSkgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5yZXNldCgpO1xyXG5cclxuICAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgICB0aGlzLnJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKTtcclxuXHJcbiAgICBpZiAoZW1pdENsb3NlRXZlbnQgPT0gdHJ1ZSAmJiB0aGlzLmFib3J0QWRkQXR0YWNobWVudCkgdGhpcy5hYm9ydEFkZEF0dGFjaG1lbnQuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW4gYmFzZSBhbCB0aXBvIGRpIGFsbGVnYXRvIGNvbnRyb2xsYSBzZSBkaXNhYmlsaXRhcmUgbyBtZW5vIGlsIHB1bHNhbnRlIHBlciBzYWx2YXJlLlxyXG4gICAqIEZ1bnppb25lIHVzYXRhIG5lbCBbZGlzYWJsZV0gZGVsIHB1bHNhbnRlIFwiU2FsdmFcIiBkZWwgZGlhbG9nIHBlciBsJ2FnZ2l1bnRhIGRpIHVuIGFsbGVnYXRvLlxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgZGlzYWJsZVNhdmUoKSB7XHJcbiAgICBpZiAodGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSB7XHJcbiAgICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSkge1xyXG4gICAgICAgIHJldHVybiAhdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHJldHVybiAhdGhpcy5uZXdBdHRhY2htZW50LkZpbGVQYXRoO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gKFxyXG4gICAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5maWx0ZXIoXHJcbiAgICAgICAgICAocCkgPT5cclxuICAgICAgICAgICAgKHAuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSAmJiAhcC5GaWxlRGF0YUJhc2U2NCkgfHxcclxuICAgICAgICAgICAgKHAuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiAhcC5GaWxlUGF0aClcclxuICAgICAgICApLmxlbmd0aCA+IDBcclxuICAgICAgKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbmZpcm1BZGRBdHRhY2htZW50KCkge1xyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IHRoaXMuaW1hZ2VDcm9wcGVyLmNyb3AoKS5iYXNlNjQuc3BsaXQoXCI7YmFzZTY0LFwiKVsxXTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSB7XHJcbiAgICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiAhdGhpcy5uZXdBdHRhY2htZW50LkZpbGVOYW1lKVxyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZSA9IHRoaXMubmV3QXR0YWNobWVudC5GaWxlUGF0aDtcclxuXHJcbiAgICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKSB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNMaXN0LnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmICh0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPT0gbnVsbCB8fCB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMubGVuZ3RoID09IDApIHJldHVybjtcclxuXHJcbiAgICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKSB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNMaXN0ID0gdGhpcy5hdHRhY2htZW50c0xpc3QuY29uY2F0KHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuYXR0YWNobWVudFRhYmxlKSB0aGlzLmF0dGFjaG1lbnRUYWJsZS5yZWxvYWREYXRhdGFibGUoKTtcclxuXHJcbiAgICB0aGlzLmxvY2FsRWRpdGVkQXR0YWNobWVudHMuZW1pdCh0aGlzLmF0dGFjaG1lbnRzTGlzdCk7XHJcblxyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgICAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXByZSBpbCBkaWFsb2cgcGVyIGwnYW50ZXByaW1hIGRlbGwnYWxsZWdhdG8gc2VsZXppb25hdG8uXHJcbiAgICogQHBhcmFtIHJvd1xyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgYXN5bmMgb3BlblByZXZpZXdEaWFsb2cocm93OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQgPSBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KHJvdykpO1xyXG5cclxuICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFKSB7XHJcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUuc3RhcnRzV2l0aChcInZpZGVvXCIpKSB7XHJcbiAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuV2FybmluZyh0aGlzLnZpZGVvUHJldmlld0Vycm9yTWVzc2FnZSk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZS5zdGFydHNXaXRoKFwiYXVkaW9cIikpIHtcclxuICAgICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5XYXJuaW5nKHRoaXMuYXVkaW9QcmV2aWV3RXJyb3JNZXNzYWdlKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5nZXRBdHRhY2htZW50RW5kcG9pbnQgJiYgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuSXNJbWFnZSAmJiAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQpIHtcclxuICAgICAgYXdhaXQgdGhpcy5nZXRBdHRhY2htZW50QnlJRCgpXHJcbiAgICAgICAgLnRoZW4oKHJlcykgPT4ge1xyXG4gICAgICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSByZXMuRmlsZURhdGFCYXNlNjQ7XHJcbiAgICAgICAgfSlcclxuICAgICAgICAuY2F0Y2goKGVycikgPT4ge1xyXG4gICAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IoZXJyKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFJlc291cmNlVXJsKFxyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVQYXRoXHJcbiAgICAgICk7XHJcbiAgICB9IGVsc2UgaWYgKFxyXG4gICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlICYmXHJcbiAgICAgICF0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJlxyXG4gICAgICAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVRodW1ibmFpbEJhc2U2NFxyXG4gICAgKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkluZm8oXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGVsbCdhbGxlZ2F0bywgZmlsZSBtYW5jYW50ZS5cIik7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2UpIHtcclxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVQYXRoICYmIHRoaXMucHJvZHVjdGlvbkJhc2VVcmwpIHtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFJlc291cmNlVXJsKFxyXG4gICAgICAgICAgXCJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9ndmlldz91cmw9XCIgK1xyXG4gICAgICAgICAgICB0aGlzLnByb2R1Y3Rpb25CYXNlVXJsICtcclxuICAgICAgICAgICAgXCIvXCIgK1xyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aCArXHJcbiAgICAgICAgICAgIFwiJmVtYmVkZGVkPXRydWVcIlxyXG4gICAgICAgICk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuSW5mbyhcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkZWwgZG9jdW1lbnRvIVwiKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmRpYWxvZy5vcGVuKHRoaXMuZGlhbG9nUHJldmlldywge1xyXG4gICAgICBkaXNhYmxlQ2xvc2U6IHRydWUsXHJcbiAgICAgIGhhc0JhY2tkcm9wOiB0cnVlXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGdldEF0dGFjaG1lbnRCeUlEKCkge1xyXG4gICAgcmV0dXJuIHRoaXMuaHR0cC5wb3N0PElBdHRhY2htZW50RFRPPih0aGlzLmdldEF0dGFjaG1lbnRFbmRwb2ludCwgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQpLnRvUHJvbWlzZSgpO1xyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIEdlc3Rpb25lIGNhcmljYW1lbnRvIGZpbGVcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnRvIHNjYXRlbmF0byBhbGxhIHNlbGV6aW9uZSBkZWwgZmlsZSAobyBkZWkgZmlsZSkuXHJcbiAgICogU2UgaWwgY2FyaWNhbWVudG8gw6ggU0lOR09MTyBvIHNlIGNvbXVucXVlIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIHNvbG8gZmlsZSBhbGxvcmEgc2kgb2NjdXBhIGRpIGNvbnRyb2xsYXJlIHNlIHNpIHRyYXR0YSBkaSB1biBpbW1hZ2luZSBpbiBtb2RvIGRhXHJcbiAgICogbW9zdHJhcmUgbGUgZnVuemlvbmFsaXTDoCBkZWwgY3JvcHBpZSAocGVyIHJpdGFnbGlhcmUgbCdpbW1hZ2luZSkgb3BwdXJlIG5vLlxyXG4gICAqIFNlIGlsIGZpbGUgY2FyaWNhdG8gbm9uIMOoIHVuIGltbWFnaW5lIGFsbG9yYSBnZW5lcmEgZGlyZXR0YW1lbnRlIGlsIGJhc2U2NCBlIGxvIGFzc29jaWEgYWxsJ2FsbGVnYXRvIGRhIHNhbHZhcmUuXHJcbiAgICogU2UgaW52ZWNlIGlsIGNhcmljYW1lbnRvIGRlaSBmaWxlIMOoIE1VTFRJUExPIGUgc29ubyBwcmVzZW50aSBwacO5IGZpbGUgYWxsb3JhIGVzZWd1ZSBsZSBzdGVzc2Ugb3BlcmF6aW9uaSBpZ25vcmFuZG8gcGVyw7IgaWwgY29udHJsbG9cclxuICAgKiBpbW1hZ2luZSBwZXIgaWwgY3JvcHBpZSAoaW4gY2FzbyBkaSBjYXJpY2FtZW50byBtdWx0aXBsbyBsZSBmdW56aW9uYWxpdMOgIGRlbCBjcm9wcGllIHNvbm8gZGlzYWJpbGl0YXRlKS5cclxuICAgKi9cclxuICBhc3luYyBvbkZpbGVBZGRlZChldmVudCwgaXNGaWxlRHJvcHBlZDogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgIGxldCBmaWxlc09uSW5wdXQgPSBpc0ZpbGVEcm9wcGVkID8gZXZlbnQgOiBldmVudC50YXJnZXQuZmlsZXM7XHJcblxyXG4gICAgLy9TZSDDqCBzdGF0byByaWNoaWVzdG8gaWwgY2FyaWNhbWVudG8gU0lOR09MTyBvcHB1cmUgc2UgaWwgY2FyaWNhbWVudG8gw6ggTVVMVElQTE8gbWEgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gc29sbyBmaWxlXHJcbiAgICAvL2FsbG9yYSB2ZXJpZmljYSBzZSBpbCBmaWxlIMOoIHVuIGltbWFnaW5lIChwZXIgbW9zdHJhcmUgaWwgQ1JPUFBJRSlcclxuICAgIGlmIChbLi4uZmlsZXNPbklucHV0XS5sZW5ndGggPT0gMSB8fCB0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBmaWxlc09uSW5wdXRbMF07XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IGZpbGVzT25JbnB1dDtcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZSkgcmV0dXJuO1xyXG5cclxuICAgICAgLy9NZW1vcml6emEgaSBkYXRpIHBlciBsJ2FsbGVnYXRvXHJcbiAgICAgIHRoaXMubmV3QXR0YWNobWVudCA9IGF3YWl0IHRoaXMuY3JlYXRlQXR0YWNobWVudEZyb21VcGxvYWRlZEZpbGUodGhpcy5zZWxlY3RlZEZpbGUsIGZhbHNlKTtcclxuICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG4gICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMucHVzaCh0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG5cclxuICAgICAgLy9TZSDDqCBzdGF0YSByaWNoaWVzdGEgbGEgZ2VzdGlvbmUgZGVsbGUgc29sZSBpbW1hZ2luaSBtYSBwZXIgZXJyb3JlIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIGZpbGUgY2hlIG5vbiDDqCB1biBpbW1hZ2luZVxyXG4gICAgICBsZXQgY2hlY2tPbmx5SW1hZ2UgPSB0aGlzLmNoZWNrQWxsb3dPbmx5SW1hZ2VGaWxlKHRoaXMubmV3QXR0YWNobWVudCk7XHJcbiAgICAgIGlmIChjaGVja09ubHlJbWFnZSA9PSBmYWxzZSkgcmV0dXJuO1xyXG5cclxuICAgICAgdGhpcy5jcmVhdGVBdHRhY2htZW50Rm9ybSgpO1xyXG5cclxuICAgICAgLy9WZXJpZmljYSBzZSBpbCBmaWxlIGNhcmljYXRvIMOoIHVuJ2ltbWFnaW5lIG9wcHVyZSBuby4gU2Ugw6ggdW4gaW1tYWdpbmUsIHByaW1hIGRpIGNhcmljYXJsYSBtb3N0cmEgaWwgY3JvcHBpZSBwZXIgaWwgcmVzaXplLlxyXG4gICAgICAvL1NlIG5vbiDDqCB1biBpbW1hZ2luZSBhbGxvcmEgZ2VuZXJhIGlsIEJhc2U2NFxyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LklzSW1hZ2UgPT0gdHJ1ZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0SW1hZ2VEaW1lbnNpb25zKGZpbGVzT25JbnB1dFswXSk7XHJcblxyXG4gICAgICAgIC8vTW9zdHJhIGlsIGNyb3BwaWUgZSBkaXNhYmlsaXRhIGxhIGZvcm0gZmluY2jDqCBub24gdGVybWluYSBsYSBtb2RpZmljYSBkZWxsJ2ltbWFnaW5lXHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5kaXNhYmxlKCk7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5jb250cm9sc1tcImN1c3RvbVdpZHRoXCJdLmVuYWJsZSgpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0uY29udHJvbHNbXCJjdXN0b21IZWlnaHRcIl0uZW5hYmxlKCk7XHJcbiAgICAgICAgdGhpcy5zaG93Q3JvcEltYWdlID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmltYWdlRmlsZSA9IGV2ZW50O1xyXG5cclxuICAgICAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZSA9IHRoaXMuZGlhbG9nLm9wZW4odGhpcy5kaWFsb2dDcm9wSW1hZ2UsIHtcclxuICAgICAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcclxuICAgICAgICAgIGhhc0JhY2tkcm9wOiB0cnVlLFxyXG4gICAgICAgICAgd2lkdGg6IFwiNjAlXCIsXHJcbiAgICAgICAgICBtYXhIZWlnaHQ6IFwiODAlXCJcclxuICAgICAgICB9KTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgICAgICBsZXQgYmFzZTY0UmVzdWx0ID0gYXdhaXQgdGhpcy5nZXRCYXNlNjRGcm9tRmlsZSh0aGlzLnNlbGVjdGVkRmlsZSk7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gYmFzZTY0UmVzdWx0LkJhc2U2NEZpbGU7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IGJhc2U2NFJlc3VsdC5Db250ZW50VHlwZTtcclxuICAgICAgICB0aGlzLmNvbmZpcm1BZGRBdHRhY2htZW50KCk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IGZpbGVzT25JbnB1dDtcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZXMgfHwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aCA9PSAwKSByZXR1cm47XHJcblxyXG4gICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgbGV0IG5ld0F0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0gYXdhaXQgdGhpcy5jcmVhdGVBdHRhY2htZW50RnJvbVVwbG9hZGVkRmlsZShcclxuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlc1tpXSxcclxuICAgICAgICAgIHRydWUsXHJcbiAgICAgICAgICB0cnVlXHJcbiAgICAgICAgKTtcclxuICAgICAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIG1hIHBlciBlcnJvcmUgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gZmlsZSBjaGUgbm9uIMOoIHVuIGltbWFnaW5lXHJcbiAgICAgICAgbGV0IGNoZWNrT25seUltYWdlID0gdGhpcy5jaGVja0FsbG93T25seUltYWdlRmlsZShuZXdBdHRhY2htZW50KTtcclxuICAgICAgICBpZiAoY2hlY2tPbmx5SW1hZ2UgPT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2gobmV3QXR0YWNobWVudCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5jb25maXJtQWRkQXR0YWNobWVudCgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vUmVzZXR0byBpbCB2YWxvcmUgZGVsIGZpbGUgaW5wdXQgaW4gbW9kbyBkYSBzY2F0ZW5hcmUgaWwgY2hhbmdlIGFuY2hlIHNlIHNpIGRvdmVzc2UgY2FyaWNhcmUgbG8gc3Rlc3NvIGZpbGVcclxuICAgIGlmICghaXNGaWxlRHJvcHBlZCkgZXZlbnQudGFyZ2V0LnZhbHVlID0gXCJcIjtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgcGFydGlyZSBkYWwgRklMRSByaWNldnV0byBpbiBpbnB1dCByaWNvc3RydWlzY2UgbCdvZ2dldHRvIElBdHRhY2htZW50RFRPIGUgbG8gcmVzdGl0dWlzY2UuXHJcbiAgICogU2UgaWwgcGFyYW1ldHJvIGdldEJhc2U2NCB2aWVuZSBwYXNzYXRvIGEgVFJVRSBhbGxvcmEsIHNlbXByZSBhIHBhcnRpcmUgZGFsIGZpbGUsZ2VuZXJhIGlsIGJhc2U2NCBlXHJcbiAgICogcmljYXZhIGlsIENvbnRlbnRUeXBlIGRhIGFzc29jaWFyZSBhbGwnb2dnZXR0byBJQXR0YWNobWVudERUTyBkYSByZXN0aXR1aXJlXHJcbiAgICogQHBhcmFtIGN1cnJlbnRGaWxlIE9nZ2V0dG8gRklMRSBkYSBwcm9jZXNzYXJlXHJcbiAgICogQHBhcmFtIGdldEJhc2U2NCBTZSBUUlVFIGFsbG9yYSBjYWxjb2xhIGJhc2U2NCBlIENvbnRlbnRUeXBlIGRlbCBmaWxlIHBhc3NhdG8gaW4gaW5wdXRcclxuICAgKiBAcmV0dXJucyBSZXN0aXR1aXNjZSB1biBvZ2dldHRvIGRpIHRpcG8gSUF0dGFjaG1lbnREVE9cclxuICAgKi9cclxuICBwcml2YXRlIGFzeW5jIGNyZWF0ZUF0dGFjaG1lbnRGcm9tVXBsb2FkZWRGaWxlKFxyXG4gICAgY3VycmVudEZpbGU6IEZpbGUsXHJcbiAgICBnZXRCYXNlNjQ6IGJvb2xlYW4gPSB0cnVlLFxyXG4gICAgY3JvcEZpbGU6IGJvb2xlYW4gPSBmYWxzZVxyXG4gICk6IFByb21pc2U8SUF0dGFjaG1lbnREVE8+IHtcclxuICAgIGxldCBuZXdBdHRhY2htZW50OiBJQXR0YWNobWVudERUTyA9IHt9IGFzIElBdHRhY2htZW50RFRPO1xyXG4gICAgLy9NZW1vcml6emEgaSBkYXRpIHBlciBsJ2FsbGVnYXRvXHJcbiAgICBuZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID0gQXR0YWNobWVudFR5cGUuRklMRTtcclxuICAgIG5ld0F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlID0gY3VycmVudEZpbGUudHlwZTtcclxuICAgIG5ld0F0dGFjaG1lbnQuRmlsZU5hbWUgPSBjdXJyZW50RmlsZS5uYW1lO1xyXG4gICAgbmV3QXR0YWNobWVudC5GaWxlRXh0ZW5zaW9uID0gY3VycmVudEZpbGUubmFtZS5zdWJzdHIoY3VycmVudEZpbGUubmFtZS5sYXN0SW5kZXhPZihcIi5cIikgKyAxKTtcclxuICAgIG5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9IEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmNoZWNrSW1hZ2VGcm9tTWltZVR5cGUoY3VycmVudEZpbGUudHlwZSk7XHJcblxyXG4gICAgaWYgKGdldEJhc2U2NCA9PSB0cnVlKSB7XHJcbiAgICAgIGxldCBiYXNlNjRSZXN1bHQgPSBhd2FpdCB0aGlzLmdldEJhc2U2NEZyb21GaWxlKGN1cnJlbnRGaWxlKTtcclxuICAgICAgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IGJhc2U2NFJlc3VsdC5CYXNlNjRGaWxlO1xyXG4gICAgICBuZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IGJhc2U2NFJlc3VsdC5Db250ZW50VHlwZTtcclxuXHJcbiAgICAgIGlmIChuZXdBdHRhY2htZW50LklzSW1hZ2UgJiYgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiBjcm9wRmlsZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0Q3JvcHBlZEFuZFVwbG9hZChgZGF0YToke2Jhc2U2NFJlc3VsdC5Db250ZW50VHlwZX07YmFzZTY0LCR7YmFzZTY0UmVzdWx0LkJhc2U2NEZpbGV9YCwgbmV3QXR0YWNobWVudCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbmV3QXR0YWNobWVudDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgcGFydGlyZSBkYWwgZmlsZSBwYXNzYXRvIGluIGlucHV0IHJlc3RpdHVpc2NlIHVuIG9nZ2V0dG9cclxuICAgKiBjb250ZW5lbnRlIGlsIGJhc2U2NCBkZWwgZmlsZSBlIGlsIHN1byBjb250ZW50VHlwZVxyXG4gICAqIEBwYXJhbSBjdXJyZW50RmlsZSBPZ2dldHRvIEZpbGUgZGEgY3VpIGVzdHJhcG9sYXJlIGJhc2U2NCBlIGNvbnRlbnRUeXBlXHJcbiAgICogQHJldHVybnMgUmVzdGl0dWlzY2UgdW4gb2dnZXR0byBhdmVudGUgbGUgcHJvcHJpZXTDoCBCYXNlNjRGaWxlIGUgQ29udGVudFR5cGVcclxuICAgKi9cclxuICBwcml2YXRlIGFzeW5jIGdldEJhc2U2NEZyb21GaWxlKGN1cnJlbnRGaWxlOiBGaWxlKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGxldCBiYXNlNjRGaWxlID0gYXdhaXQgdG9CYXNlNjQoY3VycmVudEZpbGUpO1xyXG4gICAgbGV0IGNvbnRlbnRUeXBlOiBzdHJpbmcgPSBudWxsO1xyXG4gICAgaWYgKGJhc2U2NEZpbGUpIHtcclxuICAgICAgLy8gTG9yaXMgMjAvMDEvMjAyMjogUFJPQkxFTUEgLSBRdWFuZG8gZXNlZ3VvIGwndXBsb2FkIGRpIHVuIGZpbGUgLnNxbCBub24gdmllbmUgc2FsdmF0by9zY2FyaWNhdG8gY29ycmV0dGFtZW50ZS5cclxuICAgICAgLy8gICAgICAgICAgICAgICAgICAgUXVlc3RvIHN1Y2NlZGUgcGVyY2jDqCBub24gdmllbmUgcG9wb2xhdG8gaWwgRmlsZUNvbnRlbnRUeXBlLiBQZXIgcmlzb2x2ZXJlIGlsIHByb2JsZW1hXHJcbiAgICAgIC8vICAgICAgICAgICAgICAgICAgIGZhY2NpbyB1biBjb250cm9sbG8gZSBzZSBub24gZXNpc3RlIGlsIEZpbGVDb250ZW50VHlwZSBhbGxvcmEgbG8gcmVjdXBlcm8gZGFsIGJhc2U2NCBvdHRlbnV0by5cclxuICAgICAgY29udGVudFR5cGUgPSBiYXNlNjRGaWxlLnNwbGl0KFwiLFwiKVswXS5zcGxpdChcIjpcIilbMV0uc3BsaXQoXCI7XCIpWzBdO1xyXG4gICAgICAvLyBVbiBhbHRybyBtZXRvZG8gcGVyIGxlZ2dlcmUgaWwgY2NvbnRlbnQgdHlwZSBkZWwgZmlsZSDDqCB0cmFtaXRlIHVuYSByZWd1bGFyIGV4cHJlc3Npb246XHJcbiAgICAgIGJhc2U2NEZpbGUgPSBiYXNlNjRGaWxlLnNwbGl0KFwiLFwiKVsxXTtcclxuICAgIH1cclxuXHJcbiAgICBsZXQgcmVzdWx0ID0ge1xyXG4gICAgICBCYXNlNjRGaWxlOiBiYXNlNjRGaWxlLFxyXG4gICAgICBDb250ZW50VHlwZTogY29udGVudFR5cGVcclxuICAgIH07XHJcblxyXG4gICAgcmV0dXJuIHJlc3VsdDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENvbnRyb2xsYSBzZSBpbCBmaWxlIGNoZSBzaSBzdGEgY2FyaWNhbmRvIMOoIHN1cHBvcnRhdG8gZGFsIHNpc3RlbWEuXHJcbiAgICogQHJldHVybnNcclxuICAgKi9cclxuICBwcml2YXRlIGNoZWNrQWNjZXB0ZWRGaWxlcygpOiBib29sZWFuIHtcclxuICAgIGlmIChcclxuICAgICAgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSAmJiB0aGlzLnNlbGVjdGVkRmlsZS50eXBlLnN0YXJ0c1dpdGgoXCJ2aWRlb1wiKSkgfHxcclxuICAgICAgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgPT0gdHJ1ZSAmJiBbLi4udGhpcy5zZWxlY3RlZEZpbGVzXS5maWx0ZXIoKHApID0+IHAudHlwZS5zdGFydHNXaXRoKFwidmlkZW9cIikpLmxlbmd0aCA+IDApXHJcbiAgICApXHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICBpZiAodGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9PSBcIipcIikgcmV0dXJuIHRydWU7XHJcblxyXG4gICAgLy9WZXJpZmljYSBjaGUgaSB0aXBpIGRlbCBmaWxlIChvIGRlaSBmaWxlKSBjYXJpY2F0aSBzaWFubyBjb2VyZW50aSBjb24gcXVlbGxpIGFjY2V0dGF0aSBkYWxsYSBkaXJldHRpdmFcclxuICAgIGxldCBhY2NlcHRlZDogYm9vbGVhbiA9IHRydWU7XHJcbiAgICBpZiAodGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSBhY2NlcHRlZCA9IHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMuaW5jbHVkZXModGhpcy5zZWxlY3RlZEZpbGUudHlwZSk7XHJcbiAgICBlbHNlIHtcclxuICAgICAgbGV0IHVwbG9hZGVkRmlsZVR5cGVzOiBzdHJpbmdbXSA9IFsuLi50aGlzLnNlbGVjdGVkRmlsZXNdLm1hcCgocCkgPT4gcC50eXBlKTtcclxuICAgICAgdXBsb2FkZWRGaWxlVHlwZXMuZm9yRWFjaCgodHlwZSkgPT4ge1xyXG4gICAgICAgIGlmICghdGhpcy5hY2NlcHRlZEZpbGVUeXBlcy5pbmNsdWRlcyh0eXBlKSkgYWNjZXB0ZWQgPSBmYWxzZTtcclxuICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy9RdWVzdG8gY29udHJvbGxvIHBlcm1ldHRlIGRpIGdlc3RpcmUgbGUgY2FzaXN0aWNoZSBwZXIgY3VpIHZlbmdvbm8gaW5kaWNhdGkgY29tZSB0aXBpIHZhbGlkaSwgYWQgZXNlbXBpbywgJ2ltYWdlLyonXHJcbiAgICBpZiAoIWFjY2VwdGVkICYmIHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBmb3IgKGxldCB0IG9mIHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMuc3BsaXQoXCIsXCIpLmZpbHRlcigodCkgPT4gdC5pbmNsdWRlcyhcIipcIikpKSB7XHJcbiAgICAgICAgYWNjZXB0ZWQgPSB0aGlzLnNlbGVjdGVkRmlsZS50eXBlLnN0YXJ0c1dpdGgodC5zcGxpdChcIipcIilbMF0pO1xyXG4gICAgICAgIGlmIChhY2NlcHRlZCkgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBhY2NlcHRlZDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIGVxcC1hdHRhY2htZW50cyDDqCBzdGF0YSBjb25maWd1cmF0YSBwZXIgaWwgY2FyaWNhbWVudG8gZGVsbGUgc29sZSBpbW1hZ2luaSBhbGxvcmEgdmVyaWZpY2EgY2hlIGlsIGZpbGUgcGFzc2F0byBpblxyXG4gICAqIGlucHV0IHNpYSBlZmZldHRpdmFtZW50ZSB1biBpbW1hZ2luZSBvIG5vLlxyXG4gICAqIFNlIGlsIGNvbnRyb2xsbyB2YSBhIGJ1b24gZmluZSByZXN0aXR1aXNjZSBUUlVFIGFsdHJpbWVudGkgbW9zdHJhIHVuIG1lc3NhZ2dpbyBkJ2Vycm9yZSBlIHJlc3RpdHVpc2NlIEZBTFNFXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjaGVja0FsbG93T25seUltYWdlRmlsZShuZXdBdHRhY2htZW50KTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5hbGxvd09ubHlJbWFnZXMgPT0gdHJ1ZSAmJiBuZXdBdHRhY2htZW50LklzSW1hZ2UgIT0gdHJ1ZSkge1xyXG4gICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5FcnJvcih0aGlzLm5vSW1hZ2VTZWxlY3RlZEVycm9yTWVzc2FnZSk7XHJcbiAgICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuY2hlY2tBY2NlcHRlZEZpbGVzKCkpIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IodGhpcy53cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZSk7XHJcbiAgICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdHJ1ZTtcclxuICB9XHJcblxyXG4gIC8vI3JlZ2lvbiBHZXN0aW9uZSBjcm9wIGZpbGVcclxuXHJcbiAgZ2V0SW1hZ2VEaW1lbnNpb25zKGltZzogYW55KSB7XHJcbiAgICBjb25zdCByZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG4gICAgcmVhZGVyLm9ubG9hZCA9IChlOiBhbnkpID0+IHtcclxuICAgICAgY29uc3QgaW1hZ2UgPSBuZXcgSW1hZ2UoKTtcclxuICAgICAgaW1hZ2Uuc3JjID0gZS50YXJnZXQucmVzdWx0O1xyXG4gICAgICBpbWFnZS5vbmxvYWQgPSAocnMpID0+IHtcclxuICAgICAgICB0aGlzLm9yaWdpbmFsSGVpZ2h0ID0gcnMuY3VycmVudFRhcmdldFtcImhlaWdodFwiXTtcclxuICAgICAgICB0aGlzLm9yaWdpbmFsV2lkdGggPSBycy5jdXJyZW50VGFyZ2V0W1wid2lkdGhcIl07XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm9yaWdpbmFsV2lkdGggPiAxMjgwKSB7XHJcbiAgICAgICAgICB0aGlzLmN1c3RvbVdpZHRoID0gMTI4MDtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gTWF0aC5yb3VuZCgoMTI4MCAqIHRoaXMub3JpZ2luYWxIZWlnaHQpIC8gdGhpcy5vcmlnaW5hbFdpZHRoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21IZWlnaHQgPSBycy5jdXJyZW50VGFyZ2V0W1wiaGVpZ2h0XCJdO1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21XaWR0aCA9IHJzLmN1cnJlbnRUYXJnZXRbXCJ3aWR0aFwiXTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcbiAgICB9O1xyXG4gICAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoaW1nKTtcclxuICB9XHJcblxyXG4gIHJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKSB7XHJcbiAgICB0aGlzLmN1c3RvbVdpZHRoID0gdGhpcy5vcmlnaW5hbFdpZHRoO1xyXG4gICAgdGhpcy5jdXN0b21IZWlnaHQgPSB0aGlzLm9yaWdpbmFsSGVpZ2h0O1xyXG4gICAgdGhpcy5jYW52YXNSb3RhdGlvbiA9IDA7XHJcbiAgICB0aGlzLnRyYW5zZm9ybSA9IHt9O1xyXG4gIH1cclxuXHJcbiAgb25EaW1lbnNpb25zQ2hhbmdlKGRpbWVuc2lvbjogc3RyaW5nKSB7XHJcbiAgICBpZiAoZGltZW5zaW9uID09IFwiSFwiKSB7XHJcbiAgICAgIHRoaXMuY3VzdG9tV2lkdGggPSBNYXRoLnJvdW5kKCh0aGlzLmN1c3RvbUhlaWdodCAqIHRoaXMub3JpZ2luYWxXaWR0aCkgLyB0aGlzLm9yaWdpbmFsSGVpZ2h0KTtcclxuICAgIH0gZWxzZSBpZiAoZGltZW5zaW9uID09IFwiV1wiKSB7XHJcbiAgICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gTWF0aC5yb3VuZCgodGhpcy5jdXN0b21XaWR0aCAqIHRoaXMub3JpZ2luYWxIZWlnaHQpIC8gdGhpcy5vcmlnaW5hbFdpZHRoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGltYWdlQ3JvcHBlZChldmVudDogSW1hZ2VDcm9wcGVkRXZlbnQpIHtcclxuICAgIHRoaXMuY3JvcHBlZEltYWdlID0gZXZlbnQuYmFzZTY0O1xyXG4gICAgdGhpcy5nZXRDcm9wcGVkQW5kVXBsb2FkKHRoaXMuY3JvcHBlZEltYWdlLCB0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q3JvcHBlZEFuZFVwbG9hZChmaWxlLCBuZXdBdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgdmFyIHNlbGYgPSB0aGlzO1xyXG5cclxuICAgIHZhciBmaWxlOiBhbnkgPSBiYXNlNjRUb0ZpbGUoZmlsZSk7XHJcblxyXG4gICAgY29uc3Qgb3B0aW9ucyA9IHRoaXMuY29tcHJlc3Npb25PcHRpb25zO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcHJpbWUgbCdpbW1hZ2luZSBwYXNzYW5kbyBjb21lIHBhcmFtZXRyaSBsZSBvcHRpb25zIGNyZWF0ZSBuZWxsJ29nZ2V0dG8gc29wcmEsIGUgaWwgZmlsZSBkYWwgcmVhZGVyIHByaW5jaXBhbGVcclxuICAgICAqL1xyXG4gICAgaW1hZ2VDb21wcmVzc2lvbihmaWxlLCBvcHRpb25zKS50aGVuKChmaWxlQ29tcHJlc3NlZCkgPT4ge1xyXG4gICAgICBsZXQgZmlsZVJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcblxyXG4gICAgICAvL0ZhY2NpbyBsYSBwdXNoIGRpIG9nbmkgZmlsZSBhbGwnaW50ZXJubyBkZWxsJ2FycmF5IGRpIGZpbGUgZGVsbCdpdGVtIGRhIG1hbmRhcmUgYWwgc2VydmVyXHJcbiAgICAgIGZpbGVSZWFkZXIub25sb2FkID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIGxldCByZXN1bHRSZWFkZXIgPSA8c3RyaW5nPmZpbGVSZWFkZXIucmVzdWx0O1xyXG4gICAgICAgIHZhciBtYXJrZXIgPSBcIjtiYXNlNjQsXCI7XHJcbiAgICAgICAgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IHJlc3VsdFJlYWRlci5zdWJzdHJpbmcocmVzdWx0UmVhZGVyLmluZGV4T2YobWFya2VyKSArIG1hcmtlci5sZW5ndGgpO1xyXG4gICAgICAgIHNlbGYuc2hvd0Nyb3BJbWFnZSA9IGZhbHNlO1xyXG4gICAgICAgIGlmIChzZWxmLm5ld0F0dGFjaG1lbnRGb3JtKSB7XHJcbiAgICAgICAgICBzZWxmLm5ld0F0dGFjaG1lbnRGb3JtLmVuYWJsZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfTtcclxuXHJcbiAgICAgIGZpbGVSZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlQ29tcHJlc3NlZCk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIGNvbmZpcm1Dcm9wKCkge1xyXG4gIC8vICAgdGhpcy5pbWFnZUNyb3BwZXIuY3JvcCgpO1xyXG4gIC8vICAgdGhpcy5kaWFsb2dSZWZDcm9wSW1hZ2UuY2xvc2UoKTtcclxuICAvLyAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gIC8vIH1cclxuXHJcbiAgcm90YXRlTGVmdCgpIHtcclxuICAgIHRoaXMuY2FudmFzUm90YXRpb24tLTtcclxuICAgIHRoaXMuZmxpcEFmdGVyUm90YXRlKCk7XHJcbiAgfVxyXG5cclxuICByb3RhdGVSaWdodCgpIHtcclxuICAgIHRoaXMuY2FudmFzUm90YXRpb24rKztcclxuICAgIHRoaXMuZmxpcEFmdGVyUm90YXRlKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZsaXBBZnRlclJvdGF0ZSgpIHtcclxuICAgIGNvbnN0IGZsaXBwZWRIID0gdGhpcy50cmFuc2Zvcm0uZmxpcEg7XHJcbiAgICBjb25zdCBmbGlwcGVkViA9IHRoaXMudHJhbnNmb3JtLmZsaXBWO1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7XHJcbiAgICAgIC4uLnRoaXMudHJhbnNmb3JtLFxyXG4gICAgICBmbGlwSDogZmxpcHBlZFYsXHJcbiAgICAgIGZsaXBWOiBmbGlwcGVkSFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIGZsaXBIb3Jpem9udGFsKCkge1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7XHJcbiAgICAgIC4uLnRoaXMudHJhbnNmb3JtLFxyXG4gICAgICBmbGlwSDogIXRoaXMudHJhbnNmb3JtLmZsaXBIXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgZmxpcFZlcnRpY2FsKCkge1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7XHJcbiAgICAgIC4uLnRoaXMudHJhbnNmb3JtLFxyXG4gICAgICBmbGlwVjogIXRoaXMudHJhbnNmb3JtLmZsaXBWXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8qKlxyXG4gICAqIEFubnVsbGEgbGEgc2VsZXppb25lIGRlbCBmaWxlLCBzdnVvdGFuZG8gbCdpbnB1dCBlIHJlc2V0dGFuZG8gdHV0dGUgbGUgcHJvcHJpZXTDoCBkZWxsJ0lBdHRhY2htZW50RFRPXHJcbiAgICovXHJcbiAgYWJvcnRGaWxlKCkge1xyXG4gICAgaWYgKHRoaXMuaW1hZ2VJbnB1dCkgdGhpcy5pbWFnZUlucHV0Lm5hdGl2ZUVsZW1lbnQudmFsdWUgPSBcIlwiO1xyXG5cclxuICAgIHRoaXMuc2VsZWN0ZWRGaWxlID0gbnVsbDtcclxuICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IG51bGw7XHJcbiAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuXHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gbnVsbDtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZSA9IG51bGw7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZUV4dGVuc2lvbiA9IG51bGw7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlID0gbnVsbDtcclxuXHJcbiAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgdGhpcy5jdXN0b21IZWlnaHQgPSBudWxsO1xyXG4gICAgdGhpcy5jdXN0b21XaWR0aCA9IG51bGw7XHJcbiAgICB0aGlzLm9yaWdpbmFsSGVpZ2h0ID0gbnVsbDtcclxuICAgIHRoaXMub3JpZ2luYWxXaWR0aCA9IG51bGw7XHJcblxyXG4gICAgdGhpcy5kaWFsb2dSZWZDcm9wSW1hZ2UuY2xvc2UoKTtcclxuICAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8vIFZpZW5lIGNyZWF0byB1bidhcnJheSBvYnNlcnZhYmxlcyBwZXIgbWVtb3JpenphcmUgdHV0dGkgZ2xpIG9ic2VydmFibGUgY3JlYXRpIGRhbGxlIGNoaWFtYXRlIGEgZmlsZUVudHJ5LmZpbGUoKS5cclxuICAvLyBEb3BvIGNoZSB0dXR0aSBnbGkgb2JzZXJ2YWJsZXMgc29ubyBzdGF0aSBjb21wbGV0YXRpLCB2aWVuZSB1dGlsaXp6YXRvIGlsIG1ldG9kbyBzdWJzY3JpYmUoKSBwZXIgZXNlZ3VpcmUgbGEgZnVuemlvbmUgb25GaWxlQWRkZWQoKS5cclxuICBmaWxlRHJvcHBlZChmaWxlcykge1xyXG4gICAgbGV0IGZpbGVzRHJvcHBlZCA9IFtdO1xyXG5cclxuICAgIGNvbnN0IG9ic2VydmFibGVzOiBPYnNlcnZhYmxlPGFueT5bXSA9IFtdO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmaWxlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICBpZiAoZmlsZXNbaV0uZmlsZUVudHJ5LmlzRmlsZSkge1xyXG4gICAgICAgIGNvbnN0IGZpbGVFbnRyeSA9IGZpbGVzW2ldLmZpbGVFbnRyeSBhcyBGaWxlU3lzdGVtRmlsZUVudHJ5O1xyXG4gICAgICAgIGNvbnN0IG9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZSgob2JzZXJ2ZXIpID0+IHtcclxuICAgICAgICAgIGZpbGVFbnRyeS5maWxlKChmaWxlOiBGaWxlKSA9PiB7XHJcbiAgICAgICAgICAgIGZpbGVzRHJvcHBlZC5wdXNoKGZpbGUpO1xyXG5cclxuICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCgpO1xyXG4gICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgb2JzZXJ2YWJsZXMucHVzaChvYnNlcnZhYmxlKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb25zdCBmaWxlRW50cnkgPSBmaWxlc1tpXS5maWxlRW50cnkgYXMgRmlsZVN5c3RlbURpcmVjdG9yeUVudHJ5O1xyXG4gICAgICAgIGNvbnNvbGUubG9nKGZpbGVzW2ldLnJlbGF0aXZlUGF0aCwgZmlsZUVudHJ5KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZyb20ob2JzZXJ2YWJsZXMpXHJcbiAgICAgIC5waXBlKGNvbmNhdE1hcCgob2JzZXJ2YWJsZSkgPT4gb2JzZXJ2YWJsZSkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIGNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLm9uRmlsZUFkZGVkKGZpbGVzRHJvcHBlZCwgdHJ1ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIFNlIGlsIGNhcmljYW1lbnRvIGRlbCBmaWxlIGRyb3Bib3ggdmEgYSBidW9uIGZpbmUsIGxhIGZ1bnppb25lIGRpIGNhbGxiYWNrIHJlc3RpdHVpc2NlIHVuIGFycmF5IGRpIG9nZ2V0dGkuXHJcbiAgLy8gVmllbmUgcG9pIGZhdHRhIHVuYSBYTUxIdHRwUmVxdWVzdCBjb24gcmVzcG9uc2VUeXBlICdibG9iJyBwZXIgY29udmVydGlyZSBpbCBwcmltbyBlbGVtZW50byBkZWxsYSByZXNwb25zZSBpbiB1biBCbG9iLlxyXG4gIGNob29zZURyb3Bib3hGaWxlKCkge1xyXG4gICAgdmFyIG9wdGlvbnMgPSB7XHJcbiAgICAgIHN1Y2Nlc3M6IChmaWxlczogYW55W10pID0+IHtcclxuICAgICAgICBjb25zdCB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcclxuICAgICAgICB4aHIub3BlbihcIkdFVFwiLCBmaWxlc1swXS5saW5rKTtcclxuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihcIkF1dGhvcml6YXRpb25cIiwgYEJlYXJlciAke0F0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmRyb3Bib3hDcmVkZW50aWFscy5hY2Nlc3NUb2tlbn1gKTtcclxuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gXCJibG9iXCI7XHJcblxyXG4gICAgICAgIHhoci5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBibG9iID0geGhyLnJlc3BvbnNlO1xyXG4gICAgICAgICAgY29uc3QgZmlsZSA9IG5ldyBGaWxlKFtibG9iXSwgZmlsZXNbMF0ubmFtZSwgeyB0eXBlOiBibG9iLnR5cGUgfSk7XHJcbiAgICAgICAgICBsZXQgZmlsZXNBZGRlZCA9IFtmaWxlXTtcclxuICAgICAgICAgIHRoaXMub25GaWxlQWRkZWQoZmlsZXNBZGRlZCwgdHJ1ZSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgeGhyLnNlbmQoKTtcclxuICAgICAgfSxcclxuICAgICAgbGlua1R5cGU6IFwiZGlyZWN0XCIsXHJcbiAgICAgIG11bHRpc2VsZWN0OiBmYWxzZSxcclxuICAgICAgZXh0ZW5zaW9uczogW1wiLmpwZ1wiLCBcIi5wbmdcIiwgXCIucGRmXCIsIFwiLmRvY1wiLCBcIi5kb2N4XCIsIFwiLnR4dFwiXVxyXG4gICAgfTtcclxuICAgIERyb3Bib3guY2hvb3NlKG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLy8gV29ya2Fyb3VuZCBkcm9wem9uZTogZGlzYWJpbGl0byBpbCBjbGljayBkZWdsaSBlbGVtZW50aSBpbmNsdXNpIG5lbGxhIGRyb3B6b25lIHBlciBldml0YXJlIGRpIGNsaWNjYXJlIGR1ZSB2b2x0ZVxyXG4gIG9uU2VsZWN0RmlsZShldmVudCwgZmlsZUlucHV0KSB7XHJcbiAgICBpZiAoXHJcbiAgICAgIChldmVudC50YXJnZXQgYXMgSFRNTEJ1dHRvbkVsZW1lbnQpLnRhZ05hbWUgPT09IFwiQlVUVE9OXCIgfHxcclxuICAgICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MQnV0dG9uRWxlbWVudCkudGFnTmFtZSA9PT0gXCJJTlBVVFwiIHx8XHJcbiAgICAgIHRoaXMuYWRkaW5nTGlua01vZGUgPT0gdHJ1ZVxyXG4gICAgKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGZpbGVJbnB1dC5jbGljaygpO1xyXG4gIH1cclxuXHJcbiAgLy8gTWV0b2RvIHBlciB2aXN1YWxpenphcmUgbGEgZm9ybSBkaSBhZ2dpdW50YSBkaSB1biBsaW5rXHJcbiAgc3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpIHtcclxuICAgIHRoaXMuYWRkaW5nTGlua01vZGUgPSB0cnVlO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50ID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9IGZhbHNlO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID0gdGhpcy5hdHRhY2htZW50VHlwZS5MSU5LO1xyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuXHJcbiAgICB0aGlzLmNyZWF0ZUF0dGFjaG1lbnRGb3JtKCk7XHJcbiAgfVxyXG59XHJcbiIsIjwhLS0gU2UgcmljaGllc3RhIGxhIGdlc3Rpb25lIHNpbmdvbGEgbW9zdHJhIGlsIHB1bHNhbnRlIGRpIGNhcmljYW1lbnRvIGRpIHVuIHNpbmdvbG8gZmlsZSAtLT5cclxuPGRpdiAqbmdJZj1cIm11bHRpcGxlQXR0YWNobWVudCAhPSB0cnVlXCI+XHJcbiAgPGRpdiAqbmdJZj1cIiFzaW5nbGVBdHRhY2htZW50RHJhZ0FuZERyb3BcIj5cclxuICAgIDwhLS0gVGVtcGxhdGUgZGVsIGJ1dHRvbiBwZXIgbCdhZ2dpdW50YSBkaSB1biBhbGxlZ2F0byAtLT5cclxuICAgIDxkaXYgKm5nSWY9XCIhYWRkaW5nTGlua01vZGVcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImFkZEF0dGFjaG1lbnRCdXR0b25cIj48L25nLWNvbnRhaW5lcj5cclxuICAgIDwvZGl2PlxyXG4gICAgPCEtLSBUZW1wbGF0ZSBkZWxsYSBmb3JtIHBlciBsJ2FnZ2l1bnRhIGRpIHVuIGxpbmsgLS0+XHJcbiAgICA8ZGl2ICpuZ0lmPVwiYWRkaW5nTGlua01vZGVcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImFkZGluZ0xpbmtUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiAqbmdJZj1cInNpbmdsZUF0dGFjaG1lbnREcmFnQW5kRHJvcFwiPlxyXG4gICAgPGlucHV0XHJcbiAgICAgICNmaWxlSW5wdXRcclxuICAgICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgICAgaWQ9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgICBuYW1lPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgICAgdHlwZT1cImZpbGVcIlxyXG4gICAgICAoY2hhbmdlKT1cIm9uRmlsZUFkZGVkKCRldmVudClcIlxyXG4gICAgICBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCJcclxuICAgICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICAgIDxuZ3gtZmlsZS1kcm9wXHJcbiAgICAgIChvbkZpbGVEcm9wKT1cImZpbGVEcm9wcGVkKCRldmVudClcIlxyXG4gICAgICAoY2xpY2spPVwib25TZWxlY3RGaWxlKCRldmVudCwgZmlsZUlucHV0KVwiXHJcbiAgICAgICpuZ0lmPVwiXHJcbiAgICAgICAgYWxsb3dlZFR5cGVzICYmXHJcbiAgICAgICAgYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDEpICYmXHJcbiAgICAgICAgKCFhdHRhY2htZW50c0xpc3QgfHwgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8IChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgICAgXCI+XHJcbiAgICAgIDxuZy10ZW1wbGF0ZSBuZ3gtZmlsZS1kcm9wLWNvbnRlbnQtdG1wICpuZ0lmPVwiIWFkZGluZ0xpbmtNb2RlXCI+XHJcbiAgICAgICAgPGkgY2xhc3M9XCJmYS1zb2xpZCBmYS1jbG91ZC11cGxvYWQtYWx0IGZhLTN4IG10LTNcIj48L2k+XHJcbiAgICAgICAgVHJhc2NpbmEgaSBmaWxlIHF1aVxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJidG4tZ3JvdXAgbXQtMVwiIHJvbGU9XCJncm91cFwiPlxyXG4gICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IGJvcmRlci1lbmRcIiAoY2xpY2spPVwiZmlsZUlucHV0LmNsaWNrKClcIj5TY2VnbGkgdW4gZmlsZTwvYnV0dG9uPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiIHJvbGU9XCJncm91cFwiPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IGJvcmRlci1zdGFydCBkcm9wZG93bi10b2dnbGVcIlxyXG4gICAgICAgICAgICAgIFttYXRNZW51VHJpZ2dlckZvcl09XCJhdHRhY2htZW50VHlwZU1lbnVcIj48L2J1dHRvbj5cclxuICAgICAgICAgICAgPG1hdC1tZW51ICNhdHRhY2htZW50VHlwZU1lbnU9XCJtYXRNZW51XCI+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSlcIlxyXG4gICAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cImZpbGVJbnB1dC5jbGljaygpXCJcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWZpbGUtYnRuXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhcyBmYS1maWxlXCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkZpbGU8L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgICAgICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAgICAgICAgICAgKGNsaWNrKT1cInN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiXHJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1saW5rLWJ0blwiPlxyXG4gICAgICAgICAgICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgICAgICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5MaW5rPC9zcGFuPlxyXG4gICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpXCJcclxuICAgICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgICAgICAgICAgIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCJcclxuICAgICAgICAgICAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWxpbmstYnRuXCI+XHJcbiAgICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPlxyXG4gICAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkRyb3Bib3g8L3NwYW4+XHJcbiAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgIDwvbWF0LW1lbnU+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgICAgPG5nLXRlbXBsYXRlIG5neC1maWxlLWRyb3AtY29udGVudC10bXAgKm5nSWY9XCJhZGRpbmdMaW5rTW9kZVwiPlxyXG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJhZGRpbmdMaW5rVGVtcGxhdGVcIj48L25nLWNvbnRhaW5lcj5cclxuICAgICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgIDwvbmd4LWZpbGUtZHJvcD5cclxuICA8L2Rpdj5cclxuXHJcbiAgPGJ1dHRvblxyXG4gICAgY2xhc3M9XCJtYi0yIG1lLTIgZXFwLWF0dGFjaG1lbnRzLWRvd25sb2FkLWJ0blwiXHJcbiAgICAoY2xpY2spPVwidmlld0F0dGFjaG1lbnQoYXR0YWNobWVudHNMaXN0WzBdKVwiXHJcbiAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAqbmdJZj1cImF0dGFjaG1lbnRzTGlzdCAmJiBhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiBhdHRhY2htZW50c0xpc3RbMF1cIlxyXG4gICAgY29sb3I9XCJwcmltYXJ5XCI+XHJcbiAgICA8bWF0LWljb24gKm5nSWY9XCJhdHRhY2htZW50c0xpc3RbMF0uQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRVwiPmRvd25sb2FkPC9tYXQtaWNvbj5cclxuICAgIDxtYXQtaWNvbiAqbmdJZj1cImF0dGFjaG1lbnRzTGlzdFswXS5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5GSUxFXCI+b3Blbl9pbl9uZXc8L21hdC1pY29uPlxyXG4gICAge3sgYXR0YWNobWVudHNMaXN0WzBdLkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUgPyBkb3dubG9hZExhYmVsIDogb3BlbkxpbmtMYWJlbCB9fVxyXG4gIDwvYnV0dG9uPlxyXG4gIDxidXR0b25cclxuICAgIGNsYXNzPVwibWItMiBtZS0yIGVxcC1hdHRhY2htZW50cy1wcmV2aWV3LWJ0blwiXHJcbiAgICAoY2xpY2spPVwib3BlblByZXZpZXdEaWFsb2coYXR0YWNobWVudHNMaXN0WzBdKVwiXHJcbiAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgKm5nSWY9XCJcclxuICAgICAgc2hvd1ByZXZpZXcgJiZcclxuICAgICAgYXR0YWNobWVudHNMaXN0ICYmXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdFswXSAmJlxyXG4gICAgICAoIWF0dGFjaG1lbnRzTGlzdFswXS5GaWxlQ29udGVudFR5cGUgfHxcclxuICAgICAgICAoIWF0dGFjaG1lbnRzTGlzdFswXS5GaWxlQ29udGVudFR5cGUuc3RhcnRzV2l0aCgndmlkZW8nKSAmJlxyXG4gICAgICAgICAgIWF0dGFjaG1lbnRzTGlzdFswXS5GaWxlQ29udGVudFR5cGUuc3RhcnRzV2l0aCgnYXVkaW8nKSkpICYmXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdFswXS5Jc0ltYWdlID09IHRydWVcclxuICAgIFwiPlxyXG4gICAgPG1hdC1pY29uPnZpc2liaWxpdHk8L21hdC1pY29uPiB7eyBwcmV2aWV3TGFiZWwgfX1cclxuICA8L2J1dHRvbj5cclxuICA8YnV0dG9uXHJcbiAgICBjbGFzcz1cIm1iLTIgZXFwLWF0dGFjaG1lbnRzLWRlbGV0ZS1idG5cIlxyXG4gICAgKGNsaWNrKT1cImRlbGV0ZUF0dGFjaG1lbnQoYXR0YWNobWVudHNMaXN0WzBdKVwiXHJcbiAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAqbmdJZj1cImF0dGFjaG1lbnRzTGlzdCAmJiBhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiBhdHRhY2htZW50c0xpc3RbMF1cIlxyXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIj5cclxuICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPiB7eyBkZWxldGVMYWJlbCB9fVxyXG4gIDwvYnV0dG9uPlxyXG5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cInJvd1wiXHJcbiAgICBzdHlsZT1cIm1hcmdpbi10b3A6IDEwcHhcIlxyXG4gICAgKm5nSWY9XCJcclxuICAgICAgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiZcclxuICAgICAgYXR0YWNobWVudHNMaXN0WzBdICYmXHJcbiAgICAgIGF0dGFjaG1lbnRzTGlzdFswXS5GaWxlRGF0YUJhc2U2NCAmJlxyXG4gICAgICBhdHRhY2htZW50c0xpc3RbMF0uSXNJbWFnZSA9PSB0cnVlXHJcbiAgICBcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTJcIj5cclxuICAgICAgPGRpdiBjbGFzcz1cInNpbmdsZS1hdHRhY2htZW50LWlubGluZS1wcmV2aWV3LWNvbnRhaW5lclwiPlxyXG4gICAgICAgIDxpbWcgc3JjPVwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LHt7IGF0dGFjaG1lbnRzTGlzdFswXS5GaWxlRGF0YUJhc2U2NCB9fVwiIC8+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cInJvd1wiICpuZ0lmPVwiYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiYgYXR0YWNobWVudHNMaXN0WzBdICYmIGF0dGFjaG1lbnRzTGlzdFswXS5Jc0ltYWdlICE9IHRydWVcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtc20tMTJcIj5cclxuICAgICAgPG1hdC1mb3JtLWZpZWxkPlxyXG4gICAgICAgIDxtYXQtbGFiZWw+e3sgZmlsZU5hbWVMYWJlbCB9fTwvbWF0LWxhYmVsPlxyXG4gICAgICAgIDxpbnB1dCByZWFkb25seSBtYXRJbnB1dCBbKG5nTW9kZWwpXT1cImF0dGFjaG1lbnRzTGlzdFswXS5GaWxlTmFtZVwiIC8+XHJcbiAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48ZGl2ICpuZ0lmPVwibXVsdGlwbGVBdHRhY2htZW50ID09IHRydWVcIj5cclxuICA8aW5wdXRcclxuICAgICNmaWxlSW5wdXRcclxuICAgIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiXHJcbiAgICBpZD1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICBuYW1lPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgIHR5cGU9XCJmaWxlXCJcclxuICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiXHJcbiAgICBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCJcclxuICAgIFttdWx0aXBsZV09XCJsb2FkTXVsdGlwbGVGaWxlc1wiIC8+XHJcbiAgPG5neC1maWxlLWRyb3AgKG9uRmlsZURyb3ApPVwiZmlsZURyb3BwZWQoJGV2ZW50KVwiIChjbGljayk9XCJvblNlbGVjdEZpbGUoJGV2ZW50LCBmaWxlSW5wdXQpXCI+XHJcbiAgICA8bmctdGVtcGxhdGUgbmd4LWZpbGUtZHJvcC1jb250ZW50LXRtcCAqbmdJZj1cIiFhZGRpbmdMaW5rTW9kZVwiPlxyXG4gICAgICA8aSBjbGFzcz1cImZhIGZhLWNsb3VkLXVwbG9hZC1hbHQgZmEtM3ggbXQtM1wiPjwvaT5cclxuICAgICAgVHJhc2NpbmEgaSBmaWxlIHF1aVxyXG4gICAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwIG10LTFcIiByb2xlPVwiZ3JvdXBcIj5cclxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tbGlnaHQgYm9yZGVyLWVuZFwiIChjbGljayk9XCJmaWxlSW5wdXQuY2xpY2soKVwiPlNjZWdsaSB1biBmaWxlPC9idXR0b24+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImJ0bi1ncm91cFwiIHJvbGU9XCJncm91cFwiPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgY2xhc3M9XCJidG4gYnRuLWxpZ2h0IGJvcmRlci1zdGFydCBkcm9wZG93bi10b2dnbGVcIlxyXG4gICAgICAgICAgICBbbWF0TWVudVRyaWdnZXJGb3JdPVwiYXR0YWNobWVudFR5cGVNZW51XCI+PC9idXR0b24+XHJcbiAgICAgICAgICA8bWF0LW1lbnUgI2F0dGFjaG1lbnRUeXBlTWVudT1cIm1hdE1lbnVcIj5cclxuICAgICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDEpXCJcclxuICAgICAgICAgICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cImZpbGVJbnB1dC5jbGljaygpXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1maWxlLWJ0blwiPlxyXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWZpbGVcIj48L2k+XHJcbiAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkZpbGU8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMilcIlxyXG4gICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgICAgICAgICAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1saW5rLWJ0blwiPlxyXG4gICAgICAgICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxpbmtcIj48L2k+XHJcbiAgICAgICAgICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkxpbms8L3NwYW4+XHJcbiAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMylcIlxyXG4gICAgICAgICAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgICAgICAgICAoY2xpY2spPVwiY2hvb3NlRHJvcGJveEZpbGUoKVwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgICAgICAgICA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPlxyXG4gICAgICAgICAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5Ecm9wYm94PC9zcGFuPlxyXG4gICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgIDwvbWF0LW1lbnU+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9uZy10ZW1wbGF0ZT5cclxuICAgIDxuZy10ZW1wbGF0ZSBuZ3gtZmlsZS1kcm9wLWNvbnRlbnQtdG1wICpuZ0lmPVwiYWRkaW5nTGlua01vZGVcIj5cclxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImFkZGluZ0xpbmtUZW1wbGF0ZVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgPC9uZy10ZW1wbGF0ZT5cclxuICA8L25neC1maWxlLWRyb3A+XHJcbiAgPGRpdiBjbGFzcz1cIm10LTJcIj5cclxuICAgIDxlcXAtdGFibGVcclxuICAgICAgI2F0dGFjaG1lbnRUYWJsZVxyXG4gICAgICBbY3JlYXRlTWF0Q2FyZF09XCJmYWxzZVwiXHJcbiAgICAgICN0YWJsZVxyXG4gICAgICBbY29sdW1uc109XCJhdHRhY2htZW50c0NvbHVtbnNcIlxyXG4gICAgICBbaXNNdWx0aUxhbmd1YWdlXT1cImlzRXFwVGFibGVNdWx0aUxhbmd1YWdlXCJcclxuICAgICAgW2RhdGFdPVwiYXR0YWNobWVudHNMaXN0XCJcclxuICAgICAgW3BhZ2luYXRvclZpc2libGVdPVwidGFibGVQYWdpbmF0b3JWaXNpYmxlXCJcclxuICAgICAgW21hdFBhZ2luYXRvclNpemVdPVwidGFibGVQYWdpbmF0b3JTaXplXCJcclxuICAgICAgW2VtcHR5VGFibGVNZXNzYWdlXT1cImVtcHR5VGFibGVNZXNzYWdlXCJcclxuICAgICAgW3NlYXJjaFRleHRdPVwiZXFwVGFibGVTZWFyY2hUZXh0XCJcclxuICAgICAgW2lzVGFibGVTZWFyY2hlYWJsZV09XCJpc1RhYmxlU2VhcmNoZWFibGVcIj5cclxuICAgIDwvZXFwLXRhYmxlPlxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxuXHJcbjxuZy10ZW1wbGF0ZSAjZGlhbG9nQ3JvcEltYWdlPlxyXG4gIDwhLS0gUmljaGlhbWEgaWwgdGVtcGxhdGUgcGVyIGxlIGZ1bnppb25hbGl0w6AgZGVsIENST1BQSUUgLS0+XHJcbiAgPGRpdiBzdHlsZT1cIm92ZXJmbG93LXg6IGhpZGRlblwiPlxyXG4gICAgPG5nLWNvbnRhaW5lclxyXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldF09XCJjcm9wcGllVGVtcGxhdGVcIlxyXG4gICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyBmb3JtOiBuZXdBdHRhY2htZW50Rm9ybSB9XCJcclxuICAgICAgKm5nSWY9XCJzaG93Q3JvcEltYWdlID09IHRydWVcIj48L25nLWNvbnRhaW5lcj5cclxuICA8L2Rpdj5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjxuZy10ZW1wbGF0ZSAjaW5saW5lUHJldmlld1RlbXBsYXRlIGxldC1yb3c9XCJyb3dcIj5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImlubGluZS1wcmV2aWV3LWNvbnRhaW5lclwiXHJcbiAgICAqbmdJZj1cInJvdy5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5MSU5LICYmIHJvdy5Jc0ltYWdlXCJcclxuICAgIChjbGljayk9XCJvcGVuUHJldmlld0RpYWxvZyhyb3cpXCI+XHJcbiAgICA8aW1nIHNyYz1cImRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCx7eyByb3cuRmlsZVRodW1ibmFpbEJhc2U2NCA/IHJvdy5GaWxlVGh1bWJuYWlsQmFzZTY0IDogcm93LkZpbGVEYXRhQmFzZTY0IH19XCIgLz5cclxuICA8L2Rpdj5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImlubGluZS1wcmV2aWV3LWNvbnRhaW5lclwiXHJcbiAgICAqbmdJZj1cInJvdy5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5MSU5LICYmICFyb3cuSXNJbWFnZVwiXHJcbiAgICAoY2xpY2spPVwib3BlblByZXZpZXdEaWFsb2cocm93KVwiPlxyXG4gICAgPGkgW25nQ2xhc3NdPVwiZ2V0QXR0YWNobWVudEljb24ocm93KVwiPjwvaT5cclxuICA8L2Rpdj5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjxuZy10ZW1wbGF0ZSAjZGlhbG9nUHJldmlldz5cclxuICA8bWF0LWNhcmQgY2xhc3M9XCJleGFtcGxlLWNhcmRcIiAqbmdJZj1cInNlbGVjdGVkQXR0YWNobWVudFwiPlxyXG4gICAgPG1hdC1jYXJkLWNvbnRlbnQ+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJyb3dcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLXRpdGxlLXN0YW5kYXJkXCI+XHJcbiAgICAgICAgICB7eyBwcmV2aWV3TGFiZWwgfX0ge3sgc2VsZWN0ZWRBdHRhY2htZW50Py5BdHRhY2htZW50VHlwZSA9PSBhdHRhY2htZW50VHlwZS5GSUxFID8gXCJGaWxlXCIgOiBcIkxpbmtcIiB9fVxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgY2xhc3M9XCJidG4tY2xvc2UgY2xvc2VCdXR0b25cIlxyXG4gICAgICAgICAgICBtYXQtZGlhbG9nLWNsb3NlXHJcbiAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RlZEF0dGFjaG1lbnQgPSBudWxsXCI+PC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicm93IG10LTJcIj5cclxuICAgICAgICA8IS0tIEFOVEVQUklNQSBJTU1BR0lORSAtLT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIHRleHQtY2VudGVyIHByZXZpZXctY29udGFpbmVyXCIgKm5nSWY9XCJzZWxlY3RlZEF0dGFjaG1lbnQuSXNJbWFnZVwiPlxyXG4gICAgICAgICAgPGltZ1xyXG4gICAgICAgICAgICBjbGFzcz1cImltYWdlLXByZXZpZXdcIlxyXG4gICAgICAgICAgICBzcmM9XCJkYXRhOmltYWdlL3BuZztiYXNlNjQse3tcclxuICAgICAgICAgICAgICBzZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjRcclxuICAgICAgICAgICAgICAgID8gc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0XHJcbiAgICAgICAgICAgICAgICA6IHNlbGVjdGVkQXR0YWNobWVudC5GaWxlVGh1bWJuYWlsQmFzZTY0XHJcbiAgICAgICAgICAgIH19XCIgLz5cclxuICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgPCEtLSBBTlRFUFJJTUEgTElOSyAtLT5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwiY29sLTEyIHByZXZpZXctY29udGFpbmVyXCIgKm5nSWY9XCIhc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2VcIj5cclxuICAgICAgICAgIDxpZnJhbWVcclxuICAgICAgICAgICAgY2xhc3M9XCJsaW5rLXByZXZpZXdcIlxyXG4gICAgICAgICAgICBbc3JjXT1cInNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsXCJcclxuICAgICAgICAgICAgW3RpdGxlXT1cInNlbGVjdGVkQXR0YWNobWVudC5GaWxlTmFtZVwiPjwvaWZyYW1lPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiBjbGFzcz1cInJvdyBtdC0zXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC1zbS0xMiB0ZXh0LWNlbnRlclwiPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICBtYXQtbWluaS1mYWJcclxuICAgICAgICAgICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgICAgICAgICAgbWF0VG9vbHRpcD1cIkRvd25sb2FkXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cInZpZXdBdHRhY2htZW50KHNlbGVjdGVkQXR0YWNobWVudClcIlxyXG4gICAgICAgICAgICAqbmdJZj1cInNlbGVjdGVkQXR0YWNobWVudC5BdHRhY2htZW50VHlwZSAhPSBBdHRhY2htZW50VHlwZS5MSU5LXCI+XHJcbiAgICAgICAgICAgIDxtYXQtaWNvbj5kb3dubG9hZDwvbWF0LWljb24+XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgPC9kaXY+XHJcbiAgICA8L21hdC1jYXJkLWNvbnRlbnQ+XHJcbiAgPC9tYXQtY2FyZD5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcbjwhLS0gVEVNUExBVEUgUEVSIElMIFBVTFNBTlRFIERJIEFHR0lVTlRBIE5VT1ZPIEFMTEVHQVRPIC0tPlxyXG48bmctdGVtcGxhdGUgI2FkZEF0dGFjaG1lbnRCdXR0b24+XHJcbiAgPCEtLVxyXG4gICAgICAgIFB1bHNhbnRpIHBlciBsJ2FnZ2l1bnRhIGRpIHVuIGZpbGUgbyB1biBsaW5rLiBOZSB2aWVuZSB2aXN1YWxpenphdG8gdW5vIHNlOlxyXG4gICAgICAgIC0gZ2xpIGFsbG93ZWRUeXBlcyBzb25vIHN0YXRpIHNwZWNpZmljYXRpLCBuZWxsJ2FycmF5IG5lIMOoIHByZXNlbnRlIHVubyBzb2xvLCBxdWVsbG8gaW5zZXJpdG8gw6ggQXR0YWNobWVudFR5cGUuRklMRSAobyBBdHRhY2htZW50VHlwZS5MSU5LKVxyXG4gICAgICAgIGUgc29ubyBuZWxsYSBnZXN0aW9uZSBkaSBwacO5IGFsbGVnYXRpIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSlcclxuICAgICAgICBPUFBVUkVcclxuICAgICAgICAtIGdsaSBhbGxvd2VkVHlwZXMgc29ubyBzdGF0aSBzcGVjaWZpY2F0aSwgbmVsbCdhcnJheSBuZSDDqCBwcmVzZW50ZSB1bm8gc29sbywgcXVlbGxvIGluc2VyaXRvIMOoIEF0dGFjaG1lbnRUeXBlLkZJTEUgKG8gQXR0YWNobWVudFR5cGUuTElOSylcclxuICAgICAgICBlIHNvbm8gbmVsbGEgZ2VzdGlvbmUgZGkgdW4gc2luZ29sbyBhbGxlZ2F0byAobXVsdGlwbGVBdHRhY2htZW50ID09IHRydWUpIGUgbm9uIG5lIMOoIGFuY29yYSBzdGF0byBzZWxlemlvbmF0byB1bm8gKG92dmVybyBhdHRhY2htZW50c0xpc3Qgbm9uIGVzaXN0ZSBvIG5vbiBoYSBlbGVtZW50aSlcclxuICAgIC0tPlxyXG4gIDxpbnB1dFxyXG4gICAgI2ZpbGVJbnB1dFxyXG4gICAgc3R5bGU9XCJkaXNwbGF5OiBub25lXCJcclxuICAgIGlkPVwiZmlsZV9hdHRhY2htZW50XCJcclxuICAgIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgdHlwZT1cImZpbGVcIlxyXG4gICAgKGNoYW5nZSk9XCJvbkZpbGVBZGRlZCgkZXZlbnQpXCJcclxuICAgIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxyXG4gICAgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuICA8YnV0dG9uXHJcbiAgICBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSBtYi00IG1lLTUgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIlxyXG4gICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgIGNvbG9yPVwicHJpbWFyeVwiXHJcbiAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICpuZ0lmPVwiXHJcbiAgICAgIGFsbG93ZWRUeXBlcyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMubGVuZ3RoID09IDEgJiZcclxuICAgICAgKG11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlIHx8XHJcbiAgICAgICAgIWF0dGFjaG1lbnRzTGlzdCB8fFxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCB8fFxyXG4gICAgICAgIChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgIFwiXHJcbiAgICAoY2xpY2spPVwiYWRkRmlsZShhbGxvd2VkVHlwZXNbMF0sIGZpbGVJbnB1dClcIlxyXG4gICAgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIj5cclxuICAgIDwhLS0gUGVyIGwnYWdnaXVudGEgZGVpIGZpbGUgbW9zdHJvIHVuJ2ljb25hIGRpdmVyc2EgZGFsbCdhZ2dpdW50YSBkZWkgbGluayAtLT5cclxuICAgIDxtYXQtaWNvbiAqbmdJZj1cImFsbG93ZWRUeXBlc1swXSA9PSAxXCI+Y2xvdWRfdXBsb2FkPC9tYXQtaWNvbj5cclxuICAgIDxpIGNsYXNzPVwiZmFzIGZhLWxpbmtcIiAqbmdJZj1cImFsbG93ZWRUeXBlc1swXSA9PSAyXCI+PC9pPlxyXG4gICAgPGkgY2xhc3M9XCJmYS1icmFuZHMgZmEtZHJvcGJveFwiICpuZ0lmPVwiYWxsb3dlZFR5cGVzWzBdID09IDNcIj48L2k+XHJcbiAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+XHJcbiAgICAgIHt7XHJcbiAgICAgICAgYWxsb3dlZFR5cGVzWzBdID09IDFcclxuICAgICAgICAgID8gYWRkQnV0dG9uTGFiZWwgKyBcIiBmaWxlXCJcclxuICAgICAgICAgIDogYWxsb3dlZFR5cGVzWzBdID09IDJcclxuICAgICAgICAgID8gYWRkQnV0dG9uTGFiZWwgKyBcIiBsaW5rXCJcclxuICAgICAgICAgIDogdXBsb2FkV2l0aERyb3Bib3hMYWJlbFxyXG4gICAgICB9fTwvc3BhblxyXG4gICAgPlxyXG4gIDwvYnV0dG9uPlxyXG5cclxuICA8IS0tIFB1bHNhbnRlIHBlciBhcHJpcmUgaWwgbWVudSBwZXIgbGEgc2NlbHRhIGRlbCB0aXBvIGRpIEF0dGFjaG1lbnQgZGEgY3JlYXJlIC0tPlxyXG4gIDxidXR0b25cclxuICAgIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1iLTQgbWUtNSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiXHJcbiAgICBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgY29sb3I9XCJwcmltYXJ5XCJcclxuICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImF0dGFjaG1lbnRUeXBlTWVudVwiXHJcbiAgICBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiXHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICAhc2VwYXJhdGVkVXBsb2FkQnV0dG9ucyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMgJiZcclxuICAgICAgYWxsb3dlZFR5cGVzLmxlbmd0aCA+IDEgJiZcclxuICAgICAgKG11bHRpcGxlQXR0YWNobWVudCA9PSB0cnVlIHx8XHJcbiAgICAgICAgIWF0dGFjaG1lbnRzTGlzdCB8fFxyXG4gICAgICAgIGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCB8fFxyXG4gICAgICAgIChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSlcclxuICAgIFwiPlxyXG4gICAgPG1hdC1pY29uICpuZ0lmPVwibXVsdGlwbGVBdHRhY2htZW50ICE9IHRydWVcIj5jbG91ZF91cGxvYWQ8L21hdC1pY29uPlxyXG4gICAgPG1hdC1pY29uICpuZ0lmPVwibXVsdGlwbGVBdHRhY2htZW50ID09IHRydWVcIj5hZGQ8L21hdC1pY29uPlxyXG4gICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMHB4XCI+IHt7IGFkZEJ1dHRvbkxhYmVsIH19IDwvc3Bhbj5cclxuICA8L2J1dHRvbj5cclxuICA8bWF0LW1lbnUgI2F0dGFjaG1lbnRUeXBlTWVudT1cIm1hdE1lbnVcIj5cclxuICAgIDxpbnB1dFxyXG4gICAgICAjaW1hZ2VJbnB1dFxyXG4gICAgICBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIlxyXG4gICAgICBpZD1cImZpbGVfYXR0YWNobWVudFwiXHJcbiAgICAgIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIlxyXG4gICAgICB0eXBlPVwiZmlsZVwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiXHJcbiAgICAgIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIlxyXG4gICAgICBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gICAgPGJ1dHRvblxyXG4gICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKVwiXHJcbiAgICAgIG1hdC1tZW51LWl0ZW1cclxuICAgICAgKGNsaWNrKT1cImltYWdlSW5wdXQuY2xpY2soKVwiXHJcbiAgICAgIGNsYXNzPVwiZXFwLWF0dGFjaG1lbnRzLWZpbGUtYnRuXCI+XHJcbiAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWZpbGVcIj48L2k+XHJcbiAgICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDEwcHhcIj5GaWxlPC9zcGFuPlxyXG4gICAgPC9idXR0b24+XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgICpuZ0lmPVwiYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpXCJcclxuICAgICAgbWF0LW1lbnUtaXRlbVxyXG4gICAgICAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCJcclxuICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkxpbms8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIDxidXR0b25cclxuICAgICAgKm5nSWY9XCJhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMylcIlxyXG4gICAgICBtYXQtbWVudS1pdGVtXHJcbiAgICAgIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCJcclxuICAgICAgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYS1icmFuZHMgZmEtZHJvcGJveFwiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkRyb3Bib3g8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICA8L21hdC1tZW51PlxyXG5cclxuICA8ZGl2XHJcbiAgICAqbmdJZj1cIlxyXG4gICAgICBzZXBhcmF0ZWRVcGxvYWRCdXR0b25zICYmXHJcbiAgICAgIGFsbG93ZWRUeXBlcyAmJlxyXG4gICAgICBhbGxvd2VkVHlwZXMubGVuZ3RoID4gMSAmJlxyXG4gICAgICAobXVsdGlwbGVBdHRhY2htZW50ID09IHRydWUgfHxcclxuICAgICAgICAhYXR0YWNobWVudHNMaXN0IHx8XHJcbiAgICAgICAgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8XHJcbiAgICAgICAgKGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPiAwICYmICFhdHRhY2htZW50c0xpc3RbMF0pKVxyXG4gICAgXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCI+XHJcbiAgICAgIDxidXR0b25cclxuICAgICAgICAqbmdJZj1cImFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKVwiXHJcbiAgICAgICAgKGNsaWNrKT1cImltYWdlSW5wdXQuY2xpY2soKVwiXHJcbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiXHJcbiAgICAgICAgbWF0LXJhaXNlZC1idXR0b25cclxuICAgICAgICBjb2xvcj1cInNlY29uZGFyeVwiXHJcbiAgICAgICAgdHlwZT1cImJ1dHRvblwiPlxyXG4gICAgICAgIDxpIGNsYXNzPVwiZmFzIGZhLWNsb3VkLXVwbG9hZFwiPjwvaT5cclxuICAgICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+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==