@eqproject/eqp-attachments 0.1.16 → 2.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.
Files changed (48) hide show
  1. package/README.md +0 -1
  2. package/esm2020/eqproject-eqp-attachments.mjs +5 -0
  3. package/esm2020/lib/eqp-attachments.component.mjs +830 -0
  4. package/esm2020/lib/eqp-attachments.module.mjs +39 -0
  5. package/esm2020/lib/helpers/attachment.helper.mjs +61 -0
  6. package/esm2020/lib/interfaces/IAttachment.mjs +6 -0
  7. package/esm2020/lib/interfaces/IOptions.mjs +2 -0
  8. package/esm2020/lib/modules/material.module.mjs +231 -0
  9. package/esm2020/lib/services/eqp-attachment-dialog.service.mjs +103 -0
  10. package/esm2020/public-api.mjs +10 -0
  11. package/fesm2015/eqproject-eqp-attachments.mjs +1275 -0
  12. package/fesm2015/eqproject-eqp-attachments.mjs.map +1 -0
  13. package/fesm2020/eqproject-eqp-attachments.mjs +1264 -0
  14. package/fesm2020/eqproject-eqp-attachments.mjs.map +1 -0
  15. package/{eqproject-eqp-attachments.d.ts → index.d.ts} +1 -1
  16. package/lib/eqp-attachments.component.d.ts +5 -11
  17. package/lib/eqp-attachments.module.d.ts +10 -0
  18. package/lib/helpers/attachment.helper.d.ts +3 -0
  19. package/lib/modules/material.module.d.ts +35 -0
  20. package/lib/services/eqp-attachment-dialog.service.d.ts +3 -0
  21. package/package.json +29 -16
  22. package/bundles/eqproject-eqp-attachments.umd.js +0 -1409
  23. package/bundles/eqproject-eqp-attachments.umd.js.map +0 -1
  24. package/bundles/eqproject-eqp-attachments.umd.min.js +0 -2
  25. package/bundles/eqproject-eqp-attachments.umd.min.js.map +0 -1
  26. package/eqproject-eqp-attachments.metadata.json +0 -1
  27. package/esm2015/eqproject-eqp-attachments.js +0 -6
  28. package/esm2015/lib/eqp-attachments.component.js +0 -857
  29. package/esm2015/lib/eqp-attachments.module.js +0 -26
  30. package/esm2015/lib/helpers/attachment.helper.js +0 -62
  31. package/esm2015/lib/interfaces/IAttachment.js +0 -6
  32. package/esm2015/lib/interfaces/IOptions.js +0 -1
  33. package/esm2015/lib/modules/material.module.js +0 -108
  34. package/esm2015/lib/services/eqp-attachment-dialog.service.js +0 -104
  35. package/esm2015/public-api.js +0 -9
  36. package/esm5/eqproject-eqp-attachments.js +0 -6
  37. package/esm5/lib/eqp-attachments.component.js +0 -916
  38. package/esm5/lib/eqp-attachments.module.js +0 -29
  39. package/esm5/lib/helpers/attachment.helper.js +0 -63
  40. package/esm5/lib/interfaces/IAttachment.js +0 -6
  41. package/esm5/lib/interfaces/IOptions.js +0 -1
  42. package/esm5/lib/modules/material.module.js +0 -111
  43. package/esm5/lib/services/eqp-attachment-dialog.service.js +0 -113
  44. package/esm5/public-api.js +0 -9
  45. package/fesm2015/eqproject-eqp-attachments.js +0 -1148
  46. package/fesm2015/eqproject-eqp-attachments.js.map +0 -1
  47. package/fesm5/eqproject-eqp-attachments.js +0 -1223
  48. package/fesm5/eqproject-eqp-attachments.js.map +0 -1
