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