@eqproject/eqp-attachments 3.1.14 → 21.0.0

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.
@@ -1,1602 +0,0 @@
1
- import { Component, EventEmitter, Input, Output, ViewChild } from "@angular/core";
2
- import { Validators } from "@angular/forms";
3
- import imageCompression from "browser-image-compression";
4
- import { base64ToFile, ImageCropperComponent } from "ngx-image-cropper";
5
- import { AttachmentHelperService } from "./helpers/attachment.helper";
6
- import { AttachmentType, TypeAttachmentColumn } from "./interfaces/IAttachment";
7
- import { EqpAttachmentDialogService } from "./services/eqp-attachment-dialog.service";
8
- import * as i0 from "@angular/core";
9
- import * as i1 from "@angular/material/dialog";
10
- import * as i2 from "@angular/forms";
11
- import * as i3 from "@angular/platform-browser";
12
- import * as i4 from "@angular/common/http";
13
- import * as i5 from "./services/eqp-attachment.service";
14
- import * as i6 from "@angular/material/button";
15
- import * as i7 from "@angular/material/input";
16
- import * as i8 from "@angular/material/form-field";
17
- import * as i9 from "@angular/material/menu";
18
- import * as i10 from "@angular/material/button-toggle";
19
- import * as i11 from "@angular/material/icon";
20
- import * as i12 from "@angular/material/tooltip";
21
- import * as i13 from "@angular/common";
22
- import * as i14 from "ngx-image-cropper";
23
- const toBase64 = (file) => new Promise((resolve, reject) => {
24
- const reader = new FileReader();
25
- reader.readAsDataURL(file);
26
- reader.onload = () => resolve(reader.result.toString());
27
- reader.onerror = (error) => reject(error);
28
- });
29
- export class EqpAttachmentsComponent {
30
- dialog;
31
- formBuilder;
32
- sanitizer;
33
- http;
34
- eqpAttachmentService;
35
- //#region @Input del componente
36
- /**
37
- * Se TRUE allora nasconde la colonna per le azioni sull'allegato (nel caso "multipleAttachment" è TRUE).
38
- */
39
- disableAction = false;
40
- /**
41
- * Se TRUE mostra il titolo nell'header nel caso in cui "multipleAttachment" è TRUE ("Elenco allegati" di default).
42
- */
43
- showHeader = true;
44
- /**
45
- * Sorgente dati da visualizzare. Nel caso si vuole gestire un singolo allegato va passato in ogni caso come Array.
46
- */
47
- attachmentsList = null;
48
- /**
49
- * Nel caso si vuole gestire un solo elemento senza passarlo come array, lo passo come singolo allegato e gestisco nella libreria l'array.
50
- */
51
- singleAttachment = null;
52
- /**
53
- * Se TRUE non mostra la MatCard (nel caso in cui "multipleAttachment" è TRUE).
54
- */
55
- showMatCard = true;
56
- /**
57
- * 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".
58
- * Se TRUE allora il componente mostra l'elenco di tutti gli allegati ricevuto nel parametro "attachmentsList".
59
- */
60
- multipleAttachment = true;
61
- /**
62
- * Se assume il valore TRUE allora sarà possibile caricare più file per volta. Questa funzionalità è attiva
63
- * SOLO se si gestiscono allegati multipli, quindi se l'input 'multipleAttachment' assume il valore TRUE, altrimenti è sempre disabilitata.
64
- */
65
- loadMultipleFiles = false;
66
- /**
67
- * Imposta il messaggio da visualizzare nel caso in cui la tabella degli allegati (nel caso in cui "multipleAttachment" è TRUE) è vuota.
68
- */
69
- emptyTableMessage = "Nessun dato trovato";
70
- /**
71
- * Se TRUE allora permette di selezionare soltanto file di tipo immagine, avente uno dei mimetype
72
- * specificati dentro AttachmentHelperService.
73
- * Se FALSE permette di selezionare qualsiasi tipo di file
74
- */
75
- allowOnlyImages = false;
76
- /**
77
- * Specifica i tipi di file che è possibile caricare
78
- */
79
- acceptedFileTypes;
80
- /**
81
- * Se TRUE disabilita il pulsante di Aggiunta allegato (a prescindere dal valore del parametro "multipleAttachment").
82
- */
83
- isDisabled = false;
84
- /**
85
- * Mostra/nasconde la colonna per visualizzare l'anteprima dei file nella tabella (caso multipleAtatchments = true).
86
- */
87
- showInlinePreview = false;
88
- /**
89
- * Endpoint da chiamare per recueprare l'IAttachmentDTO completo da vedere nell'anteprima. La chiamata sarà in POST e nel body
90
- * conterrà l'IAttachmentDTO selezionato dall'utente.
91
- * La chiamata viene eseguita solo per l'anteprima delle immagini essendo necessario il base64 completo dell'immagine a dimensione reale.
92
- * Per documenti/link basta che sia popolata la proprietà FilePath di IAttachmentDTO.
93
- */
94
- getAttachmentEndpoint = null;
95
- /**
96
- * Hostname dell'ambiente di produzione dell'applicativo. Necessario per visualizzare l'anteprima dei documenti
97
- * tramite il viewer di google.
98
- * NOTA: Per visualizzare l'anteprima è necessario che la prorietà FilePath dell'IAttachmentDTO sia popolata e che
99
- * sia abilitato l'accesso alla cartella sul server tramite hostname.
100
- */
101
- productionBaseUrl = null;
102
- /**
103
- * Opzioni per la compressione delle immagini caricate.
104
- */
105
- compressionOptions = {
106
- maxSizeMB: 0.5,
107
- maxWidthOrHeight: 1920,
108
- useWebWorker: true
109
- };
110
- /**
111
- * Array di AttachmentType che si possono aggiungere
112
- */
113
- allowedTypes = [AttachmentType.FILE, AttachmentType.LINK];
114
- /**
115
- * Permette di stabilire se la eqp-table contenente l'elenco degli allegati utilizza
116
- * il multilingua oppure no
117
- */
118
- isEqpTableMultiLanguage = false;
119
- /**
120
- * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
121
- * degli allegati deve essere paginata oppure no
122
- */
123
- tablePaginatorVisible = true;
124
- /**
125
- * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
126
- * degli allegati deve contenere il campo di ricerca oppure no
127
- */
128
- isTableSearcheable = true;
129
- /**
130
- * In caso di gestione allegati multipli, permette di stabilire la dimensione pagina di default
131
- * per la tabella contenente l'elenco degli allegati
132
- */
133
- tablePaginatorSize = null;
134
- /**
135
- * Permette di scegliere il modo in cui i file devono essere caricati
136
- */
137
- // @Input("uploadType") uploadType: UploadTypeEnum = UploadTypeEnum.FILE_AND_LINK;
138
- /**
139
- * Permette di stabilire se i pulsanti per il caricamento dei file sono separati o in un menù a tendina
140
- */
141
- separatedUploadButtons = false;
142
- /**
143
- * Permette di scegliere se dare la possibilità di vedere o no l'anteprima
144
- */
145
- showPreview = true;
146
- /**
147
- * In caso di allegato singolo, permette di scegliere se aggiungere file tramite drag and drop
148
- */
149
- singleAttachmentDragAndDrop = true;
150
- /**
151
- * Array di opzioni che si possono utilizzare per il crop
152
- */
153
- cropOptions = [1, 2];
154
- /**
155
- * Classe custom da assegnare al dialog del crop immagini
156
- */
157
- cropDialogClass;
158
- maxFileSizeMB = 500; // Default max size of 100 MB
159
- cardSize = 'small'; // Default
160
- customCardWidthPx = 200; // Larghezza custom in px
161
- customCardHeightPx = 180; // Altezza custom in px
162
- layout = 'compact';
163
- /**
164
- * Input per definire le label da usare nel componente
165
- */
166
- openLinkLabel = "Apri link";
167
- addButtonLabel = "Aggiungi";
168
- downloadLabel = "Download";
169
- deleteLabel = "Elimina";
170
- fileNameLabel = "Nome file";
171
- previewLabel = "Anteprima";
172
- uploadFileLabel = "Carica file";
173
- confirmLabel = "Conferma";
174
- abortLabel = "Annulla";
175
- saveLabel = "Salva";
176
- exitLabel = "Esci";
177
- uploadWithDropboxLabel = "Carica con Dropbox";
178
- cropLabel = "Scegli le dimensioni dell'immagine";
179
- deleteDialogTitle = null;
180
- deleteDialogMessage = "Sei sicuro di voler cancellare quest'allegato?";
181
- noImageSelectedErrorMessage = "Non è possibile selezionare un file che non sia un'immagine.";
182
- wrongTypeSelectedErrorMessage = "Non è possibile caricare il file selezionato.";
183
- videoPreviewErrorMessage = "Impossibile aprire l'anteprima di un file video.";
184
- audioPreviewErrorMessage = "Impossibile aprire l'anteprima di un file audio.";
185
- flipHorinzontalLabel = "Capovolgi orizzontalmente";
186
- flipVerticalLabel = "Capovolgi verticalmente";
187
- rotateRightLabel = "Ruota a destra";
188
- rotateLeftLabel = "Ruota a sinistra";
189
- base64LimitMB = 100;
190
- uploadTitle = 'Upload file';
191
- uploadSubtitle = 'Drag & drop files o click';
192
- dropHereLabel = 'Rilascia i file qui';
193
- supportedFormatsLabel = 'Formati supportati: JPEG, PNG, PDF (Max 100MB)';
194
- browseFilesLabel = 'Cerca i file';
195
- uploadSummaryLabel = 'Lista allegati';
196
- filesLabel = 'Files';
197
- totalSizeLabel = 'Dimensione totale';
198
- emptyStateLabel = 'Non sono presenti file caricati';
199
- addedSuccessfullyLabel = 'file(s) caricati con successo.';
200
- removedLabel = 'File rimosso';
201
- // @Input() removeLabel = 'Rimuovi file';
202
- chooseView = true;
203
- showSummary = false;
204
- viewMode = 'table';
205
- showUploadTitle = true;
206
- showDropArea = true;
207
- hiddenColumns = [];
208
- hiddenActions = [];
209
- showActionButtons = false;
210
- /**
211
- * Se TRUE allora mostra il dialog di crop per le immagini singole.
212
- * Se FALSE carica l'immagine direttamente (applicando comunque la compressione se attiva).
213
- */
214
- enableImageCrop = true;
215
- /**
216
- * Hook globale: decide se nascondere un’azione per quello specifico allegato.
217
- */
218
- actionHiddenFn;
219
- /**
220
- * Hook globale: decide se disabilitare un’azione per quello specifico allegato.
221
- */
222
- actionDisabledFn;
223
- videoCompression = { enabled: false, maxWidth: 1280, crf: 23, preset: 'veryfast', maxFps: 30, audioBitrate: 128000 };
224
- _customMenuActions = [];
225
- _sortedMenuActions = [];
226
- set customMenuActions(value) {
227
- this._customMenuActions = value || [];
228
- this.setupMenuActions();
229
- }
230
- get customMenuActions() {
231
- return this._customMenuActions;
232
- }
233
- _customColumns = [];
234
- /**
235
- * SOLO quando [customColumns]="..." cambia.
236
- */
237
- set customColumns(value) {
238
- this._customColumns = value || [];
239
- this.setupTableColumns();
240
- }
241
- get customColumns() {
242
- return this._customColumns;
243
- }
244
- //#endregion
245
- //#region @Output del componente
246
- /**
247
- * Restituisce la lista aggiornata degli allegati.
248
- */
249
- localEditedAttachments = new EventEmitter();
250
- /**
251
- * Evento scatenato alla pressione del pulsante ESCI della modale di caricamento file.
252
- */
253
- abortAddAttachment = new EventEmitter();
254
- /**
255
- * Evento di output che restituisce l'IAttachmentDTO selezionato per il download nel caso FileDataBase64, FileContentType o FileName non fossero specificati.
256
- */
257
- downloadAttachment = new EventEmitter();
258
- /**
259
- * Evento di output che restituisce l'elemento eliminato prima che questo venga effettivamente rismosso dalla lista.
260
- */
261
- onDeleteAttachment = new EventEmitter();
262
- //#endregion
263
- //#region Proprietà per gestione caricamento nuovo allegato
264
- newAttachment = {};
265
- newMultipleAttachments = [];
266
- attachmentType = AttachmentType;
267
- // uploadTypeEnum = UploadTypeEnum;
268
- newAttachmentForm;
269
- selectedFile = null;
270
- selectedFiles = null;
271
- showCropImage = false;
272
- dialogAddAttachment;
273
- dialogRefAddAttachment;
274
- dialogAddMultipleAttachment;
275
- dialogRefCropImage;
276
- dialogCropImage;
277
- addingLinkTemplate;
278
- //#endregion
279
- //#region Proprietà per gestione ridimensionamento file di tipo image
280
- imageChangedEvent = "";
281
- croppedImage = "";
282
- transform = {};
283
- canvasRotation = 0;
284
- imageCropper;
285
- imageInput;
286
- //#endregion
287
- AttachmentType = AttachmentType;
288
- selectedAttachment;
289
- originalWidth;
290
- originalHeight;
291
- customWidth;
292
- customHeight;
293
- inlinePreviewTemplate;
294
- dialogPreview;
295
- imageFile;
296
- addingLinkMode = false;
297
- //#region Sezione nuova refactoring
298
- // Proprietà interna che conterrà l'array finale di colonne ordinate
299
- _tableColumns = [];
300
- defaultFileTemplate;
301
- defaultActionsTemplate;
302
- // Stato drag & drop e toast
303
- dragOver = false;
304
- toast = {
305
- visible: false,
306
- type: 'success',
307
- text: '',
308
- timeoutId: 0
309
- };
310
- progressPercent = 0;
311
- totalSizeBytes = 0;
312
- get totalSizeFormatted() { return this.formatFileSize(this.totalSizeBytes); }
313
- // Utility per formattare bytes (2 decimali)
314
- formatFileSize(bytes) {
315
- if (!bytes || bytes <= 0)
316
- return '0 Bytes';
317
- const k = 1024;
318
- const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
319
- const i = Math.floor(Math.log(bytes) / Math.log(k));
320
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
321
- }
322
- // Mostra toast con auto‑hide e reset progress bar CSS
323
- showToast(message, type = 'success', durationMs = 3000) {
324
- if (this.toast.visible && this.toast.text === message) {
325
- return;
326
- }
327
- // Cancella il timeout precedente se esiste
328
- if (this.toast.timeoutId) {
329
- clearTimeout(this.toast.timeoutId);
330
- }
331
- // Calcola una durata dinamica
332
- const duration = durationMs || Math.max(4000, message.length * 100);
333
- this.toast.text = message;
334
- this.toast.type = type;
335
- this.toast.visible = true;
336
- // Imposta il nuovo timeout per nascondere automaticamente il toast
337
- this.toast.timeoutId = setTimeout(() => {
338
- this.toast.visible = false;
339
- }, duration);
340
- }
341
- #endregion;
342
- constructor(dialog, formBuilder, sanitizer, http, eqpAttachmentService) {
343
- this.dialog = dialog;
344
- this.formBuilder = formBuilder;
345
- this.sanitizer = sanitizer;
346
- this.http = http;
347
- this.eqpAttachmentService = eqpAttachmentService;
348
- }
349
- ngOnInit() {
350
- // Inizializza metriche e progress in base allo stato iniziale
351
- this.recomputeTotalsAndProgress();
352
- //Se è stata richiesta la gestione delle sole immagini allora imposta il filtro per le estensioni possibili da caricare
353
- if (!this.acceptedFileTypes)
354
- if (this.allowOnlyImages == true)
355
- this.acceptedFileTypes = "image/*";
356
- else
357
- this.acceptedFileTypes = "*";
358
- // Se non sono stati specificati i tipi da gestire ma è stato passato null o un array vuoto imposto i tipi di default.
359
- if (!this.allowedTypes || this.allowedTypes.length == 0)
360
- this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK, AttachmentType.DROPBOX];
361
- else if (this.allowedTypes.find((t) => t != AttachmentType.FILE && t != AttachmentType.LINK && t != AttachmentType.DROPBOX)) {
362
- EqpAttachmentDialogService.Warning('Almeno uno degli AttachmentType selezionati nel parametro "allowedTypes" non esiste.');
363
- this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK, AttachmentType.DROPBOX];
364
- }
365
- if (this.attachmentsList == null)
366
- this.attachmentsList = new Array();
367
- // Se è stato passato un singolo allegato lo aggiungo alla lista
368
- if (this.singleAttachment != null && this.attachmentsList.length == 0) {
369
- this.attachmentsList.push(this.singleAttachment);
370
- }
371
- this.checkAttachmentImage();
372
- if (this.allowedTypes.includes(3)) {
373
- this.eqpAttachmentService.loadDropboxScript();
374
- }
375
- this.setupTableColumns();
376
- this.setupMenuActions();
377
- }
378
- setViewMode(mode) {
379
- this.viewMode = mode;
380
- }
381
- // Ricalcola la somma pesata sugli allegati presenti
382
- recomputeTotalsAndProgress() {
383
- this.totalSizeBytes = (this.attachmentsList || [])
384
- .filter(a => !!a)
385
- .reduce((sum, a) => sum + this.bytesFromBase64(a.FileDataBase64 || a.FileThumbnailBase64 || ''), 0);
386
- // Progress fittizio: 100% se presenti file, 0 se vuoto
387
- this.progressPercent = (this.attachmentsList && this.attachmentsList.length > 0) ? 100 : 0;
388
- }
389
- ngOnDestroy() {
390
- if (this.toast.timeoutId)
391
- clearTimeout(this.toast.timeoutId);
392
- }
393
- // Calcola i byte da una stringa Base64 pura (senza prefisso data:...)
394
- bytesFromBase64(base64) {
395
- if (!base64)
396
- return 0;
397
- // Rimuovi eventuale prefisso data URL
398
- const commaIdx = base64.indexOf(',');
399
- const b64 = commaIdx >= 0 ? base64.substring(commaIdx + 1) : base64;
400
- // Conta padding
401
- let padding = 0;
402
- if (b64.endsWith('=='))
403
- padding = 2;
404
- else if (b64.endsWith('='))
405
- padding = 1;
406
- // Formula esatta: (3 * (len / 4)) - padding
407
- const len = b64.length;
408
- return Math.max(0, (3 * Math.floor(len / 4)) - padding);
409
- }
410
- checkAttachmentImage() {
411
- this.attachmentsList.forEach((a) => {
412
- a.IsImage = AttachmentHelperService.checkImageFromMimeType(a.FileContentType);
413
- });
414
- }
415
- //#region Gestione elenco allegati
416
- /**
417
- * Elimina un allegato eliminando anche il file presente nello storage di archiviazione utilizzato (AWS o cartella progetto)
418
- * @param element IAttachmentDTO da cancellare
419
- */
420
- deleteAttachment(element) {
421
- EqpAttachmentDialogService.Confirm(this.deleteDialogMessage, () => {
422
- this.removeAttachmentFromList(this.attachmentsList.indexOf(element));
423
- }, true, this.deleteDialogTitle);
424
- }
425
- /**
426
- * Rimuove l'allegato selezionato dalla lista "attachmentsList" e invoca l'evento di output che restituisce la lista aggiornata.
427
- * @param attachmentIndex Indice dell'attachment da rimuovere
428
- */
429
- removeAttachmentFromList(attachmentIndex) {
430
- this.onDeleteAttachment.emit(this.attachmentsList[attachmentIndex]);
431
- this.attachmentsList.splice(attachmentIndex, 1);
432
- this.localEditedAttachments.emit(this.attachmentsList);
433
- this.recomputeTotalsAndProgress();
434
- this.showToast(this.removedLabel || 'File removed', 'success');
435
- }
436
- simulateProgress() {
437
- this.progressPercent = 0;
438
- setTimeout(() => {
439
- this.progressPercent = 30;
440
- setTimeout(() => {
441
- this.progressPercent = 60;
442
- setTimeout(() => {
443
- this.progressPercent = 100;
444
- }, 200);
445
- }, 200);
446
- }, 100);
447
- }
448
- /**
449
- * Scarica l'allegato o apre il link
450
- * @param element Allegato da mostrare
451
- */
452
- viewAttachment(attachment) {
453
- if (attachment.AttachmentType == AttachmentType.LINK) {
454
- window.open(attachment.FilePath, "_blank");
455
- return;
456
- }
457
- if (attachment.LargeFile) {
458
- const file = attachment.LargeFile;
459
- const url = URL.createObjectURL(file);
460
- const link = document.createElement("a");
461
- link.href = url;
462
- link.download = attachment.FileName || file.name;
463
- link.click();
464
- setTimeout(() => URL.revokeObjectURL(url), 1000);
465
- return;
466
- }
467
- if (attachment.FileDataBase64 && attachment.FileContentType && attachment.FileName) {
468
- let source = `data:${attachment.FileContentType};base64,${attachment.FileDataBase64}`;
469
- const link = document.createElement("a");
470
- link.href = source;
471
- link.download = `${attachment.FileName}`;
472
- link.click();
473
- }
474
- else {
475
- this.downloadAttachment.emit(attachment);
476
- }
477
- }
478
- /**
479
- * Ridefinisce l'icona da mostrare nella colonna dell'eqp-table per ogni file.
480
- * L'icona varia in base all'estensione del file
481
- * @param attachment
482
- */
483
- getAttachmentIcon(attachment) {
484
- if (attachment.AttachmentType == AttachmentType.LINK)
485
- return "fas fa-link";
486
- else
487
- return AttachmentHelperService.getIconFromFileExtensione(attachment.FileExtension);
488
- }
489
- //#endregion
490
- /**
491
- * In caso di allegato singolo, sceglie quale metodo richiamare in base al tipo di allegato
492
- */
493
- addFile(attachmentType, imageInput = null) {
494
- if (attachmentType == AttachmentType.LINK) {
495
- this.switchToAddingLinkMode();
496
- }
497
- else if (attachmentType == AttachmentType.FILE) {
498
- imageInput.click();
499
- }
500
- else {
501
- this.chooseDropboxFile();
502
- }
503
- }
504
- createAttachmentForm() {
505
- //Crea la form per la validazione dei campi
506
- this.newAttachmentForm = this.formBuilder.group({
507
- type: [this.newAttachment.AttachmentType, Validators.required],
508
- name: [this.newAttachment.FileName],
509
- path: [this.newAttachment.FilePath],
510
- customHeight: [this.customHeight],
511
- customWidth: [this.customWidth]
512
- });
513
- }
514
- close(emitCloseEvent = true) {
515
- this.newAttachment = {};
516
- this.newMultipleAttachments = new Array();
517
- this.abortFile();
518
- if (this.newAttachmentForm)
519
- this.newAttachmentForm.reset();
520
- this.dialogRefCropImage.close();
521
- this.restoreOriginalDimensions();
522
- if (emitCloseEvent == true && this.abortAddAttachment)
523
- this.abortAddAttachment.emit();
524
- }
525
- /**
526
- * In base al tipo di allegato controlla se disabilitare o meno il pulsante per salvare.
527
- * Funzione usata nel [disable] del pulsante "Salva" del dialog per l'aggiunta di un allegato.
528
- * @returns
529
- */
530
- disableSave() {
531
- if (this.loadMultipleFiles != true) {
532
- if (this.newAttachment.AttachmentType == AttachmentType.FILE) {
533
- return !this.newAttachment.FileDataBase64 && !this.newAttachment.LargeFile;
534
- }
535
- else {
536
- return !this.newAttachment.FilePath;
537
- }
538
- }
539
- else {
540
- return (this.newMultipleAttachments.filter((p) => (p.AttachmentType == AttachmentType.FILE && !p.FileDataBase64 && !p.LargeFile) ||
541
- (p.AttachmentType == AttachmentType.LINK && !p.FilePath)).length > 0);
542
- }
543
- }
544
- confirmAddAttachment() {
545
- if (this.newAttachment.IsImage && this.imageCropper) {
546
- this.newAttachment.FileDataBase64 = this.imageCropper.crop().base64.split(";base64,")[1];
547
- }
548
- if (this.loadMultipleFiles != true) {
549
- if (this.newAttachment.AttachmentType == AttachmentType.LINK && !this.newAttachment.FileName)
550
- this.newAttachment.FileName = this.newAttachment.FilePath;
551
- if (this.attachmentsList == null)
552
- this.attachmentsList = new Array();
553
- this.attachmentsList.push(this.newAttachment);
554
- }
555
- else {
556
- if (this.newMultipleAttachments == null || this.newMultipleAttachments.length == 0)
557
- return;
558
- if (this.attachmentsList == null)
559
- this.attachmentsList = new Array();
560
- this.attachmentsList = this.attachmentsList.concat(this.newMultipleAttachments);
561
- }
562
- this.localEditedAttachments.emit(this.attachmentsList);
563
- if (this.newAttachment.IsImage) {
564
- this.dialogRefCropImage.close();
565
- this.restoreOriginalDimensions();
566
- }
567
- if (this.newAttachment.AttachmentType === AttachmentType.LINK) {
568
- this.newAttachment = {};
569
- if (this.newAttachmentForm)
570
- this.newAttachmentForm.reset();
571
- }
572
- this.resetSelectedFiles();
573
- }
574
- // 2. RESET TOTALE: Svuotiamo le proprietà di classe per evitare che
575
- // residui di upload precedenti (singoli o multipli) vengano trascinati.
576
- resetSelectedFiles() {
577
- this.newAttachment = {};
578
- this.newMultipleAttachments = [];
579
- this.selectedFile = null;
580
- this.selectedFiles = [];
581
- }
582
- /**
583
- * Apre il dialog per l'anteprima dell'allegato selezionato.
584
- * @param row
585
- * @returns
586
- */
587
- async openPreviewDialog(row) {
588
- this.selectedAttachment = { ...row };
589
- if (this.getAttachmentEndpoint && this.selectedAttachment.IsImage && !this.selectedAttachment.FileDataBase64) {
590
- await this.getAttachmentByID()
591
- .then((res) => {
592
- this.selectedAttachment.FileDataBase64 = res.FileDataBase64;
593
- })
594
- .catch((err) => {
595
- EqpAttachmentDialogService.Error(err);
596
- });
597
- }
598
- if (this.selectedAttachment.AttachmentType == AttachmentType.LINK) {
599
- this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.selectedAttachment.FilePath);
600
- }
601
- else if (this.selectedAttachment.FileContentType?.startsWith("video/") && this.selectedAttachment.LargeFile) {
602
- const videoUrl = URL.createObjectURL(this.selectedAttachment.LargeFile);
603
- // Usiamo bypassSecurityTrustUrl per la sorgente del video
604
- this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustUrl(videoUrl);
605
- }
606
- else if (this.selectedAttachment.IsImage &&
607
- !this.selectedAttachment.FileDataBase64 &&
608
- !this.selectedAttachment.FileThumbnailBase64) {
609
- EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima dell'allegato, file mancante.");
610
- return;
611
- }
612
- else if (this.selectedAttachment.FileContentType === 'application/pdf' && this.selectedAttachment.FileDataBase64) {
613
- this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(`data:application/pdf;base64,${this.selectedAttachment.FileDataBase64}`);
614
- }
615
- else if (!this.selectedAttachment.IsImage) {
616
- if (this.selectedAttachment.FilePath && this.productionBaseUrl) {
617
- this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://docs.google.com/gview?url=" +
618
- this.productionBaseUrl +
619
- "/" +
620
- this.selectedAttachment.FilePath +
621
- "&embedded=true");
622
- }
623
- else {
624
- EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima del documento!");
625
- return;
626
- }
627
- }
628
- const dialogRef = this.dialog.open(this.dialogPreview, {
629
- panelClass: 'eqp-attachments-preview-dialog',
630
- maxWidth: '95vw',
631
- width: row.IsImage || row.FileContentType?.startsWith('video/') ? 'auto' : '1100px',
632
- });
633
- // Pulizia della memoria quando il dialog si chiude
634
- dialogRef.afterClosed().subscribe(() => {
635
- if (this.selectedAttachment?.FileContentType?.startsWith("video/")) {
636
- URL.revokeObjectURL(this.selectedAttachment.TrustedUrl);
637
- }
638
- });
639
- }
640
- async getAttachmentByID() {
641
- return this.http.post(this.getAttachmentEndpoint, this.selectedAttachment).toPromise();
642
- }
643
- //#region Gestione caricamento file
644
- /**
645
- * Evento scatenato alla selezione del file (o dei file).
646
- * 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
647
- * mostrare le funzionalità del croppie (per ritagliare l'immagine) oppure no.
648
- * Se il file caricato non è un immagine allora genera direttamente il base64 e lo associa all'allegato da salvare.
649
- * Se invece il caricamento dei file è MULTIPLO e sono presenti più file allora esegue le stesse operazioni ignorando però il contrllo
650
- * immagine per il croppie (in caso di caricamento multiplo le funzionalità del croppie sono disabilitate).
651
- */
652
- async onFileAdded(event, isFileDropped = false) {
653
- if (this.isDisabled) {
654
- EqpAttachmentDialogService.Info("Caricamento allegati non disponibile.");
655
- event.preventDefault();
656
- return;
657
- }
658
- this.showCropImage = false;
659
- this.resetSelectedFiles();
660
- const filesOnInput = isFileDropped
661
- ? event
662
- : Array.from(event.target?.files || []);
663
- const { validFiles, oversizedFiles } = this.validationFile(filesOnInput);
664
- if (!validFiles || validFiles.length === 0) {
665
- if (!isFileDropped && event?.target instanceof HTMLInputElement) {
666
- event.target.value = '';
667
- }
668
- return;
669
- }
670
- //Se è stato richiesto il caricamento SINGOLO oppure se il caricamento è MULTIPLO ma è stato selezionato un solo file
671
- //allora verifica se il file è un immagine (per mostrare il CROPPIE)
672
- if ([...validFiles].length == 1 || this.loadMultipleFiles != true) {
673
- this.selectedFile = validFiles[0];
674
- this.selectedFiles = validFiles;
675
- if (!this.selectedFile)
676
- return;
677
- //Memorizza i dati per l'allegato
678
- this.newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFile, false);
679
- this.newMultipleAttachments = new Array();
680
- this.newMultipleAttachments.push(this.newAttachment);
681
- //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
682
- let checkOnlyImage = this.checkAllowOnlyImageFile(this.newAttachment);
683
- if (checkOnlyImage == false)
684
- return;
685
- this.createAttachmentForm();
686
- //Verifica se il file caricato è un'immagine oppure no. Se è un immagine, prima di caricarla mostra il croppie per il resize.
687
- //Se non è un immagine allora genera il Base64
688
- if (this.newAttachment.IsImage == true && this.enableImageCrop) {
689
- this.getImageDimensions(validFiles[0]);
690
- //Mostra il croppie e disabilita la form finchè non termina la modifica dell'immagine
691
- this.newAttachmentForm.disable();
692
- this.newAttachmentForm.controls["customWidth"].enable();
693
- this.newAttachmentForm.controls["customHeight"].enable();
694
- setTimeout(() => {
695
- this.showCropImage = true;
696
- this.imageFile = event;
697
- this.dialogRefCropImage = this.dialog.open(this.dialogCropImage, {
698
- disableClose: true,
699
- hasBackdrop: true,
700
- width: "95vw",
701
- maxWidth: "800px",
702
- maxHeight: "90vh",
703
- panelClass: ['eqp-attachments-dialog', 'crop-dialog']
704
- });
705
- });
706
- }
707
- else {
708
- this.showCropImage = false;
709
- let base64Result = await this.getBase64FromFile(this.selectedFile);
710
- this.newAttachment.FileDataBase64 = base64Result.Base64File;
711
- this.newAttachment.FileContentType = base64Result.ContentType;
712
- this.confirmAddAttachment();
713
- }
714
- }
715
- else {
716
- this.selectedFiles = validFiles;
717
- if (!this.selectedFiles || this.selectedFiles.length == 0)
718
- return;
719
- if (!this.newMultipleAttachments)
720
- this.newMultipleAttachments = [];
721
- for (let i = 0; i < this.selectedFiles.length; i++) {
722
- let newAttachment = await this.createAttachmentFromUploadedFile(this.selectedFiles[i], true, true);
723
- //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
724
- let checkOnlyImage = this.checkAllowOnlyImageFile(newAttachment);
725
- if (checkOnlyImage == false)
726
- return;
727
- this.newMultipleAttachments.push(newAttachment);
728
- }
729
- this.confirmAddAttachment();
730
- }
731
- this.recomputeTotalsAndProgress();
732
- this.simulateProgress();
733
- // Caso 1: Successo Parziale (alcuni file validi, altri no)
734
- if (oversizedFiles.length > 0 && validFiles.length > 0) {
735
- const fileNames = oversizedFiles.join(', ');
736
- this.showToast(`${validFiles.length} file aggiunti. ${oversizedFiles.length} non caricati perché troppo grandi (${fileNames}).`, 'error');
737
- }
738
- // Caso 2: Nessun file valido
739
- else if (oversizedFiles.length > 0 && validFiles.length === 0) {
740
- }
741
- // Caso 3: Tutti i file validi
742
- else if (oversizedFiles.length === 0 && validFiles.length > 0) {
743
- this.showToast(`${validFiles.length} ${this.addedSuccessfullyLabel || 'file(s) aggiunti con successo.'}`, 'success');
744
- }
745
- //Resetto il valore del file input in modo da scatenare il change anche se si dovesse caricare lo stesso file
746
- if (!isFileDropped)
747
- event.target.value = "";
748
- }
749
- validationFile(filesOnInput) {
750
- const validFiles = [];
751
- const oversizedFiles = [];
752
- for (const file of filesOnInput) {
753
- const fileSizeMB = file.size / 1024 / 1024;
754
- if (fileSizeMB > this.maxFileSizeMB) {
755
- oversizedFiles.push(file.name);
756
- }
757
- else {
758
- validFiles.push(file);
759
- }
760
- }
761
- if (oversizedFiles.length > 0) {
762
- const fileNames = oversizedFiles.join(', ');
763
- this.showToast(`File(s) troppo grandi: ${fileNames}. Limite: ${this.maxFileSizeMB}MB`, 'error');
764
- }
765
- return { validFiles, oversizedFiles };
766
- }
767
- /**
768
- * A partire dal FILE ricevuto in input ricostruisce l'oggetto IAttachmentDTO e lo restituisce.
769
- * Se il parametro getBase64 viene passato a TRUE allora, sempre a partire dal file,genera il base64 e
770
- * ricava il ContentType da associare all'oggetto IAttachmentDTO da restituire
771
- * @param currentFile Oggetto FILE da processare
772
- * @param getBase64 Se TRUE allora calcola base64 e ContentType del file passato in input
773
- * @returns Restituisce un oggetto di tipo IAttachmentDTO
774
- */
775
- async createAttachmentFromUploadedFile(currentFile, getBase64 = true, cropFile = false) {
776
- let newAttachment = {};
777
- //Memorizza i dati per l'allegato
778
- newAttachment.AttachmentType = AttachmentType.FILE;
779
- newAttachment.FileContentType = currentFile.type;
780
- newAttachment.FileName = currentFile.name;
781
- newAttachment.FileExtension = currentFile.name.substr(currentFile.name.lastIndexOf(".") + 1);
782
- newAttachment.IsImage = AttachmentHelperService.checkImageFromMimeType(currentFile.type);
783
- const fileSizeMB = currentFile.size / 1024 / 1024;
784
- const isLargeFile = fileSizeMB > this.base64LimitMB;
785
- const isVideo = currentFile.type.startsWith('video');
786
- if (isVideo) {
787
- let finalFile = currentFile;
788
- // 1. Genera la miniatura (rimane lato client perché è un'operazione istantanea)
789
- newAttachment.FileThumbnailBase64 = await this.generateVideoThumbnail(currentFile);
790
- // 2. Se la compressione è abilitata, inviamo il file all'API C#
791
- if (this.videoCompression.enabled) {
792
- this.showToast("Compressione video in corso... L'operazione potrebbe richiedere alcuni minuti.", "info");
793
- try {
794
- // Chiamata al microservizio C# (metodo ristrutturato precedentemente)
795
- const compressedBlob = await this.compressVideoApi(currentFile, this.videoCompression);
796
- // Creiamo il nuovo nome file con estensione .mp4
797
- const newFileName = currentFile.name.replace(/\.[^/.]+$/, "") + ".mp4";
798
- // Trasformiamo il Blob ricevuto in un File per mantenere la coerenza nell'oggetto DTO
799
- finalFile = new File([compressedBlob], newFileName, { type: "video/mp4" });
800
- // Aggiorniamo i metadati dell'allegato
801
- newAttachment.FileName = newFileName;
802
- newAttachment.FileContentType = "video/mp4";
803
- }
804
- catch (error) {
805
- EqpAttachmentDialogService.Error("Errore durante la compressione remota del video. Verrà caricato il file originale.");
806
- console.error("Video API Error:", error);
807
- // In caso di errore dell'API, finalFile rimane il currentFile originale
808
- }
809
- }
810
- // Impostiamo il file (compresso o originale) come LargeFile
811
- newAttachment.LargeFile = finalFile;
812
- newAttachment.IsLargeFile = true;
813
- return newAttachment;
814
- }
815
- if (isLargeFile) {
816
- // CASO LARGE FILE:
817
- // Popoliamo OriginalFile e forziamo il Base64 a null.
818
- newAttachment.FileDataBase64 = null;
819
- newAttachment.LargeFile = currentFile;
820
- newAttachment.IsLargeFile = true;
821
- getBase64 = false;
822
- }
823
- if (getBase64 == true) {
824
- let base64Result = await this.getBase64FromFile(currentFile);
825
- newAttachment.FileDataBase64 = base64Result.Base64File;
826
- if (!newAttachment.FileContentType && base64Result.ContentType) {
827
- newAttachment.FileContentType = base64Result.ContentType;
828
- }
829
- if (newAttachment.IsImage && newAttachment.FileDataBase64 && cropFile) {
830
- this.getCroppedAndUpload(`data:${base64Result.ContentType};base64,${base64Result.Base64File}`, newAttachment);
831
- }
832
- }
833
- return newAttachment;
834
- }
835
- /**
836
- * A partire dal file passato in input restituisce un oggetto
837
- * contenente il base64 del file e il suo contentType
838
- * @param currentFile Oggetto File da cui estrapolare base64 e contentType
839
- * @returns Restituisce un oggetto avente le proprietà Base64File e ContentType
840
- */
841
- async getBase64FromFile(currentFile) {
842
- const fileSizeMB = currentFile.size / 1024 / 1024;
843
- if (fileSizeMB > this.base64LimitMB) {
844
- return {
845
- Base64File: null,
846
- ContentType: currentFile.type
847
- };
848
- }
849
- // Procedura standard
850
- try {
851
- let base64File = await toBase64(currentFile);
852
- let contentType = null;
853
- if (base64File) {
854
- contentType = base64File.split(",")[0].split(":")[1].split(";")[0];
855
- base64File = base64File.split(",")[1];
856
- }
857
- return {
858
- Base64File: base64File,
859
- ContentType: contentType
860
- };
861
- }
862
- catch (ex) {
863
- return { Base64File: null, ContentType: null };
864
- }
865
- }
866
- /**
867
- * Controlla se il file che si sta caricando è supportato dal sistema.
868
- * @returns
869
- */
870
- checkAcceptedFiles() {
871
- // Se accetto tutto, esco subito
872
- if (this.acceptedFileTypes === "*")
873
- return true;
874
- const isTypeValid = (mimeType) => {
875
- if (!mimeType)
876
- return false;
877
- // Controllo corrispondenza esatta (es. image/png)
878
- if (this.acceptedFileTypes.includes(mimeType))
879
- return true;
880
- const wildcards = this.acceptedFileTypes.split(",").filter(t => t.includes("*"));
881
- for (let t of wildcards) {
882
- const prefix = t.split("*")[0]; // Prende "image/" da "image/*"
883
- if (mimeType.startsWith(prefix))
884
- return true;
885
- }
886
- return false;
887
- };
888
- if (this.loadMultipleFiles !== true) {
889
- // Caso Singolo
890
- return isTypeValid(this.selectedFile.type);
891
- }
892
- else {
893
- // Caso Multiplo: TUTTI i file selezionati devono essere validi
894
- return Array.from(this.selectedFiles).every(file => isTypeValid(file.type));
895
- }
896
- }
897
- /**
898
- * Se eqp-attachments è stata configurata per il caricamento delle sole immagini allora verifica che il file passato in
899
- * input sia effettivamente un immagine o no.
900
- * Se il controllo va a buon fine restituisce TRUE altrimenti mostra un messaggio d'errore e restituisce FALSE
901
- */
902
- checkAllowOnlyImageFile(newAttachment) {
903
- if (this.allowOnlyImages == true && newAttachment.IsImage != true) {
904
- EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage);
905
- this.abortFile();
906
- return false;
907
- }
908
- else if (!this.checkAcceptedFiles()) {
909
- EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage);
910
- this.abortFile();
911
- return false;
912
- }
913
- return true;
914
- }
915
- //#region Gestione crop file
916
- getImageDimensions(img) {
917
- const reader = new FileReader();
918
- reader.onload = (e) => {
919
- const image = new Image();
920
- image.src = e.target.result;
921
- image.onload = (rs) => {
922
- this.originalHeight = rs.currentTarget["height"];
923
- this.originalWidth = rs.currentTarget["width"];
924
- if (this.originalWidth > 1280) {
925
- this.customWidth = 1280;
926
- this.customHeight = Math.round((1280 * this.originalHeight) / this.originalWidth);
927
- }
928
- else {
929
- this.customHeight = rs.currentTarget["height"];
930
- this.customWidth = rs.currentTarget["width"];
931
- }
932
- };
933
- };
934
- reader.readAsDataURL(img);
935
- }
936
- restoreOriginalDimensions() {
937
- this.customWidth = this.originalWidth;
938
- this.customHeight = this.originalHeight;
939
- this.canvasRotation = 0;
940
- this.transform = {};
941
- }
942
- onDimensionsChange(dimension) {
943
- if (dimension == "H") {
944
- this.customWidth = Math.round((this.customHeight * this.originalWidth) / this.originalHeight);
945
- }
946
- else if (dimension == "W") {
947
- this.customHeight = Math.round((this.customWidth * this.originalHeight) / this.originalWidth);
948
- }
949
- }
950
- imageCropped(event) {
951
- this.croppedImage = event.base64;
952
- this.getCroppedAndUpload(this.croppedImage, this.newAttachment);
953
- }
954
- getCroppedAndUpload(file, newAttachment) {
955
- var self = this;
956
- var file = base64ToFile(file);
957
- const options = this.compressionOptions;
958
- /**
959
- * Comprime l'immagine passando come parametri le options create nell'oggetto sopra, e il file dal reader principale
960
- */
961
- imageCompression(file, options).then((fileCompressed) => {
962
- let fileReader = new FileReader();
963
- //Faccio la push di ogni file all'interno dell'array di file dell'item da mandare al server
964
- fileReader.onload = function () {
965
- let resultReader = fileReader.result;
966
- var marker = ";base64,";
967
- newAttachment.FileDataBase64 = resultReader.substring(resultReader.indexOf(marker) + marker.length);
968
- self.showCropImage = false;
969
- if (self.newAttachmentForm) {
970
- self.newAttachmentForm.enable();
971
- }
972
- };
973
- fileReader.readAsDataURL(fileCompressed);
974
- });
975
- }
976
- rotateLeft() {
977
- this.canvasRotation--;
978
- this.flipAfterRotate();
979
- }
980
- rotateRight() {
981
- this.canvasRotation++;
982
- this.flipAfterRotate();
983
- }
984
- flipAfterRotate() {
985
- const flippedH = this.transform.flipH;
986
- const flippedV = this.transform.flipV;
987
- this.transform = {
988
- ...this.transform,
989
- flipH: flippedV,
990
- flipV: flippedH
991
- };
992
- }
993
- flipHorizontal() {
994
- this.transform = {
995
- ...this.transform,
996
- flipH: !this.transform.flipH
997
- };
998
- }
999
- flipVertical() {
1000
- this.transform = {
1001
- ...this.transform,
1002
- flipV: !this.transform.flipV
1003
- };
1004
- }
1005
- //#endregion
1006
- /**
1007
- * Annulla la selezione del file, svuotando l'input e resettando tutte le proprietà dell'IAttachmentDTO
1008
- */
1009
- abortFile() {
1010
- if (this.imageInput)
1011
- this.imageInput.nativeElement.value = "";
1012
- this.selectedFile = null;
1013
- this.selectedFiles = null;
1014
- this.showCropImage = false;
1015
- this.newAttachment.IsImage = false;
1016
- this.newAttachment.FileDataBase64 = null;
1017
- this.newAttachment.FileName = null;
1018
- this.newAttachment.FileExtension = null;
1019
- this.newAttachment.FileContentType = null;
1020
- this.newMultipleAttachments = new Array();
1021
- this.customHeight = null;
1022
- this.customWidth = null;
1023
- this.originalHeight = null;
1024
- this.originalWidth = null;
1025
- this.dialogRefCropImage.close();
1026
- this.restoreOriginalDimensions();
1027
- }
1028
- //#endregion
1029
- fileDropped(event) {
1030
- event.preventDefault();
1031
- event.stopPropagation();
1032
- this.dragOver = false;
1033
- const files = event.dataTransfer?.files;
1034
- if (files && files.length > 0) {
1035
- this.onFileAdded({ target: { files: files } });
1036
- }
1037
- }
1038
- // Se il caricamento del file dropbox va a buon fine, la funzione di callback restituisce un array di oggetti.
1039
- // Viene poi fatta una XMLHttpRequest con responseType 'blob' per convertire il primo elemento della response in un Blob.
1040
- chooseDropboxFile() {
1041
- if (this.isDisabled)
1042
- return;
1043
- var options = {
1044
- success: (files) => {
1045
- const xhr = new XMLHttpRequest();
1046
- xhr.open("GET", files[0].link);
1047
- xhr.setRequestHeader("Authorization", `Bearer ${AttachmentHelperService.dropboxCredentials.accessToken}`);
1048
- xhr.responseType = "blob";
1049
- xhr.onload = () => {
1050
- const blob = xhr.response;
1051
- const file = new File([blob], files[0].name, { type: blob.type });
1052
- let filesAdded = [file];
1053
- this.onFileAdded(filesAdded, true);
1054
- };
1055
- xhr.send();
1056
- },
1057
- linkType: "direct",
1058
- multiselect: false,
1059
- extensions: [".jpg", ".png", ".pdf", ".doc", ".docx", ".txt"]
1060
- };
1061
- Dropbox.choose(options);
1062
- }
1063
- // Workaround dropzone: disabilito il click degli elementi inclusi nella dropzone per evitare di cliccare due volte
1064
- onSelectFile(event, fileInput) {
1065
- if (event.target.tagName === "BUTTON" ||
1066
- event.target.tagName === "INPUT" ||
1067
- this.addingLinkMode == true) {
1068
- return;
1069
- }
1070
- fileInput.click();
1071
- }
1072
- /**
1073
- * Apre il dialogo per l'inserimento del link.
1074
- */
1075
- switchToAddingLinkMode() {
1076
- if (this.isDisabled)
1077
- return;
1078
- this.newAttachmentForm = this.formBuilder.group({
1079
- fileName: [''],
1080
- filePath: ['', [Validators.required, Validators.pattern('https?://.+')]]
1081
- });
1082
- const dialogRef = this.dialog.open(this.addingLinkTemplate, {
1083
- width: '500px',
1084
- panelClass: 'eqp-attachments-dialog'
1085
- });
1086
- dialogRef.afterClosed().subscribe(result => {
1087
- if (result) {
1088
- // Crea l'oggetto per il nuovo link dai dati del form
1089
- const newLinkObject = {
1090
- ID: 0,
1091
- AttachmentType: AttachmentType.LINK,
1092
- FileName: result.fileName,
1093
- FilePath: result.filePath,
1094
- IsImage: false
1095
- };
1096
- this.newAttachment = newLinkObject;
1097
- this.newMultipleAttachments = [newLinkObject];
1098
- this.confirmAddAttachment();
1099
- }
1100
- });
1101
- }
1102
- // Metodo per ottenere le classi CSS dinamiche
1103
- getCardClass(att) {
1104
- return {
1105
- 'file-preview': true,
1106
- 'uploading': !!att.isUploading,
1107
- 'card-small': this.cardSize === 'small',
1108
- 'card-medium': this.cardSize === 'medium',
1109
- 'card-large': this.cardSize === 'large',
1110
- };
1111
- }
1112
- // Questa funzione ora si applica al contenitore, non alla singola card.
1113
- getPreviewsContainerStyle() {
1114
- let minWidth = '200px'; // Dimensione di default per 'medium'
1115
- if (this.cardSize === 'small') {
1116
- minWidth = '140px';
1117
- }
1118
- else if (this.cardSize === 'large') {
1119
- minWidth = '280px';
1120
- }
1121
- else if (this.cardSize === 'custom') {
1122
- minWidth = `${this.customCardWidthPx}px`;
1123
- }
1124
- return { '--card-min-width': minWidth };
1125
- }
1126
- handlePrimaryAction(attachment) {
1127
- // Se il file può essere visualizzato in anteprima, apri il dialog
1128
- if (this.canBePreviewed(attachment)) {
1129
- this.openPreviewDialog(attachment);
1130
- }
1131
- // Altrimenti, esegui l'azione di default (download per file, apri per link)
1132
- else {
1133
- this.viewAttachment(attachment);
1134
- }
1135
- }
1136
- /**
1137
- * Determines if an attachment can be previewed in the dialog.
1138
- * @param att The attachment to check.
1139
- * @returns `true` if a preview is available, otherwise `false`.
1140
- */
1141
- canBePreviewed(att) {
1142
- if (!att) {
1143
- return false;
1144
- }
1145
- // Case 1: It's an image with Base64 data.
1146
- const isPreviewableImage = att.IsImage && !!att.FileDataBase64;
1147
- // Case 2: It's a PDF with Base64 data.
1148
- const isPreviewablePdf = att.FileContentType === 'application/pdf' && !!att.FileDataBase64;
1149
- // Case 3: It's a remote document with a URL (for Google Viewer).
1150
- const isRemoteDocument = !att.IsImage && !!att.FilePath && !!this.productionBaseUrl;
1151
- //Case 4: Video - È un video e abbiamo il file binario salvato in LargeFile
1152
- const isPreviewableVideo = att.FileContentType?.startsWith('video/') && !!att.LargeFile;
1153
- // A preview is possible if any of these conditions are true.
1154
- return isPreviewableImage || isPreviewablePdf || isRemoteDocument || isPreviewableVideo;
1155
- }
1156
- isColumnHidden(col) {
1157
- // 1) hiddenColumns
1158
- if (this.hiddenColumns?.includes(col.key))
1159
- return true;
1160
- // 2) hidden definito sulla colonna (boolean o funzione senza args)
1161
- if (typeof col.hidden === 'function')
1162
- return !!col.hidden();
1163
- return !!col.hidden;
1164
- }
1165
- isActionHidden(action, att) {
1166
- if (this.hiddenActions?.includes(action.key))
1167
- return true;
1168
- if (this.actionHiddenFn?.(action.key, att))
1169
- return true;
1170
- if (typeof action.hidden === 'function')
1171
- return !!action.hidden(att);
1172
- return !!action.hidden;
1173
- }
1174
- isActionDisabled(action, att) {
1175
- if (this.actionDisabledFn?.(action.key, att))
1176
- return true;
1177
- if (typeof action.disabled === 'function')
1178
- return !!action.disabled(att);
1179
- return !!action.disabled;
1180
- }
1181
- isDeleteHidden(att) {
1182
- return this.actionHiddenFn?.('delete', att) || this.hiddenActions?.includes('delete');
1183
- }
1184
- isDeleteDisabled(att) {
1185
- return this.disableAction || !!this.actionDisabledFn?.('delete', att);
1186
- }
1187
- isPrimaryActionHidden(att) {
1188
- if (this.hiddenActions?.includes('download') || this.hiddenActions?.includes('preview') || this.hiddenActions?.includes('primaryAction'))
1189
- return true;
1190
- if (this.hiddenColumns?.includes('download') || this.hiddenColumns?.includes('preview') || this.hiddenColumns?.includes('primaryAction'))
1191
- return true;
1192
- if (this.actionHiddenFn?.('primaryAction', att) || this.actionHiddenFn?.('download', att) || this.actionHiddenFn?.('preview', att))
1193
- return true;
1194
- return false;
1195
- }
1196
- isPrimaryActionDisabled(att) {
1197
- if (this.actionDisabledFn?.('primaryAction', att) || this.actionDisabledFn?.('download', att) || this.actionDisabledFn?.('preview', att))
1198
- return true;
1199
- return false;
1200
- }
1201
- /**
1202
- * Unisce le colonne di default con quelle custom e le ordina.
1203
- */
1204
- setupTableColumns() {
1205
- // Definiamo le colonne standard con una posizione
1206
- const defaultFileColumn = {
1207
- key: 'file',
1208
- display: 'File',
1209
- type: TypeAttachmentColumn.TEMPLATE,
1210
- externalTemplate: this.defaultFileTemplate,
1211
- styles: { flex: '1 1 0%' },
1212
- position: 10
1213
- };
1214
- const defaultActionsColumn = {
1215
- key: 'actions',
1216
- display: 'Azioni',
1217
- type: TypeAttachmentColumn.TEMPLATE,
1218
- externalTemplate: this.defaultActionsTemplate,
1219
- position: 100,
1220
- class: 'col-actions',
1221
- styles: { flex: '0 0 150px' }
1222
- };
1223
- const processedCustomColumns = this._customColumns.map(col => {
1224
- // Flex di default
1225
- if (!col.styles || !col.styles.flex) {
1226
- return {
1227
- ...col,
1228
- styles: { ...col.styles, flex: '1 1 0%' }
1229
- };
1230
- }
1231
- return col;
1232
- });
1233
- const allColumns = [
1234
- defaultFileColumn,
1235
- defaultActionsColumn,
1236
- ...processedCustomColumns
1237
- ];
1238
- // Ordiniamo l'array finale in base alla proprietà 'position'
1239
- this._tableColumns = allColumns.filter(col => !this.isColumnHidden(col))
1240
- .sort((a, b) => {
1241
- const posA = a.position || 99;
1242
- const posB = b.position || 99;
1243
- return posA - posB;
1244
- });
1245
- }
1246
- setupMenuActions() {
1247
- const defaultPreviewAction = {
1248
- key: 'preview',
1249
- icon: 'visibility',
1250
- name: 'Anteprima',
1251
- fn: (att) => this.openPreviewDialog(att),
1252
- disabled: (att) => !this.canBePreviewed(att),
1253
- position: 10
1254
- };
1255
- const defaultDeleteAction = {
1256
- key: 'delete',
1257
- icon: 'delete',
1258
- name: 'Elimina',
1259
- fn: (att) => this.deleteAttachment(att),
1260
- disabled: () => this.disableAction,
1261
- position: 100
1262
- };
1263
- const allActions = [
1264
- defaultPreviewAction,
1265
- defaultDeleteAction,
1266
- ...this._customMenuActions
1267
- ];
1268
- // Ordiniamo l'array finale in base alla proprietà 'position'
1269
- this._sortedMenuActions = allActions.sort((a, b) => {
1270
- const posA = a.position || 99;
1271
- const posB = b.position || 99;
1272
- return posA - posB;
1273
- });
1274
- }
1275
- generateVideoThumbnail(file) {
1276
- return new Promise((resolve, reject) => {
1277
- const video = document.createElement('video');
1278
- const canvas = document.createElement('canvas');
1279
- const context = canvas.getContext('2d');
1280
- // Crea un URL temporaneo per il file video
1281
- const videoUrl = URL.createObjectURL(file);
1282
- video.src = videoUrl;
1283
- video.preload = 'metadata';
1284
- video.muted = true;
1285
- video.playsInline = true;
1286
- video.onloadedmetadata = () => {
1287
- // Vai al secondo 1 (per evitare il fotogramma nero iniziale)
1288
- video.currentTime = 1;
1289
- };
1290
- video.onseeked = () => {
1291
- // Imposta le dimensioni del canvas uguali al video
1292
- canvas.width = video.videoWidth;
1293
- canvas.height = video.videoHeight;
1294
- // Disegna il fotogramma sul canvas
1295
- context.drawImage(video, 0, 0, canvas.width, canvas.height);
1296
- // Estrai il Base64 (qualità 0.7 per risparmiare spazio)
1297
- const thumbnail = canvas.toDataURL('image/jpeg', 0.7);
1298
- // Pulisci la memoria
1299
- URL.revokeObjectURL(videoUrl);
1300
- resolve(thumbnail.split(',')[1]); // Restituiamo solo la parte Base64
1301
- };
1302
- video.onerror = (err) => {
1303
- URL.revokeObjectURL(videoUrl);
1304
- reject(err);
1305
- };
1306
- });
1307
- }
1308
- async compressVideoApi(file, config) {
1309
- // Prepariamo il FormData per inviare il file binario e i parametri di configurazione
1310
- const formData = new FormData();
1311
- formData.append('video', file);
1312
- formData.append('maxWidth', String(config.maxWidth ?? 1280));
1313
- if (config.crf != null)
1314
- formData.append('crf', String(config.crf));
1315
- if (config.preset)
1316
- formData.append('preset', config.preset);
1317
- if (config.crf == null) {
1318
- formData.append('bitrate', String(config.bitrate ?? 2500000));
1319
- }
1320
- if (config.maxFps != null)
1321
- formData.append('maxFps', String(config.maxFps));
1322
- if (config.audioBitrate != null)
1323
- formData.append('audioBitrate', String(config.audioBitrate));
1324
- // URL della tua API C#
1325
- const apiUrl = 'https://tuo-servizio-api.it/api/video/compress';
1326
- try {
1327
- // Effettuiamo la chiamata. Usiamo 'fetch' per semplicità o HttpClient di Angular
1328
- const response = await fetch(apiUrl, {
1329
- method: 'POST',
1330
- body: formData,
1331
- // Nota: Non impostare Content-Type, il browser lo farà correttamente includendo il boundary
1332
- });
1333
- if (!response.ok) {
1334
- throw new Error(`Errore server: ${response.statusText}`);
1335
- }
1336
- // Riceviamo il file compresso come Blob
1337
- return await response.blob();
1338
- }
1339
- catch (error) {
1340
- console.error("Errore durante la compressione remota:", error);
1341
- throw error;
1342
- }
1343
- }
1344
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EqpAttachmentsComponent, deps: [{ token: i1.MatDialog }, { token: i2.FormBuilder }, { token: i3.DomSanitizer }, { token: i4.HttpClient }, { token: i5.EqpAttachmentService }], target: i0.ɵɵFactoryTarget.Component });
1345
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EqpAttachmentsComponent, selector: "eqp-attachments", inputs: { disableAction: "disableAction", showHeader: "showHeader", attachmentsList: "attachmentsList", singleAttachment: "singleAttachment", showMatCard: "showMatCard", multipleAttachment: "multipleAttachment", loadMultipleFiles: "loadMultipleFiles", emptyTableMessage: "emptyTableMessage", allowOnlyImages: "allowOnlyImages", acceptedFileTypes: "acceptedFileTypes", isDisabled: "isDisabled", showInlinePreview: "showInlinePreview", getAttachmentEndpoint: "getAttachmentEndpoint", productionBaseUrl: "productionBaseUrl", compressionOptions: "compressionOptions", allowedTypes: "allowedTypes", isEqpTableMultiLanguage: "isEqpTableMultiLanguage", tablePaginatorVisible: "tablePaginatorVisible", isTableSearcheable: "isTableSearcheable", tablePaginatorSize: "tablePaginatorSize", separatedUploadButtons: "separatedUploadButtons", showPreview: "showPreview", singleAttachmentDragAndDrop: "singleAttachmentDragAndDrop", cropOptions: "cropOptions", cropDialogClass: "cropDialogClass", maxFileSizeMB: "maxFileSizeMB", cardSize: "cardSize", customCardWidthPx: "customCardWidthPx", customCardHeightPx: "customCardHeightPx", layout: "layout", 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", deleteDialogTitle: "deleteDialogTitle", deleteDialogMessage: "deleteDialogMessage", noImageSelectedErrorMessage: "noImageSelectedErrorMessage", wrongTypeSelectedErrorMessage: "wrongTypeSelectedErrorMessage", videoPreviewErrorMessage: "videoPreviewErrorMessage", audioPreviewErrorMessage: ["videoPreviewErrorMessage", "audioPreviewErrorMessage"], flipHorinzontalLabel: "flipHorinzontalLabel", flipVerticalLabel: "flipVerticalLabel", rotateRightLabel: "rotateRightLabel", rotateLeftLabel: "rotateLeftLabel", base64LimitMB: "base64LimitMB", uploadTitle: "uploadTitle", uploadSubtitle: "uploadSubtitle", dropHereLabel: "dropHereLabel", supportedFormatsLabel: "supportedFormatsLabel", browseFilesLabel: "browseFilesLabel", uploadSummaryLabel: "uploadSummaryLabel", filesLabel: "filesLabel", totalSizeLabel: "totalSizeLabel", emptyStateLabel: "emptyStateLabel", addedSuccessfullyLabel: "addedSuccessfullyLabel", removedLabel: "removedLabel", chooseView: "chooseView", showSummary: "showSummary", viewMode: "viewMode", showUploadTitle: "showUploadTitle", showDropArea: "showDropArea", hiddenColumns: "hiddenColumns", hiddenActions: "hiddenActions", showActionButtons: "showActionButtons", enableImageCrop: "enableImageCrop", actionHiddenFn: "actionHiddenFn", actionDisabledFn: "actionDisabledFn", videoCompression: "videoCompression", customMenuActions: "customMenuActions", customColumns: "customColumns" }, 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: "addingLinkTemplate", first: true, predicate: ["addingLinkTemplate"], descendants: true }, { propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true }, { propertyName: "inlinePreviewTemplate", first: true, predicate: ["inlinePreviewTemplate"], descendants: true, static: true }, { propertyName: "dialogPreview", first: true, predicate: ["dialogPreview"], descendants: true, static: true }, { propertyName: "defaultFileTemplate", first: true, predicate: ["defaultFileTemplate"], descendants: true, static: true }, { propertyName: "defaultActionsTemplate", first: true, predicate: ["defaultActionsTemplate"], descendants: true, static: true }], ngImport: i0, template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n@if(showUploadTitle == true || chooseView == true){\r\n<div class=\"header\">\r\n @if(showUploadTitle == true){\r\n <h4>{{ uploadTitle }}</h4>\r\n }\r\n @if(chooseView == true){\r\n <mat-button-toggle-group [value]=\"viewMode\" (change)=\"setViewMode($event.value)\"\r\n aria-label=\"Modalit\u00E0 di visualizzazione\">\r\n <mat-button-toggle value=\"card\"><mat-icon>grid_view</mat-icon></mat-button-toggle>\r\n <mat-button-toggle value=\"table\"><mat-icon>view_list</mat-icon></mat-button-toggle>\r\n </mat-button-toggle-group>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione singolo -->\r\n@if (multipleAttachment != true) {\r\n@if (!singleAttachmentDragAndDrop) {\r\n@if (!addingLinkMode) {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addAttachmentButton\"></ng-container>\r\n</div>\r\n} @else {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addingLinkTemplate\"></ng-container>\r\n</div>\r\n}\r\n} @else {\r\n<input #fileInput id=\"file_attachment\" name=\"file_attachment\" type=\"file\" hidden (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (allowedTypes && allowedTypes.includes(1) && (!attachmentsList || attachmentsList.length == 0 ||\r\n(attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n\r\n@if (showDropArea == true) {\r\n<!-- FULL -->\r\n@if (layout === 'full') {\r\n\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n <div class=\"secondary-action\">\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n @if (allowedTypes.includes(2) && allowedTypes.includes(3)) {\r\n <a class=\"secondary-action-link\" [matMenuTriggerFor]=\"isDisabled ? null : linkMenu\"\r\n [class.disabled-link]=\"isDisabled\" (click)=\"$event.stopPropagation()\">\r\n o aggiungi da web\r\n </a>\r\n <mat-menu #linkMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"switchToAddingLinkMode()\">\r\n <mat-icon>link</mat-icon>\r\n <span>Aggiungi da link</span>\r\n </button>\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\">\r\n <mat-icon>cloud_queue</mat-icon>\r\n <span>Carica da Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @else if (allowedTypes.includes(2)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">\r\n aggiungi un link\r\n </a>\r\n }\r\n\r\n @else if (allowedTypes.includes(3)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); chooseDropboxFile()\">\r\n carica da Dropbox\r\n </a>\r\n }\r\n }\r\n </div>\r\n</div>\r\n}@else {\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button color=\"primary\" [disabled]=\"isDisabled\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n}\r\n}\r\n\r\n<!-- Azioni singolo elemento (come prima) -->\r\n<div class=\"text-center\">\r\n @if (attachmentsList && attachmentsList.length > 0 && attachmentsList[0] && showActionButtons == true) {\r\n @if (!isPrimaryActionHidden(attachmentsList[0])) {\r\n <button class=\"mb-2 me-2 eqp-attachments-download-btn\" (click)=\"viewAttachment(attachmentsList[0])\" type=\"button\"\r\n [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button color=\"primary\">\r\n @if (attachmentsList[0].AttachmentType == AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n }\r\n\r\n @if (!isPrimaryActionHidden(attachmentsList[0]) && showPreview && (!attachmentsList[0].FileContentType || (!attachmentsList[0].FileContentType.startsWith('video')\r\n && !attachmentsList[0].FileContentType.startsWith('audio'))) && attachmentsList[0].IsImage == true) {\r\n <button class=\"mb-2 me-2 eqp-attachments-preview-btn\" (click)=\"openPreviewDialog(attachmentsList[0])\" type=\"button\"\r\n [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button color=\"primary\">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n }\r\n\r\n <button [disabled]=\"disableAction\" class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\" type=\"button\" mat-raised-button [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione multipla -->\r\n@if (multipleAttachment == true && showDropArea == true) {\r\n<input #fileInput id=\"file_attachment_multi\" name=\"file_attachment_multi\" type=\"file\" hidden\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (layout === 'full') {\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n @if (allowedTypes.includes(2)) {\r\n <div class=\"secondary-action-link\">\r\n o <a (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">aggiungi un link</a>\r\n </div>\r\n }\r\n</div>\r\n}@else{\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button [disabled]=\"isDisabled\" color=\"primary\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n\r\n@if (attachmentsList?.length > 0 && showSummary) {\r\n<div class=\"upload-stats\">\r\n\r\n <div class=\"stats-info\">\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ attachmentsList?.length }}</div>\r\n <div class=\"stat-label\">{{ filesLabel }}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ totalSizeFormatted }}</div>\r\n <div class=\"stat-label\">{{ totalSizeLabel }}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"progressPercent\"></div>\r\n </div>\r\n\r\n</div>\r\n} @else if(attachmentsList?.length == 0){\r\n<div class=\"empty-state\">{{ emptyStateLabel }}</div>\r\n}\r\n\r\n<!-- Griglia anteprime card (vale per singolo e multiplo) -->\r\n@if (viewMode === 'card') {\r\n\r\n<div class=\"file-previews\" [ngStyle]=\"getPreviewsContainerStyle()\">\r\n @for (att of attachmentsList; track att.ID) {\r\n <div [ngClass]=\"getCardClass(att)\">\r\n <div class=\"preview-img-container\" (click)=\"!att.isUploading && !isPrimaryActionHidden(att) && !isPrimaryActionDisabled(att) && handlePrimaryAction(att)\">\r\n\r\n @if (att.IsImage || att.FileThumbnailBase64) {\r\n <img class=\"preview-img\" [src]=\"'data:image/jpeg;base64,' + (att.FileThumbnailBase64 || att.FileDataBase64)\"\r\n [alt]=\"att.FileName\" />\r\n } @else {\r\n <div class=\"file-icon\"><i [ngClass]=\"getAttachmentIcon(att)\"></i></div>\r\n }\r\n\r\n @if (!isPrimaryActionHidden(att)) {\r\n <div class=\"preview-action-overlay\">\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n <mat-icon>play_arrow</mat-icon>\r\n }\r\n @else if (att.IsImage && canBePreviewed(att)) {\r\n <mat-icon>visibility</mat-icon>\r\n }\r\n @else if (att.FileContentType === 'application/pdf' && canBePreviewed(att)) {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n @else if (att.AttachmentType === AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n }\r\n @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n </div>\r\n }\r\n\r\n </div>\r\n\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"att.FileName\">{{ att.FileName }}</div>\r\n </div>\r\n\r\n @if(!isDeleteHidden(att)){\r\n <button mat-icon-button class=\"remove-btn\" (click)=\"deleteAttachment(att)\"\r\n [disabled]=\"att.isUploading || isDeleteDisabled(att)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (att.isUploading) {\r\n <div class=\"upload-spinner\"></div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n} @else if(viewMode === 'table' && attachmentsList?.length > 0) {\r\n\r\n\r\n<div class=\"table-view-container\">\r\n\r\n <div class=\"table-header\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n {{ col.display }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @for (att of attachmentsList; track att.ID) {\r\n <div class=\"table-row\">\r\n\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n\r\n @switch (col.type) {\r\n\r\n @case ('template') {\r\n <div class=\"template-wrapper\">\r\n <ng-container [ngTemplateOutlet]=\"col.externalTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: att }\"></ng-container>\r\n </div>\r\n }\r\n @case ('date') {\r\n <span class=\"metadata-value\">{{ att[col.key] | date:'dd/MM/yyyy' }}</span>\r\n }\r\n @default {\r\n <span class=\"metadata-value\">{{ att[col.key] }}</span>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Notifica toast -->\r\n<div class=\"upload-notification\" [class.show]=\"toast?.visible\" [class.success]=\"toast?.type === 'success'\"\r\n [class.error]=\"toast?.type === 'error'\">\r\n <span>{{ toast?.text }}</span>\r\n <div class=\"notification-progress\"></div>\r\n</div>\r\n\r\n<ng-template #defaultFileTemplate let-att>\r\n <i class=\"file-icon-small\" [ngClass]=\"getAttachmentIcon(att)\"></i>\r\n <div class=\"file-info-text\">\r\n <span class=\"file-name-table\">{{ att.FileName }}</span>\r\n <span class=\"file-type-table\">{{ att.FileExtension || 'Link' }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultActionsTemplate let-att>\r\n @if (!isPrimaryActionHidden(att)) {\r\n <button mat-icon-button (click)=\"handlePrimaryAction(att)\" [disabled]=\"isPrimaryActionDisabled(att)\"\r\n [matTooltip]=\"att.FileContentType?.startsWith('video/') ? 'Riproduci video' : 'Visualizza/Scarica'\">\r\n\r\n <mat-icon>\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n play_arrow\r\n } @else {\r\n {{ att.AttachmentType === AttachmentType.FILE ? 'download' : 'open_in_new' }}\r\n }\r\n </mat-icon>\r\n </button>\r\n }\r\n\r\n @if (!hiddenActions.includes('actionsMenu')) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"actionsMenu\" matTooltip=\"Altre opzioni\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n }\r\n\r\n <mat-menu #actionsMenu=\"matMenu\">\r\n @for (action of _sortedMenuActions; track action.name) {\r\n @if (!isActionHidden(action, att)) {\r\n <button mat-menu-item (click)=\"action.fn(att)\" [disabled]=\"isActionDisabled(action, att)\">\r\n <mat-icon [color]=\"action.icon === 'delete' ? 'warn' : undefined\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n <span>{{ action.name }}</span>\r\n </button>\r\n }\r\n }\r\n </mat-menu>\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogCropImage>\r\n <div style=\"overflow-x: hidden; display: flex; flex-direction: column; height: 100%; min-height: 0; flex: 1 1 auto;\"\r\n [ngClass]=\"cropDialogClass\">\r\n <!-- @if (showCropImage == true) { -->\r\n <ng-container [ngTemplateOutlet]=\"croppieTemplate\" [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\">\r\n </ng-container>\r\n <!-- } -->\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n @if (row.AttachmentType != AttachmentType.LINK && row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <img [src]=\"'data:image/png;base64,' + (row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64)\" />\r\n </div>\r\n } @else if (row.AttachmentType != AttachmentType.LINK && !row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"modern-dialog-container\"> @if (selectedAttachment) {\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ previewLabel }}</span>\r\n <span class=\"file-t\">{{ selectedAttachment.FileName }}</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"media-viewer-wrapper\">\r\n @if (selectedAttachment.IsImage) {\r\n <img class=\"main-preview-media\"\r\n [src]=\"'data:image/png;base64,' + (selectedAttachment.FileDataBase64 || selectedAttachment.FileThumbnailBase64)\"\r\n [alt]=\"selectedAttachment.FileName\" />\r\n }\r\n @else if (selectedAttachment.FileContentType?.startsWith('video/')) {\r\n <video controls autoplay playsinline class=\"main-preview-media video-player\">\r\n <source [src]=\"selectedAttachment.TrustedUrl\" [type]=\"selectedAttachment.FileContentType\">\r\n Il tuo browser non supporta il video.\r\n </video>\r\n }\r\n @else {\r\n <div class=\"iframe-container\">\r\n <iframe class=\"preview-iframe-modern\" [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n }\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Chiudi</button>\r\n @if (selectedAttachment.AttachmentType !== AttachmentType.LINK) {\r\n <button mat-raised-button color=\"primary\" (click)=\"viewAttachment(selectedAttachment)\" class=\"btn-download\">\r\n <mat-icon>download</mat-icon> <span>{{ downloadLabel }}</span>\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <input #fileInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n @if (allowedTypes && allowedTypes.length == 1 && (multipleAttachment == true || !attachmentsList ||\r\n attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\" [disabled]=\"isDisabled\">\r\n @if (allowedTypes[0] == 1) { <mat-icon>cloud_upload</mat-icon> }\r\n @if (allowedTypes[0] == 2) { <i class=\"fas fa-link\"></i> }\r\n @if (allowedTypes[0] == 3) { <i class=\"fa-brands fa-dropbox\"></i> }\r\n <span style=\"margin-left: 10px\">\r\n {{ allowedTypes[0] == 1 ? (addButtonLabel + \" file\") : allowedTypes[0] == 2 ? (addButtonLabel + \" link\") :\r\n uploadWithDropboxLabel }}\r\n </span>\r\n </button>\r\n }\r\n\r\n @if (!separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\" [disabled]=\"isDisabled\">\r\n @if (multipleAttachment != true) { <mat-icon>cloud_upload</mat-icon> } @else { <mat-icon>add</mat-icon> }\r\n <span style=\"margin-left: 0px\">{{ addButtonLabel }}</span>\r\n </button>\r\n\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(1)) {\r\n <button mat-menu-item (click)=\"imageInput.click()\" 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 }\r\n @if (allowedTypes.includes(2)) {\r\n <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"switchToAddingLinkMode()\" 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 }\r\n @if (allowedTypes.includes(3)) {\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\" 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 }\r\n </mat-menu>\r\n }\r\n\r\n @if (separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <div class=\"btn-group\">\r\n @if (allowedTypes.includes(1)) {\r\n <button (click)=\"imageInput.click()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(2)) {\r\n <button (click)=\"switchToAddingLinkMode()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(3)) {\r\n <button (click)=\"chooseDropboxFile()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" 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 }\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ cropLabel }}</span>\r\n <span class=\"file-t\">Regola le dimensioni e l'orientamento</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button type=\"button\" (click)=\"abortFile()\" class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"crop-toolbar\">\r\n @if (cropOptions.includes(1)) {\r\n <button mat-icon-button [matTooltip]=\"rotateLeftLabel\"\r\n (click)=\"rotateLeft()\"><mat-icon>rotate_left</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"rotateRightLabel\"\r\n (click)=\"rotateRight()\"><mat-icon>rotate_right</mat-icon></button>\r\n }\r\n @if (cropOptions.includes(2)) {\r\n <button mat-icon-button [matTooltip]=\"flipHorinzontalLabel\"\r\n (click)=\"flipHorizontal()\"><mat-icon>flip_horizontal</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"flipVerticalLabel\"\r\n (click)=\"flipVertical()\"><mat-icon>flip_vertical</mat-icon></button>\r\n }\r\n <button mat-icon-button matTooltip=\"Reset\"\r\n (click)=\"restoreOriginalDimensions()\"><mat-icon>replay</mat-icon></button>\r\n </div>\r\n\r\n <div class=\"media-viewer-wrapper\">\r\n <div class=\"crop-container-modern\">\r\n <image-cropper [imageFile]=\"selectedFile\" [maintainAspectRatio]=\"false\" [canvasRotation]=\"canvasRotation\"\r\n [transform]=\"transform\" format=\"png\" (imageCropped)=\"imageCropped($event)\" [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\" [output]=\"'base64'\" [containWithinAspectRatio]=\"true\" [onlyScaleDown]=\"true\"\r\n [alignImage]=\"'center'\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button (click)=\"abortFile()\" class=\"btn-close\">{{ abortLabel }}</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"confirmAddAttachment()\" class=\"btn-download\">\r\n <mat-icon>check</mat-icon> {{ confirmLabel }}\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"type-icon-wrapper\">\r\n <mat-icon>link</mat-icon>\r\n </div>\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">Aggiungi un link</span>\r\n <span class=\"file-t\">Inserisci l'URL della risorsa web</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"add-link-modern-content\">\r\n <form [formGroup]=\"newAttachmentForm\" class=\"add-link-form\">\r\n <mat-form-field appearance=\"outline\" class=\"w-100 mt-3\">\r\n <mat-label>URL del collegamento</mat-label>\r\n <input matInput formControlName=\"filePath\" placeholder=\"https://...\" required>\r\n <mat-icon matSuffix>language</mat-icon>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>Titolo (opzionale)</mat-label>\r\n <input matInput formControlName=\"fileName\" placeholder=\"Es. Documento Progetto\">\r\n <mat-icon matSuffix>title</mat-icon>\r\n </mat-form-field>\r\n </form>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Annulla</button>\r\n <button mat-raised-button color=\"primary\" [mat-dialog-close]=\"newAttachmentForm.value\"\r\n [disabled]=\"newAttachmentForm.invalid\" class=\"btn-download\">\r\n <mat-icon>add</mat-icon> Aggiungi\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{--primary-color: #6a5af9;--primary-color-dark: #5441f8;--success-color: #1ce593;--error-color: #ff5b5b;--background-light: #f7f9fc;--background-card: rgba(255, 255, 255, .7);--text-color: #1e293b;--text-color-light: #64748b;--border-color: rgba(203, 213, 225, .5);--shadow-color: rgba(99, 102, 241, .2);--border-radius: 16px;--transition-speed: .3s}@keyframes fadeIn{0%{opacity:0;transform:translateY(15px)}to{opacity:1;transform:translateY(0)}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--primary-color)}70%{box-shadow:0 0 0 10px #6a5af900}to{box-shadow:0 0 #6a5af900}}.container{width:100%;max-width:700px;margin:2rem auto;font-family:Inter,sans-serif}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border-color)}.header h1{color:var(--text-color);font-size:1.8rem;font-weight:700;margin:0}.dropbox{width:100%;border:2px dashed var(--border-color);border-radius:var(--border-radius);padding:2.5rem;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all var(--transition-speed) ease}.dropbox:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color);border-color:var(--primary-color)}.dropbox.dragover{border-style:solid;border-color:var(--primary-color);transform:scale(1.02);box-shadow:0 0 25px var(--shadow-color);animation:pulse 1.5s infinite}.dropbox .dropbox-icon{font-size:3.5rem;color:var(--primary-color)}.dropbox .dropbox-text{font-size:1.1rem;font-weight:600;color:var(--text-color);margin-top:1rem}.dropbox .dropbox-subtext{color:var(--text-color-light);margin-top:.5rem}.dropbox .browse-btn{margin-top:1.5rem;padding:.75rem 1.5rem;background-color:var(--primary-color);color:#fff;border:none;border-radius:10px;font-weight:600;transition:all var(--transition-speed) ease}.dropbox .browse-btn:hover{background-color:var(--primary-color-dark);transform:translateY(-2px)}.file-previews{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1.5rem;margin-top:2rem}.file-previews{display:grid;gap:16px;padding:16px;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width, 200px),1fr))}.file-preview{background-color:var(--background-card);border-radius:var(--border-radius);box-shadow:0 4px 15px #0000000d;border:1px solid var(--border-color);overflow:hidden;display:flex;flex-direction:column;position:relative;opacity:0;animation:fadeIn .5s ease-out forwards;transition:transform var(--transition-speed) ease,box-shadow var(--transition-speed) ease}.file-preview.uploading{cursor:wait}.file-preview.uploading .preview-img-container:after{content:\"\";position:absolute;inset:0;background:#ffffffb3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);pointer-events:none}.file-preview .preview-action-overlay{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;background-color:#0006;color:#fff;opacity:1;transition:opacity .3s ease}.file-preview .preview-action-overlay .mat-icon{font-size:36px;width:36px;height:36px}.file-preview .remove-btn{position:absolute;top:8px;right:8px;z-index:2;background-color:#0000004d;color:#fff;width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;transition:all var(--transition-speed) ease}.file-preview .remove-btn:hover{background-color:#ff5b5b}.file-preview .remove-btn .mat-icon{font-size:18px}@media (hover: hover){.file-preview .remove-btn .file-preview .preview-action-overlay{opacity:0}.file-preview .remove-btn .file-preview:hover .preview-action-overlay,.file-preview .remove-btn .file-preview:hover .remove-btn{opacity:1}.file-preview .remove-btn .file-preview .remove-btn{opacity:0}}@media (hover: hover) and (min-width: 769px){.file-preview .remove-btn{opacity:0;transform:scale(.8)}.file-preview:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color)}.file-preview:hover .remove-btn{opacity:1;transform:scale(1)}}.file-preview .preview-img-container{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;cursor:pointer;background-color:#f0f2f5}.file-preview .preview-img{width:100%;height:100%;object-fit:cover}.file-preview .file-icon{font-size:4rem;color:var(--primary-color)}.file-preview .file-info{padding:12px;border-top:1px solid var(--border-color);flex-grow:1;display:flex;align-items:center}.file-preview .file-name{font-weight:600;font-size:.9rem;color:var(--text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-preview .upload-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border:4px solid rgba(0,0,0,.1);border-left-color:var(--primary-color);border-radius:50%;animation:spin 1s linear infinite;pointer-events:none}.file-preview.card-small{width:140px}.file-preview.card-small .preview-img-container{height:80px}.file-preview.card-small .file-info{padding:8px}.file-preview.card-small .file-name{font-size:.8rem}.file-preview.card-small .file-icon{font-size:3rem}.file-preview.card-small .remove-btn{width:28px;height:28px}.file-preview.card-small .remove-btn .mat-icon{font-size:16px}.file-preview.card-large{width:280px}.file-preview.card-large .preview-img-container{height:180px}.file-preview.card-large .file-info{padding:16px}.file-preview.card-large .file-name{font-size:1rem}.file-preview.card-large .file-icon{font-size:5rem}.file-preview.card-large .remove-btn{width:36px;height:36px}.file-preview.card-large .remove-btn .mat-icon{font-size:20px}.file-preview[style*=--eqp-card-width]{width:var(--eqp-card-width)}.file-preview[style*=--eqp-card-width] .preview-img-container{height:calc(var(--eqp-card-width) * .65)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}.upload-stats{background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--border-color);border-radius:var(--border-radius);padding:1.5rem;margin-top:2rem;animation:fadeIn .5s ease-out}.upload-stats .stats-info{display:flex;justify-content:space-around}.upload-stats .progress-bar{height:10px;background-color:var(--border-color);border-radius:5px;overflow:hidden;margin-top:1rem}.upload-stats .progress-fill{height:100%;background:linear-gradient(90deg,var(--primary-color),var(--success-color));transition:width var(--transition-speed) ease-out;border-radius:5px}.upload-notification{position:fixed;bottom:20px;left:50%;transform:translate(-50%,100px);padding:1rem 1.5rem;border-radius:var(--border-radius);color:#fff;font-weight:600;box-shadow:0 10px 30px #0003;transition:transform var(--transition-speed) cubic-bezier(.175,.885,.32,1.275)}.upload-notification.show{transform:translate(-50%)}.upload-notification.success{background-color:var(--success-color)}.upload-notification.error{background-color:var(--error-color)}::ng-deep .cdk-overlay-pane.eqp-crop-dialog{transform:translateY(-4vh)}@media (max-width: 600px){::ng-deep .cdk-overlay-pane.crop-dialog{width:auto!important}}::ng-deep .eqp-attachments-dialog{display:flex!important;flex-direction:column!important}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container .mdc-dialog__surface{border-radius:20px!important;padding:0!important;overflow:hidden!important;width:fit-content!important;min-width:350px!important;max-width:95vw!important;max-height:90vh!important;margin:0 auto;background-color:#fff!important;display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden!important}.modern-dialog-container{display:flex;flex-direction:column;width:100%;max-width:100%;flex:1 1 auto;min-height:0;height:100%;max-height:100%;background:#fff;--preview-header-h: 66px;--preview-footer-h: 66px;--preview-padding-y: 30px}.modern-dialog-container .main-preview-media{display:block;max-width:100%;max-height:var(--media-max-h);width:auto;height:auto;object-fit:contain;border-radius:12px;background:#fff;padding:4px;box-shadow:0 10px 30px #00000014}.modern-dialog-container video.main-preview-media{width:min(100%,1100px);background:#000}.modern-dialog-container .iframe-container{width:min(100%,1100px);height:var(--media-max-h);display:flex;width:100%;max-width:1100px}.modern-dialog-container .preview-iframe-modern{width:100%;height:100%;border:0;border-radius:12px;background:#f8fafc}.modern-dialog-container .preview-header{flex:0 0 auto;flex-shrink:0;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;border-bottom:1px solid var(--border-color);background:#f8fafc;z-index:10;width:100%}.modern-dialog-container .preview-header .close-btn{display:inline-flex!important;align-items:center!important;justify-content:center!important;padding:0!important;width:40px!important;height:40px!important}.modern-dialog-container .preview-header .close-btn ::ng-deep mat-icon{display:flex!important;align-items:center!important;justify-content:center!important;margin:0!important;padding:0!important;line-height:1!important}.modern-dialog-container .preview-header .header-info{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex:1 1 auto;min-width:0;text-align:left}.modern-dialog-container .preview-header .header-info .type-icon-wrapper{background:var(--primary-color);color:#fff;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px var(--shadow-color)}.modern-dialog-container .preview-header .header-info .title-group{display:flex;flex-direction:column;align-items:flex-start;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .main-t{font-weight:800;color:var(--text-color);font-size:.95rem;line-height:1.2;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .file-t{font-size:.75rem;color:var(--text-color-light);max-width:250px;overflow:hidden;text-overflow:ellipsis;text-align:left}.modern-dialog-container .preview-content-area{flex:1 1 auto;background:#fff!important;display:flex;flex-direction:column;padding:15px 15px 22px!important;overflow:hidden!important;min-height:0;width:100%;--media-max-h: calc(90vh - var(--preview-header-h) - var(--preview-footer-h) - var(--preview-padding-y))}.modern-dialog-container .preview-content-area .crop-toolbar{flex-shrink:0;z-index:20;background:#0f172a14;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:6px 16px;border-radius:30px;margin:0 auto 15px;display:flex;gap:8px;box-shadow:0 4px 12px #0000000d}.modern-dialog-container .preview-content-area .crop-toolbar button{color:var(--text-color)!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper{flex:1 1 auto;width:100%;height:100%;display:flex;flex-direction:column;align-items:stretch;min-height:0;overflow:hidden}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern{flex:1 1 auto;display:flex;flex-direction:column;justify-content:center;align-items:center;background:transparent;border-radius:12px;padding:0;overflow:hidden;min-height:0;width:100%;height:100%}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern image-cropper{flex:1 1 auto;width:100%;height:100%;max-width:100%!important;max-height:100%!important;display:block;min-height:0}.modern-dialog-container .add-link-modern-content{flex:1;background:#fff;padding:24px!important}.modern-dialog-container .add-link-modern-content .add-link-form{display:flex;flex-direction:column;gap:10px}.modern-dialog-container .preview-actions{flex-shrink:0;padding:12px 24px;background:#f8fafc;border-top:1px solid #e2e8f0;margin:0}.modern-dialog-container .preview-actions .btn-download{border-radius:12px;font-weight:600;box-shadow:0 4px 12px var(--shadow-color)}@media (max-width: 600px){.modern-dialog-container{max-height:95vh}.modern-dialog-container .preview-content-area{padding:10px!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper video.main-preview-media{width:100%!important;max-height:55vh!important;border-radius:4px;box-shadow:none}.modern-dialog-container .preview-content-area .media-viewer-wrapper .iframe-container{height:50vh}.modern-dialog-container .preview-content-area .crop-toolbar{width:calc(100% - 20px);max-width:400px;margin-bottom:10px;padding:4px 8px;gap:4px;overflow-x:auto;justify-content:center;-webkit-overflow-scrolling:touch;scrollbar-width:none}.modern-dialog-container .preview-content-area .crop-toolbar::-webkit-scrollbar{display:none}.modern-dialog-container .preview-content-area .crop-toolbar button{flex-shrink:0;transform:scale(.85);width:40px;height:40px}.modern-dialog-container .preview-actions{padding:10px 15px;flex-direction:column-reverse;gap:8px}.modern-dialog-container .preview-actions button{width:100%;margin:0!important}}@media (max-width: 360px){.modern-dialog-container .preview-content-area .crop-toolbar{gap:2px}.modern-dialog-container .preview-content-area .crop-toolbar button{transform:scale(.75)}}.control-icon{font-size:28px;cursor:pointer}image-cropper{display:flex!important;max-width:100%!important;max-height:100%!important;height:100%;width:100%}image-cropper canvas,image-cropper img{max-width:100%!important;max-height:100%!important}.crop-large{display:flex}.crop-small{display:none}@media (max-width: 600px){.dialog-content{max-height:55vh}.crop-container{max-width:100%;aspect-ratio:auto}.crop-large{display:none}.crop-small{display:flex;justify-content:center;gap:14px}.control-icon{font-size:24px}}.stats-header{display:flex;justify-content:space-between;align-items:center;width:100%}.table-view-container{margin-top:1.5rem;background-color:var(--background-card);border-radius:var(--border-radius);border:1px solid var(--border-color);overflow:hidden;animation:fadeIn .5s ease-out}.table-header,.table-row{display:flex;align-items:center;padding:0 1rem;transition:background-color var(--transition-speed) ease}.table-header{background-color:#f8f9fa;font-weight:600;color:var(--text-color-light);font-size:.8rem;text-transform:uppercase;border-bottom:2px solid var(--border-color)}.table-row{border-bottom:1px solid var(--border-color)}.table-row:last-child{border-bottom:none}.table-row:hover{background-color:#00000005}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem}.name-col{flex:4}.size-col,.date-col{flex:2}.actions-col{flex:1;justify-content:flex-end;min-width:150px}.file-icon-small{font-size:1.5rem;color:var(--primary-color)}.file-info-text{display:flex;flex-direction:column}.file-name-table{font-weight:600;color:var(--text-color)}.file-type-table{font-size:.8rem;color:var(--text-color-light)}@media (max-width: 768px){.date-col{display:none}.name-col{flex:3}.size-col{flex:2}.actions-col{flex:2;min-width:120px}}.secondary-action-link{color:var(--primary-color);text-decoration:none;border-bottom:1px solid var(--primary-color);cursor:pointer;font-weight:500}.secondary-action-link:hover{color:var(--primary-color-dark);border-bottom-color:var(--primary-color-dark)}h2[mat-dialog-title]+mat-dialog-content.add-link-dialog-content{padding-top:20px}mat-dialog-content.add-link-dialog-content{padding-left:24px;padding-right:24px;padding-bottom:20px}.add-link-form{display:flex;flex-direction:column;gap:16px}::ng-deep .eqp-attachments-preview-dialog{--mdc-dialog-subhead-line-height: normal}::ng-deep .eqp-attachments-preview-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;background:#fff!important}:host ::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{--mdc-dialog-subhead-size: 1.25rem;--mdc-dialog-subhead-line-height: 1.5;--mdc-dialog-subhead-weight: 600;--mdc-dialog-supporting-text-size: 1rem}.empty-state{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:1.5rem 1rem;margin-top:1.5rem;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#f8f9fa;text-align:center;color:var(--text-color-light);animation:fadeIn .5s ease-out}.empty-state:before{content:\"\\1f4ed\";font-size:2.5rem;margin-bottom:1rem;opacity:.7}.secondary-action-link.disabled-link{color:#adb5bd;cursor:not-allowed;border-bottom-color:transparent}.secondary-action-link.disabled-link:hover{color:#adb5bd;border-bottom-color:transparent}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem;min-width:0;overflow:hidden}.table-cell.col-actions{flex:0 0 150px;justify-content:flex-end;overflow:visible}.compact-uploader{display:flex;align-items:center;gap:16px;padding:16px;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#fcfdff;transition:all .3s ease}.compact-uploader .compact-text{flex:1 1 auto;min-width:0;cursor:pointer}.compact-uploader .compact-text:hover .compact-title{color:var(--primary-color)}.compact-uploader .compact-title{font-weight:600;color:var(--text-color);transition:color .3s ease}.compact-uploader .compact-subtitle{font-size:.8rem;color:var(--text-color-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-uploader .compact-icon mat-icon{font-size:36px;width:36px;height:36px;color:var(--primary-color)}.compact-uploader .compact-actions{display:flex;gap:8px;flex-shrink:0}.compact-uploader.dragover{background-color:#f4f8ff;border-color:var(--primary-color);box-shadow:0 0 10px var(--shadow-color)}.disabled-dropzone{opacity:.5;cursor:not-allowed!important;background-color:#f5f5f5;border-color:#d1d5db}.disabled-dropzone *{pointer-events:none}.disabled-dropzone .browse-btn,.disabled-dropzone button{cursor:not-allowed!important;background-color:#e5e7eb;color:#9ca3af;border:none}.disabled-dropzone .secondary-action-link,.disabled-dropzone a{color:#9ca3af;text-decoration:none}\n"], dependencies: [{ kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", 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: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i10.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { 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: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], 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: i13.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i13.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i13.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }, { kind: "pipe", type: i13.DatePipe, name: "date" }] });
1346
- }
1347
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: EqpAttachmentsComponent, decorators: [{
1348
- type: Component,
1349
- args: [{ selector: "eqp-attachments", template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n@if(showUploadTitle == true || chooseView == true){\r\n<div class=\"header\">\r\n @if(showUploadTitle == true){\r\n <h4>{{ uploadTitle }}</h4>\r\n }\r\n @if(chooseView == true){\r\n <mat-button-toggle-group [value]=\"viewMode\" (change)=\"setViewMode($event.value)\"\r\n aria-label=\"Modalit\u00E0 di visualizzazione\">\r\n <mat-button-toggle value=\"card\"><mat-icon>grid_view</mat-icon></mat-button-toggle>\r\n <mat-button-toggle value=\"table\"><mat-icon>view_list</mat-icon></mat-button-toggle>\r\n </mat-button-toggle-group>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione singolo -->\r\n@if (multipleAttachment != true) {\r\n@if (!singleAttachmentDragAndDrop) {\r\n@if (!addingLinkMode) {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addAttachmentButton\"></ng-container>\r\n</div>\r\n} @else {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addingLinkTemplate\"></ng-container>\r\n</div>\r\n}\r\n} @else {\r\n<input #fileInput id=\"file_attachment\" name=\"file_attachment\" type=\"file\" hidden (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (allowedTypes && allowedTypes.includes(1) && (!attachmentsList || attachmentsList.length == 0 ||\r\n(attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n\r\n@if (showDropArea == true) {\r\n<!-- FULL -->\r\n@if (layout === 'full') {\r\n\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n <div class=\"secondary-action\">\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n @if (allowedTypes.includes(2) && allowedTypes.includes(3)) {\r\n <a class=\"secondary-action-link\" [matMenuTriggerFor]=\"isDisabled ? null : linkMenu\"\r\n [class.disabled-link]=\"isDisabled\" (click)=\"$event.stopPropagation()\">\r\n o aggiungi da web\r\n </a>\r\n <mat-menu #linkMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"switchToAddingLinkMode()\">\r\n <mat-icon>link</mat-icon>\r\n <span>Aggiungi da link</span>\r\n </button>\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\">\r\n <mat-icon>cloud_queue</mat-icon>\r\n <span>Carica da Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @else if (allowedTypes.includes(2)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">\r\n aggiungi un link\r\n </a>\r\n }\r\n\r\n @else if (allowedTypes.includes(3)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); chooseDropboxFile()\">\r\n carica da Dropbox\r\n </a>\r\n }\r\n }\r\n </div>\r\n</div>\r\n}@else {\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button color=\"primary\" [disabled]=\"isDisabled\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n}\r\n}\r\n\r\n<!-- Azioni singolo elemento (come prima) -->\r\n<div class=\"text-center\">\r\n @if (attachmentsList && attachmentsList.length > 0 && attachmentsList[0] && showActionButtons == true) {\r\n @if (!isPrimaryActionHidden(attachmentsList[0])) {\r\n <button class=\"mb-2 me-2 eqp-attachments-download-btn\" (click)=\"viewAttachment(attachmentsList[0])\" type=\"button\"\r\n [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button color=\"primary\">\r\n @if (attachmentsList[0].AttachmentType == AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n }\r\n\r\n @if (!isPrimaryActionHidden(attachmentsList[0]) && showPreview && (!attachmentsList[0].FileContentType || (!attachmentsList[0].FileContentType.startsWith('video')\r\n && !attachmentsList[0].FileContentType.startsWith('audio'))) && attachmentsList[0].IsImage == true) {\r\n <button class=\"mb-2 me-2 eqp-attachments-preview-btn\" (click)=\"openPreviewDialog(attachmentsList[0])\" type=\"button\"\r\n [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button color=\"primary\">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n }\r\n\r\n <button [disabled]=\"disableAction\" class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\" type=\"button\" mat-raised-button [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione multipla -->\r\n@if (multipleAttachment == true && showDropArea == true) {\r\n<input #fileInput id=\"file_attachment_multi\" name=\"file_attachment_multi\" type=\"file\" hidden\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (layout === 'full') {\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n @if (allowedTypes.includes(2)) {\r\n <div class=\"secondary-action-link\">\r\n o <a (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">aggiungi un link</a>\r\n </div>\r\n }\r\n</div>\r\n}@else{\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button [disabled]=\"isDisabled\" color=\"primary\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n\r\n@if (attachmentsList?.length > 0 && showSummary) {\r\n<div class=\"upload-stats\">\r\n\r\n <div class=\"stats-info\">\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ attachmentsList?.length }}</div>\r\n <div class=\"stat-label\">{{ filesLabel }}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ totalSizeFormatted }}</div>\r\n <div class=\"stat-label\">{{ totalSizeLabel }}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"progressPercent\"></div>\r\n </div>\r\n\r\n</div>\r\n} @else if(attachmentsList?.length == 0){\r\n<div class=\"empty-state\">{{ emptyStateLabel }}</div>\r\n}\r\n\r\n<!-- Griglia anteprime card (vale per singolo e multiplo) -->\r\n@if (viewMode === 'card') {\r\n\r\n<div class=\"file-previews\" [ngStyle]=\"getPreviewsContainerStyle()\">\r\n @for (att of attachmentsList; track att.ID) {\r\n <div [ngClass]=\"getCardClass(att)\">\r\n <div class=\"preview-img-container\" (click)=\"!att.isUploading && !isPrimaryActionHidden(att) && !isPrimaryActionDisabled(att) && handlePrimaryAction(att)\">\r\n\r\n @if (att.IsImage || att.FileThumbnailBase64) {\r\n <img class=\"preview-img\" [src]=\"'data:image/jpeg;base64,' + (att.FileThumbnailBase64 || att.FileDataBase64)\"\r\n [alt]=\"att.FileName\" />\r\n } @else {\r\n <div class=\"file-icon\"><i [ngClass]=\"getAttachmentIcon(att)\"></i></div>\r\n }\r\n\r\n @if (!isPrimaryActionHidden(att)) {\r\n <div class=\"preview-action-overlay\">\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n <mat-icon>play_arrow</mat-icon>\r\n }\r\n @else if (att.IsImage && canBePreviewed(att)) {\r\n <mat-icon>visibility</mat-icon>\r\n }\r\n @else if (att.FileContentType === 'application/pdf' && canBePreviewed(att)) {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n @else if (att.AttachmentType === AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n }\r\n @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n </div>\r\n }\r\n\r\n </div>\r\n\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"att.FileName\">{{ att.FileName }}</div>\r\n </div>\r\n\r\n @if(!isDeleteHidden(att)){\r\n <button mat-icon-button class=\"remove-btn\" (click)=\"deleteAttachment(att)\"\r\n [disabled]=\"att.isUploading || isDeleteDisabled(att)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (att.isUploading) {\r\n <div class=\"upload-spinner\"></div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n} @else if(viewMode === 'table' && attachmentsList?.length > 0) {\r\n\r\n\r\n<div class=\"table-view-container\">\r\n\r\n <div class=\"table-header\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n {{ col.display }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @for (att of attachmentsList; track att.ID) {\r\n <div class=\"table-row\">\r\n\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n\r\n @switch (col.type) {\r\n\r\n @case ('template') {\r\n <div class=\"template-wrapper\">\r\n <ng-container [ngTemplateOutlet]=\"col.externalTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: att }\"></ng-container>\r\n </div>\r\n }\r\n @case ('date') {\r\n <span class=\"metadata-value\">{{ att[col.key] | date:'dd/MM/yyyy' }}</span>\r\n }\r\n @default {\r\n <span class=\"metadata-value\">{{ att[col.key] }}</span>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Notifica toast -->\r\n<div class=\"upload-notification\" [class.show]=\"toast?.visible\" [class.success]=\"toast?.type === 'success'\"\r\n [class.error]=\"toast?.type === 'error'\">\r\n <span>{{ toast?.text }}</span>\r\n <div class=\"notification-progress\"></div>\r\n</div>\r\n\r\n<ng-template #defaultFileTemplate let-att>\r\n <i class=\"file-icon-small\" [ngClass]=\"getAttachmentIcon(att)\"></i>\r\n <div class=\"file-info-text\">\r\n <span class=\"file-name-table\">{{ att.FileName }}</span>\r\n <span class=\"file-type-table\">{{ att.FileExtension || 'Link' }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultActionsTemplate let-att>\r\n @if (!isPrimaryActionHidden(att)) {\r\n <button mat-icon-button (click)=\"handlePrimaryAction(att)\" [disabled]=\"isPrimaryActionDisabled(att)\"\r\n [matTooltip]=\"att.FileContentType?.startsWith('video/') ? 'Riproduci video' : 'Visualizza/Scarica'\">\r\n\r\n <mat-icon>\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n play_arrow\r\n } @else {\r\n {{ att.AttachmentType === AttachmentType.FILE ? 'download' : 'open_in_new' }}\r\n }\r\n </mat-icon>\r\n </button>\r\n }\r\n\r\n @if (!hiddenActions.includes('actionsMenu')) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"actionsMenu\" matTooltip=\"Altre opzioni\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n }\r\n\r\n <mat-menu #actionsMenu=\"matMenu\">\r\n @for (action of _sortedMenuActions; track action.name) {\r\n @if (!isActionHidden(action, att)) {\r\n <button mat-menu-item (click)=\"action.fn(att)\" [disabled]=\"isActionDisabled(action, att)\">\r\n <mat-icon [color]=\"action.icon === 'delete' ? 'warn' : undefined\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n <span>{{ action.name }}</span>\r\n </button>\r\n }\r\n }\r\n </mat-menu>\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogCropImage>\r\n <div style=\"overflow-x: hidden; display: flex; flex-direction: column; height: 100%; min-height: 0; flex: 1 1 auto;\"\r\n [ngClass]=\"cropDialogClass\">\r\n <!-- @if (showCropImage == true) { -->\r\n <ng-container [ngTemplateOutlet]=\"croppieTemplate\" [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\">\r\n </ng-container>\r\n <!-- } -->\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n @if (row.AttachmentType != AttachmentType.LINK && row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <img [src]=\"'data:image/png;base64,' + (row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64)\" />\r\n </div>\r\n } @else if (row.AttachmentType != AttachmentType.LINK && !row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"modern-dialog-container\"> @if (selectedAttachment) {\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ previewLabel }}</span>\r\n <span class=\"file-t\">{{ selectedAttachment.FileName }}</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"media-viewer-wrapper\">\r\n @if (selectedAttachment.IsImage) {\r\n <img class=\"main-preview-media\"\r\n [src]=\"'data:image/png;base64,' + (selectedAttachment.FileDataBase64 || selectedAttachment.FileThumbnailBase64)\"\r\n [alt]=\"selectedAttachment.FileName\" />\r\n }\r\n @else if (selectedAttachment.FileContentType?.startsWith('video/')) {\r\n <video controls autoplay playsinline class=\"main-preview-media video-player\">\r\n <source [src]=\"selectedAttachment.TrustedUrl\" [type]=\"selectedAttachment.FileContentType\">\r\n Il tuo browser non supporta il video.\r\n </video>\r\n }\r\n @else {\r\n <div class=\"iframe-container\">\r\n <iframe class=\"preview-iframe-modern\" [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n }\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Chiudi</button>\r\n @if (selectedAttachment.AttachmentType !== AttachmentType.LINK) {\r\n <button mat-raised-button color=\"primary\" (click)=\"viewAttachment(selectedAttachment)\" class=\"btn-download\">\r\n <mat-icon>download</mat-icon> <span>{{ downloadLabel }}</span>\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <input #fileInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n @if (allowedTypes && allowedTypes.length == 1 && (multipleAttachment == true || !attachmentsList ||\r\n attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\" [disabled]=\"isDisabled\">\r\n @if (allowedTypes[0] == 1) { <mat-icon>cloud_upload</mat-icon> }\r\n @if (allowedTypes[0] == 2) { <i class=\"fas fa-link\"></i> }\r\n @if (allowedTypes[0] == 3) { <i class=\"fa-brands fa-dropbox\"></i> }\r\n <span style=\"margin-left: 10px\">\r\n {{ allowedTypes[0] == 1 ? (addButtonLabel + \" file\") : allowedTypes[0] == 2 ? (addButtonLabel + \" link\") :\r\n uploadWithDropboxLabel }}\r\n </span>\r\n </button>\r\n }\r\n\r\n @if (!separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\" [disabled]=\"isDisabled\">\r\n @if (multipleAttachment != true) { <mat-icon>cloud_upload</mat-icon> } @else { <mat-icon>add</mat-icon> }\r\n <span style=\"margin-left: 0px\">{{ addButtonLabel }}</span>\r\n </button>\r\n\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(1)) {\r\n <button mat-menu-item (click)=\"imageInput.click()\" 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 }\r\n @if (allowedTypes.includes(2)) {\r\n <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"switchToAddingLinkMode()\" 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 }\r\n @if (allowedTypes.includes(3)) {\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\" 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 }\r\n </mat-menu>\r\n }\r\n\r\n @if (separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <div class=\"btn-group\">\r\n @if (allowedTypes.includes(1)) {\r\n <button (click)=\"imageInput.click()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(2)) {\r\n <button (click)=\"switchToAddingLinkMode()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(3)) {\r\n <button (click)=\"chooseDropboxFile()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" 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 }\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ cropLabel }}</span>\r\n <span class=\"file-t\">Regola le dimensioni e l'orientamento</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button type=\"button\" (click)=\"abortFile()\" class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"crop-toolbar\">\r\n @if (cropOptions.includes(1)) {\r\n <button mat-icon-button [matTooltip]=\"rotateLeftLabel\"\r\n (click)=\"rotateLeft()\"><mat-icon>rotate_left</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"rotateRightLabel\"\r\n (click)=\"rotateRight()\"><mat-icon>rotate_right</mat-icon></button>\r\n }\r\n @if (cropOptions.includes(2)) {\r\n <button mat-icon-button [matTooltip]=\"flipHorinzontalLabel\"\r\n (click)=\"flipHorizontal()\"><mat-icon>flip_horizontal</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"flipVerticalLabel\"\r\n (click)=\"flipVertical()\"><mat-icon>flip_vertical</mat-icon></button>\r\n }\r\n <button mat-icon-button matTooltip=\"Reset\"\r\n (click)=\"restoreOriginalDimensions()\"><mat-icon>replay</mat-icon></button>\r\n </div>\r\n\r\n <div class=\"media-viewer-wrapper\">\r\n <div class=\"crop-container-modern\">\r\n <image-cropper [imageFile]=\"selectedFile\" [maintainAspectRatio]=\"false\" [canvasRotation]=\"canvasRotation\"\r\n [transform]=\"transform\" format=\"png\" (imageCropped)=\"imageCropped($event)\" [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\" [output]=\"'base64'\" [containWithinAspectRatio]=\"true\" [onlyScaleDown]=\"true\"\r\n [alignImage]=\"'center'\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button (click)=\"abortFile()\" class=\"btn-close\">{{ abortLabel }}</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"confirmAddAttachment()\" class=\"btn-download\">\r\n <mat-icon>check</mat-icon> {{ confirmLabel }}\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"type-icon-wrapper\">\r\n <mat-icon>link</mat-icon>\r\n </div>\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">Aggiungi un link</span>\r\n <span class=\"file-t\">Inserisci l'URL della risorsa web</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"add-link-modern-content\">\r\n <form [formGroup]=\"newAttachmentForm\" class=\"add-link-form\">\r\n <mat-form-field appearance=\"outline\" class=\"w-100 mt-3\">\r\n <mat-label>URL del collegamento</mat-label>\r\n <input matInput formControlName=\"filePath\" placeholder=\"https://...\" required>\r\n <mat-icon matSuffix>language</mat-icon>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>Titolo (opzionale)</mat-label>\r\n <input matInput formControlName=\"fileName\" placeholder=\"Es. Documento Progetto\">\r\n <mat-icon matSuffix>title</mat-icon>\r\n </mat-form-field>\r\n </form>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Annulla</button>\r\n <button mat-raised-button color=\"primary\" [mat-dialog-close]=\"newAttachmentForm.value\"\r\n [disabled]=\"newAttachmentForm.invalid\" class=\"btn-download\">\r\n <mat-icon>add</mat-icon> Aggiungi\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{--primary-color: #6a5af9;--primary-color-dark: #5441f8;--success-color: #1ce593;--error-color: #ff5b5b;--background-light: #f7f9fc;--background-card: rgba(255, 255, 255, .7);--text-color: #1e293b;--text-color-light: #64748b;--border-color: rgba(203, 213, 225, .5);--shadow-color: rgba(99, 102, 241, .2);--border-radius: 16px;--transition-speed: .3s}@keyframes fadeIn{0%{opacity:0;transform:translateY(15px)}to{opacity:1;transform:translateY(0)}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--primary-color)}70%{box-shadow:0 0 0 10px #6a5af900}to{box-shadow:0 0 #6a5af900}}.container{width:100%;max-width:700px;margin:2rem auto;font-family:Inter,sans-serif}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border-color)}.header h1{color:var(--text-color);font-size:1.8rem;font-weight:700;margin:0}.dropbox{width:100%;border:2px dashed var(--border-color);border-radius:var(--border-radius);padding:2.5rem;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all var(--transition-speed) ease}.dropbox:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color);border-color:var(--primary-color)}.dropbox.dragover{border-style:solid;border-color:var(--primary-color);transform:scale(1.02);box-shadow:0 0 25px var(--shadow-color);animation:pulse 1.5s infinite}.dropbox .dropbox-icon{font-size:3.5rem;color:var(--primary-color)}.dropbox .dropbox-text{font-size:1.1rem;font-weight:600;color:var(--text-color);margin-top:1rem}.dropbox .dropbox-subtext{color:var(--text-color-light);margin-top:.5rem}.dropbox .browse-btn{margin-top:1.5rem;padding:.75rem 1.5rem;background-color:var(--primary-color);color:#fff;border:none;border-radius:10px;font-weight:600;transition:all var(--transition-speed) ease}.dropbox .browse-btn:hover{background-color:var(--primary-color-dark);transform:translateY(-2px)}.file-previews{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1.5rem;margin-top:2rem}.file-previews{display:grid;gap:16px;padding:16px;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width, 200px),1fr))}.file-preview{background-color:var(--background-card);border-radius:var(--border-radius);box-shadow:0 4px 15px #0000000d;border:1px solid var(--border-color);overflow:hidden;display:flex;flex-direction:column;position:relative;opacity:0;animation:fadeIn .5s ease-out forwards;transition:transform var(--transition-speed) ease,box-shadow var(--transition-speed) ease}.file-preview.uploading{cursor:wait}.file-preview.uploading .preview-img-container:after{content:\"\";position:absolute;inset:0;background:#ffffffb3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);pointer-events:none}.file-preview .preview-action-overlay{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;background-color:#0006;color:#fff;opacity:1;transition:opacity .3s ease}.file-preview .preview-action-overlay .mat-icon{font-size:36px;width:36px;height:36px}.file-preview .remove-btn{position:absolute;top:8px;right:8px;z-index:2;background-color:#0000004d;color:#fff;width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;transition:all var(--transition-speed) ease}.file-preview .remove-btn:hover{background-color:#ff5b5b}.file-preview .remove-btn .mat-icon{font-size:18px}@media (hover: hover){.file-preview .remove-btn .file-preview .preview-action-overlay{opacity:0}.file-preview .remove-btn .file-preview:hover .preview-action-overlay,.file-preview .remove-btn .file-preview:hover .remove-btn{opacity:1}.file-preview .remove-btn .file-preview .remove-btn{opacity:0}}@media (hover: hover) and (min-width: 769px){.file-preview .remove-btn{opacity:0;transform:scale(.8)}.file-preview:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color)}.file-preview:hover .remove-btn{opacity:1;transform:scale(1)}}.file-preview .preview-img-container{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;cursor:pointer;background-color:#f0f2f5}.file-preview .preview-img{width:100%;height:100%;object-fit:cover}.file-preview .file-icon{font-size:4rem;color:var(--primary-color)}.file-preview .file-info{padding:12px;border-top:1px solid var(--border-color);flex-grow:1;display:flex;align-items:center}.file-preview .file-name{font-weight:600;font-size:.9rem;color:var(--text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-preview .upload-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border:4px solid rgba(0,0,0,.1);border-left-color:var(--primary-color);border-radius:50%;animation:spin 1s linear infinite;pointer-events:none}.file-preview.card-small{width:140px}.file-preview.card-small .preview-img-container{height:80px}.file-preview.card-small .file-info{padding:8px}.file-preview.card-small .file-name{font-size:.8rem}.file-preview.card-small .file-icon{font-size:3rem}.file-preview.card-small .remove-btn{width:28px;height:28px}.file-preview.card-small .remove-btn .mat-icon{font-size:16px}.file-preview.card-large{width:280px}.file-preview.card-large .preview-img-container{height:180px}.file-preview.card-large .file-info{padding:16px}.file-preview.card-large .file-name{font-size:1rem}.file-preview.card-large .file-icon{font-size:5rem}.file-preview.card-large .remove-btn{width:36px;height:36px}.file-preview.card-large .remove-btn .mat-icon{font-size:20px}.file-preview[style*=--eqp-card-width]{width:var(--eqp-card-width)}.file-preview[style*=--eqp-card-width] .preview-img-container{height:calc(var(--eqp-card-width) * .65)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}.upload-stats{background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--border-color);border-radius:var(--border-radius);padding:1.5rem;margin-top:2rem;animation:fadeIn .5s ease-out}.upload-stats .stats-info{display:flex;justify-content:space-around}.upload-stats .progress-bar{height:10px;background-color:var(--border-color);border-radius:5px;overflow:hidden;margin-top:1rem}.upload-stats .progress-fill{height:100%;background:linear-gradient(90deg,var(--primary-color),var(--success-color));transition:width var(--transition-speed) ease-out;border-radius:5px}.upload-notification{position:fixed;bottom:20px;left:50%;transform:translate(-50%,100px);padding:1rem 1.5rem;border-radius:var(--border-radius);color:#fff;font-weight:600;box-shadow:0 10px 30px #0003;transition:transform var(--transition-speed) cubic-bezier(.175,.885,.32,1.275)}.upload-notification.show{transform:translate(-50%)}.upload-notification.success{background-color:var(--success-color)}.upload-notification.error{background-color:var(--error-color)}::ng-deep .cdk-overlay-pane.eqp-crop-dialog{transform:translateY(-4vh)}@media (max-width: 600px){::ng-deep .cdk-overlay-pane.crop-dialog{width:auto!important}}::ng-deep .eqp-attachments-dialog{display:flex!important;flex-direction:column!important}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container .mdc-dialog__surface{border-radius:20px!important;padding:0!important;overflow:hidden!important;width:fit-content!important;min-width:350px!important;max-width:95vw!important;max-height:90vh!important;margin:0 auto;background-color:#fff!important;display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden!important}.modern-dialog-container{display:flex;flex-direction:column;width:100%;max-width:100%;flex:1 1 auto;min-height:0;height:100%;max-height:100%;background:#fff;--preview-header-h: 66px;--preview-footer-h: 66px;--preview-padding-y: 30px}.modern-dialog-container .main-preview-media{display:block;max-width:100%;max-height:var(--media-max-h);width:auto;height:auto;object-fit:contain;border-radius:12px;background:#fff;padding:4px;box-shadow:0 10px 30px #00000014}.modern-dialog-container video.main-preview-media{width:min(100%,1100px);background:#000}.modern-dialog-container .iframe-container{width:min(100%,1100px);height:var(--media-max-h);display:flex;width:100%;max-width:1100px}.modern-dialog-container .preview-iframe-modern{width:100%;height:100%;border:0;border-radius:12px;background:#f8fafc}.modern-dialog-container .preview-header{flex:0 0 auto;flex-shrink:0;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;border-bottom:1px solid var(--border-color);background:#f8fafc;z-index:10;width:100%}.modern-dialog-container .preview-header .close-btn{display:inline-flex!important;align-items:center!important;justify-content:center!important;padding:0!important;width:40px!important;height:40px!important}.modern-dialog-container .preview-header .close-btn ::ng-deep mat-icon{display:flex!important;align-items:center!important;justify-content:center!important;margin:0!important;padding:0!important;line-height:1!important}.modern-dialog-container .preview-header .header-info{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex:1 1 auto;min-width:0;text-align:left}.modern-dialog-container .preview-header .header-info .type-icon-wrapper{background:var(--primary-color);color:#fff;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px var(--shadow-color)}.modern-dialog-container .preview-header .header-info .title-group{display:flex;flex-direction:column;align-items:flex-start;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .main-t{font-weight:800;color:var(--text-color);font-size:.95rem;line-height:1.2;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .file-t{font-size:.75rem;color:var(--text-color-light);max-width:250px;overflow:hidden;text-overflow:ellipsis;text-align:left}.modern-dialog-container .preview-content-area{flex:1 1 auto;background:#fff!important;display:flex;flex-direction:column;padding:15px 15px 22px!important;overflow:hidden!important;min-height:0;width:100%;--media-max-h: calc(90vh - var(--preview-header-h) - var(--preview-footer-h) - var(--preview-padding-y))}.modern-dialog-container .preview-content-area .crop-toolbar{flex-shrink:0;z-index:20;background:#0f172a14;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:6px 16px;border-radius:30px;margin:0 auto 15px;display:flex;gap:8px;box-shadow:0 4px 12px #0000000d}.modern-dialog-container .preview-content-area .crop-toolbar button{color:var(--text-color)!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper{flex:1 1 auto;width:100%;height:100%;display:flex;flex-direction:column;align-items:stretch;min-height:0;overflow:hidden}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern{flex:1 1 auto;display:flex;flex-direction:column;justify-content:center;align-items:center;background:transparent;border-radius:12px;padding:0;overflow:hidden;min-height:0;width:100%;height:100%}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern image-cropper{flex:1 1 auto;width:100%;height:100%;max-width:100%!important;max-height:100%!important;display:block;min-height:0}.modern-dialog-container .add-link-modern-content{flex:1;background:#fff;padding:24px!important}.modern-dialog-container .add-link-modern-content .add-link-form{display:flex;flex-direction:column;gap:10px}.modern-dialog-container .preview-actions{flex-shrink:0;padding:12px 24px;background:#f8fafc;border-top:1px solid #e2e8f0;margin:0}.modern-dialog-container .preview-actions .btn-download{border-radius:12px;font-weight:600;box-shadow:0 4px 12px var(--shadow-color)}@media (max-width: 600px){.modern-dialog-container{max-height:95vh}.modern-dialog-container .preview-content-area{padding:10px!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper video.main-preview-media{width:100%!important;max-height:55vh!important;border-radius:4px;box-shadow:none}.modern-dialog-container .preview-content-area .media-viewer-wrapper .iframe-container{height:50vh}.modern-dialog-container .preview-content-area .crop-toolbar{width:calc(100% - 20px);max-width:400px;margin-bottom:10px;padding:4px 8px;gap:4px;overflow-x:auto;justify-content:center;-webkit-overflow-scrolling:touch;scrollbar-width:none}.modern-dialog-container .preview-content-area .crop-toolbar::-webkit-scrollbar{display:none}.modern-dialog-container .preview-content-area .crop-toolbar button{flex-shrink:0;transform:scale(.85);width:40px;height:40px}.modern-dialog-container .preview-actions{padding:10px 15px;flex-direction:column-reverse;gap:8px}.modern-dialog-container .preview-actions button{width:100%;margin:0!important}}@media (max-width: 360px){.modern-dialog-container .preview-content-area .crop-toolbar{gap:2px}.modern-dialog-container .preview-content-area .crop-toolbar button{transform:scale(.75)}}.control-icon{font-size:28px;cursor:pointer}image-cropper{display:flex!important;max-width:100%!important;max-height:100%!important;height:100%;width:100%}image-cropper canvas,image-cropper img{max-width:100%!important;max-height:100%!important}.crop-large{display:flex}.crop-small{display:none}@media (max-width: 600px){.dialog-content{max-height:55vh}.crop-container{max-width:100%;aspect-ratio:auto}.crop-large{display:none}.crop-small{display:flex;justify-content:center;gap:14px}.control-icon{font-size:24px}}.stats-header{display:flex;justify-content:space-between;align-items:center;width:100%}.table-view-container{margin-top:1.5rem;background-color:var(--background-card);border-radius:var(--border-radius);border:1px solid var(--border-color);overflow:hidden;animation:fadeIn .5s ease-out}.table-header,.table-row{display:flex;align-items:center;padding:0 1rem;transition:background-color var(--transition-speed) ease}.table-header{background-color:#f8f9fa;font-weight:600;color:var(--text-color-light);font-size:.8rem;text-transform:uppercase;border-bottom:2px solid var(--border-color)}.table-row{border-bottom:1px solid var(--border-color)}.table-row:last-child{border-bottom:none}.table-row:hover{background-color:#00000005}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem}.name-col{flex:4}.size-col,.date-col{flex:2}.actions-col{flex:1;justify-content:flex-end;min-width:150px}.file-icon-small{font-size:1.5rem;color:var(--primary-color)}.file-info-text{display:flex;flex-direction:column}.file-name-table{font-weight:600;color:var(--text-color)}.file-type-table{font-size:.8rem;color:var(--text-color-light)}@media (max-width: 768px){.date-col{display:none}.name-col{flex:3}.size-col{flex:2}.actions-col{flex:2;min-width:120px}}.secondary-action-link{color:var(--primary-color);text-decoration:none;border-bottom:1px solid var(--primary-color);cursor:pointer;font-weight:500}.secondary-action-link:hover{color:var(--primary-color-dark);border-bottom-color:var(--primary-color-dark)}h2[mat-dialog-title]+mat-dialog-content.add-link-dialog-content{padding-top:20px}mat-dialog-content.add-link-dialog-content{padding-left:24px;padding-right:24px;padding-bottom:20px}.add-link-form{display:flex;flex-direction:column;gap:16px}::ng-deep .eqp-attachments-preview-dialog{--mdc-dialog-subhead-line-height: normal}::ng-deep .eqp-attachments-preview-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;background:#fff!important}:host ::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{--mdc-dialog-subhead-size: 1.25rem;--mdc-dialog-subhead-line-height: 1.5;--mdc-dialog-subhead-weight: 600;--mdc-dialog-supporting-text-size: 1rem}.empty-state{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:1.5rem 1rem;margin-top:1.5rem;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#f8f9fa;text-align:center;color:var(--text-color-light);animation:fadeIn .5s ease-out}.empty-state:before{content:\"\\1f4ed\";font-size:2.5rem;margin-bottom:1rem;opacity:.7}.secondary-action-link.disabled-link{color:#adb5bd;cursor:not-allowed;border-bottom-color:transparent}.secondary-action-link.disabled-link:hover{color:#adb5bd;border-bottom-color:transparent}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem;min-width:0;overflow:hidden}.table-cell.col-actions{flex:0 0 150px;justify-content:flex-end;overflow:visible}.compact-uploader{display:flex;align-items:center;gap:16px;padding:16px;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#fcfdff;transition:all .3s ease}.compact-uploader .compact-text{flex:1 1 auto;min-width:0;cursor:pointer}.compact-uploader .compact-text:hover .compact-title{color:var(--primary-color)}.compact-uploader .compact-title{font-weight:600;color:var(--text-color);transition:color .3s ease}.compact-uploader .compact-subtitle{font-size:.8rem;color:var(--text-color-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-uploader .compact-icon mat-icon{font-size:36px;width:36px;height:36px;color:var(--primary-color)}.compact-uploader .compact-actions{display:flex;gap:8px;flex-shrink:0}.compact-uploader.dragover{background-color:#f4f8ff;border-color:var(--primary-color);box-shadow:0 0 10px var(--shadow-color)}.disabled-dropzone{opacity:.5;cursor:not-allowed!important;background-color:#f5f5f5;border-color:#d1d5db}.disabled-dropzone *{pointer-events:none}.disabled-dropzone .browse-btn,.disabled-dropzone button{cursor:not-allowed!important;background-color:#e5e7eb;color:#9ca3af;border:none}.disabled-dropzone .secondary-action-link,.disabled-dropzone a{color:#9ca3af;text-decoration:none}\n"] }]
1350
- }], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2.FormBuilder }, { type: i3.DomSanitizer }, { type: i4.HttpClient }, { type: i5.EqpAttachmentService }], propDecorators: { disableAction: [{
1351
- type: Input,
1352
- args: ["disableAction"]
1353
- }], showHeader: [{
1354
- type: Input,
1355
- args: ["showHeader"]
1356
- }], attachmentsList: [{
1357
- type: Input,
1358
- args: ["attachmentsList"]
1359
- }], singleAttachment: [{
1360
- type: Input,
1361
- args: ["singleAttachment"]
1362
- }], showMatCard: [{
1363
- type: Input,
1364
- args: ["showMatCard"]
1365
- }], multipleAttachment: [{
1366
- type: Input,
1367
- args: ["multipleAttachment"]
1368
- }], loadMultipleFiles: [{
1369
- type: Input,
1370
- args: ["loadMultipleFiles"]
1371
- }], emptyTableMessage: [{
1372
- type: Input,
1373
- args: ["emptyTableMessage"]
1374
- }], allowOnlyImages: [{
1375
- type: Input,
1376
- args: ["allowOnlyImages"]
1377
- }], acceptedFileTypes: [{
1378
- type: Input,
1379
- args: ["acceptedFileTypes"]
1380
- }], isDisabled: [{
1381
- type: Input,
1382
- args: ["isDisabled"]
1383
- }], showInlinePreview: [{
1384
- type: Input,
1385
- args: ["showInlinePreview"]
1386
- }], getAttachmentEndpoint: [{
1387
- type: Input,
1388
- args: ["getAttachmentEndpoint"]
1389
- }], productionBaseUrl: [{
1390
- type: Input,
1391
- args: ["productionBaseUrl"]
1392
- }], compressionOptions: [{
1393
- type: Input,
1394
- args: ["compressionOptions"]
1395
- }], allowedTypes: [{
1396
- type: Input,
1397
- args: ["allowedTypes"]
1398
- }], isEqpTableMultiLanguage: [{
1399
- type: Input,
1400
- args: ["isEqpTableMultiLanguage"]
1401
- }], tablePaginatorVisible: [{
1402
- type: Input,
1403
- args: ["tablePaginatorVisible"]
1404
- }], isTableSearcheable: [{
1405
- type: Input,
1406
- args: ["isTableSearcheable"]
1407
- }], tablePaginatorSize: [{
1408
- type: Input,
1409
- args: ["tablePaginatorSize"]
1410
- }], separatedUploadButtons: [{
1411
- type: Input,
1412
- args: ["separatedUploadButtons"]
1413
- }], showPreview: [{
1414
- type: Input,
1415
- args: ["showPreview"]
1416
- }], singleAttachmentDragAndDrop: [{
1417
- type: Input,
1418
- args: ["singleAttachmentDragAndDrop"]
1419
- }], cropOptions: [{
1420
- type: Input,
1421
- args: ["cropOptions"]
1422
- }], cropDialogClass: [{
1423
- type: Input,
1424
- args: ["cropDialogClass"]
1425
- }], maxFileSizeMB: [{
1426
- type: Input
1427
- }], cardSize: [{
1428
- type: Input
1429
- }], customCardWidthPx: [{
1430
- type: Input
1431
- }], customCardHeightPx: [{
1432
- type: Input
1433
- }], layout: [{
1434
- type: Input
1435
- }], openLinkLabel: [{
1436
- type: Input,
1437
- args: ["openLinkLabel"]
1438
- }], addButtonLabel: [{
1439
- type: Input,
1440
- args: ["addButtonLabel"]
1441
- }], downloadLabel: [{
1442
- type: Input,
1443
- args: ["downloadLabel"]
1444
- }], deleteLabel: [{
1445
- type: Input,
1446
- args: ["deleteLabel"]
1447
- }], fileNameLabel: [{
1448
- type: Input,
1449
- args: ["fileNameLabel"]
1450
- }], previewLabel: [{
1451
- type: Input,
1452
- args: ["previewLabel"]
1453
- }], uploadFileLabel: [{
1454
- type: Input,
1455
- args: ["uploadFileLabel"]
1456
- }], confirmLabel: [{
1457
- type: Input,
1458
- args: ["confirmLabel"]
1459
- }], abortLabel: [{
1460
- type: Input,
1461
- args: ["abortLabel"]
1462
- }], saveLabel: [{
1463
- type: Input,
1464
- args: ["saveLabel"]
1465
- }], exitLabel: [{
1466
- type: Input,
1467
- args: ["exitLabel"]
1468
- }], uploadWithDropboxLabel: [{
1469
- type: Input,
1470
- args: ["uploadWithDropboxLabel"]
1471
- }], cropLabel: [{
1472
- type: Input,
1473
- args: ["cropLabel"]
1474
- }], deleteDialogTitle: [{
1475
- type: Input,
1476
- args: ["deleteDialogTitle"]
1477
- }], deleteDialogMessage: [{
1478
- type: Input,
1479
- args: ["deleteDialogMessage"]
1480
- }], noImageSelectedErrorMessage: [{
1481
- type: Input,
1482
- args: ["noImageSelectedErrorMessage"]
1483
- }], wrongTypeSelectedErrorMessage: [{
1484
- type: Input,
1485
- args: ["wrongTypeSelectedErrorMessage"]
1486
- }], videoPreviewErrorMessage: [{
1487
- type: Input,
1488
- args: ["videoPreviewErrorMessage"]
1489
- }], audioPreviewErrorMessage: [{
1490
- type: Input,
1491
- args: ["videoPreviewErrorMessage"]
1492
- }], flipHorinzontalLabel: [{
1493
- type: Input,
1494
- args: ["flipHorinzontalLabel"]
1495
- }], flipVerticalLabel: [{
1496
- type: Input,
1497
- args: ["flipVerticalLabel"]
1498
- }], rotateRightLabel: [{
1499
- type: Input,
1500
- args: ["rotateRightLabel"]
1501
- }], rotateLeftLabel: [{
1502
- type: Input,
1503
- args: ["rotateLeftLabel"]
1504
- }], base64LimitMB: [{
1505
- type: Input,
1506
- args: ["base64LimitMB"]
1507
- }], uploadTitle: [{
1508
- type: Input
1509
- }], uploadSubtitle: [{
1510
- type: Input
1511
- }], dropHereLabel: [{
1512
- type: Input
1513
- }], supportedFormatsLabel: [{
1514
- type: Input
1515
- }], browseFilesLabel: [{
1516
- type: Input
1517
- }], uploadSummaryLabel: [{
1518
- type: Input
1519
- }], filesLabel: [{
1520
- type: Input
1521
- }], totalSizeLabel: [{
1522
- type: Input
1523
- }], emptyStateLabel: [{
1524
- type: Input
1525
- }], addedSuccessfullyLabel: [{
1526
- type: Input
1527
- }], removedLabel: [{
1528
- type: Input
1529
- }], chooseView: [{
1530
- type: Input
1531
- }], showSummary: [{
1532
- type: Input
1533
- }], viewMode: [{
1534
- type: Input,
1535
- args: ["viewMode"]
1536
- }], showUploadTitle: [{
1537
- type: Input,
1538
- args: ["showUploadTitle"]
1539
- }], showDropArea: [{
1540
- type: Input,
1541
- args: ["showDropArea"]
1542
- }], hiddenColumns: [{
1543
- type: Input
1544
- }], hiddenActions: [{
1545
- type: Input
1546
- }], showActionButtons: [{
1547
- type: Input
1548
- }], enableImageCrop: [{
1549
- type: Input,
1550
- args: ["enableImageCrop"]
1551
- }], actionHiddenFn: [{
1552
- type: Input
1553
- }], actionDisabledFn: [{
1554
- type: Input
1555
- }], videoCompression: [{
1556
- type: Input
1557
- }], customMenuActions: [{
1558
- type: Input
1559
- }], customColumns: [{
1560
- type: Input
1561
- }], localEditedAttachments: [{
1562
- type: Output
1563
- }], abortAddAttachment: [{
1564
- type: Output
1565
- }], downloadAttachment: [{
1566
- type: Output,
1567
- args: ["downloadAttachment"]
1568
- }], onDeleteAttachment: [{
1569
- type: Output,
1570
- args: ["onDeleteAttachment"]
1571
- }], dialogAddAttachment: [{
1572
- type: ViewChild,
1573
- args: ["dialogAddAttachment", { static: true }]
1574
- }], dialogAddMultipleAttachment: [{
1575
- type: ViewChild,
1576
- args: ["dialogAddMultipleAttachment", { static: true }]
1577
- }], dialogCropImage: [{
1578
- type: ViewChild,
1579
- args: ["dialogCropImage", { static: true }]
1580
- }], addingLinkTemplate: [{
1581
- type: ViewChild,
1582
- args: ['addingLinkTemplate']
1583
- }], imageCropper: [{
1584
- type: ViewChild,
1585
- args: [ImageCropperComponent]
1586
- }], imageInput: [{
1587
- type: ViewChild,
1588
- args: ["imageInput"]
1589
- }], inlinePreviewTemplate: [{
1590
- type: ViewChild,
1591
- args: ["inlinePreviewTemplate", { static: true }]
1592
- }], dialogPreview: [{
1593
- type: ViewChild,
1594
- args: ["dialogPreview", { static: true }]
1595
- }], defaultFileTemplate: [{
1596
- type: ViewChild,
1597
- args: ['defaultFileTemplate', { static: true }]
1598
- }], defaultActionsTemplate: [{
1599
- type: ViewChild,
1600
- args: ['defaultActionsTemplate', { static: true }]
1601
- }] } });
1602
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL2VxcC1hdHRhY2htZW50cy9zcmMvbGliL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi9wcm9qZWN0cy9lcXAtYXR0YWNobWVudHMvc3JjL2xpYi9lcXAtYXR0YWNobWVudHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUVMLFNBQVMsRUFDVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFFTixTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUEwQixVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUdwRSxPQUFPLGdCQUFnQixNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxZQUFZLEVBQXFCLHFCQUFxQixFQUFrQixNQUFNLG1CQUFtQixDQUFDO0FBQzNHLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3RFLE9BQU8sRUFBbUUsY0FBYyxFQUFrQyxvQkFBb0IsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBRWpMLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLDBDQUEwQyxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7O0FBS3RGLE1BQU0sUUFBUSxHQUFHLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDeEIsSUFBSSxPQUFPLENBQVMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7SUFDdEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxVQUFVLEVBQUUsQ0FBQztJQUNoQyxNQUFNLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNCLE1BQU0sQ0FBQyxNQUFNLEdBQUcsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztJ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RSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBIdHRwQ2xpZW50IH0gZnJvbSBcIkBhbmd1bGFyL2NvbW1vbi9odHRwXCI7XHJcbmltcG9ydCB7XHJcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXHJcbiAgQ29tcG9uZW50LFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBJbnB1dCxcclxuICBPbkluaXQsXHJcbiAgT3V0cHV0LFxyXG4gIFRlbXBsYXRlUmVmLFxyXG4gIFZpZXdDaGlsZFxyXG59IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IEZvcm1CdWlsZGVyLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tIFwiQGFuZ3VsYXIvZm9ybXNcIjtcclxuaW1wb3J0IHsgTWF0RGlhbG9nLCBNYXREaWFsb2dSZWYgfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nXCI7XHJcbmltcG9ydCB7IERvbVNhbml0aXplciB9IGZyb20gXCJAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyXCI7XHJcbmltcG9ydCBpbWFnZUNvbXByZXNzaW9uIGZyb20gXCJicm93c2VyLWltYWdlLWNvbXByZXNzaW9uXCI7XHJcbmltcG9ydCB7IGJhc2U2NFRvRmlsZSwgSW1hZ2VDcm9wcGVkRXZlbnQsIEltYWdlQ3JvcHBlckNvbXBvbmVudCwgSW1hZ2VUcmFuc2Zvcm0gfSBmcm9tIFwibmd4LWltYWdlLWNyb3BwZXJcIjtcclxuaW1wb3J0IHsgQXR0YWNobWVudEhlbHBlclNlcnZpY2UgfSBmcm9tIFwiLi9oZWxwZXJzL2F0dGFjaG1lbnQuaGVscGVyXCI7XHJcbmltcG9ydCB7IEF0dGFjaG1lbnRDYXJkU2l6ZSwgQXR0YWNobWVudEZpZWxkQ29sdW1uLCBBdHRhY2htZW50TWVudUFjdGlvbiwgQXR0YWNobWVudFR5cGUsIENyb3BPcHRpb25FbnVtLCBJQXR0YWNobWVudERUTywgVHlwZUF0dGFjaG1lbnRDb2x1bW4gfSBmcm9tIFwiLi9pbnRlcmZhY2VzL0lBdHRhY2htZW50XCI7XHJcbmltcG9ydCB7IElPcHRpb25zIH0gZnJvbSBcIi4vaW50ZXJmYWNlcy9JT3B0aW9uc1wiO1xyXG5pbXBvcnQgeyBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZSB9IGZyb20gXCIuL3NlcnZpY2VzL2VxcC1hdHRhY2htZW50LWRpYWxvZy5zZXJ2aWNlXCI7XHJcbmltcG9ydCB7IEVxcEF0dGFjaG1lbnRTZXJ2aWNlIH0gZnJvbSBcIi4vc2VydmljZXMvZXFwLWF0dGFjaG1lbnQuc2VydmljZVwiO1xyXG5cclxuZGVjbGFyZSB2YXIgRHJvcGJveDogYW55O1xyXG5cclxuY29uc3QgdG9CYXNlNjQgPSAoZmlsZSkgPT5cclxuICBuZXcgUHJvbWlzZTxzdHJpbmc+KChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlKTtcclxuICAgIHJlYWRlci5vbmxvYWQgPSAoKSA9PiByZXNvbHZlKHJlYWRlci5yZXN1bHQudG9TdHJpbmcoKSk7XHJcbiAgICByZWFkZXIub25lcnJvciA9IChlcnJvcikgPT4gcmVqZWN0KGVycm9yKTtcclxuICB9KTtcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiBcImVxcC1hdHRhY2htZW50c1wiLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmxzOiBbXCIuL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQuc2Nzc1wiXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgRXFwQXR0YWNobWVudHNDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gIC8vI3JlZ2lvbiBASW5wdXQgZGVsIGNvbXBvbmVudGVcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgbmFzY29uZGUgbGEgY29sb25uYSBwZXIgbGUgYXppb25pIHN1bGwnYWxsZWdhdG8gKG5lbCBjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZGlzYWJsZUFjdGlvblwiKSBkaXNhYmxlQWN0aW9uOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgbW9zdHJhIGlsIHRpdG9sbyBuZWxsJ2hlYWRlciBuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFIChcIkVsZW5jbyBhbGxlZ2F0aVwiIGRpIGRlZmF1bHQpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dIZWFkZXJcIikgc2hvd0hlYWRlcjogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNvcmdlbnRlIGRhdGkgZGEgdmlzdWFsaXp6YXJlLiBOZWwgY2FzbyBzaSB2dW9sZSBnZXN0aXJlIHVuIHNpbmdvbG8gYWxsZWdhdG8gdmEgcGFzc2F0byBpbiBvZ25pIGNhc28gY29tZSBBcnJheS5cclxuICAgKi9cclxuICBASW5wdXQoXCJhdHRhY2htZW50c0xpc3RcIikgYXR0YWNobWVudHNMaXN0OiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBOZWwgY2FzbyBzaSB2dW9sZSBnZXN0aXJlIHVuIHNvbG8gZWxlbWVudG8gc2VuemEgcGFzc2FybG8gY29tZSBhcnJheSwgbG8gcGFzc28gY29tZSBzaW5nb2xvIGFsbGVnYXRvIGUgZ2VzdGlzY28gbmVsbGEgbGlicmVyaWEgbCdhcnJheS5cclxuICAgKi9cclxuICBASW5wdXQoXCJzaW5nbGVBdHRhY2htZW50XCIpIHNpbmdsZUF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBub24gbW9zdHJhIGxhIE1hdENhcmQgKG5lbCBjYXNvIGluIGN1aSBcIm11bHRpcGxlQXR0YWNobWVudFwiIMOoIFRSVUUpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dNYXRDYXJkXCIpIHNob3dNYXRDYXJkOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgRkFMU0UgYWxsb3JhIGlsIGNvbXBvbmVudGUgbW9zdHJhIHNvbG8gaWwgcHVsc2FudGUgZGkgY2FyaWNhbWVudG8gZGkgdW4gc2luZ29sbyBmaWxlLCB1bmEgdm9sdGEgY2FyaWNhdG8gaWwgZmlsZSBpbnZvY2EgbCdldmVudG8gZGkgb3V0cHV0IFwibG9jYWxFZGl0ZWRBdHRhY2htZW50c1wiLlxyXG4gICAqIFNlIFRSVUUgYWxsb3JhIGlsIGNvbXBvbmVudGUgbW9zdHJhIGwnZWxlbmNvIGRpIHR1dHRpIGdsaSBhbGxlZ2F0aSByaWNldnV0byBuZWwgcGFyYW1ldHJvIFwiYXR0YWNobWVudHNMaXN0XCIuXHJcbiAgICovXHJcbiAgQElucHV0KFwibXVsdGlwbGVBdHRhY2htZW50XCIpIG11bHRpcGxlQXR0YWNobWVudDogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIGFzc3VtZSBpbCB2YWxvcmUgVFJVRSBhbGxvcmEgc2Fyw6AgcG9zc2liaWxlIGNhcmljYXJlIHBpw7kgZmlsZSBwZXIgdm9sdGEuIFF1ZXN0YSBmdW56aW9uYWxpdMOgIMOoIGF0dGl2YVxyXG4gICAqIFNPTE8gc2Ugc2kgZ2VzdGlzY29ubyBhbGxlZ2F0aSBtdWx0aXBsaSwgcXVpbmRpIHNlIGwnaW5wdXQgJ211bHRpcGxlQXR0YWNobWVudCcgYXNzdW1lIGlsIHZhbG9yZSBUUlVFLCBhbHRyaW1lbnRpIMOoIHNlbXByZSBkaXNhYmlsaXRhdGEuXHJcbiAgICovXHJcbiAgQElucHV0KFwibG9hZE11bHRpcGxlRmlsZXNcIikgbG9hZE11bHRpcGxlRmlsZXM6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW1wb3N0YSBpbCBtZXNzYWdnaW8gZGEgdmlzdWFsaXp6YXJlIG5lbCBjYXNvIGluIGN1aSBsYSB0YWJlbGxhIGRlZ2xpIGFsbGVnYXRpIChuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFKSDDqCB2dW90YS5cclxuICAgKi9cclxuICBASW5wdXQoXCJlbXB0eVRhYmxlTWVzc2FnZVwiKSBlbXB0eVRhYmxlTWVzc2FnZTogc3RyaW5nID0gXCJOZXNzdW4gZGF0byB0cm92YXRvXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgYWxsb3JhIHBlcm1ldHRlIGRpIHNlbGV6aW9uYXJlIHNvbHRhbnRvIGZpbGUgZGkgdGlwbyBpbW1hZ2luZSwgYXZlbnRlIHVubyBkZWkgbWltZXR5cGVcclxuICAgKiBzcGVjaWZpY2F0aSBkZW50cm8gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuXHJcbiAgICogU2UgRkFMU0UgcGVybWV0dGUgZGkgc2VsZXppb25hcmUgcXVhbHNpYXNpIHRpcG8gZGkgZmlsZVxyXG4gICAqL1xyXG4gIEBJbnB1dChcImFsbG93T25seUltYWdlc1wiKSBhbGxvd09ubHlJbWFnZXM6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU3BlY2lmaWNhIGkgdGlwaSBkaSBmaWxlIGNoZSDDqCBwb3NzaWJpbGUgY2FyaWNhcmVcclxuICAgKi9cclxuICBASW5wdXQoXCJhY2NlcHRlZEZpbGVUeXBlc1wiKSBhY2NlcHRlZEZpbGVUeXBlczogc3RyaW5nO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIGRpc2FiaWxpdGEgaWwgcHVsc2FudGUgZGkgQWdnaXVudGEgYWxsZWdhdG8gKGEgcHJlc2NpbmRlcmUgZGFsIHZhbG9yZSBkZWwgcGFyYW1ldHJvIFwibXVsdGlwbGVBdHRhY2htZW50XCIpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImlzRGlzYWJsZWRcIikgaXNEaXNhYmxlZDogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBNb3N0cmEvbmFzY29uZGUgbGEgY29sb25uYSBwZXIgdmlzdWFsaXp6YXJlIGwnYW50ZXByaW1hIGRlaSBmaWxlIG5lbGxhIHRhYmVsbGEgKGNhc28gbXVsdGlwbGVBdGF0Y2htZW50cyA9IHRydWUpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dJbmxpbmVQcmV2aWV3XCIpIHNob3dJbmxpbmVQcmV2aWV3OiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIEVuZHBvaW50IGRhIGNoaWFtYXJlIHBlciByZWN1ZXByYXJlIGwnSUF0dGFjaG1lbnREVE8gY29tcGxldG8gZGEgdmVkZXJlIG5lbGwnYW50ZXByaW1hLiBMYSBjaGlhbWF0YSBzYXLDoCBpbiBQT1NUIGUgbmVsIGJvZHlcclxuICAgKiBjb250ZXJyw6AgbCdJQXR0YWNobWVudERUTyBzZWxlemlvbmF0byBkYWxsJ3V0ZW50ZS5cclxuICAgKiBMYSBjaGlhbWF0YSB2aWVuZSBlc2VndWl0YSBzb2xvIHBlciBsJ2FudGVwcmltYSBkZWxsZSBpbW1hZ2luaSBlc3NlbmRvIG5lY2Vzc2FyaW8gaWwgYmFzZTY0IGNvbXBsZXRvIGRlbGwnaW1tYWdpbmUgYSBkaW1lbnNpb25lIHJlYWxlLlxyXG4gICAqIFBlciBkb2N1bWVudGkvbGluayBiYXN0YSBjaGUgc2lhIHBvcG9sYXRhIGxhIHByb3ByaWV0w6AgRmlsZVBhdGggZGkgSUF0dGFjaG1lbnREVE8uXHJcbiAgICovXHJcbiAgQElucHV0KFwiZ2V0QXR0YWNobWVudEVuZHBvaW50XCIpIGdldEF0dGFjaG1lbnRFbmRwb2ludDogc3RyaW5nID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogSG9zdG5hbWUgZGVsbCdhbWJpZW50ZSBkaSBwcm9kdXppb25lIGRlbGwnYXBwbGljYXRpdm8uIE5lY2Vzc2FyaW8gcGVyIHZpc3VhbGl6emFyZSBsJ2FudGVwcmltYSBkZWkgZG9jdW1lbnRpXHJcbiAgICogdHJhbWl0ZSBpbCB2aWV3ZXIgZGkgZ29vZ2xlLlxyXG4gICAqIE5PVEE6IFBlciB2aXN1YWxpenphcmUgbCdhbnRlcHJpbWEgw6ggbmVjZXNzYXJpbyBjaGUgbGEgcHJvcmlldMOgIEZpbGVQYXRoIGRlbGwnSUF0dGFjaG1lbnREVE8gc2lhIHBvcG9sYXRhIGUgY2hlXHJcbiAgICogc2lhIGFiaWxpdGF0byBsJ2FjY2Vzc28gYWxsYSBjYXJ0ZWxsYSBzdWwgc2VydmVyIHRyYW1pdGUgaG9zdG5hbWUuXHJcbiAgICovXHJcbiAgQElucHV0KFwicHJvZHVjdGlvbkJhc2VVcmxcIikgcHJvZHVjdGlvbkJhc2VVcmw6IHN0cmluZyA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIE9wemlvbmkgcGVyIGxhIGNvbXByZXNzaW9uZSBkZWxsZSBpbW1hZ2luaSBjYXJpY2F0ZS5cclxuICAgKi9cclxuICBASW5wdXQoXCJjb21wcmVzc2lvbk9wdGlvbnNcIikgY29tcHJlc3Npb25PcHRpb25zOiBJT3B0aW9ucyA9IHtcclxuICAgIG1heFNpemVNQjogMC41LFxyXG4gICAgbWF4V2lkdGhPckhlaWdodDogMTkyMCxcclxuICAgIHVzZVdlYldvcmtlcjogdHJ1ZVxyXG4gIH07XHJcblxyXG4gIC8qKlxyXG4gICAqIEFycmF5IGRpIEF0dGFjaG1lbnRUeXBlIGNoZSBzaSBwb3Nzb25vIGFnZ2l1bmdlcmVcclxuICAgKi9cclxuICBASW5wdXQoXCJhbGxvd2VkVHlwZXNcIikgYWxsb3dlZFR5cGVzOiBBcnJheTxBdHRhY2htZW50VHlwZT4gPSBbQXR0YWNobWVudFR5cGUuRklMRSwgQXR0YWNobWVudFR5cGUuTElOS107XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSBzZSBsYSBlcXAtdGFibGUgY29udGVuZW50ZSBsJ2VsZW5jbyBkZWdsaSBhbGxlZ2F0aSB1dGlsaXp6YVxyXG4gICAqIGlsIG11bHRpbGluZ3VhIG9wcHVyZSBub1xyXG4gICAqL1xyXG4gIEBJbnB1dChcImlzRXFwVGFibGVNdWx0aUxhbmd1YWdlXCIpIGlzRXFwVGFibGVNdWx0aUxhbmd1YWdlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSwgaW4gY2FzbyBkaSBnZXN0aW9uZSBhbGxlZ2F0aSBtdWx0aXBsaSwgc2UgbGEgdGFiZWxsYSBjb250ZW5lbnRlIGwnZWxlbmNvXHJcbiAgICogZGVnbGkgYWxsZWdhdGkgZGV2ZSBlc3NlcmUgcGFnaW5hdGEgb3BwdXJlIG5vXHJcbiAgICovXHJcbiAgQElucHV0KFwidGFibGVQYWdpbmF0b3JWaXNpYmxlXCIpIHRhYmxlUGFnaW5hdG9yVmlzaWJsZTogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSwgaW4gY2FzbyBkaSBnZXN0aW9uZSBhbGxlZ2F0aSBtdWx0aXBsaSwgc2UgbGEgdGFiZWxsYSBjb250ZW5lbnRlIGwnZWxlbmNvXHJcbiAgICogZGVnbGkgYWxsZWdhdGkgZGV2ZSBjb250ZW5lcmUgaWwgY2FtcG8gZGkgcmljZXJjYSBvcHB1cmUgbm9cclxuICAgKi9cclxuICBASW5wdXQoXCJpc1RhYmxlU2VhcmNoZWFibGVcIikgaXNUYWJsZVNlYXJjaGVhYmxlOiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW4gY2FzbyBkaSBnZXN0aW9uZSBhbGxlZ2F0aSBtdWx0aXBsaSwgcGVybWV0dGUgZGkgc3RhYmlsaXJlIGxhIGRpbWVuc2lvbmUgcGFnaW5hIGRpIGRlZmF1bHRcclxuICAgKiBwZXIgbGEgdGFiZWxsYSBjb250ZW5lbnRlIGwnZWxlbmNvIGRlZ2xpIGFsbGVnYXRpXHJcbiAgICovXHJcbiAgQElucHV0KFwidGFibGVQYWdpbmF0b3JTaXplXCIpIHRhYmxlUGFnaW5hdG9yU2l6ZTogbnVtYmVyID0gbnVsbDtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc2NlZ2xpZXJlIGlsIG1vZG8gaW4gY3VpIGkgZmlsZSBkZXZvbm8gZXNzZXJlIGNhcmljYXRpXHJcbiAgICovXHJcbiAgLy8gQElucHV0KFwidXBsb2FkVHlwZVwiKSB1cGxvYWRUeXBlOiBVcGxvYWRUeXBlRW51bSA9IFVwbG9hZFR5cGVFbnVtLkZJTEVfQU5EX0xJTks7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHN0YWJpbGlyZSBzZSBpIHB1bHNhbnRpIHBlciBpbCBjYXJpY2FtZW50byBkZWkgZmlsZSBzb25vIHNlcGFyYXRpIG8gaW4gdW4gbWVuw7kgYSB0ZW5kaW5hXHJcbiAgICovXHJcbiAgQElucHV0KFwic2VwYXJhdGVkVXBsb2FkQnV0dG9uc1wiKSBzZXBhcmF0ZWRVcGxvYWRCdXR0b25zOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFBlcm1ldHRlIGRpIHNjZWdsaWVyZSBzZSBkYXJlIGxhIHBvc3NpYmlsaXTDoCBkaSB2ZWRlcmUgbyBubyBsJ2FudGVwcmltYVxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dQcmV2aWV3XCIpIHNob3dQcmV2aWV3OiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogSW4gY2FzbyBkaSBhbGxlZ2F0byBzaW5nb2xvLCBwZXJtZXR0ZSBkaSBzY2VnbGllcmUgc2UgYWdnaXVuZ2VyZSBmaWxlIHRyYW1pdGUgZHJhZyBhbmQgZHJvcFxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNpbmdsZUF0dGFjaG1lbnREcmFnQW5kRHJvcFwiKSBzaW5nbGVBdHRhY2htZW50RHJhZ0FuZERyb3A6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBBcnJheSBkaSBvcHppb25pIGNoZSBzaSBwb3Nzb25vIHV0aWxpenphcmUgcGVyIGlsIGNyb3BcclxuICAgKi9cclxuICBASW5wdXQoXCJjcm9wT3B0aW9uc1wiKSBjcm9wT3B0aW9uczogQXJyYXk8Q3JvcE9wdGlvbkVudW0+ID0gWzEsIDJdO1xyXG5cclxuICAvKipcclxuICAgKiBDbGFzc2UgY3VzdG9tIGRhIGFzc2VnbmFyZSBhbCBkaWFsb2cgZGVsIGNyb3AgaW1tYWdpbmlcclxuICAgKi9cclxuICBASW5wdXQoXCJjcm9wRGlhbG9nQ2xhc3NcIikgY3JvcERpYWxvZ0NsYXNzOiBzdHJpbmc7XHJcblxyXG4gIEBJbnB1dCgpIG1heEZpbGVTaXplTUI6IG51bWJlciA9IDUwMDsgLy8gRGVmYXVsdCBtYXggc2l6ZSBvZiAxMDAgTUJcclxuICBASW5wdXQoKSBjYXJkU2l6ZTogQXR0YWNobWVudENhcmRTaXplID0gJ3NtYWxsJzsgLy8gRGVmYXVsdFxyXG4gIEBJbnB1dCgpIGN1c3RvbUNhcmRXaWR0aFB4OiBudW1iZXIgPSAyMDA7IC8vIExhcmdoZXp6YSBjdXN0b20gaW4gcHhcclxuICBASW5wdXQoKSBjdXN0b21DYXJkSGVpZ2h0UHg6IG51bWJlciA9IDE4MDsgLy8gQWx0ZXp6YSBjdXN0b20gaW4gcHhcclxuXHJcbiAgQElucHV0KCkgbGF5b3V0OiAnZnVsbCcgfCAnY29tcGFjdCcgPSAnY29tcGFjdCc7XHJcblxyXG4gIC8qKlxyXG4gICAqIElucHV0IHBlciBkZWZpbmlyZSBsZSBsYWJlbCBkYSB1c2FyZSBuZWwgY29tcG9uZW50ZVxyXG4gICAqL1xyXG4gIEBJbnB1dChcIm9wZW5MaW5rTGFiZWxcIikgb3BlbkxpbmtMYWJlbDogc3RyaW5nID0gXCJBcHJpIGxpbmtcIjtcclxuICBASW5wdXQoXCJhZGRCdXR0b25MYWJlbFwiKSBhZGRCdXR0b25MYWJlbDogc3RyaW5nID0gXCJBZ2dpdW5naVwiO1xyXG4gIEBJbnB1dChcImRvd25sb2FkTGFiZWxcIikgZG93bmxvYWRMYWJlbDogc3RyaW5nID0gXCJEb3dubG9hZFwiO1xyXG4gIEBJbnB1dChcImRlbGV0ZUxhYmVsXCIpIGRlbGV0ZUxhYmVsOiBzdHJpbmcgPSBcIkVsaW1pbmFcIjtcclxuICBASW5wdXQoXCJmaWxlTmFtZUxhYmVsXCIpIGZpbGVOYW1lTGFiZWw6IHN0cmluZyA9IFwiTm9tZSBmaWxlXCI7XHJcbiAgQElucHV0KFwicHJldmlld0xhYmVsXCIpIHByZXZpZXdMYWJlbDogc3RyaW5nID0gXCJBbnRlcHJpbWFcIjtcclxuICBASW5wdXQoXCJ1cGxvYWRGaWxlTGFiZWxcIikgdXBsb2FkRmlsZUxhYmVsOiBzdHJpbmcgPSBcIkNhcmljYSBmaWxlXCI7XHJcbiAgQElucHV0KFwiY29uZmlybUxhYmVsXCIpIGNvbmZpcm1MYWJlbDogc3RyaW5nID0gXCJDb25mZXJtYVwiO1xyXG4gIEBJbnB1dChcImFib3J0TGFiZWxcIikgYWJvcnRMYWJlbDogc3RyaW5nID0gXCJBbm51bGxhXCI7XHJcbiAgQElucHV0KFwic2F2ZUxhYmVsXCIpIHNhdmVMYWJlbDogc3RyaW5nID0gXCJTYWx2YVwiO1xyXG4gIEBJbnB1dChcImV4aXRMYWJlbFwiKSBleGl0TGFiZWw6IHN0cmluZyA9IFwiRXNjaVwiO1xyXG4gIEBJbnB1dChcInVwbG9hZFdpdGhEcm9wYm94TGFiZWxcIikgdXBsb2FkV2l0aERyb3Bib3hMYWJlbDogc3RyaW5nID0gXCJDYXJpY2EgY29uIERyb3Bib3hcIjtcclxuICBASW5wdXQoXCJjcm9wTGFiZWxcIikgY3JvcExhYmVsOiBzdHJpbmcgPSBcIlNjZWdsaSBsZSBkaW1lbnNpb25pIGRlbGwnaW1tYWdpbmVcIjtcclxuICBASW5wdXQoXCJkZWxldGVEaWFsb2dUaXRsZVwiKSBkZWxldGVEaWFsb2dUaXRsZTogc3RyaW5nID0gbnVsbDtcclxuICBASW5wdXQoXCJkZWxldGVEaWFsb2dNZXNzYWdlXCIpIGRlbGV0ZURpYWxvZ01lc3NhZ2U6IHN0cmluZyA9IFwiU2VpIHNpY3VybyBkaSB2b2xlciBjYW5jZWxsYXJlIHF1ZXN0J2FsbGVnYXRvP1wiO1xyXG4gIEBJbnB1dChcIm5vSW1hZ2VTZWxlY3RlZEVycm9yTWVzc2FnZVwiKSBub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIk5vbiDDqCBwb3NzaWJpbGUgc2VsZXppb25hcmUgdW4gZmlsZSBjaGUgbm9uIHNpYSB1bidpbW1hZ2luZS5cIjtcclxuICBASW5wdXQoXCJ3cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZVwiKSB3cm9uZ1R5cGVTZWxlY3RlZEVycm9yTWVzc2FnZTogc3RyaW5nID1cclxuICAgIFwiTm9uIMOoIHBvc3NpYmlsZSBjYXJpY2FyZSBpbCBmaWxlIHNlbGV6aW9uYXRvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSB2aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkaSB1biBmaWxlIHZpZGVvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSBhdWRpb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9XHJcbiAgICBcIkltcG9zc2liaWxlIGFwcmlyZSBsJ2FudGVwcmltYSBkaSB1biBmaWxlIGF1ZGlvLlwiO1xyXG4gIEBJbnB1dChcImZsaXBIb3JpbnpvbnRhbExhYmVsXCIpIGZsaXBIb3JpbnpvbnRhbExhYmVsOiBzdHJpbmcgPSBcIkNhcG92b2xnaSBvcml6em9udGFsbWVudGVcIjtcclxuICBASW5wdXQoXCJmbGlwVmVydGljYWxMYWJlbFwiKSBmbGlwVmVydGljYWxMYWJlbDogc3RyaW5nID0gXCJDYXBvdm9sZ2kgdmVydGljYWxtZW50ZVwiO1xyXG4gIEBJbnB1dChcInJvdGF0ZVJpZ2h0TGFiZWxcIikgcm90YXRlUmlnaHRMYWJlbDogc3RyaW5nID0gXCJSdW90YSBhIGRlc3RyYVwiO1xyXG4gIEBJbnB1dChcInJvdGF0ZUxlZnRMYWJlbFwiKSByb3RhdGVMZWZ0TGFiZWw6IHN0cmluZyA9IFwiUnVvdGEgYSBzaW5pc3RyYVwiO1xyXG4gIEBJbnB1dChcImJhc2U2NExpbWl0TUJcIikgYmFzZTY0TGltaXRNQjogbnVtYmVyID0gMTAwO1xyXG4gIEBJbnB1dCgpIHVwbG9hZFRpdGxlID0gJ1VwbG9hZCBmaWxlJztcclxuICBASW5wdXQoKSB1cGxvYWRTdWJ0aXRsZSA9ICdEcmFnICYgZHJvcCBmaWxlcyBvIGNsaWNrJztcclxuICBASW5wdXQoKSBkcm9wSGVyZUxhYmVsID0gJ1JpbGFzY2lhIGkgZmlsZSBxdWknO1xyXG4gIEBJbnB1dCgpIHN1cHBvcnRlZEZvcm1hdHNMYWJlbCA9ICdGb3JtYXRpIHN1cHBvcnRhdGk6IEpQRUcsIFBORywgUERGIChNYXggMTAwTUIpJztcclxuICBASW5wdXQoKSBicm93c2VGaWxlc0xhYmVsID0gJ0NlcmNhIGkgZmlsZSc7XHJcbiAgQElucHV0KCkgdXBsb2FkU3VtbWFyeUxhYmVsID0gJ0xpc3RhIGFsbGVnYXRpJztcclxuICBASW5wdXQoKSBmaWxlc0xhYmVsID0gJ0ZpbGVzJztcclxuICBASW5wdXQoKSB0b3RhbFNpemVMYWJlbCA9ICdEaW1lbnNpb25lIHRvdGFsZSc7XHJcbiAgQElucHV0KCkgZW1wdHlTdGF0ZUxhYmVsID0gJ05vbiBzb25vIHByZXNlbnRpIGZpbGUgY2FyaWNhdGknO1xyXG4gIEBJbnB1dCgpIGFkZGVkU3VjY2Vzc2Z1bGx5TGFiZWwgPSAnZmlsZShzKSBjYXJpY2F0aSBjb24gc3VjY2Vzc28uJztcclxuICBASW5wdXQoKSByZW1vdmVkTGFiZWwgPSAnRmlsZSByaW1vc3NvJztcclxuICAvLyBASW5wdXQoKSByZW1vdmVMYWJlbCA9ICdSaW11b3ZpIGZpbGUnO1xyXG4gIEBJbnB1dCgpIGNob29zZVZpZXcgPSB0cnVlO1xyXG4gIEBJbnB1dCgpIHNob3dTdW1tYXJ5ID0gZmFsc2U7XHJcbiAgQElucHV0KFwidmlld01vZGVcIikgdmlld01vZGU6ICdjYXJkJyB8ICd0YWJsZScgPSAndGFibGUnO1xyXG4gIEBJbnB1dChcInNob3dVcGxvYWRUaXRsZVwiKSBzaG93VXBsb2FkVGl0bGU6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dChcInNob3dEcm9wQXJlYVwiKSBzaG93RHJvcEFyZWE6IGJvb2xlYW4gPSB0cnVlO1xyXG4gIEBJbnB1dCgpIGhpZGRlbkNvbHVtbnM6IHN0cmluZ1tdID0gW107XHJcbiAgQElucHV0KCkgaGlkZGVuQWN0aW9uczogc3RyaW5nW10gPSBbXTtcclxuICBASW5wdXQoKSBzaG93QWN0aW9uQnV0dG9uczogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgYWxsb3JhIG1vc3RyYSBpbCBkaWFsb2cgZGkgY3JvcCBwZXIgbGUgaW1tYWdpbmkgc2luZ29sZS5cclxuICAgKiBTZSBGQUxTRSBjYXJpY2EgbCdpbW1hZ2luZSBkaXJldHRhbWVudGUgKGFwcGxpY2FuZG8gY29tdW5xdWUgbGEgY29tcHJlc3Npb25lIHNlIGF0dGl2YSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZW5hYmxlSW1hZ2VDcm9wXCIpIGVuYWJsZUltYWdlQ3JvcDogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIEhvb2sgZ2xvYmFsZTogZGVjaWRlIHNlIG5hc2NvbmRlcmUgdW7igJlhemlvbmUgcGVyIHF1ZWxsbyBzcGVjaWZpY28gYWxsZWdhdG8uXHJcbiAgICovXHJcbiAgQElucHV0KCkgYWN0aW9uSGlkZGVuRm4/OiAoYWN0aW9uS2V5OiBzdHJpbmcsIGF0dD86IElBdHRhY2htZW50RFRPKSA9PiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBIb29rIGdsb2JhbGU6IGRlY2lkZSBzZSBkaXNhYmlsaXRhcmUgdW7igJlhemlvbmUgcGVyIHF1ZWxsbyBzcGVjaWZpY28gYWxsZWdhdG8uXHJcbiAgICovXHJcbiAgQElucHV0KCkgYWN0aW9uRGlzYWJsZWRGbj86IChhY3Rpb25LZXk6IHN0cmluZywgYXR0PzogSUF0dGFjaG1lbnREVE8pID0+IGJvb2xlYW47XHJcblxyXG5cclxuICBASW5wdXQoKSB2aWRlb0NvbXByZXNzaW9uOiB7XHJcbiAgICBlbmFibGVkOiBib29sZWFuO1xyXG4gICAgbWF4V2lkdGg/OiBudW1iZXI7XHJcbiAgICBiaXRyYXRlPzogbnVtYmVyO1xyXG4gICAgY3JmPzogbnVtYmVyO1xyXG4gICAgcHJlc2V0Pzogc3RyaW5nO1xyXG4gICAgbWF4RnBzPzogbnVtYmVyO1xyXG4gICAgYXVkaW9CaXRyYXRlPzogbnVtYmVyO1xyXG4gIH0gPSB7IGVuYWJsZWQ6IGZhbHNlLCBtYXhXaWR0aDogMTI4MCwgY3JmOiAyMywgcHJlc2V0OiAndmVyeWZhc3QnLCBtYXhGcHM6IDMwLCBhdWRpb0JpdHJhdGU6IDEyODAwMCB9O1xyXG5cclxuXHJcbiAgcHJpdmF0ZSBfY3VzdG9tTWVudUFjdGlvbnM6IEF0dGFjaG1lbnRNZW51QWN0aW9uW10gPSBbXTtcclxuICBfc29ydGVkTWVudUFjdGlvbnM6IEF0dGFjaG1lbnRNZW51QWN0aW9uW10gPSBbXTtcclxuXHJcblxyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IGN1c3RvbU1lbnVBY3Rpb25zKHZhbHVlOiBBdHRhY2htZW50TWVudUFjdGlvbltdKSB7XHJcbiAgICB0aGlzLl9jdXN0b21NZW51QWN0aW9ucyA9IHZhbHVlIHx8IFtdO1xyXG4gICAgdGhpcy5zZXR1cE1lbnVBY3Rpb25zKCk7XHJcbiAgfVxyXG5cclxuICBnZXQgY3VzdG9tTWVudUFjdGlvbnMoKTogQXR0YWNobWVudE1lbnVBY3Rpb25bXSB7XHJcbiAgICByZXR1cm4gdGhpcy5fY3VzdG9tTWVudUFjdGlvbnM7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIF9jdXN0b21Db2x1bW5zOiBBdHRhY2htZW50RmllbGRDb2x1bW5bXSA9IFtdO1xyXG5cclxuICAvKipcclxuICAgKiBTT0xPIHF1YW5kbyBbY3VzdG9tQ29sdW1uc109XCIuLi5cIiBjYW1iaWEuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBzZXQgY3VzdG9tQ29sdW1ucyh2YWx1ZTogQXR0YWNobWVudEZpZWxkQ29sdW1uW10pIHtcclxuICAgIHRoaXMuX2N1c3RvbUNvbHVtbnMgPSB2YWx1ZSB8fCBbXTtcclxuICAgIHRoaXMuc2V0dXBUYWJsZUNvbHVtbnMoKTtcclxuICB9XHJcblxyXG4gIGdldCBjdXN0b21Db2x1bW5zKCk6IEF0dGFjaG1lbnRGaWVsZENvbHVtbltdIHtcclxuICAgIHJldHVybiB0aGlzLl9jdXN0b21Db2x1bW5zO1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8vI3JlZ2lvbiBAT3V0cHV0IGRlbCBjb21wb25lbnRlXHJcblxyXG5cclxuICAvKipcclxuICAgKiBSZXN0aXR1aXNjZSBsYSBsaXN0YSBhZ2dpb3JuYXRhIGRlZ2xpIGFsbGVnYXRpLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBsb2NhbEVkaXRlZEF0dGFjaG1lbnRzOiBFdmVudEVtaXR0ZXI8QXJyYXk8SUF0dGFjaG1lbnREVE8+PiA9IG5ldyBFdmVudEVtaXR0ZXI8QXJyYXk8SUF0dGFjaG1lbnREVE8+PigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gc2NhdGVuYXRvIGFsbGEgcHJlc3Npb25lIGRlbCBwdWxzYW50ZSBFU0NJIGRlbGxhIG1vZGFsZSBkaSBjYXJpY2FtZW50byBmaWxlLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoKSBhYm9ydEFkZEF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGwnSUF0dGFjaG1lbnREVE8gc2VsZXppb25hdG8gcGVyIGlsIGRvd25sb2FkIG5lbCBjYXNvIEZpbGVEYXRhQmFzZTY0LCBGaWxlQ29udGVudFR5cGUgbyBGaWxlTmFtZSBub24gZm9zc2VybyBzcGVjaWZpY2F0aS5cclxuICAgKi9cclxuICBAT3V0cHV0KFwiZG93bmxvYWRBdHRhY2htZW50XCIpIGRvd25sb2FkQXR0YWNobWVudDogRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPiA9IG5ldyBFdmVudEVtaXR0ZXI8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGwnZWxlbWVudG8gZWxpbWluYXRvIHByaW1hIGNoZSBxdWVzdG8gdmVuZ2EgZWZmZXR0aXZhbWVudGUgcmlzbW9zc28gZGFsbGEgbGlzdGEuXHJcbiAgICovXHJcbiAgQE91dHB1dChcIm9uRGVsZXRlQXR0YWNobWVudFwiKSBvbkRlbGV0ZUF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4gPSBuZXcgRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIFByb3ByaWV0w6AgcGVyIGdlc3Rpb25lIGNhcmljYW1lbnRvIG51b3ZvIGFsbGVnYXRvXHJcbiAgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8gPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICBuZXdNdWx0aXBsZUF0dGFjaG1lbnRzOiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBbXTtcclxuICBhdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlO1xyXG4gIC8vIHVwbG9hZFR5cGVFbnVtID0gVXBsb2FkVHlwZUVudW07XHJcbiAgbmV3QXR0YWNobWVudEZvcm06IEZvcm1Hcm91cDtcclxuICBzZWxlY3RlZEZpbGU6IEZpbGUgPSBudWxsO1xyXG4gIHNlbGVjdGVkRmlsZXM6IEFycmF5PEZpbGU+ID0gbnVsbDtcclxuICBzaG93Q3JvcEltYWdlOiBib29sZWFuID0gZmFsc2U7XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0FkZEF0dGFjaG1lbnRcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nQWRkQXR0YWNobWVudDogVGVtcGxhdGVSZWY8YW55PjtcclxuICBkaWFsb2dSZWZBZGRBdHRhY2htZW50OiBNYXREaWFsb2dSZWY8VGVtcGxhdGVSZWY8YW55Pj47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0FkZE11bHRpcGxlQXR0YWNobWVudFwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dBZGRNdWx0aXBsZUF0dGFjaG1lbnQ6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgZGlhbG9nUmVmQ3JvcEltYWdlOiBNYXREaWFsb2dSZWY8VGVtcGxhdGVSZWY8YW55Pj47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ0Nyb3BJbWFnZVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dDcm9wSW1hZ2U6IFRlbXBsYXRlUmVmPGFueT47XHJcblxyXG4gIEBWaWV3Q2hpbGQoJ2FkZGluZ0xpbmtUZW1wbGF0ZScpIGFkZGluZ0xpbmtUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIFByb3ByaWV0w6AgcGVyIGdlc3Rpb25lIHJpZGltZW5zaW9uYW1lbnRvIGZpbGUgZGkgdGlwbyBpbWFnZVxyXG4gIGltYWdlQ2hhbmdlZEV2ZW50OiBhbnkgPSBcIlwiO1xyXG4gIGNyb3BwZWRJbWFnZTogYW55ID0gXCJcIjtcclxuICB0cmFuc2Zvcm06IEltYWdlVHJhbnNmb3JtID0ge307XHJcbiAgY2FudmFzUm90YXRpb24gPSAwO1xyXG4gIEBWaWV3Q2hpbGQoSW1hZ2VDcm9wcGVyQ29tcG9uZW50KSBpbWFnZUNyb3BwZXI6IEltYWdlQ3JvcHBlckNvbXBvbmVudDtcclxuICBAVmlld0NoaWxkKFwiaW1hZ2VJbnB1dFwiKSBpbWFnZUlucHV0OiBhbnk7XHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIEF0dGFjaG1lbnRUeXBlID0gQXR0YWNobWVudFR5cGU7XHJcbiAgc2VsZWN0ZWRBdHRhY2htZW50OiBJQXR0YWNobWVudERUTztcclxuXHJcbiAgb3JpZ2luYWxXaWR0aDogbnVtYmVyO1xyXG4gIG9yaWdpbmFsSGVpZ2h0OiBudW1iZXI7XHJcbiAgY3VzdG9tV2lkdGg6IG51bWJlcjtcclxuICBjdXN0b21IZWlnaHQ6IG51bWJlcjtcclxuXHJcbiAgQFZpZXdDaGlsZChcImlubGluZVByZXZpZXdUZW1wbGF0ZVwiLCB7IHN0YXRpYzogdHJ1ZSB9KSBpbmxpbmVQcmV2aWV3VGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgQFZpZXdDaGlsZChcImRpYWxvZ1ByZXZpZXdcIiwgeyBzdGF0aWM6IHRydWUgfSkgZGlhbG9nUHJldmlldzogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgaW1hZ2VGaWxlOiBGaWxlO1xyXG5cclxuICBhZGRpbmdMaW5rTW9kZTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvLyNyZWdpb24gU2V6aW9uZSBudW92YSByZWZhY3RvcmluZ1xyXG5cclxuICAvLyBQcm9wcmlldMOgIGludGVybmEgY2hlIGNvbnRlcnLDoCBsJ2FycmF5IGZpbmFsZSBkaSBjb2xvbm5lIG9yZGluYXRlXHJcbiAgX3RhYmxlQ29sdW1uczogQXR0YWNobWVudEZpZWxkQ29sdW1uW10gPSBbXTtcclxuICBAVmlld0NoaWxkKCdkZWZhdWx0RmlsZVRlbXBsYXRlJywgeyBzdGF0aWM6IHRydWUgfSkgZGVmYXVsdEZpbGVUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcclxuICBAVmlld0NoaWxkKCdkZWZhdWx0QWN0aW9uc1RlbXBsYXRlJywgeyBzdGF0aWM6IHRydWUgfSkgZGVmYXVsdEFjdGlvbnNUZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcclxuXHJcbiAgLy8gU3RhdG8gZHJhZyAmIGRyb3AgZSB0b2FzdFxyXG4gIGRyYWdPdmVyID0gZmFsc2U7XHJcbiAgdG9hc3QgPSB7XHJcbiAgICB2aXNpYmxlOiBmYWxzZSBhcyBib29sZWFuLFxyXG4gICAgdHlwZTogJ3N1Y2Nlc3MnIGFzICdzdWNjZXNzJyB8ICdlcnJvcicgfCAnaW5mbycsXHJcbiAgICB0ZXh0OiAnJyBhcyBzdHJpbmcsXHJcbiAgICB0aW1lb3V0SWQ6IDAgYXMgYW55XHJcbiAgfTtcclxuXHJcbiAgcHJvZ3Jlc3NQZXJjZW50ID0gMDtcclxuICB0b3RhbFNpemVCeXRlcyA9IDA7XHJcbiAgZ2V0IHRvdGFsU2l6ZUZvcm1hdHRlZCgpOiBzdHJpbmcgeyByZXR1cm4gdGhpcy5mb3JtYXRGaWxlU2l6ZSh0aGlzLnRvdGFsU2l6ZUJ5dGVzKTsgfVxyXG5cclxuICAvLyBVdGlsaXR5IHBlciBmb3JtYXR0YXJlIGJ5dGVzICgyIGRlY2ltYWxpKVxyXG4gIGZvcm1hdEZpbGVTaXplKGJ5dGVzOiBudW1iZXIpOiBzdHJpbmcge1xyXG4gICAgaWYgKCFieXRlcyB8fCBieXRlcyA8PSAwKSByZXR1cm4gJzAgQnl0ZXMnO1xyXG4gICAgY29uc3QgayA9IDEwMjQ7XHJcbiAgICBjb25zdCBzaXplcyA9IFsnQnl0ZXMnLCAnS0InLCAnTUInLCAnR0InLCAnVEInXTtcclxuICAgIGNvbnN0IGkgPSBNYXRoLmZsb29yKE1hdGgubG9nKGJ5dGVzKSAvIE1hdGgubG9nKGspKTtcclxuICAgIHJldHVybiBgJHtwYXJzZUZsb2F0KChieXRlcyAvIE1hdGgucG93KGssIGkpKS50b0ZpeGVkKDIpKX0gJHtzaXplc1tpXX1gO1xyXG4gIH1cclxuXHJcbiAgLy8gTW9zdHJhIHRvYXN0IGNvbiBhdXRv4oCRaGlkZSBlIHJlc2V0IHByb2dyZXNzIGJhciBDU1NcclxuICBzaG93VG9hc3QobWVzc2FnZTogc3RyaW5nLCB0eXBlOiAnc3VjY2VzcycgfCAnZXJyb3InIHwgJ2luZm8nID0gJ3N1Y2Nlc3MnLCBkdXJhdGlvbk1zID0gMzAwMCkge1xyXG4gICAgaWYgKHRoaXMudG9hc3QudmlzaWJsZSAmJiB0aGlzLnRvYXN0LnRleHQgPT09IG1lc3NhZ2UpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENhbmNlbGxhIGlsIHRpbWVvdXQgcHJlY2VkZW50ZSBzZSBlc2lzdGVcclxuICAgIGlmICh0aGlzLnRvYXN0LnRpbWVvdXRJZCkge1xyXG4gICAgICBjbGVhclRpbWVvdXQodGhpcy50b2FzdC50aW1lb3V0SWQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENhbGNvbGEgdW5hIGR1cmF0YSBkaW5hbWljYVxyXG4gICAgY29uc3QgZHVyYXRpb24gPSBkdXJhdGlvbk1zIHx8IE1hdGgubWF4KDQwMDAsIG1lc3NhZ2UubGVuZ3RoICogMTAwKTtcclxuXHJcbiAgICB0aGlzLnRvYXN0LnRleHQgPSBtZXNzYWdlO1xyXG4gICAgdGhpcy50b2FzdC50eXBlID0gdHlwZTtcclxuICAgIHRoaXMudG9hc3QudmlzaWJsZSA9IHRydWU7XHJcblxyXG4gICAgLy8gSW1wb3N0YSBpbCBudW92byB0aW1lb3V0IHBlciBuYXNjb25kZXJlIGF1dG9tYXRpY2FtZW50ZSBpbCB0b2FzdFxyXG4gICAgdGhpcy50b2FzdC50aW1lb3V0SWQgPSBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgdGhpcy50b2FzdC52aXNpYmxlID0gZmFsc2U7XHJcbiAgICB9LCBkdXJhdGlvbik7XHJcbiAgfVxyXG5cclxuICAjZW5kcmVnaW9uXHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBkaWFsb2c6IE1hdERpYWxvZyxcclxuICAgIHByaXZhdGUgZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyLFxyXG4gICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcclxuICAgIHByaXZhdGUgZXFwQXR0YWNobWVudFNlcnZpY2U6IEVxcEF0dGFjaG1lbnRTZXJ2aWNlXHJcbiAgKSB7IH1cclxuXHJcbiAgbmdPbkluaXQoKSB7XHJcblxyXG4gICAgLy8gSW5pemlhbGl6emEgbWV0cmljaGUgZSBwcm9ncmVzcyBpbiBiYXNlIGFsbG8gc3RhdG8gaW5pemlhbGVcclxuICAgIHRoaXMucmVjb21wdXRlVG90YWxzQW5kUHJvZ3Jlc3MoKTtcclxuXHJcbiAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIGFsbG9yYSBpbXBvc3RhIGlsIGZpbHRybyBwZXIgbGUgZXN0ZW5zaW9uaSBwb3NzaWJpbGkgZGEgY2FyaWNhcmVcclxuICAgIGlmICghdGhpcy5hY2NlcHRlZEZpbGVUeXBlcylcclxuICAgICAgaWYgKHRoaXMuYWxsb3dPbmx5SW1hZ2VzID09IHRydWUpIHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMgPSBcImltYWdlLypcIjtcclxuICAgICAgZWxzZSB0aGlzLmFjY2VwdGVkRmlsZVR5cGVzID0gXCIqXCI7XHJcblxyXG4gICAgLy8gU2Ugbm9uIHNvbm8gc3RhdGkgc3BlY2lmaWNhdGkgaSB0aXBpIGRhIGdlc3RpcmUgbWEgw6ggc3RhdG8gcGFzc2F0byBudWxsIG8gdW4gYXJyYXkgdnVvdG8gaW1wb3N0byBpIHRpcGkgZGkgZGVmYXVsdC5cclxuICAgIGlmICghdGhpcy5hbGxvd2VkVHlwZXMgfHwgdGhpcy5hbGxvd2VkVHlwZXMubGVuZ3RoID09IDApXHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzID0gW0F0dGFjaG1lbnRUeXBlLkZJTEUsIEF0dGFjaG1lbnRUeXBlLkxJTkssIEF0dGFjaG1lbnRUeXBlLkRST1BCT1hdO1xyXG4gICAgZWxzZSBpZiAoXHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzLmZpbmQoKHQpID0+IHQgIT0gQXR0YWNobWVudFR5cGUuRklMRSAmJiB0ICE9IEF0dGFjaG1lbnRUeXBlLkxJTksgJiYgdCAhPSBBdHRhY2htZW50VHlwZS5EUk9QQk9YKVxyXG4gICAgKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLldhcm5pbmcoXHJcbiAgICAgICAgJ0FsbWVubyB1bm8gZGVnbGkgQXR0YWNobWVudFR5cGUgc2VsZXppb25hdGkgbmVsIHBhcmFtZXRybyBcImFsbG93ZWRUeXBlc1wiIG5vbiBlc2lzdGUuJ1xyXG4gICAgICApO1xyXG4gICAgICB0aGlzLmFsbG93ZWRUeXBlcyA9IFtBdHRhY2htZW50VHlwZS5GSUxFLCBBdHRhY2htZW50VHlwZS5MSU5LLCBBdHRhY2htZW50VHlwZS5EUk9QQk9YXTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50c0xpc3QgPT0gbnVsbCkgdGhpcy5hdHRhY2htZW50c0xpc3QgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgLy8gU2Ugw6ggc3RhdG8gcGFzc2F0byB1biBzaW5nb2xvIGFsbGVnYXRvIGxvIGFnZ2l1bmdvIGFsbGEgbGlzdGFcclxuICAgIGlmICh0aGlzLnNpbmdsZUF0dGFjaG1lbnQgIT0gbnVsbCAmJiB0aGlzLmF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCkge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzTGlzdC5wdXNoKHRoaXMuc2luZ2xlQXR0YWNobWVudCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5jaGVja0F0dGFjaG1lbnRJbWFnZSgpO1xyXG5cclxuICAgIGlmICh0aGlzLmFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKSkge1xyXG4gICAgICB0aGlzLmVxcEF0dGFjaG1lbnRTZXJ2aWNlLmxvYWREcm9wYm94U2NyaXB0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5zZXR1cFRhYmxlQ29sdW1ucygpO1xyXG4gICAgdGhpcy5zZXR1cE1lbnVBY3Rpb25zKCk7XHJcbiAgfVxyXG5cclxuICBzZXRWaWV3TW9kZShtb2RlOiAnY2FyZCcgfCAndGFibGUnKTogdm9pZCB7XHJcbiAgICB0aGlzLnZpZXdNb2RlID0gbW9kZTtcclxuICB9XHJcblxyXG4gIC8vIFJpY2FsY29sYSBsYSBzb21tYSBwZXNhdGEgc3VnbGkgYWxsZWdhdGkgcHJlc2VudGlcclxuICBwcml2YXRlIHJlY29tcHV0ZVRvdGFsc0FuZFByb2dyZXNzKCkge1xyXG4gICAgdGhpcy50b3RhbFNpemVCeXRlcyA9ICh0aGlzLmF0dGFjaG1lbnRzTGlzdCB8fCBbXSlcclxuICAgICAgLmZpbHRlcihhID0+ICEhYSlcclxuICAgICAgLnJlZHVjZSgoc3VtLCBhKSA9PiBzdW0gKyB0aGlzLmJ5dGVzRnJvbUJhc2U2NChhLkZpbGVEYXRhQmFzZTY0IHx8IGEuRmlsZVRodW1ibmFpbEJhc2U2NCB8fCAnJyksIDApO1xyXG5cclxuICAgIC8vIFByb2dyZXNzIGZpdHRpemlvOiAxMDAlIHNlIHByZXNlbnRpIGZpbGUsIDAgc2UgdnVvdG9cclxuICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50ID0gKHRoaXMuYXR0YWNobWVudHNMaXN0ICYmIHRoaXMuYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDApID8gMTAwIDogMDtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gICAgaWYgKHRoaXMudG9hc3QudGltZW91dElkKSBjbGVhclRpbWVvdXQodGhpcy50b2FzdC50aW1lb3V0SWQpO1xyXG4gIH1cclxuXHJcbiAgLy8gQ2FsY29sYSBpIGJ5dGUgZGEgdW5hIHN0cmluZ2EgQmFzZTY0IHB1cmEgKHNlbnphIHByZWZpc3NvIGRhdGE6Li4uKVxyXG4gIHB1YmxpYyBieXRlc0Zyb21CYXNlNjQoYmFzZTY0OiBzdHJpbmcpOiBudW1iZXIge1xyXG4gICAgaWYgKCFiYXNlNjQpIHJldHVybiAwO1xyXG4gICAgLy8gUmltdW92aSBldmVudHVhbGUgcHJlZmlzc28gZGF0YSBVUkxcclxuICAgIGNvbnN0IGNvbW1hSWR4ID0gYmFzZTY0LmluZGV4T2YoJywnKTtcclxuICAgIGNvbnN0IGI2NCA9IGNvbW1hSWR4ID49IDAgPyBiYXNlNjQuc3Vic3RyaW5nKGNvbW1hSWR4ICsgMSkgOiBiYXNlNjQ7XHJcbiAgICAvLyBDb250YSBwYWRkaW5nXHJcbiAgICBsZXQgcGFkZGluZyA9IDA7XHJcbiAgICBpZiAoYjY0LmVuZHNXaXRoKCc9PScpKSBwYWRkaW5nID0gMjtcclxuICAgIGVsc2UgaWYgKGI2NC5lbmRzV2l0aCgnPScpKSBwYWRkaW5nID0gMTtcclxuICAgIC8vIEZvcm11bGEgZXNhdHRhOiAoMyAqIChsZW4gLyA0KSkgLSBwYWRkaW5nXHJcbiAgICBjb25zdCBsZW4gPSBiNjQubGVuZ3RoO1xyXG4gICAgcmV0dXJuIE1hdGgubWF4KDAsICgzICogTWF0aC5mbG9vcihsZW4gLyA0KSkgLSBwYWRkaW5nKTtcclxuICB9XHJcblxyXG4gIGNoZWNrQXR0YWNobWVudEltYWdlKCkge1xyXG4gICAgdGhpcy5hdHRhY2htZW50c0xpc3QuZm9yRWFjaCgoYSkgPT4ge1xyXG4gICAgICBhLklzSW1hZ2UgPSBBdHRhY2htZW50SGVscGVyU2VydmljZS5jaGVja0ltYWdlRnJvbU1pbWVUeXBlKGEuRmlsZUNvbnRlbnRUeXBlKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIEdlc3Rpb25lIGVsZW5jbyBhbGxlZ2F0aVxyXG5cclxuICAvKipcclxuICAgKiBFbGltaW5hIHVuIGFsbGVnYXRvIGVsaW1pbmFuZG8gYW5jaGUgaWwgZmlsZSBwcmVzZW50ZSBuZWxsbyBzdG9yYWdlIGRpIGFyY2hpdmlhemlvbmUgdXRpbGl6emF0byAoQVdTIG8gY2FydGVsbGEgcHJvZ2V0dG8pXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgSUF0dGFjaG1lbnREVE8gZGEgY2FuY2VsbGFyZVxyXG4gICAqL1xyXG4gIGRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkNvbmZpcm0oXHJcbiAgICAgIHRoaXMuZGVsZXRlRGlhbG9nTWVzc2FnZSxcclxuICAgICAgKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucmVtb3ZlQXR0YWNobWVudEZyb21MaXN0KHRoaXMuYXR0YWNobWVudHNMaXN0LmluZGV4T2YoZWxlbWVudCkpO1xyXG4gICAgICB9LFxyXG4gICAgICB0cnVlLFxyXG4gICAgICB0aGlzLmRlbGV0ZURpYWxvZ1RpdGxlXHJcbiAgICApO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmltdW92ZSBsJ2FsbGVnYXRvIHNlbGV6aW9uYXRvIGRhbGxhIGxpc3RhIFwiYXR0YWNobWVudHNMaXN0XCIgZSBpbnZvY2EgbCdldmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsYSBsaXN0YSBhZ2dpb3JuYXRhLlxyXG4gICAqIEBwYXJhbSBhdHRhY2htZW50SW5kZXggSW5kaWNlIGRlbGwnYXR0YWNobWVudCBkYSByaW11b3ZlcmVcclxuICAgKi9cclxuICByZW1vdmVBdHRhY2htZW50RnJvbUxpc3QoYXR0YWNobWVudEluZGV4OiBudW1iZXIpIHtcclxuICAgIHRoaXMub25EZWxldGVBdHRhY2htZW50LmVtaXQodGhpcy5hdHRhY2htZW50c0xpc3RbYXR0YWNobWVudEluZGV4XSk7XHJcblxyXG4gICAgdGhpcy5hdHRhY2htZW50c0xpc3Quc3BsaWNlKGF0dGFjaG1lbnRJbmRleCwgMSk7XHJcbiAgICB0aGlzLmxvY2FsRWRpdGVkQXR0YWNobWVudHMuZW1pdCh0aGlzLmF0dGFjaG1lbnRzTGlzdCk7XHJcblxyXG4gICAgdGhpcy5yZWNvbXB1dGVUb3RhbHNBbmRQcm9ncmVzcygpO1xyXG4gICAgdGhpcy5zaG93VG9hc3QodGhpcy5yZW1vdmVkTGFiZWwgfHwgJ0ZpbGUgcmVtb3ZlZCcsICdzdWNjZXNzJyk7XHJcblxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBzaW11bGF0ZVByb2dyZXNzKCkge1xyXG4gICAgdGhpcy5wcm9ncmVzc1BlcmNlbnQgPSAwO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50ID0gMzA7XHJcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIHRoaXMucHJvZ3Jlc3NQZXJjZW50ID0gNjA7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnByb2dyZXNzUGVyY2VudCA9IDEwMDtcclxuICAgICAgICB9LCAyMDApO1xyXG4gICAgICB9LCAyMDApO1xyXG4gICAgfSwgMTAwKTtcclxuICB9XHJcblxyXG5cclxuICAvKipcclxuICAgKiBTY2FyaWNhIGwnYWxsZWdhdG8gbyBhcHJlIGlsIGxpbmtcclxuICAgKiBAcGFyYW0gZWxlbWVudCBBbGxlZ2F0byBkYSBtb3N0cmFyZVxyXG4gICAqL1xyXG4gIHZpZXdBdHRhY2htZW50KGF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPKSB7XHJcbiAgICBpZiAoYXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKSB7XHJcbiAgICAgIHdpbmRvdy5vcGVuKGF0dGFjaG1lbnQuRmlsZVBhdGgsIFwiX2JsYW5rXCIpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGF0dGFjaG1lbnQuTGFyZ2VGaWxlKSB7XHJcbiAgICAgIGNvbnN0IGZpbGUgPSBhdHRhY2htZW50LkxhcmdlRmlsZTtcclxuICAgICAgY29uc3QgdXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcclxuICAgICAgY29uc3QgbGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xyXG4gICAgICBsaW5rLmhyZWYgPSB1cmw7XHJcbiAgICAgIGxpbmsuZG93bmxvYWQgPSBhdHRhY2htZW50LkZpbGVOYW1lIHx8IGZpbGUubmFtZTtcclxuICAgICAgbGluay5jbGljaygpO1xyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IFVSTC5yZXZva2VPYmplY3RVUkwodXJsKSwgMTAwMCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoYXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiBhdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSAmJiBhdHRhY2htZW50LkZpbGVOYW1lKSB7XHJcbiAgICAgIGxldCBzb3VyY2UgPSBgZGF0YToke2F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlfTtiYXNlNjQsJHthdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0fWA7XHJcbiAgICAgIGNvbnN0IGxpbmsgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiYVwiKTtcclxuICAgICAgbGluay5ocmVmID0gc291cmNlO1xyXG4gICAgICBsaW5rLmRvd25sb2FkID0gYCR7YXR0YWNobWVudC5GaWxlTmFtZX1gO1xyXG4gICAgICBsaW5rLmNsaWNrKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmRvd25sb2FkQXR0YWNobWVudC5lbWl0KGF0dGFjaG1lbnQpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogUmlkZWZpbmlzY2UgbCdpY29uYSBkYSBtb3N0cmFyZSBuZWxsYSBjb2xvbm5hIGRlbGwnZXFwLXRhYmxlIHBlciBvZ25pIGZpbGUuXHJcbiAgICogTCdpY29uYSB2YXJpYSBpbiBiYXNlIGFsbCdlc3RlbnNpb25lIGRlbCBmaWxlXHJcbiAgICogQHBhcmFtIGF0dGFjaG1lbnRcclxuICAgKi9cclxuICBnZXRBdHRhY2htZW50SWNvbihhdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG4gICAgaWYgKGF0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykgcmV0dXJuIFwiZmFzIGZhLWxpbmtcIjtcclxuICAgIGVsc2UgcmV0dXJuIEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmdldEljb25Gcm9tRmlsZUV4dGVuc2lvbmUoYXR0YWNobWVudC5GaWxlRXh0ZW5zaW9uKTtcclxuICB9XHJcblxyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvKipcclxuICAgKiBJbiBjYXNvIGRpIGFsbGVnYXRvIHNpbmdvbG8sIHNjZWdsaWUgcXVhbGUgbWV0b2RvIHJpY2hpYW1hcmUgaW4gYmFzZSBhbCB0aXBvIGRpIGFsbGVnYXRvXHJcbiAgICovXHJcbiAgYWRkRmlsZShhdHRhY2htZW50VHlwZTogQXR0YWNobWVudFR5cGUsIGltYWdlSW5wdXQgPSBudWxsKSB7XHJcbiAgICBpZiAoYXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICB0aGlzLnN3aXRjaFRvQWRkaW5nTGlua01vZGUoKTtcclxuICAgIH0gZWxzZSBpZiAoYXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSkge1xyXG4gICAgICBpbWFnZUlucHV0LmNsaWNrKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmNob29zZURyb3Bib3hGaWxlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjcmVhdGVBdHRhY2htZW50Rm9ybSgpIHtcclxuICAgIC8vQ3JlYSBsYSBmb3JtIHBlciBsYSB2YWxpZGF6aW9uZSBkZWkgY2FtcGlcclxuICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0gPSB0aGlzLmZvcm1CdWlsZGVyLmdyb3VwKHtcclxuICAgICAgdHlwZTogW3RoaXMubmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSwgVmFsaWRhdG9ycy5yZXF1aXJlZF0sXHJcbiAgICAgIG5hbWU6IFt0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZU5hbWVdLFxyXG4gICAgICBwYXRoOiBbdGhpcy5uZXdBdHRhY2htZW50LkZpbGVQYXRoXSxcclxuICAgICAgY3VzdG9tSGVpZ2h0OiBbdGhpcy5jdXN0b21IZWlnaHRdLFxyXG4gICAgICBjdXN0b21XaWR0aDogW3RoaXMuY3VzdG9tV2lkdGhdXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGNsb3NlKGVtaXRDbG9zZUV2ZW50ID0gdHJ1ZSkge1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50ID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcbiAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudEZvcm0pIHRoaXMubmV3QXR0YWNobWVudEZvcm0ucmVzZXQoKTtcclxuXHJcbiAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZS5jbG9zZSgpO1xyXG4gICAgdGhpcy5yZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKCk7XHJcblxyXG4gICAgaWYgKGVtaXRDbG9zZUV2ZW50ID09IHRydWUgJiYgdGhpcy5hYm9ydEFkZEF0dGFjaG1lbnQpIHRoaXMuYWJvcnRBZGRBdHRhY2htZW50LmVtaXQoKTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGJhc2UgYWwgdGlwbyBkaSBhbGxlZ2F0byBjb250cm9sbGEgc2UgZGlzYWJpbGl0YXJlIG8gbWVubyBpbCBwdWxzYW50ZSBwZXIgc2FsdmFyZS5cclxuICAgKiBGdW56aW9uZSB1c2F0YSBuZWwgW2Rpc2FibGVdIGRlbCBwdWxzYW50ZSBcIlNhbHZhXCIgZGVsIGRpYWxvZyBwZXIgbCdhZ2dpdW50YSBkaSB1biBhbGxlZ2F0by5cclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGRpc2FibGVTYXZlKCkge1xyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUpIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiAhdGhpcy5uZXdBdHRhY2htZW50LkxhcmdlRmlsZTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMubmV3QXR0YWNobWVudC5GaWxlUGF0aDtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIChcclxuICAgICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMuZmlsdGVyKFxyXG4gICAgICAgICAgKHApID0+XHJcbiAgICAgICAgICAgIChwLkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUgJiYgIXAuRmlsZURhdGFCYXNlNjQgJiYgIXAuTGFyZ2VGaWxlKSB8fFxyXG4gICAgICAgICAgICAocC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LICYmICFwLkZpbGVQYXRoKVxyXG4gICAgICAgICkubGVuZ3RoID4gMFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY29uZmlybUFkZEF0dGFjaG1lbnQoKSB7XHJcbiAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LklzSW1hZ2UgJiYgdGhpcy5pbWFnZUNyb3BwZXIpIHtcclxuICAgICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gdGhpcy5pbWFnZUNyb3BwZXIuY3JvcCgpLmJhc2U2NC5zcGxpdChcIjtiYXNlNjQsXCIpWzFdO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpIHtcclxuICAgICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LICYmICF0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZU5hbWUpXHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVOYW1lID0gdGhpcy5uZXdBdHRhY2htZW50LkZpbGVQYXRoO1xyXG5cclxuICAgICAgaWYgKHRoaXMuYXR0YWNobWVudHNMaXN0ID09IG51bGwpIHRoaXMuYXR0YWNobWVudHNMaXN0ID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAgICAgdGhpcy5hdHRhY2htZW50c0xpc3QucHVzaCh0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9PSBudWxsIHx8IHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5sZW5ndGggPT0gMCkgcmV0dXJuO1xyXG5cclxuICAgICAgaWYgKHRoaXMuYXR0YWNobWVudHNMaXN0ID09IG51bGwpIHRoaXMuYXR0YWNobWVudHNMaXN0ID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAgICAgdGhpcy5hdHRhY2htZW50c0xpc3QgPSB0aGlzLmF0dGFjaG1lbnRzTGlzdC5jb25jYXQodGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzKTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmxvY2FsRWRpdGVkQXR0YWNobWVudHMuZW1pdCh0aGlzLmF0dGFjaG1lbnRzTGlzdCk7XHJcblxyXG4gICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIHRoaXMuZGlhbG9nUmVmQ3JvcEltYWdlLmNsb3NlKCk7XHJcbiAgICAgIHRoaXMucmVzdG9yZU9yaWdpbmFsRGltZW5zaW9ucygpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPT09IEF0dGFjaG1lbnRUeXBlLkxJTkspIHtcclxuICAgICAgdGhpcy5uZXdBdHRhY2htZW50ID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnRGb3JtKSB0aGlzLm5ld0F0dGFjaG1lbnRGb3JtLnJlc2V0KCk7XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5yZXNldFNlbGVjdGVkRmlsZXMoKTtcclxuICB9XHJcblxyXG4gIC8vIDIuIFJFU0VUIFRPVEFMRTogU3Z1b3RpYW1vIGxlIHByb3ByaWV0w6AgZGkgY2xhc3NlIHBlciBldml0YXJlIGNoZSBcclxuICAvLyByZXNpZHVpIGRpIHVwbG9hZCBwcmVjZWRlbnRpIChzaW5nb2xpIG8gbXVsdGlwbGkpIHZlbmdhbm8gdHJhc2NpbmF0aS5cclxuICBwcml2YXRlIHJlc2V0U2VsZWN0ZWRGaWxlcygpIHtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudCA9IHt9IGFzIElBdHRhY2htZW50RFRPO1xyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gW107XHJcbiAgICB0aGlzLnNlbGVjdGVkRmlsZSA9IG51bGw7XHJcbiAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSBbXTtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEFwcmUgaWwgZGlhbG9nIHBlciBsJ2FudGVwcmltYSBkZWxsJ2FsbGVnYXRvIHNlbGV6aW9uYXRvLlxyXG4gICAqIEBwYXJhbSByb3dcclxuICAgKiBAcmV0dXJuc1xyXG4gICAqL1xyXG4gIGFzeW5jIG9wZW5QcmV2aWV3RGlhbG9nKHJvdzogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50ID0geyAuLi5yb3cgfTtcclxuXHJcblxyXG4gICAgaWYgKHRoaXMuZ2V0QXR0YWNobWVudEVuZHBvaW50ICYmIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2UgJiYgIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0KSB7XHJcbiAgICAgIGF3YWl0IHRoaXMuZ2V0QXR0YWNobWVudEJ5SUQoKVxyXG4gICAgICAgIC50aGVuKChyZXMpID0+IHtcclxuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gcmVzLkZpbGVEYXRhQmFzZTY0O1xyXG4gICAgICAgIH0pXHJcbiAgICAgICAgLmNhdGNoKChlcnIpID0+IHtcclxuICAgICAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkVycm9yKGVycik7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTkspIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuVHJ1c3RlZFVybCA9IHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybChcclxuICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aFxyXG4gICAgICApO1xyXG4gICAgfVxyXG4gICAgZWxzZSBpZiAodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlPy5zdGFydHNXaXRoKFwidmlkZW8vXCIpICYmIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkxhcmdlRmlsZSkge1xyXG4gICAgICBjb25zdCB2aWRlb1VybCA9IFVSTC5jcmVhdGVPYmplY3RVUkwodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuTGFyZ2VGaWxlKTtcclxuICAgICAgLy8gVXNpYW1vIGJ5cGFzc1NlY3VyaXR5VHJ1c3RVcmwgcGVyIGxhIHNvcmdlbnRlIGRlbCB2aWRlb1xyXG4gICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFVybCh2aWRlb1VybCk7XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmIChcclxuICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuSXNJbWFnZSAmJlxyXG4gICAgICAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgJiZcclxuICAgICAgIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVUaHVtYm5haWxCYXNlNjRcclxuICAgICkge1xyXG4gICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5JbmZvKFwiSW1wb3NzaWJpbGUgYXByaXJlIGwnYW50ZXByaW1hIGRlbGwnYWxsZWdhdG8sIGZpbGUgbWFuY2FudGUuXCIpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBlbHNlIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPT09ICdhcHBsaWNhdGlvbi9wZGYnICYmIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0KSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LlRydXN0ZWRVcmwgPSB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0UmVzb3VyY2VVcmwoXHJcbiAgICAgICAgYGRhdGE6YXBwbGljYXRpb24vcGRmO2Jhc2U2NCwke3RoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0fWBcclxuICAgICAgKTtcclxuICAgIH1cclxuICAgIGVsc2UgaWYgKCF0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aCAmJiB0aGlzLnByb2R1Y3Rpb25CYXNlVXJsKSB7XHJcbiAgICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuVHJ1c3RlZFVybCA9IHRoaXMuc2FuaXRpemVyLmJ5cGFzc1NlY3VyaXR5VHJ1c3RSZXNvdXJjZVVybChcclxuICAgICAgICAgIFwiaHR0cHM6Ly9kb2NzLmdvb2dsZS5jb20vZ3ZpZXc/dXJsPVwiICtcclxuICAgICAgICAgIHRoaXMucHJvZHVjdGlvbkJhc2VVcmwgK1xyXG4gICAgICAgICAgXCIvXCIgK1xyXG4gICAgICAgICAgdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVBhdGggK1xyXG4gICAgICAgICAgXCImZW1iZWRkZWQ9dHJ1ZVwiXHJcbiAgICAgICAgKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5JbmZvKFwiSW1wb3NzaWJpbGUgYXByaXJlIGwnYW50ZXByaW1hIGRlbCBkb2N1bWVudG8hXCIpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGRpYWxvZ1JlZiA9IHRoaXMuZGlhbG9nLm9wZW4odGhpcy5kaWFsb2dQcmV2aWV3LCB7XHJcbiAgICAgIHBhbmVsQ2xhc3M6ICdlcXAtYXR0YWNobWVudHMtcHJldmlldy1kaWFsb2cnLFxyXG4gICAgICBtYXhXaWR0aDogJzk1dncnLFxyXG4gICAgICB3aWR0aDogcm93LklzSW1hZ2UgfHwgcm93LkZpbGVDb250ZW50VHlwZT8uc3RhcnRzV2l0aCgndmlkZW8vJykgPyAnYXV0bycgOiAnMTEwMHB4JyxcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFB1bGl6aWEgZGVsbGEgbWVtb3JpYSBxdWFuZG8gaWwgZGlhbG9nIHNpIGNoaXVkZVxyXG4gICAgZGlhbG9nUmVmLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50Py5GaWxlQ29udGVudFR5cGU/LnN0YXJ0c1dpdGgoXCJ2aWRlby9cIikpIHtcclxuICAgICAgICBVUkwucmV2b2tlT2JqZWN0VVJMKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LlRydXN0ZWRVcmwgYXMgYW55KTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBnZXRBdHRhY2htZW50QnlJRCgpIHtcclxuICAgIHJldHVybiB0aGlzLmh0dHAucG9zdDxJQXR0YWNobWVudERUTz4odGhpcy5nZXRBdHRhY2htZW50RW5kcG9pbnQsIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50KS50b1Byb21pc2UoKTtcclxuICB9XHJcblxyXG4gIC8vI3JlZ2lvbiBHZXN0aW9uZSBjYXJpY2FtZW50byBmaWxlXHJcblxyXG4gIC8qKlxyXG4gICAqIEV2ZW50byBzY2F0ZW5hdG8gYWxsYSBzZWxlemlvbmUgZGVsIGZpbGUgKG8gZGVpIGZpbGUpLlxyXG4gICAqIFNlIGlsIGNhcmljYW1lbnRvIMOoIFNJTkdPTE8gbyBzZSBjb211bnF1ZSDDqCBzdGF0byBzZWxlemlvbmF0byB1biBzb2xvIGZpbGUgYWxsb3JhIHNpIG9jY3VwYSBkaSBjb250cm9sbGFyZSBzZSBzaSB0cmF0dGEgZGkgdW4gaW1tYWdpbmUgaW4gbW9kbyBkYVxyXG4gICAqIG1vc3RyYXJlIGxlIGZ1bnppb25hbGl0w6AgZGVsIGNyb3BwaWUgKHBlciByaXRhZ2xpYXJlIGwnaW1tYWdpbmUpIG9wcHVyZSBuby5cclxuICAgKiBTZSBpbCBmaWxlIGNhcmljYXRvIG5vbiDDqCB1biBpbW1hZ2luZSBhbGxvcmEgZ2VuZXJhIGRpcmV0dGFtZW50ZSBpbCBiYXNlNjQgZSBsbyBhc3NvY2lhIGFsbCdhbGxlZ2F0byBkYSBzYWx2YXJlLlxyXG4gICAqIFNlIGludmVjZSBpbCBjYXJpY2FtZW50byBkZWkgZmlsZSDDqCBNVUxUSVBMTyBlIHNvbm8gcHJlc2VudGkgcGnDuSBmaWxlIGFsbG9yYSBlc2VndWUgbGUgc3Rlc3NlIG9wZXJhemlvbmkgaWdub3JhbmRvIHBlcsOyIGlsIGNvbnRybGxvXHJcbiAgICogaW1tYWdpbmUgcGVyIGlsIGNyb3BwaWUgKGluIGNhc28gZGkgY2FyaWNhbWVudG8gbXVsdGlwbG8gbGUgZnVuemlvbmFsaXTDoCBkZWwgY3JvcHBpZSBzb25vIGRpc2FiaWxpdGF0ZSkuXHJcbiAgICovXHJcbiAgYXN5bmMgb25GaWxlQWRkZWQoZXZlbnQsIGlzRmlsZURyb3BwZWQ6IGJvb2xlYW4gPSBmYWxzZSkge1xyXG5cclxuICAgIGlmICh0aGlzLmlzRGlzYWJsZWQpIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuSW5mbyhcIkNhcmljYW1lbnRvIGFsbGVnYXRpIG5vbiBkaXNwb25pYmlsZS5cIik7XHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIHRoaXMuc2hvd0Nyb3BJbWFnZSA9IGZhbHNlO1xyXG5cclxuICAgIHRoaXMucmVzZXRTZWxlY3RlZEZpbGVzKCk7XHJcblxyXG4gICAgY29uc3QgZmlsZXNPbklucHV0OiBGaWxlW10gPSBpc0ZpbGVEcm9wcGVkXHJcbiAgICAgID8gKGV2ZW50IGFzIEZpbGVbXSlcclxuICAgICAgOiBBcnJheS5mcm9tKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCk/LmZpbGVzIHx8IFtdKTtcclxuXHJcbiAgICBjb25zdCB7IHZhbGlkRmlsZXMsIG92ZXJzaXplZEZpbGVzIH0gPSB0aGlzLnZhbGlkYXRpb25GaWxlKGZpbGVzT25JbnB1dCk7XHJcblxyXG4gICAgaWYgKCF2YWxpZEZpbGVzIHx8IHZhbGlkRmlsZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIGlmICghaXNGaWxlRHJvcHBlZCAmJiBldmVudD8udGFyZ2V0IGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCkge1xyXG4gICAgICAgIGV2ZW50LnRhcmdldC52YWx1ZSA9ICcnO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvL1NlIMOoIHN0YXRvIHJpY2hpZXN0byBpbCBjYXJpY2FtZW50byBTSU5HT0xPIG9wcHVyZSBzZSBpbCBjYXJpY2FtZW50byDDqCBNVUxUSVBMTyBtYSDDqCBzdGF0byBzZWxlemlvbmF0byB1biBzb2xvIGZpbGVcclxuICAgIC8vYWxsb3JhIHZlcmlmaWNhIHNlIGlsIGZpbGUgw6ggdW4gaW1tYWdpbmUgKHBlciBtb3N0cmFyZSBpbCBDUk9QUElFKVxyXG4gICAgaWYgKFsuLi52YWxpZEZpbGVzXS5sZW5ndGggPT0gMSB8fCB0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSB2YWxpZEZpbGVzWzBdO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSB2YWxpZEZpbGVzO1xyXG4gICAgICBpZiAoIXRoaXMuc2VsZWN0ZWRGaWxlKSByZXR1cm47XHJcblxyXG4gICAgICAvL01lbW9yaXp6YSBpIGRhdGkgcGVyIGwnYWxsZWdhdG9cclxuICAgICAgdGhpcy5uZXdBdHRhY2htZW50ID0gYXdhaXQgdGhpcy5jcmVhdGVBdHRhY2htZW50RnJvbVVwbG9hZGVkRmlsZSh0aGlzLnNlbGVjdGVkRmlsZSwgZmFsc2UpO1xyXG4gICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcbiAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5wdXNoKHRoaXMubmV3QXR0YWNobWVudCk7XHJcblxyXG4gICAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIG1hIHBlciBlcnJvcmUgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gZmlsZSBjaGUgbm9uIMOoIHVuIGltbWFnaW5lXHJcbiAgICAgIGxldCBjaGVja09ubHlJbWFnZSA9IHRoaXMuY2hlY2tBbGxvd09ubHlJbWFnZUZpbGUodGhpcy5uZXdBdHRhY2htZW50KTtcclxuICAgICAgaWYgKGNoZWNrT25seUltYWdlID09IGZhbHNlKSByZXR1cm47XHJcblxyXG4gICAgICB0aGlzLmNyZWF0ZUF0dGFjaG1lbnRGb3JtKCk7XHJcblxyXG4gICAgICAvL1ZlcmlmaWNhIHNlIGlsIGZpbGUgY2FyaWNhdG8gw6ggdW4naW1tYWdpbmUgb3BwdXJlIG5vLiBTZSDDqCB1biBpbW1hZ2luZSwgcHJpbWEgZGkgY2FyaWNhcmxhIG1vc3RyYSBpbCBjcm9wcGllIHBlciBpbCByZXNpemUuXHJcbiAgICAgIC8vU2Ugbm9uIMOoIHVuIGltbWFnaW5lIGFsbG9yYSBnZW5lcmEgaWwgQmFzZTY0XHJcbiAgICAgIGlmICh0aGlzLm5ld0F0dGFjaG1lbnQuSXNJbWFnZSA9PSB0cnVlICYmIHRoaXMuZW5hYmxlSW1hZ2VDcm9wKSB7XHJcbiAgICAgICAgdGhpcy5nZXRJbWFnZURpbWVuc2lvbnModmFsaWRGaWxlc1swXSk7XHJcblxyXG4gICAgICAgIC8vTW9zdHJhIGlsIGNyb3BwaWUgZSBkaXNhYmlsaXRhIGxhIGZvcm0gZmluY2jDqCBub24gdGVybWluYSBsYSBtb2RpZmljYSBkZWxsJ2ltbWFnaW5lXHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5kaXNhYmxlKCk7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5jb250cm9sc1tcImN1c3RvbVdpZHRoXCJdLmVuYWJsZSgpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0uY29udHJvbHNbXCJjdXN0b21IZWlnaHRcIl0uZW5hYmxlKCk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnNob3dDcm9wSW1hZ2UgPSB0cnVlO1xyXG4gICAgICAgICAgdGhpcy5pbWFnZUZpbGUgPSBldmVudDtcclxuXHJcbiAgICAgICAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZSA9IHRoaXMuZGlhbG9nLm9wZW4odGhpcy5kaWFsb2dDcm9wSW1hZ2UsIHtcclxuICAgICAgICAgICAgZGlzYWJsZUNsb3NlOiB0cnVlLFxyXG4gICAgICAgICAgICBoYXNCYWNrZHJvcDogdHJ1ZSxcclxuICAgICAgICAgICAgd2lkdGg6IFwiOTV2d1wiLFxyXG4gICAgICAgICAgICBtYXhXaWR0aDogXCI4MDBweFwiLFxyXG4gICAgICAgICAgICBtYXhIZWlnaHQ6IFwiOTB2aFwiLFxyXG4gICAgICAgICAgICBwYW5lbENsYXNzOiBbJ2VxcC1hdHRhY2htZW50cy1kaWFsb2cnLCAnY3JvcC1kaWFsb2cnXVxyXG4gICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zaG93Q3JvcEltYWdlID0gZmFsc2U7XHJcbiAgICAgICAgbGV0IGJhc2U2NFJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0QmFzZTY0RnJvbUZpbGUodGhpcy5zZWxlY3RlZEZpbGUpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IGJhc2U2NFJlc3VsdC5CYXNlNjRGaWxlO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBiYXNlNjRSZXN1bHQuQ29udGVudFR5cGU7XHJcbiAgICAgICAgdGhpcy5jb25maXJtQWRkQXR0YWNobWVudCgpO1xyXG4gICAgICB9XHJcblxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpbGVzID0gdmFsaWRGaWxlcztcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZXMgfHwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aCA9PSAwKSByZXR1cm47XHJcblxyXG4gICAgICBpZiAoIXRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cykgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gW107XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgbGV0IG5ld0F0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0gYXdhaXQgdGhpcy5jcmVhdGVBdHRhY2htZW50RnJvbVVwbG9hZGVkRmlsZShcclxuICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlc1tpXSxcclxuICAgICAgICAgIHRydWUsXHJcbiAgICAgICAgICB0cnVlXHJcbiAgICAgICAgKTtcclxuICAgICAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIG1hIHBlciBlcnJvcmUgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gZmlsZSBjaGUgbm9uIMOoIHVuIGltbWFnaW5lXHJcbiAgICAgICAgbGV0IGNoZWNrT25seUltYWdlID0gdGhpcy5jaGVja0FsbG93T25seUltYWdlRmlsZShuZXdBdHRhY2htZW50KTtcclxuICAgICAgICBpZiAoY2hlY2tPbmx5SW1hZ2UgPT0gZmFsc2UpIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2gobmV3QXR0YWNobWVudCk7XHJcbiAgICAgIH1cclxuICAgICAgdGhpcy5jb25maXJtQWRkQXR0YWNobWVudCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMucmVjb21wdXRlVG90YWxzQW5kUHJvZ3Jlc3MoKTtcclxuICAgIHRoaXMuc2ltdWxhdGVQcm9ncmVzcygpO1xyXG4gICAgLy8gQ2FzbyAxOiBTdWNjZXNzbyBQYXJ6aWFsZSAoYWxjdW5pIGZpbGUgdmFsaWRpLCBhbHRyaSBubylcclxuICAgIGlmIChvdmVyc2l6ZWRGaWxlcy5sZW5ndGggPiAwICYmIHZhbGlkRmlsZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICBjb25zdCBmaWxlTmFtZXMgPSBvdmVyc2l6ZWRGaWxlcy5qb2luKCcsICcpO1xyXG4gICAgICB0aGlzLnNob3dUb2FzdChcclxuICAgICAgICBgJHt2YWxpZEZpbGVzLmxlbmd0aH0gZmlsZSBhZ2dpdW50aS4gJHtvdmVyc2l6ZWRGaWxlcy5sZW5ndGh9IG5vbiBjYXJpY2F0aSBwZXJjaMOpIHRyb3BwbyBncmFuZGkgKCR7ZmlsZU5hbWVzfSkuYCxcclxuICAgICAgICAnZXJyb3InXHJcbiAgICAgICk7XHJcbiAgICB9XHJcbiAgICAvLyBDYXNvIDI6IE5lc3N1biBmaWxlIHZhbGlkb1xyXG4gICAgZWxzZSBpZiAob3ZlcnNpemVkRmlsZXMubGVuZ3RoID4gMCAmJiB2YWxpZEZpbGVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgfVxyXG4gICAgLy8gQ2FzbyAzOiBUdXR0aSBpIGZpbGUgdmFsaWRpXHJcbiAgICBlbHNlIGlmIChvdmVyc2l6ZWRGaWxlcy5sZW5ndGggPT09IDAgJiYgdmFsaWRGaWxlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMuc2hvd1RvYXN0KFxyXG4gICAgICAgIGAke3ZhbGlkRmlsZXMubGVuZ3RofSAke3RoaXMuYWRkZWRTdWNjZXNzZnVsbHlMYWJlbCB8fCAnZmlsZShzKSBhZ2dpdW50aSBjb24gc3VjY2Vzc28uJ31gLFxyXG4gICAgICAgICdzdWNjZXNzJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8vUmVzZXR0byBpbCB2YWxvcmUgZGVsIGZpbGUgaW5wdXQgaW4gbW9kbyBkYSBzY2F0ZW5hcmUgaWwgY2hhbmdlIGFuY2hlIHNlIHNpIGRvdmVzc2UgY2FyaWNhcmUgbG8gc3Rlc3NvIGZpbGVcclxuICAgIGlmICghaXNGaWxlRHJvcHBlZCkgZXZlbnQudGFyZ2V0LnZhbHVlID0gXCJcIjtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgdmFsaWRhdGlvbkZpbGUoZmlsZXNPbklucHV0OiBGaWxlW10pIHtcclxuICAgIGNvbnN0IHZhbGlkRmlsZXM6IEZpbGVbXSA9IFtdO1xyXG4gICAgY29uc3Qgb3ZlcnNpemVkRmlsZXM6IHN0cmluZ1tdID0gW107XHJcblxyXG4gICAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzT25JbnB1dCkge1xyXG4gICAgICBjb25zdCBmaWxlU2l6ZU1CID0gZmlsZS5zaXplIC8gMTAyNCAvIDEwMjQ7XHJcbiAgICAgIGlmIChmaWxlU2l6ZU1CID4gdGhpcy5tYXhGaWxlU2l6ZU1CKSB7XHJcbiAgICAgICAgb3ZlcnNpemVkRmlsZXMucHVzaChmaWxlLm5hbWUpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHZhbGlkRmlsZXMucHVzaChmaWxlKTtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChvdmVyc2l6ZWRGaWxlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGNvbnN0IGZpbGVOYW1lcyA9IG92ZXJzaXplZEZpbGVzLmpvaW4oJywgJyk7XHJcbiAgICAgIHRoaXMuc2hvd1RvYXN0KFxyXG4gICAgICAgIGBGaWxlKHMpIHRyb3BwbyBncmFuZGk6ICR7ZmlsZU5hbWVzfS4gTGltaXRlOiAke3RoaXMubWF4RmlsZVNpemVNQn1NQmAsXHJcbiAgICAgICAgJ2Vycm9yJ1xyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB7IHZhbGlkRmlsZXMsIG92ZXJzaXplZEZpbGVzIH07XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogQSBwYXJ0aXJlIGRhbCBGSUxFIHJpY2V2dXRvIGluIGlucHV0IHJpY29zdHJ1aXNjZSBsJ29nZ2V0dG8gSUF0dGFjaG1lbnREVE8gZSBsbyByZXN0aXR1aXNjZS5cclxuICAgKiBTZSBpbCBwYXJhbWV0cm8gZ2V0QmFzZTY0IHZpZW5lIHBhc3NhdG8gYSBUUlVFIGFsbG9yYSwgc2VtcHJlIGEgcGFydGlyZSBkYWwgZmlsZSxnZW5lcmEgaWwgYmFzZTY0IGVcclxuICAgKiByaWNhdmEgaWwgQ29udGVudFR5cGUgZGEgYXNzb2NpYXJlIGFsbCdvZ2dldHRvIElBdHRhY2htZW50RFRPIGRhIHJlc3RpdHVpcmVcclxuICAgKiBAcGFyYW0gY3VycmVudEZpbGUgT2dnZXR0byBGSUxFIGRhIHByb2Nlc3NhcmVcclxuICAgKiBAcGFyYW0gZ2V0QmFzZTY0IFNlIFRSVUUgYWxsb3JhIGNhbGNvbGEgYmFzZTY0IGUgQ29udGVudFR5cGUgZGVsIGZpbGUgcGFzc2F0byBpbiBpbnB1dFxyXG4gICAqIEByZXR1cm5zIFJlc3RpdHVpc2NlIHVuIG9nZ2V0dG8gZGkgdGlwbyBJQXR0YWNobWVudERUT1xyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgY3JlYXRlQXR0YWNobWVudEZyb21VcGxvYWRlZEZpbGUoXHJcbiAgICBjdXJyZW50RmlsZTogRmlsZSxcclxuICAgIGdldEJhc2U2NDogYm9vbGVhbiA9IHRydWUsXHJcbiAgICBjcm9wRmlsZTogYm9vbGVhbiA9IGZhbHNlXHJcbiAgKTogUHJvbWlzZTxJQXR0YWNobWVudERUTz4ge1xyXG4gICAgbGV0IG5ld0F0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0ge30gYXMgSUF0dGFjaG1lbnREVE87XHJcbiAgICAvL01lbW9yaXp6YSBpIGRhdGkgcGVyIGwnYWxsZWdhdG9cclxuICAgIG5ld0F0dGFjaG1lbnQuQXR0YWNobWVudFR5cGUgPSBBdHRhY2htZW50VHlwZS5GSUxFO1xyXG4gICAgbmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBjdXJyZW50RmlsZS50eXBlO1xyXG4gICAgbmV3QXR0YWNobWVudC5GaWxlTmFtZSA9IGN1cnJlbnRGaWxlLm5hbWU7XHJcbiAgICBuZXdBdHRhY2htZW50LkZpbGVFeHRlbnNpb24gPSBjdXJyZW50RmlsZS5uYW1lLnN1YnN0cihjdXJyZW50RmlsZS5uYW1lLmxhc3RJbmRleE9mKFwiLlwiKSArIDEpO1xyXG4gICAgbmV3QXR0YWNobWVudC5Jc0ltYWdlID0gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuY2hlY2tJbWFnZUZyb21NaW1lVHlwZShjdXJyZW50RmlsZS50eXBlKTtcclxuXHJcbiAgICBjb25zdCBmaWxlU2l6ZU1CID0gY3VycmVudEZpbGUuc2l6ZSAvIDEwMjQgLyAxMDI0O1xyXG4gICAgY29uc3QgaXNMYXJnZUZpbGUgPSBmaWxlU2l6ZU1CID4gdGhpcy5iYXNlNjRMaW1pdE1CO1xyXG4gICAgY29uc3QgaXNWaWRlbyA9IGN1cnJlbnRGaWxlLnR5cGUuc3RhcnRzV2l0aCgndmlkZW8nKTtcclxuXHJcbiAgICBpZiAoaXNWaWRlbykge1xyXG4gICAgICBsZXQgZmluYWxGaWxlOiBGaWxlIHwgQmxvYiA9IGN1cnJlbnRGaWxlO1xyXG5cclxuICAgICAgLy8gMS4gR2VuZXJhIGxhIG1pbmlhdHVyYSAocmltYW5lIGxhdG8gY2xpZW50IHBlcmNow6kgw6ggdW4nb3BlcmF6aW9uZSBpc3RhbnRhbmVhKVxyXG4gICAgICBuZXdBdHRhY2htZW50LkZpbGVUaHVtYm5haWxCYXNlNjQgPSBhd2FpdCB0aGlzLmdlbmVyYXRlVmlkZW9UaHVtYm5haWwoY3VycmVudEZpbGUpO1xyXG5cclxuICAgICAgLy8gMi4gU2UgbGEgY29tcHJlc3Npb25lIMOoIGFiaWxpdGF0YSwgaW52aWFtbyBpbCBmaWxlIGFsbCdBUEkgQyNcclxuICAgICAgaWYgKHRoaXMudmlkZW9Db21wcmVzc2lvbi5lbmFibGVkKSB7XHJcbiAgICAgICAgdGhpcy5zaG93VG9hc3QoXCJDb21wcmVzc2lvbmUgdmlkZW8gaW4gY29yc28uLi4gTCdvcGVyYXppb25lIHBvdHJlYmJlIHJpY2hpZWRlcmUgYWxjdW5pIG1pbnV0aS5cIiwgXCJpbmZvXCIpO1xyXG5cclxuICAgICAgICB0cnkge1xyXG4gICAgICAgICAgLy8gQ2hpYW1hdGEgYWwgbWljcm9zZXJ2aXppbyBDIyAobWV0b2RvIHJpc3RydXR0dXJhdG8gcHJlY2VkZW50ZW1lbnRlKVxyXG4gICAgICAgICAgY29uc3QgY29tcHJlc3NlZEJsb2IgPSBhd2FpdCB0aGlzLmNvbXByZXNzVmlkZW9BcGkoY3VycmVudEZpbGUsIHRoaXMudmlkZW9Db21wcmVzc2lvbik7XHJcblxyXG4gICAgICAgICAgLy8gQ3JlaWFtbyBpbCBudW92byBub21lIGZpbGUgY29uIGVzdGVuc2lvbmUgLm1wNFxyXG4gICAgICAgICAgY29uc3QgbmV3RmlsZU5hbWUgPSBjdXJyZW50RmlsZS5uYW1lLnJlcGxhY2UoL1xcLlteLy5dKyQvLCBcIlwiKSArIFwiLm1wNFwiO1xyXG5cclxuICAgICAgICAgIC8vIFRyYXNmb3JtaWFtbyBpbCBCbG9iIHJpY2V2dXRvIGluIHVuIEZpbGUgcGVyIG1hbnRlbmVyZSBsYSBjb2VyZW56YSBuZWxsJ29nZ2V0dG8gRFRPXHJcbiAgICAgICAgICBmaW5hbEZpbGUgPSBuZXcgRmlsZShbY29tcHJlc3NlZEJsb2JdLCBuZXdGaWxlTmFtZSwgeyB0eXBlOiBcInZpZGVvL21wNFwiIH0pO1xyXG5cclxuICAgICAgICAgIC8vIEFnZ2lvcm5pYW1vIGkgbWV0YWRhdGkgZGVsbCdhbGxlZ2F0b1xyXG4gICAgICAgICAgbmV3QXR0YWNobWVudC5GaWxlTmFtZSA9IG5ld0ZpbGVOYW1lO1xyXG4gICAgICAgICAgbmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBcInZpZGVvL21wNFwiO1xyXG5cclxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IoXCJFcnJvcmUgZHVyYW50ZSBsYSBjb21wcmVzc2lvbmUgcmVtb3RhIGRlbCB2aWRlby4gVmVycsOgIGNhcmljYXRvIGlsIGZpbGUgb3JpZ2luYWxlLlwiKTtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJWaWRlbyBBUEkgRXJyb3I6XCIsIGVycm9yKTtcclxuICAgICAgICAgIC8vIEluIGNhc28gZGkgZXJyb3JlIGRlbGwnQVBJLCBmaW5hbEZpbGUgcmltYW5lIGlsIGN1cnJlbnRGaWxlIG9yaWdpbmFsZVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gSW1wb3N0aWFtbyBpbCBmaWxlIChjb21wcmVzc28gbyBvcmlnaW5hbGUpIGNvbWUgTGFyZ2VGaWxlXHJcbiAgICAgIG5ld0F0dGFjaG1lbnQuTGFyZ2VGaWxlID0gZmluYWxGaWxlIGFzIEZpbGU7XHJcbiAgICAgIG5ld0F0dGFjaG1lbnQuSXNMYXJnZUZpbGUgPSB0cnVlO1xyXG4gICAgICByZXR1cm4gbmV3QXR0YWNobWVudDtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoaXNMYXJnZUZpbGUpIHtcclxuICAgICAgLy8gQ0FTTyBMQVJHRSBGSUxFOlxyXG4gICAgICAvLyBQb3BvbGlhbW8gT3JpZ2luYWxGaWxlIGUgZm9yemlhbW8gaWwgQmFzZTY0IGEgbnVsbC5cclxuICAgICAgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IG51bGw7XHJcbiAgICAgIG5ld0F0dGFjaG1lbnQuTGFyZ2VGaWxlID0gY3VycmVudEZpbGU7XHJcbiAgICAgIG5ld0F0dGFjaG1lbnQuSXNMYXJnZUZpbGUgPSB0cnVlO1xyXG4gICAgICBnZXRCYXNlNjQgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoZ2V0QmFzZTY0ID09IHRydWUpIHtcclxuICAgICAgbGV0IGJhc2U2NFJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0QmFzZTY0RnJvbUZpbGUoY3VycmVudEZpbGUpO1xyXG4gICAgICBuZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gYmFzZTY0UmVzdWx0LkJhc2U2NEZpbGU7XHJcbiAgICAgIGlmICghbmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgJiYgYmFzZTY0UmVzdWx0LkNvbnRlbnRUeXBlKSB7XHJcbiAgICAgICAgbmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBiYXNlNjRSZXN1bHQuQ29udGVudFR5cGU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChuZXdBdHRhY2htZW50LklzSW1hZ2UgJiYgbmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiBjcm9wRmlsZSkge1xyXG4gICAgICAgIHRoaXMuZ2V0Q3JvcHBlZEFuZFVwbG9hZChgZGF0YToke2Jhc2U2NFJlc3VsdC5Db250ZW50VHlwZX07YmFzZTY0LCR7YmFzZTY0UmVzdWx0LkJhc2U2NEZpbGV9YCwgbmV3QXR0YWNobWVudCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbmV3QXR0YWNobWVudDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEEgcGFydGlyZSBkYWwgZmlsZSBwYXNzYXRvIGluIGlucHV0IHJlc3RpdHVpc2NlIHVuIG9nZ2V0dG9cclxuICAgKiBjb250ZW5lbnRlIGlsIGJhc2U2NCBkZWwgZmlsZSBlIGlsIHN1byBjb250ZW50VHlwZVxyXG4gICAqIEBwYXJhbSBjdXJyZW50RmlsZSBPZ2dldHRvIEZpbGUgZGEgY3VpIGVzdHJhcG9sYXJlIGJhc2U2NCBlIGNvbnRlbnRUeXBlXHJcbiAgICogQHJldHVybnMgUmVzdGl0dWlzY2UgdW4gb2dnZXR0byBhdmVudGUgbGUgcHJvcHJpZXTDoCBCYXNlNjRGaWxlIGUgQ29udGVudFR5cGVcclxuICAgKi9cclxuICBwcml2YXRlIGFzeW5jIGdldEJhc2U2NEZyb21GaWxlKGN1cnJlbnRGaWxlOiBGaWxlKTogUHJvbWlzZTxhbnk+IHtcclxuICAgIGNvbnN0IGZpbGVTaXplTUIgPSBjdXJyZW50RmlsZS5zaXplIC8gMTAyNCAvIDEwMjQ7XHJcbiAgICBpZiAoZmlsZVNpemVNQiA+IHRoaXMuYmFzZTY0TGltaXRNQikge1xyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIEJhc2U2NEZpbGU6IG51bGwsXHJcbiAgICAgICAgQ29udGVudFR5cGU6IGN1cnJlbnRGaWxlLnR5cGVcclxuICAgICAgfTtcclxuICAgIH1cclxuICAgIC8vIFByb2NlZHVyYSBzdGFuZGFyZFxyXG4gICAgdHJ5IHtcclxuICAgICAgbGV0IGJhc2U2NEZpbGUgPSBhd2FpdCB0b0Jhc2U2NChjdXJyZW50RmlsZSk7XHJcbiAgICAgIGxldCBjb250ZW50VHlwZTogc3RyaW5nID0gbnVsbDtcclxuICAgICAgaWYgKGJhc2U2NEZpbGUpIHtcclxuICAgICAgICBjb250ZW50VHlwZSA9IGJhc2U2NEZpbGUuc3BsaXQoXCIsXCIpWzBdLnNwbGl0KFwiOlwiKVsxXS5zcGxpdChcIjtcIilbMF07XHJcbiAgICAgICAgYmFzZTY0RmlsZSA9IGJhc2U2NEZpbGUuc3BsaXQoXCIsXCIpWzFdO1xyXG4gICAgICB9XHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgQmFzZTY0RmlsZTogYmFzZTY0RmlsZSxcclxuICAgICAgICBDb250ZW50VHlwZTogY29udGVudFR5cGVcclxuICAgICAgfTtcclxuICAgIH0gY2F0Y2ggKGV4KSB7XHJcbiAgICAgIHJldHVybiB7IEJhc2U2NEZpbGU6IG51bGwsIENvbnRlbnRUeXBlOiBudWxsIH07XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb250cm9sbGEgc2UgaWwgZmlsZSBjaGUgc2kgc3RhIGNhcmljYW5kbyDDqCBzdXBwb3J0YXRvIGRhbCBzaXN0ZW1hLlxyXG4gICAqIEByZXR1cm5zXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjaGVja0FjY2VwdGVkRmlsZXMoKTogYm9vbGVhbiB7XHJcbiAgICAvLyBTZSBhY2NldHRvIHR1dHRvLCBlc2NvIHN1Yml0b1xyXG4gICAgaWYgKHRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMgPT09IFwiKlwiKSByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgICBjb25zdCBpc1R5cGVWYWxpZCA9IChtaW1lVHlwZTogc3RyaW5nKTogYm9vbGVhbiA9PiB7XHJcbiAgICAgIGlmICghbWltZVR5cGUpIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICAgIC8vIENvbnRyb2xsbyBjb3JyaXNwb25kZW56YSBlc2F0dGEgKGVzLiBpbWFnZS9wbmcpXHJcbiAgICAgIGlmICh0aGlzLmFjY2VwdGVkRmlsZVR5cGVzLmluY2x1ZGVzKG1pbWVUeXBlKSkgcmV0dXJuIHRydWU7XHJcblxyXG4gICAgICBjb25zdCB3aWxkY2FyZHMgPSB0aGlzLmFjY2VwdGVkRmlsZVR5cGVzLnNwbGl0KFwiLFwiKS5maWx0ZXIodCA9PiB0LmluY2x1ZGVzKFwiKlwiKSk7XHJcbiAgICAgIGZvciAobGV0IHQgb2Ygd2lsZGNhcmRzKSB7XHJcbiAgICAgICAgY29uc3QgcHJlZml4ID0gdC5zcGxpdChcIipcIilbMF07IC8vIFByZW5kZSBcImltYWdlL1wiIGRhIFwiaW1hZ2UvKlwiXHJcbiAgICAgICAgaWYgKG1pbWVUeXBlLnN0YXJ0c1dpdGgocHJlZml4KSkgcmV0dXJuIHRydWU7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH07XHJcblxyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT09IHRydWUpIHtcclxuICAgICAgLy8gQ2FzbyBTaW5nb2xvXHJcbiAgICAgIHJldHVybiBpc1R5cGVWYWxpZCh0aGlzLnNlbGVjdGVkRmlsZS50eXBlKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIENhc28gTXVsdGlwbG86IFRVVFRJIGkgZmlsZSBzZWxlemlvbmF0aSBkZXZvbm8gZXNzZXJlIHZhbGlkaVxyXG4gICAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLnNlbGVjdGVkRmlsZXMpLmV2ZXJ5KGZpbGUgPT4gaXNUeXBlVmFsaWQoZmlsZS50eXBlKSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZSBlcXAtYXR0YWNobWVudHMgw6ggc3RhdGEgY29uZmlndXJhdGEgcGVyIGlsIGNhcmljYW1lbnRvIGRlbGxlIHNvbGUgaW1tYWdpbmkgYWxsb3JhIHZlcmlmaWNhIGNoZSBpbCBmaWxlIHBhc3NhdG8gaW5cclxuICAgKiBpbnB1dCBzaWEgZWZmZXR0aXZhbWVudGUgdW4gaW1tYWdpbmUgbyBuby5cclxuICAgKiBTZSBpbCBjb250cm9sbG8gdmEgYSBidW9uIGZpbmUgcmVzdGl0dWlzY2UgVFJVRSBhbHRyaW1lbnRpIG1vc3RyYSB1biBtZXNzYWdnaW8gZCdlcnJvcmUgZSByZXN0aXR1aXNjZSBGQUxTRVxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2hlY2tBbGxvd09ubHlJbWFnZUZpbGUobmV3QXR0YWNobWVudCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuYWxsb3dPbmx5SW1hZ2VzID09IHRydWUgJiYgbmV3QXR0YWNobWVudC5Jc0ltYWdlICE9IHRydWUpIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IodGhpcy5ub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2UpO1xyXG4gICAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9IGVsc2UgaWYgKCF0aGlzLmNoZWNrQWNjZXB0ZWRGaWxlcygpKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkVycm9yKHRoaXMud3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2UpO1xyXG4gICAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICAvLyNyZWdpb24gR2VzdGlvbmUgY3JvcCBmaWxlXHJcblxyXG4gIGdldEltYWdlRGltZW5zaW9ucyhpbWc6IGFueSkge1xyXG4gICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcclxuICAgIHJlYWRlci5vbmxvYWQgPSAoZTogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IGltYWdlID0gbmV3IEltYWdlKCk7XHJcbiAgICAgIGltYWdlLnNyYyA9IGUudGFyZ2V0LnJlc3VsdDtcclxuICAgICAgaW1hZ2Uub25sb2FkID0gKHJzKSA9PiB7XHJcbiAgICAgICAgdGhpcy5vcmlnaW5hbEhlaWdodCA9IHJzLmN1cnJlbnRUYXJnZXRbXCJoZWlnaHRcIl07XHJcbiAgICAgICAgdGhpcy5vcmlnaW5hbFdpZHRoID0gcnMuY3VycmVudFRhcmdldFtcIndpZHRoXCJdO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5vcmlnaW5hbFdpZHRoID4gMTI4MCkge1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21XaWR0aCA9IDEyODA7XHJcbiAgICAgICAgICB0aGlzLmN1c3RvbUhlaWdodCA9IE1hdGgucm91bmQoKDEyODAgKiB0aGlzLm9yaWdpbmFsSGVpZ2h0KSAvIHRoaXMub3JpZ2luYWxXaWR0aCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gcnMuY3VycmVudFRhcmdldFtcImhlaWdodFwiXTtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tV2lkdGggPSBycy5jdXJyZW50VGFyZ2V0W1wid2lkdGhcIl07XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG4gICAgfTtcclxuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGltZyk7XHJcbiAgfVxyXG5cclxuICByZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKCkge1xyXG4gICAgdGhpcy5jdXN0b21XaWR0aCA9IHRoaXMub3JpZ2luYWxXaWR0aDtcclxuICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gdGhpcy5vcmlnaW5hbEhlaWdodDtcclxuICAgIHRoaXMuY2FudmFzUm90YXRpb24gPSAwO1xyXG4gICAgdGhpcy50cmFuc2Zvcm0gPSB7fTtcclxuICB9XHJcblxyXG4gIG9uRGltZW5zaW9uc0NoYW5nZShkaW1lbnNpb246IHN0cmluZykge1xyXG4gICAgaWYgKGRpbWVuc2lvbiA9PSBcIkhcIikge1xyXG4gICAgICB0aGlzLmN1c3RvbVdpZHRoID0gTWF0aC5yb3VuZCgodGhpcy5jdXN0b21IZWlnaHQgKiB0aGlzLm9yaWdpbmFsV2lkdGgpIC8gdGhpcy5vcmlnaW5hbEhlaWdodCk7XHJcbiAgICB9IGVsc2UgaWYgKGRpbWVuc2lvbiA9PSBcIldcIikge1xyXG4gICAgICB0aGlzLmN1c3RvbUhlaWdodCA9IE1hdGgucm91bmQoKHRoaXMuY3VzdG9tV2lkdGggKiB0aGlzLm9yaWdpbmFsSGVpZ2h0KSAvIHRoaXMub3JpZ2luYWxXaWR0aCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbWFnZUNyb3BwZWQoZXZlbnQ6IEltYWdlQ3JvcHBlZEV2ZW50KSB7XHJcbiAgICB0aGlzLmNyb3BwZWRJbWFnZSA9IGV2ZW50LmJhc2U2NDtcclxuICAgIHRoaXMuZ2V0Q3JvcHBlZEFuZFVwbG9hZCh0aGlzLmNyb3BwZWRJbWFnZSwgdGhpcy5uZXdBdHRhY2htZW50KTtcclxuICB9XHJcblxyXG4gIGdldENyb3BwZWRBbmRVcGxvYWQoZmlsZSwgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIHZhciBzZWxmID0gdGhpcztcclxuXHJcbiAgICB2YXIgZmlsZTogYW55ID0gYmFzZTY0VG9GaWxlKGZpbGUpO1xyXG5cclxuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmNvbXByZXNzaW9uT3B0aW9ucztcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbXByaW1lIGwnaW1tYWdpbmUgcGFzc2FuZG8gY29tZSBwYXJhbWV0cmkgbGUgb3B0aW9ucyBjcmVhdGUgbmVsbCdvZ2dldHRvIHNvcHJhLCBlIGlsIGZpbGUgZGFsIHJlYWRlciBwcmluY2lwYWxlXHJcbiAgICAgKi9cclxuICAgIGltYWdlQ29tcHJlc3Npb24oZmlsZSwgb3B0aW9ucykudGhlbigoZmlsZUNvbXByZXNzZWQpID0+IHtcclxuICAgICAgbGV0IGZpbGVSZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG5cclxuICAgICAgLy9GYWNjaW8gbGEgcHVzaCBkaSBvZ25pIGZpbGUgYWxsJ2ludGVybm8gZGVsbCdhcnJheSBkaSBmaWxlIGRlbGwnaXRlbSBkYSBtYW5kYXJlIGFsIHNlcnZlclxyXG4gICAgICBmaWxlUmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBsZXQgcmVzdWx0UmVhZGVyID0gPHN0cmluZz5maWxlUmVhZGVyLnJlc3VsdDtcclxuICAgICAgICB2YXIgbWFya2VyID0gXCI7YmFzZTY0LFwiO1xyXG4gICAgICAgIG5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSByZXN1bHRSZWFkZXIuc3Vic3RyaW5nKHJlc3VsdFJlYWRlci5pbmRleE9mKG1hcmtlcikgKyBtYXJrZXIubGVuZ3RoKTtcclxuICAgICAgICBzZWxmLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgICAgICBpZiAoc2VsZi5uZXdBdHRhY2htZW50Rm9ybSkge1xyXG4gICAgICAgICAgc2VsZi5uZXdBdHRhY2htZW50Rm9ybS5lbmFibGUoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICBmaWxlUmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZUNvbXByZXNzZWQpO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICByb3RhdGVMZWZ0KCkge1xyXG4gICAgdGhpcy5jYW52YXNSb3RhdGlvbi0tO1xyXG4gICAgdGhpcy5mbGlwQWZ0ZXJSb3RhdGUoKTtcclxuICB9XHJcblxyXG4gIHJvdGF0ZVJpZ2h0KCkge1xyXG4gICAgdGhpcy5jYW52YXNSb3RhdGlvbisrO1xyXG4gICAgdGhpcy5mbGlwQWZ0ZXJSb3RhdGUoKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZmxpcEFmdGVyUm90YXRlKCkge1xyXG4gICAgY29uc3QgZmxpcHBlZEggPSB0aGlzLnRyYW5zZm9ybS5mbGlwSDtcclxuICAgIGNvbnN0IGZsaXBwZWRWID0gdGhpcy50cmFuc2Zvcm0uZmxpcFY7XHJcbiAgICB0aGlzLnRyYW5zZm9ybSA9IHtcclxuICAgICAgLi4udGhpcy50cmFuc2Zvcm0sXHJcbiAgICAgIGZsaXBIOiBmbGlwcGVkVixcclxuICAgICAgZmxpcFY6IGZsaXBwZWRIXHJcbiAgICB9O1xyXG4gIH1cclxuXHJcbiAgZmxpcEhvcml6b250YWwoKSB7XHJcbiAgICB0aGlzLnRyYW5zZm9ybSA9IHtcclxuICAgICAgLi4udGhpcy50cmFuc2Zvcm0sXHJcbiAgICAgIGZsaXBIOiAhdGhpcy50cmFuc2Zvcm0uZmxpcEhcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBmbGlwVmVydGljYWwoKSB7XHJcbiAgICB0aGlzLnRyYW5zZm9ybSA9IHtcclxuICAgICAgLi4udGhpcy50cmFuc2Zvcm0sXHJcbiAgICAgIGZsaXBWOiAhdGhpcy50cmFuc2Zvcm0uZmxpcFZcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLyoqXHJcbiAgICogQW5udWxsYSBsYSBzZWxlemlvbmUgZGVsIGZpbGUsIHN2dW90YW5kbyBsJ2lucHV0IGUgcmVzZXR0YW5kbyB0dXR0ZSBsZSBwcm9wcmlldMOgIGRlbGwnSUF0dGFjaG1lbnREVE9cclxuICAgKi9cclxuICBhYm9ydEZpbGUoKSB7XHJcbiAgICBpZiAodGhpcy5pbWFnZUlucHV0KSB0aGlzLmltYWdlSW5wdXQubmF0aXZlRWxlbWVudC52YWx1ZSA9IFwiXCI7XHJcblxyXG4gICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBudWxsO1xyXG4gICAgdGhpcy5zZWxlY3RlZEZpbGVzID0gbnVsbDtcclxuICAgIHRoaXMuc2hvd0Nyb3BJbWFnZSA9IGZhbHNlO1xyXG5cclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlID0gZmFsc2U7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSBudWxsO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVOYW1lID0gbnVsbDtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRXh0ZW5zaW9uID0gbnVsbDtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBudWxsO1xyXG5cclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICB0aGlzLmN1c3RvbUhlaWdodCA9IG51bGw7XHJcbiAgICB0aGlzLmN1c3RvbVdpZHRoID0gbnVsbDtcclxuICAgIHRoaXMub3JpZ2luYWxIZWlnaHQgPSBudWxsO1xyXG4gICAgdGhpcy5vcmlnaW5hbFdpZHRoID0gbnVsbDtcclxuXHJcbiAgICB0aGlzLmRpYWxvZ1JlZkNyb3BJbWFnZS5jbG9zZSgpO1xyXG4gICAgdGhpcy5yZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKCk7XHJcbiAgfVxyXG5cclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgZmlsZURyb3BwZWQoZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xyXG5cclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgIHRoaXMuZHJhZ092ZXIgPSBmYWxzZTtcclxuXHJcbiAgICBjb25zdCBmaWxlcyA9IGV2ZW50LmRhdGFUcmFuc2Zlcj8uZmlsZXM7XHJcblxyXG4gICAgaWYgKGZpbGVzICYmIGZpbGVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgdGhpcy5vbkZpbGVBZGRlZCh7IHRhcmdldDogeyBmaWxlczogZmlsZXMgfSB9KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIFNlIGlsIGNhcmljYW1lbnRvIGRlbCBmaWxlIGRyb3Bib3ggdmEgYSBidW9uIGZpbmUsIGxhIGZ1bnppb25lIGRpIGNhbGxiYWNrIHJlc3RpdHVpc2NlIHVuIGFycmF5IGRpIG9nZ2V0dGkuXHJcbiAgLy8gVmllbmUgcG9pIGZhdHRhIHVuYSBYTUxIdHRwUmVxdWVzdCBjb24gcmVzcG9uc2VUeXBlICdibG9iJyBwZXIgY29udmVydGlyZSBpbCBwcmltbyBlbGVtZW50byBkZWxsYSByZXNwb25zZSBpbiB1biBCbG9iLlxyXG4gIGNob29zZURyb3Bib3hGaWxlKCkge1xyXG4gICAgaWYgKHRoaXMuaXNEaXNhYmxlZCkgcmV0dXJuO1xyXG4gICAgdmFyIG9wdGlvbnMgPSB7XHJcbiAgICAgIHN1Y2Nlc3M6IChmaWxlczogYW55W10pID0+IHtcclxuICAgICAgICBjb25zdCB4aHIgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcclxuICAgICAgICB4aHIub3BlbihcIkdFVFwiLCBmaWxlc1swXS5saW5rKTtcclxuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihcIkF1dGhvcml6YXRpb25cIiwgYEJlYXJlciAke0F0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLmRyb3Bib3hDcmVkZW50aWFscy5hY2Nlc3NUb2tlbn1gKTtcclxuICAgICAgICB4aHIucmVzcG9uc2VUeXBlID0gXCJibG9iXCI7XHJcblxyXG4gICAgICAgIHhoci5vbmxvYWQgPSAoKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBibG9iID0geGhyLnJlc3BvbnNlO1xyXG4gICAgICAgICAgY29uc3QgZmlsZSA9IG5ldyBGaWxlKFtibG9iXSwgZmlsZXNbMF0ubmFtZSwgeyB0eXBlOiBibG9iLnR5cGUgfSk7XHJcbiAgICAgICAgICBsZXQgZmlsZXNBZGRlZCA9IFtmaWxlXTtcclxuICAgICAgICAgIHRoaXMub25GaWxlQWRkZWQoZmlsZXNBZGRlZCwgdHJ1ZSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgeGhyLnNlbmQoKTtcclxuICAgICAgfSxcclxuICAgICAgbGlua1R5cGU6IFwiZGlyZWN0XCIsXHJcbiAgICAgIG11bHRpc2VsZWN0OiBmYWxzZSxcclxuICAgICAgZXh0ZW5zaW9uczogW1wiLmpwZ1wiLCBcIi5wbmdcIiwgXCIucGRmXCIsIFwiLmRvY1wiLCBcIi5kb2N4XCIsIFwiLnR4dFwiXVxyXG4gICAgfTtcclxuICAgIERyb3Bib3guY2hvb3NlKG9wdGlvbnMpO1xyXG4gIH1cclxuXHJcbiAgLy8gV29ya2Fyb3VuZCBkcm9wem9uZTogZGlzYWJpbGl0byBpbCBjbGljayBkZWdsaSBlbGVtZW50aSBpbmNsdXNpIG5lbGxhIGRyb3B6b25lIHBlciBldml0YXJlIGRpIGNsaWNjYXJlIGR1ZSB2b2x0ZVxyXG4gIG9uU2VsZWN0RmlsZShldmVudCwgZmlsZUlucHV0KSB7XHJcbiAgICBpZiAoXHJcbiAgICAgIChldmVudC50YXJnZXQgYXMgSFRNTEJ1dHRvbkVsZW1lbnQpLnRhZ05hbWUgPT09IFwiQlVUVE9OXCIgfHxcclxuICAgICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MQnV0dG9uRWxlbWVudCkudGFnTmFtZSA9PT0gXCJJTlBVVFwiIHx8XHJcbiAgICAgIHRoaXMuYWRkaW5nTGlua01vZGUgPT0gdHJ1ZVxyXG4gICAgKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGZpbGVJbnB1dC5jbGljaygpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXByZSBpbCBkaWFsb2dvIHBlciBsJ2luc2VyaW1lbnRvIGRlbCBsaW5rLlxyXG4gICAqL1xyXG4gIHN3aXRjaFRvQWRkaW5nTGlua01vZGUoKTogdm9pZCB7XHJcblxyXG4gICAgaWYgKHRoaXMuaXNEaXNhYmxlZCkgcmV0dXJuO1xyXG5cclxuICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0gPSB0aGlzLmZvcm1CdWlsZGVyLmdyb3VwKHtcclxuICAgICAgZmlsZU5hbWU6IFsnJ10sXHJcbiAgICAgIGZpbGVQYXRoOiBbJycsIFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLnBhdHRlcm4oJ2h0dHBzPzovLy4rJyldXVxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3Blbih0aGlzLmFkZGluZ0xpbmtUZW1wbGF0ZSwge1xyXG4gICAgICB3aWR0aDogJzUwMHB4JyxcclxuICAgICAgcGFuZWxDbGFzczogJ2VxcC1hdHRhY2htZW50cy1kaWFsb2cnXHJcbiAgICB9KTtcclxuXHJcbiAgICBkaWFsb2dSZWYuYWZ0ZXJDbG9zZWQoKS5zdWJzY3JpYmUocmVzdWx0ID0+IHtcclxuICAgICAgaWYgKHJlc3VsdCkge1xyXG4gICAgICAgIC8vIENyZWEgbCdvZ2dldHRvIHBlciBpbCBudW92byBsaW5rIGRhaSBkYXRpIGRlbCBmb3JtXHJcbiAgICAgICAgY29uc3QgbmV3TGlua09iamVjdDogSUF0dGFjaG1lbnREVE8gPSB7XHJcbiAgICAgICAgICBJRDogMCxcclxuICAgICAgICAgIEF0dGFjaG1lbnRUeXBlOiBBdHRhY2htZW50VHlwZS5MSU5LLFxyXG4gICAgICAgICAgRmlsZU5hbWU6IHJlc3VsdC5maWxlTmFtZSxcclxuICAgICAgICAgIEZpbGVQYXRoOiByZXN1bHQuZmlsZVBhdGgsXHJcbiAgICAgICAgICBJc0ltYWdlOiBmYWxzZVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudCA9IG5ld0xpbmtPYmplY3Q7XHJcbiAgICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gW25ld0xpbmtPYmplY3RdO1xyXG5cclxuXHJcbiAgICAgICAgdGhpcy5jb25maXJtQWRkQXR0YWNobWVudCgpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG5cclxuXHJcbiAgLy8gTWV0b2RvIHBlciBvdHRlbmVyZSBsZSBjbGFzc2kgQ1NTIGRpbmFtaWNoZVxyXG4gIGdldENhcmRDbGFzcyhhdHQ6IElBdHRhY2htZW50RFRPKTogeyBba2V5OiBzdHJpbmddOiBib29sZWFuIH0ge1xyXG4gICAgcmV0dXJuIHtcclxuICAgICAgJ2ZpbGUtcHJldmlldyc6IHRydWUsXHJcbiAgICAgICd1cGxvYWRpbmcnOiAhIWF0dC5pc1VwbG9hZGluZyxcclxuICAgICAgJ2NhcmQtc21hbGwnOiB0aGlzLmNhcmRTaXplID09PSAnc21hbGwnLFxyXG4gICAgICAnY2FyZC1tZWRpdW0nOiB0aGlzLmNhcmRTaXplID09PSAnbWVkaXVtJyxcclxuICAgICAgJ2NhcmQtbGFyZ2UnOiB0aGlzLmNhcmRTaXplID09PSAnbGFyZ2UnLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIC8vIFF1ZXN0YSBmdW56aW9uZSBvcmEgc2kgYXBwbGljYSBhbCBjb250ZW5pdG9yZSwgbm9uIGFsbGEgc2luZ29sYSBjYXJkLlxyXG4gIGdldFByZXZpZXdzQ29udGFpbmVyU3R5bGUoKTogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSB7XHJcbiAgICBsZXQgbWluV2lkdGggPSAnMjAwcHgnOyAvLyBEaW1lbnNpb25lIGRpIGRlZmF1bHQgcGVyICdtZWRpdW0nXHJcblxyXG4gICAgaWYgKHRoaXMuY2FyZFNpemUgPT09ICdzbWFsbCcpIHtcclxuICAgICAgbWluV2lkdGggPSAnMTQwcHgnO1xyXG4gICAgfSBlbHNlIGlmICh0aGlzLmNhcmRTaXplID09PSAnbGFyZ2UnKSB7XHJcbiAgICAgIG1pbldpZHRoID0gJzI4MHB4JztcclxuICAgIH0gZWxzZSBpZiAodGhpcy5jYXJkU2l6ZSA9PT0gJ2N1c3RvbScpIHtcclxuICAgICAgbWluV2lkdGggPSBgJHt0aGlzLmN1c3RvbUNhcmRXaWR0aFB4fXB4YDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4geyAnLS1jYXJkLW1pbi13aWR0aCc6IG1pbldpZHRoIH07XHJcbiAgfVxyXG5cclxuICBoYW5kbGVQcmltYXJ5QWN0aW9uKGF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPKTogdm9pZCB7XHJcbiAgICAvLyBTZSBpbCBmaWxlIHB1w7IgZXNzZXJlIHZpc3VhbGl6emF0byBpbiBhbnRlcHJpbWEsIGFwcmkgaWwgZGlhbG9nXHJcbiAgICBpZiAodGhpcy5jYW5CZVByZXZpZXdlZChhdHRhY2htZW50KSkge1xyXG4gICAgICB0aGlzLm9wZW5QcmV2aWV3RGlhbG9nKGF0dGFjaG1lbnQpO1xyXG4gICAgfVxyXG4gICAgLy8gQWx0cmltZW50aSwgZXNlZ3VpIGwnYXppb25lIGRpIGRlZmF1bHQgKGRvd25sb2FkIHBlciBmaWxlLCBhcHJpIHBlciBsaW5rKVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHRoaXMudmlld0F0dGFjaG1lbnQoYXR0YWNobWVudCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICogRGV0ZXJtaW5lcyBpZiBhbiBhdHRhY2htZW50IGNhbiBiZSBwcmV2aWV3ZWQgaW4gdGhlIGRpYWxvZy5cclxuICogQHBhcmFtIGF0dCBUaGUgYXR0YWNobWVudCB0byBjaGVjay5cclxuICogQHJldHVybnMgYHRydWVgIGlmIGEgcHJldmlldyBpcyBhdmFpbGFibGUsIG90aGVyd2lzZSBgZmFsc2VgLlxyXG4gKi9cclxuICBjYW5CZVByZXZpZXdlZChhdHQ6IElBdHRhY2htZW50RFRPKTogYm9vbGVhbiB7XHJcbiAgICBpZiAoIWF0dCkge1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2FzZSAxOiBJdCdzIGFuIGltYWdlIHdpdGggQmFzZTY0IGRhdGEuXHJcbiAgICBjb25zdCBpc1ByZXZpZXdhYmxlSW1hZ2UgPSBhdHQuSXNJbWFnZSAmJiAhIWF0dC5GaWxlRGF0YUJhc2U2NDtcclxuXHJcbiAgICAvLyBDYXNlIDI6IEl0J3MgYSBQREYgd2l0aCBCYXNlNjQgZGF0YS5cclxuICAgIGNvbnN0IGlzUHJldmlld2FibGVQZGYgPSBhdHQuRmlsZUNvbnRlbnRUeXBlID09PSAnYXBwbGljYXRpb24vcGRmJyAmJiAhIWF0dC5GaWxlRGF0YUJhc2U2NDtcclxuXHJcbiAgICAvLyBDYXNlIDM6IEl0J3MgYSByZW1vdGUgZG9jdW1lbnQgd2l0aCBhIFVSTCAoZm9yIEdvb2dsZSBWaWV3ZXIpLlxyXG4gICAgY29uc3QgaXNSZW1vdGVEb2N1bWVudCA9ICFhdHQuSXNJbWFnZSAmJiAhIWF0dC5GaWxlUGF0aCAmJiAhIXRoaXMucHJvZHVjdGlvbkJhc2VVcmw7XHJcblxyXG4gICAgLy9DYXNlIDQ6IFZpZGVvIC0gw4ggdW4gdmlkZW8gZSBhYmJpYW1vIGlsIGZpbGUgYmluYXJpbyBzYWx2YXRvIGluIExhcmdlRmlsZVxyXG4gICAgY29uc3QgaXNQcmV2aWV3YWJsZVZpZGVvID0gYXR0LkZpbGVDb250ZW50VHlwZT8uc3RhcnRzV2l0aCgndmlkZW8vJykgJiYgISFhdHQuTGFyZ2VGaWxlO1xyXG5cclxuICAgIC8vIEEgcHJldmlldyBpcyBwb3NzaWJsZSBpZiBhbnkgb2YgdGhlc2UgY29uZGl0aW9ucyBhcmUgdHJ1ZS5cclxuICAgIHJldHVybiBpc1ByZXZpZXdhYmxlSW1hZ2UgfHwgaXNQcmV2aWV3YWJsZVBkZiB8fCBpc1JlbW90ZURvY3VtZW50IHx8IGlzUHJldmlld2FibGVWaWRlbztcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaXNDb2x1bW5IaWRkZW4oY29sOiBBdHRhY2htZW50RmllbGRDb2x1bW4pOiBib29sZWFuIHtcclxuICAgIC8vIDEpIGhpZGRlbkNvbHVtbnNcclxuICAgIGlmICh0aGlzLmhpZGRlbkNvbHVtbnM/LmluY2x1ZGVzKGNvbC5rZXkpKSByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgICAvLyAyKSBoaWRkZW4gZGVmaW5pdG8gc3VsbGEgY29sb25uYSAoYm9vbGVhbiBvIGZ1bnppb25lIHNlbnphIGFyZ3MpXHJcbiAgICBpZiAodHlwZW9mIGNvbC5oaWRkZW4gPT09ICdmdW5jdGlvbicpIHJldHVybiAhIWNvbC5oaWRkZW4oKTtcclxuICAgIHJldHVybiAhIWNvbC5oaWRkZW47XHJcbiAgfVxyXG5cclxuICBpc0FjdGlvbkhpZGRlbihhY3Rpb246IEF0dGFjaG1lbnRNZW51QWN0aW9uLCBhdHQ/OiBJQXR0YWNobWVudERUTyk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuaGlkZGVuQWN0aW9ucz8uaW5jbHVkZXMoYWN0aW9uLmtleSkpIHJldHVybiB0cnVlO1xyXG4gICAgaWYgKHRoaXMuYWN0aW9uSGlkZGVuRm4/LihhY3Rpb24ua2V5LCBhdHQpKSByZXR1cm4gdHJ1ZTtcclxuICAgIGlmICh0eXBlb2YgYWN0aW9uLmhpZGRlbiA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuICEhYWN0aW9uLmhpZGRlbihhdHQpO1xyXG4gICAgcmV0dXJuICEhYWN0aW9uLmhpZGRlbjtcclxuICB9XHJcblxyXG4gIGlzQWN0aW9uRGlzYWJsZWQoYWN0aW9uOiBBdHRhY2htZW50TWVudUFjdGlvbiwgYXR0PzogSUF0dGFjaG1lbnREVE8pOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLmFjdGlvbkRpc2FibGVkRm4/LihhY3Rpb24ua2V5LCBhdHQpKSByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgICBpZiAodHlwZW9mIGFjdGlvbi5kaXNhYmxlZCA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuICEhYWN0aW9uLmRpc2FibGVkKGF0dCk7XHJcblxyXG4gICAgcmV0dXJuICEhYWN0aW9uLmRpc2FibGVkO1xyXG4gIH1cclxuXHJcbiAgaXNEZWxldGVIaWRkZW4oYXR0OiBJQXR0YWNobWVudERUTyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuYWN0aW9uSGlkZGVuRm4/LignZGVsZXRlJywgYXR0KSB8fCB0aGlzLmhpZGRlbkFjdGlvbnM/LmluY2x1ZGVzKCdkZWxldGUnKTtcclxuICB9XHJcblxyXG4gIGlzRGVsZXRlRGlzYWJsZWQoYXR0OiBJQXR0YWNobWVudERUTyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuZGlzYWJsZUFjdGlvbiB8fCAhIXRoaXMuYWN0aW9uRGlzYWJsZWRGbj8uKCdkZWxldGUnLCBhdHQpO1xyXG4gIH1cclxuXHJcbiAgaXNQcmltYXJ5QWN0aW9uSGlkZGVuKGF0dDogSUF0dGFjaG1lbnREVE8pOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLmhpZGRlbkFjdGlvbnM/LmluY2x1ZGVzKCdkb3dubG9hZCcpIHx8IHRoaXMuaGlkZGVuQWN0aW9ucz8uaW5jbHVkZXMoJ3ByZXZpZXcnKSB8fCB0aGlzLmhpZGRlbkFjdGlvbnM/LmluY2x1ZGVzKCdwcmltYXJ5QWN0aW9uJykpIHJldHVybiB0cnVlO1xyXG4gICAgaWYgKHRoaXMuaGlkZGVuQ29sdW1ucz8uaW5jbHVkZXMoJ2Rvd25sb2FkJykgfHwgdGhpcy5oaWRkZW5Db2x1bW5zPy5pbmNsdWRlcygncHJldmlldycpIHx8IHRoaXMuaGlkZGVuQ29sdW1ucz8uaW5jbHVkZXMoJ3ByaW1hcnlBY3Rpb24nKSkgcmV0dXJuIHRydWU7XHJcbiAgICBpZiAodGhpcy5hY3Rpb25IaWRkZW5Gbj8uKCdwcmltYXJ5QWN0aW9uJywgYXR0KSB8fCB0aGlzLmFjdGlvbkhpZGRlbkZuPy4oJ2Rvd25sb2FkJywgYXR0KSB8fCB0aGlzLmFjdGlvbkhpZGRlbkZuPy4oJ3ByZXZpZXcnLCBhdHQpKSByZXR1cm4gdHJ1ZTtcclxuICAgIHJldHVybiBmYWxzZTtcclxuICB9XHJcblxyXG4gIGlzUHJpbWFyeUFjdGlvbkRpc2FibGVkKGF0dDogSUF0dGFjaG1lbnREVE8pOiBib29sZWFuIHtcclxuICAgIGlmICh0aGlzLmFjdGlvbkRpc2FibGVkRm4/LigncHJpbWFyeUFjdGlvbicsIGF0dCkgfHwgdGhpcy5hY3Rpb25EaXNhYmxlZEZuPy4oJ2Rvd25sb2FkJywgYXR0KSB8fCB0aGlzLmFjdGlvbkRpc2FibGVkRm4/LigncHJldmlldycsIGF0dCkpIHJldHVybiB0cnVlO1xyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcblxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogVW5pc2NlIGxlIGNvbG9ubmUgZGkgZGVmYXVsdCBjb24gcXVlbGxlIGN1c3RvbSBlIGxlIG9yZGluYS5cclxuICAgKi9cclxuICBwcml2YXRlIHNldHVwVGFibGVDb2x1bW5zKCk6IHZvaWQge1xyXG4gICAgLy8gRGVmaW5pYW1vIGxlIGNvbG9ubmUgc3RhbmRhcmQgY29uIHVuYSBwb3NpemlvbmVcclxuICAgIGNvbnN0IGRlZmF1bHRGaWxlQ29sdW1uOiBBdHRhY2htZW50RmllbGRDb2x1bW4gPSB7XHJcbiAgICAgIGtleTogJ2ZpbGUnLFxyXG4gICAgICBkaXNwbGF5OiAnRmlsZScsXHJcbiAgICAgIHR5cGU6IFR5cGVBdHRhY2htZW50Q29sdW1uLlRFTVBMQVRFLFxyXG4gICAgICBleHRlcm5hbFRlbXBsYXRlOiB0aGlzLmRlZmF1bHRGaWxlVGVtcGxhdGUsXHJcbiAgICAgIHN0eWxlczogeyBmbGV4OiAnMSAxIDAlJyB9LFxyXG4gICAgICBwb3NpdGlvbjogMTBcclxuICAgIH07XHJcblxyXG4gICAgY29uc3QgZGVmYXVsdEFjdGlvbnNDb2x1bW46IEF0dGFjaG1lbnRGaWVsZENvbHVtbiA9IHtcclxuICAgICAga2V5OiAnYWN0aW9ucycsXHJcbiAgICAgIGRpc3BsYXk6ICdBemlvbmknLFxyXG4gICAgICB0eXBlOiBUeXBlQXR0YWNobWVudENvbHVtbi5URU1QTEFURSxcclxuICAgICAgZXh0ZXJuYWxUZW1wbGF0ZTogdGhpcy5kZWZhdWx0QWN0aW9uc1RlbXBsYXRlLFxyXG4gICAgICBwb3NpdGlvbjogMTAwLFxyXG4gICAgICBjbGFzczogJ2NvbC1hY3Rpb25zJyxcclxuICAgICAgc3R5bGVzOiB7IGZsZXg6ICcwIDAgMTUwcHgnIH1cclxuICAgIH07XHJcblxyXG4gICAgY29uc3QgcHJvY2Vzc2VkQ3VzdG9tQ29sdW1ucyA9IHRoaXMuX2N1c3RvbUNvbHVtbnMubWFwKGNvbCA9PiB7XHJcbiAgICAgIC8vIEZsZXggZGkgZGVmYXVsdFxyXG4gICAgICBpZiAoIWNvbC5zdHlsZXMgfHwgIWNvbC5zdHlsZXMuZmxleCkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAuLi5jb2wsXHJcbiAgICAgICAgICBzdHlsZXM6IHsgLi4uY29sLnN0eWxlcywgZmxleDogJzEgMSAwJScgfVxyXG4gICAgICAgIH07XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIGNvbDtcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IGFsbENvbHVtbnMgPSBbXHJcbiAgICAgIGRlZmF1bHRGaWxlQ29sdW1uLFxyXG4gICAgICBkZWZhdWx0QWN0aW9uc0NvbHVtbixcclxuICAgICAgLi4ucHJvY2Vzc2VkQ3VzdG9tQ29sdW1uc1xyXG4gICAgXTtcclxuXHJcbiAgICAvLyBPcmRpbmlhbW8gbCdhcnJheSBmaW5hbGUgaW4gYmFzZSBhbGxhIHByb3ByaWV0w6AgJ3Bvc2l0aW9uJ1xyXG4gICAgdGhpcy5fdGFibGVDb2x1bW5zID0gYWxsQ29sdW1ucy5maWx0ZXIoY29sID0+ICF0aGlzLmlzQ29sdW1uSGlkZGVuKGNvbCkpXHJcbiAgICAgIC5zb3J0KChhLCBiKSA9PiB7XHJcbiAgICAgICAgY29uc3QgcG9zQSA9IGEucG9zaXRpb24gfHwgOTk7XHJcbiAgICAgICAgY29uc3QgcG9zQiA9IGIucG9zaXRpb24gfHwgOTk7XHJcbiAgICAgICAgcmV0dXJuIHBvc0EgLSBwb3NCO1xyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgc2V0dXBNZW51QWN0aW9ucygpOiB2b2lkIHtcclxuICAgIGNvbnN0IGRlZmF1bHRQcmV2aWV3QWN0aW9uOiBBdHRhY2htZW50TWVudUFjdGlvbiA9IHtcclxuICAgICAga2V5OiAncHJldmlldycsXHJcbiAgICAgIGljb246ICd2aXNpYmlsaXR5JyxcclxuICAgICAgbmFtZTogJ0FudGVwcmltYScsXHJcbiAgICAgIGZuOiAoYXR0KSA9PiB0aGlzLm9wZW5QcmV2aWV3RGlhbG9nKGF0dCksXHJcbiAgICAgIGRpc2FibGVkOiAoYXR0KSA9PiAhdGhpcy5jYW5CZVByZXZpZXdlZChhdHQpLFxyXG4gICAgICBwb3NpdGlvbjogMTBcclxuICAgIH07XHJcblxyXG4gICAgY29uc3QgZGVmYXVsdERlbGV0ZUFjdGlvbjogQXR0YWNobWVudE1lbnVBY3Rpb24gPSB7XHJcbiAgICAgIGtleTogJ2RlbGV0ZScsXHJcbiAgICAgIGljb246ICdkZWxldGUnLFxyXG4gICAgICBuYW1lOiAnRWxpbWluYScsXHJcbiAgICAgIGZuOiAoYXR0KSA9PiB0aGlzLmRlbGV0ZUF0dGFjaG1lbnQoYXR0KSxcclxuICAgICAgZGlzYWJsZWQ6ICgpID0+IHRoaXMuZGlzYWJsZUFjdGlvbixcclxuICAgICAgcG9zaXRpb246IDEwMFxyXG4gICAgfTtcclxuXHJcbiAgICBjb25zdCBhbGxBY3Rpb25zID0gW1xyXG4gICAgICBkZWZhdWx0UHJldmlld0FjdGlvbixcclxuICAgICAgZGVmYXVsdERlbGV0ZUFjdGlvbixcclxuICAgICAgLi4udGhpcy5fY3VzdG9tTWVudUFjdGlvbnNcclxuICAgIF07XHJcblxyXG4gICAgLy8gT3JkaW5pYW1vIGwnYXJyYXkgZmluYWxlIGluIGJhc2UgYWxsYSBwcm9wcmlldMOgICdwb3NpdGlvbidcclxuICAgIHRoaXMuX3NvcnRlZE1lbnVBY3Rpb25zID0gYWxsQWN0aW9ucy5zb3J0KChhLCBiKSA9PiB7XHJcbiAgICAgIGNvbnN0IHBvc0EgPSBhLnBvc2l0aW9uIHx8IDk5O1xyXG4gICAgICBjb25zdCBwb3NCID0gYi5wb3NpdGlvbiB8fCA5OTtcclxuICAgICAgcmV0dXJuIHBvc0EgLSBwb3NCO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGdlbmVyYXRlVmlkZW9UaHVtYm5haWwoZmlsZTogRmlsZSk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICBjb25zdCB2aWRlbyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7XHJcbiAgICAgIGNvbnN0IGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xyXG4gICAgICBjb25zdCBjb250ZXh0ID0gY2FudmFzLmdldENvbnRleHQoJzJkJyk7XHJcblxyXG4gICAgICAvLyBDcmVhIHVuIFVSTCB0ZW1wb3JhbmVvIHBlciBpbCBmaWxlIHZpZGVvXHJcbiAgICAgIGNvbnN0IHZpZGVvVXJsID0gVVJMLmNyZWF0ZU9iamVjdFVSTChmaWxlKTtcclxuICAgICAgdmlkZW8uc3JjID0gdmlkZW9Vcmw7XHJcbiAgICAgIHZpZGVvLnByZWxvYWQgPSAnbWV0YWRhdGEnO1xyXG4gICAgICB2aWRlby5tdXRlZCA9IHRydWU7XHJcbiAgICAgIHZpZGVvLnBsYXlzSW5saW5lID0gdHJ1ZTtcclxuXHJcbiAgICAgIHZpZGVvLm9ubG9hZGVkbWV0YWRhdGEgPSAoKSA9PiB7XHJcbiAgICAgICAgLy8gVmFpIGFsIHNlY29uZG8gMSAocGVyIGV2aXRhcmUgaWwgZm90b2dyYW1tYSBuZXJvIGluaXppYWxlKVxyXG4gICAgICAgIHZpZGVvLmN1cnJlbnRUaW1lID0gMTtcclxuICAgICAgfTtcclxuXHJcbiAgICAgIHZpZGVvLm9uc2Vla2VkID0gKCkgPT4ge1xyXG4gICAgICAgIC8vIEltcG9zdGEgbGUgZGltZW5zaW9uaSBkZWwgY2FudmFzIHVndWFsaSBhbCB2aWRlb1xyXG4gICAgICAgIGNhbnZhcy53aWR0aCA9IHZpZGVvLnZpZGVvV2lkdGg7XHJcbiAgICAgICAgY2FudmFzLmhlaWdodCA9IHZpZGVvLnZpZGVvSGVpZ2h0O1xyXG5cclxuICAgICAgICAvLyBEaXNlZ25hIGlsIGZvdG9ncmFtbWEgc3VsIGNhbnZhc1xyXG4gICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKHZpZGVvLCAwLCAwLCBjYW52YXMud2lkdGgsIGNhbnZhcy5oZWlnaHQpO1xyXG5cclxuICAgICAgICAvLyBFc3RyYWkgaWwgQmFzZTY0IChxdWFsaXTDoCAwLjcgcGVyIHJpc3Bhcm1pYXJlIHNwYXppbylcclxuICAgICAgICBjb25zdCB0aHVtYm5haWwgPSBjYW52YXMudG9EYXRhVVJMKCdpbWFnZS9qcGVnJywgMC43KTtcclxuXHJcbiAgICAgICAgLy8gUHVsaXNjaSBsYSBtZW1vcmlhXHJcbiAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh2aWRlb1VybCk7XHJcbiAgICAgICAgcmVzb2x2ZSh0aHVtYm5haWwuc3BsaXQoJywnKVsxXSk7IC8vIFJlc3RpdHVpYW1vIHNvbG8gbGEgcGFydGUgQmFzZTY0XHJcbiAgICAgIH07XHJcblxyXG4gICAgICB2aWRlby5vbmVycm9yID0gKGVycikgPT4ge1xyXG4gICAgICAgIFVSTC5yZXZva2VPYmplY3RVUkwodmlkZW9VcmwpO1xyXG4gICAgICAgIHJlamVjdChlcnIpO1xyXG4gICAgICB9O1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGFzeW5jIGNvbXByZXNzVmlkZW9BcGkoZmlsZTogRmlsZSwgY29uZmlnOiBhbnkpOiBQcm9taXNlPEJsb2I+IHtcclxuICAgIC8vIFByZXBhcmlhbW8gaWwgRm9ybURhdGEgcGVyIGludmlhcmUgaWwgZmlsZSBiaW5hcmlvIGUgaSBwYXJhbWV0cmkgZGkgY29uZmlndXJhemlvbmVcclxuICAgIGNvbnN0IGZvcm1EYXRhID0gbmV3IEZvcm1EYXRhKCk7XHJcbiAgICBmb3JtRGF0YS5hcHBlbmQoJ3ZpZGVvJywgZmlsZSk7XHJcbiAgICBmb3JtRGF0YS5hcHBlbmQoJ21heFdpZHRoJywgU3RyaW5nKGNvbmZpZy5tYXhXaWR0aCA/PyAxMjgwKSk7XHJcblxyXG4gICAgaWYgKGNvbmZpZy5jcmYgIT0gbnVsbCkgZm9ybURhdGEuYXBwZW5kKCdjcmYnLCBTdHJpbmcoY29uZmlnLmNyZikpO1xyXG4gICAgaWYgKGNvbmZpZy5wcmVzZXQpIGZvcm1EYXRhLmFwcGVuZCgncHJlc2V0JywgY29uZmlnLnByZXNldCk7XHJcblxyXG4gICAgaWYgKGNvbmZpZy5jcmYgPT0gbnVsbCkge1xyXG4gICAgICBmb3JtRGF0YS5hcHBlbmQoJ2JpdHJhdGUnLCBTdHJpbmcoY29uZmlnLmJpdHJhdGUgPz8gMjUwMDAwMCkpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChjb25maWcubWF4RnBzICE9IG51bGwpIGZvcm1EYXRhLmFwcGVuZCgnbWF4RnBzJywgU3RyaW5nKGNvbmZpZy5tYXhGcHMpKTtcclxuICAgIGlmIChjb25maWcuYXVkaW9CaXRyYXRlICE9IG51bGwpIGZvcm1EYXRhLmFwcGVuZCgnYXVkaW9CaXRyYXRlJywgU3RyaW5nKGNvbmZpZy5hdWRpb0JpdHJhdGUpKTtcclxuXHJcblxyXG4gICAgLy8gVVJMIGRlbGxhIHR1YSBBUEkgQyNcclxuICAgIGNvbnN0IGFwaVVybCA9ICdodHRwczovL3R1by1zZXJ2aXppby1hcGkuaXQvYXBpL3ZpZGVvL2NvbXByZXNzJztcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICAvLyBFZmZldHR1aWFtbyBsYSBjaGlhbWF0YS4gVXNpYW1vICdmZXRjaCcgcGVyIHNlbXBsaWNpdMOgIG8gSHR0cENsaWVudCBkaSBBbmd1bGFyXHJcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYXBpVXJsLCB7XHJcbiAgICAgICAgbWV0aG9kOiAnUE9TVCcsXHJcbiAgICAgICAgYm9keTogZm9ybURhdGEsXHJcbiAgICAgICAgLy8gTm90YTogTm9uIGltcG9zdGFyZSBDb250ZW50LVR5cGUsIGlsIGJyb3dzZXIgbG8gZmFyw6AgY29ycmV0dGFtZW50ZSBpbmNsdWRlbmRvIGlsIGJvdW5kYXJ5XHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgaWYgKCFyZXNwb25zZS5vaykge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRXJyb3JlIHNlcnZlcjogJHtyZXNwb25zZS5zdGF0dXNUZXh0fWApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBSaWNldmlhbW8gaWwgZmlsZSBjb21wcmVzc28gY29tZSBCbG9iXHJcbiAgICAgIHJldHVybiBhd2FpdCByZXNwb25zZS5ibG9iKCk7XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3JlIGR1cmFudGUgbGEgY29tcHJlc3Npb25lIHJlbW90YTpcIiwgZXJyb3IpO1xyXG4gICAgICB0aHJvdyBlcnJvcjtcclxuICAgIH1cclxuICB9XHJcbn1cclxuIiwiPCEtLSBTZSByaWNoaWVzdGEgbGEgZ2VzdGlvbmUgc2luZ29sYSBtb3N0cmEgaWwgcHVsc2FudGUgZGkgY2FyaWNhbWVudG8gZGkgdW4gc2luZ29sbyBmaWxlIC0tPlxyXG5AaWYoc2hvd1VwbG9hZFRpdGxlID09IHRydWUgfHwgY2hvb3NlVmlldyA9PSB0cnVlKXtcclxuPGRpdiBjbGFzcz1cImhlYWRlclwiPlxyXG4gIEBpZihzaG93VXBsb2FkVGl0bGUgPT0gdHJ1ZSl7XHJcbiAgPGg0Pnt7IHVwbG9hZFRpdGxlIH19PC9oND5cclxuICB9XHJcbiAgQGlmKGNob29zZVZpZXcgPT0gdHJ1ZSl7XHJcbiAgPG1hdC1idXR0b24tdG9nZ2xlLWdyb3VwIFt2YWx1ZV09XCJ2aWV3TW9kZVwiIChjaGFuZ2UpPVwic2V0Vmlld01vZGUoJGV2ZW50LnZhbHVlKVwiXHJcbiAgICBhcmlhLWxhYmVsPVwiTW9kYWxpdMOgIGRpIHZpc3VhbGl6emF6aW9uZVwiPlxyXG4gICAgPG1hdC1idXR0b24tdG9nZ2xlIHZhbHVlPVwiY2FyZFwiPjxtYXQtaWNvbj5ncmlkX3ZpZXc8L21hdC1pY29uPjwvbWF0LWJ1dHRvbi10b2dnbGU+XHJcbiAgICA8bWF0LWJ1dHRvbi10b2dnbGUgdmFsdWU9XCJ0YWJsZVwiPjxtYXQtaWNvbj52aWV3X2xpc3Q8L21hdC1pY29uPjwvbWF0LWJ1dHRvbi10b2dnbGU+XHJcbiAgPC9tYXQtYnV0dG9uLXRvZ2dsZS1ncm91cD5cclxuICB9XHJcbjwvZGl2PlxyXG59XHJcblxyXG48IS0tIEdlc3Rpb25lIHNpbmdvbG8gLS0+XHJcbkBpZiAobXVsdGlwbGVBdHRhY2htZW50ICE9IHRydWUpIHtcclxuQGlmICghc2luZ2xlQXR0YWNobWVudERyYWdBbmREcm9wKSB7XHJcbkBpZiAoIWFkZGluZ0xpbmtNb2RlKSB7XHJcbjxkaXYgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxyXG4gIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiYWRkQXR0YWNobWVudEJ1dHRvblwiPjwvbmctY29udGFpbmVyPlxyXG48L2Rpdj5cclxufSBAZWxzZSB7XHJcbjxkaXYgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxyXG4gIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiYWRkaW5nTGlua1RlbXBsYXRlXCI+PC9uZy1jb250YWluZXI+XHJcbjwvZGl2PlxyXG59XHJcbn0gQGVsc2Uge1xyXG48aW5wdXQgI2ZpbGVJbnB1dCBpZD1cImZpbGVfYXR0YWNobWVudFwiIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIiB0eXBlPVwiZmlsZVwiIGhpZGRlbiAoY2hhbmdlKT1cIm9uRmlsZUFkZGVkKCRldmVudClcIlxyXG4gIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIiBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG5cclxuQGlmIChhbGxvd2VkVHlwZXMgJiYgYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDEpICYmICghYXR0YWNobWVudHNMaXN0IHx8IGF0dGFjaG1lbnRzTGlzdC5sZW5ndGggPT0gMCB8fFxyXG4oYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiYgIWF0dGFjaG1lbnRzTGlzdFswXSkpKSB7XHJcblxyXG5AaWYgKHNob3dEcm9wQXJlYSA9PSB0cnVlKSB7XHJcbjwhLS0gRlVMTCAtLT5cclxuQGlmIChsYXlvdXQgPT09ICdmdWxsJykge1xyXG5cclxuPGRpdiBjbGFzcz1cImRyb3Bib3hcIiBbY2xhc3MuZHJhZ292ZXJdPVwiZHJhZ092ZXIgJiYgIWlzRGlzYWJsZWRcIiBbY2xhc3MuZGlzYWJsZWQtZHJvcHpvbmVdPVwiaXNEaXNhYmxlZFwiXHJcbiAgKGRyYWdvdmVyKT1cIiFpc0Rpc2FibGVkID8gZHJhZ092ZXIgPSB0cnVlIDogbnVsbDsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIiAoZHJhZ2xlYXZlKT1cImRyYWdPdmVyID0gZmFsc2VcIlxyXG4gIChkcm9wKT1cIiFpc0Rpc2FibGVkID8gKGRyYWdPdmVyID0gZmFsc2UpIDogbnVsbDsgZmlsZURyb3BwZWQoJGV2ZW50KVwiXHJcbiAgKGNsaWNrKT1cIiFpc0Rpc2FibGVkICYmIG9uU2VsZWN0RmlsZSgkZXZlbnQsIGZpbGVJbnB1dClcIiByb2xlPVwiYnV0dG9uXCIgW2F0dHIudGFiaW5kZXhdPVwiaXNEaXNhYmxlZCA/IC0xIDogMFwiXHJcbiAgKGtleWRvd24uZW50ZXIpPVwiIWlzRGlzYWJsZWQgJiYgZmlsZUlucHV0LmNsaWNrKClcIiAoa2V5ZG93bi5zcGFjZSk9XCIhaXNEaXNhYmxlZCAmJiBmaWxlSW5wdXQuY2xpY2soKVwiPlxyXG4gIDxkaXYgY2xhc3M9XCJkcm9wYm94LWljb25cIj7wn5OBPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cImRyb3Bib3gtdGV4dFwiPnt7IGRyb3BIZXJlTGFiZWwgfX08L2Rpdj5cclxuICA8ZGl2IGNsYXNzPVwiZHJvcGJveC1zdWJ0ZXh0XCI+XHJcbiAgICB7eyBzdXBwb3J0ZWRGb3JtYXRzTGFiZWwgfX1cclxuICA8L2Rpdj5cclxuICA8YnV0dG9uIGNsYXNzPVwiYnJvd3NlLWJ0blwiIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyBmaWxlSW5wdXQuY2xpY2soKVwiPlxyXG4gICAge3sgYnJvd3NlRmlsZXNMYWJlbCB9fVxyXG4gIDwvYnV0dG9uPlxyXG4gIDxkaXYgY2xhc3M9XCJzZWNvbmRhcnktYWN0aW9uXCI+XHJcbiAgICBAaWYgKGFsbG93ZWRUeXBlcy5pbmNsdWRlcygyKSB8fCBhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMykpIHtcclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpICYmIGFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKSkge1xyXG4gICAgPGEgY2xhc3M9XCJzZWNvbmRhcnktYWN0aW9uLWxpbmtcIiBbbWF0TWVudVRyaWdnZXJGb3JdPVwiaXNEaXNhYmxlZCA/IG51bGwgOiBsaW5rTWVudVwiXHJcbiAgICAgIFtjbGFzcy5kaXNhYmxlZC1saW5rXT1cImlzRGlzYWJsZWRcIiAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCI+XHJcbiAgICAgIG8gYWdnaXVuZ2kgZGEgd2ViXHJcbiAgICA8L2E+XHJcbiAgICA8bWF0LW1lbnUgI2xpbmtNZW51PVwibWF0TWVudVwiPlxyXG4gICAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cInN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiPlxyXG4gICAgICAgIDxtYXQtaWNvbj5saW5rPC9tYXQtaWNvbj5cclxuICAgICAgICA8c3Bhbj5BZ2dpdW5naSBkYSBsaW5rPC9zcGFuPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCI+XHJcbiAgICAgICAgPG1hdC1pY29uPmNsb3VkX3F1ZXVlPC9tYXQtaWNvbj5cclxuICAgICAgICA8c3Bhbj5DYXJpY2EgZGEgRHJvcGJveDwvc3Bhbj5cclxuICAgICAgPC9idXR0b24+XHJcbiAgICA8L21hdC1tZW51PlxyXG4gICAgfVxyXG5cclxuICAgIEBlbHNlIGlmIChhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMikpIHtcclxuICAgIDxhIFtjbGFzcy5kaXNhYmxlZC1saW5rXT1cImlzRGlzYWJsZWRcIiBjbGFzcz1cInNlY29uZGFyeS1hY3Rpb24tbGlua1wiXHJcbiAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IHN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiPlxyXG4gICAgICBhZ2dpdW5naSB1biBsaW5rXHJcbiAgICA8L2E+XHJcbiAgICB9XHJcblxyXG4gICAgQGVsc2UgaWYgKGFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKSkge1xyXG4gICAgPGEgW2NsYXNzLmRpc2FibGVkLWxpbmtdPVwiaXNEaXNhYmxlZFwiIGNsYXNzPVwic2Vjb25kYXJ5LWFjdGlvbi1saW5rXCJcclxuICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgY2hvb3NlRHJvcGJveEZpbGUoKVwiPlxyXG4gICAgICBjYXJpY2EgZGEgRHJvcGJveFxyXG4gICAgPC9hPlxyXG4gICAgfVxyXG4gICAgfVxyXG4gIDwvZGl2PlxyXG48L2Rpdj5cclxufUBlbHNlIHtcclxuPGRpdiBjbGFzcz1cImNvbXBhY3QtdXBsb2FkZXJcIiBbY2xhc3MuZHJhZ292ZXJdPVwiZHJhZ092ZXIgJiYgIWlzRGlzYWJsZWRcIiBbY2xhc3MuZGlzYWJsZWQtZHJvcHpvbmVdPVwiaXNEaXNhYmxlZFwiXHJcbiAgKGRyYWdvdmVyKT1cIiFpc0Rpc2FibGVkID8gZHJhZ092ZXIgPSB0cnVlIDogbnVsbDsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIiAoZHJhZ2xlYXZlKT1cImRyYWdPdmVyID0gZmFsc2VcIlxyXG4gIChkcm9wKT1cIiFpc0Rpc2FibGVkID8gKGRyYWdPdmVyID0gZmFsc2UpIDogbnVsbDsgZmlsZURyb3BwZWQoJGV2ZW50KVwiPlxyXG4gIDxkaXYgY2xhc3M9XCJjb21wYWN0LWljb25cIj48bWF0LWljb24+Zm9sZGVyX29wZW48L21hdC1pY29uPjwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJjb21wYWN0LXRleHRcIiAoY2xpY2spPVwiIWlzRGlzYWJsZWQgJiYgb25TZWxlY3RGaWxlKCRldmVudCwgZmlsZUlucHV0KVwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImNvbXBhY3QtdGl0bGVcIj5UcmFzY2luYSBpIGZpbGUgbyBzZWxlemlvbmEgZGFsIGNvbXB1dGVyPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29tcGFjdC1zdWJ0aXRsZVwiPnt7IHN1cHBvcnRlZEZvcm1hdHNMYWJlbCB9fTwvZGl2PlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJjb21wYWN0LWFjdGlvbnNcIj5cclxuICAgIDxidXR0b24gbWF0LXN0cm9rZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcclxuICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgZmlsZUlucHV0LmNsaWNrKClcIj5TZm9nbGlhPC9idXR0b24+XHJcbiAgICBAaWYgKGFsbG93ZWRUeXBlcy5pbmNsdWRlcygyKSB8fCBhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMykpIHtcclxuICAgIDxidXR0b24gbWF0LXN0cm9rZWQtYnV0dG9uIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCIgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImNvbXBhY3RMaW5rTWVudVwiXHJcbiAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj5MaW5rPC9idXR0b24+XHJcbiAgICA8bWF0LW1lbnUgI2NvbXBhY3RMaW5rTWVudT1cIm1hdE1lbnVcIj5cclxuICAgICAgQGlmIChhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMikpIHsgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCJcclxuICAgICAgICAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCI+e3sgb3BlbkxpbmtMYWJlbCB9fTwvYnV0dG9uPiB9XHJcbiAgICAgIEBpZiAoYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpKSB7IDxidXR0b24gbWF0LW1lbnUtaXRlbSBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCI+e3tcclxuICAgICAgICB1cGxvYWRXaXRoRHJvcGJveExhYmVsIH19PC9idXR0b24+IH1cclxuICAgIDwvbWF0LW1lbnU+XHJcbiAgICB9XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG59XHJcbn1cclxufVxyXG59XHJcblxyXG48IS0tIEF6aW9uaSBzaW5nb2xvIGVsZW1lbnRvIChjb21lIHByaW1hKSAtLT5cclxuPGRpdiBjbGFzcz1cInRleHQtY2VudGVyXCI+XHJcbiAgQGlmIChhdHRhY2htZW50c0xpc3QgJiYgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA+IDAgJiYgYXR0YWNobWVudHNMaXN0WzBdICYmIHNob3dBY3Rpb25CdXR0b25zID09IHRydWUpIHtcclxuICBAaWYgKCFpc1ByaW1hcnlBY3Rpb25IaWRkZW4oYXR0YWNobWVudHNMaXN0WzBdKSkge1xyXG4gIDxidXR0b24gY2xhc3M9XCJtYi0yIG1lLTIgZXFwLWF0dGFjaG1lbnRzLWRvd25sb2FkLWJ0blwiIChjbGljayk9XCJ2aWV3QXR0YWNobWVudChhdHRhY2htZW50c0xpc3RbMF0pXCIgdHlwZT1cImJ1dHRvblwiXHJcbiAgICBbZGlzYWJsZWRdPVwiaXNQcmltYXJ5QWN0aW9uRGlzYWJsZWQoYXR0YWNobWVudHNMaXN0WzBdKVwiXHJcbiAgICBtYXQtcmFpc2VkLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIj5cclxuICAgIEBpZiAoYXR0YWNobWVudHNMaXN0WzBdLkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUpIHtcclxuICAgIDxtYXQtaWNvbj5kb3dubG9hZDwvbWF0LWljb24+XHJcbiAgICB9IEBlbHNlIHtcclxuICAgIDxtYXQtaWNvbj5vcGVuX2luX25ldzwvbWF0LWljb24+XHJcbiAgICB9XHJcbiAgICB7eyBhdHRhY2htZW50c0xpc3RbMF0uQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSA/IGRvd25sb2FkTGFiZWwgOiBvcGVuTGlua0xhYmVsIH19XHJcbiAgPC9idXR0b24+XHJcbiAgfVxyXG5cclxuICBAaWYgKCFpc1ByaW1hcnlBY3Rpb25IaWRkZW4oYXR0YWNobWVudHNMaXN0WzBdKSAmJiBzaG93UHJldmlldyAmJiAoIWF0dGFjaG1lbnRzTGlzdFswXS5GaWxlQ29udGVudFR5cGUgfHwgKCFhdHRhY2htZW50c0xpc3RbMF0uRmlsZUNvbnRlbnRUeXBlLnN0YXJ0c1dpdGgoJ3ZpZGVvJylcclxuICAmJiAhYXR0YWNobWVudHNMaXN0WzBdLkZpbGVDb250ZW50VHlwZS5zdGFydHNXaXRoKCdhdWRpbycpKSkgJiYgYXR0YWNobWVudHNMaXN0WzBdLklzSW1hZ2UgPT0gdHJ1ZSkge1xyXG4gIDxidXR0b24gY2xhc3M9XCJtYi0yIG1lLTIgZXFwLWF0dGFjaG1lbnRzLXByZXZpZXctYnRuXCIgKGNsaWNrKT1cIm9wZW5QcmV2aWV3RGlhbG9nKGF0dGFjaG1lbnRzTGlzdFswXSlcIiB0eXBlPVwiYnV0dG9uXCJcclxuICAgIFtkaXNhYmxlZF09XCJpc1ByaW1hcnlBY3Rpb25EaXNhYmxlZChhdHRhY2htZW50c0xpc3RbMF0pXCJcclxuICAgIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiPlxyXG4gICAgPG1hdC1pY29uPnZpc2liaWxpdHk8L21hdC1pY29uPiB7eyBwcmV2aWV3TGFiZWwgfX1cclxuICA8L2J1dHRvbj5cclxuICB9XHJcblxyXG4gIDxidXR0b24gW2Rpc2FibGVkXT1cImRpc2FibGVBY3Rpb25cIiBjbGFzcz1cIm1iLTIgZXFwLWF0dGFjaG1lbnRzLWRlbGV0ZS1idG5cIlxyXG4gICAgKGNsaWNrKT1cImRlbGV0ZUF0dGFjaG1lbnQoYXR0YWNobWVudHNMaXN0WzBdKVwiIHR5cGU9XCJidXR0b25cIiBtYXQtcmFpc2VkLWJ1dHRvbiBbZGlzYWJsZWRdPVwiaXNEaXNhYmxlZFwiPlxyXG4gICAgPG1hdC1pY29uPmRlbGV0ZTwvbWF0LWljb24+IHt7IGRlbGV0ZUxhYmVsIH19XHJcbiAgPC9idXR0b24+XHJcbiAgfVxyXG48L2Rpdj5cclxufVxyXG5cclxuPCEtLSBHZXN0aW9uZSBtdWx0aXBsYSAtLT5cclxuQGlmIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSAmJiBzaG93RHJvcEFyZWEgPT0gdHJ1ZSkge1xyXG48aW5wdXQgI2ZpbGVJbnB1dCBpZD1cImZpbGVfYXR0YWNobWVudF9tdWx0aVwiIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRfbXVsdGlcIiB0eXBlPVwiZmlsZVwiIGhpZGRlblxyXG4gIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIiBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG5cclxuQGlmIChsYXlvdXQgPT09ICdmdWxsJykge1xyXG48ZGl2IGNsYXNzPVwiZHJvcGJveFwiIFtjbGFzcy5kcmFnb3Zlcl09XCJkcmFnT3ZlciAmJiAhaXNEaXNhYmxlZFwiIFtjbGFzcy5kaXNhYmxlZC1kcm9wem9uZV09XCJpc0Rpc2FibGVkXCJcclxuICAoZHJhZ292ZXIpPVwiIWlzRGlzYWJsZWQgPyBkcmFnT3ZlciA9IHRydWUgOiBudWxsOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiIChkcmFnbGVhdmUpPVwiZHJhZ092ZXIgPSBmYWxzZVwiXHJcbiAgKGRyb3ApPVwiIWlzRGlzYWJsZWQgPyAoZHJhZ092ZXIgPSBmYWxzZSkgOiBudWxsOyBmaWxlRHJvcHBlZCgkZXZlbnQpXCJcclxuICAoY2xpY2spPVwiIWlzRGlzYWJsZWQgJiYgb25TZWxlY3RGaWxlKCRldmVudCwgZmlsZUlucHV0KVwiIHJvbGU9XCJidXR0b25cIiBbYXR0ci50YWJpbmRleF09XCJpc0Rpc2FibGVkID8gLTEgOiAwXCJcclxuICAoa2V5ZG93bi5lbnRlcik9XCIhaXNEaXNhYmxlZCAmJiBmaWxlSW5wdXQuY2xpY2soKVwiIChrZXlkb3duLnNwYWNlKT1cIiFpc0Rpc2FibGVkICYmIGZpbGVJbnB1dC5jbGljaygpXCI+XHJcbiAgPGRpdiBjbGFzcz1cImRyb3Bib3gtaWNvblwiPvCfk4E8L2Rpdj5cclxuICA8ZGl2IGNsYXNzPVwiZHJvcGJveC10ZXh0XCI+e3sgZHJvcEhlcmVMYWJlbCB9fTwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJkcm9wYm94LXN1YnRleHRcIj5cclxuICAgIHt7IHN1cHBvcnRlZEZvcm1hdHNMYWJlbCB9fVxyXG4gIDwvZGl2PlxyXG4gIDxidXR0b24gY2xhc3M9XCJicm93c2UtYnRuXCIgdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IGZpbGVJbnB1dC5jbGljaygpXCI+XHJcbiAgICB7eyBicm93c2VGaWxlc0xhYmVsIH19XHJcbiAgPC9idXR0b24+XHJcbiAgQGlmIChhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMikpIHtcclxuICA8ZGl2IGNsYXNzPVwic2Vjb25kYXJ5LWFjdGlvbi1saW5rXCI+XHJcbiAgICBvIDxhIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IHN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiPmFnZ2l1bmdpIHVuIGxpbms8L2E+XHJcbiAgPC9kaXY+XHJcbiAgfVxyXG48L2Rpdj5cclxufUBlbHNle1xyXG48ZGl2IGNsYXNzPVwiY29tcGFjdC11cGxvYWRlclwiIFtjbGFzcy5kcmFnb3Zlcl09XCJkcmFnT3ZlciAmJiAhaXNEaXNhYmxlZFwiIFtjbGFzcy5kaXNhYmxlZC1kcm9wem9uZV09XCJpc0Rpc2FibGVkXCJcclxuICAoZHJhZ292ZXIpPVwiIWlzRGlzYWJsZWQgPyBkcmFnT3ZlciA9IHRydWUgOiBudWxsOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVwiIChkcmFnbGVhdmUpPVwiZHJhZ092ZXIgPSBmYWxzZVwiXHJcbiAgKGRyb3ApPVwiIWlzRGlzYWJsZWQgPyAoZHJhZ092ZXIgPSBmYWxzZSkgOiBudWxsOyBmaWxlRHJvcHBlZCgkZXZlbnQpXCI+XHJcbiAgPGRpdiBjbGFzcz1cImNvbXBhY3QtaWNvblwiPjxtYXQtaWNvbj5mb2xkZXJfb3BlbjwvbWF0LWljb24+PC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cImNvbXBhY3QtdGV4dFwiIChjbGljayk9XCIhaXNEaXNhYmxlZCAmJiBvblNlbGVjdEZpbGUoJGV2ZW50LCBmaWxlSW5wdXQpXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwiY29tcGFjdC10aXRsZVwiPlRyYXNjaW5hIGkgZmlsZSBvIHNlbGV6aW9uYSBkYWwgY29tcHV0ZXI8L2Rpdj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb21wYWN0LXN1YnRpdGxlXCI+e3sgc3VwcG9ydGVkRm9ybWF0c0xhYmVsIH19PC9kaXY+XHJcbiAgPC9kaXY+XHJcbiAgPGRpdiBjbGFzcz1cImNvbXBhY3QtYWN0aW9uc1wiPlxyXG4gICAgPGJ1dHRvbiBtYXQtc3Ryb2tlZC1idXR0b24gW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIiBjb2xvcj1cInByaW1hcnlcIlxyXG4gICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpOyBmaWxlSW5wdXQuY2xpY2soKVwiPlNmb2dsaWE8L2J1dHRvbj5cclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpIHx8IGFsbG93ZWRUeXBlcy5pbmNsdWRlcygzKSkge1xyXG4gICAgPGJ1dHRvbiBtYXQtc3Ryb2tlZC1idXR0b24gW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIiBbbWF0TWVudVRyaWdnZXJGb3JdPVwiY29tcGFjdExpbmtNZW51XCJcclxuICAgICAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiPkxpbms8L2J1dHRvbj5cclxuICAgIDxtYXQtbWVudSAjY29tcGFjdExpbmtNZW51PVwibWF0TWVudVwiPlxyXG4gICAgICBAaWYgKGFsbG93ZWRUeXBlcy5pbmNsdWRlcygyKSkgeyA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIlxyXG4gICAgICAgIChjbGljayk9XCJzd2l0Y2hUb0FkZGluZ0xpbmtNb2RlKClcIj57eyBvcGVuTGlua0xhYmVsIH19PC9idXR0b24+IH1cclxuICAgICAgQGlmIChhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMykpIHsgPGJ1dHRvbiBtYXQtbWVudS1pdGVtIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCIgKGNsaWNrKT1cImNob29zZURyb3Bib3hGaWxlKClcIj57e1xyXG4gICAgICAgIHVwbG9hZFdpdGhEcm9wYm94TGFiZWwgfX08L2J1dHRvbj4gfVxyXG4gICAgPC9tYXQtbWVudT5cclxuICAgIH1cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbn1cclxufVxyXG5cclxuQGlmIChhdHRhY2htZW50c0xpc3Q/Lmxlbmd0aCA+IDAgJiYgc2hvd1N1bW1hcnkpIHtcclxuPGRpdiBjbGFzcz1cInVwbG9hZC1zdGF0c1wiPlxyXG5cclxuICA8ZGl2IGNsYXNzPVwic3RhdHMtaW5mb1wiPlxyXG4gICAgPGRpdiBjbGFzcz1cInN0YXQtaXRlbVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwic3RhdC12YWx1ZVwiPnt7IGF0dGFjaG1lbnRzTGlzdD8ubGVuZ3RoIH19PC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJzdGF0LWxhYmVsXCI+e3sgZmlsZXNMYWJlbCB9fTwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbiAgICA8ZGl2IGNsYXNzPVwic3RhdC1pdGVtXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJzdGF0LXZhbHVlXCI+e3sgdG90YWxTaXplRm9ybWF0dGVkIH19PC9kaXY+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJzdGF0LWxhYmVsXCI+e3sgdG90YWxTaXplTGFiZWwgfX08L2Rpdj5cclxuICAgIDwvZGl2PlxyXG4gIDwvZGl2PlxyXG5cclxuICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtYmFyXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwicHJvZ3Jlc3MtZmlsbFwiIFtzdHlsZS53aWR0aC4lXT1cInByb2dyZXNzUGVyY2VudFwiPjwvZGl2PlxyXG4gIDwvZGl2PlxyXG5cclxuPC9kaXY+XHJcbn0gQGVsc2UgaWYoYXR0YWNobWVudHNMaXN0Py5sZW5ndGggPT0gMCl7XHJcbjxkaXYgY2xhc3M9XCJlbXB0eS1zdGF0ZVwiPnt7IGVtcHR5U3RhdGVMYWJlbCB9fTwvZGl2PlxyXG59XHJcblxyXG48IS0tIEdyaWdsaWEgYW50ZXByaW1lIGNhcmQgKHZhbGUgcGVyIHNpbmdvbG8gZSBtdWx0aXBsbykgLS0+XHJcbkBpZiAodmlld01vZGUgPT09ICdjYXJkJykge1xyXG5cclxuPGRpdiBjbGFzcz1cImZpbGUtcHJldmlld3NcIiBbbmdTdHlsZV09XCJnZXRQcmV2aWV3c0NvbnRhaW5lclN0eWxlKClcIj5cclxuICBAZm9yIChhdHQgb2YgYXR0YWNobWVudHNMaXN0OyB0cmFjayBhdHQuSUQpIHtcclxuICA8ZGl2IFtuZ0NsYXNzXT1cImdldENhcmRDbGFzcyhhdHQpXCI+XHJcbiAgICA8ZGl2IGNsYXNzPVwicHJldmlldy1pbWctY29udGFpbmVyXCIgKGNsaWNrKT1cIiFhdHQuaXNVcGxvYWRpbmcgJiYgIWlzUHJpbWFyeUFjdGlvbkhpZGRlbihhdHQpICYmICFpc1ByaW1hcnlBY3Rpb25EaXNhYmxlZChhdHQpICYmIGhhbmRsZVByaW1hcnlBY3Rpb24oYXR0KVwiPlxyXG5cclxuICAgICAgQGlmIChhdHQuSXNJbWFnZSB8fCBhdHQuRmlsZVRodW1ibmFpbEJhc2U2NCkge1xyXG4gICAgICA8aW1nIGNsYXNzPVwicHJldmlldy1pbWdcIiBbc3JjXT1cIidkYXRhOmltYWdlL2pwZWc7YmFzZTY0LCcgKyAoYXR0LkZpbGVUaHVtYm5haWxCYXNlNjQgfHwgYXR0LkZpbGVEYXRhQmFzZTY0KVwiXHJcbiAgICAgICAgW2FsdF09XCJhdHQuRmlsZU5hbWVcIiAvPlxyXG4gICAgICB9IEBlbHNlIHtcclxuICAgICAgPGRpdiBjbGFzcz1cImZpbGUtaWNvblwiPjxpIFtuZ0NsYXNzXT1cImdldEF0dGFjaG1lbnRJY29uKGF0dClcIj48L2k+PC9kaXY+XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIEBpZiAoIWlzUHJpbWFyeUFjdGlvbkhpZGRlbihhdHQpKSB7XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJwcmV2aWV3LWFjdGlvbi1vdmVybGF5XCI+XHJcbiAgICAgICAgQGlmIChhdHQuRmlsZUNvbnRlbnRUeXBlPy5zdGFydHNXaXRoKCd2aWRlby8nKSkge1xyXG4gICAgICAgIDxtYXQtaWNvbj5wbGF5X2Fycm93PC9tYXQtaWNvbj5cclxuICAgICAgICB9XHJcbiAgICAgICAgQGVsc2UgaWYgKGF0dC5Jc0ltYWdlICYmIGNhbkJlUHJldmlld2VkKGF0dCkpIHtcclxuICAgICAgICA8bWF0LWljb24+dmlzaWJpbGl0eTwvbWF0LWljb24+XHJcbiAgICAgICAgfVxyXG4gICAgICAgIEBlbHNlIGlmIChhdHQuRmlsZUNvbnRlbnRUeXBlID09PSAnYXBwbGljYXRpb24vcGRmJyAmJiBjYW5CZVByZXZpZXdlZChhdHQpKSB7XHJcbiAgICAgICAgPG1hdC1pY29uPm9wZW5faW5fbmV3PC9tYXQtaWNvbj5cclxuICAgICAgICB9XHJcbiAgICAgICAgQGVsc2UgaWYgKGF0dC5BdHRhY2htZW50VHlwZSA9PT0gQXR0YWNobWVudFR5cGUuRklMRSkge1xyXG4gICAgICAgIDxtYXQtaWNvbj5kb3dubG9hZDwvbWF0LWljb24+XHJcbiAgICAgICAgfVxyXG4gICAgICAgIEBlbHNlIHtcclxuICAgICAgICA8bWF0LWljb24+b3Blbl9pbl9uZXc8L21hdC1pY29uPlxyXG4gICAgICAgIH1cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIH1cclxuXHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwiZmlsZS1pbmZvXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJmaWxlLW5hbWVcIiBbdGl0bGVdPVwiYXR0LkZpbGVOYW1lXCI+e3sgYXR0LkZpbGVOYW1lIH19PC9kaXY+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICBAaWYoIWlzRGVsZXRlSGlkZGVuKGF0dCkpe1xyXG4gICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gY2xhc3M9XCJyZW1vdmUtYnRuXCIgKGNsaWNrKT1cImRlbGV0ZUF0dGFjaG1lbnQoYXR0KVwiXHJcbiAgICAgIFtkaXNhYmxlZF09XCJhdHQuaXNVcGxvYWRpbmcgfHwgaXNEZWxldGVEaXNhYmxlZChhdHQpXCI+XHJcbiAgICAgIDxtYXQtaWNvbj5kZWxldGU8L21hdC1pY29uPlxyXG4gICAgPC9idXR0b24+XHJcbiAgICB9XHJcblxyXG4gICAgQGlmIChhdHQuaXNVcGxvYWRpbmcpIHtcclxuICAgIDxkaXYgY2xhc3M9XCJ1cGxvYWQtc3Bpbm5lclwiPjwvZGl2PlxyXG4gICAgfVxyXG4gIDwvZGl2PlxyXG4gIH1cclxuPC9kaXY+XHJcblxyXG59IEBlbHNlIGlmKHZpZXdNb2RlID09PSAndGFibGUnICYmIGF0dGFjaG1lbnRzTGlzdD8ubGVuZ3RoID4gMCkge1xyXG5cclxuXHJcbjxkaXYgY2xhc3M9XCJ0YWJsZS12aWV3LWNvbnRhaW5lclwiPlxyXG5cclxuICA8ZGl2IGNsYXNzPVwidGFibGUtaGVhZGVyXCI+XHJcbiAgICBAZm9yIChjb2wgb2YgX3RhYmxlQ29sdW1uczsgdHJhY2sgY29sLmtleSkge1xyXG4gICAgPGRpdiBjbGFzcz1cInRhYmxlLWNlbGxcIiBbc3R5bGUuZmxleF09XCJjb2wuc3R5bGVzPy5mbGV4XCIgW25nQ2xhc3NdPVwiY29sLmNsYXNzXCI+XHJcbiAgICAgIHt7IGNvbC5kaXNwbGF5IH19XHJcbiAgICA8L2Rpdj5cclxuICAgIH1cclxuICA8L2Rpdj5cclxuXHJcbiAgQGZvciAoYXR0IG9mIGF0dGFjaG1lbnRzTGlzdDsgdHJhY2sgYXR0LklEKSB7XHJcbiAgPGRpdiBjbGFzcz1cInRhYmxlLXJvd1wiPlxyXG5cclxuICAgIEBmb3IgKGNvbCBvZiBfdGFibGVDb2x1bW5zOyB0cmFjayBjb2wua2V5KSB7XHJcbiAgICA8ZGl2IGNsYXNzPVwidGFibGUtY2VsbFwiIFtzdHlsZS5mbGV4XT1cImNvbC5zdHlsZXM/LmZsZXhcIiBbbmdDbGFzc109XCJjb2wuY2xhc3NcIj5cclxuXHJcbiAgICAgIEBzd2l0Y2ggKGNvbC50eXBlKSB7XHJcblxyXG4gICAgICBAY2FzZSAoJ3RlbXBsYXRlJykge1xyXG4gICAgICA8ZGl2IGNsYXNzPVwidGVtcGxhdGUtd3JhcHBlclwiPlxyXG4gICAgICAgIDxuZy1jb250YWluZXIgW25nVGVtcGxhdGVPdXRsZXRdPVwiY29sLmV4dGVybmFsVGVtcGxhdGVcIlxyXG4gICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiBhdHQgfVwiPjwvbmctY29udGFpbmVyPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgfVxyXG4gICAgICBAY2FzZSAoJ2RhdGUnKSB7XHJcbiAgICAgIDxzcGFuIGNsYXNzPVwibWV0YWRhdGEtdmFsdWVcIj57eyBhdHRbY29sLmtleV0gfCBkYXRlOidkZC9NTS95eXl5JyB9fTwvc3Bhbj5cclxuICAgICAgfVxyXG4gICAgICBAZGVmYXVsdCB7XHJcbiAgICAgIDxzcGFuIGNsYXNzPVwibWV0YWRhdGEtdmFsdWVcIj57eyBhdHRbY29sLmtleV0gfX08L3NwYW4+XHJcbiAgICAgIH1cclxuICAgICAgfVxyXG4gICAgPC9kaXY+XHJcbiAgICB9XHJcbiAgPC9kaXY+XHJcbiAgfVxyXG48L2Rpdj5cclxufVxyXG5cclxuPCEtLSBOb3RpZmljYSB0b2FzdCAtLT5cclxuPGRpdiBjbGFzcz1cInVwbG9hZC1ub3RpZmljYXRpb25cIiBbY2xhc3Muc2hvd109XCJ0b2FzdD8udmlzaWJsZVwiIFtjbGFzcy5zdWNjZXNzXT1cInRvYXN0Py50eXBlID09PSAnc3VjY2VzcydcIlxyXG4gIFtjbGFzcy5lcnJvcl09XCJ0b2FzdD8udHlwZSA9PT0gJ2Vycm9yJ1wiPlxyXG4gIDxzcGFuPnt7IHRvYXN0Py50ZXh0IH19PC9zcGFuPlxyXG4gIDxkaXYgY2xhc3M9XCJub3RpZmljYXRpb24tcHJvZ3Jlc3NcIj48L2Rpdj5cclxuPC9kaXY+XHJcblxyXG48bmctdGVtcGxhdGUgI2RlZmF1bHRGaWxlVGVtcGxhdGUgbGV0LWF0dD5cclxuICA8aSBjbGFzcz1cImZpbGUtaWNvbi1zbWFsbFwiIFtuZ0NsYXNzXT1cImdldEF0dGFjaG1lbnRJY29uKGF0dClcIj48L2k+XHJcbiAgPGRpdiBjbGFzcz1cImZpbGUtaW5mby10ZXh0XCI+XHJcbiAgICA8c3BhbiBjbGFzcz1cImZpbGUtbmFtZS10YWJsZVwiPnt7IGF0dC5GaWxlTmFtZSB9fTwvc3Bhbj5cclxuICAgIDxzcGFuIGNsYXNzPVwiZmlsZS10eXBlLXRhYmxlXCI+e3sgYXR0LkZpbGVFeHRlbnNpb24gfHwgJ0xpbmsnIH19PC9zcGFuPlxyXG4gIDwvZGl2PlxyXG48L25nLXRlbXBsYXRlPlxyXG5cclxuPG5nLXRlbXBsYXRlICNkZWZhdWx0QWN0aW9uc1RlbXBsYXRlIGxldC1hdHQ+XHJcbiAgQGlmICghaXNQcmltYXJ5QWN0aW9uSGlkZGVuKGF0dCkpIHtcclxuICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiAoY2xpY2spPVwiaGFuZGxlUHJpbWFyeUFjdGlvbihhdHQpXCIgW2Rpc2FibGVkXT1cImlzUHJpbWFyeUFjdGlvbkRpc2FibGVkKGF0dClcIlxyXG4gICAgW21hdFRvb2x0aXBdPVwiYXR0LkZpbGVDb250ZW50VHlwZT8uc3RhcnRzV2l0aCgndmlkZW8vJykgPyAnUmlwcm9kdWNpIHZpZGVvJyA6ICdWaXN1YWxpenphL1NjYXJpY2EnXCI+XHJcblxyXG4gICAgPG1hdC1pY29uPlxyXG4gICAgICBAaWYgKGF0dC5GaWxlQ29udGVudFR5cGU/LnN0YXJ0c1dpdGgoJ3ZpZGVvLycpKSB7XHJcbiAgICAgIHBsYXlfYXJyb3dcclxuICAgICAgfSBAZWxzZSB7XHJcbiAgICAgIHt7IGF0dC5BdHRhY2htZW50VHlwZSA9PT0gQXR0YWNobWVudFR5cGUuRklMRSA/ICdkb3dubG9hZCcgOiAnb3Blbl9pbl9uZXcnIH19XHJcbiAgICAgIH1cclxuICAgIDwvbWF0LWljb24+XHJcbiAgPC9idXR0b24+XHJcbiAgfVxyXG5cclxuICBAaWYgKCFoaWRkZW5BY3Rpb25zLmluY2x1ZGVzKCdhY3Rpb25zTWVudScpKSB7XHJcbiAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gW21hdE1lbnVUcmlnZ2VyRm9yXT1cImFjdGlvbnNNZW51XCIgbWF0VG9vbHRpcD1cIkFsdHJlIG9wemlvbmlcIj5cclxuICAgIDxtYXQtaWNvbj5tb3JlX3ZlcnQ8L21hdC1pY29uPlxyXG4gIDwvYnV0dG9uPlxyXG4gIH1cclxuXHJcbiAgPG1hdC1tZW51ICNhY3Rpb25zTWVudT1cIm1hdE1lbnVcIj5cclxuICAgIEBmb3IgKGFjdGlvbiBvZiBfc29ydGVkTWVudUFjdGlvbnM7IHRyYWNrIGFjdGlvbi5uYW1lKSB7XHJcbiAgICBAaWYgKCFpc0FjdGlvbkhpZGRlbihhY3Rpb24sIGF0dCkpIHtcclxuICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2spPVwiYWN0aW9uLmZuKGF0dClcIiBbZGlzYWJsZWRdPVwiaXNBY3Rpb25EaXNhYmxlZChhY3Rpb24sIGF0dClcIj5cclxuICAgICAgPG1hdC1pY29uIFtjb2xvcl09XCJhY3Rpb24uaWNvbiA9PT0gJ2RlbGV0ZScgPyAnd2FybicgOiB1bmRlZmluZWRcIj5cclxuICAgICAgICB7eyBhY3Rpb24uaWNvbiB9fVxyXG4gICAgICA8L21hdC1pY29uPlxyXG4gICAgICA8c3Bhbj57eyBhY3Rpb24ubmFtZSB9fTwvc3Bhbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgfVxyXG4gICAgfVxyXG4gIDwvbWF0LW1lbnU+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG5cclxuPG5nLXRlbXBsYXRlICNkaWFsb2dDcm9wSW1hZ2U+XHJcbiAgPGRpdiBzdHlsZT1cIm92ZXJmbG93LXg6IGhpZGRlbjsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsgaGVpZ2h0OiAxMDAlOyBtaW4taGVpZ2h0OiAwOyBmbGV4OiAxIDEgYXV0bztcIlxyXG4gICAgW25nQ2xhc3NdPVwiY3JvcERpYWxvZ0NsYXNzXCI+XHJcbiAgICA8IS0tIEBpZiAoc2hvd0Nyb3BJbWFnZSA9PSB0cnVlKSB7IC0tPlxyXG4gICAgPG5nLWNvbnRhaW5lciBbbmdUZW1wbGF0ZU91dGxldF09XCJjcm9wcGllVGVtcGxhdGVcIiBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyBmb3JtOiBuZXdBdHRhY2htZW50Rm9ybSB9XCI+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgIDwhLS0gfSAtLT5cclxuICA8L2Rpdj5cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcblxyXG48bmctdGVtcGxhdGUgI2lubGluZVByZXZpZXdUZW1wbGF0ZSBsZXQtcm93PVwicm93XCI+XHJcbiAgQGlmIChyb3cuQXR0YWNobWVudFR5cGUgIT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiByb3cuSXNJbWFnZSkge1xyXG4gIDxkaXYgY2xhc3M9XCJpbmxpbmUtcHJldmlldy1jb250YWluZXJcIiAoY2xpY2spPVwib3BlblByZXZpZXdEaWFsb2cocm93KVwiPlxyXG4gICAgPGltZyBbc3JjXT1cIidkYXRhOmltYWdlL3BuZztiYXNlNjQsJyArIChyb3cuRmlsZVRodW1ibmFpbEJhc2U2NCA/IHJvdy5GaWxlVGh1bWJuYWlsQmFzZTY0IDogcm93LkZpbGVEYXRhQmFzZTY0KVwiIC8+XHJcbiAgPC9kaXY+XHJcbiAgfSBAZWxzZSBpZiAocm93LkF0dGFjaG1lbnRUeXBlICE9IEF0dGFjaG1lbnRUeXBlLkxJTksgJiYgIXJvdy5Jc0ltYWdlKSB7XHJcbiAgPGRpdiBjbGFzcz1cImlubGluZS1wcmV2aWV3LWNvbnRhaW5lclwiIChjbGljayk9XCJvcGVuUHJldmlld0RpYWxvZyhyb3cpXCI+XHJcbiAgICA8aSBbbmdDbGFzc109XCJnZXRBdHRhY2htZW50SWNvbihyb3cpXCI+PC9pPlxyXG4gIDwvZGl2PlxyXG4gIH1cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcblxyXG48bmctdGVtcGxhdGUgI2RpYWxvZ1ByZXZpZXc+XHJcbiAgPGRpdiBjbGFzcz1cIm1vZGVybi1kaWFsb2ctY29udGFpbmVyXCI+IEBpZiAoc2VsZWN0ZWRBdHRhY2htZW50KSB7XHJcbiAgICA8ZGl2IG1hdC1kaWFsb2ctdGl0bGUgY2xhc3M9XCJwcmV2aWV3LWhlYWRlclwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLWluZm9cIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGUtZ3JvdXBcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWFpbi10XCI+e3sgcHJldmlld0xhYmVsIH19PC9zcGFuPlxyXG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJmaWxlLXRcIj57eyBzZWxlY3RlZEF0dGFjaG1lbnQuRmlsZU5hbWUgfX08L3NwYW4+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiBtYXQtZGlhbG9nLWNsb3NlIGNsYXNzPVwiY2xvc2UtYnRuXCI+PG1hdC1pY29uPmNsb3NlPC9tYXQtaWNvbj48L2J1dHRvbj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQgY2xhc3M9XCJwcmV2aWV3LWNvbnRlbnQtYXJlYVwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwibWVkaWEtdmlld2VyLXdyYXBwZXJcIj5cclxuICAgICAgICBAaWYgKHNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlKSB7XHJcbiAgICAgICAgPGltZyBjbGFzcz1cIm1haW4tcHJldmlldy1tZWRpYVwiXHJcbiAgICAgICAgICBbc3JjXT1cIidkYXRhOmltYWdlL3BuZztiYXNlNjQsJyArIChzZWxlY3RlZEF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgfHwgc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVUaHVtYm5haWxCYXNlNjQpXCJcclxuICAgICAgICAgIFthbHRdPVwic2VsZWN0ZWRBdHRhY2htZW50LkZpbGVOYW1lXCIgLz5cclxuICAgICAgICB9XHJcbiAgICAgICAgQGVsc2UgaWYgKHNlbGVjdGVkQXR0YWNobWVudC5GaWxlQ29udGVudFR5cGU/LnN0YXJ0c1dpdGgoJ3ZpZGVvLycpKSB7XHJcbiAgICAgICAgPHZpZGVvIGNvbnRyb2xzIGF1dG9wbGF5IHBsYXlzaW5saW5lIGNsYXNzPVwibWFpbi1wcmV2aWV3LW1lZGlhIHZpZGVvLXBsYXllclwiPlxyXG4gICAgICAgICAgPHNvdXJjZSBbc3JjXT1cInNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsXCIgW3R5cGVdPVwic2VsZWN0ZWRBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZVwiPlxyXG4gICAgICAgICAgSWwgdHVvIGJyb3dzZXIgbm9uIHN1cHBvcnRhIGlsIHZpZGVvLlxyXG4gICAgICAgIDwvdmlkZW8+XHJcbiAgICAgICAgfVxyXG4gICAgICAgIEBlbHNlIHtcclxuICAgICAgICA8ZGl2IGNsYXNzPVwiaWZyYW1lLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgPGlmcmFtZSBjbGFzcz1cInByZXZpZXctaWZyYW1lLW1vZGVyblwiIFtzcmNdPVwic2VsZWN0ZWRBdHRhY2htZW50LlRydXN0ZWRVcmxcIlxyXG4gICAgICAgICAgICBbdGl0bGVdPVwic2VsZWN0ZWRBdHRhY2htZW50LkZpbGVOYW1lXCI+PC9pZnJhbWU+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgfVxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvbWF0LWRpYWxvZy1jb250ZW50PlxyXG5cclxuICAgIDxtYXQtZGlhbG9nLWFjdGlvbnMgYWxpZ249XCJlbmRcIiBjbGFzcz1cInByZXZpZXctYWN0aW9uc1wiPlxyXG4gICAgICA8YnV0dG9uIG1hdC1idXR0b24gbWF0LWRpYWxvZy1jbG9zZSBjbGFzcz1cImJ0bi1jbG9zZVwiPkNoaXVkaTwvYnV0dG9uPlxyXG4gICAgICBAaWYgKHNlbGVjdGVkQXR0YWNobWVudC5BdHRhY2htZW50VHlwZSAhPT0gQXR0YWNobWVudFR5cGUuTElOSykge1xyXG4gICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIChjbGljayk9XCJ2aWV3QXR0YWNobWVudChzZWxlY3RlZEF0dGFjaG1lbnQpXCIgY2xhc3M9XCJidG4tZG93bmxvYWRcIj5cclxuICAgICAgICA8bWF0LWljb24+ZG93bmxvYWQ8L21hdC1pY29uPiA8c3Bhbj57eyBkb3dubG9hZExhYmVsIH19PC9zcGFuPlxyXG4gICAgICA8L2J1dHRvbj5cclxuICAgICAgfVxyXG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XHJcbiAgICB9XHJcbiAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG5cclxuPCEtLSBURU1QTEFURSBQRVIgSUwgUFVMU0FOVEUgREkgQUdHSVVOVEEgTlVPVk8gQUxMRUdBVE8gLS0+XHJcbjxuZy10ZW1wbGF0ZSAjYWRkQXR0YWNobWVudEJ1dHRvbj5cclxuICA8aW5wdXQgI2ZpbGVJbnB1dCBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIiBpZD1cImZpbGVfYXR0YWNobWVudFwiIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIiB0eXBlPVwiZmlsZVwiXHJcbiAgICAoY2hhbmdlKT1cIm9uRmlsZUFkZGVkKCRldmVudClcIiBbYWNjZXB0XT1cImFjY2VwdGVkRmlsZVR5cGVzXCIgW211bHRpcGxlXT1cImxvYWRNdWx0aXBsZUZpbGVzXCIgLz5cclxuXHJcbiAgQGlmIChhbGxvd2VkVHlwZXMgJiYgYWxsb3dlZFR5cGVzLmxlbmd0aCA9PSAxICYmIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSB8fCAhYXR0YWNobWVudHNMaXN0IHx8XHJcbiAgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8IChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSkpIHtcclxuICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1iLTQgbWUtNSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIHR5cGU9XCJidXR0b25cIlxyXG4gICAgKGNsaWNrKT1cImFkZEZpbGUoYWxsb3dlZFR5cGVzWzBdLCBmaWxlSW5wdXQpXCIgW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIj5cclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzWzBdID09IDEpIHsgPG1hdC1pY29uPmNsb3VkX3VwbG9hZDwvbWF0LWljb24+IH1cclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzWzBdID09IDIpIHsgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT4gfVxyXG4gICAgQGlmIChhbGxvd2VkVHlwZXNbMF0gPT0gMykgeyA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPiB9XHJcbiAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+XHJcbiAgICAgIHt7IGFsbG93ZWRUeXBlc1swXSA9PSAxID8gKGFkZEJ1dHRvbkxhYmVsICsgXCIgZmlsZVwiKSA6IGFsbG93ZWRUeXBlc1swXSA9PSAyID8gKGFkZEJ1dHRvbkxhYmVsICsgXCIgbGlua1wiKSA6XHJcbiAgICAgIHVwbG9hZFdpdGhEcm9wYm94TGFiZWwgfX1cclxuICAgIDwvc3Bhbj5cclxuICA8L2J1dHRvbj5cclxuICB9XHJcblxyXG4gIEBpZiAoIXNlcGFyYXRlZFVwbG9hZEJ1dHRvbnMgJiYgYWxsb3dlZFR5cGVzICYmIGFsbG93ZWRUeXBlcy5sZW5ndGggPiAxICYmIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSB8fFxyXG4gICFhdHRhY2htZW50c0xpc3QgfHwgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8IChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSkpIHtcclxuICA8YnV0dG9uIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IG1iLTQgbWUtNSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIHR5cGU9XCJidXR0b25cIlxyXG4gICAgW21hdE1lbnVUcmlnZ2VyRm9yXT1cImF0dGFjaG1lbnRUeXBlTWVudVwiIFtkaXNhYmxlZF09XCJpc0Rpc2FibGVkXCI+XHJcbiAgICBAaWYgKG11bHRpcGxlQXR0YWNobWVudCAhPSB0cnVlKSB7IDxtYXQtaWNvbj5jbG91ZF91cGxvYWQ8L21hdC1pY29uPiB9IEBlbHNlIHsgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+IH1cclxuICAgIDxzcGFuIHN0eWxlPVwibWFyZ2luLWxlZnQ6IDBweFwiPnt7IGFkZEJ1dHRvbkxhYmVsIH19PC9zcGFuPlxyXG4gIDwvYnV0dG9uPlxyXG5cclxuICA8bWF0LW1lbnUgI2F0dGFjaG1lbnRUeXBlTWVudT1cIm1hdE1lbnVcIj5cclxuICAgIDxpbnB1dCAjaW1hZ2VJbnB1dCBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIiBpZD1cImZpbGVfYXR0YWNobWVudFwiIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIiB0eXBlPVwiZmlsZVwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIiBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gICAgQGlmIChhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMSkpIHtcclxuICAgIDxidXR0b24gbWF0LW1lbnUtaXRlbSAoY2xpY2spPVwiaW1hZ2VJbnB1dC5jbGljaygpXCIgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtZmlsZS1idG5cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtZmlsZVwiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkZpbGU8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIH1cclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDIpKSB7XHJcbiAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gW2Rpc2FibGVkXT1cImlzRGlzYWJsZWRcIiAoY2xpY2spPVwic3dpdGNoVG9BZGRpbmdMaW5rTW9kZSgpXCIgY2xhc3M9XCJlcXAtYXR0YWNobWVudHMtbGluay1idG5cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkxpbms8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIH1cclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpKSB7XHJcbiAgICA8YnV0dG9uIG1hdC1tZW51LWl0ZW0gKGNsaWNrKT1cImNob29zZURyb3Bib3hGaWxlKClcIiBjbGFzcz1cImVxcC1hdHRhY2htZW50cy1saW5rLWJ0blwiPlxyXG4gICAgICA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPlxyXG4gICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RHJvcGJveDwvc3Bhbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgfVxyXG4gIDwvbWF0LW1lbnU+XHJcbiAgfVxyXG5cclxuICBAaWYgKHNlcGFyYXRlZFVwbG9hZEJ1dHRvbnMgJiYgYWxsb3dlZFR5cGVzICYmIGFsbG93ZWRUeXBlcy5sZW5ndGggPiAxICYmIChtdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSB8fFxyXG4gICFhdHRhY2htZW50c0xpc3QgfHwgYXR0YWNobWVudHNMaXN0Lmxlbmd0aCA9PSAwIHx8IChhdHRhY2htZW50c0xpc3QubGVuZ3RoID4gMCAmJiAhYXR0YWNobWVudHNMaXN0WzBdKSkpIHtcclxuICA8ZGl2IGNsYXNzPVwiYnRuLWdyb3VwXCI+XHJcbiAgICBAaWYgKGFsbG93ZWRUeXBlcy5pbmNsdWRlcygxKSkge1xyXG4gICAgPGJ1dHRvbiAoY2xpY2spPVwiaW1hZ2VJbnB1dC5jbGljaygpXCIgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgIGNvbG9yPVwic2Vjb25kYXJ5XCIgdHlwZT1cImJ1dHRvblwiPlxyXG4gICAgICA8aSBjbGFzcz1cImZhLXNvbGlkIGZhLWNsb3VkLXVwbG9hZFwiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkZpbGU8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIH1cclxuICAgIDxpbnB1dCAjaW1hZ2VJbnB1dCBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIiBpZD1cImZpbGVfYXR0YWNobWVudFwiIG5hbWU9XCJmaWxlX2F0dGFjaG1lbnRcIiB0eXBlPVwiZmlsZVwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25GaWxlQWRkZWQoJGV2ZW50KVwiIFthY2NlcHRdPVwiYWNjZXB0ZWRGaWxlVHlwZXNcIiBbbXVsdGlwbGVdPVwibG9hZE11bHRpcGxlRmlsZXNcIiAvPlxyXG4gICAgQGlmIChhbGxvd2VkVHlwZXMuaW5jbHVkZXMoMikpIHtcclxuICAgIDxidXR0b24gKGNsaWNrKT1cInN3aXRjaFRvQWRkaW5nTGlua01vZGUoKVwiIGNsYXNzPVwiYnRuIGJ0bi1zZWNvbmRhcnkgZXFwLWF0dGFjaG1lbnRzLWFkZC1idG5cIiBtYXQtcmFpc2VkLWJ1dHRvblxyXG4gICAgICBjb2xvcj1cInNlY29uZGFyeVwiIHR5cGU9XCJidXR0b25cIj5cclxuICAgICAgPGkgY2xhc3M9XCJmYXMgZmEtbGlua1wiPjwvaT5cclxuICAgICAgPHNwYW4gc3R5bGU9XCJtYXJnaW4tbGVmdDogMTBweFwiPkxpbms8L3NwYW4+XHJcbiAgICA8L2J1dHRvbj5cclxuICAgIH1cclxuICAgIEBpZiAoYWxsb3dlZFR5cGVzLmluY2x1ZGVzKDMpKSB7XHJcbiAgICA8YnV0dG9uIChjbGljayk9XCJjaG9vc2VEcm9wYm94RmlsZSgpXCIgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBlcXAtYXR0YWNobWVudHMtYWRkLWJ0blwiIG1hdC1yYWlzZWQtYnV0dG9uXHJcbiAgICAgIGNvbG9yPVwic2Vjb25kYXJ5XCIgdHlwZT1cImJ1dHRvblwiPlxyXG4gICAgICA8aSBjbGFzcz1cImZhLWJyYW5kcyBmYS1kcm9wYm94XCI+PC9pPlxyXG4gICAgICA8c3BhbiBzdHlsZT1cIm1hcmdpbi1sZWZ0OiAxMHB4XCI+RHJvcGJveDwvc3Bhbj5cclxuICAgIDwvYnV0dG9uPlxyXG4gICAgfVxyXG4gIDwvZGl2PlxyXG4gIH1cclxuPC9uZy10ZW1wbGF0ZT5cclxuXHJcblxyXG48bmctdGVtcGxhdGUgI2Nyb3BwaWVUZW1wbGF0ZT5cclxuICA8ZGl2IGNsYXNzPVwibW9kZXJuLWRpYWxvZy1jb250YWluZXJcIj5cclxuICAgIDxkaXYgbWF0LWRpYWxvZy10aXRsZSBjbGFzcz1cInByZXZpZXctaGVhZGVyXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJoZWFkZXItaW5mb1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJ0aXRsZS1ncm91cFwiPlxyXG4gICAgICAgICAgPHNwYW4gY2xhc3M9XCJtYWluLXRcIj57eyBjcm9wTGFiZWwgfX08L3NwYW4+XHJcbiAgICAgICAgICA8c3BhbiBjbGFzcz1cImZpbGUtdFwiPlJlZ29sYSBsZSBkaW1lbnNpb25pIGUgbCdvcmllbnRhbWVudG88L3NwYW4+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKGNsaWNrKT1cImFib3J0RmlsZSgpXCIgY2xhc3M9XCJjbG9zZS1idG5cIj48bWF0LWljb24+Y2xvc2U8L21hdC1pY29uPjwvYnV0dG9uPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPG1hdC1kaWFsb2ctY29udGVudCBjbGFzcz1cInByZXZpZXctY29udGVudC1hcmVhXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJjcm9wLXRvb2xiYXJcIj5cclxuICAgICAgICBAaWYgKGNyb3BPcHRpb25zLmluY2x1ZGVzKDEpKSB7XHJcbiAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gW21hdFRvb2x0aXBdPVwicm90YXRlTGVmdExhYmVsXCJcclxuICAgICAgICAgIChjbGljayk9XCJyb3RhdGVMZWZ0KClcIj48bWF0LWljb24+cm90YXRlX2xlZnQ8L21hdC1pY29uPjwvYnV0dG9uPlxyXG4gICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIFttYXRUb29sdGlwXT1cInJvdGF0ZVJpZ2h0TGFiZWxcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cInJvdGF0ZVJpZ2h0KClcIj48bWF0LWljb24+cm90YXRlX3JpZ2h0PC9tYXQtaWNvbj48L2J1dHRvbj5cclxuICAgICAgICB9XHJcbiAgICAgICAgQGlmIChjcm9wT3B0aW9ucy5pbmNsdWRlcygyKSkge1xyXG4gICAgICAgIDxidXR0b24gbWF0LWljb24tYnV0dG9uIFttYXRUb29sdGlwXT1cImZsaXBIb3JpbnpvbnRhbExhYmVsXCJcclxuICAgICAgICAgIChjbGljayk9XCJmbGlwSG9yaXpvbnRhbCgpXCI+PG1hdC1pY29uPmZsaXBfaG9yaXpvbnRhbDwvbWF0LWljb24+PC9idXR0b24+XHJcbiAgICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gW21hdFRvb2x0aXBdPVwiZmxpcFZlcnRpY2FsTGFiZWxcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cImZsaXBWZXJ0aWNhbCgpXCI+PG1hdC1pY29uPmZsaXBfdmVydGljYWw8L21hdC1pY29uPjwvYnV0dG9uPlxyXG4gICAgICAgIH1cclxuICAgICAgICA8YnV0dG9uIG1hdC1pY29uLWJ1dHRvbiBtYXRUb29sdGlwPVwiUmVzZXRcIlxyXG4gICAgICAgICAgKGNsaWNrKT1cInJlc3RvcmVPcmlnaW5hbERpbWVuc2lvbnMoKVwiPjxtYXQtaWNvbj5yZXBsYXk8L21hdC1pY29uPjwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDxkaXYgY2xhc3M9XCJtZWRpYS12aWV3ZXItd3JhcHBlclwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjcm9wLWNvbnRhaW5lci1tb2Rlcm5cIj5cclxuICAgICAgICAgIDxpbWFnZS1jcm9wcGVyIFtpbWFnZUZpbGVdPVwic2VsZWN0ZWRGaWxlXCIgW21haW50YWluQXNwZWN0UmF0aW9dPVwiZmFsc2VcIiBbY2FudmFzUm90YXRpb25dPVwiY2FudmFzUm90YXRpb25cIlxyXG4gICAgICAgICAgICBbdHJhbnNmb3JtXT1cInRyYW5zZm9ybVwiIGZvcm1hdD1cInBuZ1wiIChpbWFnZUNyb3BwZWQpPVwiaW1hZ2VDcm9wcGVkKCRldmVudClcIiBbcmVzaXplVG9XaWR0aF09XCJjdXN0b21XaWR0aFwiXHJcbiAgICAgICAgICAgIFtyZXNpemVUb0hlaWdodF09XCJjdXN0b21IZWlnaHRcIiBbb3V0cHV0XT1cIidiYXNlNjQnXCIgW2NvbnRhaW5XaXRoaW5Bc3BlY3RSYXRpb109XCJ0cnVlXCIgW29ubHlTY2FsZURvd25dPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgIFthbGlnbkltYWdlXT1cIidjZW50ZXInXCI+XHJcbiAgICAgICAgICA8L2ltYWdlLWNyb3BwZXI+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XHJcblxyXG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucyBhbGlnbj1cImVuZFwiIGNsYXNzPVwicHJldmlldy1hY3Rpb25zXCI+XHJcbiAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiAoY2xpY2spPVwiYWJvcnRGaWxlKClcIiBjbGFzcz1cImJ0bi1jbG9zZVwiPnt7IGFib3J0TGFiZWwgfX08L2J1dHRvbj5cclxuICAgICAgPGJ1dHRvbiBtYXQtcmFpc2VkLWJ1dHRvbiBjb2xvcj1cInByaW1hcnlcIiAoY2xpY2spPVwiY29uZmlybUFkZEF0dGFjaG1lbnQoKVwiIGNsYXNzPVwiYnRuLWRvd25sb2FkXCI+XHJcbiAgICAgICAgPG1hdC1pY29uPmNoZWNrPC9tYXQtaWNvbj4ge3sgY29uZmlybUxhYmVsIH19XHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XHJcbiAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG5cclxuXHJcbjwhLS0gVEVNUExBVEUgUEVSIEZPUk0gREkgQUdHSVVOVEEgREkgVU4gTElOSyAtLT5cclxuPG5nLXRlbXBsYXRlICNhZGRpbmdMaW5rVGVtcGxhdGU+XHJcbiAgPGRpdiBjbGFzcz1cIm1vZGVybi1kaWFsb2ctY29udGFpbmVyXCI+XHJcbiAgICA8ZGl2IG1hdC1kaWFsb2ctdGl0bGUgY2xhc3M9XCJwcmV2aWV3LWhlYWRlclwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLWluZm9cIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwidHlwZS1pY29uLXdyYXBwZXJcIj5cclxuICAgICAgICAgIDxtYXQtaWNvbj5saW5rPC9tYXQtaWNvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwidGl0bGUtZ3JvdXBcIj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwibWFpbi10XCI+QWdnaXVuZ2kgdW4gbGluazwvc3Bhbj5cclxuICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZmlsZS10XCI+SW5zZXJpc2NpIGwnVVJMIGRlbGxhIHJpc29yc2Egd2ViPC9zcGFuPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGJ1dHRvbiBtYXQtaWNvbi1idXR0b24gbWF0LWRpYWxvZy1jbG9zZSBjbGFzcz1cImNsb3NlLWJ0blwiPjxtYXQtaWNvbj5jbG9zZTwvbWF0LWljb24+PC9idXR0b24+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8bWF0LWRpYWxvZy1jb250ZW50IGNsYXNzPVwiYWRkLWxpbmstbW9kZXJuLWNvbnRlbnRcIj5cclxuICAgICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJuZXdBdHRhY2htZW50Rm9ybVwiIGNsYXNzPVwiYWRkLWxpbmstZm9ybVwiPlxyXG4gICAgICAgIDxtYXQtZm9ybS1maWVsZCBhcHBlYXJhbmNlPVwib3V0bGluZVwiIGNsYXNzPVwidy0xMDAgbXQtM1wiPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5VUkwgZGVsIGNvbGxlZ2FtZW50bzwvbWF0LWxhYmVsPlxyXG4gICAgICAgICAgPGlucHV0IG1hdElucHV0IGZvcm1Db250cm9sTmFtZT1cImZpbGVQYXRoXCIgcGxhY2Vob2xkZXI9XCJodHRwczovLy4uLlwiIHJlcXVpcmVkPlxyXG4gICAgICAgICAgPG1hdC1pY29uIG1hdFN1ZmZpeD5sYW5ndWFnZTwvbWF0LWljb24+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuXHJcbiAgICAgICAgPG1hdC1mb3JtLWZpZWxkIGFwcGVhcmFuY2U9XCJvdXRsaW5lXCIgY2xhc3M9XCJ3LTEwMFwiPlxyXG4gICAgICAgICAgPG1hdC1sYWJlbD5UaXRvbG8gKG9wemlvbmFsZSk8L21hdC1sYWJlbD5cclxuICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJmaWxlTmFtZVwiIHBsYWNlaG9sZGVyPVwiRXMuIERvY3VtZW50byBQcm9nZXR0b1wiPlxyXG4gICAgICAgICAgPG1hdC1pY29uIG1hdFN1ZmZpeD50aXRsZTwvbWF0LWljb24+XHJcbiAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cclxuICAgICAgPC9mb3JtPlxyXG4gICAgPC9tYXQtZGlhbG9nLWNvbnRlbnQ+XHJcblxyXG4gICAgPG1hdC1kaWFsb2ctYWN0aW9ucyBhbGlnbj1cImVuZFwiIGNsYXNzPVwicHJldmlldy1hY3Rpb25zXCI+XHJcbiAgICAgIDxidXR0b24gbWF0LWJ1dHRvbiBtYXQtZGlhbG9nLWNsb3NlIGNsYXNzPVwiYnRuLWNsb3NlXCI+QW5udWxsYTwvYnV0dG9uPlxyXG4gICAgICA8YnV0dG9uIG1hdC1yYWlzZWQtYnV0dG9uIGNvbG9yPVwicHJpbWFyeVwiIFttYXQtZGlhbG9nLWNsb3NlXT1cIm5ld0F0dGFjaG1lbnRGb3JtLnZhbHVlXCJcclxuICAgICAgICBbZGlzYWJsZWRdPVwibmV3QXR0YWNobWVudEZvcm0uaW52YWxpZFwiIGNsYXNzPVwiYnRuLWRvd25sb2FkXCI+XHJcbiAgICAgICAgPG1hdC1pY29uPmFkZDwvbWF0LWljb24+IEFnZ2l1bmdpXHJcbiAgICAgIDwvYnV0dG9uPlxyXG4gICAgPC9tYXQtZGlhbG9nLWFjdGlvbnM+XHJcbiAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+Il19