@@ -1,857 +0,0 @@
1
- import { __awaiter, __decorate } from "tslib";
2
- import { AfterViewInit, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output, TemplateRef, ViewChild } from '@angular/core';
3
- import { FormBuilder, FormGroup, Validators } from '@angular/forms';
4
- import { base64ToFile, ImageCropperComponent } from 'ngx-image-cropper';
5
- import imageCompression from 'browser-image-compression';
6
- import { AttachmentType } from './interfaces/IAttachment';
7
- import { TooltipPositionType, TypeColumn } from '@eqproject/eqp-table';
8
- import { MatDialog, MatDialogRef } from '@angular/material/dialog';
9
- import { AttachmentHelperService } from './helpers/attachment.helper';
10
- import { EqpAttachmentDialogService } from './services/eqp-attachment-dialog.service';
11
- import { DomSanitizer } from '@angular/platform-browser';
12
- import { HttpClient } from '@angular/common/http';
13
- const toBase64 = file => new Promise((resolve, reject) => {
14
- const reader = new FileReader();
15
- reader.readAsDataURL(file);
16
- reader.onload = () => resolve(reader.result.toString());
17
- reader.onerror = error => reject(error);
18
- });
19
- const ɵ0 = toBase64;
20
- let EqpAttachmentsComponent = class EqpAttachmentsComponent {
21
- constructor(dialog, formBuilder, sanitizer, http, cd) {
22
- this.dialog = dialog;
23
- this.formBuilder = formBuilder;
24
- this.sanitizer = sanitizer;
25
- this.http = http;
26
- this.cd = cd;
27
- //#region @Input del componente
28
- /**
29
- * Se TRUE allora nasconde la colonna per le azioni sull'allegato (nel caso "multipleAttachment" è TRUE).
30
- */
31
- this.disableAction = false;
32
- /**
33
- * Se TRUE mostra il titolo nell'header nel caso in cui "multipleAttachment" è TRUE ("Elenco allegati" di default).
34
- */
35
- this.showHeader = true;
36
- /**
37
- * Titolo da visualizzare se il parametro "showHeader" è TRUE. Di devault viene visualizzato "Elenco allegati".
38
- */
39
- this.headerTitle = "Elenco allegati";
40
- /**
41
- * Sorgente dati da visualizzare. Nel caso si vuole gestire un singolo allegato va passato in ogni caso come Array.
42
- */
43
- this.attachmentsList = null;
44
- /**
45
- * Se TRUE non mostra la MatCard (nel caso in cui "multipleAttachment" è TRUE).
46
- */
47
- this.showMatCard = true;
48
- /**
49
- * 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".
50
- * Se TRUE allora il componente mostra l'elenco di tutti gli allegati ricevuto nel parametro "attachmentsList".
51
- */
52
- this.multipleAttachment = true;
53
- /**
54
- * Se assume il valore TRUE allora sarà possibile caricare più file per volta. Questa funzionalità è attiva
55
- * SOLO se si gestiscono allegati multipli, quindi se l'input 'multipleAttachment' assume il valore TRUE, altrimenti è sempre disabilitata.
56
- */
57
- this.loadMultipleFiles = false;
58
- /**
59
- * Configurazione delle colonne della eqp-table per la visualizzazione degli allegati (caso "multipleAttachment" è TRUE).
60
- */
61
- this.attachmentsColumns = null;
62
- /**
63
- * Imposta il messaggio da visualizzare nel caso in cui la tabella degli allegati (nel caso in cui "multipleAttachment" è TRUE) è vuota.
64
- */
65
- this.emptyTableMessage = "Nessun dato trovato";
66
- /**
67
- * Se TRUE allora permette di selezionare soltanto file di tipo immagine, avente uno dei mimetype
68
- * specificati dentro AttachmentHelperService.
69
- * Se FALSE permette di selezionare qualsiasi tipo di file
70
- */
71
- this.allowOnlyImages = false;
72
- /**
73
- * Se TRUE disabilita il pulsante di Aggiunta allegato (a prescindere dal valore del parametro "multipleAttachment").
74
- */
75
- this.isDisabled = false;
76
- /**
77
- * Mostra/nasconde la colonna per visualizzare l'anteprima dei file nella tabella (caso multipleAtatchments = true).
78
- */
79
- this.showInlinePreview = false;
80
- /**
81
- * Endpoint da chiamare per recueprare l'IAttachmentDTO completo da vedere nell'anteprima. La chiamata sarà in POST e nel body
82
- * conterrà l'IAttachmentDTO selezionato dall'utente.
83
- * La chiamata viene eseguita solo per l'anteprima delle immagini essendo necessario il base64 completo dell'immagine a dimensione reale.
84
- * Per documenti/link basta che sia popolata la proprietà FilePath di IAttachmentDTO.
85
- */
86
- this.getAttachmentEndpoint = null;
87
- /**
88
- * Hostname dell'ambiente di produzione dell'applicativo. Necessario per visualizzare l'anteprima dei documenti
89
- * tramite il viewer di google.
90
- * NOTA: Per visualizzare l'anteprima è necessario che la prorietà FilePath dell'IAttachmentDTO sia popolata e che
91
- * sia abilitato l'accesso alla cartella sul server tramite hostname.
92
- */
93
- this.productionBaseUrl = null;
94
- /**
95
- * Opzioni per la compressione delle immagini caricate.
96
- */
97
- this.compressionOptions = { maxSizeMB: 0.5, maxWidthOrHeight: 1920, useWebWorker: true };
98
- /**
99
- * Array di AttachmentType che si possono aggiungere
100
- */
101
- this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK];
102
- /**
103
- * Permette di stabilire se la eqp-table contenente l'elenco degli allegati utilizza
104
- * il multilingua oppure no
105
- */
106
- this.isEqpTableMultiLanguage = false;
107
- /**
108
- * Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
109
- * degli allegati deve essere paginata oppure no
110
- */
111
- this.tablePaginatorVisible = true;
112
- /**
113
- * In caso di gestione allegati multipli, permette di stabilire la dimensione pagina di default
114
- * per la tabella contenente l'elenco degli allegati
115
- */
116
- this.tablePaginatorSize = null;
117
- /**
118
- * Input per definire le label da usare nel componente
119
- */
120
- this.downloadTooltipPosition = TooltipPositionType.Below;
121
- this.openLinkLabel = "Apri link";
122
- this.addButtonLabel = "Aggiungi";
123
- this.downloadLabel = "Download";
124
- this.deleteLabel = "Elimina";
125
- this.fileNameLabel = "Nome file";
126
- this.previewLabel = "Anteprima";
127
- this.uploadFileLabel = "Carica file";
128
- this.confirmLabel = "Conferma";
129
- this.abortLabel = "Annulla";
130
- this.saveLabel = "Salva";
131
- this.exitLabel = "Esci";
132
- this.eqpTableSearchText = "Cerca";
133
- this.deleteDialogTitle = null;
134
- this.deleteDialogMessage = "Sei sicuro di voler cancellare quest'allegato?";
135
- this.noImageSelectedErrorMessage = "Non è possibile selezionare un file che non sia un'immagine.";
136
- this.wrongTypeSelectedErrorMessage = "Non è possibile caricare il file selezionato.";
137
- this.videoPreviewErrorMessage = "Impossibile aprire l'anteprima di un file video.";
138
- this.audioPreviewErrorMessage = "Impossibile aprire l'anteprima di un file audio.";
139
- //#endregion
140
- //#region @Output del componente
141
- /**
142
- * Restituisce la lista aggiornata degli allegati.
143
- */
144
- this.localEditedAttachments = new EventEmitter();
145
- /**
146
- * Evento scatenato alla pressione del pulsante ESCI della modale di caricamento file.
147
- */
148
- this.abortAddAttachment = new EventEmitter();
149
- /**
150
- * Evento di output che restituisce l'IAttachmentDTO selezionato per il download nel caso FileDataBase64, FileContentType o FileName non fossero specificati.
151
- */
152
- this.downloadAttachment = new EventEmitter();
153
- /**
154
- * Evento di output che restituisce l'elemento eliminato prima che questo venga effettivamente rismosso dalla lista.
155
- */
156
- this.onDeleteAttachment = new EventEmitter();
157
- /**
158
- * Evento di output scatenato durante l'AfterViewInit del componente che restituisce l'istanza corrente del componente.
159
- * Questo evento avvisa quando il componente è stato renderizzato, utile per esempio quando si vogliono aggiungere delle colonne
160
- * alla visualizzazione con allegati multipli lasciando però quelle pre esistenti. Questo si può fare intervenendo sulla
161
- * proprietà "attachmentsColumns" di questo componente tramite l'istanza passata come paramentro oppure tramite ViewChild
162
- * dal componente che lo ospita.
163
- */
164
- this.onComponentLoaded = new EventEmitter();
165
- //#endregion
166
- //#region Proprietà per gestione caricamento nuovo allegato
167
- this.newAttachment = {};
168
- this.newMultipleAttachments = [];
169
- this.attachmentType = AttachmentType;
170
- this.selectedFile = null;
171
- this.selectedFiles = null;
172
- this.showCropImage = false;
173
- //#endregion
174
- //#region Proprietà per gestione ridimensionamento file di tipo image
175
- this.imageChangedEvent = '';
176
- this.croppedImage = '';
177
- this.transform = {};
178
- //#endregion
179
- this.AttachmentType = AttachmentType;
180
- }
181
- ngOnInit() {
182
- //Se è stata richiesta la gestione delle sole immagini allora imposta il filtro per le estensioni possibili da caricare
183
- if (!this.acceptedFileTypes)
184
- if (this.allowOnlyImages == true)
185
- this.acceptedFileTypes = "image/*";
186
- else
187
- this.acceptedFileTypes = "*";
188
- // Se non sono stati specificati i tipi da gestire ma è stato passato null o un array vuoto imposto i tipi di default.
189
- if (!this.allowedTypes || this.allowedTypes.length == 0)
190
- this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK];
191
- else if (this.allowedTypes.find(t => t != AttachmentType.FILE && t != AttachmentType.LINK)) {
192
- EqpAttachmentDialogService.Warning("Almeno uno degli AttachmentType selezionati nel parametro \"allowedTypes\" non esiste.");
193
- this.allowedTypes = [AttachmentType.FILE, AttachmentType.LINK];
194
- }
195
- //Se è stata richiesta la gestione multipla degli allegati allora configura l'eqp-table
196
- if (this.multipleAttachment == true && (!this.attachmentsColumns || this.attachmentsColumns.length == 0)) {
197
- this.configureColumns();
198
- }
199
- if (this.attachmentsList == null)
200
- this.attachmentsList = new Array();
201
- this.checkAttachmentImage();
202
- }
203
- ngAfterViewInit() {
204
- this.onComponentLoaded.emit(this);
205
- }
206
- reloadData() {
207
- if (this.attachmentTable)
208
- this.attachmentTable.reloadDatatable();
209
- }
210
- checkAttachmentImage() {
211
- this.attachmentsList.forEach(a => {
212
- a.IsImage = AttachmentHelperService.checkImageFromMimeType(a.FileContentType);
213
- });
214
- }
215
- //#region Gestione elenco allegati
216
- /**
217
- * Configura le colonne per l'eqp-table nel caso in cui il parametro "multipleAttachments" è TRUE.
218
- */
219
- configureColumns() {
220
- this.attachmentsColumns = [];
221
- if (this.disableAction != true) {
222
- this.attachmentsColumns.push({
223
- key: "action", display: "",
224
- type: TypeColumn.MenuAction, buttonMenuIcon: "more_vert", styles: { flex: "0 0 6%" },
225
- actions: [
226
- { name: this.deleteLabel, icon: "delete", fn: (element, index, col) => this.deleteAttachment(element) },
227
- ],
228
- });
229
- }
230
- let downloadColumn = {
231
- key: "attachment", display: "",
232
- type: TypeColumn.SimpleAction, styles: { flex: "0 0 6%" },
233
- actions: [
234
- {
235
- name: '', fontawesome: true,
236
- icon: (element) => { return this.showInlinePreview ? (element.AttachmentType == AttachmentType.FILE ? "fas fa-cloud-download-alt" : "fas fa-external-link-alt") : this.getAttachmentIcon(element); },
237
- fn: (element, col, elementIndex) => this.viewAttachment(element),
238
- tooltip: { tooltipText: (element) => { return element.AttachmentType == AttachmentType.FILE ? this.downloadLabel : this.openLinkLabel; }, tooltipPosition: this.downloadTooltipPosition }
239
- },
240
- ]
241
- };
242
- let inlinePreviewColumn = {
243
- key: "InlinePreview", display: this.previewLabel,
244
- type: TypeColumn.ExternalTemplate,
245
- externalTemplate: this.inlinePreviewTemplate,
246
- styles: { flex: "0 0 10%" }
247
- };
248
- let fileNameColumn = { key: "FileName", display: this.fileNameLabel };
249
- if (this.showInlinePreview) {
250
- this.attachmentsColumns.push(inlinePreviewColumn);
251
- this.attachmentsColumns.push(fileNameColumn);
252
- this.attachmentsColumns.push(downloadColumn);
253
- }
254
- else {
255
- this.attachmentsColumns.push(downloadColumn);
256
- this.attachmentsColumns.push(fileNameColumn);
257
- }
258
- }
259
- /**
260
- * Elimina un allegato eliminando anche il file presente nello storage di archiviazione utilizzato (AWS o cartella progetto)
261
- * @param element IAttachmentDTO da cancellare
262
- */
263
- deleteAttachment(element) {
264
- EqpAttachmentDialogService.Confirm(this.deleteDialogMessage, () => {
265
- this.removeAttachmentFromList(this.attachmentsList.indexOf(element));
266
- }, true, this.deleteDialogTitle);
267
- }
268
- /**
269
- * Rimuove l'allegato selezionato dalla lista "attachmentsList" e invoca l'evento di output che restituisce la lista aggiornata.
270
- * @param attachmentIndex Indice dell'attachment da rimuovere
271
- */
272
- removeAttachmentFromList(attachmentIndex) {
273
- this.onDeleteAttachment.emit(this.attachmentsList[attachmentIndex]);
274
- this.attachmentsList.splice(attachmentIndex, 1);
275
- if (this.attachmentTable)
276
- this.attachmentTable.reloadDatatable();
277
- this.localEditedAttachments.emit(this.attachmentsList);
278
- }
279
- /**
280
- * Scarica l'allegato o apre il link
281
- * @param element Allegato da mostrare
282
- */
283
- viewAttachment(attachment) {
284
- if (attachment.AttachmentType == AttachmentType.LINK) {
285
- window.open(attachment.FilePath, '_blank');
286
- return;
287
- }
288
- if (attachment.FileDataBase64 && attachment.FileContentType && attachment.FileName) {
289
- let source = `data:${attachment.FileContentType};base64,${attachment.FileDataBase64}`;
290
- const link = document.createElement("a");
291
- link.href = source;
292
- link.download = `${attachment.FileName}`;
293
- link.click();
294
- }
295
- else {
296
- this.downloadAttachment.emit(attachment);
297
- }
298
- }
299
- /**
300
- * Ridefinisce l'icona da mostrare nella colonna dell'eqp-table per ogni file.
301
- * L'icona varia in base all'estensione del file
302
- * @param attachment
303
- */
304
- getAttachmentIcon(attachment) {
305
- if (attachment.AttachmentType == AttachmentType.LINK)
306
- return "fas fa-link";
307
- else
308
- return AttachmentHelperService.getIconFromFileExtensione(attachment.FileExtension);
309
- }
310
- //#endregion
311
- /**
312
- * Apre la modale per la definizione dei parametri del nuovo file
313
- */
314
- openModalAddAttachment(attachmentType) {
315
- //Se è stato richiesto il caricamento di un LINK o è impostato il caricamento di FILE SINGOLO allora apre la modale per
316
- //il caricamento singolo del file altrimenti apre quella per il caricamento multiplo
317
- // if (attachmentType == AttachmentType.LINK || (attachmentType == AttachmentType.FILE && this.loadMultipleFiles != true)) {
318
- this.newAttachment = {};
319
- this.newAttachment.IsImage = false;
320
- this.newAttachment.AttachmentType = attachmentType;
321
- this.newMultipleAttachments = new Array();
322
- if (attachmentType == AttachmentType.LINK)
323
- this.newMultipleAttachments.push(this.newAttachment);
324
- this.createAttachmentForm();
325
- //Apre la modale
326
- this.dialofRefAddAttachment = this.dialog.open(this.dialogAddAttachment, {
327
- disableClose: true,
328
- hasBackdrop: true,
329
- width: '60%',
330
- maxHeight: '80%'
331
- });
332
- }
333
- createAttachmentForm() {
334
- //Crea la form per la validazione dei campi
335
- this.newAttachmentForm = this.formBuilder.group({
336
- type: [this.newAttachment.AttachmentType, Validators.required],
337
- name: [this.newAttachment.FileName],
338
- path: [this.newAttachment.FilePath],
339
- customHeight: [this.customHeight],
340
- customWidth: [this.customWidth]
341
- });
342
- }
343
- close(emitCloseEvent = true) {
344
- this.newAttachment = {};
345
- this.newMultipleAttachments = new Array();
346
- this.abortFile();
347
- if (this.newAttachmentForm)
348
- this.newAttachmentForm.reset();
349
- this.dialofRefAddAttachment.close();
350
- if (emitCloseEvent == true && this.abortAddAttachment)
351
- this.abortAddAttachment.emit();
352
- }
353
- /**
354
- * In base al tipo di allegato controlla se disabilitare o meno il pulsante per salvare.
355
- * Funzione usata nel [disable] del pulsante "Salva" del dialog per l'aggiunta di un allegato.
356
- * @returns
357
- */
358
- disableSave() {
359
- if (this.loadMultipleFiles != true) {
360
- if (this.newAttachment.AttachmentType == AttachmentType.FILE) {
361
- return !this.newAttachment.FileDataBase64;
362
- }
363
- else {
364
- return !this.newAttachment.FilePath;
365
- }
366
- }
367
- else {
368
- return this.newMultipleAttachments.filter(p => (p.AttachmentType == AttachmentType.FILE && !p.FileDataBase64) || (p.AttachmentType == AttachmentType.LINK && !p.FilePath)).length > 0;
369
- }
370
- }
371
- confirmAddAttachment() {
372
- if (this.loadMultipleFiles != true) {
373
- if (this.newAttachment.AttachmentType == AttachmentType.LINK && !this.newAttachment.FileName)
374
- this.newAttachment.FileName = this.newAttachment.FilePath;
375
- if (this.attachmentsList == null)
376
- this.attachmentsList = new Array();
377
- this.attachmentsList.push(this.newAttachment);
378
- }
379
- else {
380
- if (this.newMultipleAttachments == null || this.newMultipleAttachments.length == 0)
381
- return;
382
- if (this.attachmentsList == null)
383
- this.attachmentsList = new Array();
384
- this.attachmentsList = this.attachmentsList.concat(this.newMultipleAttachments);
385
- }
386
- if (this.attachmentTable)
387
- this.attachmentTable.reloadDatatable();
388
- this.localEditedAttachments.emit(this.attachmentsList);
389
- this.close(false);
390
- }
391
- /**
392
- * Apre il dialog per l'anteprima dell'allegato selezionato.
393
- * @param row
394
- * @returns
395
- */
396
- openPreviewDialog(row) {
397
- return __awaiter(this, void 0, void 0, function* () {
398
- this.selectedAttachment = JSON.parse(JSON.stringify(row));
399
- if (this.selectedAttachment.AttachmentType == AttachmentType.FILE) {
400
- if (this.selectedAttachment.FileContentType.startsWith("video")) {
401
- EqpAttachmentDialogService.Warning(this.videoPreviewErrorMessage);
402
- return;
403
- }
404
- else if (this.selectedAttachment.FileContentType.startsWith("audio")) {
405
- EqpAttachmentDialogService.Warning(this.audioPreviewErrorMessage);
406
- return;
407
- }
408
- }
409
- if (this.getAttachmentEndpoint && this.selectedAttachment.IsImage && !this.selectedAttachment.FileDataBase64) {
410
- yield this.getAttachmentByID()
411
- .then((res) => { this.selectedAttachment.FileDataBase64 = res.FileDataBase64; })
412
- .catch((err) => { EqpAttachmentDialogService.Error(err); });
413
- }
414
- if (this.selectedAttachment.AttachmentType == AttachmentType.LINK) {
415
- this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.selectedAttachment.FilePath);
416
- }
417
- else if (this.selectedAttachment.IsImage && !this.selectedAttachment.FileDataBase64 && !this.selectedAttachment.FileThumbnailBase64) {
418
- EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima dell'allegato, file mancante.");
419
- return;
420
- }
421
- else if (!this.selectedAttachment.IsImage) {
422
- if (this.selectedAttachment.FilePath && this.productionBaseUrl) {
423
- this.selectedAttachment.TrustedUrl = this.sanitizer.bypassSecurityTrustResourceUrl("https://docs.google.com/gview?url=" +
424
- this.productionBaseUrl +
425
- "/" +
426
- this.selectedAttachment.FilePath +
427
- "&embedded=true");
428
- }
429
- else {
430
- EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima del documento!");
431
- return;
432
- }
433
- }
434
- this.dialog.open(this.dialogPreview, {
435
- disableClose: true,
436
- hasBackdrop: true,
437
- });
438
- });
439
- }
440
- getAttachmentByID() {
441
- return __awaiter(this, void 0, void 0, function* () {
442
- return this.http.post(this.getAttachmentEndpoint, this.selectedAttachment).toPromise();
443
- });
444
- }
445
- //#region Gestione caricamento file
446
- /**
447
- * Evento scatenato alla selezione del file (o dei file).
448
- * 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
449
- * mostrare le funzionalità del croppie (per ritagliare l'immagine) oppure no.
450
- * Se il file caricato non è un immagine allora genera direttamente il base64 e lo associa all'allegato da salvare.
451
- * Se invece il caricamento dei file è MULTIPLO e sono presenti più file allora esegue le stesse operazioni ignorando però il contrllo
452
- * immagine per il croppie (in caso di caricamento multiplo le funzionalità del croppie sono disabilitate).
453
- */
454
- onFileInputChange(event) {
455
- return __awaiter(this, void 0, void 0, function* () {
456
- this.showCropImage = false;
457
- //Se è stato richiesto il caricamento SINGOLO oppure se il caricamento è MULTIPLO ma è stato selezionato un solo file
458
- //allora verifica se il file è un immagine (per mostrare il CROPPIE)
459
- if ([...event.target.files].length == 1 || this.loadMultipleFiles != true) {
460
- this.selectedFile = event.target.files[0];
461
- this.selectedFiles = event.target.files;
462
- if (!this.selectedFile)
463
- return;
464
- //Memorizza i dati per l'allegato
465
- this.newAttachment = yield this.createAttachmentFromUploadedFile(this.selectedFile, false);
466
- this.newMultipleAttachments = new Array();
467
- this.newMultipleAttachments.push(this.newAttachment);
468
- //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
469
- let checkOnlyImage = this.checkAllowOnlyImageFile(this.newAttachment);
470
- if (checkOnlyImage == false)
471
- return;
472
- if (this.loadMultipleFiles == true && [...event.target.files].length == 1)
473
- this.createAttachmentForm();
474
- //Verifica se il file caricato è un'immagine oppure no. Se è un immagine, prima di caricarla mostra il croppie per il resize.
475
- //Se non è un immagine allora genera il Base64
476
- if (this.newAttachment.IsImage == true) {
477
- this.getImageDimensions(event.target.files[0]);
478
- //Mostra il croppie e disabilita la form finchè non termina la modifica dell'immagine
479
- this.newAttachmentForm.disable();
480
- this.newAttachmentForm.controls["customWidth"].enable();
481
- this.newAttachmentForm.controls["customHeight"].enable();
482
- this.showCropImage = true;
483
- this.imageChangedEvent = event;
484
- }
485
- else {
486
- this.showCropImage = false;
487
- let base64Result = yield this.getBase64FromFile(this.selectedFile);
488
- this.newAttachment.FileDataBase64 = base64Result.Base64File;
489
- this.newAttachment.FileContentType = base64Result.ContentType;
490
- }
491
- }
492
- else {
493
- this.selectedFiles = event.target.files;
494
- if (!this.selectedFiles || this.selectedFiles.length == 0)
495
- return;
496
- this.newMultipleAttachments = new Array();
497
- for (let i = 0; i < this.selectedFiles.length; i++) {
498
- let newAttachment = yield this.createAttachmentFromUploadedFile(this.selectedFiles[i], true);
499
- //Se è stata richiesta la gestione delle sole immagini ma per errore è stato selezionato un file che non è un immagine
500
- let checkOnlyImage = this.checkAllowOnlyImageFile(newAttachment);
501
- if (checkOnlyImage == false)
502
- return;
503
- this.newMultipleAttachments.push(newAttachment);
504
- }
505
- }
506
- });
507
- }
508
- /**
509
- * A partire dal FILE ricevuto in input ricostruisce l'oggetto IAttachmentDTO e lo restituisce.
510
- * Se il parametro getBase64 viene passato a TRUE allora, sempre a partire dal file,genera il base64 e
511
- * ricava il ContentType da associare all'oggetto IAttachmentDTO da restituire
512
- * @param currentFile Oggetto FILE da processare
513
- * @param getBase64 Se TRUE allora calcola base64 e ContentType del file passato in input
514
- * @returns Restituisce un oggetto di tipo IAttachmentDTO
515
- */
516
- createAttachmentFromUploadedFile(currentFile, getBase64 = true) {
517
- return __awaiter(this, void 0, void 0, function* () {
518
- let newAttachment = {};
519
- //Memorizza i dati per l'allegato
520
- newAttachment.AttachmentType = AttachmentType.FILE;
521
- newAttachment.FileContentType = currentFile.type;
522
- newAttachment.FileName = currentFile.name;
523
- newAttachment.FileExtension = currentFile.name.substr(currentFile.name.lastIndexOf('.') + 1);
524
- newAttachment.IsImage = AttachmentHelperService.checkImageFromMimeType(currentFile.type);
525
- if (getBase64 == true) {
526
- let base64Result = yield this.getBase64FromFile(currentFile);
527
- newAttachment.FileDataBase64 = base64Result.Base64File;
528
- newAttachment.FileContentType = base64Result.ContentType;
529
- }
530
- return newAttachment;
531
- });
532
- }
533
- /**
534
- * A partire dal file passato in input restituisce un oggetto
535
- * contenente il base64 del file e il suo contentType
536
- * @param currentFile Oggetto File da cui estrapolare base64 e contentType
537
- * @returns Restituisce un oggetto avente le proprietà Base64File e ContentType
538
- */
539
- getBase64FromFile(currentFile) {
540
- return __awaiter(this, void 0, void 0, function* () {
541
- let base64File = yield toBase64(currentFile);
542
- let contentType = null;
543
- if (base64File) {
544
- // Loris 20/01/2022: PROBLEMA - Quando eseguo l'upload di un file .sql non viene salvato/scaricato correttamente.
545
- // Questo succede perchè non viene popolato il FileContentType. Per risolvere il problema
546
- // faccio un controllo e se non esiste il FileContentType allora lo recupero dal base64 ottenuto.
547
- contentType = base64File.split(",")[0].split(":")[1].split(";")[0];
548
- // Un altro metodo per leggere il ccontent type del file è tramite una regular expression:
549
- base64File = base64File.split(",")[1];
550
- }
551
- let result = {
552
- Base64File: base64File,
553
- ContentType: contentType
554
- };
555
- return result;
556
- });
557
- }
558
- /**
559
- * Controlla se il file che si sta caricando è supportato dal sistema.
560
- * @returns
561
- */
562
- checkAcceptedFiles() {
563
- if ((this.loadMultipleFiles != true && this.selectedFile.type.startsWith("video"))
564
- || (this.loadMultipleFiles == true && [...this.selectedFiles].filter(p => p.type.startsWith("video")).length > 0))
565
- return false;
566
- if (this.acceptedFileTypes == "*")
567
- return true;
568
- //Verifica che i tipi del file (o dei file) caricati siano coerenti con quelli accettati dalla direttiva
569
- let accepted = true;
570
- if (this.loadMultipleFiles != true)
571
- accepted = this.acceptedFileTypes.includes(this.selectedFile.type);
572
- else {
573
- let uploadedFileTypes = [...this.selectedFiles].map(p => p.type);
574
- uploadedFileTypes.forEach(type => {
575
- if (!this.acceptedFileTypes.includes(type))
576
- accepted = false;
577
- });
578
- }
579
- //Questo controllo permette di gestire le casistiche per cui vengono indicati come tipi validi, ad esempio, 'image/*'
580
- if (!accepted && this.loadMultipleFiles != true) {
581
- for (let t of this.acceptedFileTypes.split(",").filter(t => t.includes("*"))) {
582
- accepted = this.selectedFile.type.startsWith(t.split("*")[0]);
583
- if (accepted)
584
- break;
585
- }
586
- }
587
- return accepted;
588
- }
589
- /**
590
- * Se eqp-attachments è stata configurata per il caricamento delle sole immagini allora verifica che il file passato in
591
- * input sia effettivamente un immagine o no.
592
- * Se il controllo va a buon fine restituisce TRUE altrimenti mostra un messaggio d'errore e restituisce FALSE
593
- */
594
- checkAllowOnlyImageFile(newAttachment) {
595
- if (this.allowOnlyImages == true && newAttachment.IsImage != true) {
596
- EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage);
597
- this.abortFile();
598
- return false;
599
- }
600
- else if (!this.checkAcceptedFiles()) {
601
- EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage);
602
- this.abortFile();
603
- return false;
604
- }
605
- return true;
606
- }
607
- getImageDimensions(img) {
608
- const reader = new FileReader();
609
- reader.onload = (e) => {
610
- const image = new Image();
611
- image.src = e.target.result;
612
- image.onload = rs => {
613
- this.originalHeight = rs.currentTarget['height'];
614
- this.originalWidth = rs.currentTarget['width'];
615
- if (this.originalWidth > 1280) {
616
- this.customWidth = 1280;
617
- this.customHeight = Math.round((1280 * this.originalHeight) / this.originalWidth);
618
- }
619
- else {
620
- this.customHeight = rs.currentTarget['height'];
621
- this.customWidth = rs.currentTarget['width'];
622
- }
623
- };
624
- };
625
- reader.readAsDataURL(img);
626
- }
627
- restoreOriginalDimensions() {
628
- this.customWidth = this.originalWidth;
629
- this.customHeight = this.originalHeight;
630
- }
631
- onDimensionsChange(dimension) {
632
- if (dimension == "H") {
633
- this.customWidth = Math.round((this.customHeight * this.originalWidth) / this.originalHeight);
634
- }
635
- else if (dimension == "W") {
636
- this.customHeight = Math.round((this.customWidth * this.originalHeight) / this.originalWidth);
637
- }
638
- }
639
- imageCropped(event) {
640
- this.croppedImage = event.base64;
641
- this.getCroppedAndUpload(this.croppedImage);
642
- }
643
- getCroppedAndUpload(file) {
644
- var self = this;
645
- var file = base64ToFile(file);
646
- const options = this.compressionOptions;
647
- /**
648
- * Comprime l'immagine passando come parametri le options create nell'oggetto sopra, e il file dal reader principale
649
- */
650
- imageCompression(file, options).then((fileCompressed => {
651
- let fileReader = new FileReader();
652
- //Faccio la push di ogni file all'interno dell'array di file dell'item da mandare al server
653
- fileReader.onload = function () {
654
- let resultReader = fileReader.result;
655
- var marker = ';base64,';
656
- self.newAttachment.FileDataBase64 = resultReader.substring(resultReader.indexOf(marker) + marker.length);
657
- self.showCropImage = false;
658
- self.newAttachmentForm.enable();
659
- };
660
- fileReader.readAsDataURL(fileCompressed);
661
- }));
662
- }
663
- confirmCrop() {
664
- this.imageCropper.crop();
665
- }
666
- /**
667
- * Annulla la selezione del file, svuotando l'input e resettando tutte le proprietà dell'IAttachmentDTO
668
- */
669
- abortFile() {
670
- this.imageChangedEvent = '';
671
- if (this.imageInput)
672
- this.imageInput.nativeElement.value = '';
673
- this.selectedFile = null;
674
- this.selectedFiles = null;
675
- this.showCropImage = false;
676
- this.newAttachment.IsImage = false;
677
- this.newAttachment.FileDataBase64 = null;
678
- this.newAttachment.FileName = null;
679
- this.newAttachment.FileExtension = null;
680
- this.newAttachment.FileContentType = null;
681
- this.newMultipleAttachments = new Array();
682
- this.customHeight = null;
683
- this.customWidth = null;
684
- this.originalHeight = null;
685
- this.originalWidth = null;
686
- }
687
- };
688
- EqpAttachmentsComponent.ctorParameters = () => [
689
- { type: MatDialog },
690
- { type: FormBuilder },
691
- { type: DomSanitizer },
692
- { type: HttpClient },
693
- { type: ChangeDetectorRef }
694
- ];
695
- __decorate([
696
- Input("disableAction")
697
- ], EqpAttachmentsComponent.prototype, "disableAction", void 0);
698
- __decorate([
699
- Input("showHeader")
700
- ], EqpAttachmentsComponent.prototype, "showHeader", void 0);
701
- __decorate([
702
- Input("headerTitle")
703
- ], EqpAttachmentsComponent.prototype, "headerTitle", void 0);
704
- __decorate([
705
- Input("attachmentsList")
706
- ], EqpAttachmentsComponent.prototype, "attachmentsList", void 0);
707
- __decorate([
708
- Input("showMatCard")
709
- ], EqpAttachmentsComponent.prototype, "showMatCard", void 0);
710
- __decorate([
711
- Input("multipleAttachment")
712
- ], EqpAttachmentsComponent.prototype, "multipleAttachment", void 0);
713
- __decorate([
714
- Input("loadMultipleFiles")
715
- ], EqpAttachmentsComponent.prototype, "loadMultipleFiles", void 0);
716
- __decorate([
717
- Input("attachmentsColumns")
718
- ], EqpAttachmentsComponent.prototype, "attachmentsColumns", void 0);
719
- __decorate([
720
- Input("emptyTableMessage")
721
- ], EqpAttachmentsComponent.prototype, "emptyTableMessage", void 0);
722
- __decorate([
723
- Input("allowOnlyImages")
724
- ], EqpAttachmentsComponent.prototype, "allowOnlyImages", void 0);
725
- __decorate([
726
- Input("acceptedFileTypes")
727
- ], EqpAttachmentsComponent.prototype, "acceptedFileTypes", void 0);
728
- __decorate([
729
- Input("isDisabled")
730
- ], EqpAttachmentsComponent.prototype, "isDisabled", void 0);
731
- __decorate([
732
- Input("showInlinePreview")
733
- ], EqpAttachmentsComponent.prototype, "showInlinePreview", void 0);
734
- __decorate([
735
- Input("getAttachmentEndpoint")
736
- ], EqpAttachmentsComponent.prototype, "getAttachmentEndpoint", void 0);
737
- __decorate([
738
- Input("productionBaseUrl")
739
- ], EqpAttachmentsComponent.prototype, "productionBaseUrl", void 0);
740
- __decorate([
741
- Input("compressionOptions")
742
- ], EqpAttachmentsComponent.prototype, "compressionOptions", void 0);
743
- __decorate([
744
- Input("allowedTypes")
745
- ], EqpAttachmentsComponent.prototype, "allowedTypes", void 0);
746
- __decorate([
747
- Input("isEqpTableMultiLanguage")
748
- ], EqpAttachmentsComponent.prototype, "isEqpTableMultiLanguage", void 0);
749
- __decorate([
750
- Input("tablePaginatorVisible")
751
- ], EqpAttachmentsComponent.prototype, "tablePaginatorVisible", void 0);
752
- __decorate([
753
- Input("tablePaginatorSize")
754
- ], EqpAttachmentsComponent.prototype, "tablePaginatorSize", void 0);
755
- __decorate([
756
- Input("downloadTooltipPosition")
757
- ], EqpAttachmentsComponent.prototype, "downloadTooltipPosition", void 0);
758
- __decorate([
759
- Input("openLinkLabel")
760
- ], EqpAttachmentsComponent.prototype, "openLinkLabel", void 0);
761
- __decorate([
762
- Input("addButtonLabel")
763
- ], EqpAttachmentsComponent.prototype, "addButtonLabel", void 0);
764
- __decorate([
765
- Input("downloadLabel")
766
- ], EqpAttachmentsComponent.prototype, "downloadLabel", void 0);
767
- __decorate([
768
- Input("deleteLabel")
769
- ], EqpAttachmentsComponent.prototype, "deleteLabel", void 0);
770
- __decorate([
771
- Input("fileNameLabel")
772
- ], EqpAttachmentsComponent.prototype, "fileNameLabel", void 0);
773
- __decorate([
774
- Input("previewLabel")
775
- ], EqpAttachmentsComponent.prototype, "previewLabel", void 0);
776
- __decorate([
777
- Input("uploadFileLabel")
778
- ], EqpAttachmentsComponent.prototype, "uploadFileLabel", void 0);
779
- __decorate([
780
- Input("confirmLabel")
781
- ], EqpAttachmentsComponent.prototype, "confirmLabel", void 0);
782
- __decorate([
783
- Input("abortLabel")
784
- ], EqpAttachmentsComponent.prototype, "abortLabel", void 0);
785
- __decorate([
786
- Input("saveLabel")
787
- ], EqpAttachmentsComponent.prototype, "saveLabel", void 0);
788
- __decorate([
789
- Input("exitLabel")
790
- ], EqpAttachmentsComponent.prototype, "exitLabel", void 0);
791
- __decorate([
792
- Input("eqpTableSearchText")
793
- ], EqpAttachmentsComponent.prototype, "eqpTableSearchText", void 0);
794
- __decorate([
795
- Input("deleteDialogTitle")
796
- ], EqpAttachmentsComponent.prototype, "deleteDialogTitle", void 0);
797
- __decorate([
798
- Input("deleteDialogMessage")
799
- ], EqpAttachmentsComponent.prototype, "deleteDialogMessage", void 0);
800
- __decorate([
801
- Input("noImageSelectedErrorMessage")
802
- ], EqpAttachmentsComponent.prototype, "noImageSelectedErrorMessage", void 0);
803
- __decorate([
804
- Input("wrongTypeSelectedErrorMessage")
805
- ], EqpAttachmentsComponent.prototype, "wrongTypeSelectedErrorMessage", void 0);
806
- __decorate([
807
- Input("videoPreviewErrorMessage")
808
- ], EqpAttachmentsComponent.prototype, "videoPreviewErrorMessage", void 0);
809
- __decorate([
810
- Input("videoPreviewErrorMessage")
811
- ], EqpAttachmentsComponent.prototype, "audioPreviewErrorMessage", void 0);
812
- __decorate([
813
- Output()
814
- ], EqpAttachmentsComponent.prototype, "localEditedAttachments", void 0);
815
- __decorate([
816
- Output()
817
- ], EqpAttachmentsComponent.prototype, "abortAddAttachment", void 0);
818
- __decorate([
819
- Output("downloadAttachment")
820
- ], EqpAttachmentsComponent.prototype, "downloadAttachment", void 0);
821
- __decorate([
822
- Output("onDeleteAttachment")
823
- ], EqpAttachmentsComponent.prototype, "onDeleteAttachment", void 0);
824
- __decorate([
825
- Output("onComponentLoaded")
826
- ], EqpAttachmentsComponent.prototype, "onComponentLoaded", void 0);
827
- __decorate([
828
- ViewChild('dialogAddAttachment', { static: true })
829
- ], EqpAttachmentsComponent.prototype, "dialogAddAttachment", void 0);
830
- __decorate([
831
- ViewChild('dialogAddMultipleAttachment', { static: true })
832
- ], EqpAttachmentsComponent.prototype, "dialogAddMultipleAttachment", void 0);
833
- __decorate([
834
- ViewChild(ImageCropperComponent)
835
- ], EqpAttachmentsComponent.prototype, "imageCropper", void 0);
836
- __decorate([
837
- ViewChild('imageInput')
838
- ], EqpAttachmentsComponent.prototype, "imageInput", void 0);
839
- __decorate([
840
- ViewChild('attachmentTable', { static: false })
841
- ], EqpAttachmentsComponent.prototype, "attachmentTable", void 0);
842
- __decorate([
843
- ViewChild('inlinePreviewTemplate', { static: true })
844
- ], EqpAttachmentsComponent.prototype, "inlinePreviewTemplate", void 0);
845
- __decorate([
846
- ViewChild('dialogPreview', { static: true })
847
- ], EqpAttachmentsComponent.prototype, "dialogPreview", void 0);
848
- EqpAttachmentsComponent = __decorate([
849
- Component({
850
- selector: 'eqp-attachments',
851
- template: "<!-- Se richiesta la gestione multipla mostra il pulsante di aggiunta e la tabella con l'elenco allegati -->\r\n<div *ngIf=\"multipleAttachment == true\">\r\n <mat-card [ngStyle]=\"{ 'box-shadow': showMatCard == false ? 'none' : null }\">\r\n <mat-card-header>\r\n <div class=\"col-md-6\">\r\n <div class=\"text-nowrap eqp-attachments-header-title\" *ngIf=\"showHeader == true\">\r\n {{headerTitle}}\r\n </div>\r\n </div>\r\n <div class=\"col-md-6 text-right\">\r\n <div class=\"row justify-content-end\">\r\n <!-- Template del button per l'aggiunta di un allegato -->\r\n <ng-container *ngTemplateOutlet=\"addAttachmentButton\"></ng-container>\r\n </div>\r\n </div>\r\n </mat-card-header>\r\n <mat-card-content>\r\n <eqp-table #attachmentTable [createMatCard]=\"false\" #table [columns]=\"attachmentsColumns\"\r\n [isMultiLanguage]=\"isEqpTableMultiLanguage\" [data]=\"attachmentsList\"\r\n [paginatorVisible]=\"tablePaginatorVisible\" [matPaginatorSize]=\"tablePaginatorSize\"\r\n [emptyTableMessage]=\"emptyTableMessage\" [searchText]=\"eqpTableSearchText\">\r\n </eqp-table>\r\n </mat-card-content>\r\n </mat-card>\r\n</div>\r\n\r\n<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n<div *ngIf=\"multipleAttachment != true\">\r\n <!-- Template del button per l'aggiunta di un allegato -->\r\n <ng-container *ngTemplateOutlet=\"addAttachmentButton\"></ng-container>\r\n\r\n <button class=\"mb-2 mr-2 eqp-attachments-download-btn\" (click)=\"viewAttachment(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\" color=\"primary\">\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType == AttachmentType.FILE\">download</mat-icon>\r\n <mat-icon *ngIf=\"attachmentsList[0].AttachmentType != AttachmentType.FILE\">open_in_new</mat-icon>\r\n {{attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel}}\r\n </button>\r\n <button class=\"mb-2 mr-2 eqp-attachments-preview-btn\" (click)=\"openPreviewDialog(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button color=\"primary\"\r\n *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0] && (!attachmentsList[0].FileContentType || (!attachmentsList[0].FileContentType.startsWith('video') && !attachmentsList[0].FileContentType.startsWith('audio')))\">\r\n <mat-icon>visibility</mat-icon> {{previewLabel}}\r\n </button>\r\n <button class=\"mb-2 eqp-attachments-delete-btn\" (click)=\"deleteAttachment(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button *ngIf=\"attachmentsList && attachmentsList.length > 0 && attachmentsList[0]\"\r\n [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{deleteLabel}}\r\n </button>\r\n\r\n <div class=\"row\" style=\"margin-top: 10px;\"\r\n *ngIf=\"attachmentsList.length > 0 && attachmentsList[0] && attachmentsList[0].FileDataBase64 && attachmentsList[0].IsImage == true\">\r\n <div class=\"col-sm-12\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{attachmentsList[0].FileDataBase64}}\">\r\n </div>\r\n </div>\r\n </div>\r\n <div class=\"row\" *ngIf=\"attachmentsList.length > 0 && attachmentsList[0] && attachmentsList[0].IsImage != true\">\r\n <div class=\"col-sm-12\">\r\n <mat-form-field>\r\n <mat-label>{{fileNameLabel}}</mat-label>\r\n <input readonly matInput [(ngModel)]=\"attachmentsList[0].FileName\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n<ng-template #dialogAddAttachment>\r\n <div class=\"container-fluid eqp-attachments-dialog-add-container\"\r\n style=\"max-height: 70vh !important; overflow-x: hidden; overflow-y: auto;\">\r\n <form [formGroup]=\"newAttachmentForm\" (ngSubmit)=\"confirmAddAttachment()\" *ngIf=\"newAttachmentForm\">\r\n <div class=\"row\">\r\n <div class=\"header-title-standard\"> {{addButtonLabel}} {{ newAttachment.AttachmentType ==\r\n attachmentType.FILE ?\r\n 'File' : 'Link'}} </div>\r\n </div>\r\n <div class=\"row\" style=\"margin-top: 20px;\">\r\n <div class=\"col-sm-12\" *ngIf=\"newAttachment.AttachmentType == attachmentType.FILE\">\r\n <input #imageInput style=\"display:none;\" id=\"file_attachment\"\r\n name=\"file_attachment\" type=\"file\" (change)=\"onFileInputChange($event)\"\r\n [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\"/>\r\n <button (click)=\"imageInput.click()\" type=\"button\" style=\"margin-left: 10px;\" id=\"file_attachment\"\r\n mat-raised-button color=\"primary\" [disabled]=\"showCropImage == true\"\r\n class=\"mb-2 btn btn-primary eqp-attachments-upload-btn\" *ngIf=\"(loadMultipleFiles != true && !newAttachment.FileDataBase64) || (loadMultipleFiles == true && newMultipleAttachments && newMultipleAttachments.length == 0)\">\r\n <mat-icon>cloud_upload</mat-icon>\r\n {{uploadFileLabel}}\r\n </button>\r\n <button (click)=\"abortFile()\" type=\"button\" style=\"margin-left: 10px;\" mat-raised-button\r\n *ngIf=\"(loadMultipleFiles != true && newAttachment.FileDataBase64) || (loadMultipleFiles == true && newMultipleAttachments && newMultipleAttachments.length > 0)\" class=\"mb-2 eqp-attachments-delete-btn\">\r\n <mat-icon>delete</mat-icon> {{deleteLabel}}\r\n </button>\r\n </div>\r\n <div class=\"col-sm-12\" *ngIf=\"newAttachment.AttachmentType == 2 || (selectedFile && loadMultipleFiles != true)\">\r\n <mat-form-field style=\"width: 100%;\">\r\n <mat-label> {{fileNameLabel}} </mat-label>\r\n <input formControlName=\"name\" matInput [(ngModel)]=\"newAttachment.FileName\">\r\n </mat-form-field>\r\n </div>\r\n <div class=\"col-sm-12\" *ngIf=\"newAttachment.AttachmentType == 2\">\r\n <mat-form-field style=\"width: 100%;\">\r\n <mat-label> Link </mat-label>\r\n <input formControlName=\"path\" required matInput [(ngModel)]=\"newAttachment.FilePath\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- Riporta l'elenco dei nomi dei file caricati contemporaneamente (visibile solo se loadMultipleFiles = TRUE e se ci sono realmente pi\u00F9 file senza link) -->\r\n <div class=\"row\" *ngIf=\"loadMultipleFiles == true && newMultipleAttachments && newMultipleAttachments.length > 0 && newMultipleAttachments[0].AttachmentType != attachmentType.LINK\">\r\n <div class=\"col-12\" *ngFor=\"let attach of newMultipleAttachments\">\r\n <mat-form-field style=\"width: 100%\">\r\n <mat-label> {{fileNameLabel}} </mat-label>\r\n <input disabled matInput [(ngModel)]=\"attach.FileName\" [ngModelOptions]=\"{standalone: true}\">\r\n </mat-form-field>\r\n </div>\r\n </div>\r\n\r\n <!-- Riporta la preview dell'immagine quando \u00E8 richiesto il caricamento MULTIPLO ma \u00E8 stata selezionata una sola immagine (quindi \u00E8 entrato in gioco anche il croppie) -->\r\n <div class=\"row\" *ngIf=\"loadMultipleFiles == true && showCropImage != true && newMultipleAttachments && newMultipleAttachments.length == 1 && newMultipleAttachments[0].IsImage == true\" style=\"margin-top: 10px;\">\r\n <div class=\"col-4\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{newMultipleAttachments[0].FileDataBase64}}\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Riporta la preview dell'immagine quando \u00E8 richiesto il caricamento SINGOLO ed \u00E8 stata selezionata un'immagine -->\r\n <div class=\"row\" *ngIf=\"loadMultipleFiles != true && showCropImage != true && newAttachment.FileDataBase64 && newAttachment.IsImage == true\" style=\"margin-top: 10px;\">\r\n <div class=\"col-4\">\r\n <div class=\"single-attachment-inline-preview-container\">\r\n <img src=\"data:image/png;base64,{{newAttachment.FileDataBase64}}\">\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Richiama il template per le funzionalit\u00E0 del CROPPIE -->\r\n <ng-container [ngTemplateOutlet]=\"croppieTemplate\" [ngTemplateOutletContext]=\"{form: newAttachmentForm}\" *ngIf=\"showCropImage == true\"></ng-container>\r\n\r\n <div class=\"row mt-2\">\r\n <div class=\"col-sm-12 text-right\">\r\n <button class=\"btn btn-primary mat-raised-button eqp-attachments-save-btn mr-2\" type=\"submit\"\r\n [disabled]=\"showCropImage == true || (loadMultipleFiles != true && newAttachmentForm?.disabled == true) || disableSave()\">\r\n {{saveLabel}}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-exit-btn\" (click)=\"close()\"\r\n [disabled]=\"showCropImage == true\" type=\"button\">\r\n {{exitLabel}}\r\n </button>\r\n </div>\r\n </div>\r\n </form>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n <div class=\"inline-preview-container\" *ngIf=\"row.AttachmentType != AttachmentType.LINK && row.IsImage\" (click)=\"openPreviewDialog(row)\">\r\n <img src=\"data:image/png;base64,{{row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64}}\">\r\n </div>\r\n <div class=\"inline-preview-container\" *ngIf=\"row.AttachmentType != AttachmentType.LINK && !row.IsImage\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"container-fluid\" style=\"max-height: 70vh !important;\" *ngIf=\"selectedAttachment\">\r\n <div class=\"row\">\r\n <div class=\"header-title-standard\">\r\n {{previewLabel}} {{ selectedAttachment?.AttachmentType == attachmentType.FILE ? 'File' : 'Link'}}\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mt-2\">\r\n <!-- ANTEPRIMA IMMAGINE -->\r\n <div class=\"col-12 text-center preview-container\" *ngIf=\"selectedAttachment.IsImage\">\r\n <img class=\"image-preview\"\r\n src=\"data:image/png;base64,{{selectedAttachment.FileDataBase64 ? selectedAttachment.FileDataBase64 : selectedAttachment.FileThumbnailBase64}}\">\r\n </div>\r\n\r\n <!-- ANTEPRIMA LINK -->\r\n <div class=\"col-12 preview-container\" *ngIf=\"!selectedAttachment.IsImage\">\r\n <iframe class=\"link-preview\" [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n </div>\r\n\r\n <div class=\"row mt-3\">\r\n <div class=\"col-sm-12 text-right\">\r\n <button class=\"btn btn-primary mat-raised-button eqp-attachments-save-btn mr-2\" type=\"submit\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n *ngIf=\"selectedAttachment.AttachmentType != AttachmentType.LINK\">\r\n {{downloadLabel}}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-exit-btn\" mat-dialog-close type=\"button\"\r\n (click)=\"selectedAttachment = null\">\r\n {{exitLabel}}\r\n </button>\r\n </div>\r\n </div>\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\r\n <!-- \r\n Pulsanti per l'aggiunta di un file o un link. Ne viene visualizzato uno se:\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK) \r\n e sono nella gestione di pi\u00F9 allegati (multipleAttachment == true)\r\n OPPURE\r\n - gli allowedTypes sono stati specificati, nell'array ne \u00E8 presente uno solo, quello inserito \u00E8 AttachmentType.FILE (o AttachmentType.LINK) \r\n e sono nella gestione di un singolo allegato (multipleAttachment == true) e non ne \u00E8 ancora stato selezionato uno (ovvero attachmentsList non esiste o non ha elementi)\r\n -->\r\n <button class=\"btn btn-primary mb-4 mr-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n *ngIf=\"allowedTypes && allowedTypes.length == 1 && (multipleAttachment == true || (!attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0])))\"\r\n (click)=\"openModalAddAttachment(allowedTypes[0])\" [disabled]=\"isDisabled\">\r\n <!-- Per l'aggiunta dei file mostro un'icona diversa dall'aggiunta dei link -->\r\n <mat-icon *ngIf=\"allowedTypes[0] == 1\">cloud_upload</mat-icon>\r\n <i class=\"fas fa-link\" *ngIf=\"allowedTypes[0] == 2\"></i>\r\n <span style=\"margin-left: 10px;\">{{addButtonLabel}} {{allowedTypes[0] == 1 ? \"file\" : \"link\"}}</span>\r\n </button>\r\n\r\n\r\n <!-- Pulsante per aprire il menu per la scelta del tipo di Attachment da creare -->\r\n <button class=\"btn btn-primary mb-4 mr-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\" [disabled]=\"isDisabled\"\r\n *ngIf=\"allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true || (!attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0])))\">\r\n <mat-icon *ngIf=\"multipleAttachment != true\">cloud_upload</mat-icon>\r\n <mat-icon *ngIf=\"multipleAttachment == true\">add</mat-icon>\r\n <span style=\"margin-left: 0px;\"> {{addButtonLabel}} </span>\r\n </button>\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"openModalAddAttachment(1)\" class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px;\">File</span>\r\n </button>\r\n <button mat-menu-item (click)=\"openModalAddAttachment(2)\" 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 </mat-menu>\r\n</ng-template>\r\n\r\n\r\n<ng-template #croppieTemplate let-form=\"form\">\r\n <div class=\"row mt-2 mb-2\" [formGroup]=\"form\">\r\n <div class=\"col-md-12 d-flex align-items-center justify-content-center\">\r\n <span class=\"mr-1\">Max H(px):</span>\r\n <mat-form-field>\r\n <input formControlName=\"customHeight\" type=\"number\" matInput [(ngModel)]=\"customHeight\"\r\n (change)=\"onDimensionsChange('H')\">\r\n </mat-form-field>\r\n\r\n <span class=\"ml-2 mr-1\">Max W(px):</span>\r\n <mat-form-field>\r\n <input formControlName=\"customWidth\" type=\"number\" matInput [(ngModel)]=\"customWidth\"\r\n (change)=\"onDimensionsChange('W')\">\r\n </mat-form-field>\r\n\r\n <button class=\"btn btn-primary mat-raised-button ml-2\" (click)=\"restoreOriginalDimensions()\"\r\n [disabled]=\"customWidth == originalWidth && customHeight == originalHeight\">\r\n <mat-icon style=\"vertical-align: middle;\">replay</mat-icon>\r\n </button>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center\">\r\n <div style=\"max-height: 450px; max-width: 450px;\">\r\n <image-cropper [imageChangedEvent]=\"imageChangedEvent\" [maintainAspectRatio]=\"false\"\r\n [autoCrop]=\"false\" [containWithinAspectRatio]=\"false\" [aspectRatio]=\"4/3\"\r\n [cropperMinWidth]=\"128\" [onlyScaleDown]=\"true\" [roundCropper]=\"false\" [canvasRotation]=\"0\"\r\n [transform]=\"transform\" [alignImage]=\"'left'\" format=\"png\" (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\" [resizeToHeight]=\"customHeight\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n <div class=\"row justify-content-center mt-2\">\r\n <div style=\"max-height: 450px; max-width: 450px;\">\r\n <button class=\"btn btn-primary mat-raised-button eqp-attachments-confirm-btn mr-2\" type=\"button\"\r\n (click)=\"confirmCrop()\">\r\n {{confirmLabel}}\r\n </button>\r\n <button class=\"btn mat-raised-button eqp-attachments-abort-btn\" type=\"button\" (click)=\"abortFile()\">\r\n {{abortLabel}}\r\n </button>\r\n </div>\r\n </div>\r\n</ng-template>",
852
- styles: [".eqp-attachments-header-title{font-weight:700;font-size:19px;line-height:24px;margin-bottom:auto}.single-attachment-inline-preview-container{max-height:400px;max-width:400px;display:flex;align-items:center}.single-attachment-inline-preview-container img{max-width:100%;max-height:120px}.inline-preview-container{max-height:100px;max-width:100px;display:flex;align-items:center;justify-content:center;width:100%;cursor:pointer}.inline-preview-container img{max-width:100%;max-height:100px}.inline-preview-container i{font-size:25px;margin:auto}.preview-container{max-height:60vh;max-width:100%}.preview-container .image-preview{max-width:100%;max-height:100%}.preview-container .link-preview{width:70vw;height:55vh}"]
853
- })
854
- ], EqpAttachmentsComponent);
855
- export { EqpAttachmentsComponent };
856
- export { ɵ0 };
857
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXFwLWF0dGFjaG1lbnRzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL0BlcXByb2plY3QvZXFwLWF0dGFjaG1lbnRzLyIsInNvdXJjZXMiOlsibGliL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsaUJBQWlCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pJLE9BQU8sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxZQUFZLEVBQXFCLHFCQUFxQixFQUFrQixNQUFNLG1CQUFtQixDQUFDO0FBQzNHLE9BQU8sZ0JBQWdCLE1BQU0sMkJBQTJCLENBQUE7QUFDeEQsT0FBTyxFQUFFLGNBQWMsRUFBa0IsTUFBTSwwQkFBMEIsQ0FBQztBQUMxRSxPQUFPLEVBQW1DLG1CQUFtQixFQUFFLFVBQVUsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3hHLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDbkUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDdEUsT0FBTyxFQUFFLDBCQUEwQixFQUFFLE1BQU0sMENBQTBDLENBQUM7QUFDdEYsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUdsRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksT0FBTyxDQUFTLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBQy9ELE1BQU0sTUFBTSxHQUFHLElBQUksVUFBVSxFQUFFLENB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QUt4RztJQUFULE1BQU0sRUFBRTttRUFBaUU7QUFLNUM7SUFBN0IsTUFBTSxDQUFDLG9CQUFvQixDQUFDO21FQUF1RjtBQUt0RjtJQUE3QixNQUFNLENBQUMsb0JBQW9CLENBQUM7bUVBQXVGO0FBU3ZGO0lBQTVCLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQztrRUFBd0c7QUFhaEY7SUFBbkQsU0FBUyxDQUFDLHFCQUFxQixFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDO29FQUF1QztBQUM5QjtJQUEzRCxTQUFTLENBQUMsNkJBQTZCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUM7NEVBQStDO0FBT3hFO0lBQWpDLFNBQVMsQ0FBQyxxQkFBcUIsQ0FBQzs2REFBcUM7QUFDN0M7SUFBeEIsU0FBUyxDQUFDLFlBQVksQ0FBQzsyREFBaUI7QUFXUTtJQUFoRCxTQUFTLENBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUM7Z0VBQW9DO0FBQzlCO0lBQXJELFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQztzRUFBeUM7QUFDaEQ7SUFBN0MsU0FBUyxDQUFDLGVBQWUsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQzs4REFBaUM7QUE3TW5FLHVCQUF1QjtJQUxuQyxTQUFTLENBQUM7UUFDVCxRQUFRLEVBQUUsaUJBQWlCO1FBQzNCLG12akJBQStDOztLQUVoRCxDQUFDO0dBQ1csdUJBQXVCLENBbXlCbkM7U0FueUJZLHVCQUF1QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEFmdGVyVmlld0luaXQsIENoYW5nZURldGVjdG9yUmVmLCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5wdXQsIE9uSW5pdCwgT3V0cHV0LCBUZW1wbGF0ZVJlZiwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IEZvcm1CdWlsZGVyLCBGb3JtR3JvdXAsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IGJhc2U2NFRvRmlsZSwgSW1hZ2VDcm9wcGVkRXZlbnQsIEltYWdlQ3JvcHBlckNvbXBvbmVudCwgSW1hZ2VUcmFuc2Zvcm0gfSBmcm9tICduZ3gtaW1hZ2UtY3JvcHBlcic7XHJcbmltcG9ydCBpbWFnZUNvbXByZXNzaW9uIGZyb20gJ2Jyb3dzZXItaW1hZ2UtY29tcHJlc3Npb24nXHJcbmltcG9ydCB7IEF0dGFjaG1lbnRUeXBlLCBJQXR0YWNobWVudERUTyB9IGZyb20gJy4vaW50ZXJmYWNlcy9JQXR0YWNobWVudCc7XHJcbmltcG9ydCB7IENvbmZpZ0NvbHVtbiwgRXFwVGFibGVDb21wb25lbnQsIFRvb2x0aXBQb3NpdGlvblR5cGUsIFR5cGVDb2x1bW4gfSBmcm9tICdAZXFwcm9qZWN0L2VxcC10YWJsZSc7XHJcbmltcG9ydCB7IE1hdERpYWxvZywgTWF0RGlhbG9nUmVmIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcclxuaW1wb3J0IHsgQXR0YWNobWVudEhlbHBlclNlcnZpY2UgfSBmcm9tICcuL2hlbHBlcnMvYXR0YWNobWVudC5oZWxwZXInO1xyXG5pbXBvcnQgeyBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZSB9IGZyb20gJy4vc2VydmljZXMvZXFwLWF0dGFjaG1lbnQtZGlhbG9nLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBEb21TYW5pdGl6ZXIgfSBmcm9tICdAYW5ndWxhci9wbGF0Zm9ybS1icm93c2VyJztcclxuaW1wb3J0IHsgSHR0cENsaWVudCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHsgSU9wdGlvbnMgfSBmcm9tICcuL2ludGVyZmFjZXMvSU9wdGlvbnMnO1xyXG5cclxuY29uc3QgdG9CYXNlNjQgPSBmaWxlID0+IG5ldyBQcm9taXNlPHN0cmluZz4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgcmVhZGVyLnJlYWRBc0RhdGFVUkwoZmlsZSk7XHJcbiAgcmVhZGVyLm9ubG9hZCA9ICgpID0+IHJlc29sdmUocmVhZGVyLnJlc3VsdC50b1N0cmluZygpKTtcclxuICByZWFkZXIub25lcnJvciA9IGVycm9yID0+IHJlamVjdChlcnJvcik7XHJcbn0pO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdlcXAtYXR0YWNobWVudHMnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9lcXAtYXR0YWNobWVudHMuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2VxcC1hdHRhY2htZW50cy5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBFcXBBdHRhY2htZW50c0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgQWZ0ZXJWaWV3SW5pdCB7XHJcblxyXG4gIC8vI3JlZ2lvbiBASW5wdXQgZGVsIGNvbXBvbmVudGVcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgbmFzY29uZGUgbGEgY29sb25uYSBwZXIgbGUgYXppb25pIHN1bGwnYWxsZWdhdG8gKG5lbCBjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZGlzYWJsZUFjdGlvblwiKSBkaXNhYmxlQWN0aW9uOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNlIFRSVUUgbW9zdHJhIGlsIHRpdG9sbyBuZWxsJ2hlYWRlciBuZWwgY2FzbyBpbiBjdWkgXCJtdWx0aXBsZUF0dGFjaG1lbnRcIiDDqCBUUlVFIChcIkVsZW5jbyBhbGxlZ2F0aVwiIGRpIGRlZmF1bHQpLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInNob3dIZWFkZXJcIikgc2hvd0hlYWRlcjogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIFRpdG9sbyBkYSB2aXN1YWxpenphcmUgc2UgaWwgcGFyYW1ldHJvIFwic2hvd0hlYWRlclwiIMOoIFRSVUUuIERpIGRldmF1bHQgdmllbmUgdmlzdWFsaXp6YXRvIFwiRWxlbmNvIGFsbGVnYXRpXCIuXHJcbiAgICovXHJcbiAgQElucHV0KFwiaGVhZGVyVGl0bGVcIikgaGVhZGVyVGl0bGU6IHN0cmluZyA9IFwiRWxlbmNvIGFsbGVnYXRpXCI7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNvcmdlbnRlIGRhdGkgZGEgdmlzdWFsaXp6YXJlLiBOZWwgY2FzbyBzaSB2dW9sZSBnZXN0aXJlIHVuIHNpbmdvbG8gYWxsZWdhdG8gdmEgcGFzc2F0byBpbiBvZ25pIGNhc28gY29tZSBBcnJheS5cclxuICAgKi9cclxuICBASW5wdXQoXCJhdHRhY2htZW50c0xpc3RcIikgYXR0YWNobWVudHNMaXN0OiBBcnJheTxJQXR0YWNobWVudERUTz4gPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIG5vbiBtb3N0cmEgbGEgTWF0Q2FyZCAobmVsIGNhc28gaW4gY3VpIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwic2hvd01hdENhcmRcIikgc2hvd01hdENhcmQ6IGJvb2xlYW4gPSB0cnVlO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBGQUxTRSBhbGxvcmEgaWwgY29tcG9uZW50ZSBtb3N0cmEgc29sbyBpbCBwdWxzYW50ZSBkaSBjYXJpY2FtZW50byBkaSB1biBzaW5nb2xvIGZpbGUsIHVuYSB2b2x0YSBjYXJpY2F0byBpbCBmaWxlIGludm9jYSBsJ2V2ZW50byBkaSBvdXRwdXQgXCJsb2NhbEVkaXRlZEF0dGFjaG1lbnRzXCIuXHJcbiAgICogU2UgVFJVRSBhbGxvcmEgaWwgY29tcG9uZW50ZSBtb3N0cmEgbCdlbGVuY28gZGkgdHV0dGkgZ2xpIGFsbGVnYXRpIHJpY2V2dXRvIG5lbCBwYXJhbWV0cm8gXCJhdHRhY2htZW50c0xpc3RcIi5cclxuICAgKi9cclxuICBASW5wdXQoXCJtdWx0aXBsZUF0dGFjaG1lbnRcIikgbXVsdGlwbGVBdHRhY2htZW50OiBib29sZWFuID0gdHJ1ZTtcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgYXNzdW1lIGlsIHZhbG9yZSBUUlVFIGFsbG9yYSBzYXLDoCBwb3NzaWJpbGUgY2FyaWNhcmUgcGnDuSBmaWxlIHBlciB2b2x0YS4gUXVlc3RhIGZ1bnppb25hbGl0w6Agw6ggYXR0aXZhXHJcbiAgICogU09MTyBzZSBzaSBnZXN0aXNjb25vIGFsbGVnYXRpIG11bHRpcGxpLCBxdWluZGkgc2UgbCdpbnB1dCAnbXVsdGlwbGVBdHRhY2htZW50JyBhc3N1bWUgaWwgdmFsb3JlIFRSVUUsIGFsdHJpbWVudGkgw6ggc2VtcHJlIGRpc2FiaWxpdGF0YS5cclxuICAgKi9cclxuICBASW5wdXQoXCJsb2FkTXVsdGlwbGVGaWxlc1wiKSBsb2FkTXVsdGlwbGVGaWxlczogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBDb25maWd1cmF6aW9uZSBkZWxsZSBjb2xvbm5lIGRlbGxhIGVxcC10YWJsZSBwZXIgbGEgdmlzdWFsaXp6YXppb25lIGRlZ2xpIGFsbGVnYXRpIChjYXNvIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkuXHJcbiAgICovXHJcbiAgQElucHV0KFwiYXR0YWNobWVudHNDb2x1bW5zXCIpIGF0dGFjaG1lbnRzQ29sdW1uczogQXJyYXk8Q29uZmlnQ29sdW1uPiA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIEltcG9zdGEgaWwgbWVzc2FnZ2lvIGRhIHZpc3VhbGl6emFyZSBuZWwgY2FzbyBpbiBjdWkgbGEgdGFiZWxsYSBkZWdsaSBhbGxlZ2F0aSAobmVsIGNhc28gaW4gY3VpIFwibXVsdGlwbGVBdHRhY2htZW50XCIgw6ggVFJVRSkgw6ggdnVvdGEuXHJcbiAgICovXHJcbiAgQElucHV0KFwiZW1wdHlUYWJsZU1lc3NhZ2VcIikgZW1wdHlUYWJsZU1lc3NhZ2U6IHN0cmluZyA9IFwiTmVzc3VuIGRhdG8gdHJvdmF0b1wiO1xyXG5cclxuICAvKipcclxuICAgKiBTZSBUUlVFIGFsbG9yYSBwZXJtZXR0ZSBkaSBzZWxlemlvbmFyZSBzb2x0YW50byBmaWxlIGRpIHRpcG8gaW1tYWdpbmUsIGF2ZW50ZSB1bm8gZGVpIG1pbWV0eXBlXHJcbiAgICogc3BlY2lmaWNhdGkgZGVudHJvIEF0dGFjaG1lbnRIZWxwZXJTZXJ2aWNlLlxyXG4gICAqIFNlIEZBTFNFIHBlcm1ldHRlIGRpIHNlbGV6aW9uYXJlIHF1YWxzaWFzaSB0aXBvIGRpIGZpbGVcclxuICAgKi9cclxuICBASW5wdXQoXCJhbGxvd09ubHlJbWFnZXNcIikgYWxsb3dPbmx5SW1hZ2VzOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIC8qKlxyXG4gICAqIFNwZWNpZmljYSBpIHRpcGkgZGkgZmlsZSBjaGUgw6ggcG9zc2liaWxlIGNhcmljYXJlXHJcbiAgICovXHJcbiAgQElucHV0KFwiYWNjZXB0ZWRGaWxlVHlwZXNcIikgYWNjZXB0ZWRGaWxlVHlwZXM6IHN0cmluZztcclxuXHJcbiAgLyoqXHJcbiAgICogU2UgVFJVRSBkaXNhYmlsaXRhIGlsIHB1bHNhbnRlIGRpIEFnZ2l1bnRhIGFsbGVnYXRvIChhIHByZXNjaW5kZXJlIGRhbCB2YWxvcmUgZGVsIHBhcmFtZXRybyBcIm11bHRpcGxlQXR0YWNobWVudFwiKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJpc0Rpc2FibGVkXCIpIGlzRGlzYWJsZWQ6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogTW9zdHJhL25hc2NvbmRlIGxhIGNvbG9ubmEgcGVyIHZpc3VhbGl6emFyZSBsJ2FudGVwcmltYSBkZWkgZmlsZSBuZWxsYSB0YWJlbGxhIChjYXNvIG11bHRpcGxlQXRhdGNobWVudHMgPSB0cnVlKS5cclxuICAgKi9cclxuICBASW5wdXQoXCJzaG93SW5saW5lUHJldmlld1wiKSBzaG93SW5saW5lUHJldmlldzogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICAvKipcclxuICAgKiBFbmRwb2ludCBkYSBjaGlhbWFyZSBwZXIgcmVjdWVwcmFyZSBsJ0lBdHRhY2htZW50RFRPIGNvbXBsZXRvIGRhIHZlZGVyZSBuZWxsJ2FudGVwcmltYS4gTGEgY2hpYW1hdGEgc2Fyw6AgaW4gUE9TVCBlIG5lbCBib2R5XHJcbiAgICogY29udGVycsOgIGwnSUF0dGFjaG1lbnREVE8gc2VsZXppb25hdG8gZGFsbCd1dGVudGUuXHJcbiAgICogTGEgY2hpYW1hdGEgdmllbmUgZXNlZ3VpdGEgc29sbyBwZXIgbCdhbnRlcHJpbWEgZGVsbGUgaW1tYWdpbmkgZXNzZW5kbyBuZWNlc3NhcmlvIGlsIGJhc2U2NCBjb21wbGV0byBkZWxsJ2ltbWFnaW5lIGEgZGltZW5zaW9uZSByZWFsZS5cclxuICAgKiBQZXIgZG9jdW1lbnRpL2xpbmsgYmFzdGEgY2hlIHNpYSBwb3BvbGF0YSBsYSBwcm9wcmlldMOgIEZpbGVQYXRoIGRpIElBdHRhY2htZW50RFRPLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcImdldEF0dGFjaG1lbnRFbmRwb2ludFwiKSBnZXRBdHRhY2htZW50RW5kcG9pbnQ6IHN0cmluZyA9IG51bGw7XHJcblxyXG4gIC8qKlxyXG4gICAqIEhvc3RuYW1lIGRlbGwnYW1iaWVudGUgZGkgcHJvZHV6aW9uZSBkZWxsJ2FwcGxpY2F0aXZvLiBOZWNlc3NhcmlvIHBlciB2aXN1YWxpenphcmUgbCdhbnRlcHJpbWEgZGVpIGRvY3VtZW50aVxyXG4gICAqIHRyYW1pdGUgaWwgdmlld2VyIGRpIGdvb2dsZS5cclxuICAgKiBOT1RBOiBQZXIgdmlzdWFsaXp6YXJlIGwnYW50ZXByaW1hIMOoIG5lY2Vzc2FyaW8gY2hlIGxhIHByb3JpZXTDoCBGaWxlUGF0aCBkZWxsJ0lBdHRhY2htZW50RFRPIHNpYSBwb3BvbGF0YSBlIGNoZVxyXG4gICAqIHNpYSBhYmlsaXRhdG8gbCdhY2Nlc3NvIGFsbGEgY2FydGVsbGEgc3VsIHNlcnZlciB0cmFtaXRlIGhvc3RuYW1lLlxyXG4gICAqL1xyXG4gIEBJbnB1dChcInByb2R1Y3Rpb25CYXNlVXJsXCIpIHByb2R1Y3Rpb25CYXNlVXJsOiBzdHJpbmcgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBPcHppb25pIHBlciBsYSBjb21wcmVzc2lvbmUgZGVsbGUgaW1tYWdpbmkgY2FyaWNhdGUuXHJcbiAgICovXHJcbiAgQElucHV0KFwiY29tcHJlc3Npb25PcHRpb25zXCIpIGNvbXByZXNzaW9uT3B0aW9uczogSU9wdGlvbnMgPSB7IG1heFNpemVNQjogMC41LCBtYXhXaWR0aE9ySGVpZ2h0OiAxOTIwLCB1c2VXZWJXb3JrZXI6IHRydWUgfTtcclxuXHJcbiAgLyoqXHJcbiAgICogQXJyYXkgZGkgQXR0YWNobWVudFR5cGUgY2hlIHNpIHBvc3Nvbm8gYWdnaXVuZ2VyZVxyXG4gICAqL1xyXG4gIEBJbnB1dChcImFsbG93ZWRUeXBlc1wiKSBhbGxvd2VkVHlwZXM6IEFycmF5PEF0dGFjaG1lbnRUeXBlPiA9IFtBdHRhY2htZW50VHlwZS5GSUxFLCBBdHRhY2htZW50VHlwZS5MSU5LXTtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc3RhYmlsaXJlIHNlIGxhIGVxcC10YWJsZSBjb250ZW5lbnRlIGwnZWxlbmNvIGRlZ2xpIGFsbGVnYXRpIHV0aWxpenphXHJcbiAgICogaWwgbXVsdGlsaW5ndWEgb3BwdXJlIG5vXHJcbiAgICovXHJcbiAgQElucHV0KFwiaXNFcXBUYWJsZU11bHRpTGFuZ3VhZ2VcIikgaXNFcXBUYWJsZU11bHRpTGFuZ3VhZ2U6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgLyoqXHJcbiAgICogUGVybWV0dGUgZGkgc3RhYmlsaXJlLCBpbiBjYXNvIGRpIGdlc3Rpb25lIGFsbGVnYXRpIG11bHRpcGxpLCBzZSBsYSB0YWJlbGxhIGNvbnRlbmVudGUgbCdlbGVuY28gXHJcbiAgICogZGVnbGkgYWxsZWdhdGkgZGV2ZSBlc3NlcmUgcGFnaW5hdGEgb3BwdXJlIG5vXHJcbiAgICovXHJcbiAgQElucHV0KFwidGFibGVQYWdpbmF0b3JWaXNpYmxlXCIpIHRhYmxlUGFnaW5hdG9yVmlzaWJsZTogYm9vbGVhbiA9IHRydWU7XHJcblxyXG4gIC8qKlxyXG4gICAqIEluIGNhc28gZGkgZ2VzdGlvbmUgYWxsZWdhdGkgbXVsdGlwbGksIHBlcm1ldHRlIGRpIHN0YWJpbGlyZSBsYSBkaW1lbnNpb25lIHBhZ2luYSBkaSBkZWZhdWx0IFxyXG4gICAqIHBlciBsYSB0YWJlbGxhIGNvbnRlbmVudGUgbCdlbGVuY28gZGVnbGkgYWxsZWdhdGlcclxuICAgKi9cclxuICBASW5wdXQoXCJ0YWJsZVBhZ2luYXRvclNpemVcIikgdGFibGVQYWdpbmF0b3JTaXplOiBudW1iZXIgPSBudWxsO1xyXG5cclxuICAvKipcclxuICAgKiBJbnB1dCBwZXIgZGVmaW5pcmUgbGUgbGFiZWwgZGEgdXNhcmUgbmVsIGNvbXBvbmVudGVcclxuICAgKi9cclxuICBASW5wdXQoXCJkb3dubG9hZFRvb2x0aXBQb3NpdGlvblwiKSBkb3dubG9hZFRvb2x0aXBQb3NpdGlvbjogVG9vbHRpcFBvc2l0aW9uVHlwZSA9IFRvb2x0aXBQb3NpdGlvblR5cGUuQmVsb3c7XHJcbiAgQElucHV0KFwib3BlbkxpbmtMYWJlbFwiKSBvcGVuTGlua0xhYmVsOiBzdHJpbmcgPSBcIkFwcmkgbGlua1wiO1xyXG4gIEBJbnB1dChcImFkZEJ1dHRvbkxhYmVsXCIpIGFkZEJ1dHRvbkxhYmVsOiBzdHJpbmcgPSBcIkFnZ2l1bmdpXCI7XHJcbiAgQElucHV0KFwiZG93bmxvYWRMYWJlbFwiKSBkb3dubG9hZExhYmVsOiBzdHJpbmcgPSBcIkRvd25sb2FkXCI7XHJcbiAgQElucHV0KFwiZGVsZXRlTGFiZWxcIikgZGVsZXRlTGFiZWw6IHN0cmluZyA9IFwiRWxpbWluYVwiO1xyXG4gIEBJbnB1dChcImZpbGVOYW1lTGFiZWxcIikgZmlsZU5hbWVMYWJlbDogc3RyaW5nID0gXCJOb21lIGZpbGVcIjtcclxuICBASW5wdXQoXCJwcmV2aWV3TGFiZWxcIikgcHJldmlld0xhYmVsOiBzdHJpbmcgPSBcIkFudGVwcmltYVwiO1xyXG4gIEBJbnB1dChcInVwbG9hZEZpbGVMYWJlbFwiKSB1cGxvYWRGaWxlTGFiZWw6IHN0cmluZyA9IFwiQ2FyaWNhIGZpbGVcIjtcclxuICBASW5wdXQoXCJjb25maXJtTGFiZWxcIikgY29uZmlybUxhYmVsOiBzdHJpbmcgPSBcIkNvbmZlcm1hXCI7XHJcbiAgQElucHV0KFwiYWJvcnRMYWJlbFwiKSBhYm9ydExhYmVsOiBzdHJpbmcgPSBcIkFubnVsbGFcIjtcclxuICBASW5wdXQoXCJzYXZlTGFiZWxcIikgc2F2ZUxhYmVsOiBzdHJpbmcgPSBcIlNhbHZhXCI7XHJcbiAgQElucHV0KFwiZXhpdExhYmVsXCIpIGV4aXRMYWJlbDogc3RyaW5nID0gXCJFc2NpXCI7XHJcbiAgQElucHV0KFwiZXFwVGFibGVTZWFyY2hUZXh0XCIpIGVxcFRhYmxlU2VhcmNoVGV4dDogc3RyaW5nID0gXCJDZXJjYVwiO1xyXG4gIEBJbnB1dChcImRlbGV0ZURpYWxvZ1RpdGxlXCIpIGRlbGV0ZURpYWxvZ1RpdGxlOiBzdHJpbmcgPSBudWxsO1xyXG4gIEBJbnB1dChcImRlbGV0ZURpYWxvZ01lc3NhZ2VcIikgZGVsZXRlRGlhbG9nTWVzc2FnZTogc3RyaW5nID0gXCJTZWkgc2ljdXJvIGRpIHZvbGVyIGNhbmNlbGxhcmUgcXVlc3QnYWxsZWdhdG8/XCI7XHJcbiAgQElucHV0KFwibm9JbWFnZVNlbGVjdGVkRXJyb3JNZXNzYWdlXCIpIG5vSW1hZ2VTZWxlY3RlZEVycm9yTWVzc2FnZTogc3RyaW5nID0gXCJOb24gw6ggcG9zc2liaWxlIHNlbGV6aW9uYXJlIHVuIGZpbGUgY2hlIG5vbiBzaWEgdW4naW1tYWdpbmUuXCI7XHJcbiAgQElucHV0KFwid3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2VcIikgd3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2U6IHN0cmluZyA9IFwiTm9uIMOoIHBvc3NpYmlsZSBjYXJpY2FyZSBpbCBmaWxlIHNlbGV6aW9uYXRvLlwiO1xyXG4gIEBJbnB1dChcInZpZGVvUHJldmlld0Vycm9yTWVzc2FnZVwiKSB2aWRlb1ByZXZpZXdFcnJvck1lc3NhZ2U6IHN0cmluZyA9IFwiSW1wb3NzaWJpbGUgYXByaXJlIGwnYW50ZXByaW1hIGRpIHVuIGZpbGUgdmlkZW8uXCI7XHJcbiAgQElucHV0KFwidmlkZW9QcmV2aWV3RXJyb3JNZXNzYWdlXCIpIGF1ZGlvUHJldmlld0Vycm9yTWVzc2FnZTogc3RyaW5nID0gXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGkgdW4gZmlsZSBhdWRpby5cIjtcclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIEBPdXRwdXQgZGVsIGNvbXBvbmVudGVcclxuXHJcbiAgLyoqXHJcbiAgICogUmVzdGl0dWlzY2UgbGEgbGlzdGEgYWdnaW9ybmF0YSBkZWdsaSBhbGxlZ2F0aS5cclxuICAgKi9cclxuICBAT3V0cHV0KCkgbG9jYWxFZGl0ZWRBdHRhY2htZW50czogRXZlbnRFbWl0dGVyPEFycmF5PElBdHRhY2htZW50RFRPPj4gPSBuZXcgRXZlbnRFbWl0dGVyPEFycmF5PElBdHRhY2htZW50RFRPPj4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnRvIHNjYXRlbmF0byBhbGxhIHByZXNzaW9uZSBkZWwgcHVsc2FudGUgRVNDSSBkZWxsYSBtb2RhbGUgZGkgY2FyaWNhbWVudG8gZmlsZS5cclxuICAgKi9cclxuICBAT3V0cHV0KCkgYWJvcnRBZGRBdHRhY2htZW50OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsJ0lBdHRhY2htZW50RFRPIHNlbGV6aW9uYXRvIHBlciBpbCBkb3dubG9hZCBuZWwgY2FzbyBGaWxlRGF0YUJhc2U2NCwgRmlsZUNvbnRlbnRUeXBlIG8gRmlsZU5hbWUgbm9uIGZvc3Nlcm8gc3BlY2lmaWNhdGkuXHJcbiAgICovXHJcbiAgQE91dHB1dChcImRvd25sb2FkQXR0YWNobWVudFwiKSBkb3dubG9hZEF0dGFjaG1lbnQ6IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4gPSBuZXcgRXZlbnRFbWl0dGVyPElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAvKipcclxuICAgKiBFdmVudG8gZGkgb3V0cHV0IGNoZSByZXN0aXR1aXNjZSBsJ2VsZW1lbnRvIGVsaW1pbmF0byBwcmltYSBjaGUgcXVlc3RvIHZlbmdhIGVmZmV0dGl2YW1lbnRlIHJpc21vc3NvIGRhbGxhIGxpc3RhLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoXCJvbkRlbGV0ZUF0dGFjaG1lbnRcIikgb25EZWxldGVBdHRhY2htZW50OiBFdmVudEVtaXR0ZXI8SUF0dGFjaG1lbnREVE8+ID0gbmV3IEV2ZW50RW1pdHRlcjxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgLyoqXHJcbiAgICogRXZlbnRvIGRpIG91dHB1dCBzY2F0ZW5hdG8gZHVyYW50ZSBsJ0FmdGVyVmlld0luaXQgZGVsIGNvbXBvbmVudGUgY2hlIHJlc3RpdHVpc2NlIGwnaXN0YW56YSBjb3JyZW50ZSBkZWwgY29tcG9uZW50ZS5cclxuICAgKiBRdWVzdG8gZXZlbnRvIGF2dmlzYSBxdWFuZG8gaWwgY29tcG9uZW50ZSDDqCBzdGF0byByZW5kZXJpenphdG8sIHV0aWxlIHBlciBlc2VtcGlvIHF1YW5kbyBzaSB2b2dsaW9ubyBhZ2dpdW5nZXJlIGRlbGxlIGNvbG9ubmUgXHJcbiAgICogYWxsYSB2aXN1YWxpenphemlvbmUgY29uIGFsbGVnYXRpIG11bHRpcGxpIGxhc2NpYW5kbyBwZXLDsiBxdWVsbGUgcHJlIGVzaXN0ZW50aS4gUXVlc3RvIHNpIHB1w7IgZmFyZSBpbnRlcnZlbmVuZG8gc3VsbGEgXHJcbiAgICogcHJvcHJpZXTDoCBcImF0dGFjaG1lbnRzQ29sdW1uc1wiIGRpIHF1ZXN0byBjb21wb25lbnRlIHRyYW1pdGUgbCdpc3RhbnphIHBhc3NhdGEgY29tZSBwYXJhbWVudHJvIG9wcHVyZSB0cmFtaXRlIFZpZXdDaGlsZCBcclxuICAgKiBkYWwgY29tcG9uZW50ZSBjaGUgbG8gb3NwaXRhLlxyXG4gICAqL1xyXG4gIEBPdXRwdXQoXCJvbkNvbXBvbmVudExvYWRlZFwiKSBvbkNvbXBvbmVudExvYWRlZDogRXZlbnRFbWl0dGVyPEVxcEF0dGFjaG1lbnRzQ29tcG9uZW50PiA9IG5ldyBFdmVudEVtaXR0ZXI8RXFwQXR0YWNobWVudHNDb21wb25lbnQ+KCk7XHJcblxyXG4gIC8vI2VuZHJlZ2lvblxyXG5cclxuICAvLyNyZWdpb24gUHJvcHJpZXTDoCBwZXIgZ2VzdGlvbmUgY2FyaWNhbWVudG8gbnVvdm8gYWxsZWdhdG9cclxuICBuZXdBdHRhY2htZW50OiBJQXR0YWNobWVudERUTyA9IHt9IGFzIElBdHRhY2htZW50RFRPO1xyXG4gIG5ld011bHRpcGxlQXR0YWNobWVudHM6IEFycmF5PElBdHRhY2htZW50RFRPPiA9IFtdO1xyXG4gIGRpYWxvZlJlZkFkZEF0dGFjaG1lbnQ6IE1hdERpYWxvZ1JlZjxUZW1wbGF0ZVJlZjxhbnk+PjtcclxuICBhdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlO1xyXG4gIG5ld0F0dGFjaG1lbnRGb3JtOiBGb3JtR3JvdXA7XHJcbiAgc2VsZWN0ZWRGaWxlOiBGaWxlID0gbnVsbDtcclxuICBzZWxlY3RlZEZpbGVzOiBBcnJheTxGaWxlPiA9IG51bGw7XHJcbiAgc2hvd0Nyb3BJbWFnZTogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBWaWV3Q2hpbGQoJ2RpYWxvZ0FkZEF0dGFjaG1lbnQnLCB7IHN0YXRpYzogdHJ1ZSB9KSBkaWFsb2dBZGRBdHRhY2htZW50OiBUZW1wbGF0ZVJlZjxhbnk+O1xyXG4gIEBWaWV3Q2hpbGQoJ2RpYWxvZ0FkZE11bHRpcGxlQXR0YWNobWVudCcsIHsgc3RhdGljOiB0cnVlIH0pIGRpYWxvZ0FkZE11bHRpcGxlQXR0YWNobWVudDogVGVtcGxhdGVSZWY8YW55PjtcclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgLy8jcmVnaW9uIFByb3ByaWV0w6AgcGVyIGdlc3Rpb25lIHJpZGltZW5zaW9uYW1lbnRvIGZpbGUgZGkgdGlwbyBpbWFnZVxyXG4gIGltYWdlQ2hhbmdlZEV2ZW50OiBhbnkgPSAnJztcclxuICBjcm9wcGVkSW1hZ2U6IGFueSA9ICcnO1xyXG4gIHRyYW5zZm9ybTogSW1hZ2VUcmFuc2Zvcm0gPSB7fTtcclxuICBAVmlld0NoaWxkKEltYWdlQ3JvcHBlckNvbXBvbmVudCkgaW1hZ2VDcm9wcGVyOiBJbWFnZUNyb3BwZXJDb21wb25lbnQ7XHJcbiAgQFZpZXdDaGlsZCgnaW1hZ2VJbnB1dCcpIGltYWdlSW5wdXQ6IGFueTtcclxuICAvLyNlbmRyZWdpb25cclxuXHJcbiAgQXR0YWNobWVudFR5cGUgPSBBdHRhY2htZW50VHlwZTtcclxuICBzZWxlY3RlZEF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPO1xyXG5cclxuICBvcmlnaW5hbFdpZHRoOiBudW1iZXI7XHJcbiAgb3JpZ2luYWxIZWlnaHQ6IG51bWJlcjtcclxuICBjdXN0b21XaWR0aDogbnVtYmVyO1xyXG4gIGN1c3RvbUhlaWdodDogbnVtYmVyO1xyXG5cclxuICBAVmlld0NoaWxkKCdhdHRhY2htZW50VGFibGUnLCB7IHN0YXRpYzogZmFsc2UgfSkgYXR0YWNobWVudFRhYmxlOiBFcXBUYWJsZUNvbXBvbmVudDtcclxuICBAVmlld0NoaWxkKCdpbmxpbmVQcmV2aWV3VGVtcGxhdGUnLCB7IHN0YXRpYzogdHJ1ZSB9KSBpbmxpbmVQcmV2aWV3VGVtcGxhdGU6IFRlbXBsYXRlUmVmPGFueT47XHJcbiAgQFZpZXdDaGlsZCgnZGlhbG9nUHJldmlldycsIHsgc3RhdGljOiB0cnVlIH0pIGRpYWxvZ1ByZXZpZXc6IFRlbXBsYXRlUmVmPGFueT47XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJpdmF0ZSBkaWFsb2c6IE1hdERpYWxvZyxcclxuICAgIHByaXZhdGUgZm9ybUJ1aWxkZXI6IEZvcm1CdWlsZGVyLFxyXG4gICAgcHJpdmF0ZSBzYW5pdGl6ZXI6IERvbVNhbml0aXplcixcclxuICAgIHByaXZhdGUgaHR0cDogSHR0cENsaWVudCxcclxuICAgIHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmXHJcbiAgKSB7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuXHJcbiAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIGFsbG9yYSBpbXBvc3RhIGlsIGZpbHRybyBwZXIgbGUgZXN0ZW5zaW9uaSBwb3NzaWJpbGkgZGEgY2FyaWNhcmVcclxuICAgIGlmICghdGhpcy5hY2NlcHRlZEZpbGVUeXBlcylcclxuICAgICAgaWYgKHRoaXMuYWxsb3dPbmx5SW1hZ2VzID09IHRydWUpXHJcbiAgICAgICAgdGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9IFwiaW1hZ2UvKlwiO1xyXG4gICAgICBlbHNlXHJcbiAgICAgICAgdGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9IFwiKlwiO1xyXG5cclxuICAgIC8vIFNlIG5vbiBzb25vIHN0YXRpIHNwZWNpZmljYXRpIGkgdGlwaSBkYSBnZXN0aXJlIG1hIMOoIHN0YXRvIHBhc3NhdG8gbnVsbCBvIHVuIGFycmF5IHZ1b3RvIGltcG9zdG8gaSB0aXBpIGRpIGRlZmF1bHQuXHJcbiAgICBpZiAoIXRoaXMuYWxsb3dlZFR5cGVzIHx8IHRoaXMuYWxsb3dlZFR5cGVzLmxlbmd0aCA9PSAwKVxyXG4gICAgICB0aGlzLmFsbG93ZWRUeXBlcyA9IFtBdHRhY2htZW50VHlwZS5GSUxFLCBBdHRhY2htZW50VHlwZS5MSU5LXTtcclxuICAgIGVsc2UgaWYgKHRoaXMuYWxsb3dlZFR5cGVzLmZpbmQodCA9PiB0ICE9IEF0dGFjaG1lbnRUeXBlLkZJTEUgJiYgdCAhPSBBdHRhY2htZW50VHlwZS5MSU5LKSkge1xyXG4gICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5XYXJuaW5nKFwiQWxtZW5vIHVubyBkZWdsaSBBdHRhY2htZW50VHlwZSBzZWxlemlvbmF0aSBuZWwgcGFyYW1ldHJvIFxcXCJhbGxvd2VkVHlwZXNcXFwiIG5vbiBlc2lzdGUuXCIpXHJcbiAgICAgIHRoaXMuYWxsb3dlZFR5cGVzID0gW0F0dGFjaG1lbnRUeXBlLkZJTEUsIEF0dGFjaG1lbnRUeXBlLkxJTktdO1xyXG4gICAgfVxyXG5cclxuXHJcbiAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBtdWx0aXBsYSBkZWdsaSBhbGxlZ2F0aSBhbGxvcmEgY29uZmlndXJhIGwnZXFwLXRhYmxlXHJcbiAgICBpZiAodGhpcy5tdWx0aXBsZUF0dGFjaG1lbnQgPT0gdHJ1ZSAmJiAoIXRoaXMuYXR0YWNobWVudHNDb2x1bW5zIHx8IHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLmxlbmd0aCA9PSAwKSkge1xyXG4gICAgICB0aGlzLmNvbmZpZ3VyZUNvbHVtbnMoKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50c0xpc3QgPT0gbnVsbClcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0xpc3QgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcblxyXG4gICAgdGhpcy5jaGVja0F0dGFjaG1lbnRJbWFnZSgpO1xyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgdGhpcy5vbkNvbXBvbmVudExvYWRlZC5lbWl0KHRoaXMpO1xyXG4gIH1cclxuXHJcbiAgcHVibGljIHJlbG9hZERhdGEoKSB7XHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50VGFibGUpXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudFRhYmxlLnJlbG9hZERhdGF0YWJsZSgpO1xyXG4gIH1cclxuXHJcbiAgY2hlY2tBdHRhY2htZW50SW1hZ2UoKSB7XHJcbiAgICB0aGlzLmF0dGFjaG1lbnRzTGlzdC5mb3JFYWNoKGEgPT4ge1xyXG4gICAgICBhLklzSW1hZ2UgPSBBdHRhY2htZW50SGVscGVyU2VydmljZS5jaGVja0ltYWdlRnJvbU1pbWVUeXBlKGEuRmlsZUNvbnRlbnRUeXBlKTtcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgLy8jcmVnaW9uIEdlc3Rpb25lIGVsZW5jbyBhbGxlZ2F0aVxyXG5cclxuICAvKipcclxuICAgKiBDb25maWd1cmEgbGUgY29sb25uZSBwZXIgbCdlcXAtdGFibGUgbmVsIGNhc28gaW4gY3VpIGlsIHBhcmFtZXRybyBcIm11bHRpcGxlQXR0YWNobWVudHNcIiDDqCBUUlVFLlxyXG4gICAqL1xyXG4gIGNvbmZpZ3VyZUNvbHVtbnMoKSB7XHJcbiAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucyA9IFtdO1xyXG4gICAgaWYgKHRoaXMuZGlzYWJsZUFjdGlvbiAhPSB0cnVlKSB7XHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNDb2x1bW5zLnB1c2goe1xyXG4gICAgICAgIGtleTogXCJhY3Rpb25cIiwgZGlzcGxheTogXCJcIixcclxuICAgICAgICB0eXBlOiBUeXBlQ29sdW1uLk1lbnVBY3Rpb24sIGJ1dHRvbk1lbnVJY29uOiBcIm1vcmVfdmVydFwiLCBzdHlsZXM6IHsgZmxleDogXCIwIDAgNiVcIiB9LFxyXG4gICAgICAgIGFjdGlvbnM6IFtcclxuICAgICAgICAgIHsgbmFtZTogdGhpcy5kZWxldGVMYWJlbCwgaWNvbjogXCJkZWxldGVcIiwgZm46IChlbGVtZW50LCBpbmRleCwgY29sKSA9PiB0aGlzLmRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudCkgfSxcclxuICAgICAgICBdLFxyXG4gICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIGxldCBkb3dubG9hZENvbHVtbiA9IHtcclxuICAgICAga2V5OiBcImF0dGFjaG1lbnRcIiwgZGlzcGxheTogXCJcIixcclxuICAgICAgdHlwZTogVHlwZUNvbHVtbi5TaW1wbGVBY3Rpb24sIHN0eWxlczogeyBmbGV4OiBcIjAgMCA2JVwiIH0sXHJcbiAgICAgIGFjdGlvbnM6IFtcclxuICAgICAgICB7XHJcbiAgICAgICAgICBuYW1lOiAnJywgZm9udGF3ZXNvbWU6IHRydWUsXHJcbiAgICAgICAgICBpY29uOiAoZWxlbWVudCkgPT4geyByZXR1cm4gdGhpcy5zaG93SW5saW5lUHJldmlldyA/IChlbGVtZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUgPyBcImZhcyBmYS1jbG91ZC1kb3dubG9hZC1hbHRcIiA6IFwiZmFzIGZhLWV4dGVybmFsLWxpbmstYWx0XCIpIDogdGhpcy5nZXRBdHRhY2htZW50SWNvbihlbGVtZW50KTsgfSxcclxuICAgICAgICAgIGZuOiAoZWxlbWVudCwgY29sLCBlbGVtZW50SW5kZXgpID0+IHRoaXMudmlld0F0dGFjaG1lbnQoZWxlbWVudCksXHJcbiAgICAgICAgICB0b29sdGlwOiB7IHRvb2x0aXBUZXh0OiAoZWxlbWVudCkgPT4geyByZXR1cm4gZWxlbWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFID8gdGhpcy5kb3dubG9hZExhYmVsIDogdGhpcy5vcGVuTGlua0xhYmVsOyB9LCB0b29sdGlwUG9zaXRpb246IHRoaXMuZG93bmxvYWRUb29sdGlwUG9zaXRpb24gfVxyXG4gICAgICAgIH0sXHJcbiAgICAgIF1cclxuICAgIH07XHJcblxyXG4gICAgbGV0IGlubGluZVByZXZpZXdDb2x1bW4gPSB7XHJcbiAgICAgIGtleTogXCJJbmxpbmVQcmV2aWV3XCIsIGRpc3BsYXk6IHRoaXMucHJldmlld0xhYmVsLFxyXG4gICAgICB0eXBlOiBUeXBlQ29sdW1uLkV4dGVybmFsVGVtcGxhdGUsXHJcbiAgICAgIGV4dGVybmFsVGVtcGxhdGU6IHRoaXMuaW5saW5lUHJldmlld1RlbXBsYXRlLFxyXG4gICAgICBzdHlsZXM6IHsgZmxleDogXCIwIDAgMTAlXCIgfVxyXG4gICAgfTtcclxuXHJcbiAgICBsZXQgZmlsZU5hbWVDb2x1bW4gPSB7IGtleTogXCJGaWxlTmFtZVwiLCBkaXNwbGF5OiB0aGlzLmZpbGVOYW1lTGFiZWwgfTtcclxuXHJcbiAgICBpZiAodGhpcy5zaG93SW5saW5lUHJldmlldykge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGlubGluZVByZXZpZXdDb2x1bW4pO1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGZpbGVOYW1lQ29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChkb3dubG9hZENvbHVtbik7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmF0dGFjaG1lbnRzQ29sdW1ucy5wdXNoKGRvd25sb2FkQ29sdW1uKTtcclxuICAgICAgdGhpcy5hdHRhY2htZW50c0NvbHVtbnMucHVzaChmaWxlTmFtZUNvbHVtbik7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBFbGltaW5hIHVuIGFsbGVnYXRvIGVsaW1pbmFuZG8gYW5jaGUgaWwgZmlsZSBwcmVzZW50ZSBuZWxsbyBzdG9yYWdlIGRpIGFyY2hpdmlhemlvbmUgdXRpbGl6emF0byAoQVdTIG8gY2FydGVsbGEgcHJvZ2V0dG8pXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgSUF0dGFjaG1lbnREVE8gZGEgY2FuY2VsbGFyZVxyXG4gICAqL1xyXG4gIGRlbGV0ZUF0dGFjaG1lbnQoZWxlbWVudDogSUF0dGFjaG1lbnREVE8pIHtcclxuICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkNvbmZpcm0odGhpcy5kZWxldGVEaWFsb2dNZXNzYWdlLCAoKSA9PiB7XHJcbiAgICAgIHRoaXMucmVtb3ZlQXR0YWNobWVudEZyb21MaXN0KHRoaXMuYXR0YWNobWVudHNMaXN0LmluZGV4T2YoZWxlbWVudCkpO1xyXG4gICAgfSwgdHJ1ZSwgdGhpcy5kZWxldGVEaWFsb2dUaXRsZSk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSaW11b3ZlIGwnYWxsZWdhdG8gc2VsZXppb25hdG8gZGFsbGEgbGlzdGEgXCJhdHRhY2htZW50c0xpc3RcIiBlIGludm9jYSBsJ2V2ZW50byBkaSBvdXRwdXQgY2hlIHJlc3RpdHVpc2NlIGxhIGxpc3RhIGFnZ2lvcm5hdGEuXHJcbiAgICogQHBhcmFtIGF0dGFjaG1lbnRJbmRleCBJbmRpY2UgZGVsbCdhdHRhY2htZW50IGRhIHJpbXVvdmVyZVxyXG4gICAqL1xyXG4gIHJlbW92ZUF0dGFjaG1lbnRGcm9tTGlzdChhdHRhY2htZW50SW5kZXg6IG51bWJlcikge1xyXG4gICAgdGhpcy5vbkRlbGV0ZUF0dGFjaG1lbnQuZW1pdCh0aGlzLmF0dGFjaG1lbnRzTGlzdFthdHRhY2htZW50SW5kZXhdKTtcclxuXHJcbiAgICB0aGlzLmF0dGFjaG1lbnRzTGlzdC5zcGxpY2UoYXR0YWNobWVudEluZGV4LCAxKTtcclxuICAgIGlmICh0aGlzLmF0dGFjaG1lbnRUYWJsZSlcclxuICAgICAgdGhpcy5hdHRhY2htZW50VGFibGUucmVsb2FkRGF0YXRhYmxlKCk7XHJcbiAgICB0aGlzLmxvY2FsRWRpdGVkQXR0YWNobWVudHMuZW1pdCh0aGlzLmF0dGFjaG1lbnRzTGlzdCk7XHJcbiAgfVxyXG5cclxuXHJcbiAgLyoqXHJcbiAgICogU2NhcmljYSBsJ2FsbGVnYXRvIG8gYXByZSBpbCBsaW5rXHJcbiAgICogQHBhcmFtIGVsZW1lbnQgQWxsZWdhdG8gZGEgbW9zdHJhcmVcclxuICAgKi9cclxuICB2aWV3QXR0YWNobWVudChhdHRhY2htZW50OiBJQXR0YWNobWVudERUTykge1xyXG5cclxuICAgIGlmIChhdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTkspIHtcclxuICAgICAgd2luZG93Lm9wZW4oYXR0YWNobWVudC5GaWxlUGF0aCwgJ19ibGFuaycpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGF0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgJiYgYXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgJiYgYXR0YWNobWVudC5GaWxlTmFtZSkge1xyXG4gICAgICBsZXQgc291cmNlID0gYGRhdGE6JHthdHRhY2htZW50LkZpbGVDb250ZW50VHlwZX07YmFzZTY0LCR7YXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NH1gO1xyXG4gICAgICBjb25zdCBsaW5rID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImFcIik7XHJcbiAgICAgIGxpbmsuaHJlZiA9IHNvdXJjZTtcclxuICAgICAgbGluay5kb3dubG9hZCA9IGAke2F0dGFjaG1lbnQuRmlsZU5hbWV9YFxyXG4gICAgICBsaW5rLmNsaWNrKCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmRvd25sb2FkQXR0YWNobWVudC5lbWl0KGF0dGFjaG1lbnQpO1xyXG4gICAgfVxyXG5cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFJpZGVmaW5pc2NlIGwnaWNvbmEgZGEgbW9zdHJhcmUgbmVsbGEgY29sb25uYSBkZWxsJ2VxcC10YWJsZSBwZXIgb2duaSBmaWxlLlxyXG4gICAqIEwnaWNvbmEgdmFyaWEgaW4gYmFzZSBhbGwnZXN0ZW5zaW9uZSBkZWwgZmlsZVxyXG4gICAqIEBwYXJhbSBhdHRhY2htZW50IFxyXG4gICAqL1xyXG4gIGdldEF0dGFjaG1lbnRJY29uKGF0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPKSB7XHJcbiAgICBpZiAoYXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKVxyXG4gICAgICByZXR1cm4gXCJmYXMgZmEtbGlua1wiO1xyXG4gICAgZWxzZVxyXG4gICAgICByZXR1cm4gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuZ2V0SWNvbkZyb21GaWxlRXh0ZW5zaW9uZShhdHRhY2htZW50LkZpbGVFeHRlbnNpb24pO1xyXG4gIH1cclxuXHJcbiAgLy8jZW5kcmVnaW9uXHJcblxyXG4gIC8qKlxyXG4gICAqIEFwcmUgbGEgbW9kYWxlIHBlciBsYSBkZWZpbml6aW9uZSBkZWkgcGFyYW1ldHJpIGRlbCBudW92byBmaWxlXHJcbiAgICovXHJcbiAgb3Blbk1vZGFsQWRkQXR0YWNobWVudChhdHRhY2htZW50VHlwZTogQXR0YWNobWVudFR5cGUpIHtcclxuXHJcbiAgICAvL1NlIMOoIHN0YXRvIHJpY2hpZXN0byBpbCBjYXJpY2FtZW50byBkaSB1biBMSU5LIG8gw6ggaW1wb3N0YXRvIGlsIGNhcmljYW1lbnRvIGRpIEZJTEUgU0lOR09MTyBhbGxvcmEgYXByZSBsYSBtb2RhbGUgcGVyXHJcbiAgICAvL2lsIGNhcmljYW1lbnRvIHNpbmdvbG8gZGVsIGZpbGUgYWx0cmltZW50aSBhcHJlIHF1ZWxsYSBwZXIgaWwgY2FyaWNhbWVudG8gbXVsdGlwbG9cclxuICAgIC8vIGlmIChhdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LIHx8IChhdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5GSUxFICYmIHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkpIHtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudCA9IHt9IGFzIElBdHRhY2htZW50RFRPO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LklzSW1hZ2UgPSBmYWxzZTtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9IGF0dGFjaG1lbnRUeXBlO1xyXG4gICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG4gICAgaWYgKGF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTkspXHJcbiAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5wdXNoKHRoaXMubmV3QXR0YWNobWVudCk7XHJcblxyXG4gICAgdGhpcy5jcmVhdGVBdHRhY2htZW50Rm9ybSgpO1xyXG5cclxuICAgIC8vQXByZSBsYSBtb2RhbGVcclxuICAgIHRoaXMuZGlhbG9mUmVmQWRkQXR0YWNobWVudCA9IHRoaXMuZGlhbG9nLm9wZW4odGhpcy5kaWFsb2dBZGRBdHRhY2htZW50LCB7XHJcbiAgICAgIGRpc2FibGVDbG9zZTogdHJ1ZSxcclxuICAgICAgaGFzQmFja2Ryb3A6IHRydWUsXHJcbiAgICAgIHdpZHRoOiAnNjAlJyxcclxuICAgICAgbWF4SGVpZ2h0OiAnODAlJ1xyXG4gICAgfSk7XHJcblxyXG5cclxuICB9XHJcblxyXG4gIGNyZWF0ZUF0dGFjaG1lbnRGb3JtKCkge1xyXG4gICAgLy9DcmVhIGxhIGZvcm0gcGVyIGxhIHZhbGlkYXppb25lIGRlaSBjYW1waVxyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybSA9IHRoaXMuZm9ybUJ1aWxkZXIuZ3JvdXAoe1xyXG4gICAgICB0eXBlOiBbdGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlLCBWYWxpZGF0b3JzLnJlcXVpcmVkXSxcclxuICAgICAgbmFtZTogW3RoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZV0sXHJcbiAgICAgIHBhdGg6IFt0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZVBhdGhdLFxyXG4gICAgICBjdXN0b21IZWlnaHQ6IFt0aGlzLmN1c3RvbUhlaWdodF0sXHJcbiAgICAgIGN1c3RvbVdpZHRoOiBbdGhpcy5jdXN0b21XaWR0aF1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgY2xvc2UoZW1pdENsb3NlRXZlbnQgPSB0cnVlKSB7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQgPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuICAgIHRoaXMuYWJvcnRGaWxlKCk7XHJcbiAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50Rm9ybSlcclxuICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5yZXNldCgpO1xyXG5cclxuICAgIHRoaXMuZGlhbG9mUmVmQWRkQXR0YWNobWVudC5jbG9zZSgpO1xyXG5cclxuXHJcbiAgICBpZiAoZW1pdENsb3NlRXZlbnQgPT0gdHJ1ZSAmJiB0aGlzLmFib3J0QWRkQXR0YWNobWVudClcclxuICAgICAgdGhpcy5hYm9ydEFkZEF0dGFjaG1lbnQuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSW4gYmFzZSBhbCB0aXBvIGRpIGFsbGVnYXRvIGNvbnRyb2xsYSBzZSBkaXNhYmlsaXRhcmUgbyBtZW5vIGlsIHB1bHNhbnRlIHBlciBzYWx2YXJlLlxyXG4gICAqIEZ1bnppb25lIHVzYXRhIG5lbCBbZGlzYWJsZV0gZGVsIHB1bHNhbnRlIFwiU2FsdmFcIiBkZWwgZGlhbG9nIHBlciBsJ2FnZ2l1bnRhIGRpIHVuIGFsbGVnYXRvLlxyXG4gICAqIEByZXR1cm5zIFxyXG4gICAqL1xyXG4gIGRpc2FibGVTYXZlKCkge1xyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUpIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NDtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMubmV3QXR0YWNobWVudC5GaWxlUGF0aDtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgZWxzZSB7XHJcbiAgICAgIHJldHVybiB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMuZmlsdGVyKHAgPT4gKHAuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuRklMRSAmJiAhcC5GaWxlRGF0YUJhc2U2NCkgfHwgKHAuQXR0YWNobWVudFR5cGUgPT0gQXR0YWNobWVudFR5cGUuTElOSyAmJiAhcC5GaWxlUGF0aCkpLmxlbmd0aCA+IDA7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgY29uZmlybUFkZEF0dGFjaG1lbnQoKSB7XHJcblxyXG4gICAgaWYgKHRoaXMubG9hZE11bHRpcGxlRmlsZXMgIT0gdHJ1ZSkge1xyXG4gICAgICBpZiAodGhpcy5uZXdBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkxJTksgJiYgIXRoaXMubmV3QXR0YWNobWVudC5GaWxlTmFtZSlcclxuICAgICAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZU5hbWUgPSB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZVBhdGg7XHJcblxyXG4gICAgICBpZiAodGhpcy5hdHRhY2htZW50c0xpc3QgPT0gbnVsbClcclxuICAgICAgICB0aGlzLmF0dGFjaG1lbnRzTGlzdCA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudHNMaXN0LnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICBpZiAodGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzID09IG51bGwgfHwgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLmxlbmd0aCA9PSAwKVxyXG4gICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgIGlmICh0aGlzLmF0dGFjaG1lbnRzTGlzdCA9PSBudWxsKVxyXG4gICAgICAgIHRoaXMuYXR0YWNobWVudHNMaXN0ID0gbmV3IEFycmF5PElBdHRhY2htZW50RFRPPigpO1xyXG5cclxuICAgICAgdGhpcy5hdHRhY2htZW50c0xpc3QgPSB0aGlzLmF0dGFjaG1lbnRzTGlzdC5jb25jYXQodGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAodGhpcy5hdHRhY2htZW50VGFibGUpXHJcbiAgICAgIHRoaXMuYXR0YWNobWVudFRhYmxlLnJlbG9hZERhdGF0YWJsZSgpO1xyXG5cclxuICAgIHRoaXMubG9jYWxFZGl0ZWRBdHRhY2htZW50cy5lbWl0KHRoaXMuYXR0YWNobWVudHNMaXN0KTtcclxuICAgIHRoaXMuY2xvc2UoZmFsc2UpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQXByZSBpbCBkaWFsb2cgcGVyIGwnYW50ZXByaW1hIGRlbGwnYWxsZWdhdG8gc2VsZXppb25hdG8uXHJcbiAgICogQHBhcmFtIHJvdyBcclxuICAgKiBAcmV0dXJucyBcclxuICAgKi9cclxuICBhc3luYyBvcGVuUHJldmlld0RpYWxvZyhyb3c6IElBdHRhY2htZW50RFRPKSB7XHJcbiAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudCA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkocm93KSk7XHJcblxyXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkF0dGFjaG1lbnRUeXBlID09IEF0dGFjaG1lbnRUeXBlLkZJTEUpIHtcclxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZS5zdGFydHNXaXRoKFwidmlkZW9cIikpIHtcclxuICAgICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5XYXJuaW5nKHRoaXMudmlkZW9QcmV2aWV3RXJyb3JNZXNzYWdlKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH0gZWxzZSBpZiAodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlLnN0YXJ0c1dpdGgoXCJhdWRpb1wiKSkge1xyXG4gICAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLldhcm5pbmcodGhpcy5hdWRpb1ByZXZpZXdFcnJvck1lc3NhZ2UpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLmdldEF0dGFjaG1lbnRFbmRwb2ludCAmJiB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlICYmICF0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCkge1xyXG4gICAgICBhd2FpdCB0aGlzLmdldEF0dGFjaG1lbnRCeUlEKClcclxuICAgICAgICAudGhlbigocmVzKSA9PiB7IHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gcmVzLkZpbGVEYXRhQmFzZTY0OyB9KVxyXG4gICAgICAgIC5jYXRjaCgoZXJyKSA9PiB7IEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkVycm9yKGVycik7IH0pO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9PSBBdHRhY2htZW50VHlwZS5MSU5LKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LlRydXN0ZWRVcmwgPSB0aGlzLnNhbml0aXplci5ieXBhc3NTZWN1cml0eVRydXN0UmVzb3VyY2VVcmwodGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVBhdGgpO1xyXG4gICAgfSBlbHNlIGlmICh0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5Jc0ltYWdlICYmICF0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCAmJiAhdGhpcy5zZWxlY3RlZEF0dGFjaG1lbnQuRmlsZVRodW1ibmFpbEJhc2U2NCkge1xyXG4gICAgICBFcXBBdHRhY2htZW50RGlhbG9nU2VydmljZS5JbmZvKFwiSW1wb3NzaWJpbGUgYXByaXJlIGwnYW50ZXByaW1hIGRlbGwnYWxsZWdhdG8sIGZpbGUgbWFuY2FudGUuXCIpXHJcbiAgICAgIHJldHVybjtcclxuICAgIH0gZWxzZSBpZiAoIXRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LklzSW1hZ2UpIHtcclxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRBdHRhY2htZW50LkZpbGVQYXRoICYmIHRoaXMucHJvZHVjdGlvbkJhc2VVcmwpIHtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5UcnVzdGVkVXJsID0gdGhpcy5zYW5pdGl6ZXIuYnlwYXNzU2VjdXJpdHlUcnVzdFJlc291cmNlVXJsKFxyXG4gICAgICAgICAgXCJodHRwczovL2RvY3MuZ29vZ2xlLmNvbS9ndmlldz91cmw9XCIgK1xyXG4gICAgICAgICAgdGhpcy5wcm9kdWN0aW9uQmFzZVVybCArXHJcbiAgICAgICAgICBcIi9cIiArXHJcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkQXR0YWNobWVudC5GaWxlUGF0aCArXHJcbiAgICAgICAgICBcIiZlbWJlZGRlZD10cnVlXCJcclxuICAgICAgICApO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkluZm8oXCJJbXBvc3NpYmlsZSBhcHJpcmUgbCdhbnRlcHJpbWEgZGVsIGRvY3VtZW50byFcIik7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgdGhpcy5kaWFsb2cub3Blbih0aGlzLmRpYWxvZ1ByZXZpZXcsIHtcclxuICAgICAgZGlzYWJsZUNsb3NlOiB0cnVlLFxyXG4gICAgICBoYXNCYWNrZHJvcDogdHJ1ZSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0QXR0YWNobWVudEJ5SUQoKSB7XHJcbiAgICByZXR1cm4gdGhpcy5odHRwLnBvc3Q8SUF0dGFjaG1lbnREVE8+KHRoaXMuZ2V0QXR0YWNobWVudEVuZHBvaW50LCB0aGlzLnNlbGVjdGVkQXR0YWNobWVudCkudG9Qcm9taXNlKCk7XHJcbiAgfVxyXG5cclxuICAvLyNyZWdpb24gR2VzdGlvbmUgY2FyaWNhbWVudG8gZmlsZVxyXG5cclxuICAvKiogXHJcbiAgICogRXZlbnRvIHNjYXRlbmF0byBhbGxhIHNlbGV6aW9uZSBkZWwgZmlsZSAobyBkZWkgZmlsZSkuXHJcbiAgICogU2UgaWwgY2FyaWNhbWVudG8gw6ggU0lOR09MTyBvIHNlIGNvbXVucXVlIMOoIHN0YXRvIHNlbGV6aW9uYXRvIHVuIHNvbG8gZmlsZSBhbGxvcmEgc2kgb2NjdXBhIGRpIGNvbnRyb2xsYXJlIHNlIHNpIHRyYXR0YSBkaSB1biBpbW1hZ2luZSBpbiBtb2RvIGRhXHJcbiAgICogbW9zdHJhcmUgbGUgZnVuemlvbmFsaXTDoCBkZWwgY3JvcHBpZSAocGVyIHJpdGFnbGlhcmUgbCdpbW1hZ2luZSkgb3BwdXJlIG5vLlxyXG4gICAqIFNlIGlsIGZpbGUgY2FyaWNhdG8gbm9uIMOoIHVuIGltbWFnaW5lIGFsbG9yYSBnZW5lcmEgZGlyZXR0YW1lbnRlIGlsIGJhc2U2NCBlIGxvIGFzc29jaWEgYWxsJ2FsbGVnYXRvIGRhIHNhbHZhcmUuXHJcbiAgICogU2UgaW52ZWNlIGlsIGNhcmljYW1lbnRvIGRlaSBmaWxlIMOoIE1VTFRJUExPIGUgc29ubyBwcmVzZW50aSBwacO5IGZpbGUgYWxsb3JhIGVzZWd1ZSBsZSBzdGVzc2Ugb3BlcmF6aW9uaSBpZ25vcmFuZG8gcGVyw7IgaWwgY29udHJsbG9cclxuICAgKiBpbW1hZ2luZSBwZXIgaWwgY3JvcHBpZSAoaW4gY2FzbyBkaSBjYXJpY2FtZW50byBtdWx0aXBsbyBsZSBmdW56aW9uYWxpdMOgIGRlbCBjcm9wcGllIHNvbm8gZGlzYWJpbGl0YXRlKS5cclxuICAgKi9cclxuICBhc3luYyBvbkZpbGVJbnB1dENoYW5nZShldmVudCkge1xyXG4gICAgdGhpcy5zaG93Q3JvcEltYWdlID0gZmFsc2U7XHJcblxyXG4gICAgLy9TZSDDqCBzdGF0byByaWNoaWVzdG8gaWwgY2FyaWNhbWVudG8gU0lOR09MTyBvcHB1cmUgc2UgaWwgY2FyaWNhbWVudG8gw6ggTVVMVElQTE8gbWEgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gc29sbyBmaWxlXHJcbiAgICAvL2FsbG9yYSB2ZXJpZmljYSBzZSBpbCBmaWxlIMOoIHVuIGltbWFnaW5lIChwZXIgbW9zdHJhcmUgaWwgQ1JPUFBJRSlcclxuICAgIGlmIChbLi4uZXZlbnQudGFyZ2V0LmZpbGVzXS5sZW5ndGggPT0gMSB8fCB0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBldmVudC50YXJnZXQuZmlsZXNbMF07XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaWxlcyA9IGV2ZW50LnRhcmdldC5maWxlcztcclxuICAgICAgaWYgKCF0aGlzLnNlbGVjdGVkRmlsZSlcclxuICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAvL01lbW9yaXp6YSBpIGRhdGkgcGVyIGwnYWxsZWdhdG8gICAgICAgIFxyXG4gICAgICB0aGlzLm5ld0F0dGFjaG1lbnQgPSBhd2FpdCB0aGlzLmNyZWF0ZUF0dGFjaG1lbnRGcm9tVXBsb2FkZWRGaWxlKHRoaXMuc2VsZWN0ZWRGaWxlLCBmYWxzZSk7XHJcbiAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuICAgICAgdGhpcy5uZXdNdWx0aXBsZUF0dGFjaG1lbnRzLnB1c2godGhpcy5uZXdBdHRhY2htZW50KTtcclxuXHJcbiAgICAgIC8vU2Ugw6ggc3RhdGEgcmljaGllc3RhIGxhIGdlc3Rpb25lIGRlbGxlIHNvbGUgaW1tYWdpbmkgbWEgcGVyIGVycm9yZSDDqCBzdGF0byBzZWxlemlvbmF0byB1biBmaWxlIGNoZSBub24gw6ggdW4gaW1tYWdpbmVcclxuICAgICAgbGV0IGNoZWNrT25seUltYWdlID0gdGhpcy5jaGVja0FsbG93T25seUltYWdlRmlsZSh0aGlzLm5ld0F0dGFjaG1lbnQpO1xyXG4gICAgICBpZiAoY2hlY2tPbmx5SW1hZ2UgPT0gZmFsc2UpXHJcbiAgICAgICAgcmV0dXJuO1xyXG5cclxuXHJcbiAgICAgIGlmICh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzID09IHRydWUgJiYgWy4uLmV2ZW50LnRhcmdldC5maWxlc10ubGVuZ3RoID09IDEpXHJcbiAgICAgICAgdGhpcy5jcmVhdGVBdHRhY2htZW50Rm9ybSgpO1xyXG5cclxuICAgICAgLy9WZXJpZmljYSBzZSBpbCBmaWxlIGNhcmljYXRvIMOoIHVuJ2ltbWFnaW5lIG9wcHVyZSBuby4gU2Ugw6ggdW4gaW1tYWdpbmUsIHByaW1hIGRpIGNhcmljYXJsYSBtb3N0cmEgaWwgY3JvcHBpZSBwZXIgaWwgcmVzaXplLlxyXG4gICAgICAvL1NlIG5vbiDDqCB1biBpbW1hZ2luZSBhbGxvcmEgZ2VuZXJhIGlsIEJhc2U2NCBcclxuICAgICAgaWYgKHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlID09IHRydWUpIHtcclxuICAgICAgICB0aGlzLmdldEltYWdlRGltZW5zaW9ucyhldmVudC50YXJnZXQuZmlsZXNbMF0pXHJcblxyXG4gICAgICAgIC8vTW9zdHJhIGlsIGNyb3BwaWUgZSBkaXNhYmlsaXRhIGxhIGZvcm0gZmluY2jDqCBub24gdGVybWluYSBsYSBtb2RpZmljYSBkZWxsJ2ltbWFnaW5lXHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5kaXNhYmxlKCk7XHJcbiAgICAgICAgdGhpcy5uZXdBdHRhY2htZW50Rm9ybS5jb250cm9sc1tcImN1c3RvbVdpZHRoXCJdLmVuYWJsZSgpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudEZvcm0uY29udHJvbHNbXCJjdXN0b21IZWlnaHRcIl0uZW5hYmxlKCk7XHJcbiAgICAgICAgdGhpcy5zaG93Q3JvcEltYWdlID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmltYWdlQ2hhbmdlZEV2ZW50ID0gZXZlbnQ7XHJcbiAgICAgIH1cclxuICAgICAgZWxzZSB7XHJcbiAgICAgICAgdGhpcy5zaG93Q3JvcEltYWdlID0gZmFsc2U7XHJcbiAgICAgICAgbGV0IGJhc2U2NFJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0QmFzZTY0RnJvbUZpbGUodGhpcy5zZWxlY3RlZEZpbGUpO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRGF0YUJhc2U2NCA9IGJhc2U2NFJlc3VsdC5CYXNlNjRGaWxlO1xyXG4gICAgICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBiYXNlNjRSZXN1bHQuQ29udGVudFR5cGU7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIGVsc2Uge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRmlsZXMgPSBldmVudC50YXJnZXQuZmlsZXM7XHJcbiAgICAgIGlmICghdGhpcy5zZWxlY3RlZEZpbGVzIHx8IHRoaXMuc2VsZWN0ZWRGaWxlcy5sZW5ndGggPT0gMClcclxuICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICB0aGlzLm5ld011bHRpcGxlQXR0YWNobWVudHMgPSBuZXcgQXJyYXk8SUF0dGFjaG1lbnREVE8+KCk7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5zZWxlY3RlZEZpbGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgbGV0IG5ld0F0dGFjaG1lbnQ6IElBdHRhY2htZW50RFRPID0gYXdhaXQgdGhpcy5jcmVhdGVBdHRhY2htZW50RnJvbVVwbG9hZGVkRmlsZSh0aGlzLnNlbGVjdGVkRmlsZXNbaV0sIHRydWUpO1xyXG5cclxuICAgICAgICAvL1NlIMOoIHN0YXRhIHJpY2hpZXN0YSBsYSBnZXN0aW9uZSBkZWxsZSBzb2xlIGltbWFnaW5pIG1hIHBlciBlcnJvcmUgw6ggc3RhdG8gc2VsZXppb25hdG8gdW4gZmlsZSBjaGUgbm9uIMOoIHVuIGltbWFnaW5lXHJcbiAgICAgICAgbGV0IGNoZWNrT25seUltYWdlID0gdGhpcy5jaGVja0FsbG93T25seUltYWdlRmlsZShuZXdBdHRhY2htZW50KTtcclxuICAgICAgICBpZiAoY2hlY2tPbmx5SW1hZ2UgPT0gZmFsc2UpXHJcbiAgICAgICAgICByZXR1cm47XHJcblxyXG4gICAgICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cy5wdXNoKG5ld0F0dGFjaG1lbnQpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBIHBhcnRpcmUgZGFsIEZJTEUgcmljZXZ1dG8gaW4gaW5wdXQgcmljb3N0cnVpc2NlIGwnb2dnZXR0byBJQXR0YWNobWVudERUTyBlIGxvIHJlc3RpdHVpc2NlLlxyXG4gICAqIFNlIGlsIHBhcmFtZXRybyBnZXRCYXNlNjQgdmllbmUgcGFzc2F0byBhIFRSVUUgYWxsb3JhLCBzZW1wcmUgYSBwYXJ0aXJlIGRhbCBmaWxlLGdlbmVyYSBpbCBiYXNlNjQgZSBcclxuICAgKiByaWNhdmEgaWwgQ29udGVudFR5cGUgZGEgYXNzb2NpYXJlIGFsbCdvZ2dldHRvIElBdHRhY2htZW50RFRPIGRhIHJlc3RpdHVpcmVcclxuICAgKiBAcGFyYW0gY3VycmVudEZpbGUgT2dnZXR0byBGSUxFIGRhIHByb2Nlc3NhcmVcclxuICAgKiBAcGFyYW0gZ2V0QmFzZTY0IFNlIFRSVUUgYWxsb3JhIGNhbGNvbGEgYmFzZTY0IGUgQ29udGVudFR5cGUgZGVsIGZpbGUgcGFzc2F0byBpbiBpbnB1dFxyXG4gICAqIEByZXR1cm5zIFJlc3RpdHVpc2NlIHVuIG9nZ2V0dG8gZGkgdGlwbyBJQXR0YWNobWVudERUT1xyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgY3JlYXRlQXR0YWNobWVudEZyb21VcGxvYWRlZEZpbGUoY3VycmVudEZpbGU6IEZpbGUsIGdldEJhc2U2NDogYm9vbGVhbiA9IHRydWUpOiBQcm9taXNlPElBdHRhY2htZW50RFRPPiB7XHJcbiAgICBsZXQgbmV3QXR0YWNobWVudDogSUF0dGFjaG1lbnREVE8gPSB7fSBhcyBJQXR0YWNobWVudERUTztcclxuXHJcbiAgICAvL01lbW9yaXp6YSBpIGRhdGkgcGVyIGwnYWxsZWdhdG8gICAgICAgIFxyXG4gICAgbmV3QXR0YWNobWVudC5BdHRhY2htZW50VHlwZSA9IEF0dGFjaG1lbnRUeXBlLkZJTEU7XHJcbiAgICBuZXdBdHRhY2htZW50LkZpbGVDb250ZW50VHlwZSA9IGN1cnJlbnRGaWxlLnR5cGU7XHJcbiAgICBuZXdBdHRhY2htZW50LkZpbGVOYW1lID0gY3VycmVudEZpbGUubmFtZTtcclxuICAgIG5ld0F0dGFjaG1lbnQuRmlsZUV4dGVuc2lvbiA9IGN1cnJlbnRGaWxlLm5hbWUuc3Vic3RyKGN1cnJlbnRGaWxlLm5hbWUubGFzdEluZGV4T2YoJy4nKSArIDEpO1xyXG4gICAgbmV3QXR0YWNobWVudC5Jc0ltYWdlID0gQXR0YWNobWVudEhlbHBlclNlcnZpY2UuY2hlY2tJbWFnZUZyb21NaW1lVHlwZShjdXJyZW50RmlsZS50eXBlKTtcclxuXHJcbiAgICBpZiAoZ2V0QmFzZTY0ID09IHRydWUpIHtcclxuICAgICAgbGV0IGJhc2U2NFJlc3VsdCA9IGF3YWl0IHRoaXMuZ2V0QmFzZTY0RnJvbUZpbGUoY3VycmVudEZpbGUpO1xyXG4gICAgICBuZXdBdHRhY2htZW50LkZpbGVEYXRhQmFzZTY0ID0gYmFzZTY0UmVzdWx0LkJhc2U2NEZpbGU7XHJcbiAgICAgIG5ld0F0dGFjaG1lbnQuRmlsZUNvbnRlbnRUeXBlID0gYmFzZTY0UmVzdWx0LkNvbnRlbnRUeXBlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBuZXdBdHRhY2htZW50O1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQSBwYXJ0aXJlIGRhbCBmaWxlIHBhc3NhdG8gaW4gaW5wdXQgcmVzdGl0dWlzY2UgdW4gb2dnZXR0b1xyXG4gICAqIGNvbnRlbmVudGUgaWwgYmFzZTY0IGRlbCBmaWxlIGUgaWwgc3VvIGNvbnRlbnRUeXBlXHJcbiAgICogQHBhcmFtIGN1cnJlbnRGaWxlIE9nZ2V0dG8gRmlsZSBkYSBjdWkgZXN0cmFwb2xhcmUgYmFzZTY0IGUgY29udGVudFR5cGVcclxuICAgKiBAcmV0dXJucyBSZXN0aXR1aXNjZSB1biBvZ2dldHRvIGF2ZW50ZSBsZSBwcm9wcmlldMOgIEJhc2U2NEZpbGUgZSBDb250ZW50VHlwZVxyXG4gICAqL1xyXG4gIHByaXZhdGUgYXN5bmMgZ2V0QmFzZTY0RnJvbUZpbGUoY3VycmVudEZpbGU6IEZpbGUpOiBQcm9taXNlPGFueT4ge1xyXG4gICAgbGV0IGJhc2U2NEZpbGUgPSBhd2FpdCB0b0Jhc2U2NChjdXJyZW50RmlsZSk7XHJcbiAgICBsZXQgY29udGVudFR5cGU6IHN0cmluZyA9IG51bGw7XHJcbiAgICBpZiAoYmFzZTY0RmlsZSkge1xyXG4gICAgICAvLyBMb3JpcyAyMC8wMS8yMDIyOiBQUk9CTEVNQSAtIFF1YW5kbyBlc2VndW8gbCd1cGxvYWQgZGkgdW4gZmlsZSAuc3FsIG5vbiB2aWVuZSBzYWx2YXRvL3NjYXJpY2F0byBjb3JyZXR0YW1lbnRlLlxyXG4gICAgICAvLyAgICAgICAgICAgICAgICAgICBRdWVzdG8gc3VjY2VkZSBwZXJjaMOoIG5vbiB2aWVuZSBwb3BvbGF0byBpbCBGaWxlQ29udGVudFR5cGUuIFBlciByaXNvbHZlcmUgaWwgcHJvYmxlbWFcclxuICAgICAgLy8gICAgICAgICAgICAgICAgICAgZmFjY2lvIHVuIGNvbnRyb2xsbyBlIHNlIG5vbiBlc2lzdGUgaWwgRmlsZUNvbnRlbnRUeXBlIGFsbG9yYSBsbyByZWN1cGVybyBkYWwgYmFzZTY0IG90dGVudXRvLlxyXG4gICAgICBjb250ZW50VHlwZSA9IGJhc2U2NEZpbGUuc3BsaXQoXCIsXCIpWzBdLnNwbGl0KFwiOlwiKVsxXS5zcGxpdChcIjtcIilbMF07XHJcbiAgICAgIC8vIFVuIGFsdHJvIG1ldG9kbyBwZXIgbGVnZ2VyZSBpbCBjY29udGVudCB0eXBlIGRlbCBmaWxlIMOoIHRyYW1pdGUgdW5hIHJlZ3VsYXIgZXhwcmVzc2lvbjpcclxuICAgICAgYmFzZTY0RmlsZSA9IGJhc2U2NEZpbGUuc3BsaXQoXCIsXCIpWzFdO1xyXG4gICAgfVxyXG5cclxuICAgIGxldCByZXN1bHQgPSB7XHJcbiAgICAgIEJhc2U2NEZpbGU6IGJhc2U2NEZpbGUsXHJcbiAgICAgIENvbnRlbnRUeXBlOiBjb250ZW50VHlwZVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiByZXN1bHQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBDb250cm9sbGEgc2UgaWwgZmlsZSBjaGUgc2kgc3RhIGNhcmljYW5kbyDDqCBzdXBwb3J0YXRvIGRhbCBzaXN0ZW1hLlxyXG4gICAqIEByZXR1cm5zIFxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2hlY2tBY2NlcHRlZEZpbGVzKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKCh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUgJiYgdGhpcy5zZWxlY3RlZEZpbGUudHlwZS5zdGFydHNXaXRoKFwidmlkZW9cIikpXHJcbiAgICAgIHx8ICh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzID09IHRydWUgJiYgWy4uLnRoaXMuc2VsZWN0ZWRGaWxlc10uZmlsdGVyKHAgPT4gcC50eXBlLnN0YXJ0c1dpdGgoXCJ2aWRlb1wiKSkubGVuZ3RoID4gMCkpXHJcbiAgICAgIHJldHVybiBmYWxzZTtcclxuXHJcbiAgICBpZiAodGhpcy5hY2NlcHRlZEZpbGVUeXBlcyA9PSBcIipcIilcclxuICAgICAgcmV0dXJuIHRydWU7XHJcblxyXG4gICAgLy9WZXJpZmljYSBjaGUgaSB0aXBpIGRlbCBmaWxlIChvIGRlaSBmaWxlKSBjYXJpY2F0aSBzaWFubyBjb2VyZW50aSBjb24gcXVlbGxpIGFjY2V0dGF0aSBkYWxsYSBkaXJldHRpdmFcclxuICAgIGxldCBhY2NlcHRlZDogYm9vbGVhbiA9IHRydWVcclxuICAgIGlmICh0aGlzLmxvYWRNdWx0aXBsZUZpbGVzICE9IHRydWUpXHJcbiAgICAgIGFjY2VwdGVkID0gdGhpcy5hY2NlcHRlZEZpbGVUeXBlcy5pbmNsdWRlcyh0aGlzLnNlbGVjdGVkRmlsZS50eXBlKTtcclxuICAgIGVsc2Uge1xyXG4gICAgICBsZXQgdXBsb2FkZWRGaWxlVHlwZXM6IHN0cmluZ1tdID0gWy4uLnRoaXMuc2VsZWN0ZWRGaWxlc10ubWFwKHAgPT4gcC50eXBlKTtcclxuICAgICAgdXBsb2FkZWRGaWxlVHlwZXMuZm9yRWFjaCh0eXBlID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMuYWNjZXB0ZWRGaWxlVHlwZXMuaW5jbHVkZXModHlwZSkpXHJcbiAgICAgICAgICBhY2NlcHRlZCA9IGZhbHNlO1xyXG4gICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvL1F1ZXN0byBjb250cm9sbG8gcGVybWV0dGUgZGkgZ2VzdGlyZSBsZSBjYXNpc3RpY2hlIHBlciBjdWkgdmVuZ29ubyBpbmRpY2F0aSBjb21lIHRpcGkgdmFsaWRpLCBhZCBlc2VtcGlvLCAnaW1hZ2UvKidcclxuICAgIGlmICghYWNjZXB0ZWQgJiYgdGhpcy5sb2FkTXVsdGlwbGVGaWxlcyAhPSB0cnVlKSB7XHJcbiAgICAgIGZvciAobGV0IHQgb2YgdGhpcy5hY2NlcHRlZEZpbGVUeXBlcy5zcGxpdChcIixcIikuZmlsdGVyKHQgPT4gdC5pbmNsdWRlcyhcIipcIikpKSB7XHJcbiAgICAgICAgYWNjZXB0ZWQgPSB0aGlzLnNlbGVjdGVkRmlsZS50eXBlLnN0YXJ0c1dpdGgodC5zcGxpdChcIipcIilbMF0pO1xyXG4gICAgICAgIGlmIChhY2NlcHRlZClcclxuICAgICAgICAgIGJyZWFrO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gYWNjZXB0ZWQ7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZSBlcXAtYXR0YWNobWVudHMgw6ggc3RhdGEgY29uZmlndXJhdGEgcGVyIGlsIGNhcmljYW1lbnRvIGRlbGxlIHNvbGUgaW1tYWdpbmkgYWxsb3JhIHZlcmlmaWNhIGNoZSBpbCBmaWxlIHBhc3NhdG8gaW5cclxuICAgKiBpbnB1dCBzaWEgZWZmZXR0aXZhbWVudGUgdW4gaW1tYWdpbmUgbyBuby5cclxuICAgKiBTZSBpbCBjb250cm9sbG8gdmEgYSBidW9uIGZpbmUgcmVzdGl0dWlzY2UgVFJVRSBhbHRyaW1lbnRpIG1vc3RyYSB1biBtZXNzYWdnaW8gZCdlcnJvcmUgZSByZXN0aXR1aXNjZSBGQUxTRVxyXG4gICAqL1xyXG4gIHByaXZhdGUgY2hlY2tBbGxvd09ubHlJbWFnZUZpbGUobmV3QXR0YWNobWVudCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMuYWxsb3dPbmx5SW1hZ2VzID09IHRydWUgJiYgbmV3QXR0YWNobWVudC5Jc0ltYWdlICE9IHRydWUpIHtcclxuICAgICAgRXFwQXR0YWNobWVudERpYWxvZ1NlcnZpY2UuRXJyb3IodGhpcy5ub0ltYWdlU2VsZWN0ZWRFcnJvck1lc3NhZ2UpO1xyXG4gICAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9IGVsc2UgaWYgKCF0aGlzLmNoZWNrQWNjZXB0ZWRGaWxlcygpKSB7XHJcbiAgICAgIEVxcEF0dGFjaG1lbnREaWFsb2dTZXJ2aWNlLkVycm9yKHRoaXMud3JvbmdUeXBlU2VsZWN0ZWRFcnJvck1lc3NhZ2UpO1xyXG4gICAgICB0aGlzLmFib3J0RmlsZSgpO1xyXG4gICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHRydWU7XHJcbiAgfVxyXG5cclxuICBnZXRJbWFnZURpbWVuc2lvbnMoaW1nOiBhbnkpIHtcclxuICAgIGNvbnN0IHJlYWRlciA9IG5ldyBGaWxlUmVhZGVyKCk7XHJcbiAgICByZWFkZXIub25sb2FkID0gKGU6IGFueSkgPT4ge1xyXG4gICAgICBjb25zdCBpbWFnZSA9IG5ldyBJbWFnZSgpO1xyXG4gICAgICBpbWFnZS5zcmMgPSBlLnRhcmdldC5yZXN1bHQ7XHJcbiAgICAgIGltYWdlLm9ubG9hZCA9IHJzID0+IHtcclxuICAgICAgICB0aGlzLm9yaWdpbmFsSGVpZ2h0ID0gcnMuY3VycmVudFRhcmdldFsnaGVpZ2h0J107XHJcbiAgICAgICAgdGhpcy5vcmlnaW5hbFdpZHRoID0gcnMuY3VycmVudFRhcmdldFsnd2lkdGgnXTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMub3JpZ2luYWxXaWR0aCA+IDEyODApIHtcclxuICAgICAgICAgIHRoaXMuY3VzdG9tV2lkdGggPSAxMjgwO1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21IZWlnaHQgPSBNYXRoLnJvdW5kKCgxMjgwICogdGhpcy5vcmlnaW5hbEhlaWdodCkgLyB0aGlzLm9yaWdpbmFsV2lkdGgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICB0aGlzLmN1c3RvbUhlaWdodCA9IHJzLmN1cnJlbnRUYXJnZXRbJ2hlaWdodCddO1xyXG4gICAgICAgICAgdGhpcy5jdXN0b21XaWR0aCA9IHJzLmN1cnJlbnRUYXJnZXRbJ3dpZHRoJ107XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG4gICAgfTtcclxuICAgIHJlYWRlci5yZWFkQXNEYXRhVVJMKGltZyk7XHJcbiAgfVxyXG5cclxuICByZXN0b3JlT3JpZ2luYWxEaW1lbnNpb25zKCkge1xyXG4gICAgdGhpcy5jdXN0b21XaWR0aCA9IHRoaXMub3JpZ2luYWxXaWR0aDtcclxuICAgIHRoaXMuY3VzdG9tSGVpZ2h0ID0gdGhpcy5vcmlnaW5hbEhlaWdodDtcclxuICB9XHJcblxyXG4gIG9uRGltZW5zaW9uc0NoYW5nZShkaW1lbnNpb246IHN0cmluZykge1xyXG4gICAgaWYgKGRpbWVuc2lvbiA9PSBcIkhcIikge1xyXG4gICAgICB0aGlzLmN1c3RvbVdpZHRoID0gTWF0aC5yb3VuZCgodGhpcy5jdXN0b21IZWlnaHQgKiB0aGlzLm9yaWdpbmFsV2lkdGgpIC8gdGhpcy5vcmlnaW5hbEhlaWdodCk7XHJcbiAgICB9IGVsc2UgaWYgKGRpbWVuc2lvbiA9PSBcIldcIikge1xyXG4gICAgICB0aGlzLmN1c3RvbUhlaWdodCA9IE1hdGgucm91bmQoKHRoaXMuY3VzdG9tV2lkdGggKiB0aGlzLm9yaWdpbmFsSGVpZ2h0KSAvIHRoaXMub3JpZ2luYWxXaWR0aCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpbWFnZUNyb3BwZWQoZXZlbnQ6IEltYWdlQ3JvcHBlZEV2ZW50KSB7XHJcbiAgICB0aGlzLmNyb3BwZWRJbWFnZSA9IGV2ZW50LmJhc2U2NDtcclxuICAgIHRoaXMuZ2V0Q3JvcHBlZEFuZFVwbG9hZCh0aGlzLmNyb3BwZWRJbWFnZSk7XHJcbiAgfVxyXG5cclxuICBnZXRDcm9wcGVkQW5kVXBsb2FkKGZpbGUpIHtcclxuICAgIHZhciBzZWxmID0gdGhpcztcclxuXHJcbiAgICB2YXIgZmlsZTogYW55ID0gYmFzZTY0VG9GaWxlKGZpbGUpO1xyXG5cclxuICAgIGNvbnN0IG9wdGlvbnMgPSB0aGlzLmNvbXByZXNzaW9uT3B0aW9ucztcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbXByaW1lIGwnaW1tYWdpbmUgcGFzc2FuZG8gY29tZSBwYXJhbWV0cmkgbGUgb3B0aW9ucyBjcmVhdGUgbmVsbCdvZ2dldHRvIHNvcHJhLCBlIGlsIGZpbGUgZGFsIHJlYWRlciBwcmluY2lwYWxlXHJcbiAgICAgKi9cclxuICAgIGltYWdlQ29tcHJlc3Npb24oZmlsZSwgb3B0aW9ucykudGhlbigoZmlsZUNvbXByZXNzZWQgPT4ge1xyXG5cclxuICAgICAgbGV0IGZpbGVSZWFkZXIgPSBuZXcgRmlsZVJlYWRlcigpO1xyXG5cclxuICAgICAgLy9GYWNjaW8gbGEgcHVzaCBkaSBvZ25pIGZpbGUgYWxsJ2ludGVybm8gZGVsbCdhcnJheSBkaSBmaWxlIGRlbGwnaXRlbSBkYSBtYW5kYXJlIGFsIHNlcnZlclxyXG4gICAgICBmaWxlUmVhZGVyLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICBsZXQgcmVzdWx0UmVhZGVyID0gPHN0cmluZz5maWxlUmVhZGVyLnJlc3VsdDtcclxuICAgICAgICB2YXIgbWFya2VyID0gJztiYXNlNjQsJztcclxuICAgICAgICBzZWxmLm5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSByZXN1bHRSZWFkZXIuc3Vic3RyaW5nKHJlc3VsdFJlYWRlci5pbmRleE9mKG1hcmtlcikgKyBtYXJrZXIubGVuZ3RoKTtcclxuICAgICAgICBzZWxmLnNob3dDcm9wSW1hZ2UgPSBmYWxzZTtcclxuICAgICAgICBzZWxmLm5ld0F0dGFjaG1lbnRGb3JtLmVuYWJsZSgpO1xyXG4gICAgICB9O1xyXG5cclxuICAgICAgZmlsZVJlYWRlci5yZWFkQXNEYXRhVVJMKGZpbGVDb21wcmVzc2VkKTtcclxuXHJcbiAgICB9KSk7XHJcblxyXG4gIH1cclxuXHJcbiAgY29uZmlybUNyb3AoKSB7XHJcbiAgICB0aGlzLmltYWdlQ3JvcHBlci5jcm9wKCk7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBbm51bGxhIGxhIHNlbGV6aW9uZSBkZWwgZmlsZSwgc3Z1b3RhbmRvIGwnaW5wdXQgZSByZXNldHRhbmRvIHR1dHRlIGxlIHByb3ByaWV0w6AgZGVsbCdJQXR0YWNobWVudERUT1xyXG4gICAqL1xyXG4gIGFib3J0RmlsZSgpIHtcclxuICAgIHRoaXMuaW1hZ2VDaGFuZ2VkRXZlbnQgPSAnJztcclxuICAgIGlmICh0aGlzLmltYWdlSW5wdXQpXHJcbiAgICAgIHRoaXMuaW1hZ2VJbnB1dC5uYXRpdmVFbGVtZW50LnZhbHVlID0gJyc7XHJcblxyXG4gICAgdGhpcy5zZWxlY3RlZEZpbGUgPSBudWxsO1xyXG4gICAgdGhpcy5zZWxlY3RlZEZpbGVzID0gbnVsbDtcclxuICAgIHRoaXMuc2hvd0Nyb3BJbWFnZSA9IGZhbHNlO1xyXG5cclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5Jc0ltYWdlID0gZmFsc2U7XHJcbiAgICB0aGlzLm5ld0F0dGFjaG1lbnQuRmlsZURhdGFCYXNlNjQgPSBudWxsO1xyXG4gICAgdGhpcy5uZXdBdHRhY2htZW50LkZpbGVOYW1lID0gbnVsbDtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlRXh0ZW5zaW9uID0gbnVsbDtcclxuICAgIHRoaXMubmV3QXR0YWNobWVudC5GaWxlQ29udGVudFR5cGUgPSBudWxsO1xyXG5cclxuICAgIHRoaXMubmV3TXVsdGlwbGVBdHRhY2htZW50cyA9IG5ldyBBcnJheTxJQXR0YWNobWVudERUTz4oKTtcclxuXHJcbiAgICB0aGlzLmN1c3RvbUhlaWdodCA9IG51bGw7XHJcbiAgICB0aGlzLmN1c3RvbVdpZHRoID0gbnVsbDtcclxuICAgIHRoaXMub3JpZ2luYWxIZWlnaHQgPSBudWxsO1xyXG4gICAgdGhpcy5vcmlnaW5hbFdpZHRoID0gbnVsbDtcclxuICB9XHJcblxyXG4gIC8vI2VuZHJlZ2lvblxyXG59Il19