@eqproject/eqp-attachments 3.1.13 → 21.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +591 -433
- package/fesm2022/eqproject-eqp-attachments.mjs +381 -558
- package/fesm2022/eqproject-eqp-attachments.mjs.map +1 -1
- package/package.json +6 -8
- package/types/eqproject-eqp-attachments.d.ts +581 -0
- package/esm2022/eqproject-eqp-attachments.mjs +0 -5
- package/esm2022/lib/eqp-attachments.component.mjs +0 -1588
- package/esm2022/lib/eqp-attachments.module.mjs +0 -35
- package/esm2022/lib/helpers/attachment.helper.mjs +0 -66
- package/esm2022/lib/interfaces/IAttachment.mjs +0 -18
- package/esm2022/lib/interfaces/IOptions.mjs +0 -2
- package/esm2022/lib/modules/material.module.mjs +0 -231
- package/esm2022/lib/services/eqp-attachment-dialog.service.mjs +0 -103
- package/esm2022/lib/services/eqp-attachment.service.mjs +0 -23
- package/esm2022/public-api.mjs +0 -10
- package/index.d.ts +0 -5
- package/lib/eqp-attachments.component.d.ts +0 -413
- package/lib/eqp-attachments.module.d.ts +0 -11
- package/lib/helpers/attachment.helper.d.ts +0 -20
- package/lib/interfaces/IAttachment.d.ts +0 -53
- package/lib/interfaces/IOptions.d.ts +0 -11
- package/lib/modules/material.module.d.ts +0 -37
- package/lib/services/eqp-attachment-dialog.service.d.ts +0 -31
- package/lib/services/eqp-attachment.service.d.ts +0 -7
- package/public-api.d.ts +0 -6
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable,
|
|
2
|
+
import { Injectable, input, output, viewChild, signal, computed, effect, Input, Component, NgModule } from '@angular/core';
|
|
3
3
|
import * as i2 from '@angular/forms';
|
|
4
4
|
import { Validators, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
5
5
|
import imageCompression from 'browser-image-compression';
|
|
6
|
-
import * as
|
|
7
|
-
import {
|
|
6
|
+
import * as i13 from 'ngx-image-cropper';
|
|
7
|
+
import { ImageCropperComponent, base64ToFile } from 'ngx-image-cropper';
|
|
8
8
|
import Swal from 'sweetalert2';
|
|
9
9
|
import * as i1 from '@angular/material/dialog';
|
|
10
10
|
import { MatDialogModule } from '@angular/material/dialog';
|
|
@@ -14,21 +14,20 @@ import * as i6 from '@angular/material/button';
|
|
|
14
14
|
import { MatButtonModule } from '@angular/material/button';
|
|
15
15
|
import * as i7 from '@angular/material/input';
|
|
16
16
|
import { MatInputModule } from '@angular/material/input';
|
|
17
|
-
import * as i8 from '@angular/material/
|
|
18
|
-
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
19
|
-
import * as i9 from '@angular/material/menu';
|
|
17
|
+
import * as i8 from '@angular/material/menu';
|
|
20
18
|
import { MatMenuModule } from '@angular/material/menu';
|
|
21
|
-
import * as
|
|
19
|
+
import * as i9 from '@angular/material/button-toggle';
|
|
22
20
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
23
|
-
import * as
|
|
21
|
+
import * as i10 from '@angular/material/icon';
|
|
24
22
|
import { MatIconModule } from '@angular/material/icon';
|
|
25
|
-
import * as
|
|
23
|
+
import * as i11 from '@angular/material/tooltip';
|
|
26
24
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
27
|
-
import * as
|
|
25
|
+
import * as i12 from '@angular/common';
|
|
28
26
|
import { CommonModule } from '@angular/common';
|
|
29
27
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
30
28
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
|
31
29
|
import { MatDatepickerModule } from '@angular/material/datepicker';
|
|
30
|
+
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
32
31
|
import { MatRadioModule } from '@angular/material/radio';
|
|
33
32
|
import { MatSelectModule } from '@angular/material/select';
|
|
34
33
|
import { MatSliderModule } from '@angular/material/slider';
|
|
@@ -104,10 +103,10 @@ class AttachmentHelperService {
|
|
|
104
103
|
let fileIcon = this.fileExtensionIcon[extension];
|
|
105
104
|
return fileIcon ?? "fas fa-file";
|
|
106
105
|
}
|
|
107
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
108
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
106
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AttachmentHelperService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
107
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AttachmentHelperService, providedIn: 'root' });
|
|
109
108
|
}
|
|
110
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
109
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: AttachmentHelperService, decorators: [{
|
|
111
110
|
type: Injectable,
|
|
112
111
|
args: [{
|
|
113
112
|
providedIn: 'root'
|
|
@@ -222,10 +221,10 @@ class EqpAttachmentDialogService {
|
|
|
222
221
|
Swal.fire(currentTitle, message, 'warning');
|
|
223
222
|
}
|
|
224
223
|
}
|
|
225
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
226
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
224
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentDialogService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
225
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentDialogService, providedIn: 'root' });
|
|
227
226
|
}
|
|
228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
227
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentDialogService, decorators: [{
|
|
229
228
|
type: Injectable,
|
|
230
229
|
args: [{
|
|
231
230
|
providedIn: 'root'
|
|
@@ -242,10 +241,10 @@ class EqpAttachmentService {
|
|
|
242
241
|
script.dataset.appKey = AttachmentHelperService.dropboxCredentials.apiKey;
|
|
243
242
|
document.body.appendChild(script);
|
|
244
243
|
}
|
|
245
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
246
|
-
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "
|
|
244
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
245
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentService, providedIn: "root" });
|
|
247
246
|
}
|
|
248
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
247
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentService, decorators: [{
|
|
249
248
|
type: Injectable,
|
|
250
249
|
args: [{
|
|
251
250
|
providedIn: "root"
|
|
@@ -268,11 +267,11 @@ class EqpAttachmentsComponent {
|
|
|
268
267
|
/**
|
|
269
268
|
* Se TRUE allora nasconde la colonna per le azioni sull'allegato (nel caso "multipleAttachment" è TRUE).
|
|
270
269
|
*/
|
|
271
|
-
disableAction = false;
|
|
270
|
+
disableAction = input(false, ...(ngDevMode ? [{ debugName: "disableAction" }] : /* istanbul ignore next */ []));
|
|
272
271
|
/**
|
|
273
272
|
* Se TRUE mostra il titolo nell'header nel caso in cui "multipleAttachment" è TRUE ("Elenco allegati" di default).
|
|
274
273
|
*/
|
|
275
|
-
showHeader = true;
|
|
274
|
+
showHeader = input(true, ...(ngDevMode ? [{ debugName: "showHeader" }] : /* istanbul ignore next */ []));
|
|
276
275
|
/**
|
|
277
276
|
* Sorgente dati da visualizzare. Nel caso si vuole gestire un singolo allegato va passato in ogni caso come Array.
|
|
278
277
|
*/
|
|
@@ -280,31 +279,31 @@ class EqpAttachmentsComponent {
|
|
|
280
279
|
/**
|
|
281
280
|
* Nel caso si vuole gestire un solo elemento senza passarlo come array, lo passo come singolo allegato e gestisco nella libreria l'array.
|
|
282
281
|
*/
|
|
283
|
-
singleAttachment = null;
|
|
282
|
+
singleAttachment = input(null, ...(ngDevMode ? [{ debugName: "singleAttachment" }] : /* istanbul ignore next */ []));
|
|
284
283
|
/**
|
|
285
284
|
* Se TRUE non mostra la MatCard (nel caso in cui "multipleAttachment" è TRUE).
|
|
286
285
|
*/
|
|
287
|
-
showMatCard = true;
|
|
286
|
+
showMatCard = input(true, ...(ngDevMode ? [{ debugName: "showMatCard" }] : /* istanbul ignore next */ []));
|
|
288
287
|
/**
|
|
289
288
|
* 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".
|
|
290
289
|
* Se TRUE allora il componente mostra l'elenco di tutti gli allegati ricevuto nel parametro "attachmentsList".
|
|
291
290
|
*/
|
|
292
|
-
multipleAttachment = true;
|
|
291
|
+
multipleAttachment = input(true, ...(ngDevMode ? [{ debugName: "multipleAttachment" }] : /* istanbul ignore next */ []));
|
|
293
292
|
/**
|
|
294
293
|
* Se assume il valore TRUE allora sarà possibile caricare più file per volta. Questa funzionalità è attiva
|
|
295
294
|
* SOLO se si gestiscono allegati multipli, quindi se l'input 'multipleAttachment' assume il valore TRUE, altrimenti è sempre disabilitata.
|
|
296
295
|
*/
|
|
297
|
-
loadMultipleFiles = false;
|
|
296
|
+
loadMultipleFiles = input(false, ...(ngDevMode ? [{ debugName: "loadMultipleFiles" }] : /* istanbul ignore next */ []));
|
|
298
297
|
/**
|
|
299
298
|
* Imposta il messaggio da visualizzare nel caso in cui la tabella degli allegati (nel caso in cui "multipleAttachment" è TRUE) è vuota.
|
|
300
299
|
*/
|
|
301
|
-
emptyTableMessage = "Nessun dato trovato";
|
|
300
|
+
emptyTableMessage = input("Nessun dato trovato", ...(ngDevMode ? [{ debugName: "emptyTableMessage" }] : /* istanbul ignore next */ []));
|
|
302
301
|
/**
|
|
303
302
|
* Se TRUE allora permette di selezionare soltanto file di tipo immagine, avente uno dei mimetype
|
|
304
303
|
* specificati dentro AttachmentHelperService.
|
|
305
304
|
* Se FALSE permette di selezionare qualsiasi tipo di file
|
|
306
305
|
*/
|
|
307
|
-
allowOnlyImages = false;
|
|
306
|
+
allowOnlyImages = input(false, ...(ngDevMode ? [{ debugName: "allowOnlyImages" }] : /* istanbul ignore next */ []));
|
|
308
307
|
/**
|
|
309
308
|
* Specifica i tipi di file che è possibile caricare
|
|
310
309
|
*/
|
|
@@ -312,57 +311,60 @@ class EqpAttachmentsComponent {
|
|
|
312
311
|
/**
|
|
313
312
|
* Se TRUE disabilita il pulsante di Aggiunta allegato (a prescindere dal valore del parametro "multipleAttachment").
|
|
314
313
|
*/
|
|
315
|
-
isDisabled = false;
|
|
314
|
+
isDisabled = input(false, ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
316
315
|
/**
|
|
317
316
|
* Mostra/nasconde la colonna per visualizzare l'anteprima dei file nella tabella (caso multipleAtatchments = true).
|
|
318
317
|
*/
|
|
319
|
-
showInlinePreview = false;
|
|
318
|
+
showInlinePreview = input(false, ...(ngDevMode ? [{ debugName: "showInlinePreview" }] : /* istanbul ignore next */ []));
|
|
320
319
|
/**
|
|
321
320
|
* Endpoint da chiamare per recueprare l'IAttachmentDTO completo da vedere nell'anteprima. La chiamata sarà in POST e nel body
|
|
322
321
|
* conterrà l'IAttachmentDTO selezionato dall'utente.
|
|
323
322
|
* La chiamata viene eseguita solo per l'anteprima delle immagini essendo necessario il base64 completo dell'immagine a dimensione reale.
|
|
324
323
|
* Per documenti/link basta che sia popolata la proprietà FilePath di IAttachmentDTO.
|
|
325
324
|
*/
|
|
326
|
-
getAttachmentEndpoint = null;
|
|
325
|
+
getAttachmentEndpoint = input(null, ...(ngDevMode ? [{ debugName: "getAttachmentEndpoint" }] : /* istanbul ignore next */ []));
|
|
327
326
|
/**
|
|
328
327
|
* Hostname dell'ambiente di produzione dell'applicativo. Necessario per visualizzare l'anteprima dei documenti
|
|
329
328
|
* tramite il viewer di google.
|
|
330
329
|
* NOTA: Per visualizzare l'anteprima è necessario che la prorietà FilePath dell'IAttachmentDTO sia popolata e che
|
|
331
330
|
* sia abilitato l'accesso alla cartella sul server tramite hostname.
|
|
332
331
|
*/
|
|
333
|
-
productionBaseUrl = null;
|
|
332
|
+
productionBaseUrl = input(null, ...(ngDevMode ? [{ debugName: "productionBaseUrl" }] : /* istanbul ignore next */ []));
|
|
334
333
|
/**
|
|
335
334
|
* Opzioni per la compressione delle immagini caricate.
|
|
336
335
|
*/
|
|
337
|
-
compressionOptions = {
|
|
336
|
+
compressionOptions = input({
|
|
338
337
|
maxSizeMB: 0.5,
|
|
339
338
|
maxWidthOrHeight: 1920,
|
|
340
|
-
useWebWorker: true
|
|
341
|
-
};
|
|
339
|
+
useWebWorker: true,
|
|
340
|
+
}, ...(ngDevMode ? [{ debugName: "compressionOptions" }] : /* istanbul ignore next */ []));
|
|
342
341
|
/**
|
|
343
342
|
* Array di AttachmentType che si possono aggiungere
|
|
344
343
|
*/
|
|
345
|
-
allowedTypes = [
|
|
344
|
+
allowedTypes = [
|
|
345
|
+
AttachmentType.FILE,
|
|
346
|
+
AttachmentType.LINK,
|
|
347
|
+
];
|
|
346
348
|
/**
|
|
347
349
|
* Permette di stabilire se la eqp-table contenente l'elenco degli allegati utilizza
|
|
348
350
|
* il multilingua oppure no
|
|
349
351
|
*/
|
|
350
|
-
isEqpTableMultiLanguage = false;
|
|
352
|
+
isEqpTableMultiLanguage = input(false, ...(ngDevMode ? [{ debugName: "isEqpTableMultiLanguage" }] : /* istanbul ignore next */ []));
|
|
351
353
|
/**
|
|
352
354
|
* Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
|
|
353
355
|
* degli allegati deve essere paginata oppure no
|
|
354
356
|
*/
|
|
355
|
-
tablePaginatorVisible = true;
|
|
357
|
+
tablePaginatorVisible = input(true, ...(ngDevMode ? [{ debugName: "tablePaginatorVisible" }] : /* istanbul ignore next */ []));
|
|
356
358
|
/**
|
|
357
359
|
* Permette di stabilire, in caso di gestione allegati multipli, se la tabella contenente l'elenco
|
|
358
360
|
* degli allegati deve contenere il campo di ricerca oppure no
|
|
359
361
|
*/
|
|
360
|
-
isTableSearcheable = true;
|
|
362
|
+
isTableSearcheable = input(true, ...(ngDevMode ? [{ debugName: "isTableSearcheable" }] : /* istanbul ignore next */ []));
|
|
361
363
|
/**
|
|
362
364
|
* In caso di gestione allegati multipli, permette di stabilire la dimensione pagina di default
|
|
363
365
|
* per la tabella contenente l'elenco degli allegati
|
|
364
366
|
*/
|
|
365
|
-
tablePaginatorSize = null;
|
|
367
|
+
tablePaginatorSize = input(null, ...(ngDevMode ? [{ debugName: "tablePaginatorSize" }] : /* istanbul ignore next */ []));
|
|
366
368
|
/**
|
|
367
369
|
* Permette di scegliere il modo in cui i file devono essere caricati
|
|
368
370
|
*/
|
|
@@ -370,127 +372,124 @@ class EqpAttachmentsComponent {
|
|
|
370
372
|
/**
|
|
371
373
|
* Permette di stabilire se i pulsanti per il caricamento dei file sono separati o in un menù a tendina
|
|
372
374
|
*/
|
|
373
|
-
separatedUploadButtons = false;
|
|
375
|
+
separatedUploadButtons = input(false, ...(ngDevMode ? [{ debugName: "separatedUploadButtons" }] : /* istanbul ignore next */ []));
|
|
374
376
|
/**
|
|
375
377
|
* Permette di scegliere se dare la possibilità di vedere o no l'anteprima
|
|
376
378
|
*/
|
|
377
|
-
showPreview = true;
|
|
379
|
+
showPreview = input(true, ...(ngDevMode ? [{ debugName: "showPreview" }] : /* istanbul ignore next */ []));
|
|
378
380
|
/**
|
|
379
381
|
* In caso di allegato singolo, permette di scegliere se aggiungere file tramite drag and drop
|
|
380
382
|
*/
|
|
381
|
-
singleAttachmentDragAndDrop = true;
|
|
383
|
+
singleAttachmentDragAndDrop = input(true, ...(ngDevMode ? [{ debugName: "singleAttachmentDragAndDrop" }] : /* istanbul ignore next */ []));
|
|
382
384
|
/**
|
|
383
385
|
* Array di opzioni che si possono utilizzare per il crop
|
|
384
386
|
*/
|
|
385
|
-
cropOptions = [1, 2];
|
|
387
|
+
cropOptions = input([1, 2], ...(ngDevMode ? [{ debugName: "cropOptions" }] : /* istanbul ignore next */ []));
|
|
386
388
|
/**
|
|
387
389
|
* Classe custom da assegnare al dialog del crop immagini
|
|
388
390
|
*/
|
|
389
|
-
cropDialogClass;
|
|
390
|
-
maxFileSizeMB = 500; // Default max size of 100 MB
|
|
391
|
-
cardSize =
|
|
392
|
-
customCardWidthPx = 200; // Larghezza custom in px
|
|
393
|
-
customCardHeightPx = 180; // Altezza custom in px
|
|
394
|
-
layout =
|
|
391
|
+
cropDialogClass = input(undefined, ...(ngDevMode ? [{ debugName: "cropDialogClass" }] : /* istanbul ignore next */ []));
|
|
392
|
+
maxFileSizeMB = input(500, ...(ngDevMode ? [{ debugName: "maxFileSizeMB" }] : /* istanbul ignore next */ [])); // Default max size of 100 MB
|
|
393
|
+
cardSize = input("small", ...(ngDevMode ? [{ debugName: "cardSize" }] : /* istanbul ignore next */ [])); // Default
|
|
394
|
+
customCardWidthPx = input(200, ...(ngDevMode ? [{ debugName: "customCardWidthPx" }] : /* istanbul ignore next */ [])); // Larghezza custom in px
|
|
395
|
+
customCardHeightPx = input(180, ...(ngDevMode ? [{ debugName: "customCardHeightPx" }] : /* istanbul ignore next */ [])); // Altezza custom in px
|
|
396
|
+
layout = input("compact", ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
|
|
395
397
|
/**
|
|
396
398
|
* Input per definire le label da usare nel componente
|
|
397
399
|
*/
|
|
398
|
-
openLinkLabel = "Apri link";
|
|
399
|
-
addButtonLabel = "Aggiungi";
|
|
400
|
-
downloadLabel = "Download";
|
|
401
|
-
deleteLabel = "Elimina";
|
|
402
|
-
fileNameLabel = "Nome file";
|
|
403
|
-
previewLabel = "Anteprima";
|
|
404
|
-
uploadFileLabel = "Carica file";
|
|
405
|
-
confirmLabel = "Conferma";
|
|
406
|
-
abortLabel = "Annulla";
|
|
407
|
-
saveLabel = "Salva";
|
|
408
|
-
exitLabel = "Esci";
|
|
409
|
-
uploadWithDropboxLabel = "Carica con Dropbox";
|
|
410
|
-
cropLabel = "Scegli le dimensioni dell'immagine";
|
|
411
|
-
deleteDialogTitle = null;
|
|
412
|
-
deleteDialogMessage = "Sei sicuro di voler cancellare quest'allegato?";
|
|
413
|
-
noImageSelectedErrorMessage = "Non è possibile selezionare un file che non sia un'immagine.";
|
|
414
|
-
wrongTypeSelectedErrorMessage = "Non è possibile caricare il file selezionato.";
|
|
415
|
-
videoPreviewErrorMessage = "Impossibile aprire l'anteprima di un file video.";
|
|
416
|
-
audioPreviewErrorMessage = "Impossibile aprire l'anteprima di un file audio.";
|
|
417
|
-
flipHorinzontalLabel = "Capovolgi orizzontalmente";
|
|
418
|
-
flipVerticalLabel = "Capovolgi verticalmente";
|
|
419
|
-
rotateRightLabel = "Ruota a destra";
|
|
420
|
-
rotateLeftLabel = "Ruota a sinistra";
|
|
421
|
-
base64LimitMB = 100;
|
|
422
|
-
uploadTitle =
|
|
423
|
-
uploadSubtitle =
|
|
424
|
-
dropHereLabel =
|
|
425
|
-
supportedFormatsLabel =
|
|
426
|
-
browseFilesLabel =
|
|
427
|
-
uploadSummaryLabel =
|
|
428
|
-
filesLabel =
|
|
429
|
-
totalSizeLabel =
|
|
430
|
-
emptyStateLabel =
|
|
431
|
-
addedSuccessfullyLabel =
|
|
432
|
-
removedLabel =
|
|
400
|
+
openLinkLabel = input("Apri link", ...(ngDevMode ? [{ debugName: "openLinkLabel" }] : /* istanbul ignore next */ []));
|
|
401
|
+
addButtonLabel = input("Aggiungi", ...(ngDevMode ? [{ debugName: "addButtonLabel" }] : /* istanbul ignore next */ []));
|
|
402
|
+
downloadLabel = input("Download", ...(ngDevMode ? [{ debugName: "downloadLabel" }] : /* istanbul ignore next */ []));
|
|
403
|
+
deleteLabel = input("Elimina", ...(ngDevMode ? [{ debugName: "deleteLabel" }] : /* istanbul ignore next */ []));
|
|
404
|
+
fileNameLabel = input("Nome file", ...(ngDevMode ? [{ debugName: "fileNameLabel" }] : /* istanbul ignore next */ []));
|
|
405
|
+
previewLabel = input("Anteprima", ...(ngDevMode ? [{ debugName: "previewLabel" }] : /* istanbul ignore next */ []));
|
|
406
|
+
uploadFileLabel = input("Carica file", ...(ngDevMode ? [{ debugName: "uploadFileLabel" }] : /* istanbul ignore next */ []));
|
|
407
|
+
confirmLabel = input("Conferma", ...(ngDevMode ? [{ debugName: "confirmLabel" }] : /* istanbul ignore next */ []));
|
|
408
|
+
abortLabel = input("Annulla", ...(ngDevMode ? [{ debugName: "abortLabel" }] : /* istanbul ignore next */ []));
|
|
409
|
+
saveLabel = input("Salva", ...(ngDevMode ? [{ debugName: "saveLabel" }] : /* istanbul ignore next */ []));
|
|
410
|
+
exitLabel = input("Esci", ...(ngDevMode ? [{ debugName: "exitLabel" }] : /* istanbul ignore next */ []));
|
|
411
|
+
uploadWithDropboxLabel = input("Carica con Dropbox", ...(ngDevMode ? [{ debugName: "uploadWithDropboxLabel" }] : /* istanbul ignore next */ []));
|
|
412
|
+
cropLabel = input("Scegli le dimensioni dell'immagine", ...(ngDevMode ? [{ debugName: "cropLabel" }] : /* istanbul ignore next */ []));
|
|
413
|
+
deleteDialogTitle = input(null, ...(ngDevMode ? [{ debugName: "deleteDialogTitle" }] : /* istanbul ignore next */ []));
|
|
414
|
+
deleteDialogMessage = input("Sei sicuro di voler cancellare quest'allegato?", ...(ngDevMode ? [{ debugName: "deleteDialogMessage" }] : /* istanbul ignore next */ []));
|
|
415
|
+
noImageSelectedErrorMessage = input("Non è possibile selezionare un file che non sia un'immagine.", ...(ngDevMode ? [{ debugName: "noImageSelectedErrorMessage" }] : /* istanbul ignore next */ []));
|
|
416
|
+
wrongTypeSelectedErrorMessage = input("Non è possibile caricare il file selezionato.", ...(ngDevMode ? [{ debugName: "wrongTypeSelectedErrorMessage" }] : /* istanbul ignore next */ []));
|
|
417
|
+
videoPreviewErrorMessage = input("Impossibile aprire l'anteprima di un file video.", ...(ngDevMode ? [{ debugName: "videoPreviewErrorMessage" }] : /* istanbul ignore next */ []));
|
|
418
|
+
audioPreviewErrorMessage = input("Impossibile aprire l'anteprima di un file audio.", { ...(ngDevMode ? { debugName: "audioPreviewErrorMessage" } : /* istanbul ignore next */ {}), alias: "videoPreviewErrorMessage" });
|
|
419
|
+
flipHorinzontalLabel = input("Capovolgi orizzontalmente", ...(ngDevMode ? [{ debugName: "flipHorinzontalLabel" }] : /* istanbul ignore next */ []));
|
|
420
|
+
flipVerticalLabel = input("Capovolgi verticalmente", ...(ngDevMode ? [{ debugName: "flipVerticalLabel" }] : /* istanbul ignore next */ []));
|
|
421
|
+
rotateRightLabel = input("Ruota a destra", ...(ngDevMode ? [{ debugName: "rotateRightLabel" }] : /* istanbul ignore next */ []));
|
|
422
|
+
rotateLeftLabel = input("Ruota a sinistra", ...(ngDevMode ? [{ debugName: "rotateLeftLabel" }] : /* istanbul ignore next */ []));
|
|
423
|
+
base64LimitMB = input(100, ...(ngDevMode ? [{ debugName: "base64LimitMB" }] : /* istanbul ignore next */ []));
|
|
424
|
+
uploadTitle = input("Upload file", ...(ngDevMode ? [{ debugName: "uploadTitle" }] : /* istanbul ignore next */ []));
|
|
425
|
+
uploadSubtitle = input("Drag & drop files o click", ...(ngDevMode ? [{ debugName: "uploadSubtitle" }] : /* istanbul ignore next */ []));
|
|
426
|
+
dropHereLabel = input("Rilascia i file qui", ...(ngDevMode ? [{ debugName: "dropHereLabel" }] : /* istanbul ignore next */ []));
|
|
427
|
+
supportedFormatsLabel = input("Formati supportati: JPEG, PNG, PDF (Max 100MB)", ...(ngDevMode ? [{ debugName: "supportedFormatsLabel" }] : /* istanbul ignore next */ []));
|
|
428
|
+
browseFilesLabel = input("Cerca i file", ...(ngDevMode ? [{ debugName: "browseFilesLabel" }] : /* istanbul ignore next */ []));
|
|
429
|
+
uploadSummaryLabel = input("Lista allegati", ...(ngDevMode ? [{ debugName: "uploadSummaryLabel" }] : /* istanbul ignore next */ []));
|
|
430
|
+
filesLabel = input("Files", ...(ngDevMode ? [{ debugName: "filesLabel" }] : /* istanbul ignore next */ []));
|
|
431
|
+
totalSizeLabel = input("Dimensione totale", ...(ngDevMode ? [{ debugName: "totalSizeLabel" }] : /* istanbul ignore next */ []));
|
|
432
|
+
emptyStateLabel = input("Non sono presenti file caricati", ...(ngDevMode ? [{ debugName: "emptyStateLabel" }] : /* istanbul ignore next */ []));
|
|
433
|
+
addedSuccessfullyLabel = input("file(s) caricati con successo.", ...(ngDevMode ? [{ debugName: "addedSuccessfullyLabel" }] : /* istanbul ignore next */ []));
|
|
434
|
+
removedLabel = input("File rimosso", ...(ngDevMode ? [{ debugName: "removedLabel" }] : /* istanbul ignore next */ []));
|
|
433
435
|
// @Input() removeLabel = 'Rimuovi file';
|
|
434
|
-
chooseView = true;
|
|
435
|
-
showSummary = false;
|
|
436
|
-
viewMode =
|
|
437
|
-
showUploadTitle = true;
|
|
438
|
-
showDropArea = true;
|
|
439
|
-
hiddenColumns = [];
|
|
440
|
-
hiddenActions = [];
|
|
441
|
-
showActionButtons = false;
|
|
436
|
+
chooseView = input(true, ...(ngDevMode ? [{ debugName: "chooseView" }] : /* istanbul ignore next */ []));
|
|
437
|
+
showSummary = input(false, ...(ngDevMode ? [{ debugName: "showSummary" }] : /* istanbul ignore next */ []));
|
|
438
|
+
viewMode = "table";
|
|
439
|
+
showUploadTitle = input(true, ...(ngDevMode ? [{ debugName: "showUploadTitle" }] : /* istanbul ignore next */ []));
|
|
440
|
+
showDropArea = input(true, ...(ngDevMode ? [{ debugName: "showDropArea" }] : /* istanbul ignore next */ []));
|
|
441
|
+
hiddenColumns = input([], ...(ngDevMode ? [{ debugName: "hiddenColumns" }] : /* istanbul ignore next */ []));
|
|
442
|
+
hiddenActions = input([], ...(ngDevMode ? [{ debugName: "hiddenActions" }] : /* istanbul ignore next */ []));
|
|
443
|
+
showActionButtons = input(false, ...(ngDevMode ? [{ debugName: "showActionButtons" }] : /* istanbul ignore next */ []));
|
|
442
444
|
/**
|
|
443
445
|
* Se TRUE allora mostra il dialog di crop per le immagini singole.
|
|
444
446
|
* Se FALSE carica l'immagine direttamente (applicando comunque la compressione se attiva).
|
|
445
447
|
*/
|
|
446
|
-
enableImageCrop = true;
|
|
448
|
+
enableImageCrop = input(true, ...(ngDevMode ? [{ debugName: "enableImageCrop" }] : /* istanbul ignore next */ []));
|
|
447
449
|
/**
|
|
448
450
|
* Hook globale: decide se nascondere un’azione per quello specifico allegato.
|
|
449
451
|
*/
|
|
450
|
-
actionHiddenFn;
|
|
452
|
+
actionHiddenFn = input(undefined, ...(ngDevMode ? [{ debugName: "actionHiddenFn" }] : /* istanbul ignore next */ []));
|
|
451
453
|
/**
|
|
452
454
|
* Hook globale: decide se disabilitare un’azione per quello specifico allegato.
|
|
453
455
|
*/
|
|
454
|
-
actionDisabledFn;
|
|
455
|
-
videoCompression = {
|
|
456
|
-
|
|
456
|
+
actionDisabledFn = input(undefined, ...(ngDevMode ? [{ debugName: "actionDisabledFn" }] : /* istanbul ignore next */ []));
|
|
457
|
+
videoCompression = input({
|
|
458
|
+
enabled: false,
|
|
459
|
+
maxWidth: 1280,
|
|
460
|
+
crf: 23,
|
|
461
|
+
preset: "veryfast",
|
|
462
|
+
maxFps: 30,
|
|
463
|
+
audioBitrate: 128000,
|
|
464
|
+
}, ...(ngDevMode ? [{ debugName: "videoCompression" }] : /* istanbul ignore next */ []));
|
|
465
|
+
customMenuActions = input([], ...(ngDevMode ? [{ debugName: "customMenuActions" }] : /* istanbul ignore next */ []));
|
|
457
466
|
_sortedMenuActions = [];
|
|
458
|
-
set customMenuActions(value) {
|
|
459
|
-
this._customMenuActions = value || [];
|
|
460
|
-
this.setupMenuActions();
|
|
461
|
-
}
|
|
462
|
-
get customMenuActions() {
|
|
463
|
-
return this._customMenuActions;
|
|
464
|
-
}
|
|
465
|
-
_customColumns = [];
|
|
466
467
|
/**
|
|
467
468
|
* SOLO quando [customColumns]="..." cambia.
|
|
468
469
|
*/
|
|
469
|
-
|
|
470
|
-
this._customColumns = value || [];
|
|
471
|
-
this.setupTableColumns();
|
|
472
|
-
}
|
|
473
|
-
get customColumns() {
|
|
474
|
-
return this._customColumns;
|
|
475
|
-
}
|
|
470
|
+
customColumns = input([], ...(ngDevMode ? [{ debugName: "customColumns" }] : /* istanbul ignore next */ []));
|
|
476
471
|
//#endregion
|
|
477
472
|
//#region @Output del componente
|
|
478
473
|
/**
|
|
479
474
|
* Restituisce la lista aggiornata degli allegati.
|
|
480
475
|
*/
|
|
481
|
-
localEditedAttachments =
|
|
476
|
+
localEditedAttachments = output();
|
|
482
477
|
/**
|
|
483
478
|
* Evento scatenato alla pressione del pulsante ESCI della modale di caricamento file.
|
|
484
479
|
*/
|
|
485
|
-
abortAddAttachment =
|
|
480
|
+
abortAddAttachment = output();
|
|
486
481
|
/**
|
|
487
482
|
* Evento di output che restituisce l'IAttachmentDTO selezionato per il download nel caso FileDataBase64, FileContentType o FileName non fossero specificati.
|
|
488
483
|
*/
|
|
489
|
-
downloadAttachment =
|
|
484
|
+
downloadAttachment = output({
|
|
485
|
+
alias: "downloadAttachment",
|
|
486
|
+
});
|
|
490
487
|
/**
|
|
491
488
|
* Evento di output che restituisce l'elemento eliminato prima che questo venga effettivamente rismosso dalla lista.
|
|
492
489
|
*/
|
|
493
|
-
onDeleteAttachment =
|
|
490
|
+
onDeleteAttachment = output({
|
|
491
|
+
alias: "onDeleteAttachment",
|
|
492
|
+
});
|
|
494
493
|
//#endregion
|
|
495
494
|
//#region Proprietà per gestione caricamento nuovo allegato
|
|
496
495
|
newAttachment = {};
|
|
@@ -501,20 +500,20 @@ class EqpAttachmentsComponent {
|
|
|
501
500
|
selectedFile = null;
|
|
502
501
|
selectedFiles = null;
|
|
503
502
|
showCropImage = false;
|
|
504
|
-
dialogAddAttachment;
|
|
503
|
+
dialogAddAttachment = viewChild("dialogAddAttachment", ...(ngDevMode ? [{ debugName: "dialogAddAttachment" }] : /* istanbul ignore next */ []));
|
|
505
504
|
dialogRefAddAttachment;
|
|
506
|
-
dialogAddMultipleAttachment;
|
|
505
|
+
dialogAddMultipleAttachment = viewChild("dialogAddMultipleAttachment", ...(ngDevMode ? [{ debugName: "dialogAddMultipleAttachment" }] : /* istanbul ignore next */ []));
|
|
507
506
|
dialogRefCropImage;
|
|
508
|
-
dialogCropImage;
|
|
509
|
-
addingLinkTemplate;
|
|
507
|
+
dialogCropImage = viewChild("dialogCropImage", ...(ngDevMode ? [{ debugName: "dialogCropImage" }] : /* istanbul ignore next */ []));
|
|
508
|
+
addingLinkTemplate = viewChild("addingLinkTemplate", ...(ngDevMode ? [{ debugName: "addingLinkTemplate" }] : /* istanbul ignore next */ []));
|
|
510
509
|
//#endregion
|
|
511
510
|
//#region Proprietà per gestione ridimensionamento file di tipo image
|
|
512
511
|
imageChangedEvent = "";
|
|
513
512
|
croppedImage = "";
|
|
514
513
|
transform = {};
|
|
515
514
|
canvasRotation = 0;
|
|
516
|
-
imageCropper;
|
|
517
|
-
imageInput;
|
|
515
|
+
imageCropper = viewChild(ImageCropperComponent, ...(ngDevMode ? [{ debugName: "imageCropper" }] : /* istanbul ignore next */ []));
|
|
516
|
+
imageInput = viewChild("imageInput", ...(ngDevMode ? [{ debugName: "imageInput" }] : /* istanbul ignore next */ []));
|
|
518
517
|
//#endregion
|
|
519
518
|
AttachmentType = AttachmentType;
|
|
520
519
|
selectedAttachment;
|
|
@@ -522,37 +521,37 @@ class EqpAttachmentsComponent {
|
|
|
522
521
|
originalHeight;
|
|
523
522
|
customWidth;
|
|
524
523
|
customHeight;
|
|
525
|
-
inlinePreviewTemplate;
|
|
526
|
-
dialogPreview;
|
|
524
|
+
inlinePreviewTemplate = viewChild("inlinePreviewTemplate", ...(ngDevMode ? [{ debugName: "inlinePreviewTemplate" }] : /* istanbul ignore next */ []));
|
|
525
|
+
dialogPreview = viewChild("dialogPreview", ...(ngDevMode ? [{ debugName: "dialogPreview" }] : /* istanbul ignore next */ []));
|
|
527
526
|
imageFile;
|
|
528
|
-
addingLinkMode = false;
|
|
527
|
+
addingLinkMode = signal(false, ...(ngDevMode ? [{ debugName: "addingLinkMode" }] : /* istanbul ignore next */ []));
|
|
529
528
|
//#region Sezione nuova refactoring
|
|
530
529
|
// Proprietà interna che conterrà l'array finale di colonne ordinate
|
|
531
530
|
_tableColumns = [];
|
|
532
|
-
defaultFileTemplate;
|
|
533
|
-
defaultActionsTemplate;
|
|
531
|
+
defaultFileTemplate = viewChild("defaultFileTemplate", ...(ngDevMode ? [{ debugName: "defaultFileTemplate" }] : /* istanbul ignore next */ []));
|
|
532
|
+
defaultActionsTemplate = viewChild("defaultActionsTemplate", ...(ngDevMode ? [{ debugName: "defaultActionsTemplate" }] : /* istanbul ignore next */ []));
|
|
534
533
|
// Stato drag & drop e toast
|
|
535
534
|
dragOver = false;
|
|
536
535
|
toast = {
|
|
537
536
|
visible: false,
|
|
538
|
-
type:
|
|
539
|
-
text:
|
|
540
|
-
timeoutId: 0
|
|
537
|
+
type: "success",
|
|
538
|
+
text: "",
|
|
539
|
+
timeoutId: 0,
|
|
541
540
|
};
|
|
542
|
-
progressPercent = 0;
|
|
543
|
-
totalSizeBytes = 0;
|
|
544
|
-
|
|
541
|
+
progressPercent = signal(0, ...(ngDevMode ? [{ debugName: "progressPercent" }] : /* istanbul ignore next */ []));
|
|
542
|
+
totalSizeBytes = signal(0, ...(ngDevMode ? [{ debugName: "totalSizeBytes" }] : /* istanbul ignore next */ []));
|
|
543
|
+
totalSizeFormatted = computed(() => this.formatFileSize(this.totalSizeBytes()), ...(ngDevMode ? [{ debugName: "totalSizeFormatted" }] : /* istanbul ignore next */ []));
|
|
545
544
|
// Utility per formattare bytes (2 decimali)
|
|
546
545
|
formatFileSize(bytes) {
|
|
547
546
|
if (!bytes || bytes <= 0)
|
|
548
|
-
return
|
|
547
|
+
return "0 Bytes";
|
|
549
548
|
const k = 1024;
|
|
550
|
-
const sizes = [
|
|
549
|
+
const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
|
|
551
550
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
552
551
|
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`;
|
|
553
552
|
}
|
|
554
553
|
// Mostra toast con auto‑hide e reset progress bar CSS
|
|
555
|
-
showToast(message, type =
|
|
554
|
+
showToast(message, type = "success", durationMs = 3000) {
|
|
556
555
|
if (this.toast.visible && this.toast.text === message) {
|
|
557
556
|
return;
|
|
558
557
|
}
|
|
@@ -577,46 +576,61 @@ class EqpAttachmentsComponent {
|
|
|
577
576
|
this.sanitizer = sanitizer;
|
|
578
577
|
this.http = http;
|
|
579
578
|
this.eqpAttachmentService = eqpAttachmentService;
|
|
579
|
+
effect(() => {
|
|
580
|
+
this.setupMenuActions();
|
|
581
|
+
});
|
|
582
|
+
effect(() => {
|
|
583
|
+
this.setupTableColumns();
|
|
584
|
+
});
|
|
580
585
|
}
|
|
581
586
|
ngOnInit() {
|
|
582
587
|
// Inizializza metriche e progress in base allo stato iniziale
|
|
583
588
|
this.recomputeTotalsAndProgress();
|
|
584
589
|
//Se è stata richiesta la gestione delle sole immagini allora imposta il filtro per le estensioni possibili da caricare
|
|
585
590
|
if (!this.acceptedFileTypes)
|
|
586
|
-
if (this.allowOnlyImages == true)
|
|
591
|
+
if (this.allowOnlyImages() == true)
|
|
587
592
|
this.acceptedFileTypes = "image/*";
|
|
588
593
|
else
|
|
589
594
|
this.acceptedFileTypes = "*";
|
|
590
595
|
// Se non sono stati specificati i tipi da gestire ma è stato passato null o un array vuoto imposto i tipi di default.
|
|
591
596
|
if (!this.allowedTypes || this.allowedTypes.length == 0)
|
|
592
|
-
this.allowedTypes = [
|
|
593
|
-
|
|
597
|
+
this.allowedTypes = [
|
|
598
|
+
AttachmentType.FILE,
|
|
599
|
+
AttachmentType.LINK,
|
|
600
|
+
AttachmentType.DROPBOX,
|
|
601
|
+
];
|
|
602
|
+
else if (this.allowedTypes.find((t) => t != AttachmentType.FILE &&
|
|
603
|
+
t != AttachmentType.LINK &&
|
|
604
|
+
t != AttachmentType.DROPBOX)) {
|
|
594
605
|
EqpAttachmentDialogService.Warning('Almeno uno degli AttachmentType selezionati nel parametro "allowedTypes" non esiste.');
|
|
595
|
-
this.allowedTypes = [
|
|
606
|
+
this.allowedTypes = [
|
|
607
|
+
AttachmentType.FILE,
|
|
608
|
+
AttachmentType.LINK,
|
|
609
|
+
AttachmentType.DROPBOX,
|
|
610
|
+
];
|
|
596
611
|
}
|
|
597
612
|
if (this.attachmentsList == null)
|
|
598
613
|
this.attachmentsList = new Array();
|
|
599
614
|
// Se è stato passato un singolo allegato lo aggiungo alla lista
|
|
600
|
-
if (this.singleAttachment != null && this.attachmentsList.length == 0) {
|
|
601
|
-
this.attachmentsList.push(this.singleAttachment);
|
|
615
|
+
if (this.singleAttachment() != null && this.attachmentsList.length == 0) {
|
|
616
|
+
this.attachmentsList.push(this.singleAttachment());
|
|
602
617
|
}
|
|
603
618
|
this.checkAttachmentImage();
|
|
604
619
|
if (this.allowedTypes.includes(3)) {
|
|
605
620
|
this.eqpAttachmentService.loadDropboxScript();
|
|
606
621
|
}
|
|
607
|
-
this.setupTableColumns();
|
|
608
|
-
this.setupMenuActions();
|
|
609
622
|
}
|
|
610
623
|
setViewMode(mode) {
|
|
611
624
|
this.viewMode = mode;
|
|
612
625
|
}
|
|
613
626
|
// Ricalcola la somma pesata sugli allegati presenti
|
|
614
627
|
recomputeTotalsAndProgress() {
|
|
615
|
-
this.totalSizeBytes
|
|
616
|
-
.filter(a => !!a)
|
|
617
|
-
.reduce((sum, a) => sum +
|
|
628
|
+
this.totalSizeBytes.set((this.attachmentsList || [])
|
|
629
|
+
.filter((a) => !!a)
|
|
630
|
+
.reduce((sum, a) => sum +
|
|
631
|
+
this.bytesFromBase64(a.FileDataBase64 || a.FileThumbnailBase64 || ""), 0));
|
|
618
632
|
// Progress fittizio: 100% se presenti file, 0 se vuoto
|
|
619
|
-
this.progressPercent
|
|
633
|
+
this.progressPercent.set(this.attachmentsList && this.attachmentsList.length > 0 ? 100 : 0);
|
|
620
634
|
}
|
|
621
635
|
ngOnDestroy() {
|
|
622
636
|
if (this.toast.timeoutId)
|
|
@@ -627,17 +641,17 @@ class EqpAttachmentsComponent {
|
|
|
627
641
|
if (!base64)
|
|
628
642
|
return 0;
|
|
629
643
|
// Rimuovi eventuale prefisso data URL
|
|
630
|
-
const commaIdx = base64.indexOf(
|
|
644
|
+
const commaIdx = base64.indexOf(",");
|
|
631
645
|
const b64 = commaIdx >= 0 ? base64.substring(commaIdx + 1) : base64;
|
|
632
646
|
// Conta padding
|
|
633
647
|
let padding = 0;
|
|
634
|
-
if (b64.endsWith(
|
|
648
|
+
if (b64.endsWith("=="))
|
|
635
649
|
padding = 2;
|
|
636
|
-
else if (b64.endsWith(
|
|
650
|
+
else if (b64.endsWith("="))
|
|
637
651
|
padding = 1;
|
|
638
652
|
// Formula esatta: (3 * (len / 4)) - padding
|
|
639
653
|
const len = b64.length;
|
|
640
|
-
return Math.max(0,
|
|
654
|
+
return Math.max(0, 3 * Math.floor(len / 4) - padding);
|
|
641
655
|
}
|
|
642
656
|
checkAttachmentImage() {
|
|
643
657
|
this.attachmentsList.forEach((a) => {
|
|
@@ -650,9 +664,9 @@ class EqpAttachmentsComponent {
|
|
|
650
664
|
* @param element IAttachmentDTO da cancellare
|
|
651
665
|
*/
|
|
652
666
|
deleteAttachment(element) {
|
|
653
|
-
EqpAttachmentDialogService.Confirm(this.deleteDialogMessage, () => {
|
|
667
|
+
EqpAttachmentDialogService.Confirm(this.deleteDialogMessage(), () => {
|
|
654
668
|
this.removeAttachmentFromList(this.attachmentsList.indexOf(element));
|
|
655
|
-
}, true, this.deleteDialogTitle);
|
|
669
|
+
}, true, this.deleteDialogTitle());
|
|
656
670
|
}
|
|
657
671
|
/**
|
|
658
672
|
* Rimuove l'allegato selezionato dalla lista "attachmentsList" e invoca l'evento di output che restituisce la lista aggiornata.
|
|
@@ -663,16 +677,16 @@ class EqpAttachmentsComponent {
|
|
|
663
677
|
this.attachmentsList.splice(attachmentIndex, 1);
|
|
664
678
|
this.localEditedAttachments.emit(this.attachmentsList);
|
|
665
679
|
this.recomputeTotalsAndProgress();
|
|
666
|
-
this.showToast(this.removedLabel ||
|
|
680
|
+
this.showToast(this.removedLabel() || "File removed", "success");
|
|
667
681
|
}
|
|
668
682
|
simulateProgress() {
|
|
669
|
-
this.progressPercent
|
|
683
|
+
this.progressPercent.set(0);
|
|
670
684
|
setTimeout(() => {
|
|
671
|
-
this.progressPercent
|
|
685
|
+
this.progressPercent.set(30);
|
|
672
686
|
setTimeout(() => {
|
|
673
|
-
this.progressPercent
|
|
687
|
+
this.progressPercent.set(60);
|
|
674
688
|
setTimeout(() => {
|
|
675
|
-
this.progressPercent
|
|
689
|
+
this.progressPercent.set(100);
|
|
676
690
|
}, 200);
|
|
677
691
|
}, 200);
|
|
678
692
|
}, 100);
|
|
@@ -696,7 +710,9 @@ class EqpAttachmentsComponent {
|
|
|
696
710
|
setTimeout(() => URL.revokeObjectURL(url), 1000);
|
|
697
711
|
return;
|
|
698
712
|
}
|
|
699
|
-
if (attachment.FileDataBase64 &&
|
|
713
|
+
if (attachment.FileDataBase64 &&
|
|
714
|
+
attachment.FileContentType &&
|
|
715
|
+
attachment.FileName) {
|
|
700
716
|
let source = `data:${attachment.FileContentType};base64,${attachment.FileDataBase64}`;
|
|
701
717
|
const link = document.createElement("a");
|
|
702
718
|
link.href = source;
|
|
@@ -740,7 +756,7 @@ class EqpAttachmentsComponent {
|
|
|
740
756
|
name: [this.newAttachment.FileName],
|
|
741
757
|
path: [this.newAttachment.FilePath],
|
|
742
758
|
customHeight: [this.customHeight],
|
|
743
|
-
customWidth: [this.customWidth]
|
|
759
|
+
customWidth: [this.customWidth],
|
|
744
760
|
});
|
|
745
761
|
}
|
|
746
762
|
close(emitCloseEvent = true) {
|
|
@@ -760,32 +776,39 @@ class EqpAttachmentsComponent {
|
|
|
760
776
|
* @returns
|
|
761
777
|
*/
|
|
762
778
|
disableSave() {
|
|
763
|
-
if (this.loadMultipleFiles != true) {
|
|
779
|
+
if (this.loadMultipleFiles() != true) {
|
|
764
780
|
if (this.newAttachment.AttachmentType == AttachmentType.FILE) {
|
|
765
|
-
return !this.newAttachment.FileDataBase64 && !this.newAttachment.LargeFile;
|
|
781
|
+
return (!this.newAttachment.FileDataBase64 && !this.newAttachment.LargeFile);
|
|
766
782
|
}
|
|
767
783
|
else {
|
|
768
784
|
return !this.newAttachment.FilePath;
|
|
769
785
|
}
|
|
770
786
|
}
|
|
771
787
|
else {
|
|
772
|
-
return (this.newMultipleAttachments.filter((p) => (p.AttachmentType == AttachmentType.FILE &&
|
|
788
|
+
return (this.newMultipleAttachments.filter((p) => (p.AttachmentType == AttachmentType.FILE &&
|
|
789
|
+
!p.FileDataBase64 &&
|
|
790
|
+
!p.LargeFile) ||
|
|
773
791
|
(p.AttachmentType == AttachmentType.LINK && !p.FilePath)).length > 0);
|
|
774
792
|
}
|
|
775
793
|
}
|
|
776
794
|
confirmAddAttachment() {
|
|
777
|
-
|
|
778
|
-
|
|
795
|
+
const imageCropper = this.imageCropper();
|
|
796
|
+
if (this.newAttachment.IsImage && imageCropper) {
|
|
797
|
+
this.newAttachment.FileDataBase64 = imageCropper
|
|
798
|
+
.crop()
|
|
799
|
+
.base64.split(";base64,")[1];
|
|
779
800
|
}
|
|
780
|
-
if (this.loadMultipleFiles != true) {
|
|
781
|
-
if (this.newAttachment.AttachmentType == AttachmentType.LINK &&
|
|
801
|
+
if (this.loadMultipleFiles() != true) {
|
|
802
|
+
if (this.newAttachment.AttachmentType == AttachmentType.LINK &&
|
|
803
|
+
!this.newAttachment.FileName)
|
|
782
804
|
this.newAttachment.FileName = this.newAttachment.FilePath;
|
|
783
805
|
if (this.attachmentsList == null)
|
|
784
806
|
this.attachmentsList = new Array();
|
|
785
807
|
this.attachmentsList.push(this.newAttachment);
|
|
786
808
|
}
|
|
787
809
|
else {
|
|
788
|
-
if (this.newMultipleAttachments == null ||
|
|
810
|
+
if (this.newMultipleAttachments == null ||
|
|
811
|
+
this.newMultipleAttachments.length == 0)
|
|
789
812
|
return;
|
|
790
813
|
if (this.attachmentsList == null)
|
|
791
814
|
this.attachmentsList = new Array();
|
|
@@ -803,7 +826,7 @@ class EqpAttachmentsComponent {
|
|
|
803
826
|
}
|
|
804
827
|
this.resetSelectedFiles();
|
|
805
828
|
}
|
|
806
|
-
// 2. RESET TOTALE: Svuotiamo le proprietà di classe per evitare che
|
|
829
|
+
// 2. RESET TOTALE: Svuotiamo le proprietà di classe per evitare che
|
|
807
830
|
// residui di upload precedenti (singoli o multipli) vengano trascinati.
|
|
808
831
|
resetSelectedFiles() {
|
|
809
832
|
this.newAttachment = {};
|
|
@@ -818,7 +841,9 @@ class EqpAttachmentsComponent {
|
|
|
818
841
|
*/
|
|
819
842
|
async openPreviewDialog(row) {
|
|
820
843
|
this.selectedAttachment = { ...row };
|
|
821
|
-
if (this.getAttachmentEndpoint &&
|
|
844
|
+
if (this.getAttachmentEndpoint() &&
|
|
845
|
+
this.selectedAttachment.IsImage &&
|
|
846
|
+
!this.selectedAttachment.FileDataBase64) {
|
|
822
847
|
await this.getAttachmentByID()
|
|
823
848
|
.then((res) => {
|
|
824
849
|
this.selectedAttachment.FileDataBase64 = res.FileDataBase64;
|
|
@@ -828,12 +853,15 @@ class EqpAttachmentsComponent {
|
|
|
828
853
|
});
|
|
829
854
|
}
|
|
830
855
|
if (this.selectedAttachment.AttachmentType == AttachmentType.LINK) {
|
|
831
|
-
this.selectedAttachment.TrustedUrl =
|
|
856
|
+
this.selectedAttachment.TrustedUrl =
|
|
857
|
+
this.sanitizer.bypassSecurityTrustResourceUrl(this.selectedAttachment.FilePath);
|
|
832
858
|
}
|
|
833
|
-
else if (this.selectedAttachment.FileContentType?.startsWith("video/") &&
|
|
859
|
+
else if (this.selectedAttachment.FileContentType?.startsWith("video/") &&
|
|
860
|
+
this.selectedAttachment.LargeFile) {
|
|
834
861
|
const videoUrl = URL.createObjectURL(this.selectedAttachment.LargeFile);
|
|
835
862
|
// Usiamo bypassSecurityTrustUrl per la sorgente del video
|
|
836
|
-
this.selectedAttachment.TrustedUrl =
|
|
863
|
+
this.selectedAttachment.TrustedUrl =
|
|
864
|
+
this.sanitizer.bypassSecurityTrustUrl(videoUrl);
|
|
837
865
|
}
|
|
838
866
|
else if (this.selectedAttachment.IsImage &&
|
|
839
867
|
!this.selectedAttachment.FileDataBase64 &&
|
|
@@ -841,26 +869,32 @@ class EqpAttachmentsComponent {
|
|
|
841
869
|
EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima dell'allegato, file mancante.");
|
|
842
870
|
return;
|
|
843
871
|
}
|
|
844
|
-
else if (this.selectedAttachment.FileContentType ===
|
|
845
|
-
this.selectedAttachment.
|
|
872
|
+
else if (this.selectedAttachment.FileContentType === "application/pdf" &&
|
|
873
|
+
this.selectedAttachment.FileDataBase64) {
|
|
874
|
+
this.selectedAttachment.TrustedUrl =
|
|
875
|
+
this.sanitizer.bypassSecurityTrustResourceUrl(`data:application/pdf;base64,${this.selectedAttachment.FileDataBase64}`);
|
|
846
876
|
}
|
|
847
877
|
else if (!this.selectedAttachment.IsImage) {
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
"/" +
|
|
852
|
-
|
|
853
|
-
|
|
878
|
+
const productionBaseUrl = this.productionBaseUrl();
|
|
879
|
+
if (this.selectedAttachment.FilePath && productionBaseUrl) {
|
|
880
|
+
this.selectedAttachment.TrustedUrl =
|
|
881
|
+
this.sanitizer.bypassSecurityTrustResourceUrl("https://docs.google.com/gview?url=" +
|
|
882
|
+
productionBaseUrl +
|
|
883
|
+
"/" +
|
|
884
|
+
this.selectedAttachment.FilePath +
|
|
885
|
+
"&embedded=true");
|
|
854
886
|
}
|
|
855
887
|
else {
|
|
856
888
|
EqpAttachmentDialogService.Info("Impossibile aprire l'anteprima del documento!");
|
|
857
889
|
return;
|
|
858
890
|
}
|
|
859
891
|
}
|
|
860
|
-
const dialogRef = this.dialog.open(this.dialogPreview, {
|
|
861
|
-
panelClass:
|
|
862
|
-
maxWidth:
|
|
863
|
-
width: row.IsImage || row.FileContentType?.startsWith(
|
|
892
|
+
const dialogRef = this.dialog.open(this.dialogPreview(), {
|
|
893
|
+
panelClass: "eqp-attachments-preview-dialog",
|
|
894
|
+
maxWidth: "95vw",
|
|
895
|
+
width: row.IsImage || row.FileContentType?.startsWith("video/")
|
|
896
|
+
? "auto"
|
|
897
|
+
: "1100px",
|
|
864
898
|
});
|
|
865
899
|
// Pulizia della memoria quando il dialog si chiude
|
|
866
900
|
dialogRef.afterClosed().subscribe(() => {
|
|
@@ -870,7 +904,9 @@ class EqpAttachmentsComponent {
|
|
|
870
904
|
});
|
|
871
905
|
}
|
|
872
906
|
async getAttachmentByID() {
|
|
873
|
-
return this.http
|
|
907
|
+
return this.http
|
|
908
|
+
.post(this.getAttachmentEndpoint(), this.selectedAttachment)
|
|
909
|
+
.toPromise();
|
|
874
910
|
}
|
|
875
911
|
//#region Gestione caricamento file
|
|
876
912
|
/**
|
|
@@ -882,7 +918,7 @@ class EqpAttachmentsComponent {
|
|
|
882
918
|
* immagine per il croppie (in caso di caricamento multiplo le funzionalità del croppie sono disabilitate).
|
|
883
919
|
*/
|
|
884
920
|
async onFileAdded(event, isFileDropped = false) {
|
|
885
|
-
if (this.isDisabled) {
|
|
921
|
+
if (this.isDisabled()) {
|
|
886
922
|
EqpAttachmentDialogService.Info("Caricamento allegati non disponibile.");
|
|
887
923
|
event.preventDefault();
|
|
888
924
|
return;
|
|
@@ -895,13 +931,13 @@ class EqpAttachmentsComponent {
|
|
|
895
931
|
const { validFiles, oversizedFiles } = this.validationFile(filesOnInput);
|
|
896
932
|
if (!validFiles || validFiles.length === 0) {
|
|
897
933
|
if (!isFileDropped && event?.target instanceof HTMLInputElement) {
|
|
898
|
-
event.target.value =
|
|
934
|
+
event.target.value = "";
|
|
899
935
|
}
|
|
900
936
|
return;
|
|
901
937
|
}
|
|
902
938
|
//Se è stato richiesto il caricamento SINGOLO oppure se il caricamento è MULTIPLO ma è stato selezionato un solo file
|
|
903
939
|
//allora verifica se il file è un immagine (per mostrare il CROPPIE)
|
|
904
|
-
if ([...validFiles].length == 1 || this.loadMultipleFiles != true) {
|
|
940
|
+
if ([...validFiles].length == 1 || this.loadMultipleFiles() != true) {
|
|
905
941
|
this.selectedFile = validFiles[0];
|
|
906
942
|
this.selectedFiles = validFiles;
|
|
907
943
|
if (!this.selectedFile)
|
|
@@ -917,7 +953,7 @@ class EqpAttachmentsComponent {
|
|
|
917
953
|
this.createAttachmentForm();
|
|
918
954
|
//Verifica se il file caricato è un'immagine oppure no. Se è un immagine, prima di caricarla mostra il croppie per il resize.
|
|
919
955
|
//Se non è un immagine allora genera il Base64
|
|
920
|
-
if (this.newAttachment.IsImage == true && this.enableImageCrop) {
|
|
956
|
+
if (this.newAttachment.IsImage == true && this.enableImageCrop()) {
|
|
921
957
|
this.getImageDimensions(validFiles[0]);
|
|
922
958
|
//Mostra il croppie e disabilita la form finchè non termina la modifica dell'immagine
|
|
923
959
|
this.newAttachmentForm.disable();
|
|
@@ -926,13 +962,13 @@ class EqpAttachmentsComponent {
|
|
|
926
962
|
setTimeout(() => {
|
|
927
963
|
this.showCropImage = true;
|
|
928
964
|
this.imageFile = event;
|
|
929
|
-
this.dialogRefCropImage = this.dialog.open(this.dialogCropImage, {
|
|
965
|
+
this.dialogRefCropImage = this.dialog.open(this.dialogCropImage(), {
|
|
930
966
|
disableClose: true,
|
|
931
967
|
hasBackdrop: true,
|
|
932
|
-
width: "
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
panelClass: [
|
|
968
|
+
width: "60%",
|
|
969
|
+
maxHeight: "80%",
|
|
970
|
+
maxWidth: "70vh",
|
|
971
|
+
panelClass: ["eqp-attachments-dialog", "crop-dialog"],
|
|
936
972
|
});
|
|
937
973
|
});
|
|
938
974
|
}
|
|
@@ -964,15 +1000,15 @@ class EqpAttachmentsComponent {
|
|
|
964
1000
|
this.simulateProgress();
|
|
965
1001
|
// Caso 1: Successo Parziale (alcuni file validi, altri no)
|
|
966
1002
|
if (oversizedFiles.length > 0 && validFiles.length > 0) {
|
|
967
|
-
const fileNames = oversizedFiles.join(
|
|
968
|
-
this.showToast(`${validFiles.length} file aggiunti. ${oversizedFiles.length} non caricati perché troppo grandi (${fileNames}).`,
|
|
1003
|
+
const fileNames = oversizedFiles.join(", ");
|
|
1004
|
+
this.showToast(`${validFiles.length} file aggiunti. ${oversizedFiles.length} non caricati perché troppo grandi (${fileNames}).`, "error");
|
|
969
1005
|
}
|
|
970
1006
|
// Caso 2: Nessun file valido
|
|
971
1007
|
else if (oversizedFiles.length > 0 && validFiles.length === 0) {
|
|
972
1008
|
}
|
|
973
1009
|
// Caso 3: Tutti i file validi
|
|
974
1010
|
else if (oversizedFiles.length === 0 && validFiles.length > 0) {
|
|
975
|
-
this.showToast(`${validFiles.length} ${this.addedSuccessfullyLabel ||
|
|
1011
|
+
this.showToast(`${validFiles.length} ${this.addedSuccessfullyLabel() || "file(s) aggiunti con successo."}`, "success");
|
|
976
1012
|
}
|
|
977
1013
|
//Resetto il valore del file input in modo da scatenare il change anche se si dovesse caricare lo stesso file
|
|
978
1014
|
if (!isFileDropped)
|
|
@@ -983,7 +1019,7 @@ class EqpAttachmentsComponent {
|
|
|
983
1019
|
const oversizedFiles = [];
|
|
984
1020
|
for (const file of filesOnInput) {
|
|
985
1021
|
const fileSizeMB = file.size / 1024 / 1024;
|
|
986
|
-
if (fileSizeMB > this.maxFileSizeMB) {
|
|
1022
|
+
if (fileSizeMB > this.maxFileSizeMB()) {
|
|
987
1023
|
oversizedFiles.push(file.name);
|
|
988
1024
|
}
|
|
989
1025
|
else {
|
|
@@ -991,8 +1027,8 @@ class EqpAttachmentsComponent {
|
|
|
991
1027
|
}
|
|
992
1028
|
}
|
|
993
1029
|
if (oversizedFiles.length > 0) {
|
|
994
|
-
const fileNames = oversizedFiles.join(
|
|
995
|
-
this.showToast(`File(s) troppo grandi: ${fileNames}. Limite: ${this.maxFileSizeMB}MB`,
|
|
1030
|
+
const fileNames = oversizedFiles.join(", ");
|
|
1031
|
+
this.showToast(`File(s) troppo grandi: ${fileNames}. Limite: ${this.maxFileSizeMB()}MB`, "error");
|
|
996
1032
|
}
|
|
997
1033
|
return { validFiles, oversizedFiles };
|
|
998
1034
|
}
|
|
@@ -1013,22 +1049,25 @@ class EqpAttachmentsComponent {
|
|
|
1013
1049
|
newAttachment.FileExtension = currentFile.name.substr(currentFile.name.lastIndexOf(".") + 1);
|
|
1014
1050
|
newAttachment.IsImage = AttachmentHelperService.checkImageFromMimeType(currentFile.type);
|
|
1015
1051
|
const fileSizeMB = currentFile.size / 1024 / 1024;
|
|
1016
|
-
const isLargeFile = fileSizeMB > this.base64LimitMB;
|
|
1017
|
-
const isVideo = currentFile.type.startsWith(
|
|
1052
|
+
const isLargeFile = fileSizeMB > this.base64LimitMB();
|
|
1053
|
+
const isVideo = currentFile.type.startsWith("video");
|
|
1018
1054
|
if (isVideo) {
|
|
1019
1055
|
let finalFile = currentFile;
|
|
1020
1056
|
// 1. Genera la miniatura (rimane lato client perché è un'operazione istantanea)
|
|
1021
1057
|
newAttachment.FileThumbnailBase64 = await this.generateVideoThumbnail(currentFile);
|
|
1022
1058
|
// 2. Se la compressione è abilitata, inviamo il file all'API C#
|
|
1023
|
-
|
|
1059
|
+
const videoCompression = this.videoCompression();
|
|
1060
|
+
if (videoCompression.enabled) {
|
|
1024
1061
|
this.showToast("Compressione video in corso... L'operazione potrebbe richiedere alcuni minuti.", "info");
|
|
1025
1062
|
try {
|
|
1026
1063
|
// Chiamata al microservizio C# (metodo ristrutturato precedentemente)
|
|
1027
|
-
const compressedBlob = await this.compressVideoApi(currentFile,
|
|
1064
|
+
const compressedBlob = await this.compressVideoApi(currentFile, videoCompression);
|
|
1028
1065
|
// Creiamo il nuovo nome file con estensione .mp4
|
|
1029
1066
|
const newFileName = currentFile.name.replace(/\.[^/.]+$/, "") + ".mp4";
|
|
1030
1067
|
// Trasformiamo il Blob ricevuto in un File per mantenere la coerenza nell'oggetto DTO
|
|
1031
|
-
finalFile = new File([compressedBlob], newFileName, {
|
|
1068
|
+
finalFile = new File([compressedBlob], newFileName, {
|
|
1069
|
+
type: "video/mp4",
|
|
1070
|
+
});
|
|
1032
1071
|
// Aggiorniamo i metadati dell'allegato
|
|
1033
1072
|
newAttachment.FileName = newFileName;
|
|
1034
1073
|
newAttachment.FileContentType = "video/mp4";
|
|
@@ -1072,10 +1111,10 @@ class EqpAttachmentsComponent {
|
|
|
1072
1111
|
*/
|
|
1073
1112
|
async getBase64FromFile(currentFile) {
|
|
1074
1113
|
const fileSizeMB = currentFile.size / 1024 / 1024;
|
|
1075
|
-
if (fileSizeMB > this.base64LimitMB) {
|
|
1114
|
+
if (fileSizeMB > this.base64LimitMB()) {
|
|
1076
1115
|
return {
|
|
1077
1116
|
Base64File: null,
|
|
1078
|
-
ContentType: currentFile.type
|
|
1117
|
+
ContentType: currentFile.type,
|
|
1079
1118
|
};
|
|
1080
1119
|
}
|
|
1081
1120
|
// Procedura standard
|
|
@@ -1088,7 +1127,7 @@ class EqpAttachmentsComponent {
|
|
|
1088
1127
|
}
|
|
1089
1128
|
return {
|
|
1090
1129
|
Base64File: base64File,
|
|
1091
|
-
ContentType: contentType
|
|
1130
|
+
ContentType: contentType,
|
|
1092
1131
|
};
|
|
1093
1132
|
}
|
|
1094
1133
|
catch (ex) {
|
|
@@ -1109,7 +1148,9 @@ class EqpAttachmentsComponent {
|
|
|
1109
1148
|
// Controllo corrispondenza esatta (es. image/png)
|
|
1110
1149
|
if (this.acceptedFileTypes.includes(mimeType))
|
|
1111
1150
|
return true;
|
|
1112
|
-
const wildcards = this.acceptedFileTypes
|
|
1151
|
+
const wildcards = this.acceptedFileTypes
|
|
1152
|
+
.split(",")
|
|
1153
|
+
.filter((t) => t.includes("*"));
|
|
1113
1154
|
for (let t of wildcards) {
|
|
1114
1155
|
const prefix = t.split("*")[0]; // Prende "image/" da "image/*"
|
|
1115
1156
|
if (mimeType.startsWith(prefix))
|
|
@@ -1117,13 +1158,13 @@ class EqpAttachmentsComponent {
|
|
|
1117
1158
|
}
|
|
1118
1159
|
return false;
|
|
1119
1160
|
};
|
|
1120
|
-
if (this.loadMultipleFiles !== true) {
|
|
1161
|
+
if (this.loadMultipleFiles() !== true) {
|
|
1121
1162
|
// Caso Singolo
|
|
1122
1163
|
return isTypeValid(this.selectedFile.type);
|
|
1123
1164
|
}
|
|
1124
1165
|
else {
|
|
1125
1166
|
// Caso Multiplo: TUTTI i file selezionati devono essere validi
|
|
1126
|
-
return Array.from(this.selectedFiles).every(file => isTypeValid(file.type));
|
|
1167
|
+
return Array.from(this.selectedFiles).every((file) => isTypeValid(file.type));
|
|
1127
1168
|
}
|
|
1128
1169
|
}
|
|
1129
1170
|
/**
|
|
@@ -1132,13 +1173,13 @@ class EqpAttachmentsComponent {
|
|
|
1132
1173
|
* Se il controllo va a buon fine restituisce TRUE altrimenti mostra un messaggio d'errore e restituisce FALSE
|
|
1133
1174
|
*/
|
|
1134
1175
|
checkAllowOnlyImageFile(newAttachment) {
|
|
1135
|
-
if (this.allowOnlyImages == true && newAttachment.IsImage != true) {
|
|
1136
|
-
EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage);
|
|
1176
|
+
if (this.allowOnlyImages() == true && newAttachment.IsImage != true) {
|
|
1177
|
+
EqpAttachmentDialogService.Error(this.noImageSelectedErrorMessage());
|
|
1137
1178
|
this.abortFile();
|
|
1138
1179
|
return false;
|
|
1139
1180
|
}
|
|
1140
1181
|
else if (!this.checkAcceptedFiles()) {
|
|
1141
|
-
EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage);
|
|
1182
|
+
EqpAttachmentDialogService.Error(this.wrongTypeSelectedErrorMessage());
|
|
1142
1183
|
this.abortFile();
|
|
1143
1184
|
return false;
|
|
1144
1185
|
}
|
|
@@ -1186,7 +1227,7 @@ class EqpAttachmentsComponent {
|
|
|
1186
1227
|
getCroppedAndUpload(file, newAttachment) {
|
|
1187
1228
|
var self = this;
|
|
1188
1229
|
var file = base64ToFile(file);
|
|
1189
|
-
const options = this.compressionOptions;
|
|
1230
|
+
const options = this.compressionOptions();
|
|
1190
1231
|
/**
|
|
1191
1232
|
* Comprime l'immagine passando come parametri le options create nell'oggetto sopra, e il file dal reader principale
|
|
1192
1233
|
*/
|
|
@@ -1219,19 +1260,19 @@ class EqpAttachmentsComponent {
|
|
|
1219
1260
|
this.transform = {
|
|
1220
1261
|
...this.transform,
|
|
1221
1262
|
flipH: flippedV,
|
|
1222
|
-
flipV: flippedH
|
|
1263
|
+
flipV: flippedH,
|
|
1223
1264
|
};
|
|
1224
1265
|
}
|
|
1225
1266
|
flipHorizontal() {
|
|
1226
1267
|
this.transform = {
|
|
1227
1268
|
...this.transform,
|
|
1228
|
-
flipH: !this.transform.flipH
|
|
1269
|
+
flipH: !this.transform.flipH,
|
|
1229
1270
|
};
|
|
1230
1271
|
}
|
|
1231
1272
|
flipVertical() {
|
|
1232
1273
|
this.transform = {
|
|
1233
1274
|
...this.transform,
|
|
1234
|
-
flipV: !this.transform.flipV
|
|
1275
|
+
flipV: !this.transform.flipV,
|
|
1235
1276
|
};
|
|
1236
1277
|
}
|
|
1237
1278
|
//#endregion
|
|
@@ -1239,8 +1280,9 @@ class EqpAttachmentsComponent {
|
|
|
1239
1280
|
* Annulla la selezione del file, svuotando l'input e resettando tutte le proprietà dell'IAttachmentDTO
|
|
1240
1281
|
*/
|
|
1241
1282
|
abortFile() {
|
|
1242
|
-
|
|
1243
|
-
|
|
1283
|
+
const imageInput = this.imageInput();
|
|
1284
|
+
if (imageInput)
|
|
1285
|
+
imageInput.nativeElement.value = "";
|
|
1244
1286
|
this.selectedFile = null;
|
|
1245
1287
|
this.selectedFiles = null;
|
|
1246
1288
|
this.showCropImage = false;
|
|
@@ -1270,7 +1312,7 @@ class EqpAttachmentsComponent {
|
|
|
1270
1312
|
// Se il caricamento del file dropbox va a buon fine, la funzione di callback restituisce un array di oggetti.
|
|
1271
1313
|
// Viene poi fatta una XMLHttpRequest con responseType 'blob' per convertire il primo elemento della response in un Blob.
|
|
1272
1314
|
chooseDropboxFile() {
|
|
1273
|
-
if (this.isDisabled)
|
|
1315
|
+
if (this.isDisabled())
|
|
1274
1316
|
return;
|
|
1275
1317
|
var options = {
|
|
1276
1318
|
success: (files) => {
|
|
@@ -1288,7 +1330,7 @@ class EqpAttachmentsComponent {
|
|
|
1288
1330
|
},
|
|
1289
1331
|
linkType: "direct",
|
|
1290
1332
|
multiselect: false,
|
|
1291
|
-
extensions: [".jpg", ".png", ".pdf", ".doc", ".docx", ".txt"]
|
|
1333
|
+
extensions: [".jpg", ".png", ".pdf", ".doc", ".docx", ".txt"],
|
|
1292
1334
|
};
|
|
1293
1335
|
Dropbox.choose(options);
|
|
1294
1336
|
}
|
|
@@ -1296,7 +1338,7 @@ class EqpAttachmentsComponent {
|
|
|
1296
1338
|
onSelectFile(event, fileInput) {
|
|
1297
1339
|
if (event.target.tagName === "BUTTON" ||
|
|
1298
1340
|
event.target.tagName === "INPUT" ||
|
|
1299
|
-
this.addingLinkMode == true) {
|
|
1341
|
+
this.addingLinkMode() == true) {
|
|
1300
1342
|
return;
|
|
1301
1343
|
}
|
|
1302
1344
|
fileInput.click();
|
|
@@ -1305,17 +1347,17 @@ class EqpAttachmentsComponent {
|
|
|
1305
1347
|
* Apre il dialogo per l'inserimento del link.
|
|
1306
1348
|
*/
|
|
1307
1349
|
switchToAddingLinkMode() {
|
|
1308
|
-
if (this.isDisabled)
|
|
1350
|
+
if (this.isDisabled())
|
|
1309
1351
|
return;
|
|
1310
1352
|
this.newAttachmentForm = this.formBuilder.group({
|
|
1311
|
-
fileName: [
|
|
1312
|
-
filePath: [
|
|
1353
|
+
fileName: [""],
|
|
1354
|
+
filePath: ["", [Validators.required, Validators.pattern("https?://.+")]],
|
|
1313
1355
|
});
|
|
1314
|
-
const dialogRef = this.dialog.open(this.addingLinkTemplate, {
|
|
1315
|
-
width:
|
|
1316
|
-
panelClass:
|
|
1356
|
+
const dialogRef = this.dialog.open(this.addingLinkTemplate(), {
|
|
1357
|
+
width: "500px",
|
|
1358
|
+
panelClass: "eqp-attachments-dialog",
|
|
1317
1359
|
});
|
|
1318
|
-
dialogRef.afterClosed().subscribe(result => {
|
|
1360
|
+
dialogRef.afterClosed().subscribe((result) => {
|
|
1319
1361
|
if (result) {
|
|
1320
1362
|
// Crea l'oggetto per il nuovo link dai dati del form
|
|
1321
1363
|
const newLinkObject = {
|
|
@@ -1323,7 +1365,7 @@ class EqpAttachmentsComponent {
|
|
|
1323
1365
|
AttachmentType: AttachmentType.LINK,
|
|
1324
1366
|
FileName: result.fileName,
|
|
1325
1367
|
FilePath: result.filePath,
|
|
1326
|
-
IsImage: false
|
|
1368
|
+
IsImage: false,
|
|
1327
1369
|
};
|
|
1328
1370
|
this.newAttachment = newLinkObject;
|
|
1329
1371
|
this.newMultipleAttachments = [newLinkObject];
|
|
@@ -1334,26 +1376,27 @@ class EqpAttachmentsComponent {
|
|
|
1334
1376
|
// Metodo per ottenere le classi CSS dinamiche
|
|
1335
1377
|
getCardClass(att) {
|
|
1336
1378
|
return {
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1379
|
+
"file-preview": true,
|
|
1380
|
+
uploading: !!att.isUploading,
|
|
1381
|
+
"card-small": this.cardSize() === "small",
|
|
1382
|
+
"card-medium": this.cardSize() === "medium",
|
|
1383
|
+
"card-large": this.cardSize() === "large",
|
|
1342
1384
|
};
|
|
1343
1385
|
}
|
|
1344
1386
|
// Questa funzione ora si applica al contenitore, non alla singola card.
|
|
1345
1387
|
getPreviewsContainerStyle() {
|
|
1346
|
-
let minWidth =
|
|
1347
|
-
|
|
1348
|
-
|
|
1388
|
+
let minWidth = "200px"; // Dimensione di default per 'medium'
|
|
1389
|
+
const cardSize = this.cardSize();
|
|
1390
|
+
if (cardSize === "small") {
|
|
1391
|
+
minWidth = "140px";
|
|
1349
1392
|
}
|
|
1350
|
-
else if (
|
|
1351
|
-
minWidth =
|
|
1393
|
+
else if (cardSize === "large") {
|
|
1394
|
+
minWidth = "280px";
|
|
1352
1395
|
}
|
|
1353
|
-
else if (
|
|
1354
|
-
minWidth = `${this.customCardWidthPx}px`;
|
|
1396
|
+
else if (cardSize === "custom") {
|
|
1397
|
+
minWidth = `${this.customCardWidthPx()}px`;
|
|
1355
1398
|
}
|
|
1356
|
-
return {
|
|
1399
|
+
return { "--card-min-width": minWidth };
|
|
1357
1400
|
}
|
|
1358
1401
|
handlePrimaryAction(attachment) {
|
|
1359
1402
|
// Se il file può essere visualizzato in anteprima, apri il dialog
|
|
@@ -1366,10 +1409,10 @@ class EqpAttachmentsComponent {
|
|
|
1366
1409
|
}
|
|
1367
1410
|
}
|
|
1368
1411
|
/**
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1412
|
+
* Determines if an attachment can be previewed in the dialog.
|
|
1413
|
+
* @param att The attachment to check.
|
|
1414
|
+
* @returns `true` if a preview is available, otherwise `false`.
|
|
1415
|
+
*/
|
|
1373
1416
|
canBePreviewed(att) {
|
|
1374
1417
|
if (!att) {
|
|
1375
1418
|
return false;
|
|
@@ -1377,44 +1420,62 @@ class EqpAttachmentsComponent {
|
|
|
1377
1420
|
// Case 1: It's an image with Base64 data.
|
|
1378
1421
|
const isPreviewableImage = att.IsImage && !!att.FileDataBase64;
|
|
1379
1422
|
// Case 2: It's a PDF with Base64 data.
|
|
1380
|
-
const isPreviewablePdf = att.FileContentType ===
|
|
1423
|
+
const isPreviewablePdf = att.FileContentType === "application/pdf" && !!att.FileDataBase64;
|
|
1381
1424
|
// Case 3: It's a remote document with a URL (for Google Viewer).
|
|
1382
|
-
const isRemoteDocument = !att.IsImage && !!att.FilePath && !!this.productionBaseUrl;
|
|
1425
|
+
const isRemoteDocument = !att.IsImage && !!att.FilePath && !!this.productionBaseUrl();
|
|
1383
1426
|
//Case 4: Video - È un video e abbiamo il file binario salvato in LargeFile
|
|
1384
|
-
const isPreviewableVideo = att.FileContentType?.startsWith(
|
|
1427
|
+
const isPreviewableVideo = att.FileContentType?.startsWith("video/") && !!att.LargeFile;
|
|
1385
1428
|
// A preview is possible if any of these conditions are true.
|
|
1386
|
-
return isPreviewableImage ||
|
|
1429
|
+
return (isPreviewableImage ||
|
|
1430
|
+
isPreviewablePdf ||
|
|
1431
|
+
isRemoteDocument ||
|
|
1432
|
+
isPreviewableVideo);
|
|
1387
1433
|
}
|
|
1388
1434
|
isColumnHidden(col) {
|
|
1389
1435
|
// 1) hiddenColumns
|
|
1390
|
-
if (this.hiddenColumns?.includes(col.key))
|
|
1436
|
+
if (this.hiddenColumns()?.includes(col.key))
|
|
1391
1437
|
return true;
|
|
1392
1438
|
// 2) hidden definito sulla colonna (boolean o funzione senza args)
|
|
1393
|
-
if (typeof col.hidden ===
|
|
1439
|
+
if (typeof col.hidden === "function")
|
|
1394
1440
|
return !!col.hidden();
|
|
1395
1441
|
return !!col.hidden;
|
|
1396
1442
|
}
|
|
1397
1443
|
isActionHidden(action, att) {
|
|
1398
|
-
if (this.hiddenActions?.includes(action.key))
|
|
1444
|
+
if (this.hiddenActions()?.includes(action.key))
|
|
1399
1445
|
return true;
|
|
1400
|
-
if (this.actionHiddenFn?.(action.key, att))
|
|
1446
|
+
if (this.actionHiddenFn()?.(action.key, att))
|
|
1401
1447
|
return true;
|
|
1402
|
-
if (typeof action.hidden ===
|
|
1448
|
+
if (typeof action.hidden === "function")
|
|
1403
1449
|
return !!action.hidden(att);
|
|
1404
1450
|
return !!action.hidden;
|
|
1405
1451
|
}
|
|
1406
1452
|
isActionDisabled(action, att) {
|
|
1407
|
-
if (this.actionDisabledFn?.(action.key, att))
|
|
1453
|
+
if (this.actionDisabledFn()?.(action.key, att))
|
|
1408
1454
|
return true;
|
|
1409
|
-
if (typeof action.disabled ===
|
|
1455
|
+
if (typeof action.disabled === "function")
|
|
1410
1456
|
return !!action.disabled(att);
|
|
1411
1457
|
return !!action.disabled;
|
|
1412
1458
|
}
|
|
1413
1459
|
isDeleteHidden(att) {
|
|
1414
|
-
return this.actionHiddenFn?.(
|
|
1460
|
+
return (this.actionHiddenFn()?.("delete", att) ||
|
|
1461
|
+
this.hiddenActions()?.includes("delete"));
|
|
1415
1462
|
}
|
|
1416
1463
|
isDeleteDisabled(att) {
|
|
1417
|
-
return this.disableAction || !!this.actionDisabledFn?.(
|
|
1464
|
+
return this.disableAction() || !!this.actionDisabledFn()?.("delete", att);
|
|
1465
|
+
}
|
|
1466
|
+
isPrimaryActionHidden(att) {
|
|
1467
|
+
if (this.hiddenActions()?.includes('download') || this.hiddenActions()?.includes('preview') || this.hiddenActions()?.includes('primaryAction'))
|
|
1468
|
+
return true;
|
|
1469
|
+
if (this.hiddenColumns()?.includes('download') || this.hiddenColumns()?.includes('preview') || this.hiddenColumns()?.includes('primaryAction'))
|
|
1470
|
+
return true;
|
|
1471
|
+
if (this.actionHiddenFn()?.('primaryAction', att) || this.actionHiddenFn()?.('download', att) || this.actionHiddenFn()?.('preview', att))
|
|
1472
|
+
return true;
|
|
1473
|
+
return false;
|
|
1474
|
+
}
|
|
1475
|
+
isPrimaryActionDisabled(att) {
|
|
1476
|
+
if (this.actionDisabledFn()?.('primaryAction', att) || this.actionDisabledFn()?.('download', att) || this.actionDisabledFn()?.('preview', att))
|
|
1477
|
+
return true;
|
|
1478
|
+
return false;
|
|
1418
1479
|
}
|
|
1419
1480
|
/**
|
|
1420
1481
|
* Unisce le colonne di default con quelle custom e le ordina.
|
|
@@ -1422,28 +1483,28 @@ class EqpAttachmentsComponent {
|
|
|
1422
1483
|
setupTableColumns() {
|
|
1423
1484
|
// Definiamo le colonne standard con una posizione
|
|
1424
1485
|
const defaultFileColumn = {
|
|
1425
|
-
key:
|
|
1426
|
-
display:
|
|
1486
|
+
key: "file",
|
|
1487
|
+
display: "File",
|
|
1427
1488
|
type: TypeAttachmentColumn.TEMPLATE,
|
|
1428
|
-
externalTemplate: this.defaultFileTemplate,
|
|
1429
|
-
styles: { flex:
|
|
1430
|
-
position: 10
|
|
1489
|
+
externalTemplate: this.defaultFileTemplate(),
|
|
1490
|
+
styles: { flex: "1 1 0%" },
|
|
1491
|
+
position: 10,
|
|
1431
1492
|
};
|
|
1432
1493
|
const defaultActionsColumn = {
|
|
1433
|
-
key:
|
|
1434
|
-
display:
|
|
1494
|
+
key: "actions",
|
|
1495
|
+
display: "Azioni",
|
|
1435
1496
|
type: TypeAttachmentColumn.TEMPLATE,
|
|
1436
|
-
externalTemplate: this.defaultActionsTemplate,
|
|
1497
|
+
externalTemplate: this.defaultActionsTemplate(),
|
|
1437
1498
|
position: 100,
|
|
1438
|
-
class:
|
|
1439
|
-
styles: { flex:
|
|
1499
|
+
class: "col-actions",
|
|
1500
|
+
styles: { flex: "0 0 150px" },
|
|
1440
1501
|
};
|
|
1441
|
-
const processedCustomColumns = this.
|
|
1502
|
+
const processedCustomColumns = this.customColumns().map((col) => {
|
|
1442
1503
|
// Flex di default
|
|
1443
1504
|
if (!col.styles || !col.styles.flex) {
|
|
1444
1505
|
return {
|
|
1445
1506
|
...col,
|
|
1446
|
-
styles: { ...col.styles, flex:
|
|
1507
|
+
styles: { ...col.styles, flex: "1 1 0%" },
|
|
1447
1508
|
};
|
|
1448
1509
|
}
|
|
1449
1510
|
return col;
|
|
@@ -1451,10 +1512,11 @@ class EqpAttachmentsComponent {
|
|
|
1451
1512
|
const allColumns = [
|
|
1452
1513
|
defaultFileColumn,
|
|
1453
1514
|
defaultActionsColumn,
|
|
1454
|
-
...processedCustomColumns
|
|
1515
|
+
...processedCustomColumns,
|
|
1455
1516
|
];
|
|
1456
1517
|
// Ordiniamo l'array finale in base alla proprietà 'position'
|
|
1457
|
-
this._tableColumns = allColumns
|
|
1518
|
+
this._tableColumns = allColumns
|
|
1519
|
+
.filter((col) => !this.isColumnHidden(col))
|
|
1458
1520
|
.sort((a, b) => {
|
|
1459
1521
|
const posA = a.position || 99;
|
|
1460
1522
|
const posB = b.position || 99;
|
|
@@ -1463,25 +1525,25 @@ class EqpAttachmentsComponent {
|
|
|
1463
1525
|
}
|
|
1464
1526
|
setupMenuActions() {
|
|
1465
1527
|
const defaultPreviewAction = {
|
|
1466
|
-
key:
|
|
1467
|
-
icon:
|
|
1468
|
-
name:
|
|
1528
|
+
key: "preview",
|
|
1529
|
+
icon: "visibility",
|
|
1530
|
+
name: "Anteprima",
|
|
1469
1531
|
fn: (att) => this.openPreviewDialog(att),
|
|
1470
1532
|
disabled: (att) => !this.canBePreviewed(att),
|
|
1471
|
-
position: 10
|
|
1533
|
+
position: 10,
|
|
1472
1534
|
};
|
|
1473
1535
|
const defaultDeleteAction = {
|
|
1474
|
-
key:
|
|
1475
|
-
icon:
|
|
1476
|
-
name:
|
|
1536
|
+
key: "delete",
|
|
1537
|
+
icon: "delete",
|
|
1538
|
+
name: "Elimina",
|
|
1477
1539
|
fn: (att) => this.deleteAttachment(att),
|
|
1478
|
-
disabled: () => this.disableAction,
|
|
1479
|
-
position: 100
|
|
1540
|
+
disabled: () => this.disableAction(),
|
|
1541
|
+
position: 100,
|
|
1480
1542
|
};
|
|
1481
1543
|
const allActions = [
|
|
1482
1544
|
defaultPreviewAction,
|
|
1483
1545
|
defaultDeleteAction,
|
|
1484
|
-
...this.
|
|
1546
|
+
...this.customMenuActions(),
|
|
1485
1547
|
];
|
|
1486
1548
|
// Ordiniamo l'array finale in base alla proprietà 'position'
|
|
1487
1549
|
this._sortedMenuActions = allActions.sort((a, b) => {
|
|
@@ -1492,13 +1554,13 @@ class EqpAttachmentsComponent {
|
|
|
1492
1554
|
}
|
|
1493
1555
|
generateVideoThumbnail(file) {
|
|
1494
1556
|
return new Promise((resolve, reject) => {
|
|
1495
|
-
const video = document.createElement(
|
|
1496
|
-
const canvas = document.createElement(
|
|
1497
|
-
const context = canvas.getContext(
|
|
1557
|
+
const video = document.createElement("video");
|
|
1558
|
+
const canvas = document.createElement("canvas");
|
|
1559
|
+
const context = canvas.getContext("2d");
|
|
1498
1560
|
// Crea un URL temporaneo per il file video
|
|
1499
1561
|
const videoUrl = URL.createObjectURL(file);
|
|
1500
1562
|
video.src = videoUrl;
|
|
1501
|
-
video.preload =
|
|
1563
|
+
video.preload = "metadata";
|
|
1502
1564
|
video.muted = true;
|
|
1503
1565
|
video.playsInline = true;
|
|
1504
1566
|
video.onloadedmetadata = () => {
|
|
@@ -1512,10 +1574,10 @@ class EqpAttachmentsComponent {
|
|
|
1512
1574
|
// Disegna il fotogramma sul canvas
|
|
1513
1575
|
context.drawImage(video, 0, 0, canvas.width, canvas.height);
|
|
1514
1576
|
// Estrai il Base64 (qualità 0.7 per risparmiare spazio)
|
|
1515
|
-
const thumbnail = canvas.toDataURL(
|
|
1577
|
+
const thumbnail = canvas.toDataURL("image/jpeg", 0.7);
|
|
1516
1578
|
// Pulisci la memoria
|
|
1517
1579
|
URL.revokeObjectURL(videoUrl);
|
|
1518
|
-
resolve(thumbnail.split(
|
|
1580
|
+
resolve(thumbnail.split(",")[1]); // Restituiamo solo la parte Base64
|
|
1519
1581
|
};
|
|
1520
1582
|
video.onerror = (err) => {
|
|
1521
1583
|
URL.revokeObjectURL(videoUrl);
|
|
@@ -1526,25 +1588,25 @@ class EqpAttachmentsComponent {
|
|
|
1526
1588
|
async compressVideoApi(file, config) {
|
|
1527
1589
|
// Prepariamo il FormData per inviare il file binario e i parametri di configurazione
|
|
1528
1590
|
const formData = new FormData();
|
|
1529
|
-
formData.append(
|
|
1530
|
-
formData.append(
|
|
1591
|
+
formData.append("video", file);
|
|
1592
|
+
formData.append("maxWidth", String(config.maxWidth ?? 1280));
|
|
1531
1593
|
if (config.crf != null)
|
|
1532
|
-
formData.append(
|
|
1594
|
+
formData.append("crf", String(config.crf));
|
|
1533
1595
|
if (config.preset)
|
|
1534
|
-
formData.append(
|
|
1596
|
+
formData.append("preset", config.preset);
|
|
1535
1597
|
if (config.crf == null) {
|
|
1536
|
-
formData.append(
|
|
1598
|
+
formData.append("bitrate", String(config.bitrate ?? 2500000));
|
|
1537
1599
|
}
|
|
1538
1600
|
if (config.maxFps != null)
|
|
1539
|
-
formData.append(
|
|
1601
|
+
formData.append("maxFps", String(config.maxFps));
|
|
1540
1602
|
if (config.audioBitrate != null)
|
|
1541
|
-
formData.append(
|
|
1603
|
+
formData.append("audioBitrate", String(config.audioBitrate));
|
|
1542
1604
|
// URL della tua API C#
|
|
1543
|
-
const apiUrl =
|
|
1605
|
+
const apiUrl = "https://tuo-servizio-api.it/api/video/compress";
|
|
1544
1606
|
try {
|
|
1545
1607
|
// Effettuiamo la chiamata. Usiamo 'fetch' per semplicità o HttpClient di Angular
|
|
1546
1608
|
const response = await fetch(apiUrl, {
|
|
1547
|
-
method:
|
|
1609
|
+
method: "POST",
|
|
1548
1610
|
body: formData,
|
|
1549
1611
|
// Nota: Non impostare Content-Type, il browser lo farà correttamente includendo il boundary
|
|
1550
1612
|
});
|
|
@@ -1559,268 +1621,29 @@ class EqpAttachmentsComponent {
|
|
|
1559
1621
|
throw error;
|
|
1560
1622
|
}
|
|
1561
1623
|
}
|
|
1562
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1563
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "17.3.12", type: EqpAttachmentsComponent, selector: "eqp-attachments", inputs: { disableAction: "disableAction", showHeader: "showHeader", attachmentsList: "attachmentsList", singleAttachment: "singleAttachment", showMatCard: "showMatCard", multipleAttachment: "multipleAttachment", loadMultipleFiles: "loadMultipleFiles", emptyTableMessage: "emptyTableMessage", allowOnlyImages: "allowOnlyImages", acceptedFileTypes: "acceptedFileTypes", isDisabled: "isDisabled", showInlinePreview: "showInlinePreview", getAttachmentEndpoint: "getAttachmentEndpoint", productionBaseUrl: "productionBaseUrl", compressionOptions: "compressionOptions", allowedTypes: "allowedTypes", isEqpTableMultiLanguage: "isEqpTableMultiLanguage", tablePaginatorVisible: "tablePaginatorVisible", isTableSearcheable: "isTableSearcheable", tablePaginatorSize: "tablePaginatorSize", separatedUploadButtons: "separatedUploadButtons", showPreview: "showPreview", singleAttachmentDragAndDrop: "singleAttachmentDragAndDrop", cropOptions: "cropOptions", cropDialogClass: "cropDialogClass", maxFileSizeMB: "maxFileSizeMB", cardSize: "cardSize", customCardWidthPx: "customCardWidthPx", customCardHeightPx: "customCardHeightPx", layout: "layout", openLinkLabel: "openLinkLabel", addButtonLabel: "addButtonLabel", downloadLabel: "downloadLabel", deleteLabel: "deleteLabel", fileNameLabel: "fileNameLabel", previewLabel: "previewLabel", uploadFileLabel: "uploadFileLabel", confirmLabel: "confirmLabel", abortLabel: "abortLabel", saveLabel: "saveLabel", exitLabel: "exitLabel", uploadWithDropboxLabel: "uploadWithDropboxLabel", cropLabel: "cropLabel", deleteDialogTitle: "deleteDialogTitle", deleteDialogMessage: "deleteDialogMessage", noImageSelectedErrorMessage: "noImageSelectedErrorMessage", wrongTypeSelectedErrorMessage: "wrongTypeSelectedErrorMessage", videoPreviewErrorMessage: "videoPreviewErrorMessage", audioPreviewErrorMessage: ["videoPreviewErrorMessage", "audioPreviewErrorMessage"], flipHorinzontalLabel: "flipHorinzontalLabel", flipVerticalLabel: "flipVerticalLabel", rotateRightLabel: "rotateRightLabel", rotateLeftLabel: "rotateLeftLabel", base64LimitMB: "base64LimitMB", uploadTitle: "uploadTitle", uploadSubtitle: "uploadSubtitle", dropHereLabel: "dropHereLabel", supportedFormatsLabel: "supportedFormatsLabel", browseFilesLabel: "browseFilesLabel", uploadSummaryLabel: "uploadSummaryLabel", filesLabel: "filesLabel", totalSizeLabel: "totalSizeLabel", emptyStateLabel: "emptyStateLabel", addedSuccessfullyLabel: "addedSuccessfullyLabel", removedLabel: "removedLabel", chooseView: "chooseView", showSummary: "showSummary", viewMode: "viewMode", showUploadTitle: "showUploadTitle", showDropArea: "showDropArea", hiddenColumns: "hiddenColumns", hiddenActions: "hiddenActions", showActionButtons: "showActionButtons", enableImageCrop: "enableImageCrop", actionHiddenFn: "actionHiddenFn", actionDisabledFn: "actionDisabledFn", videoCompression: "videoCompression", customMenuActions: "customMenuActions", customColumns: "customColumns" }, outputs: { localEditedAttachments: "localEditedAttachments", abortAddAttachment: "abortAddAttachment", downloadAttachment: "downloadAttachment", onDeleteAttachment: "onDeleteAttachment" }, viewQueries: [{ propertyName: "dialogAddAttachment", first: true, predicate: ["dialogAddAttachment"], descendants: true, static: true }, { propertyName: "dialogAddMultipleAttachment", first: true, predicate: ["dialogAddMultipleAttachment"], descendants: true, static: true }, { propertyName: "dialogCropImage", first: true, predicate: ["dialogCropImage"], descendants: true, static: true }, { propertyName: "addingLinkTemplate", first: true, predicate: ["addingLinkTemplate"], descendants: true }, { propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true }, { propertyName: "inlinePreviewTemplate", first: true, predicate: ["inlinePreviewTemplate"], descendants: true, static: true }, { propertyName: "dialogPreview", first: true, predicate: ["dialogPreview"], descendants: true, static: true }, { propertyName: "defaultFileTemplate", first: true, predicate: ["defaultFileTemplate"], descendants: true, static: true }, { propertyName: "defaultActionsTemplate", first: true, predicate: ["defaultActionsTemplate"], descendants: true, static: true }], ngImport: i0, template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n@if(showUploadTitle == true || chooseView == true){\r\n<div class=\"header\">\r\n @if(showUploadTitle == true){\r\n <h4>{{ uploadTitle }}</h4>\r\n }\r\n @if(chooseView == true){\r\n <mat-button-toggle-group [value]=\"viewMode\" (change)=\"setViewMode($event.value)\"\r\n aria-label=\"Modalit\u00E0 di visualizzazione\">\r\n <mat-button-toggle value=\"card\"><mat-icon>grid_view</mat-icon></mat-button-toggle>\r\n <mat-button-toggle value=\"table\"><mat-icon>view_list</mat-icon></mat-button-toggle>\r\n </mat-button-toggle-group>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione singolo -->\r\n@if (multipleAttachment != true) {\r\n@if (!singleAttachmentDragAndDrop) {\r\n@if (!addingLinkMode) {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addAttachmentButton\"></ng-container>\r\n</div>\r\n} @else {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addingLinkTemplate\"></ng-container>\r\n</div>\r\n}\r\n} @else {\r\n<input #fileInput id=\"file_attachment\" name=\"file_attachment\" type=\"file\" hidden (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (allowedTypes && allowedTypes.includes(1) && (!attachmentsList || attachmentsList.length == 0 ||\r\n(attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n\r\n@if (showDropArea == true) {\r\n<!-- FULL -->\r\n@if (layout === 'full') {\r\n\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n <div class=\"secondary-action\">\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n @if (allowedTypes.includes(2) && allowedTypes.includes(3)) {\r\n <a class=\"secondary-action-link\" [matMenuTriggerFor]=\"isDisabled ? null : linkMenu\"\r\n [class.disabled-link]=\"isDisabled\" (click)=\"$event.stopPropagation()\">\r\n o aggiungi da web\r\n </a>\r\n <mat-menu #linkMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"switchToAddingLinkMode()\">\r\n <mat-icon>link</mat-icon>\r\n <span>Aggiungi da link</span>\r\n </button>\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\">\r\n <mat-icon>cloud_queue</mat-icon>\r\n <span>Carica da Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @else if (allowedTypes.includes(2)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">\r\n aggiungi un link\r\n </a>\r\n }\r\n\r\n @else if (allowedTypes.includes(3)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); chooseDropboxFile()\">\r\n carica da Dropbox\r\n </a>\r\n }\r\n }\r\n </div>\r\n</div>\r\n}@else {\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button color=\"primary\" [disabled]=\"isDisabled\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n}\r\n}\r\n\r\n<!-- Azioni singolo elemento (come prima) -->\r\n<div class=\"text-center\">\r\n @if (attachmentsList && attachmentsList.length > 0 && attachmentsList[0] && showActionButtons == true) {\r\n <button class=\"mb-2 me-2 eqp-attachments-download-btn\" (click)=\"viewAttachment(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button color=\"primary\">\r\n @if (attachmentsList[0].AttachmentType == AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n\r\n @if (showPreview && (!attachmentsList[0].FileContentType || (!attachmentsList[0].FileContentType.startsWith('video')\r\n && !attachmentsList[0].FileContentType.startsWith('audio'))) && attachmentsList[0].IsImage == true) {\r\n <button class=\"mb-2 me-2 eqp-attachments-preview-btn\" (click)=\"openPreviewDialog(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button color=\"primary\">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n }\r\n\r\n <button [disabled]=\"disableAction\" class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\" type=\"button\" mat-raised-button [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione multipla -->\r\n@if (multipleAttachment == true && showDropArea == true) {\r\n<input #fileInput id=\"file_attachment_multi\" name=\"file_attachment_multi\" type=\"file\" hidden\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (layout === 'full') {\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n @if (allowedTypes.includes(2)) {\r\n <div class=\"secondary-action-link\">\r\n o <a (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">aggiungi un link</a>\r\n </div>\r\n }\r\n</div>\r\n}@else{\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button [disabled]=\"isDisabled\" color=\"primary\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n\r\n@if (attachmentsList?.length > 0 && showSummary) {\r\n<div class=\"upload-stats\">\r\n\r\n <div class=\"stats-info\">\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ attachmentsList?.length }}</div>\r\n <div class=\"stat-label\">{{ filesLabel }}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ totalSizeFormatted }}</div>\r\n <div class=\"stat-label\">{{ totalSizeLabel }}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"progressPercent\"></div>\r\n </div>\r\n\r\n</div>\r\n} @else if(attachmentsList?.length == 0){\r\n<div class=\"empty-state\">{{ emptyStateLabel }}</div>\r\n}\r\n\r\n<!-- Griglia anteprime card (vale per singolo e multiplo) -->\r\n@if (viewMode === 'card') {\r\n\r\n<div class=\"file-previews\" [ngStyle]=\"getPreviewsContainerStyle()\">\r\n @for (att of attachmentsList; track att.ID) {\r\n <div [ngClass]=\"getCardClass(att)\">\r\n <div class=\"preview-img-container\" (click)=\"!att.isUploading && handlePrimaryAction(att)\">\r\n\r\n @if (att.IsImage || att.FileThumbnailBase64) {\r\n <img class=\"preview-img\" [src]=\"'data:image/jpeg;base64,' + (att.FileThumbnailBase64 || att.FileDataBase64)\"\r\n [alt]=\"att.FileName\" />\r\n } @else {\r\n <div class=\"file-icon\"><i [ngClass]=\"getAttachmentIcon(att)\"></i></div>\r\n }\r\n\r\n <div class=\"preview-action-overlay\">\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n <mat-icon>play_arrow</mat-icon>\r\n }\r\n @else if (att.IsImage && canBePreviewed(att)) {\r\n <mat-icon>visibility</mat-icon>\r\n }\r\n @else if (att.FileContentType === 'application/pdf' && canBePreviewed(att)) {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n @else if (att.AttachmentType === AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n }\r\n @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"att.FileName\">{{ att.FileName }}</div>\r\n </div>\r\n\r\n @if(!isDeleteHidden(att)){\r\n <button mat-icon-button class=\"remove-btn\" (click)=\"deleteAttachment(att)\"\r\n [disabled]=\"att.isUploading || isDeleteDisabled(att)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (att.isUploading) {\r\n <div class=\"upload-spinner\"></div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n} @else if(viewMode === 'table' && attachmentsList?.length > 0) {\r\n\r\n\r\n<div class=\"table-view-container\">\r\n\r\n <div class=\"table-header\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n {{ col.display }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @for (att of attachmentsList; track att.ID) {\r\n <div class=\"table-row\">\r\n\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n\r\n @switch (col.type) {\r\n\r\n @case ('template') {\r\n <div class=\"template-wrapper\">\r\n <ng-container [ngTemplateOutlet]=\"col.externalTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: att }\"></ng-container>\r\n </div>\r\n }\r\n @case ('date') {\r\n <span class=\"metadata-value\">{{ att[col.key] | date:'dd/MM/yyyy' }}</span>\r\n }\r\n @default {\r\n <span class=\"metadata-value\">{{ att[col.key] }}</span>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Notifica toast -->\r\n<div class=\"upload-notification\" [class.show]=\"toast?.visible\" [class.success]=\"toast?.type === 'success'\"\r\n [class.error]=\"toast?.type === 'error'\">\r\n <span>{{ toast?.text }}</span>\r\n <div class=\"notification-progress\"></div>\r\n</div>\r\n\r\n<ng-template #defaultFileTemplate let-att>\r\n <i class=\"file-icon-small\" [ngClass]=\"getAttachmentIcon(att)\"></i>\r\n <div class=\"file-info-text\">\r\n <span class=\"file-name-table\">{{ att.FileName }}</span>\r\n <span class=\"file-type-table\">{{ att.FileExtension || 'Link' }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultActionsTemplate let-att>\r\n <button mat-icon-button (click)=\"handlePrimaryAction(att)\"\r\n [matTooltip]=\"att.FileContentType?.startsWith('video/') ? 'Riproduci video' : 'Visualizza/Scarica'\">\r\n\r\n <mat-icon>\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n play_arrow\r\n } @else {\r\n {{ att.AttachmentType === AttachmentType.FILE ? 'download' : 'open_in_new' }}\r\n }\r\n </mat-icon>\r\n </button>\r\n\r\n @if (!hiddenActions.includes('actionsMenu')) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"actionsMenu\" matTooltip=\"Altre opzioni\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n }\r\n\r\n <mat-menu #actionsMenu=\"matMenu\">\r\n @for (action of _sortedMenuActions; track action.name) {\r\n @if (!isActionHidden(action, att)) {\r\n <button mat-menu-item (click)=\"action.fn(att)\" [disabled]=\"isActionDisabled(action, att)\">\r\n <mat-icon [color]=\"action.icon === 'delete' ? 'warn' : undefined\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n <span>{{ action.name }}</span>\r\n </button>\r\n }\r\n }\r\n </mat-menu>\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogCropImage>\r\n <div style=\"overflow-x: hidden; display: flex; flex-direction: column; height: 100%; min-height: 0; flex: 1 1 auto;\"\r\n [ngClass]=\"cropDialogClass\">\r\n <!-- @if (showCropImage == true) { -->\r\n <ng-container [ngTemplateOutlet]=\"croppieTemplate\" [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\">\r\n </ng-container>\r\n <!-- } -->\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n @if (row.AttachmentType != AttachmentType.LINK && row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <img [src]=\"'data:image/png;base64,' + (row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64)\" />\r\n </div>\r\n } @else if (row.AttachmentType != AttachmentType.LINK && !row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"modern-dialog-container\"> @if (selectedAttachment) {\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ previewLabel }}</span>\r\n <span class=\"file-t\">{{ selectedAttachment.FileName }}</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"media-viewer-wrapper\">\r\n @if (selectedAttachment.IsImage) {\r\n <img class=\"main-preview-media\"\r\n [src]=\"'data:image/png;base64,' + (selectedAttachment.FileDataBase64 || selectedAttachment.FileThumbnailBase64)\"\r\n [alt]=\"selectedAttachment.FileName\" />\r\n }\r\n @else if (selectedAttachment.FileContentType?.startsWith('video/')) {\r\n <video controls autoplay playsinline class=\"main-preview-media video-player\">\r\n <source [src]=\"selectedAttachment.TrustedUrl\" [type]=\"selectedAttachment.FileContentType\">\r\n Il tuo browser non supporta il video.\r\n </video>\r\n }\r\n @else {\r\n <div class=\"iframe-container\">\r\n <iframe class=\"preview-iframe-modern\" [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n }\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Chiudi</button>\r\n @if (selectedAttachment.AttachmentType !== AttachmentType.LINK) {\r\n <button mat-raised-button color=\"primary\" (click)=\"viewAttachment(selectedAttachment)\" class=\"btn-download\">\r\n <mat-icon>download</mat-icon> <span>{{ downloadLabel }}</span>\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <input #fileInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n @if (allowedTypes && allowedTypes.length == 1 && (multipleAttachment == true || !attachmentsList ||\r\n attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\" [disabled]=\"isDisabled\">\r\n @if (allowedTypes[0] == 1) { <mat-icon>cloud_upload</mat-icon> }\r\n @if (allowedTypes[0] == 2) { <i class=\"fas fa-link\"></i> }\r\n @if (allowedTypes[0] == 3) { <i class=\"fa-brands fa-dropbox\"></i> }\r\n <span style=\"margin-left: 10px\">\r\n {{ allowedTypes[0] == 1 ? (addButtonLabel + \" file\") : allowedTypes[0] == 2 ? (addButtonLabel + \" link\") :\r\n uploadWithDropboxLabel }}\r\n </span>\r\n </button>\r\n }\r\n\r\n @if (!separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\" [disabled]=\"isDisabled\">\r\n @if (multipleAttachment != true) { <mat-icon>cloud_upload</mat-icon> } @else { <mat-icon>add</mat-icon> }\r\n <span style=\"margin-left: 0px\">{{ addButtonLabel }}</span>\r\n </button>\r\n\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(1)) {\r\n <button mat-menu-item (click)=\"imageInput.click()\" class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(2)) {\r\n <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"switchToAddingLinkMode()\" class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(3)) {\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\" class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n }\r\n\r\n @if (separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <div class=\"btn-group\">\r\n @if (allowedTypes.includes(1)) {\r\n <button (click)=\"imageInput.click()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(2)) {\r\n <button (click)=\"switchToAddingLinkMode()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(3)) {\r\n <button (click)=\"chooseDropboxFile()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ cropLabel }}</span>\r\n <span class=\"file-t\">Regola le dimensioni e l'orientamento</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button type=\"button\" (click)=\"abortFile()\" class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"crop-toolbar\">\r\n @if (cropOptions.includes(1)) {\r\n <button mat-icon-button [matTooltip]=\"rotateLeftLabel\"\r\n (click)=\"rotateLeft()\"><mat-icon>rotate_left</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"rotateRightLabel\"\r\n (click)=\"rotateRight()\"><mat-icon>rotate_right</mat-icon></button>\r\n }\r\n @if (cropOptions.includes(2)) {\r\n <button mat-icon-button [matTooltip]=\"flipHorinzontalLabel\"\r\n (click)=\"flipHorizontal()\"><mat-icon>flip_horizontal</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"flipVerticalLabel\"\r\n (click)=\"flipVertical()\"><mat-icon>flip_vertical</mat-icon></button>\r\n }\r\n <button mat-icon-button matTooltip=\"Reset\"\r\n (click)=\"restoreOriginalDimensions()\"><mat-icon>replay</mat-icon></button>\r\n </div>\r\n\r\n <div class=\"media-viewer-wrapper\">\r\n <div class=\"crop-container-modern\">\r\n <image-cropper [imageFile]=\"selectedFile\" [maintainAspectRatio]=\"false\" [canvasRotation]=\"canvasRotation\"\r\n [transform]=\"transform\" format=\"png\" (imageCropped)=\"imageCropped($event)\" [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\" [output]=\"'base64'\" [containWithinAspectRatio]=\"true\" [onlyScaleDown]=\"true\"\r\n [alignImage]=\"'center'\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button (click)=\"abortFile()\" class=\"btn-close\">{{ abortLabel }}</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"confirmAddAttachment()\" class=\"btn-download\">\r\n <mat-icon>check</mat-icon> {{ confirmLabel }}\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"type-icon-wrapper\">\r\n <mat-icon>link</mat-icon>\r\n </div>\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">Aggiungi un link</span>\r\n <span class=\"file-t\">Inserisci l'URL della risorsa web</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"add-link-modern-content\">\r\n <form [formGroup]=\"newAttachmentForm\" class=\"add-link-form\">\r\n <mat-form-field appearance=\"outline\" class=\"w-100 mt-3\">\r\n <mat-label>URL del collegamento</mat-label>\r\n <input matInput formControlName=\"filePath\" placeholder=\"https://...\" required>\r\n <mat-icon matSuffix>language</mat-icon>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>Titolo (opzionale)</mat-label>\r\n <input matInput formControlName=\"fileName\" placeholder=\"Es. Documento Progetto\">\r\n <mat-icon matSuffix>title</mat-icon>\r\n </mat-form-field>\r\n </form>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Annulla</button>\r\n <button mat-raised-button color=\"primary\" [mat-dialog-close]=\"newAttachmentForm.value\"\r\n [disabled]=\"newAttachmentForm.invalid\" class=\"btn-download\">\r\n <mat-icon>add</mat-icon> Aggiungi\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{--primary-color: #6a5af9;--primary-color-dark: #5441f8;--success-color: #1ce593;--error-color: #ff5b5b;--background-light: #f7f9fc;--background-card: rgba(255, 255, 255, .7);--text-color: #1e293b;--text-color-light: #64748b;--border-color: rgba(203, 213, 225, .5);--shadow-color: rgba(99, 102, 241, .2);--border-radius: 16px;--transition-speed: .3s}@keyframes fadeIn{0%{opacity:0;transform:translateY(15px)}to{opacity:1;transform:translateY(0)}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--primary-color)}70%{box-shadow:0 0 0 10px #6a5af900}to{box-shadow:0 0 #6a5af900}}.container{width:100%;max-width:700px;margin:2rem auto;font-family:Inter,sans-serif}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border-color)}.header h1{color:var(--text-color);font-size:1.8rem;font-weight:700;margin:0}.dropbox{width:100%;border:2px dashed var(--border-color);border-radius:var(--border-radius);padding:2.5rem;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all var(--transition-speed) ease}.dropbox:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color);border-color:var(--primary-color)}.dropbox.dragover{border-style:solid;border-color:var(--primary-color);transform:scale(1.02);box-shadow:0 0 25px var(--shadow-color);animation:pulse 1.5s infinite}.dropbox .dropbox-icon{font-size:3.5rem;color:var(--primary-color)}.dropbox .dropbox-text{font-size:1.1rem;font-weight:600;color:var(--text-color);margin-top:1rem}.dropbox .dropbox-subtext{color:var(--text-color-light);margin-top:.5rem}.dropbox .browse-btn{margin-top:1.5rem;padding:.75rem 1.5rem;background-color:var(--primary-color);color:#fff;border:none;border-radius:10px;font-weight:600;transition:all var(--transition-speed) ease}.dropbox .browse-btn:hover{background-color:var(--primary-color-dark);transform:translateY(-2px)}.file-previews{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1.5rem;margin-top:2rem}.file-previews{display:grid;gap:16px;padding:16px;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width, 200px),1fr))}.file-preview{background-color:var(--background-card);border-radius:var(--border-radius);box-shadow:0 4px 15px #0000000d;border:1px solid var(--border-color);overflow:hidden;display:flex;flex-direction:column;position:relative;opacity:0;animation:fadeIn .5s ease-out forwards;transition:transform var(--transition-speed) ease,box-shadow var(--transition-speed) ease}.file-preview.uploading{cursor:wait}.file-preview.uploading .preview-img-container:after{content:\"\";position:absolute;inset:0;background:#ffffffb3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);pointer-events:none}.file-preview .preview-action-overlay{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;background-color:#0006;color:#fff;opacity:1;transition:opacity .3s ease}.file-preview .preview-action-overlay .mat-icon{font-size:36px;width:36px;height:36px}.file-preview .remove-btn{position:absolute;top:8px;right:8px;z-index:2;background-color:#0000004d;color:#fff;width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;transition:all var(--transition-speed) ease}.file-preview .remove-btn:hover{background-color:#ff5b5b}.file-preview .remove-btn .mat-icon{font-size:18px}@media (hover: hover){.file-preview .remove-btn .file-preview .preview-action-overlay{opacity:0}.file-preview .remove-btn .file-preview:hover .preview-action-overlay,.file-preview .remove-btn .file-preview:hover .remove-btn{opacity:1}.file-preview .remove-btn .file-preview .remove-btn{opacity:0}}@media (hover: hover) and (min-width: 769px){.file-preview .remove-btn{opacity:0;transform:scale(.8)}.file-preview:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color)}.file-preview:hover .remove-btn{opacity:1;transform:scale(1)}}.file-preview .preview-img-container{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;cursor:pointer;background-color:#f0f2f5}.file-preview .preview-img{width:100%;height:100%;object-fit:cover}.file-preview .file-icon{font-size:4rem;color:var(--primary-color)}.file-preview .file-info{padding:12px;border-top:1px solid var(--border-color);flex-grow:1;display:flex;align-items:center}.file-preview .file-name{font-weight:600;font-size:.9rem;color:var(--text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-preview .upload-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border:4px solid rgba(0,0,0,.1);border-left-color:var(--primary-color);border-radius:50%;animation:spin 1s linear infinite;pointer-events:none}.file-preview.card-small{width:140px}.file-preview.card-small .preview-img-container{height:80px}.file-preview.card-small .file-info{padding:8px}.file-preview.card-small .file-name{font-size:.8rem}.file-preview.card-small .file-icon{font-size:3rem}.file-preview.card-small .remove-btn{width:28px;height:28px}.file-preview.card-small .remove-btn .mat-icon{font-size:16px}.file-preview.card-large{width:280px}.file-preview.card-large .preview-img-container{height:180px}.file-preview.card-large .file-info{padding:16px}.file-preview.card-large .file-name{font-size:1rem}.file-preview.card-large .file-icon{font-size:5rem}.file-preview.card-large .remove-btn{width:36px;height:36px}.file-preview.card-large .remove-btn .mat-icon{font-size:20px}.file-preview[style*=--eqp-card-width]{width:var(--eqp-card-width)}.file-preview[style*=--eqp-card-width] .preview-img-container{height:calc(var(--eqp-card-width) * .65)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}.upload-stats{background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--border-color);border-radius:var(--border-radius);padding:1.5rem;margin-top:2rem;animation:fadeIn .5s ease-out}.upload-stats .stats-info{display:flex;justify-content:space-around}.upload-stats .progress-bar{height:10px;background-color:var(--border-color);border-radius:5px;overflow:hidden;margin-top:1rem}.upload-stats .progress-fill{height:100%;background:linear-gradient(90deg,var(--primary-color),var(--success-color));transition:width var(--transition-speed) ease-out;border-radius:5px}.upload-notification{position:fixed;bottom:20px;left:50%;transform:translate(-50%,100px);padding:1rem 1.5rem;border-radius:var(--border-radius);color:#fff;font-weight:600;box-shadow:0 10px 30px #0003;transition:transform var(--transition-speed) cubic-bezier(.175,.885,.32,1.275)}.upload-notification.show{transform:translate(-50%)}.upload-notification.success{background-color:var(--success-color)}.upload-notification.error{background-color:var(--error-color)}::ng-deep .cdk-overlay-pane.eqp-crop-dialog{transform:translateY(-4vh)}@media (max-width: 600px){::ng-deep .cdk-overlay-pane.crop-dialog{width:auto!important}}::ng-deep .eqp-attachments-dialog{display:flex!important;flex-direction:column!important}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container .mdc-dialog__surface{border-radius:20px!important;padding:0!important;overflow:hidden!important;width:fit-content!important;min-width:350px!important;max-width:95vw!important;max-height:90vh!important;margin:0 auto;background-color:#fff!important;display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden!important}.modern-dialog-container{display:flex;flex-direction:column;width:100%;max-width:100%;flex:1 1 auto;min-height:0;height:100%;max-height:100%;background:#fff;--preview-header-h: 66px;--preview-footer-h: 66px;--preview-padding-y: 30px}.modern-dialog-container .main-preview-media{display:block;max-width:100%;max-height:var(--media-max-h);width:auto;height:auto;object-fit:contain;border-radius:12px;background:#fff;padding:4px;box-shadow:0 10px 30px #00000014}.modern-dialog-container video.main-preview-media{width:min(100%,1100px);background:#000}.modern-dialog-container .iframe-container{width:min(100%,1100px);height:var(--media-max-h);display:flex;width:100%;max-width:1100px}.modern-dialog-container .preview-iframe-modern{width:100%;height:100%;border:0;border-radius:12px;background:#f8fafc}.modern-dialog-container .preview-header{flex:0 0 auto;flex-shrink:0;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;border-bottom:1px solid var(--border-color);background:#f8fafc;z-index:10;width:100%}.modern-dialog-container .preview-header .close-btn{display:inline-flex!important;align-items:center!important;justify-content:center!important;padding:0!important;width:40px!important;height:40px!important}.modern-dialog-container .preview-header .close-btn ::ng-deep mat-icon{display:flex!important;align-items:center!important;justify-content:center!important;margin:0!important;padding:0!important;line-height:1!important}.modern-dialog-container .preview-header .header-info{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex:1 1 auto;min-width:0;text-align:left}.modern-dialog-container .preview-header .header-info .type-icon-wrapper{background:var(--primary-color);color:#fff;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px var(--shadow-color)}.modern-dialog-container .preview-header .header-info .title-group{display:flex;flex-direction:column;align-items:flex-start;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .main-t{font-weight:800;color:var(--text-color);font-size:.95rem;line-height:1.2;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .file-t{font-size:.75rem;color:var(--text-color-light);max-width:250px;overflow:hidden;text-overflow:ellipsis;text-align:left}.modern-dialog-container .preview-content-area{flex:1 1 auto;background:#fff!important;display:flex;flex-direction:column;padding:15px 15px 22px!important;overflow:hidden!important;min-height:0;width:100%;--media-max-h: calc(90vh - var(--preview-header-h) - var(--preview-footer-h) - var(--preview-padding-y))}.modern-dialog-container .preview-content-area .crop-toolbar{flex-shrink:0;z-index:20;background:#0f172a14;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:6px 16px;border-radius:30px;margin:0 auto 15px;display:flex;gap:8px;box-shadow:0 4px 12px #0000000d}.modern-dialog-container .preview-content-area .crop-toolbar button{color:var(--text-color)!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper{flex:1 1 auto;width:100%;height:100%;display:flex;flex-direction:column;align-items:stretch;min-height:0;overflow:hidden}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern{flex:1 1 auto;display:flex;flex-direction:column;justify-content:center;align-items:center;background:transparent;border-radius:12px;padding:0;overflow:hidden;min-height:0;width:100%;height:100%}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern image-cropper{flex:1 1 auto;width:100%;height:100%;max-width:100%!important;max-height:100%!important;display:block;min-height:0}.modern-dialog-container .add-link-modern-content{flex:1;background:#fff;padding:24px!important}.modern-dialog-container .add-link-modern-content .add-link-form{display:flex;flex-direction:column;gap:10px}.modern-dialog-container .preview-actions{flex-shrink:0;padding:12px 24px;background:#f8fafc;border-top:1px solid #e2e8f0;margin:0}.modern-dialog-container .preview-actions .btn-download{border-radius:12px;font-weight:600;box-shadow:0 4px 12px var(--shadow-color)}@media (max-width: 600px){.modern-dialog-container{max-height:95vh}.modern-dialog-container .preview-content-area{padding:10px!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper video.main-preview-media{width:100%!important;max-height:55vh!important;border-radius:4px;box-shadow:none}.modern-dialog-container .preview-content-area .media-viewer-wrapper .iframe-container{height:50vh}.modern-dialog-container .preview-content-area .crop-toolbar{width:calc(100% - 20px);max-width:400px;margin-bottom:10px;padding:4px 8px;gap:4px;overflow-x:auto;justify-content:center;-webkit-overflow-scrolling:touch;scrollbar-width:none}.modern-dialog-container .preview-content-area .crop-toolbar::-webkit-scrollbar{display:none}.modern-dialog-container .preview-content-area .crop-toolbar button{flex-shrink:0;transform:scale(.85);width:40px;height:40px}.modern-dialog-container .preview-actions{padding:10px 15px;flex-direction:column-reverse;gap:8px}.modern-dialog-container .preview-actions button{width:100%;margin:0!important}}@media (max-width: 360px){.modern-dialog-container .preview-content-area .crop-toolbar{gap:2px}.modern-dialog-container .preview-content-area .crop-toolbar button{transform:scale(.75)}}.control-icon{font-size:28px;cursor:pointer}image-cropper{display:flex!important;max-width:100%!important;max-height:100%!important;height:100%;width:100%}image-cropper canvas,image-cropper img{max-width:100%!important;max-height:100%!important}.crop-large{display:flex}.crop-small{display:none}@media (max-width: 600px){.dialog-content{max-height:55vh}.crop-container{max-width:100%;aspect-ratio:auto}.crop-large{display:none}.crop-small{display:flex;justify-content:center;gap:14px}.control-icon{font-size:24px}}.stats-header{display:flex;justify-content:space-between;align-items:center;width:100%}.table-view-container{margin-top:1.5rem;background-color:var(--background-card);border-radius:var(--border-radius);border:1px solid var(--border-color);overflow:hidden;animation:fadeIn .5s ease-out}.table-header,.table-row{display:flex;align-items:center;padding:0 1rem;transition:background-color var(--transition-speed) ease}.table-header{background-color:#f8f9fa;font-weight:600;color:var(--text-color-light);font-size:.8rem;text-transform:uppercase;border-bottom:2px solid var(--border-color)}.table-row{border-bottom:1px solid var(--border-color)}.table-row:last-child{border-bottom:none}.table-row:hover{background-color:#00000005}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem}.name-col{flex:4}.size-col,.date-col{flex:2}.actions-col{flex:1;justify-content:flex-end;min-width:150px}.file-icon-small{font-size:1.5rem;color:var(--primary-color)}.file-info-text{display:flex;flex-direction:column}.file-name-table{font-weight:600;color:var(--text-color)}.file-type-table{font-size:.8rem;color:var(--text-color-light)}@media (max-width: 768px){.date-col{display:none}.name-col{flex:3}.size-col{flex:2}.actions-col{flex:2;min-width:120px}}.secondary-action-link{color:var(--primary-color);text-decoration:none;border-bottom:1px solid var(--primary-color);cursor:pointer;font-weight:500}.secondary-action-link:hover{color:var(--primary-color-dark);border-bottom-color:var(--primary-color-dark)}h2[mat-dialog-title]+mat-dialog-content.add-link-dialog-content{padding-top:20px}mat-dialog-content.add-link-dialog-content{padding-left:24px;padding-right:24px;padding-bottom:20px}.add-link-form{display:flex;flex-direction:column;gap:16px}::ng-deep .eqp-attachments-preview-dialog{--mdc-dialog-subhead-line-height: normal}::ng-deep .eqp-attachments-preview-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;background:#fff!important}:host ::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{--mdc-dialog-subhead-size: 1.25rem;--mdc-dialog-subhead-line-height: 1.5;--mdc-dialog-subhead-weight: 600;--mdc-dialog-supporting-text-size: 1rem}.empty-state{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:1.5rem 1rem;margin-top:1.5rem;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#f8f9fa;text-align:center;color:var(--text-color-light);animation:fadeIn .5s ease-out}.empty-state:before{content:\"\\1f4ed\";font-size:2.5rem;margin-bottom:1rem;opacity:.7}.secondary-action-link.disabled-link{color:#adb5bd;cursor:not-allowed;border-bottom-color:transparent}.secondary-action-link.disabled-link:hover{color:#adb5bd;border-bottom-color:transparent}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem;min-width:0;overflow:hidden}.table-cell.col-actions{flex:0 0 150px;justify-content:flex-end;overflow:visible}.compact-uploader{display:flex;align-items:center;gap:16px;padding:16px;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#fcfdff;transition:all .3s ease}.compact-uploader .compact-text{flex:1 1 auto;min-width:0;cursor:pointer}.compact-uploader .compact-text:hover .compact-title{color:var(--primary-color)}.compact-uploader .compact-title{font-weight:600;color:var(--text-color);transition:color .3s ease}.compact-uploader .compact-subtitle{font-size:.8rem;color:var(--text-color-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-uploader .compact-icon mat-icon{font-size:36px;width:36px;height:36px;color:var(--primary-color)}.compact-uploader .compact-actions{display:flex;gap:8px;flex-shrink:0}.compact-uploader.dragover{background-color:#f4f8ff;border-color:var(--primary-color);box-shadow:0 0 10px var(--shadow-color)}.disabled-dropzone{opacity:.5;cursor:not-allowed!important;background-color:#f5f5f5;border-color:#d1d5db}.disabled-dropzone *{pointer-events:none}.disabled-dropzone .browse-btn,.disabled-dropzone button{cursor:not-allowed!important;background-color:#e5e7eb;color:#9ca3af;border:none}.disabled-dropzone .secondary-action-link,.disabled-dropzone a{color:#9ca3af;text-decoration:none}\n"], dependencies: [{ kind: "component", type: i6.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i7.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i8.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i8.MatLabel, selector: "mat-label" }, { kind: "directive", type: i8.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i9.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i9.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i9.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i10.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i10.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i11.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i12.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i13.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i13.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i13.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i14.ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }, { kind: "pipe", type: i13.DatePipe, name: "date" }] });
|
|
1624
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentsComponent, deps: [{ token: i1.MatDialog }, { token: i2.FormBuilder }, { token: i3.DomSanitizer }, { token: i4.HttpClient }, { token: EqpAttachmentService }], target: i0.ɵɵFactoryTarget.Component });
|
|
1625
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.5", type: EqpAttachmentsComponent, isStandalone: false, selector: "eqp-attachments", inputs: { disableAction: { classPropertyName: "disableAction", publicName: "disableAction", isSignal: true, isRequired: false, transformFunction: null }, showHeader: { classPropertyName: "showHeader", publicName: "showHeader", isSignal: true, isRequired: false, transformFunction: null }, attachmentsList: { classPropertyName: "attachmentsList", publicName: "attachmentsList", isSignal: false, isRequired: false, transformFunction: null }, singleAttachment: { classPropertyName: "singleAttachment", publicName: "singleAttachment", isSignal: true, isRequired: false, transformFunction: null }, showMatCard: { classPropertyName: "showMatCard", publicName: "showMatCard", isSignal: true, isRequired: false, transformFunction: null }, multipleAttachment: { classPropertyName: "multipleAttachment", publicName: "multipleAttachment", isSignal: true, isRequired: false, transformFunction: null }, loadMultipleFiles: { classPropertyName: "loadMultipleFiles", publicName: "loadMultipleFiles", isSignal: true, isRequired: false, transformFunction: null }, emptyTableMessage: { classPropertyName: "emptyTableMessage", publicName: "emptyTableMessage", isSignal: true, isRequired: false, transformFunction: null }, allowOnlyImages: { classPropertyName: "allowOnlyImages", publicName: "allowOnlyImages", isSignal: true, isRequired: false, transformFunction: null }, acceptedFileTypes: { classPropertyName: "acceptedFileTypes", publicName: "acceptedFileTypes", isSignal: false, isRequired: false, transformFunction: null }, isDisabled: { classPropertyName: "isDisabled", publicName: "isDisabled", isSignal: true, isRequired: false, transformFunction: null }, showInlinePreview: { classPropertyName: "showInlinePreview", publicName: "showInlinePreview", isSignal: true, isRequired: false, transformFunction: null }, getAttachmentEndpoint: { classPropertyName: "getAttachmentEndpoint", publicName: "getAttachmentEndpoint", isSignal: true, isRequired: false, transformFunction: null }, productionBaseUrl: { classPropertyName: "productionBaseUrl", publicName: "productionBaseUrl", isSignal: true, isRequired: false, transformFunction: null }, compressionOptions: { classPropertyName: "compressionOptions", publicName: "compressionOptions", isSignal: true, isRequired: false, transformFunction: null }, allowedTypes: { classPropertyName: "allowedTypes", publicName: "allowedTypes", isSignal: false, isRequired: false, transformFunction: null }, isEqpTableMultiLanguage: { classPropertyName: "isEqpTableMultiLanguage", publicName: "isEqpTableMultiLanguage", isSignal: true, isRequired: false, transformFunction: null }, tablePaginatorVisible: { classPropertyName: "tablePaginatorVisible", publicName: "tablePaginatorVisible", isSignal: true, isRequired: false, transformFunction: null }, isTableSearcheable: { classPropertyName: "isTableSearcheable", publicName: "isTableSearcheable", isSignal: true, isRequired: false, transformFunction: null }, tablePaginatorSize: { classPropertyName: "tablePaginatorSize", publicName: "tablePaginatorSize", isSignal: true, isRequired: false, transformFunction: null }, separatedUploadButtons: { classPropertyName: "separatedUploadButtons", publicName: "separatedUploadButtons", isSignal: true, isRequired: false, transformFunction: null }, showPreview: { classPropertyName: "showPreview", publicName: "showPreview", isSignal: true, isRequired: false, transformFunction: null }, singleAttachmentDragAndDrop: { classPropertyName: "singleAttachmentDragAndDrop", publicName: "singleAttachmentDragAndDrop", isSignal: true, isRequired: false, transformFunction: null }, cropOptions: { classPropertyName: "cropOptions", publicName: "cropOptions", isSignal: true, isRequired: false, transformFunction: null }, cropDialogClass: { classPropertyName: "cropDialogClass", publicName: "cropDialogClass", isSignal: true, isRequired: false, transformFunction: null }, maxFileSizeMB: { classPropertyName: "maxFileSizeMB", publicName: "maxFileSizeMB", isSignal: true, isRequired: false, transformFunction: null }, cardSize: { classPropertyName: "cardSize", publicName: "cardSize", isSignal: true, isRequired: false, transformFunction: null }, customCardWidthPx: { classPropertyName: "customCardWidthPx", publicName: "customCardWidthPx", isSignal: true, isRequired: false, transformFunction: null }, customCardHeightPx: { classPropertyName: "customCardHeightPx", publicName: "customCardHeightPx", isSignal: true, isRequired: false, transformFunction: null }, layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, openLinkLabel: { classPropertyName: "openLinkLabel", publicName: "openLinkLabel", isSignal: true, isRequired: false, transformFunction: null }, addButtonLabel: { classPropertyName: "addButtonLabel", publicName: "addButtonLabel", isSignal: true, isRequired: false, transformFunction: null }, downloadLabel: { classPropertyName: "downloadLabel", publicName: "downloadLabel", isSignal: true, isRequired: false, transformFunction: null }, deleteLabel: { classPropertyName: "deleteLabel", publicName: "deleteLabel", isSignal: true, isRequired: false, transformFunction: null }, fileNameLabel: { classPropertyName: "fileNameLabel", publicName: "fileNameLabel", isSignal: true, isRequired: false, transformFunction: null }, previewLabel: { classPropertyName: "previewLabel", publicName: "previewLabel", isSignal: true, isRequired: false, transformFunction: null }, uploadFileLabel: { classPropertyName: "uploadFileLabel", publicName: "uploadFileLabel", isSignal: true, isRequired: false, transformFunction: null }, confirmLabel: { classPropertyName: "confirmLabel", publicName: "confirmLabel", isSignal: true, isRequired: false, transformFunction: null }, abortLabel: { classPropertyName: "abortLabel", publicName: "abortLabel", isSignal: true, isRequired: false, transformFunction: null }, saveLabel: { classPropertyName: "saveLabel", publicName: "saveLabel", isSignal: true, isRequired: false, transformFunction: null }, exitLabel: { classPropertyName: "exitLabel", publicName: "exitLabel", isSignal: true, isRequired: false, transformFunction: null }, uploadWithDropboxLabel: { classPropertyName: "uploadWithDropboxLabel", publicName: "uploadWithDropboxLabel", isSignal: true, isRequired: false, transformFunction: null }, cropLabel: { classPropertyName: "cropLabel", publicName: "cropLabel", isSignal: true, isRequired: false, transformFunction: null }, deleteDialogTitle: { classPropertyName: "deleteDialogTitle", publicName: "deleteDialogTitle", isSignal: true, isRequired: false, transformFunction: null }, deleteDialogMessage: { classPropertyName: "deleteDialogMessage", publicName: "deleteDialogMessage", isSignal: true, isRequired: false, transformFunction: null }, noImageSelectedErrorMessage: { classPropertyName: "noImageSelectedErrorMessage", publicName: "noImageSelectedErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, wrongTypeSelectedErrorMessage: { classPropertyName: "wrongTypeSelectedErrorMessage", publicName: "wrongTypeSelectedErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, videoPreviewErrorMessage: { classPropertyName: "videoPreviewErrorMessage", publicName: "videoPreviewErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, audioPreviewErrorMessage: { classPropertyName: "audioPreviewErrorMessage", publicName: "videoPreviewErrorMessage", isSignal: true, isRequired: false, transformFunction: null }, flipHorinzontalLabel: { classPropertyName: "flipHorinzontalLabel", publicName: "flipHorinzontalLabel", isSignal: true, isRequired: false, transformFunction: null }, flipVerticalLabel: { classPropertyName: "flipVerticalLabel", publicName: "flipVerticalLabel", isSignal: true, isRequired: false, transformFunction: null }, rotateRightLabel: { classPropertyName: "rotateRightLabel", publicName: "rotateRightLabel", isSignal: true, isRequired: false, transformFunction: null }, rotateLeftLabel: { classPropertyName: "rotateLeftLabel", publicName: "rotateLeftLabel", isSignal: true, isRequired: false, transformFunction: null }, base64LimitMB: { classPropertyName: "base64LimitMB", publicName: "base64LimitMB", isSignal: true, isRequired: false, transformFunction: null }, uploadTitle: { classPropertyName: "uploadTitle", publicName: "uploadTitle", isSignal: true, isRequired: false, transformFunction: null }, uploadSubtitle: { classPropertyName: "uploadSubtitle", publicName: "uploadSubtitle", isSignal: true, isRequired: false, transformFunction: null }, dropHereLabel: { classPropertyName: "dropHereLabel", publicName: "dropHereLabel", isSignal: true, isRequired: false, transformFunction: null }, supportedFormatsLabel: { classPropertyName: "supportedFormatsLabel", publicName: "supportedFormatsLabel", isSignal: true, isRequired: false, transformFunction: null }, browseFilesLabel: { classPropertyName: "browseFilesLabel", publicName: "browseFilesLabel", isSignal: true, isRequired: false, transformFunction: null }, uploadSummaryLabel: { classPropertyName: "uploadSummaryLabel", publicName: "uploadSummaryLabel", isSignal: true, isRequired: false, transformFunction: null }, filesLabel: { classPropertyName: "filesLabel", publicName: "filesLabel", isSignal: true, isRequired: false, transformFunction: null }, totalSizeLabel: { classPropertyName: "totalSizeLabel", publicName: "totalSizeLabel", isSignal: true, isRequired: false, transformFunction: null }, emptyStateLabel: { classPropertyName: "emptyStateLabel", publicName: "emptyStateLabel", isSignal: true, isRequired: false, transformFunction: null }, addedSuccessfullyLabel: { classPropertyName: "addedSuccessfullyLabel", publicName: "addedSuccessfullyLabel", isSignal: true, isRequired: false, transformFunction: null }, removedLabel: { classPropertyName: "removedLabel", publicName: "removedLabel", isSignal: true, isRequired: false, transformFunction: null }, chooseView: { classPropertyName: "chooseView", publicName: "chooseView", isSignal: true, isRequired: false, transformFunction: null }, showSummary: { classPropertyName: "showSummary", publicName: "showSummary", isSignal: true, isRequired: false, transformFunction: null }, viewMode: { classPropertyName: "viewMode", publicName: "viewMode", isSignal: false, isRequired: false, transformFunction: null }, showUploadTitle: { classPropertyName: "showUploadTitle", publicName: "showUploadTitle", isSignal: true, isRequired: false, transformFunction: null }, showDropArea: { classPropertyName: "showDropArea", publicName: "showDropArea", isSignal: true, isRequired: false, transformFunction: null }, hiddenColumns: { classPropertyName: "hiddenColumns", publicName: "hiddenColumns", isSignal: true, isRequired: false, transformFunction: null }, hiddenActions: { classPropertyName: "hiddenActions", publicName: "hiddenActions", isSignal: true, isRequired: false, transformFunction: null }, showActionButtons: { classPropertyName: "showActionButtons", publicName: "showActionButtons", isSignal: true, isRequired: false, transformFunction: null }, enableImageCrop: { classPropertyName: "enableImageCrop", publicName: "enableImageCrop", isSignal: true, isRequired: false, transformFunction: null }, actionHiddenFn: { classPropertyName: "actionHiddenFn", publicName: "actionHiddenFn", isSignal: true, isRequired: false, transformFunction: null }, actionDisabledFn: { classPropertyName: "actionDisabledFn", publicName: "actionDisabledFn", isSignal: true, isRequired: false, transformFunction: null }, videoCompression: { classPropertyName: "videoCompression", publicName: "videoCompression", isSignal: true, isRequired: false, transformFunction: null }, customMenuActions: { classPropertyName: "customMenuActions", publicName: "customMenuActions", isSignal: true, isRequired: false, transformFunction: null }, customColumns: { classPropertyName: "customColumns", publicName: "customColumns", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { localEditedAttachments: "localEditedAttachments", abortAddAttachment: "abortAddAttachment", downloadAttachment: "downloadAttachment", onDeleteAttachment: "onDeleteAttachment" }, viewQueries: [{ propertyName: "dialogAddAttachment", first: true, predicate: ["dialogAddAttachment"], descendants: true, isSignal: true }, { propertyName: "dialogAddMultipleAttachment", first: true, predicate: ["dialogAddMultipleAttachment"], descendants: true, isSignal: true }, { propertyName: "dialogCropImage", first: true, predicate: ["dialogCropImage"], descendants: true, isSignal: true }, { propertyName: "addingLinkTemplate", first: true, predicate: ["addingLinkTemplate"], descendants: true, isSignal: true }, { propertyName: "imageCropper", first: true, predicate: ImageCropperComponent, descendants: true, isSignal: true }, { propertyName: "imageInput", first: true, predicate: ["imageInput"], descendants: true, isSignal: true }, { propertyName: "inlinePreviewTemplate", first: true, predicate: ["inlinePreviewTemplate"], descendants: true, isSignal: true }, { propertyName: "dialogPreview", first: true, predicate: ["dialogPreview"], descendants: true, isSignal: true }, { propertyName: "defaultFileTemplate", first: true, predicate: ["defaultFileTemplate"], descendants: true, isSignal: true }, { propertyName: "defaultActionsTemplate", first: true, predicate: ["defaultActionsTemplate"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n@if(showUploadTitle() == true || chooseView() == true){\r\n<div class=\"header\">\r\n @if(showUploadTitle() == true){\r\n <h4>{{ uploadTitle() }}</h4>\r\n } @if(chooseView() == true){\r\n <mat-button-toggle-group\r\n [value]=\"viewMode\"\r\n (change)=\"setViewMode($event.value)\"\r\n aria-label=\"Modalit\u00E0 di visualizzazione\"\r\n >\r\n <mat-button-toggle value=\"card\"\r\n ><mat-icon>grid_view</mat-icon></mat-button-toggle\r\n >\r\n <mat-button-toggle value=\"table\"\r\n ><mat-icon>view_list</mat-icon></mat-button-toggle\r\n >\r\n </mat-button-toggle-group>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione singolo -->\r\n@if (multipleAttachment() != true) { @if (!singleAttachmentDragAndDrop()) { @if\r\n(!addingLinkMode()) {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addAttachmentButton\"></ng-container>\r\n</div>\r\n} @else {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addingLinkTemplate\"></ng-container>\r\n</div>\r\n} } @else {\r\n<input\r\n #fileInput\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n hidden\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles()\"\r\n/>\r\n\r\n@if (allowedTypes && allowedTypes.includes(1) && (!attachmentsList ||\r\nattachmentsList.length == 0 || (attachmentsList.length > 0 &&\r\n!attachmentsList[0]))) { @if (showDropArea() == true) {\r\n<!-- FULL -->\r\n@if (layout() === 'full') {\r\n\r\n<div\r\n class=\"dropbox\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n (keydown.enter)=\"fileInput.click()\"\r\n (keydown.space)=\"fileInput.click()\"\r\n>\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel() }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel() }}\r\n </div>\r\n <button\r\n class=\"browse-btn\"\r\n type=\"button\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n {{ browseFilesLabel() }}\r\n </button>\r\n <div class=\"secondary-action\">\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) { @if\r\n (allowedTypes.includes(2) && allowedTypes.includes(3)) {\r\n <a\r\n class=\"secondary-action-link\"\r\n [matMenuTriggerFor]=\"isDisabled() ? null : linkMenu\"\r\n [class.disabled-link]=\"isDisabled()\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n o aggiungi da web\r\n </a>\r\n <mat-menu #linkMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"switchToAddingLinkMode()\">\r\n <mat-icon>link</mat-icon>\r\n <span>Aggiungi da link</span>\r\n </button>\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\">\r\n <mat-icon>cloud_queue</mat-icon>\r\n <span>Carica da Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n } @else if (allowedTypes.includes(2)) {\r\n <a\r\n [class.disabled-link]=\"isDisabled()\"\r\n class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\"\r\n >\r\n aggiungi un link\r\n </a>\r\n } @else if (allowedTypes.includes(3)) {\r\n <a\r\n [class.disabled-link]=\"isDisabled()\"\r\n class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); chooseDropboxFile()\"\r\n >\r\n carica da Dropbox\r\n </a>\r\n } }\r\n </div>\r\n</div>\r\n}@else {\r\n<div\r\n class=\"compact-uploader\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n>\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel() }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button\r\n mat-stroked-button\r\n color=\"primary\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n Sfoglia\r\n </button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button\r\n mat-stroked-button\r\n [disabled]=\"isDisabled()\"\r\n [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n Link\r\n </button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n >\r\n {{ openLinkLabel() }}\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"chooseDropboxFile()\"\r\n >\r\n {{ uploadWithDropboxLabel() }}\r\n </button>\r\n }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n} } } }\r\n\r\n<!-- Azioni singolo elemento (come prima) -->\r\n<div class=\"text-center\">\r\n @if (attachmentsList && attachmentsList.length > 0 && attachmentsList[0] &&\r\n showActionButtons() == true) {\r\n @if (!isPrimaryActionHidden(attachmentsList[0])) {\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 [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button\r\n color=\"primary\"\r\n >\r\n @if (attachmentsList[0].AttachmentType == AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n {{\r\n attachmentsList[0].AttachmentType == AttachmentType.FILE\r\n ? downloadLabel()\r\n : openLinkLabel()\r\n }}\r\n </button>\r\n }\r\n\r\n @if (!isPrimaryActionHidden(attachmentsList[0]) && showPreview() && (!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 <button\r\n class=\"mb-2 me-2 eqp-attachments-preview-btn\"\r\n (click)=\"openPreviewDialog(attachmentsList[0])\"\r\n type=\"button\"\r\n [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button\r\n color=\"primary\"\r\n >\r\n <mat-icon>visibility</mat-icon> {{ previewLabel() }}\r\n </button>\r\n }\r\n\r\n <button\r\n [disabled]=\"disableAction()\"\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 [disabled]=\"isDisabled()\"\r\n >\r\n <mat-icon>delete</mat-icon> {{ deleteLabel() }}\r\n </button>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione multipla -->\r\n@if (multipleAttachment() == true && showDropArea() == true) {\r\n<input\r\n #fileInput\r\n id=\"file_attachment_multi\"\r\n name=\"file_attachment_multi\"\r\n type=\"file\"\r\n hidden\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles()\"\r\n/>\r\n\r\n@if (layout() === 'full') {\r\n<div\r\n class=\"dropbox\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n (keydown.enter)=\"fileInput.click()\"\r\n (keydown.space)=\"fileInput.click()\"\r\n>\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel() }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel() }}\r\n </div>\r\n <button\r\n class=\"browse-btn\"\r\n type=\"button\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n {{ browseFilesLabel() }}\r\n </button>\r\n @if (allowedTypes.includes(2)) {\r\n <div class=\"secondary-action-link\">\r\n o\r\n <a (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\"\r\n >aggiungi un link</a\r\n >\r\n </div>\r\n }\r\n</div>\r\n}@else{\r\n<div\r\n class=\"compact-uploader\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n>\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel() }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button\r\n mat-stroked-button\r\n [disabled]=\"isDisabled()\"\r\n color=\"primary\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n Sfoglia\r\n </button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button\r\n mat-stroked-button\r\n [disabled]=\"isDisabled()\"\r\n [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n Link\r\n </button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n >\r\n {{ openLinkLabel() }}\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"chooseDropboxFile()\"\r\n >\r\n {{ uploadWithDropboxLabel() }}\r\n </button>\r\n }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n} } @if (attachmentsList?.length > 0 && showSummary()) {\r\n<div class=\"upload-stats\">\r\n <div class=\"stats-info\">\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ attachmentsList?.length }}</div>\r\n <div class=\"stat-label\">{{ filesLabel() }}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ totalSizeFormatted() }}</div>\r\n <div class=\"stat-label\">{{ totalSizeLabel() }}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"progressPercent()\"></div>\r\n </div>\r\n</div>\r\n} @else if(attachmentsList?.length == 0){\r\n<div class=\"empty-state\">{{ emptyStateLabel() }}</div>\r\n}\r\n\r\n<!-- Griglia anteprime card (vale per singolo e multiplo) -->\r\n@if (viewMode === 'card') {\r\n\r\n<div class=\"file-previews\" [ngStyle]=\"getPreviewsContainerStyle()\">\r\n @for (att of attachmentsList; track att.ID) {\r\n <div [ngClass]=\"getCardClass(att)\">\r\n <div\r\n class=\"preview-img-container\"\r\n (click)=\"!att.isUploading && handlePrimaryAction(att)\"\r\n >\r\n @if (att.IsImage || att.FileThumbnailBase64) {\r\n <img\r\n class=\"preview-img\"\r\n [src]=\"\r\n 'data:image/jpeg;base64,' +\r\n (att.FileThumbnailBase64 || att.FileDataBase64)\r\n \"\r\n [alt]=\"att.FileName\"\r\n />\r\n } @else {\r\n <div class=\"file-icon\"><i [ngClass]=\"getAttachmentIcon(att)\"></i></div>\r\n }\r\n\r\n <div class=\"preview-action-overlay\">\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n <mat-icon>play_arrow</mat-icon>\r\n } @else if (att.IsImage && canBePreviewed(att)) {\r\n <mat-icon>visibility</mat-icon>\r\n } @else if (att.FileContentType === 'application/pdf' &&\r\n canBePreviewed(att)) {\r\n <mat-icon>open_in_new</mat-icon>\r\n } @else if (att.AttachmentType === AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"att.FileName\">{{ att.FileName }}</div>\r\n </div>\r\n\r\n @if(!isDeleteHidden(att)){\r\n <button\r\n mat-icon-button\r\n class=\"remove-btn\"\r\n (click)=\"deleteAttachment(att)\"\r\n [disabled]=\"att.isUploading || isDeleteDisabled(att)\"\r\n >\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n } @if (att.isUploading) {\r\n <div class=\"upload-spinner\"></div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n} @else if(viewMode === 'table' && attachmentsList?.length > 0) {\r\n\r\n<div class=\"table-view-container\">\r\n <div class=\"table-header\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div\r\n class=\"table-cell\"\r\n [style.flex]=\"col.styles?.flex\"\r\n [ngClass]=\"col.class\"\r\n >\r\n {{ col.display }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @for (att of attachmentsList; track att.ID) {\r\n <div class=\"table-row\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div\r\n class=\"table-cell\"\r\n [style.flex]=\"col.styles?.flex\"\r\n [ngClass]=\"col.class\"\r\n >\r\n @switch (col.type) { @case ('template') {\r\n <div class=\"template-wrapper\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"col.externalTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: att }\"\r\n ></ng-container>\r\n </div>\r\n } @case ('date') {\r\n <span class=\"metadata-value\">{{\r\n att[col.key] | date : \"dd/MM/yyyy\"\r\n }}</span>\r\n } @default {\r\n <span class=\"metadata-value\">{{ att[col.key] }}</span>\r\n } }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Notifica toast -->\r\n<div\r\n class=\"upload-notification\"\r\n [class.show]=\"toast?.visible\"\r\n [class.success]=\"toast?.type === 'success'\"\r\n [class.error]=\"toast?.type === 'error'\"\r\n>\r\n <span>{{ toast?.text }}</span>\r\n <div class=\"notification-progress\"></div>\r\n</div>\r\n\r\n<ng-template #defaultFileTemplate let-att>\r\n <i class=\"file-icon-small\" [ngClass]=\"getAttachmentIcon(att)\"></i>\r\n <div class=\"file-info-text\">\r\n <span class=\"file-name-table\">{{ att.FileName }}</span>\r\n <span class=\"file-type-table\">{{ att.FileExtension || \"Link\" }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultActionsTemplate let-att>\r\n <button\r\n mat-icon-button\r\n (click)=\"handlePrimaryAction(att)\"\r\n [matTooltip]=\"\r\n att.FileContentType?.startsWith('video/')\r\n ? 'Riproduci video'\r\n : 'Visualizza/Scarica'\r\n \"\r\n >\r\n <mat-icon>\r\n @if (att.FileContentType?.startsWith('video/')) { play_arrow } @else {\r\n {{\r\n att.AttachmentType === AttachmentType.FILE ? \"download\" : \"open_in_new\"\r\n }}\r\n }\r\n </mat-icon>\r\n </button>\r\n\r\n @if (!hiddenActions().includes('actionsMenu')) {\r\n <button\r\n mat-icon-button\r\n [matMenuTriggerFor]=\"actionsMenu\"\r\n matTooltip=\"Altre opzioni\"\r\n >\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n }\r\n\r\n <mat-menu #actionsMenu=\"matMenu\">\r\n @for (action of _sortedMenuActions; track action.name) { @if\r\n (!isActionHidden(action, att)) {\r\n <button\r\n mat-menu-item\r\n (click)=\"action.fn(att)\"\r\n [disabled]=\"isActionDisabled(action, att)\"\r\n >\r\n <mat-icon [color]=\"action.icon === 'delete' ? 'warn' : undefined\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n <span>{{ action.name }}</span>\r\n </button>\r\n } }\r\n </mat-menu>\r\n</ng-template>\r\n\r\n<ng-template #dialogCropImage>\r\n <div style=\"overflow-x: hidden\" [ngClass]=\"cropDialogClass()\">\r\n <!-- @if (showCropImage == true) { -->\r\n <ng-container\r\n [ngTemplateOutlet]=\"croppieTemplate\"\r\n [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\"\r\n >\r\n </ng-container>\r\n <!-- } -->\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n @if (row.AttachmentType != AttachmentType.LINK && row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <img\r\n [src]=\"\r\n 'data:image/png;base64,' +\r\n (row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64)\r\n \"\r\n />\r\n </div>\r\n } @else if (row.AttachmentType != AttachmentType.LINK && !row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"modern-dialog-container\">\r\n @if (selectedAttachment) {\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ previewLabel() }}</span>\r\n <span class=\"file-t\">{{ selectedAttachment.FileName }}</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"media-viewer-wrapper\">\r\n @if (selectedAttachment.IsImage) {\r\n <img\r\n class=\"main-preview-media\"\r\n [src]=\"\r\n 'data:image/png;base64,' +\r\n (selectedAttachment.FileDataBase64 ||\r\n selectedAttachment.FileThumbnailBase64)\r\n \"\r\n [alt]=\"selectedAttachment.FileName\"\r\n />\r\n } @else if (selectedAttachment.FileContentType?.startsWith('video/')) {\r\n <video\r\n controls\r\n autoplay\r\n playsinline\r\n class=\"main-preview-media video-player\"\r\n >\r\n <source\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [type]=\"selectedAttachment.FileContentType\"\r\n />\r\n Il tuo browser non supporta il video.\r\n </video>\r\n } @else {\r\n <div class=\"iframe-container\">\r\n <iframe\r\n class=\"preview-iframe-modern\"\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"\r\n ></iframe>\r\n </div>\r\n }\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Chiudi</button>\r\n @if (selectedAttachment.AttachmentType !== AttachmentType.LINK) {\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n class=\"btn-download\"\r\n >\r\n <mat-icon>download</mat-icon> <span>{{ downloadLabel() }}</span>\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\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 />\r\n\r\n @if (allowedTypes && allowedTypes.length == 1 && (multipleAttachment() == true\r\n || !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length\r\n > 0 && !attachmentsList[0]))) {\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 (click)=\"addFile(allowedTypes[0], fileInput)\"\r\n [disabled]=\"isDisabled()\"\r\n >\r\n @if (allowedTypes[0] == 1) { <mat-icon>cloud_upload</mat-icon> } @if\r\n (allowedTypes[0] == 2) { <i class=\"fas fa-link\"></i> } @if (allowedTypes[0]\r\n == 3) { <i class=\"fa-brands fa-dropbox\"></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 }}\r\n </span>\r\n </button>\r\n } @if (!separatedUploadButtons() && allowedTypes && allowedTypes.length > 1 &&\r\n (multipleAttachment() == true || !attachmentsList || attachmentsList.length == 0\r\n || (attachmentsList.length > 0 && !attachmentsList[0]))) {\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 >\r\n @if (multipleAttachment() != true) { <mat-icon>cloud_upload</mat-icon> } @else\r\n { <mat-icon>add</mat-icon> }\r\n <span style=\"margin-left: 0px\">{{ addButtonLabel() }}</span>\r\n </button>\r\n\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input\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 />\r\n @if (allowedTypes.includes(1)) {\r\n <button\r\n mat-menu-item\r\n (click)=\"imageInput.click()\"\r\n class=\"eqp-attachments-file-btn\"\r\n >\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n } @if (allowedTypes.includes(2)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\"\r\n >\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\"\r\n >\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @if (separatedUploadButtons() && allowedTypes && allowedTypes.length > 1 &&\r\n (multipleAttachment() == true || !attachmentsList || attachmentsList.length == 0\r\n || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <div class=\"btn-group\">\r\n @if (allowedTypes.includes(1)) {\r\n <button\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 >\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n <input\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 />\r\n @if (allowedTypes.includes(2)) {\r\n <button\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 >\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\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 >\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ cropLabel() }}</span>\r\n <span class=\"file-t\">Regola le dimensioni e l'orientamento</span>\r\n </div>\r\n </div>\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"abortFile()\"\r\n class=\"close-btn\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"crop-toolbar\">\r\n @if (cropOptions().includes(1)) {\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"rotateLeftLabel()\"\r\n (click)=\"rotateLeft()\"\r\n >\r\n <mat-icon>rotate_left</mat-icon>\r\n </button>\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"rotateRightLabel()\"\r\n (click)=\"rotateRight()\"\r\n >\r\n <mat-icon>rotate_right</mat-icon>\r\n </button>\r\n } @if (cropOptions().includes(2)) {\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"flipHorinzontalLabel()\"\r\n (click)=\"flipHorizontal()\"\r\n >\r\n <mat-icon>flip_horizontal</mat-icon>\r\n </button>\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"flipVerticalLabel()\"\r\n (click)=\"flipVertical()\"\r\n >\r\n <mat-icon>flip_vertical</mat-icon>\r\n </button>\r\n }\r\n <button\r\n mat-icon-button\r\n matTooltip=\"Reset\"\r\n (click)=\"restoreOriginalDimensions()\"\r\n >\r\n <mat-icon>replay</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"media-viewer-wrapper\">\r\n <div class=\"crop-container-modern\">\r\n <image-cropper\r\n [imageFile]=\"selectedFile\"\r\n [maintainAspectRatio]=\"false\"\r\n [canvasRotation]=\"canvasRotation\"\r\n [transform]=\"transform\"\r\n format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\"\r\n [output]=\"'base64'\"\r\n [containWithinAspectRatio]=\"true\"\r\n [onlyScaleDown]=\"true\"\r\n [alignImage]=\"'center'\"\r\n >\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button (click)=\"abortFile()\" class=\"btn-close\">\r\n {{ abortLabel() }}\r\n </button>\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"confirmAddAttachment()\"\r\n class=\"btn-download\"\r\n >\r\n <mat-icon>check</mat-icon> {{ confirmLabel() }}\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"type-icon-wrapper\">\r\n <mat-icon>link</mat-icon>\r\n </div>\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">Aggiungi un link</span>\r\n <span class=\"file-t\">Inserisci l'URL della risorsa web</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"add-link-modern-content\">\r\n <form [formGroup]=\"newAttachmentForm\" class=\"add-link-form\">\r\n <mat-form-field appearance=\"outline\" class=\"w-100 mt-3\">\r\n <mat-label>URL del collegamento</mat-label>\r\n <input\r\n matInput\r\n formControlName=\"filePath\"\r\n placeholder=\"https://...\"\r\n required\r\n />\r\n <mat-icon matSuffix>language</mat-icon>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>Titolo (opzionale)</mat-label>\r\n <input\r\n matInput\r\n formControlName=\"fileName\"\r\n placeholder=\"Es. Documento Progetto\"\r\n />\r\n <mat-icon matSuffix>title</mat-icon>\r\n </mat-form-field>\r\n </form>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Annulla</button>\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n [mat-dialog-close]=\"newAttachmentForm.value\"\r\n [disabled]=\"newAttachmentForm.invalid\"\r\n class=\"btn-download\"\r\n >\r\n <mat-icon>add</mat-icon> Aggiungi\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{--primary-color: #6a5af9;--primary-color-dark: rgb(83.7807017544, 65.3947368421, 248.1052631579);--success-color: #1ce593;--error-color: #ff5b5b;--background-light: #f7f9fc;--background-card: rgba(255, 255, 255, .7);--text-color: #1e293b;--text-color-light: #64748b;--border-color: rgba(203, 213, 225, .5);--shadow-color: rgba(99, 102, 241, .2);--border-radius: 16px;--transition-speed: .3s}@keyframes fadeIn{0%{opacity:0;transform:translateY(15px)}to{opacity:1;transform:translateY(0)}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--primary-color)}70%{box-shadow:0 0 0 10px #6a5af900}to{box-shadow:0 0 #6a5af900}}.container{width:100%;max-width:700px;margin:2rem auto;font-family:Inter,sans-serif}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border-color)}.header h1{color:var(--text-color);font-size:1.8rem;font-weight:700;margin:0}.dropbox{width:100%;border:2px dashed var(--border-color);border-radius:var(--border-radius);padding:2.5rem;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;background-color:var(--background-card);backdrop-filter:blur(10px);transition:all var(--transition-speed) ease}.dropbox:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color);border-color:var(--primary-color)}.dropbox.dragover{border-style:solid;border-color:var(--primary-color);transform:scale(1.02);box-shadow:0 0 25px var(--shadow-color);animation:pulse 1.5s infinite}.dropbox .dropbox-icon{font-size:3.5rem;color:var(--primary-color)}.dropbox .dropbox-text{font-size:1.1rem;font-weight:600;color:var(--text-color);margin-top:1rem}.dropbox .dropbox-subtext{color:var(--text-color-light);margin-top:.5rem}.dropbox .browse-btn{margin-top:1.5rem;padding:.75rem 1.5rem;background-color:var(--primary-color);color:#fff;border:none;border-radius:10px;font-weight:600;transition:all var(--transition-speed) ease}.dropbox .browse-btn:hover{background-color:var(--primary-color-dark);transform:translateY(-2px)}.file-previews{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1.5rem;margin-top:2rem}.file-previews{display:grid;gap:16px;padding:16px;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width, 200px),1fr))}.file-preview{background-color:var(--background-card);border-radius:var(--border-radius);box-shadow:0 4px 15px #0000000d;border:1px solid var(--border-color);overflow:hidden;display:flex;flex-direction:column;position:relative;opacity:0;animation:fadeIn .5s ease-out forwards;transition:transform var(--transition-speed) ease,box-shadow var(--transition-speed) ease}.file-preview.uploading{cursor:wait}.file-preview.uploading .preview-img-container:after{content:\"\";position:absolute;inset:0;background:#ffffffb3;backdrop-filter:blur(5px);pointer-events:none}.file-preview .preview-action-overlay{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;background-color:#0006;color:#fff;opacity:1;transition:opacity .3s ease}.file-preview .preview-action-overlay .mat-icon{font-size:36px;width:36px;height:36px}.file-preview .remove-btn{position:absolute;top:8px;right:8px;z-index:2;background-color:#0000004d;color:#fff;width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;transition:all var(--transition-speed) ease}.file-preview .remove-btn:hover{background-color:#ff5b5b}.file-preview .remove-btn .mat-icon{font-size:18px}@media(hover:hover){.file-preview .remove-btn .file-preview .preview-action-overlay{opacity:0}.file-preview .remove-btn .file-preview:hover .preview-action-overlay,.file-preview .remove-btn .file-preview:hover .remove-btn{opacity:1}.file-preview .remove-btn .file-preview .remove-btn{opacity:0}}@media(hover:hover)and (min-width:769px){.file-preview .remove-btn{opacity:0;transform:scale(.8)}.file-preview:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color)}.file-preview:hover .remove-btn{opacity:1;transform:scale(1)}}.file-preview .preview-img-container{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;cursor:pointer;background-color:#f0f2f5}.file-preview .preview-img{width:100%;height:100%;object-fit:cover}.file-preview .file-icon{font-size:4rem;color:var(--primary-color)}.file-preview .file-info{padding:12px;border-top:1px solid var(--border-color);flex-grow:1;display:flex;align-items:center}.file-preview .file-name{font-weight:600;font-size:.9rem;color:var(--text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-preview .upload-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border:4px solid rgba(0,0,0,.1);border-left-color:var(--primary-color);border-radius:50%;animation:spin 1s linear infinite;pointer-events:none}.file-preview.card-small{width:140px}.file-preview.card-small .preview-img-container{height:80px}.file-preview.card-small .file-info{padding:8px}.file-preview.card-small .file-name{font-size:.8rem}.file-preview.card-small .file-icon{font-size:3rem}.file-preview.card-small .remove-btn{width:28px;height:28px}.file-preview.card-small .remove-btn .mat-icon{font-size:16px}.file-preview.card-large{width:280px}.file-preview.card-large .preview-img-container{height:180px}.file-preview.card-large .file-info{padding:16px}.file-preview.card-large .file-name{font-size:1rem}.file-preview.card-large .file-icon{font-size:5rem}.file-preview.card-large .remove-btn{width:36px;height:36px}.file-preview.card-large .remove-btn .mat-icon{font-size:20px}.file-preview[style*=--eqp-card-width]{width:var(--eqp-card-width)}.file-preview[style*=--eqp-card-width] .preview-img-container{height:calc(var(--eqp-card-width) * .65)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}.upload-stats{background-color:var(--background-card);backdrop-filter:blur(10px);border:1px solid var(--border-color);border-radius:var(--border-radius);padding:1.5rem;margin-top:2rem;animation:fadeIn .5s ease-out}.upload-stats .stats-info{display:flex;justify-content:space-around}.upload-stats .progress-bar{height:10px;background-color:var(--border-color);border-radius:5px;overflow:hidden;margin-top:1rem}.upload-stats .progress-fill{height:100%;background:linear-gradient(90deg,var(--primary-color),var(--success-color));transition:width var(--transition-speed) ease-out;border-radius:5px}.upload-notification{position:fixed;bottom:20px;left:50%;transform:translate(-50%,100px);padding:1rem 1.5rem;border-radius:var(--border-radius);color:#fff;font-weight:600;box-shadow:0 10px 30px #0003;transition:transform var(--transition-speed) cubic-bezier(.175,.885,.32,1.275)}.upload-notification.show{transform:translate(-50%)}.upload-notification.success{background-color:var(--success-color)}.upload-notification.error{background-color:var(--error-color)}::ng-deep .cdk-overlay-pane.eqp-crop-dialog{transform:translateY(-4vh)}@media(max-width:600px){::ng-deep .cdk-overlay-pane.crop-dialog{width:auto!important}}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__surface{border-radius:20px!important;padding:0!important;overflow:hidden!important;width:fit-content!important;min-width:350px!important;max-width:95vw!important;margin:0 auto;background-color:#fff!important}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;display:flex;flex-direction:column}.modern-dialog-container{display:flex;flex-direction:column;width:100%;max-width:100%;height:100%;max-height:90vh;background:#fff;--preview-header-h: 66px;--preview-footer-h: 66px;--preview-padding-y: 30px}.modern-dialog-container .main-preview-media{display:block;max-width:100%;max-height:var(--media-max-h);width:auto;height:auto;object-fit:contain;border-radius:12px;background:#fff;padding:4px;box-shadow:0 10px 30px #00000014}.modern-dialog-container video.main-preview-media{width:min(100%,1100px);background:#000}.modern-dialog-container .iframe-container{width:min(100%,1100px);height:var(--media-max-h);display:flex;width:100%;max-width:1100px}.modern-dialog-container .preview-iframe-modern{width:100%;height:100%;border:0;border-radius:12px;background:#f8fafc}.modern-dialog-container .preview-header{flex:0 0 auto;flex-shrink:0;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;border-bottom:1px solid var(--border-color);background:#f8fafc;z-index:10;width:100%}.modern-dialog-container .preview-header .header-info{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex:1 1 auto;min-width:0;text-align:left}.modern-dialog-container .preview-header .header-info .type-icon-wrapper{background:var(--primary-color);color:#fff;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px var(--shadow-color)}.modern-dialog-container .preview-header .header-info .title-group{display:flex;flex-direction:column;align-items:flex-start;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .main-t{font-weight:800;color:var(--text-color);font-size:.95rem;line-height:1.2;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .file-t{font-size:.75rem;color:var(--text-color-light);max-width:250px;overflow:hidden;text-overflow:ellipsis;text-align:left}.modern-dialog-container .preview-content-area{flex:1;background:#fff!important;display:flex;flex-direction:column;padding:15px 15px 22px!important;overflow:hidden!important;min-height:0;width:auto;--media-max-h: calc(90vh - var(--preview-header-h) - var(--preview-footer-h) - var(--preview-padding-y));width:100%}.modern-dialog-container .preview-content-area .crop-toolbar{flex-shrink:0;z-index:20;background:#0f172a14;backdrop-filter:blur(10px);padding:6px 16px;border-radius:30px;margin:0 auto 15px;display:flex;gap:8px;box-shadow:0 4px 12px #0000000d}.modern-dialog-container .preview-content-area .crop-toolbar button{color:var(--text-color)!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper{flex:1;width:100%;display:flex;justify-content:center;align-items:center;min-height:0;overflow:visible}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern{width:100%;height:100%;display:flex;justify-content:center;align-items:center;background:transparent;border-radius:12px;padding:0}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern image-cropper{max-width:100%;max-height:100%;display:block}.modern-dialog-container .add-link-modern-content{flex:1;background:#fff;padding:24px!important}.modern-dialog-container .add-link-modern-content .add-link-form{display:flex;flex-direction:column;gap:10px}.modern-dialog-container .preview-actions{flex-shrink:0;padding:12px 24px;background:#f8fafc;border-top:1px solid #e2e8f0;margin:0}.modern-dialog-container .preview-actions .btn-download{border-radius:12px;font-weight:600;box-shadow:0 4px 12px var(--shadow-color)}@media(max-width:600px){.modern-dialog-container{max-height:95vh}.modern-dialog-container .preview-content-area{padding:10px!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper video.main-preview-media{width:100%!important;max-height:55vh!important;border-radius:4px;box-shadow:none}.modern-dialog-container .preview-content-area .media-viewer-wrapper .iframe-container{height:50vh}.modern-dialog-container .preview-content-area .crop-toolbar{width:calc(100% - 20px);max-width:400px;margin-bottom:10px;padding:4px 8px;gap:4px;overflow-x:auto;justify-content:center;-webkit-overflow-scrolling:touch}.modern-dialog-container .preview-content-area .crop-toolbar::-webkit-scrollbar{display:none}.modern-dialog-container .preview-content-area .crop-toolbar{scrollbar-width:none}.modern-dialog-container .preview-content-area .crop-toolbar button{flex-shrink:0;transform:scale(.85);width:40px;height:40px}.modern-dialog-container .preview-actions{padding:10px 15px;flex-direction:column-reverse;gap:8px}.modern-dialog-container .preview-actions button{width:100%;margin:0!important}}@media(max-width:360px){.modern-dialog-container .preview-content-area .crop-toolbar{gap:2px}.modern-dialog-container .preview-content-area .crop-toolbar button{transform:scale(.75)}}.control-icon{font-size:28px;cursor:pointer}image-cropper,image-cropper canvas,image-cropper img{max-width:100%!important;max-height:100%!important}.crop-large{display:flex}.crop-small{display:none}@media(max-width:600px){.dialog-content{max-height:55vh}.crop-container{max-width:100%;aspect-ratio:auto}.crop-large{display:none}.crop-small{display:flex;justify-content:center;gap:14px}.control-icon{font-size:24px}}.stats-header{display:flex;justify-content:space-between;align-items:center;width:100%}.table-view-container{margin-top:1.5rem;background-color:var(--background-card);border-radius:var(--border-radius);border:1px solid var(--border-color);overflow:hidden;animation:fadeIn .5s ease-out}.table-header,.table-row{display:flex;align-items:center;padding:0 1rem;transition:background-color var(--transition-speed) ease}.table-header{background-color:#f8f9fa;font-weight:600;color:var(--text-color-light);font-size:.8rem;text-transform:uppercase;border-bottom:2px solid var(--border-color)}.table-row{border-bottom:1px solid var(--border-color)}.table-row:last-child{border-bottom:none}.table-row:hover{background-color:#00000005}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem}.name-col{flex:4}.size-col,.date-col{flex:2}.actions-col{flex:1;justify-content:flex-end;min-width:150px}.file-icon-small{font-size:1.5rem;color:var(--primary-color)}.file-info-text{display:flex;flex-direction:column}.file-name-table{font-weight:600;color:var(--text-color)}.file-type-table{font-size:.8rem;color:var(--text-color-light)}@media(max-width:768px){.date-col{display:none}.name-col{flex:3}.size-col{flex:2}.actions-col{flex:2;min-width:120px}}.secondary-action-link{color:var(--primary-color);text-decoration:none;border-bottom:1px solid var(--primary-color);cursor:pointer;font-weight:500}.secondary-action-link:hover{color:var(--primary-color-dark);border-bottom-color:var(--primary-color-dark)}h2[mat-dialog-title]+mat-dialog-content.add-link-dialog-content{padding-top:20px}mat-dialog-content.add-link-dialog-content{padding-left:24px;padding-right:24px;padding-bottom:20px}.add-link-form{display:flex;flex-direction:column;gap:16px}::ng-deep .eqp-attachments-preview-dialog{--mat-dialog-subhead-line-height: normal}::ng-deep .eqp-attachments-preview-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;background:#fff!important}:host ::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{--mat-dialog-subhead-size: 1.25rem;--mat-dialog-subhead-line-height: 1.5;--mat-dialog-subhead-weight: 600;--mat-dialog-supporting-text-size: 1rem}.empty-state{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:1.5rem 1rem;margin-top:1.5rem;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#f8f9fa;text-align:center;color:var(--text-color-light);animation:fadeIn .5s ease-out}.empty-state:before{content:\"\\1f4ed\";font-size:2.5rem;margin-bottom:1rem;opacity:.7}.secondary-action-link.disabled-link{color:#adb5bd;cursor:not-allowed;border-bottom-color:transparent}.secondary-action-link.disabled-link:hover{color:#adb5bd;border-bottom-color:transparent}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem;min-width:0;overflow:hidden}.table-cell.col-actions{flex:0 0 150px;justify-content:flex-end;overflow:visible}.compact-uploader{display:flex;align-items:center;gap:16px;padding:16px;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#fcfdff;transition:all .3s ease}.compact-uploader .compact-text{flex:1 1 auto;min-width:0;cursor:pointer}.compact-uploader .compact-text:hover .compact-title{color:var(--primary-color)}.compact-uploader .compact-title{font-weight:600;color:var(--text-color);transition:color .3s ease}.compact-uploader .compact-subtitle{font-size:.8rem;color:var(--text-color-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-uploader .compact-icon mat-icon{font-size:36px;width:36px;height:36px;color:var(--primary-color)}.compact-uploader .compact-actions{display:flex;gap:8px;flex-shrink:0}.compact-uploader.dragover{background-color:#f4f8ff;border-color:var(--primary-color);box-shadow:0 0 10px var(--shadow-color)}\n"], dependencies: [{ kind: "component", type: i6.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i6.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { 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", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "component", type: i7.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i7.MatLabel, selector: "mat-label" }, { kind: "directive", type: i7.MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "component", type: i8.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: i8.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i8.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "directive", type: i9.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i9.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "component", type: i10.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i1.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "directive", type: i1.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "directive", type: i1.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i11.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],[formArray],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: i12.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i12.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i12.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i13.ImageCropperComponent, selector: "image-cropper", inputs: ["imageChangedEvent", "imageURL", "imageBase64", "imageFile", "imageAltText", "options", "cropperFrameAriaLabel", "output", "format", "autoCrop", "cropper", "transform", "maintainAspectRatio", "aspectRatio", "resetCropOnAspectRatioChange", "resizeToWidth", "resizeToHeight", "cropperMinWidth", "cropperMinHeight", "cropperMaxHeight", "cropperMaxWidth", "cropperStaticWidth", "cropperStaticHeight", "canvasRotation", "initialStepSize", "roundCropper", "onlyScaleDown", "imageQuality", "backgroundColor", "containWithinAspectRatio", "hideResizeSquares", "allowMoveImage", "checkImageType", "alignImage", "disabled", "hidden"], outputs: ["imageCropped", "startCropImage", "imageLoaded", "cropperReady", "loadImageFailed", "transformChange", "cropperChange"] }, { kind: "pipe", type: i12.DatePipe, name: "date" }] });
|
|
1564
1626
|
}
|
|
1565
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1627
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentsComponent, decorators: [{
|
|
1566
1628
|
type: Component,
|
|
1567
|
-
args: [{ selector: "eqp-attachments", template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n@if(showUploadTitle == true || chooseView == true){\r\n<div class=\"header\">\r\n @if(showUploadTitle == true){\r\n <h4>{{ uploadTitle }}</h4>\r\n }\r\n @if(chooseView == true){\r\n <mat-button-toggle-group [value]=\"viewMode\" (change)=\"setViewMode($event.value)\"\r\n aria-label=\"Modalit\u00E0 di visualizzazione\">\r\n <mat-button-toggle value=\"card\"><mat-icon>grid_view</mat-icon></mat-button-toggle>\r\n <mat-button-toggle value=\"table\"><mat-icon>view_list</mat-icon></mat-button-toggle>\r\n </mat-button-toggle-group>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione singolo -->\r\n@if (multipleAttachment != true) {\r\n@if (!singleAttachmentDragAndDrop) {\r\n@if (!addingLinkMode) {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addAttachmentButton\"></ng-container>\r\n</div>\r\n} @else {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addingLinkTemplate\"></ng-container>\r\n</div>\r\n}\r\n} @else {\r\n<input #fileInput id=\"file_attachment\" name=\"file_attachment\" type=\"file\" hidden (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (allowedTypes && allowedTypes.includes(1) && (!attachmentsList || attachmentsList.length == 0 ||\r\n(attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n\r\n@if (showDropArea == true) {\r\n<!-- FULL -->\r\n@if (layout === 'full') {\r\n\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n <div class=\"secondary-action\">\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n @if (allowedTypes.includes(2) && allowedTypes.includes(3)) {\r\n <a class=\"secondary-action-link\" [matMenuTriggerFor]=\"isDisabled ? null : linkMenu\"\r\n [class.disabled-link]=\"isDisabled\" (click)=\"$event.stopPropagation()\">\r\n o aggiungi da web\r\n </a>\r\n <mat-menu #linkMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"switchToAddingLinkMode()\">\r\n <mat-icon>link</mat-icon>\r\n <span>Aggiungi da link</span>\r\n </button>\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\">\r\n <mat-icon>cloud_queue</mat-icon>\r\n <span>Carica da Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n }\r\n\r\n @else if (allowedTypes.includes(2)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">\r\n aggiungi un link\r\n </a>\r\n }\r\n\r\n @else if (allowedTypes.includes(3)) {\r\n <a [class.disabled-link]=\"isDisabled\" class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); chooseDropboxFile()\">\r\n carica da Dropbox\r\n </a>\r\n }\r\n }\r\n </div>\r\n</div>\r\n}@else {\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button color=\"primary\" [disabled]=\"isDisabled\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n}\r\n}\r\n\r\n<!-- Azioni singolo elemento (come prima) -->\r\n<div class=\"text-center\">\r\n @if (attachmentsList && attachmentsList.length > 0 && attachmentsList[0] && showActionButtons == true) {\r\n <button class=\"mb-2 me-2 eqp-attachments-download-btn\" (click)=\"viewAttachment(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button color=\"primary\">\r\n @if (attachmentsList[0].AttachmentType == AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n {{ attachmentsList[0].AttachmentType == AttachmentType.FILE ? downloadLabel : openLinkLabel }}\r\n </button>\r\n\r\n @if (showPreview && (!attachmentsList[0].FileContentType || (!attachmentsList[0].FileContentType.startsWith('video')\r\n && !attachmentsList[0].FileContentType.startsWith('audio'))) && attachmentsList[0].IsImage == true) {\r\n <button class=\"mb-2 me-2 eqp-attachments-preview-btn\" (click)=\"openPreviewDialog(attachmentsList[0])\" type=\"button\"\r\n mat-raised-button color=\"primary\">\r\n <mat-icon>visibility</mat-icon> {{ previewLabel }}\r\n </button>\r\n }\r\n\r\n <button [disabled]=\"disableAction\" class=\"mb-2 eqp-attachments-delete-btn\"\r\n (click)=\"deleteAttachment(attachmentsList[0])\" type=\"button\" mat-raised-button [disabled]=\"isDisabled\">\r\n <mat-icon>delete</mat-icon> {{ deleteLabel }}\r\n </button>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione multipla -->\r\n@if (multipleAttachment == true && showDropArea == true) {\r\n<input #fileInput id=\"file_attachment_multi\" name=\"file_attachment_multi\" type=\"file\" hidden\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n@if (layout === 'full') {\r\n<div class=\"dropbox\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\"\r\n (click)=\"!isDisabled && onSelectFile($event, fileInput)\" role=\"button\" [attr.tabindex]=\"isDisabled ? -1 : 0\"\r\n (keydown.enter)=\"!isDisabled && fileInput.click()\" (keydown.space)=\"!isDisabled && fileInput.click()\">\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel }}\r\n </div>\r\n <button class=\"browse-btn\" type=\"button\" (click)=\"$event.stopPropagation(); fileInput.click()\">\r\n {{ browseFilesLabel }}\r\n </button>\r\n @if (allowedTypes.includes(2)) {\r\n <div class=\"secondary-action-link\">\r\n o <a (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\">aggiungi un link</a>\r\n </div>\r\n }\r\n</div>\r\n}@else{\r\n<div class=\"compact-uploader\" [class.dragover]=\"dragOver && !isDisabled\" [class.disabled-dropzone]=\"isDisabled\"\r\n (dragover)=\"!isDisabled ? dragOver = true : null; $event.preventDefault()\" (dragleave)=\"dragOver = false\"\r\n (drop)=\"!isDisabled ? (dragOver = false) : null; fileDropped($event)\">\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"!isDisabled && onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button mat-stroked-button [disabled]=\"isDisabled\" color=\"primary\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\">Sfoglia</button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button mat-stroked-button [disabled]=\"isDisabled\" [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\">Link</button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) { <button mat-menu-item [disabled]=\"isDisabled\"\r\n (click)=\"switchToAddingLinkMode()\">{{ openLinkLabel }}</button> }\r\n @if (allowedTypes.includes(3)) { <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"chooseDropboxFile()\">{{\r\n uploadWithDropboxLabel }}</button> }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n}\r\n}\r\n\r\n@if (attachmentsList?.length > 0 && showSummary) {\r\n<div class=\"upload-stats\">\r\n\r\n <div class=\"stats-info\">\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ attachmentsList?.length }}</div>\r\n <div class=\"stat-label\">{{ filesLabel }}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ totalSizeFormatted }}</div>\r\n <div class=\"stat-label\">{{ totalSizeLabel }}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"progressPercent\"></div>\r\n </div>\r\n\r\n</div>\r\n} @else if(attachmentsList?.length == 0){\r\n<div class=\"empty-state\">{{ emptyStateLabel }}</div>\r\n}\r\n\r\n<!-- Griglia anteprime card (vale per singolo e multiplo) -->\r\n@if (viewMode === 'card') {\r\n\r\n<div class=\"file-previews\" [ngStyle]=\"getPreviewsContainerStyle()\">\r\n @for (att of attachmentsList; track att.ID) {\r\n <div [ngClass]=\"getCardClass(att)\">\r\n <div class=\"preview-img-container\" (click)=\"!att.isUploading && handlePrimaryAction(att)\">\r\n\r\n @if (att.IsImage || att.FileThumbnailBase64) {\r\n <img class=\"preview-img\" [src]=\"'data:image/jpeg;base64,' + (att.FileThumbnailBase64 || att.FileDataBase64)\"\r\n [alt]=\"att.FileName\" />\r\n } @else {\r\n <div class=\"file-icon\"><i [ngClass]=\"getAttachmentIcon(att)\"></i></div>\r\n }\r\n\r\n <div class=\"preview-action-overlay\">\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n <mat-icon>play_arrow</mat-icon>\r\n }\r\n @else if (att.IsImage && canBePreviewed(att)) {\r\n <mat-icon>visibility</mat-icon>\r\n }\r\n @else if (att.FileContentType === 'application/pdf' && canBePreviewed(att)) {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n @else if (att.AttachmentType === AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n }\r\n @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n </div>\r\n\r\n </div>\r\n\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"att.FileName\">{{ att.FileName }}</div>\r\n </div>\r\n\r\n @if(!isDeleteHidden(att)){\r\n <button mat-icon-button class=\"remove-btn\" (click)=\"deleteAttachment(att)\"\r\n [disabled]=\"att.isUploading || isDeleteDisabled(att)\">\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n }\r\n\r\n @if (att.isUploading) {\r\n <div class=\"upload-spinner\"></div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n} @else if(viewMode === 'table' && attachmentsList?.length > 0) {\r\n\r\n\r\n<div class=\"table-view-container\">\r\n\r\n <div class=\"table-header\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n {{ col.display }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @for (att of attachmentsList; track att.ID) {\r\n <div class=\"table-row\">\r\n\r\n @for (col of _tableColumns; track col.key) {\r\n <div class=\"table-cell\" [style.flex]=\"col.styles?.flex\" [ngClass]=\"col.class\">\r\n\r\n @switch (col.type) {\r\n\r\n @case ('template') {\r\n <div class=\"template-wrapper\">\r\n <ng-container [ngTemplateOutlet]=\"col.externalTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: att }\"></ng-container>\r\n </div>\r\n }\r\n @case ('date') {\r\n <span class=\"metadata-value\">{{ att[col.key] | date:'dd/MM/yyyy' }}</span>\r\n }\r\n @default {\r\n <span class=\"metadata-value\">{{ att[col.key] }}</span>\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Notifica toast -->\r\n<div class=\"upload-notification\" [class.show]=\"toast?.visible\" [class.success]=\"toast?.type === 'success'\"\r\n [class.error]=\"toast?.type === 'error'\">\r\n <span>{{ toast?.text }}</span>\r\n <div class=\"notification-progress\"></div>\r\n</div>\r\n\r\n<ng-template #defaultFileTemplate let-att>\r\n <i class=\"file-icon-small\" [ngClass]=\"getAttachmentIcon(att)\"></i>\r\n <div class=\"file-info-text\">\r\n <span class=\"file-name-table\">{{ att.FileName }}</span>\r\n <span class=\"file-type-table\">{{ att.FileExtension || 'Link' }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultActionsTemplate let-att>\r\n <button mat-icon-button (click)=\"handlePrimaryAction(att)\"\r\n [matTooltip]=\"att.FileContentType?.startsWith('video/') ? 'Riproduci video' : 'Visualizza/Scarica'\">\r\n\r\n <mat-icon>\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n play_arrow\r\n } @else {\r\n {{ att.AttachmentType === AttachmentType.FILE ? 'download' : 'open_in_new' }}\r\n }\r\n </mat-icon>\r\n </button>\r\n\r\n @if (!hiddenActions.includes('actionsMenu')) {\r\n <button mat-icon-button [matMenuTriggerFor]=\"actionsMenu\" matTooltip=\"Altre opzioni\">\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n }\r\n\r\n <mat-menu #actionsMenu=\"matMenu\">\r\n @for (action of _sortedMenuActions; track action.name) {\r\n @if (!isActionHidden(action, att)) {\r\n <button mat-menu-item (click)=\"action.fn(att)\" [disabled]=\"isActionDisabled(action, att)\">\r\n <mat-icon [color]=\"action.icon === 'delete' ? 'warn' : undefined\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n <span>{{ action.name }}</span>\r\n </button>\r\n }\r\n }\r\n </mat-menu>\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogCropImage>\r\n <div style=\"overflow-x: hidden; display: flex; flex-direction: column; height: 100%; min-height: 0; flex: 1 1 auto;\"\r\n [ngClass]=\"cropDialogClass\">\r\n <!-- @if (showCropImage == true) { -->\r\n <ng-container [ngTemplateOutlet]=\"croppieTemplate\" [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\">\r\n </ng-container>\r\n <!-- } -->\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n @if (row.AttachmentType != AttachmentType.LINK && row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <img [src]=\"'data:image/png;base64,' + (row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64)\" />\r\n </div>\r\n } @else if (row.AttachmentType != AttachmentType.LINK && !row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"modern-dialog-container\"> @if (selectedAttachment) {\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ previewLabel }}</span>\r\n <span class=\"file-t\">{{ selectedAttachment.FileName }}</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"media-viewer-wrapper\">\r\n @if (selectedAttachment.IsImage) {\r\n <img class=\"main-preview-media\"\r\n [src]=\"'data:image/png;base64,' + (selectedAttachment.FileDataBase64 || selectedAttachment.FileThumbnailBase64)\"\r\n [alt]=\"selectedAttachment.FileName\" />\r\n }\r\n @else if (selectedAttachment.FileContentType?.startsWith('video/')) {\r\n <video controls autoplay playsinline class=\"main-preview-media video-player\">\r\n <source [src]=\"selectedAttachment.TrustedUrl\" [type]=\"selectedAttachment.FileContentType\">\r\n Il tuo browser non supporta il video.\r\n </video>\r\n }\r\n @else {\r\n <div class=\"iframe-container\">\r\n <iframe class=\"preview-iframe-modern\" [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"></iframe>\r\n </div>\r\n }\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Chiudi</button>\r\n @if (selectedAttachment.AttachmentType !== AttachmentType.LINK) {\r\n <button mat-raised-button color=\"primary\" (click)=\"viewAttachment(selectedAttachment)\" class=\"btn-download\">\r\n <mat-icon>download</mat-icon> <span>{{ downloadLabel }}</span>\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\r\n <input #fileInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n\r\n @if (allowedTypes && allowedTypes.length == 1 && (multipleAttachment == true || !attachmentsList ||\r\n attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n (click)=\"addFile(allowedTypes[0], fileInput)\" [disabled]=\"isDisabled\">\r\n @if (allowedTypes[0] == 1) { <mat-icon>cloud_upload</mat-icon> }\r\n @if (allowedTypes[0] == 2) { <i class=\"fas fa-link\"></i> }\r\n @if (allowedTypes[0] == 3) { <i class=\"fa-brands fa-dropbox\"></i> }\r\n <span style=\"margin-left: 10px\">\r\n {{ allowedTypes[0] == 1 ? (addButtonLabel + \" file\") : allowedTypes[0] == 2 ? (addButtonLabel + \" link\") :\r\n uploadWithDropboxLabel }}\r\n </span>\r\n </button>\r\n }\r\n\r\n @if (!separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <button class=\"btn btn-primary mb-4 me-5 eqp-attachments-add-btn\" mat-raised-button color=\"primary\" type=\"button\"\r\n [matMenuTriggerFor]=\"attachmentTypeMenu\" [disabled]=\"isDisabled\">\r\n @if (multipleAttachment != true) { <mat-icon>cloud_upload</mat-icon> } @else { <mat-icon>add</mat-icon> }\r\n <span style=\"margin-left: 0px\">{{ addButtonLabel }}</span>\r\n </button>\r\n\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(1)) {\r\n <button mat-menu-item (click)=\"imageInput.click()\" class=\"eqp-attachments-file-btn\">\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(2)) {\r\n <button mat-menu-item [disabled]=\"isDisabled\" (click)=\"switchToAddingLinkMode()\" class=\"eqp-attachments-link-btn\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(3)) {\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\" class=\"eqp-attachments-link-btn\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n }\r\n\r\n @if (separatedUploadButtons && allowedTypes && allowedTypes.length > 1 && (multipleAttachment == true ||\r\n !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <div class=\"btn-group\">\r\n @if (allowedTypes.includes(1)) {\r\n <button (click)=\"imageInput.click()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n <input #imageInput style=\"display: none\" id=\"file_attachment\" name=\"file_attachment\" type=\"file\"\r\n (change)=\"onFileAdded($event)\" [accept]=\"acceptedFileTypes\" [multiple]=\"loadMultipleFiles\" />\r\n @if (allowedTypes.includes(2)) {\r\n <button (click)=\"switchToAddingLinkMode()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n }\r\n @if (allowedTypes.includes(3)) {\r\n <button (click)=\"chooseDropboxFile()\" class=\"btn btn-secondary eqp-attachments-add-btn\" mat-raised-button\r\n color=\"secondary\" type=\"button\">\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ cropLabel }}</span>\r\n <span class=\"file-t\">Regola le dimensioni e l'orientamento</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button type=\"button\" (click)=\"abortFile()\" class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"crop-toolbar\">\r\n @if (cropOptions.includes(1)) {\r\n <button mat-icon-button [matTooltip]=\"rotateLeftLabel\"\r\n (click)=\"rotateLeft()\"><mat-icon>rotate_left</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"rotateRightLabel\"\r\n (click)=\"rotateRight()\"><mat-icon>rotate_right</mat-icon></button>\r\n }\r\n @if (cropOptions.includes(2)) {\r\n <button mat-icon-button [matTooltip]=\"flipHorinzontalLabel\"\r\n (click)=\"flipHorizontal()\"><mat-icon>flip_horizontal</mat-icon></button>\r\n <button mat-icon-button [matTooltip]=\"flipVerticalLabel\"\r\n (click)=\"flipVertical()\"><mat-icon>flip_vertical</mat-icon></button>\r\n }\r\n <button mat-icon-button matTooltip=\"Reset\"\r\n (click)=\"restoreOriginalDimensions()\"><mat-icon>replay</mat-icon></button>\r\n </div>\r\n\r\n <div class=\"media-viewer-wrapper\">\r\n <div class=\"crop-container-modern\">\r\n <image-cropper [imageFile]=\"selectedFile\" [maintainAspectRatio]=\"false\" [canvasRotation]=\"canvasRotation\"\r\n [transform]=\"transform\" format=\"png\" (imageCropped)=\"imageCropped($event)\" [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\" [output]=\"'base64'\" [containWithinAspectRatio]=\"true\" [onlyScaleDown]=\"true\"\r\n [alignImage]=\"'center'\">\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button (click)=\"abortFile()\" class=\"btn-close\">{{ abortLabel }}</button>\r\n <button mat-raised-button color=\"primary\" (click)=\"confirmAddAttachment()\" class=\"btn-download\">\r\n <mat-icon>check</mat-icon> {{ confirmLabel }}\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n\r\n\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"type-icon-wrapper\">\r\n <mat-icon>link</mat-icon>\r\n </div>\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">Aggiungi un link</span>\r\n <span class=\"file-t\">Inserisci l'URL della risorsa web</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\"><mat-icon>close</mat-icon></button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"add-link-modern-content\">\r\n <form [formGroup]=\"newAttachmentForm\" class=\"add-link-form\">\r\n <mat-form-field appearance=\"outline\" class=\"w-100 mt-3\">\r\n <mat-label>URL del collegamento</mat-label>\r\n <input matInput formControlName=\"filePath\" placeholder=\"https://...\" required>\r\n <mat-icon matSuffix>language</mat-icon>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>Titolo (opzionale)</mat-label>\r\n <input matInput formControlName=\"fileName\" placeholder=\"Es. Documento Progetto\">\r\n <mat-icon matSuffix>title</mat-icon>\r\n </mat-form-field>\r\n </form>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Annulla</button>\r\n <button mat-raised-button color=\"primary\" [mat-dialog-close]=\"newAttachmentForm.value\"\r\n [disabled]=\"newAttachmentForm.invalid\" class=\"btn-download\">\r\n <mat-icon>add</mat-icon> Aggiungi\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>", styles: ["@charset \"UTF-8\";:host{--primary-color: #6a5af9;--primary-color-dark: #5441f8;--success-color: #1ce593;--error-color: #ff5b5b;--background-light: #f7f9fc;--background-card: rgba(255, 255, 255, .7);--text-color: #1e293b;--text-color-light: #64748b;--border-color: rgba(203, 213, 225, .5);--shadow-color: rgba(99, 102, 241, .2);--border-radius: 16px;--transition-speed: .3s}@keyframes fadeIn{0%{opacity:0;transform:translateY(15px)}to{opacity:1;transform:translateY(0)}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--primary-color)}70%{box-shadow:0 0 0 10px #6a5af900}to{box-shadow:0 0 #6a5af900}}.container{width:100%;max-width:700px;margin:2rem auto;font-family:Inter,sans-serif}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border-color)}.header h1{color:var(--text-color);font-size:1.8rem;font-weight:700;margin:0}.dropbox{width:100%;border:2px dashed var(--border-color);border-radius:var(--border-radius);padding:2.5rem;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);transition:all var(--transition-speed) ease}.dropbox:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color);border-color:var(--primary-color)}.dropbox.dragover{border-style:solid;border-color:var(--primary-color);transform:scale(1.02);box-shadow:0 0 25px var(--shadow-color);animation:pulse 1.5s infinite}.dropbox .dropbox-icon{font-size:3.5rem;color:var(--primary-color)}.dropbox .dropbox-text{font-size:1.1rem;font-weight:600;color:var(--text-color);margin-top:1rem}.dropbox .dropbox-subtext{color:var(--text-color-light);margin-top:.5rem}.dropbox .browse-btn{margin-top:1.5rem;padding:.75rem 1.5rem;background-color:var(--primary-color);color:#fff;border:none;border-radius:10px;font-weight:600;transition:all var(--transition-speed) ease}.dropbox .browse-btn:hover{background-color:var(--primary-color-dark);transform:translateY(-2px)}.file-previews{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1.5rem;margin-top:2rem}.file-previews{display:grid;gap:16px;padding:16px;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width, 200px),1fr))}.file-preview{background-color:var(--background-card);border-radius:var(--border-radius);box-shadow:0 4px 15px #0000000d;border:1px solid var(--border-color);overflow:hidden;display:flex;flex-direction:column;position:relative;opacity:0;animation:fadeIn .5s ease-out forwards;transition:transform var(--transition-speed) ease,box-shadow var(--transition-speed) ease}.file-preview.uploading{cursor:wait}.file-preview.uploading .preview-img-container:after{content:\"\";position:absolute;inset:0;background:#ffffffb3;-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);pointer-events:none}.file-preview .preview-action-overlay{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;background-color:#0006;color:#fff;opacity:1;transition:opacity .3s ease}.file-preview .preview-action-overlay .mat-icon{font-size:36px;width:36px;height:36px}.file-preview .remove-btn{position:absolute;top:8px;right:8px;z-index:2;background-color:#0000004d;color:#fff;width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;transition:all var(--transition-speed) ease}.file-preview .remove-btn:hover{background-color:#ff5b5b}.file-preview .remove-btn .mat-icon{font-size:18px}@media (hover: hover){.file-preview .remove-btn .file-preview .preview-action-overlay{opacity:0}.file-preview .remove-btn .file-preview:hover .preview-action-overlay,.file-preview .remove-btn .file-preview:hover .remove-btn{opacity:1}.file-preview .remove-btn .file-preview .remove-btn{opacity:0}}@media (hover: hover) and (min-width: 769px){.file-preview .remove-btn{opacity:0;transform:scale(.8)}.file-preview:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color)}.file-preview:hover .remove-btn{opacity:1;transform:scale(1)}}.file-preview .preview-img-container{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;cursor:pointer;background-color:#f0f2f5}.file-preview .preview-img{width:100%;height:100%;object-fit:cover}.file-preview .file-icon{font-size:4rem;color:var(--primary-color)}.file-preview .file-info{padding:12px;border-top:1px solid var(--border-color);flex-grow:1;display:flex;align-items:center}.file-preview .file-name{font-weight:600;font-size:.9rem;color:var(--text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-preview .upload-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border:4px solid rgba(0,0,0,.1);border-left-color:var(--primary-color);border-radius:50%;animation:spin 1s linear infinite;pointer-events:none}.file-preview.card-small{width:140px}.file-preview.card-small .preview-img-container{height:80px}.file-preview.card-small .file-info{padding:8px}.file-preview.card-small .file-name{font-size:.8rem}.file-preview.card-small .file-icon{font-size:3rem}.file-preview.card-small .remove-btn{width:28px;height:28px}.file-preview.card-small .remove-btn .mat-icon{font-size:16px}.file-preview.card-large{width:280px}.file-preview.card-large .preview-img-container{height:180px}.file-preview.card-large .file-info{padding:16px}.file-preview.card-large .file-name{font-size:1rem}.file-preview.card-large .file-icon{font-size:5rem}.file-preview.card-large .remove-btn{width:36px;height:36px}.file-preview.card-large .remove-btn .mat-icon{font-size:20px}.file-preview[style*=--eqp-card-width]{width:var(--eqp-card-width)}.file-preview[style*=--eqp-card-width] .preview-img-container{height:calc(var(--eqp-card-width) * .65)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}.upload-stats{background-color:var(--background-card);-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid var(--border-color);border-radius:var(--border-radius);padding:1.5rem;margin-top:2rem;animation:fadeIn .5s ease-out}.upload-stats .stats-info{display:flex;justify-content:space-around}.upload-stats .progress-bar{height:10px;background-color:var(--border-color);border-radius:5px;overflow:hidden;margin-top:1rem}.upload-stats .progress-fill{height:100%;background:linear-gradient(90deg,var(--primary-color),var(--success-color));transition:width var(--transition-speed) ease-out;border-radius:5px}.upload-notification{position:fixed;bottom:20px;left:50%;transform:translate(-50%,100px);padding:1rem 1.5rem;border-radius:var(--border-radius);color:#fff;font-weight:600;box-shadow:0 10px 30px #0003;transition:transform var(--transition-speed) cubic-bezier(.175,.885,.32,1.275)}.upload-notification.show{transform:translate(-50%)}.upload-notification.success{background-color:var(--success-color)}.upload-notification.error{background-color:var(--error-color)}::ng-deep .cdk-overlay-pane.eqp-crop-dialog{transform:translateY(-4vh)}@media (max-width: 600px){::ng-deep .cdk-overlay-pane.crop-dialog{width:auto!important}}::ng-deep .eqp-attachments-dialog{display:flex!important;flex-direction:column!important}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container{display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__container .mdc-dialog__surface{border-radius:20px!important;padding:0!important;overflow:hidden!important;width:fit-content!important;min-width:350px!important;max-width:95vw!important;max-height:90vh!important;margin:0 auto;background-color:#fff!important;display:flex!important;flex-direction:column!important;flex:1 1 auto;min-height:0}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;display:flex;flex-direction:column;flex:1 1 auto;min-height:0;overflow:hidden!important}.modern-dialog-container{display:flex;flex-direction:column;width:100%;max-width:100%;flex:1 1 auto;min-height:0;height:100%;max-height:100%;background:#fff;--preview-header-h: 66px;--preview-footer-h: 66px;--preview-padding-y: 30px}.modern-dialog-container .main-preview-media{display:block;max-width:100%;max-height:var(--media-max-h);width:auto;height:auto;object-fit:contain;border-radius:12px;background:#fff;padding:4px;box-shadow:0 10px 30px #00000014}.modern-dialog-container video.main-preview-media{width:min(100%,1100px);background:#000}.modern-dialog-container .iframe-container{width:min(100%,1100px);height:var(--media-max-h);display:flex;width:100%;max-width:1100px}.modern-dialog-container .preview-iframe-modern{width:100%;height:100%;border:0;border-radius:12px;background:#f8fafc}.modern-dialog-container .preview-header{flex:0 0 auto;flex-shrink:0;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;border-bottom:1px solid var(--border-color);background:#f8fafc;z-index:10;width:100%}.modern-dialog-container .preview-header .close-btn{display:inline-flex!important;align-items:center!important;justify-content:center!important;padding:0!important;width:40px!important;height:40px!important}.modern-dialog-container .preview-header .close-btn ::ng-deep mat-icon{display:flex!important;align-items:center!important;justify-content:center!important;margin:0!important;padding:0!important;line-height:1!important}.modern-dialog-container .preview-header .header-info{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex:1 1 auto;min-width:0;text-align:left}.modern-dialog-container .preview-header .header-info .type-icon-wrapper{background:var(--primary-color);color:#fff;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px var(--shadow-color)}.modern-dialog-container .preview-header .header-info .title-group{display:flex;flex-direction:column;align-items:flex-start;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .main-t{font-weight:800;color:var(--text-color);font-size:.95rem;line-height:1.2;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .file-t{font-size:.75rem;color:var(--text-color-light);max-width:250px;overflow:hidden;text-overflow:ellipsis;text-align:left}.modern-dialog-container .preview-content-area{flex:1 1 auto;background:#fff!important;display:flex;flex-direction:column;padding:15px 15px 22px!important;overflow:hidden!important;min-height:0;width:100%;--media-max-h: calc(90vh - var(--preview-header-h) - var(--preview-footer-h) - var(--preview-padding-y))}.modern-dialog-container .preview-content-area .crop-toolbar{flex-shrink:0;z-index:20;background:#0f172a14;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);padding:6px 16px;border-radius:30px;margin:0 auto 15px;display:flex;gap:8px;box-shadow:0 4px 12px #0000000d}.modern-dialog-container .preview-content-area .crop-toolbar button{color:var(--text-color)!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper{flex:1 1 auto;width:100%;height:100%;display:flex;flex-direction:column;align-items:stretch;min-height:0;overflow:hidden}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern{flex:1 1 auto;display:flex;flex-direction:column;justify-content:center;align-items:center;background:transparent;border-radius:12px;padding:0;overflow:hidden;min-height:0;width:100%;height:100%}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern image-cropper{flex:1 1 auto;width:100%;height:100%;max-width:100%!important;max-height:100%!important;display:block;min-height:0}.modern-dialog-container .add-link-modern-content{flex:1;background:#fff;padding:24px!important}.modern-dialog-container .add-link-modern-content .add-link-form{display:flex;flex-direction:column;gap:10px}.modern-dialog-container .preview-actions{flex-shrink:0;padding:12px 24px;background:#f8fafc;border-top:1px solid #e2e8f0;margin:0}.modern-dialog-container .preview-actions .btn-download{border-radius:12px;font-weight:600;box-shadow:0 4px 12px var(--shadow-color)}@media (max-width: 600px){.modern-dialog-container{max-height:95vh}.modern-dialog-container .preview-content-area{padding:10px!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper video.main-preview-media{width:100%!important;max-height:55vh!important;border-radius:4px;box-shadow:none}.modern-dialog-container .preview-content-area .media-viewer-wrapper .iframe-container{height:50vh}.modern-dialog-container .preview-content-area .crop-toolbar{width:calc(100% - 20px);max-width:400px;margin-bottom:10px;padding:4px 8px;gap:4px;overflow-x:auto;justify-content:center;-webkit-overflow-scrolling:touch;scrollbar-width:none}.modern-dialog-container .preview-content-area .crop-toolbar::-webkit-scrollbar{display:none}.modern-dialog-container .preview-content-area .crop-toolbar button{flex-shrink:0;transform:scale(.85);width:40px;height:40px}.modern-dialog-container .preview-actions{padding:10px 15px;flex-direction:column-reverse;gap:8px}.modern-dialog-container .preview-actions button{width:100%;margin:0!important}}@media (max-width: 360px){.modern-dialog-container .preview-content-area .crop-toolbar{gap:2px}.modern-dialog-container .preview-content-area .crop-toolbar button{transform:scale(.75)}}.control-icon{font-size:28px;cursor:pointer}image-cropper{display:flex!important;max-width:100%!important;max-height:100%!important;height:100%;width:100%}image-cropper canvas,image-cropper img{max-width:100%!important;max-height:100%!important}.crop-large{display:flex}.crop-small{display:none}@media (max-width: 600px){.dialog-content{max-height:55vh}.crop-container{max-width:100%;aspect-ratio:auto}.crop-large{display:none}.crop-small{display:flex;justify-content:center;gap:14px}.control-icon{font-size:24px}}.stats-header{display:flex;justify-content:space-between;align-items:center;width:100%}.table-view-container{margin-top:1.5rem;background-color:var(--background-card);border-radius:var(--border-radius);border:1px solid var(--border-color);overflow:hidden;animation:fadeIn .5s ease-out}.table-header,.table-row{display:flex;align-items:center;padding:0 1rem;transition:background-color var(--transition-speed) ease}.table-header{background-color:#f8f9fa;font-weight:600;color:var(--text-color-light);font-size:.8rem;text-transform:uppercase;border-bottom:2px solid var(--border-color)}.table-row{border-bottom:1px solid var(--border-color)}.table-row:last-child{border-bottom:none}.table-row:hover{background-color:#00000005}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem}.name-col{flex:4}.size-col,.date-col{flex:2}.actions-col{flex:1;justify-content:flex-end;min-width:150px}.file-icon-small{font-size:1.5rem;color:var(--primary-color)}.file-info-text{display:flex;flex-direction:column}.file-name-table{font-weight:600;color:var(--text-color)}.file-type-table{font-size:.8rem;color:var(--text-color-light)}@media (max-width: 768px){.date-col{display:none}.name-col{flex:3}.size-col{flex:2}.actions-col{flex:2;min-width:120px}}.secondary-action-link{color:var(--primary-color);text-decoration:none;border-bottom:1px solid var(--primary-color);cursor:pointer;font-weight:500}.secondary-action-link:hover{color:var(--primary-color-dark);border-bottom-color:var(--primary-color-dark)}h2[mat-dialog-title]+mat-dialog-content.add-link-dialog-content{padding-top:20px}mat-dialog-content.add-link-dialog-content{padding-left:24px;padding-right:24px;padding-bottom:20px}.add-link-form{display:flex;flex-direction:column;gap:16px}::ng-deep .eqp-attachments-preview-dialog{--mdc-dialog-subhead-line-height: normal}::ng-deep .eqp-attachments-preview-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;background:#fff!important}:host ::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{--mdc-dialog-subhead-size: 1.25rem;--mdc-dialog-subhead-line-height: 1.5;--mdc-dialog-subhead-weight: 600;--mdc-dialog-supporting-text-size: 1rem}.empty-state{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:1.5rem 1rem;margin-top:1.5rem;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#f8f9fa;text-align:center;color:var(--text-color-light);animation:fadeIn .5s ease-out}.empty-state:before{content:\"\\1f4ed\";font-size:2.5rem;margin-bottom:1rem;opacity:.7}.secondary-action-link.disabled-link{color:#adb5bd;cursor:not-allowed;border-bottom-color:transparent}.secondary-action-link.disabled-link:hover{color:#adb5bd;border-bottom-color:transparent}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem;min-width:0;overflow:hidden}.table-cell.col-actions{flex:0 0 150px;justify-content:flex-end;overflow:visible}.compact-uploader{display:flex;align-items:center;gap:16px;padding:16px;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#fcfdff;transition:all .3s ease}.compact-uploader .compact-text{flex:1 1 auto;min-width:0;cursor:pointer}.compact-uploader .compact-text:hover .compact-title{color:var(--primary-color)}.compact-uploader .compact-title{font-weight:600;color:var(--text-color);transition:color .3s ease}.compact-uploader .compact-subtitle{font-size:.8rem;color:var(--text-color-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-uploader .compact-icon mat-icon{font-size:36px;width:36px;height:36px;color:var(--primary-color)}.compact-uploader .compact-actions{display:flex;gap:8px;flex-shrink:0}.compact-uploader.dragover{background-color:#f4f8ff;border-color:var(--primary-color);box-shadow:0 0 10px var(--shadow-color)}.disabled-dropzone{opacity:.5;cursor:not-allowed!important;background-color:#f5f5f5;border-color:#d1d5db}.disabled-dropzone *{pointer-events:none}.disabled-dropzone .browse-btn,.disabled-dropzone button{cursor:not-allowed!important;background-color:#e5e7eb;color:#9ca3af;border:none}.disabled-dropzone .secondary-action-link,.disabled-dropzone a{color:#9ca3af;text-decoration:none}\n"] }]
|
|
1568
|
-
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2.FormBuilder }, { type: i3.DomSanitizer }, { type: i4.HttpClient }, { type: EqpAttachmentService }], propDecorators: { disableAction: [{
|
|
1569
|
-
type: Input,
|
|
1570
|
-
args: ["disableAction"]
|
|
1571
|
-
}], showHeader: [{
|
|
1572
|
-
type: Input,
|
|
1573
|
-
args: ["showHeader"]
|
|
1574
|
-
}], attachmentsList: [{
|
|
1629
|
+
args: [{ selector: "eqp-attachments", standalone: false, template: "<!-- Se richiesta la gestione singola mostra il pulsante di caricamento di un singolo file -->\r\n@if(showUploadTitle() == true || chooseView() == true){\r\n<div class=\"header\">\r\n @if(showUploadTitle() == true){\r\n <h4>{{ uploadTitle() }}</h4>\r\n } @if(chooseView() == true){\r\n <mat-button-toggle-group\r\n [value]=\"viewMode\"\r\n (change)=\"setViewMode($event.value)\"\r\n aria-label=\"Modalit\u00E0 di visualizzazione\"\r\n >\r\n <mat-button-toggle value=\"card\"\r\n ><mat-icon>grid_view</mat-icon></mat-button-toggle\r\n >\r\n <mat-button-toggle value=\"table\"\r\n ><mat-icon>view_list</mat-icon></mat-button-toggle\r\n >\r\n </mat-button-toggle-group>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione singolo -->\r\n@if (multipleAttachment() != true) { @if (!singleAttachmentDragAndDrop()) { @if\r\n(!addingLinkMode()) {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addAttachmentButton\"></ng-container>\r\n</div>\r\n} @else {\r\n<div class=\"text-center\">\r\n <ng-container [ngTemplateOutlet]=\"addingLinkTemplate\"></ng-container>\r\n</div>\r\n} } @else {\r\n<input\r\n #fileInput\r\n id=\"file_attachment\"\r\n name=\"file_attachment\"\r\n type=\"file\"\r\n hidden\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles()\"\r\n/>\r\n\r\n@if (allowedTypes && allowedTypes.includes(1) && (!attachmentsList ||\r\nattachmentsList.length == 0 || (attachmentsList.length > 0 &&\r\n!attachmentsList[0]))) { @if (showDropArea() == true) {\r\n<!-- FULL -->\r\n@if (layout() === 'full') {\r\n\r\n<div\r\n class=\"dropbox\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n (keydown.enter)=\"fileInput.click()\"\r\n (keydown.space)=\"fileInput.click()\"\r\n>\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel() }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel() }}\r\n </div>\r\n <button\r\n class=\"browse-btn\"\r\n type=\"button\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n {{ browseFilesLabel() }}\r\n </button>\r\n <div class=\"secondary-action\">\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) { @if\r\n (allowedTypes.includes(2) && allowedTypes.includes(3)) {\r\n <a\r\n class=\"secondary-action-link\"\r\n [matMenuTriggerFor]=\"isDisabled() ? null : linkMenu\"\r\n [class.disabled-link]=\"isDisabled()\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n o aggiungi da web\r\n </a>\r\n <mat-menu #linkMenu=\"matMenu\">\r\n <button mat-menu-item (click)=\"switchToAddingLinkMode()\">\r\n <mat-icon>link</mat-icon>\r\n <span>Aggiungi da link</span>\r\n </button>\r\n <button mat-menu-item (click)=\"chooseDropboxFile()\">\r\n <mat-icon>cloud_queue</mat-icon>\r\n <span>Carica da Dropbox</span>\r\n </button>\r\n </mat-menu>\r\n } @else if (allowedTypes.includes(2)) {\r\n <a\r\n [class.disabled-link]=\"isDisabled()\"\r\n class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\"\r\n >\r\n aggiungi un link\r\n </a>\r\n } @else if (allowedTypes.includes(3)) {\r\n <a\r\n [class.disabled-link]=\"isDisabled()\"\r\n class=\"secondary-action-link\"\r\n (click)=\"$event.stopPropagation(); chooseDropboxFile()\"\r\n >\r\n carica da Dropbox\r\n </a>\r\n } }\r\n </div>\r\n</div>\r\n}@else {\r\n<div\r\n class=\"compact-uploader\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n>\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel() }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button\r\n mat-stroked-button\r\n color=\"primary\"\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n Sfoglia\r\n </button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button\r\n mat-stroked-button\r\n [disabled]=\"isDisabled()\"\r\n [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n Link\r\n </button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n >\r\n {{ openLinkLabel() }}\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"chooseDropboxFile()\"\r\n >\r\n {{ uploadWithDropboxLabel() }}\r\n </button>\r\n }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n} } } }\r\n\r\n<!-- Azioni singolo elemento (come prima) -->\r\n<div class=\"text-center\">\r\n @if (attachmentsList && attachmentsList.length > 0 && attachmentsList[0] &&\r\n showActionButtons() == true) {\r\n @if (!isPrimaryActionHidden(attachmentsList[0])) {\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 [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button\r\n color=\"primary\"\r\n >\r\n @if (attachmentsList[0].AttachmentType == AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n {{\r\n attachmentsList[0].AttachmentType == AttachmentType.FILE\r\n ? downloadLabel()\r\n : openLinkLabel()\r\n }}\r\n </button>\r\n }\r\n\r\n @if (!isPrimaryActionHidden(attachmentsList[0]) && showPreview() && (!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 <button\r\n class=\"mb-2 me-2 eqp-attachments-preview-btn\"\r\n (click)=\"openPreviewDialog(attachmentsList[0])\"\r\n type=\"button\"\r\n [disabled]=\"isPrimaryActionDisabled(attachmentsList[0])\"\r\n mat-raised-button\r\n color=\"primary\"\r\n >\r\n <mat-icon>visibility</mat-icon> {{ previewLabel() }}\r\n </button>\r\n }\r\n\r\n <button\r\n [disabled]=\"disableAction()\"\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 [disabled]=\"isDisabled()\"\r\n >\r\n <mat-icon>delete</mat-icon> {{ deleteLabel() }}\r\n </button>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Gestione multipla -->\r\n@if (multipleAttachment() == true && showDropArea() == true) {\r\n<input\r\n #fileInput\r\n id=\"file_attachment_multi\"\r\n name=\"file_attachment_multi\"\r\n type=\"file\"\r\n hidden\r\n (change)=\"onFileAdded($event)\"\r\n [accept]=\"acceptedFileTypes\"\r\n [multiple]=\"loadMultipleFiles()\"\r\n/>\r\n\r\n@if (layout() === 'full') {\r\n<div\r\n class=\"dropbox\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n (click)=\"onSelectFile($event, fileInput)\"\r\n role=\"button\"\r\n tabindex=\"0\"\r\n (keydown.enter)=\"fileInput.click()\"\r\n (keydown.space)=\"fileInput.click()\"\r\n>\r\n <div class=\"dropbox-icon\">\uD83D\uDCC1</div>\r\n <div class=\"dropbox-text\">{{ dropHereLabel() }}</div>\r\n <div class=\"dropbox-subtext\">\r\n {{ supportedFormatsLabel() }}\r\n </div>\r\n <button\r\n class=\"browse-btn\"\r\n type=\"button\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n {{ browseFilesLabel() }}\r\n </button>\r\n @if (allowedTypes.includes(2)) {\r\n <div class=\"secondary-action-link\">\r\n o\r\n <a (click)=\"$event.stopPropagation(); switchToAddingLinkMode()\"\r\n >aggiungi un link</a\r\n >\r\n </div>\r\n }\r\n</div>\r\n}@else{\r\n<div\r\n class=\"compact-uploader\"\r\n [class.dragover]=\"dragOver\"\r\n (dragover)=\"dragOver = true; $event.preventDefault()\"\r\n (dragleave)=\"dragOver = false\"\r\n (drop)=\"dragOver = false; fileDropped($event)\"\r\n>\r\n <div class=\"compact-icon\"><mat-icon>folder_open</mat-icon></div>\r\n <div class=\"compact-text\" (click)=\"onSelectFile($event, fileInput)\">\r\n <div class=\"compact-title\">Trascina i file o seleziona dal computer</div>\r\n <div class=\"compact-subtitle\">{{ supportedFormatsLabel() }}</div>\r\n </div>\r\n <div class=\"compact-actions\">\r\n <button\r\n mat-stroked-button\r\n [disabled]=\"isDisabled()\"\r\n color=\"primary\"\r\n (click)=\"$event.stopPropagation(); fileInput.click()\"\r\n >\r\n Sfoglia\r\n </button>\r\n @if (allowedTypes.includes(2) || allowedTypes.includes(3)) {\r\n <button\r\n mat-stroked-button\r\n [disabled]=\"isDisabled()\"\r\n [matMenuTriggerFor]=\"compactLinkMenu\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n Link\r\n </button>\r\n <mat-menu #compactLinkMenu=\"matMenu\">\r\n @if (allowedTypes.includes(2)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n >\r\n {{ openLinkLabel() }}\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"chooseDropboxFile()\"\r\n >\r\n {{ uploadWithDropboxLabel() }}\r\n </button>\r\n }\r\n </mat-menu>\r\n }\r\n </div>\r\n</div>\r\n} } @if (attachmentsList?.length > 0 && showSummary()) {\r\n<div class=\"upload-stats\">\r\n <div class=\"stats-info\">\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ attachmentsList?.length }}</div>\r\n <div class=\"stat-label\">{{ filesLabel() }}</div>\r\n </div>\r\n <div class=\"stat-item\">\r\n <div class=\"stat-value\">{{ totalSizeFormatted() }}</div>\r\n <div class=\"stat-label\">{{ totalSizeLabel() }}</div>\r\n </div>\r\n </div>\r\n\r\n <div class=\"progress-bar\">\r\n <div class=\"progress-fill\" [style.width.%]=\"progressPercent()\"></div>\r\n </div>\r\n</div>\r\n} @else if(attachmentsList?.length == 0){\r\n<div class=\"empty-state\">{{ emptyStateLabel() }}</div>\r\n}\r\n\r\n<!-- Griglia anteprime card (vale per singolo e multiplo) -->\r\n@if (viewMode === 'card') {\r\n\r\n<div class=\"file-previews\" [ngStyle]=\"getPreviewsContainerStyle()\">\r\n @for (att of attachmentsList; track att.ID) {\r\n <div [ngClass]=\"getCardClass(att)\">\r\n <div\r\n class=\"preview-img-container\"\r\n (click)=\"!att.isUploading && handlePrimaryAction(att)\"\r\n >\r\n @if (att.IsImage || att.FileThumbnailBase64) {\r\n <img\r\n class=\"preview-img\"\r\n [src]=\"\r\n 'data:image/jpeg;base64,' +\r\n (att.FileThumbnailBase64 || att.FileDataBase64)\r\n \"\r\n [alt]=\"att.FileName\"\r\n />\r\n } @else {\r\n <div class=\"file-icon\"><i [ngClass]=\"getAttachmentIcon(att)\"></i></div>\r\n }\r\n\r\n <div class=\"preview-action-overlay\">\r\n @if (att.FileContentType?.startsWith('video/')) {\r\n <mat-icon>play_arrow</mat-icon>\r\n } @else if (att.IsImage && canBePreviewed(att)) {\r\n <mat-icon>visibility</mat-icon>\r\n } @else if (att.FileContentType === 'application/pdf' &&\r\n canBePreviewed(att)) {\r\n <mat-icon>open_in_new</mat-icon>\r\n } @else if (att.AttachmentType === AttachmentType.FILE) {\r\n <mat-icon>download</mat-icon>\r\n } @else {\r\n <mat-icon>open_in_new</mat-icon>\r\n }\r\n </div>\r\n </div>\r\n\r\n <div class=\"file-info\">\r\n <div class=\"file-name\" [title]=\"att.FileName\">{{ att.FileName }}</div>\r\n </div>\r\n\r\n @if(!isDeleteHidden(att)){\r\n <button\r\n mat-icon-button\r\n class=\"remove-btn\"\r\n (click)=\"deleteAttachment(att)\"\r\n [disabled]=\"att.isUploading || isDeleteDisabled(att)\"\r\n >\r\n <mat-icon>delete</mat-icon>\r\n </button>\r\n } @if (att.isUploading) {\r\n <div class=\"upload-spinner\"></div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n\r\n} @else if(viewMode === 'table' && attachmentsList?.length > 0) {\r\n\r\n<div class=\"table-view-container\">\r\n <div class=\"table-header\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div\r\n class=\"table-cell\"\r\n [style.flex]=\"col.styles?.flex\"\r\n [ngClass]=\"col.class\"\r\n >\r\n {{ col.display }}\r\n </div>\r\n }\r\n </div>\r\n\r\n @for (att of attachmentsList; track att.ID) {\r\n <div class=\"table-row\">\r\n @for (col of _tableColumns; track col.key) {\r\n <div\r\n class=\"table-cell\"\r\n [style.flex]=\"col.styles?.flex\"\r\n [ngClass]=\"col.class\"\r\n >\r\n @switch (col.type) { @case ('template') {\r\n <div class=\"template-wrapper\">\r\n <ng-container\r\n [ngTemplateOutlet]=\"col.externalTemplate\"\r\n [ngTemplateOutletContext]=\"{ $implicit: att }\"\r\n ></ng-container>\r\n </div>\r\n } @case ('date') {\r\n <span class=\"metadata-value\">{{\r\n att[col.key] | date : \"dd/MM/yyyy\"\r\n }}</span>\r\n } @default {\r\n <span class=\"metadata-value\">{{ att[col.key] }}</span>\r\n } }\r\n </div>\r\n }\r\n </div>\r\n }\r\n</div>\r\n}\r\n\r\n<!-- Notifica toast -->\r\n<div\r\n class=\"upload-notification\"\r\n [class.show]=\"toast?.visible\"\r\n [class.success]=\"toast?.type === 'success'\"\r\n [class.error]=\"toast?.type === 'error'\"\r\n>\r\n <span>{{ toast?.text }}</span>\r\n <div class=\"notification-progress\"></div>\r\n</div>\r\n\r\n<ng-template #defaultFileTemplate let-att>\r\n <i class=\"file-icon-small\" [ngClass]=\"getAttachmentIcon(att)\"></i>\r\n <div class=\"file-info-text\">\r\n <span class=\"file-name-table\">{{ att.FileName }}</span>\r\n <span class=\"file-type-table\">{{ att.FileExtension || \"Link\" }}</span>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #defaultActionsTemplate let-att>\r\n <button\r\n mat-icon-button\r\n (click)=\"handlePrimaryAction(att)\"\r\n [matTooltip]=\"\r\n att.FileContentType?.startsWith('video/')\r\n ? 'Riproduci video'\r\n : 'Visualizza/Scarica'\r\n \"\r\n >\r\n <mat-icon>\r\n @if (att.FileContentType?.startsWith('video/')) { play_arrow } @else {\r\n {{\r\n att.AttachmentType === AttachmentType.FILE ? \"download\" : \"open_in_new\"\r\n }}\r\n }\r\n </mat-icon>\r\n </button>\r\n\r\n @if (!hiddenActions().includes('actionsMenu')) {\r\n <button\r\n mat-icon-button\r\n [matMenuTriggerFor]=\"actionsMenu\"\r\n matTooltip=\"Altre opzioni\"\r\n >\r\n <mat-icon>more_vert</mat-icon>\r\n </button>\r\n }\r\n\r\n <mat-menu #actionsMenu=\"matMenu\">\r\n @for (action of _sortedMenuActions; track action.name) { @if\r\n (!isActionHidden(action, att)) {\r\n <button\r\n mat-menu-item\r\n (click)=\"action.fn(att)\"\r\n [disabled]=\"isActionDisabled(action, att)\"\r\n >\r\n <mat-icon [color]=\"action.icon === 'delete' ? 'warn' : undefined\">\r\n {{ action.icon }}\r\n </mat-icon>\r\n <span>{{ action.name }}</span>\r\n </button>\r\n } }\r\n </mat-menu>\r\n</ng-template>\r\n\r\n<ng-template #dialogCropImage>\r\n <div style=\"overflow-x: hidden\" [ngClass]=\"cropDialogClass()\">\r\n <!-- @if (showCropImage == true) { -->\r\n <ng-container\r\n [ngTemplateOutlet]=\"croppieTemplate\"\r\n [ngTemplateOutletContext]=\"{ form: newAttachmentForm }\"\r\n >\r\n </ng-container>\r\n <!-- } -->\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #inlinePreviewTemplate let-row=\"row\">\r\n @if (row.AttachmentType != AttachmentType.LINK && row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <img\r\n [src]=\"\r\n 'data:image/png;base64,' +\r\n (row.FileThumbnailBase64 ? row.FileThumbnailBase64 : row.FileDataBase64)\r\n \"\r\n />\r\n </div>\r\n } @else if (row.AttachmentType != AttachmentType.LINK && !row.IsImage) {\r\n <div class=\"inline-preview-container\" (click)=\"openPreviewDialog(row)\">\r\n <i [ngClass]=\"getAttachmentIcon(row)\"></i>\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #dialogPreview>\r\n <div class=\"modern-dialog-container\">\r\n @if (selectedAttachment) {\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ previewLabel() }}</span>\r\n <span class=\"file-t\">{{ selectedAttachment.FileName }}</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"media-viewer-wrapper\">\r\n @if (selectedAttachment.IsImage) {\r\n <img\r\n class=\"main-preview-media\"\r\n [src]=\"\r\n 'data:image/png;base64,' +\r\n (selectedAttachment.FileDataBase64 ||\r\n selectedAttachment.FileThumbnailBase64)\r\n \"\r\n [alt]=\"selectedAttachment.FileName\"\r\n />\r\n } @else if (selectedAttachment.FileContentType?.startsWith('video/')) {\r\n <video\r\n controls\r\n autoplay\r\n playsinline\r\n class=\"main-preview-media video-player\"\r\n >\r\n <source\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [type]=\"selectedAttachment.FileContentType\"\r\n />\r\n Il tuo browser non supporta il video.\r\n </video>\r\n } @else {\r\n <div class=\"iframe-container\">\r\n <iframe\r\n class=\"preview-iframe-modern\"\r\n [src]=\"selectedAttachment.TrustedUrl\"\r\n [title]=\"selectedAttachment.FileName\"\r\n ></iframe>\r\n </div>\r\n }\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Chiudi</button>\r\n @if (selectedAttachment.AttachmentType !== AttachmentType.LINK) {\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"viewAttachment(selectedAttachment)\"\r\n class=\"btn-download\"\r\n >\r\n <mat-icon>download</mat-icon> <span>{{ downloadLabel() }}</span>\r\n </button>\r\n }\r\n </mat-dialog-actions>\r\n }\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER IL PULSANTE DI AGGIUNTA NUOVO ALLEGATO -->\r\n<ng-template #addAttachmentButton>\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 />\r\n\r\n @if (allowedTypes && allowedTypes.length == 1 && (multipleAttachment() == true\r\n || !attachmentsList || attachmentsList.length == 0 || (attachmentsList.length\r\n > 0 && !attachmentsList[0]))) {\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 (click)=\"addFile(allowedTypes[0], fileInput)\"\r\n [disabled]=\"isDisabled()\"\r\n >\r\n @if (allowedTypes[0] == 1) { <mat-icon>cloud_upload</mat-icon> } @if\r\n (allowedTypes[0] == 2) { <i class=\"fas fa-link\"></i> } @if (allowedTypes[0]\r\n == 3) { <i class=\"fa-brands fa-dropbox\"></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 }}\r\n </span>\r\n </button>\r\n } @if (!separatedUploadButtons() && allowedTypes && allowedTypes.length > 1 &&\r\n (multipleAttachment() == true || !attachmentsList || attachmentsList.length == 0\r\n || (attachmentsList.length > 0 && !attachmentsList[0]))) {\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 >\r\n @if (multipleAttachment() != true) { <mat-icon>cloud_upload</mat-icon> } @else\r\n { <mat-icon>add</mat-icon> }\r\n <span style=\"margin-left: 0px\">{{ addButtonLabel() }}</span>\r\n </button>\r\n\r\n <mat-menu #attachmentTypeMenu=\"matMenu\">\r\n <input\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 />\r\n @if (allowedTypes.includes(1)) {\r\n <button\r\n mat-menu-item\r\n (click)=\"imageInput.click()\"\r\n class=\"eqp-attachments-file-btn\"\r\n >\r\n <i class=\"fas fa-file\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n } @if (allowedTypes.includes(2)) {\r\n <button\r\n mat-menu-item\r\n [disabled]=\"isDisabled()\"\r\n (click)=\"switchToAddingLinkMode()\"\r\n class=\"eqp-attachments-link-btn\"\r\n >\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\r\n mat-menu-item\r\n (click)=\"chooseDropboxFile()\"\r\n class=\"eqp-attachments-link-btn\"\r\n >\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </mat-menu>\r\n } @if (separatedUploadButtons() && allowedTypes && allowedTypes.length > 1 &&\r\n (multipleAttachment() == true || !attachmentsList || attachmentsList.length == 0\r\n || (attachmentsList.length > 0 && !attachmentsList[0]))) {\r\n <div class=\"btn-group\">\r\n @if (allowedTypes.includes(1)) {\r\n <button\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 >\r\n <i class=\"fa-solid fa-cloud-upload\"></i>\r\n <span style=\"margin-left: 10px\">File</span>\r\n </button>\r\n }\r\n <input\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 />\r\n @if (allowedTypes.includes(2)) {\r\n <button\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 >\r\n <i class=\"fas fa-link\"></i>\r\n <span style=\"margin-left: 10px\">Link</span>\r\n </button>\r\n } @if (allowedTypes.includes(3)) {\r\n <button\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 >\r\n <i class=\"fa-brands fa-dropbox\"></i>\r\n <span style=\"margin-left: 10px\">Dropbox</span>\r\n </button>\r\n }\r\n </div>\r\n }\r\n</ng-template>\r\n\r\n<ng-template #croppieTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">{{ cropLabel() }}</span>\r\n <span class=\"file-t\">Regola le dimensioni e l'orientamento</span>\r\n </div>\r\n </div>\r\n <button\r\n mat-icon-button\r\n type=\"button\"\r\n (click)=\"abortFile()\"\r\n class=\"close-btn\"\r\n >\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"preview-content-area\">\r\n <div class=\"crop-toolbar\">\r\n @if (cropOptions().includes(1)) {\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"rotateLeftLabel()\"\r\n (click)=\"rotateLeft()\"\r\n >\r\n <mat-icon>rotate_left</mat-icon>\r\n </button>\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"rotateRightLabel()\"\r\n (click)=\"rotateRight()\"\r\n >\r\n <mat-icon>rotate_right</mat-icon>\r\n </button>\r\n } @if (cropOptions().includes(2)) {\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"flipHorinzontalLabel()\"\r\n (click)=\"flipHorizontal()\"\r\n >\r\n <mat-icon>flip_horizontal</mat-icon>\r\n </button>\r\n <button\r\n mat-icon-button\r\n [matTooltip]=\"flipVerticalLabel()\"\r\n (click)=\"flipVertical()\"\r\n >\r\n <mat-icon>flip_vertical</mat-icon>\r\n </button>\r\n }\r\n <button\r\n mat-icon-button\r\n matTooltip=\"Reset\"\r\n (click)=\"restoreOriginalDimensions()\"\r\n >\r\n <mat-icon>replay</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <div class=\"media-viewer-wrapper\">\r\n <div class=\"crop-container-modern\">\r\n <image-cropper\r\n [imageFile]=\"selectedFile\"\r\n [maintainAspectRatio]=\"false\"\r\n [canvasRotation]=\"canvasRotation\"\r\n [transform]=\"transform\"\r\n format=\"png\"\r\n (imageCropped)=\"imageCropped($event)\"\r\n [resizeToWidth]=\"customWidth\"\r\n [resizeToHeight]=\"customHeight\"\r\n [output]=\"'base64'\"\r\n [containWithinAspectRatio]=\"true\"\r\n [onlyScaleDown]=\"true\"\r\n [alignImage]=\"'center'\"\r\n >\r\n </image-cropper>\r\n </div>\r\n </div>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button (click)=\"abortFile()\" class=\"btn-close\">\r\n {{ abortLabel() }}\r\n </button>\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n (click)=\"confirmAddAttachment()\"\r\n class=\"btn-download\"\r\n >\r\n <mat-icon>check</mat-icon> {{ confirmLabel() }}\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- TEMPLATE PER FORM DI AGGIUNTA DI UN LINK -->\r\n<ng-template #addingLinkTemplate>\r\n <div class=\"modern-dialog-container\">\r\n <div mat-dialog-title class=\"preview-header\">\r\n <div class=\"header-info\">\r\n <div class=\"type-icon-wrapper\">\r\n <mat-icon>link</mat-icon>\r\n </div>\r\n <div class=\"title-group\">\r\n <span class=\"main-t\">Aggiungi un link</span>\r\n <span class=\"file-t\">Inserisci l'URL della risorsa web</span>\r\n </div>\r\n </div>\r\n <button mat-icon-button mat-dialog-close class=\"close-btn\">\r\n <mat-icon>close</mat-icon>\r\n </button>\r\n </div>\r\n\r\n <mat-dialog-content class=\"add-link-modern-content\">\r\n <form [formGroup]=\"newAttachmentForm\" class=\"add-link-form\">\r\n <mat-form-field appearance=\"outline\" class=\"w-100 mt-3\">\r\n <mat-label>URL del collegamento</mat-label>\r\n <input\r\n matInput\r\n formControlName=\"filePath\"\r\n placeholder=\"https://...\"\r\n required\r\n />\r\n <mat-icon matSuffix>language</mat-icon>\r\n </mat-form-field>\r\n\r\n <mat-form-field appearance=\"outline\" class=\"w-100\">\r\n <mat-label>Titolo (opzionale)</mat-label>\r\n <input\r\n matInput\r\n formControlName=\"fileName\"\r\n placeholder=\"Es. Documento Progetto\"\r\n />\r\n <mat-icon matSuffix>title</mat-icon>\r\n </mat-form-field>\r\n </form>\r\n </mat-dialog-content>\r\n\r\n <mat-dialog-actions align=\"end\" class=\"preview-actions\">\r\n <button mat-button mat-dialog-close class=\"btn-close\">Annulla</button>\r\n <button\r\n mat-raised-button\r\n color=\"primary\"\r\n [mat-dialog-close]=\"newAttachmentForm.value\"\r\n [disabled]=\"newAttachmentForm.invalid\"\r\n class=\"btn-download\"\r\n >\r\n <mat-icon>add</mat-icon> Aggiungi\r\n </button>\r\n </mat-dialog-actions>\r\n </div>\r\n</ng-template>\r\n", styles: ["@charset \"UTF-8\";:host{--primary-color: #6a5af9;--primary-color-dark: rgb(83.7807017544, 65.3947368421, 248.1052631579);--success-color: #1ce593;--error-color: #ff5b5b;--background-light: #f7f9fc;--background-card: rgba(255, 255, 255, .7);--text-color: #1e293b;--text-color-light: #64748b;--border-color: rgba(203, 213, 225, .5);--shadow-color: rgba(99, 102, 241, .2);--border-radius: 16px;--transition-speed: .3s}@keyframes fadeIn{0%{opacity:0;transform:translateY(15px)}to{opacity:1;transform:translateY(0)}}@keyframes pulse{0%{box-shadow:0 0 0 0 var(--primary-color)}70%{box-shadow:0 0 0 10px #6a5af900}to{box-shadow:0 0 #6a5af900}}.container{width:100%;max-width:700px;margin:2rem auto;font-family:Inter,sans-serif}.header{display:flex;justify-content:space-between;align-items:center;margin-bottom:2rem;padding-bottom:1.5rem;border-bottom:1px solid var(--border-color)}.header h1{color:var(--text-color);font-size:1.8rem;font-weight:700;margin:0}.dropbox{width:100%;border:2px dashed var(--border-color);border-radius:var(--border-radius);padding:2.5rem;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;cursor:pointer;background-color:var(--background-card);backdrop-filter:blur(10px);transition:all var(--transition-speed) ease}.dropbox:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color);border-color:var(--primary-color)}.dropbox.dragover{border-style:solid;border-color:var(--primary-color);transform:scale(1.02);box-shadow:0 0 25px var(--shadow-color);animation:pulse 1.5s infinite}.dropbox .dropbox-icon{font-size:3.5rem;color:var(--primary-color)}.dropbox .dropbox-text{font-size:1.1rem;font-weight:600;color:var(--text-color);margin-top:1rem}.dropbox .dropbox-subtext{color:var(--text-color-light);margin-top:.5rem}.dropbox .browse-btn{margin-top:1.5rem;padding:.75rem 1.5rem;background-color:var(--primary-color);color:#fff;border:none;border-radius:10px;font-weight:600;transition:all var(--transition-speed) ease}.dropbox .browse-btn:hover{background-color:var(--primary-color-dark);transform:translateY(-2px)}.file-previews{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:1.5rem;margin-top:2rem}.file-previews{display:grid;gap:16px;padding:16px;grid-template-columns:repeat(auto-fill,minmax(var(--card-min-width, 200px),1fr))}.file-preview{background-color:var(--background-card);border-radius:var(--border-radius);box-shadow:0 4px 15px #0000000d;border:1px solid var(--border-color);overflow:hidden;display:flex;flex-direction:column;position:relative;opacity:0;animation:fadeIn .5s ease-out forwards;transition:transform var(--transition-speed) ease,box-shadow var(--transition-speed) ease}.file-preview.uploading{cursor:wait}.file-preview.uploading .preview-img-container:after{content:\"\";position:absolute;inset:0;background:#ffffffb3;backdrop-filter:blur(5px);pointer-events:none}.file-preview .preview-action-overlay{position:absolute;inset:0;display:flex;justify-content:center;align-items:center;background-color:#0006;color:#fff;opacity:1;transition:opacity .3s ease}.file-preview .preview-action-overlay .mat-icon{font-size:36px;width:36px;height:36px}.file-preview .remove-btn{position:absolute;top:8px;right:8px;z-index:2;background-color:#0000004d;color:#fff;width:32px;height:32px;display:flex;align-items:center;justify-content:center;padding:0;transition:all var(--transition-speed) ease}.file-preview .remove-btn:hover{background-color:#ff5b5b}.file-preview .remove-btn .mat-icon{font-size:18px}@media(hover:hover){.file-preview .remove-btn .file-preview .preview-action-overlay{opacity:0}.file-preview .remove-btn .file-preview:hover .preview-action-overlay,.file-preview .remove-btn .file-preview:hover .remove-btn{opacity:1}.file-preview .remove-btn .file-preview .remove-btn{opacity:0}}@media(hover:hover)and (min-width:769px){.file-preview .remove-btn{opacity:0;transform:scale(.8)}.file-preview:hover{transform:translateY(-5px);box-shadow:0 10px 25px var(--shadow-color)}.file-preview:hover .remove-btn{opacity:1;transform:scale(1)}}.file-preview .preview-img-container{aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;position:relative;cursor:pointer;background-color:#f0f2f5}.file-preview .preview-img{width:100%;height:100%;object-fit:cover}.file-preview .file-icon{font-size:4rem;color:var(--primary-color)}.file-preview .file-info{padding:12px;border-top:1px solid var(--border-color);flex-grow:1;display:flex;align-items:center}.file-preview .file-name{font-weight:600;font-size:.9rem;color:var(--text-color);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.file-preview .upload-spinner{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:40px;height:40px;border:4px solid rgba(0,0,0,.1);border-left-color:var(--primary-color);border-radius:50%;animation:spin 1s linear infinite;pointer-events:none}.file-preview.card-small{width:140px}.file-preview.card-small .preview-img-container{height:80px}.file-preview.card-small .file-info{padding:8px}.file-preview.card-small .file-name{font-size:.8rem}.file-preview.card-small .file-icon{font-size:3rem}.file-preview.card-small .remove-btn{width:28px;height:28px}.file-preview.card-small .remove-btn .mat-icon{font-size:16px}.file-preview.card-large{width:280px}.file-preview.card-large .preview-img-container{height:180px}.file-preview.card-large .file-info{padding:16px}.file-preview.card-large .file-name{font-size:1rem}.file-preview.card-large .file-icon{font-size:5rem}.file-preview.card-large .remove-btn{width:36px;height:36px}.file-preview.card-large .remove-btn .mat-icon{font-size:20px}.file-preview[style*=--eqp-card-width]{width:var(--eqp-card-width)}.file-preview[style*=--eqp-card-width] .preview-img-container{height:calc(var(--eqp-card-width) * .65)}@keyframes spin{to{transform:translate(-50%,-50%) rotate(360deg)}}.upload-stats{background-color:var(--background-card);backdrop-filter:blur(10px);border:1px solid var(--border-color);border-radius:var(--border-radius);padding:1.5rem;margin-top:2rem;animation:fadeIn .5s ease-out}.upload-stats .stats-info{display:flex;justify-content:space-around}.upload-stats .progress-bar{height:10px;background-color:var(--border-color);border-radius:5px;overflow:hidden;margin-top:1rem}.upload-stats .progress-fill{height:100%;background:linear-gradient(90deg,var(--primary-color),var(--success-color));transition:width var(--transition-speed) ease-out;border-radius:5px}.upload-notification{position:fixed;bottom:20px;left:50%;transform:translate(-50%,100px);padding:1rem 1.5rem;border-radius:var(--border-radius);color:#fff;font-weight:600;box-shadow:0 10px 30px #0003;transition:transform var(--transition-speed) cubic-bezier(.175,.885,.32,1.275)}.upload-notification.show{transform:translate(-50%)}.upload-notification.success{background-color:var(--success-color)}.upload-notification.error{background-color:var(--error-color)}::ng-deep .cdk-overlay-pane.eqp-crop-dialog{transform:translateY(-4vh)}@media(max-width:600px){::ng-deep .cdk-overlay-pane.crop-dialog{width:auto!important}}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container .mdc-dialog__surface{border-radius:20px!important;padding:0!important;overflow:hidden!important;width:fit-content!important;min-width:350px!important;max-width:95vw!important;margin:0 auto;background-color:#fff!important}::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;display:flex;flex-direction:column}.modern-dialog-container{display:flex;flex-direction:column;width:100%;max-width:100%;height:100%;max-height:90vh;background:#fff;--preview-header-h: 66px;--preview-footer-h: 66px;--preview-padding-y: 30px}.modern-dialog-container .main-preview-media{display:block;max-width:100%;max-height:var(--media-max-h);width:auto;height:auto;object-fit:contain;border-radius:12px;background:#fff;padding:4px;box-shadow:0 10px 30px #00000014}.modern-dialog-container video.main-preview-media{width:min(100%,1100px);background:#000}.modern-dialog-container .iframe-container{width:min(100%,1100px);height:var(--media-max-h);display:flex;width:100%;max-width:1100px}.modern-dialog-container .preview-iframe-modern{width:100%;height:100%;border:0;border-radius:12px;background:#f8fafc}.modern-dialog-container .preview-header{flex:0 0 auto;flex-shrink:0;padding:14px 20px;display:flex;align-items:center;justify-content:flex-start;border-bottom:1px solid var(--border-color);background:#f8fafc;z-index:10;width:100%}.modern-dialog-container .preview-header .header-info{display:flex;align-items:center;justify-content:flex-start;gap:12px;flex:1 1 auto;min-width:0;text-align:left}.modern-dialog-container .preview-header .header-info .type-icon-wrapper{background:var(--primary-color);color:#fff;width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px var(--shadow-color)}.modern-dialog-container .preview-header .header-info .title-group{display:flex;flex-direction:column;align-items:flex-start;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .main-t{font-weight:800;color:var(--text-color);font-size:.95rem;line-height:1.2;text-align:left}.modern-dialog-container .preview-header .header-info .title-group .file-t{font-size:.75rem;color:var(--text-color-light);max-width:250px;overflow:hidden;text-overflow:ellipsis;text-align:left}.modern-dialog-container .preview-content-area{flex:1;background:#fff!important;display:flex;flex-direction:column;padding:15px 15px 22px!important;overflow:hidden!important;min-height:0;width:auto;--media-max-h: calc(90vh - var(--preview-header-h) - var(--preview-footer-h) - var(--preview-padding-y));width:100%}.modern-dialog-container .preview-content-area .crop-toolbar{flex-shrink:0;z-index:20;background:#0f172a14;backdrop-filter:blur(10px);padding:6px 16px;border-radius:30px;margin:0 auto 15px;display:flex;gap:8px;box-shadow:0 4px 12px #0000000d}.modern-dialog-container .preview-content-area .crop-toolbar button{color:var(--text-color)!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper{flex:1;width:100%;display:flex;justify-content:center;align-items:center;min-height:0;overflow:visible}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern{width:100%;height:100%;display:flex;justify-content:center;align-items:center;background:transparent;border-radius:12px;padding:0}.modern-dialog-container .preview-content-area .media-viewer-wrapper .crop-container-modern image-cropper{max-width:100%;max-height:100%;display:block}.modern-dialog-container .add-link-modern-content{flex:1;background:#fff;padding:24px!important}.modern-dialog-container .add-link-modern-content .add-link-form{display:flex;flex-direction:column;gap:10px}.modern-dialog-container .preview-actions{flex-shrink:0;padding:12px 24px;background:#f8fafc;border-top:1px solid #e2e8f0;margin:0}.modern-dialog-container .preview-actions .btn-download{border-radius:12px;font-weight:600;box-shadow:0 4px 12px var(--shadow-color)}@media(max-width:600px){.modern-dialog-container{max-height:95vh}.modern-dialog-container .preview-content-area{padding:10px!important}.modern-dialog-container .preview-content-area .media-viewer-wrapper video.main-preview-media{width:100%!important;max-height:55vh!important;border-radius:4px;box-shadow:none}.modern-dialog-container .preview-content-area .media-viewer-wrapper .iframe-container{height:50vh}.modern-dialog-container .preview-content-area .crop-toolbar{width:calc(100% - 20px);max-width:400px;margin-bottom:10px;padding:4px 8px;gap:4px;overflow-x:auto;justify-content:center;-webkit-overflow-scrolling:touch}.modern-dialog-container .preview-content-area .crop-toolbar::-webkit-scrollbar{display:none}.modern-dialog-container .preview-content-area .crop-toolbar{scrollbar-width:none}.modern-dialog-container .preview-content-area .crop-toolbar button{flex-shrink:0;transform:scale(.85);width:40px;height:40px}.modern-dialog-container .preview-actions{padding:10px 15px;flex-direction:column-reverse;gap:8px}.modern-dialog-container .preview-actions button{width:100%;margin:0!important}}@media(max-width:360px){.modern-dialog-container .preview-content-area .crop-toolbar{gap:2px}.modern-dialog-container .preview-content-area .crop-toolbar button{transform:scale(.75)}}.control-icon{font-size:28px;cursor:pointer}image-cropper,image-cropper canvas,image-cropper img{max-width:100%!important;max-height:100%!important}.crop-large{display:flex}.crop-small{display:none}@media(max-width:600px){.dialog-content{max-height:55vh}.crop-container{max-width:100%;aspect-ratio:auto}.crop-large{display:none}.crop-small{display:flex;justify-content:center;gap:14px}.control-icon{font-size:24px}}.stats-header{display:flex;justify-content:space-between;align-items:center;width:100%}.table-view-container{margin-top:1.5rem;background-color:var(--background-card);border-radius:var(--border-radius);border:1px solid var(--border-color);overflow:hidden;animation:fadeIn .5s ease-out}.table-header,.table-row{display:flex;align-items:center;padding:0 1rem;transition:background-color var(--transition-speed) ease}.table-header{background-color:#f8f9fa;font-weight:600;color:var(--text-color-light);font-size:.8rem;text-transform:uppercase;border-bottom:2px solid var(--border-color)}.table-row{border-bottom:1px solid var(--border-color)}.table-row:last-child{border-bottom:none}.table-row:hover{background-color:#00000005}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem}.name-col{flex:4}.size-col,.date-col{flex:2}.actions-col{flex:1;justify-content:flex-end;min-width:150px}.file-icon-small{font-size:1.5rem;color:var(--primary-color)}.file-info-text{display:flex;flex-direction:column}.file-name-table{font-weight:600;color:var(--text-color)}.file-type-table{font-size:.8rem;color:var(--text-color-light)}@media(max-width:768px){.date-col{display:none}.name-col{flex:3}.size-col{flex:2}.actions-col{flex:2;min-width:120px}}.secondary-action-link{color:var(--primary-color);text-decoration:none;border-bottom:1px solid var(--primary-color);cursor:pointer;font-weight:500}.secondary-action-link:hover{color:var(--primary-color-dark);border-bottom-color:var(--primary-color-dark)}h2[mat-dialog-title]+mat-dialog-content.add-link-dialog-content{padding-top:20px}mat-dialog-content.add-link-dialog-content{padding-left:24px;padding-right:24px;padding-bottom:20px}.add-link-form{display:flex;flex-direction:column;gap:16px}::ng-deep .eqp-attachments-preview-dialog{--mat-dialog-subhead-line-height: normal}::ng-deep .eqp-attachments-preview-dialog .mat-mdc-dialog-content{padding:0!important;margin:0!important;max-height:none!important;background:#fff!important}:host ::ng-deep .eqp-attachments-dialog .mat-mdc-dialog-container{--mat-dialog-subhead-size: 1.25rem;--mat-dialog-subhead-line-height: 1.5;--mat-dialog-subhead-weight: 600;--mat-dialog-supporting-text-size: 1rem}.empty-state{display:flex;flex-direction:column;justify-content:center;align-items:center;padding:1.5rem 1rem;margin-top:1.5rem;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#f8f9fa;text-align:center;color:var(--text-color-light);animation:fadeIn .5s ease-out}.empty-state:before{content:\"\\1f4ed\";font-size:2.5rem;margin-bottom:1rem;opacity:.7}.secondary-action-link.disabled-link{color:#adb5bd;cursor:not-allowed;border-bottom-color:transparent}.secondary-action-link.disabled-link:hover{color:#adb5bd;border-bottom-color:transparent}.table-cell{padding:1rem .5rem;display:flex;align-items:center;gap:1rem;min-width:0;overflow:hidden}.table-cell.col-actions{flex:0 0 150px;justify-content:flex-end;overflow:visible}.compact-uploader{display:flex;align-items:center;gap:16px;padding:16px;border:2px dashed var(--border-color);border-radius:var(--border-radius);background-color:#fcfdff;transition:all .3s ease}.compact-uploader .compact-text{flex:1 1 auto;min-width:0;cursor:pointer}.compact-uploader .compact-text:hover .compact-title{color:var(--primary-color)}.compact-uploader .compact-title{font-weight:600;color:var(--text-color);transition:color .3s ease}.compact-uploader .compact-subtitle{font-size:.8rem;color:var(--text-color-light);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.compact-uploader .compact-icon mat-icon{font-size:36px;width:36px;height:36px;color:var(--primary-color)}.compact-uploader .compact-actions{display:flex;gap:8px;flex-shrink:0}.compact-uploader.dragover{background-color:#f4f8ff;border-color:var(--primary-color);box-shadow:0 0 10px var(--shadow-color)}\n"] }]
|
|
1630
|
+
}], ctorParameters: () => [{ type: i1.MatDialog }, { type: i2.FormBuilder }, { type: i3.DomSanitizer }, { type: i4.HttpClient }, { type: EqpAttachmentService }], propDecorators: { disableAction: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableAction", required: false }] }], showHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "showHeader", required: false }] }], attachmentsList: [{
|
|
1575
1631
|
type: Input,
|
|
1576
1632
|
args: ["attachmentsList"]
|
|
1577
|
-
}], singleAttachment: [{
|
|
1578
|
-
type: Input,
|
|
1579
|
-
args: ["singleAttachment"]
|
|
1580
|
-
}], showMatCard: [{
|
|
1581
|
-
type: Input,
|
|
1582
|
-
args: ["showMatCard"]
|
|
1583
|
-
}], multipleAttachment: [{
|
|
1584
|
-
type: Input,
|
|
1585
|
-
args: ["multipleAttachment"]
|
|
1586
|
-
}], loadMultipleFiles: [{
|
|
1587
|
-
type: Input,
|
|
1588
|
-
args: ["loadMultipleFiles"]
|
|
1589
|
-
}], emptyTableMessage: [{
|
|
1590
|
-
type: Input,
|
|
1591
|
-
args: ["emptyTableMessage"]
|
|
1592
|
-
}], allowOnlyImages: [{
|
|
1593
|
-
type: Input,
|
|
1594
|
-
args: ["allowOnlyImages"]
|
|
1595
|
-
}], acceptedFileTypes: [{
|
|
1633
|
+
}], singleAttachment: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleAttachment", required: false }] }], showMatCard: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMatCard", required: false }] }], multipleAttachment: [{ type: i0.Input, args: [{ isSignal: true, alias: "multipleAttachment", required: false }] }], loadMultipleFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "loadMultipleFiles", required: false }] }], emptyTableMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyTableMessage", required: false }] }], allowOnlyImages: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowOnlyImages", required: false }] }], acceptedFileTypes: [{
|
|
1596
1634
|
type: Input,
|
|
1597
1635
|
args: ["acceptedFileTypes"]
|
|
1598
|
-
}], isDisabled: [{
|
|
1599
|
-
type: Input,
|
|
1600
|
-
args: ["isDisabled"]
|
|
1601
|
-
}], showInlinePreview: [{
|
|
1602
|
-
type: Input,
|
|
1603
|
-
args: ["showInlinePreview"]
|
|
1604
|
-
}], getAttachmentEndpoint: [{
|
|
1605
|
-
type: Input,
|
|
1606
|
-
args: ["getAttachmentEndpoint"]
|
|
1607
|
-
}], productionBaseUrl: [{
|
|
1608
|
-
type: Input,
|
|
1609
|
-
args: ["productionBaseUrl"]
|
|
1610
|
-
}], compressionOptions: [{
|
|
1611
|
-
type: Input,
|
|
1612
|
-
args: ["compressionOptions"]
|
|
1613
|
-
}], allowedTypes: [{
|
|
1636
|
+
}], isDisabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "isDisabled", required: false }] }], showInlinePreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showInlinePreview", required: false }] }], getAttachmentEndpoint: [{ type: i0.Input, args: [{ isSignal: true, alias: "getAttachmentEndpoint", required: false }] }], productionBaseUrl: [{ type: i0.Input, args: [{ isSignal: true, alias: "productionBaseUrl", required: false }] }], compressionOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "compressionOptions", required: false }] }], allowedTypes: [{
|
|
1614
1637
|
type: Input,
|
|
1615
1638
|
args: ["allowedTypes"]
|
|
1616
|
-
}], isEqpTableMultiLanguage: [{
|
|
1617
|
-
type: Input,
|
|
1618
|
-
args: ["isEqpTableMultiLanguage"]
|
|
1619
|
-
}], tablePaginatorVisible: [{
|
|
1620
|
-
type: Input,
|
|
1621
|
-
args: ["tablePaginatorVisible"]
|
|
1622
|
-
}], isTableSearcheable: [{
|
|
1623
|
-
type: Input,
|
|
1624
|
-
args: ["isTableSearcheable"]
|
|
1625
|
-
}], tablePaginatorSize: [{
|
|
1626
|
-
type: Input,
|
|
1627
|
-
args: ["tablePaginatorSize"]
|
|
1628
|
-
}], separatedUploadButtons: [{
|
|
1629
|
-
type: Input,
|
|
1630
|
-
args: ["separatedUploadButtons"]
|
|
1631
|
-
}], showPreview: [{
|
|
1632
|
-
type: Input,
|
|
1633
|
-
args: ["showPreview"]
|
|
1634
|
-
}], singleAttachmentDragAndDrop: [{
|
|
1635
|
-
type: Input,
|
|
1636
|
-
args: ["singleAttachmentDragAndDrop"]
|
|
1637
|
-
}], cropOptions: [{
|
|
1638
|
-
type: Input,
|
|
1639
|
-
args: ["cropOptions"]
|
|
1640
|
-
}], cropDialogClass: [{
|
|
1641
|
-
type: Input,
|
|
1642
|
-
args: ["cropDialogClass"]
|
|
1643
|
-
}], maxFileSizeMB: [{
|
|
1644
|
-
type: Input
|
|
1645
|
-
}], cardSize: [{
|
|
1646
|
-
type: Input
|
|
1647
|
-
}], customCardWidthPx: [{
|
|
1648
|
-
type: Input
|
|
1649
|
-
}], customCardHeightPx: [{
|
|
1650
|
-
type: Input
|
|
1651
|
-
}], layout: [{
|
|
1652
|
-
type: Input
|
|
1653
|
-
}], openLinkLabel: [{
|
|
1654
|
-
type: Input,
|
|
1655
|
-
args: ["openLinkLabel"]
|
|
1656
|
-
}], addButtonLabel: [{
|
|
1657
|
-
type: Input,
|
|
1658
|
-
args: ["addButtonLabel"]
|
|
1659
|
-
}], downloadLabel: [{
|
|
1660
|
-
type: Input,
|
|
1661
|
-
args: ["downloadLabel"]
|
|
1662
|
-
}], deleteLabel: [{
|
|
1663
|
-
type: Input,
|
|
1664
|
-
args: ["deleteLabel"]
|
|
1665
|
-
}], fileNameLabel: [{
|
|
1666
|
-
type: Input,
|
|
1667
|
-
args: ["fileNameLabel"]
|
|
1668
|
-
}], previewLabel: [{
|
|
1669
|
-
type: Input,
|
|
1670
|
-
args: ["previewLabel"]
|
|
1671
|
-
}], uploadFileLabel: [{
|
|
1672
|
-
type: Input,
|
|
1673
|
-
args: ["uploadFileLabel"]
|
|
1674
|
-
}], confirmLabel: [{
|
|
1675
|
-
type: Input,
|
|
1676
|
-
args: ["confirmLabel"]
|
|
1677
|
-
}], abortLabel: [{
|
|
1678
|
-
type: Input,
|
|
1679
|
-
args: ["abortLabel"]
|
|
1680
|
-
}], saveLabel: [{
|
|
1681
|
-
type: Input,
|
|
1682
|
-
args: ["saveLabel"]
|
|
1683
|
-
}], exitLabel: [{
|
|
1684
|
-
type: Input,
|
|
1685
|
-
args: ["exitLabel"]
|
|
1686
|
-
}], uploadWithDropboxLabel: [{
|
|
1687
|
-
type: Input,
|
|
1688
|
-
args: ["uploadWithDropboxLabel"]
|
|
1689
|
-
}], cropLabel: [{
|
|
1690
|
-
type: Input,
|
|
1691
|
-
args: ["cropLabel"]
|
|
1692
|
-
}], deleteDialogTitle: [{
|
|
1693
|
-
type: Input,
|
|
1694
|
-
args: ["deleteDialogTitle"]
|
|
1695
|
-
}], deleteDialogMessage: [{
|
|
1696
|
-
type: Input,
|
|
1697
|
-
args: ["deleteDialogMessage"]
|
|
1698
|
-
}], noImageSelectedErrorMessage: [{
|
|
1699
|
-
type: Input,
|
|
1700
|
-
args: ["noImageSelectedErrorMessage"]
|
|
1701
|
-
}], wrongTypeSelectedErrorMessage: [{
|
|
1702
|
-
type: Input,
|
|
1703
|
-
args: ["wrongTypeSelectedErrorMessage"]
|
|
1704
|
-
}], videoPreviewErrorMessage: [{
|
|
1705
|
-
type: Input,
|
|
1706
|
-
args: ["videoPreviewErrorMessage"]
|
|
1707
|
-
}], audioPreviewErrorMessage: [{
|
|
1708
|
-
type: Input,
|
|
1709
|
-
args: ["videoPreviewErrorMessage"]
|
|
1710
|
-
}], flipHorinzontalLabel: [{
|
|
1711
|
-
type: Input,
|
|
1712
|
-
args: ["flipHorinzontalLabel"]
|
|
1713
|
-
}], flipVerticalLabel: [{
|
|
1714
|
-
type: Input,
|
|
1715
|
-
args: ["flipVerticalLabel"]
|
|
1716
|
-
}], rotateRightLabel: [{
|
|
1717
|
-
type: Input,
|
|
1718
|
-
args: ["rotateRightLabel"]
|
|
1719
|
-
}], rotateLeftLabel: [{
|
|
1720
|
-
type: Input,
|
|
1721
|
-
args: ["rotateLeftLabel"]
|
|
1722
|
-
}], base64LimitMB: [{
|
|
1723
|
-
type: Input,
|
|
1724
|
-
args: ["base64LimitMB"]
|
|
1725
|
-
}], uploadTitle: [{
|
|
1726
|
-
type: Input
|
|
1727
|
-
}], uploadSubtitle: [{
|
|
1728
|
-
type: Input
|
|
1729
|
-
}], dropHereLabel: [{
|
|
1730
|
-
type: Input
|
|
1731
|
-
}], supportedFormatsLabel: [{
|
|
1732
|
-
type: Input
|
|
1733
|
-
}], browseFilesLabel: [{
|
|
1734
|
-
type: Input
|
|
1735
|
-
}], uploadSummaryLabel: [{
|
|
1736
|
-
type: Input
|
|
1737
|
-
}], filesLabel: [{
|
|
1738
|
-
type: Input
|
|
1739
|
-
}], totalSizeLabel: [{
|
|
1740
|
-
type: Input
|
|
1741
|
-
}], emptyStateLabel: [{
|
|
1742
|
-
type: Input
|
|
1743
|
-
}], addedSuccessfullyLabel: [{
|
|
1744
|
-
type: Input
|
|
1745
|
-
}], removedLabel: [{
|
|
1746
|
-
type: Input
|
|
1747
|
-
}], chooseView: [{
|
|
1748
|
-
type: Input
|
|
1749
|
-
}], showSummary: [{
|
|
1750
|
-
type: Input
|
|
1751
|
-
}], viewMode: [{
|
|
1639
|
+
}], isEqpTableMultiLanguage: [{ type: i0.Input, args: [{ isSignal: true, alias: "isEqpTableMultiLanguage", required: false }] }], tablePaginatorVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "tablePaginatorVisible", required: false }] }], isTableSearcheable: [{ type: i0.Input, args: [{ isSignal: true, alias: "isTableSearcheable", required: false }] }], tablePaginatorSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "tablePaginatorSize", required: false }] }], separatedUploadButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "separatedUploadButtons", required: false }] }], showPreview: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPreview", required: false }] }], singleAttachmentDragAndDrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "singleAttachmentDragAndDrop", required: false }] }], cropOptions: [{ type: i0.Input, args: [{ isSignal: true, alias: "cropOptions", required: false }] }], cropDialogClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "cropDialogClass", required: false }] }], maxFileSizeMB: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFileSizeMB", required: false }] }], cardSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "cardSize", required: false }] }], customCardWidthPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "customCardWidthPx", required: false }] }], customCardHeightPx: [{ type: i0.Input, args: [{ isSignal: true, alias: "customCardHeightPx", required: false }] }], layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], openLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "openLinkLabel", required: false }] }], addButtonLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addButtonLabel", required: false }] }], downloadLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "downloadLabel", required: false }] }], deleteLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteLabel", required: false }] }], fileNameLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "fileNameLabel", required: false }] }], previewLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "previewLabel", required: false }] }], uploadFileLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadFileLabel", required: false }] }], confirmLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "confirmLabel", required: false }] }], abortLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "abortLabel", required: false }] }], saveLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "saveLabel", required: false }] }], exitLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "exitLabel", required: false }] }], uploadWithDropboxLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadWithDropboxLabel", required: false }] }], cropLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "cropLabel", required: false }] }], deleteDialogTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteDialogTitle", required: false }] }], deleteDialogMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "deleteDialogMessage", required: false }] }], noImageSelectedErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "noImageSelectedErrorMessage", required: false }] }], wrongTypeSelectedErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "wrongTypeSelectedErrorMessage", required: false }] }], videoPreviewErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "videoPreviewErrorMessage", required: false }] }], audioPreviewErrorMessage: [{ type: i0.Input, args: [{ isSignal: true, alias: "videoPreviewErrorMessage", required: false }] }], flipHorinzontalLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "flipHorinzontalLabel", required: false }] }], flipVerticalLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "flipVerticalLabel", required: false }] }], rotateRightLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rotateRightLabel", required: false }] }], rotateLeftLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "rotateLeftLabel", required: false }] }], base64LimitMB: [{ type: i0.Input, args: [{ isSignal: true, alias: "base64LimitMB", required: false }] }], uploadTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadTitle", required: false }] }], uploadSubtitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadSubtitle", required: false }] }], dropHereLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropHereLabel", required: false }] }], supportedFormatsLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "supportedFormatsLabel", required: false }] }], browseFilesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "browseFilesLabel", required: false }] }], uploadSummaryLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "uploadSummaryLabel", required: false }] }], filesLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "filesLabel", required: false }] }], totalSizeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "totalSizeLabel", required: false }] }], emptyStateLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "emptyStateLabel", required: false }] }], addedSuccessfullyLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "addedSuccessfullyLabel", required: false }] }], removedLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removedLabel", required: false }] }], chooseView: [{ type: i0.Input, args: [{ isSignal: true, alias: "chooseView", required: false }] }], showSummary: [{ type: i0.Input, args: [{ isSignal: true, alias: "showSummary", required: false }] }], viewMode: [{
|
|
1752
1640
|
type: Input,
|
|
1753
1641
|
args: ["viewMode"]
|
|
1754
|
-
}], showUploadTitle: [{
|
|
1755
|
-
type: Input,
|
|
1756
|
-
args: ["showUploadTitle"]
|
|
1757
|
-
}], showDropArea: [{
|
|
1758
|
-
type: Input,
|
|
1759
|
-
args: ["showDropArea"]
|
|
1760
|
-
}], hiddenColumns: [{
|
|
1761
|
-
type: Input
|
|
1762
|
-
}], hiddenActions: [{
|
|
1763
|
-
type: Input
|
|
1764
|
-
}], showActionButtons: [{
|
|
1765
|
-
type: Input
|
|
1766
|
-
}], enableImageCrop: [{
|
|
1767
|
-
type: Input,
|
|
1768
|
-
args: ["enableImageCrop"]
|
|
1769
|
-
}], actionHiddenFn: [{
|
|
1770
|
-
type: Input
|
|
1771
|
-
}], actionDisabledFn: [{
|
|
1772
|
-
type: Input
|
|
1773
|
-
}], videoCompression: [{
|
|
1774
|
-
type: Input
|
|
1775
|
-
}], customMenuActions: [{
|
|
1776
|
-
type: Input
|
|
1777
|
-
}], customColumns: [{
|
|
1778
|
-
type: Input
|
|
1779
|
-
}], localEditedAttachments: [{
|
|
1780
|
-
type: Output
|
|
1781
|
-
}], abortAddAttachment: [{
|
|
1782
|
-
type: Output
|
|
1783
|
-
}], downloadAttachment: [{
|
|
1784
|
-
type: Output,
|
|
1785
|
-
args: ["downloadAttachment"]
|
|
1786
|
-
}], onDeleteAttachment: [{
|
|
1787
|
-
type: Output,
|
|
1788
|
-
args: ["onDeleteAttachment"]
|
|
1789
|
-
}], dialogAddAttachment: [{
|
|
1790
|
-
type: ViewChild,
|
|
1791
|
-
args: ["dialogAddAttachment", { static: true }]
|
|
1792
|
-
}], dialogAddMultipleAttachment: [{
|
|
1793
|
-
type: ViewChild,
|
|
1794
|
-
args: ["dialogAddMultipleAttachment", { static: true }]
|
|
1795
|
-
}], dialogCropImage: [{
|
|
1796
|
-
type: ViewChild,
|
|
1797
|
-
args: ["dialogCropImage", { static: true }]
|
|
1798
|
-
}], addingLinkTemplate: [{
|
|
1799
|
-
type: ViewChild,
|
|
1800
|
-
args: ['addingLinkTemplate']
|
|
1801
|
-
}], imageCropper: [{
|
|
1802
|
-
type: ViewChild,
|
|
1803
|
-
args: [ImageCropperComponent]
|
|
1804
|
-
}], imageInput: [{
|
|
1805
|
-
type: ViewChild,
|
|
1806
|
-
args: ["imageInput"]
|
|
1807
|
-
}], inlinePreviewTemplate: [{
|
|
1808
|
-
type: ViewChild,
|
|
1809
|
-
args: ["inlinePreviewTemplate", { static: true }]
|
|
1810
|
-
}], dialogPreview: [{
|
|
1811
|
-
type: ViewChild,
|
|
1812
|
-
args: ["dialogPreview", { static: true }]
|
|
1813
|
-
}], defaultFileTemplate: [{
|
|
1814
|
-
type: ViewChild,
|
|
1815
|
-
args: ['defaultFileTemplate', { static: true }]
|
|
1816
|
-
}], defaultActionsTemplate: [{
|
|
1817
|
-
type: ViewChild,
|
|
1818
|
-
args: ['defaultActionsTemplate', { static: true }]
|
|
1819
|
-
}] } });
|
|
1642
|
+
}], showUploadTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "showUploadTitle", required: false }] }], showDropArea: [{ type: i0.Input, args: [{ isSignal: true, alias: "showDropArea", required: false }] }], hiddenColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenColumns", required: false }] }], hiddenActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "hiddenActions", required: false }] }], showActionButtons: [{ type: i0.Input, args: [{ isSignal: true, alias: "showActionButtons", required: false }] }], enableImageCrop: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableImageCrop", required: false }] }], actionHiddenFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionHiddenFn", required: false }] }], actionDisabledFn: [{ type: i0.Input, args: [{ isSignal: true, alias: "actionDisabledFn", required: false }] }], videoCompression: [{ type: i0.Input, args: [{ isSignal: true, alias: "videoCompression", required: false }] }], customMenuActions: [{ type: i0.Input, args: [{ isSignal: true, alias: "customMenuActions", required: false }] }], customColumns: [{ type: i0.Input, args: [{ isSignal: true, alias: "customColumns", required: false }] }], localEditedAttachments: [{ type: i0.Output, args: ["localEditedAttachments"] }], abortAddAttachment: [{ type: i0.Output, args: ["abortAddAttachment"] }], downloadAttachment: [{ type: i0.Output, args: ["downloadAttachment"] }], onDeleteAttachment: [{ type: i0.Output, args: ["onDeleteAttachment"] }], dialogAddAttachment: [{ type: i0.ViewChild, args: ["dialogAddAttachment", { isSignal: true }] }], dialogAddMultipleAttachment: [{ type: i0.ViewChild, args: ["dialogAddMultipleAttachment", { isSignal: true }] }], dialogCropImage: [{ type: i0.ViewChild, args: ["dialogCropImage", { isSignal: true }] }], addingLinkTemplate: [{ type: i0.ViewChild, args: ["addingLinkTemplate", { isSignal: true }] }], imageCropper: [{ type: i0.ViewChild, args: [i0.forwardRef(() => ImageCropperComponent), { isSignal: true }] }], imageInput: [{ type: i0.ViewChild, args: ["imageInput", { isSignal: true }] }], inlinePreviewTemplate: [{ type: i0.ViewChild, args: ["inlinePreviewTemplate", { isSignal: true }] }], dialogPreview: [{ type: i0.ViewChild, args: ["dialogPreview", { isSignal: true }] }], defaultFileTemplate: [{ type: i0.ViewChild, args: ["defaultFileTemplate", { isSignal: true }] }], defaultActionsTemplate: [{ type: i0.ViewChild, args: ["defaultActionsTemplate", { isSignal: true }] }] } });
|
|
1820
1643
|
|
|
1821
1644
|
class MaterialModule {
|
|
1822
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
1823
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
1645
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MaterialModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1646
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.5", ngImport: i0, type: MaterialModule, imports: [MatCheckboxModule,
|
|
1824
1647
|
MatButtonModule,
|
|
1825
1648
|
MatInputModule,
|
|
1826
1649
|
MatAutocompleteModule,
|
|
@@ -1881,7 +1704,7 @@ class MaterialModule {
|
|
|
1881
1704
|
MatTableModule,
|
|
1882
1705
|
MatSortModule,
|
|
1883
1706
|
MatPaginatorModule] });
|
|
1884
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
1707
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MaterialModule, imports: [MatCheckboxModule,
|
|
1885
1708
|
MatButtonModule,
|
|
1886
1709
|
MatInputModule,
|
|
1887
1710
|
MatAutocompleteModule,
|
|
@@ -1943,7 +1766,7 @@ class MaterialModule {
|
|
|
1943
1766
|
MatSortModule,
|
|
1944
1767
|
MatPaginatorModule] });
|
|
1945
1768
|
}
|
|
1946
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1769
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: MaterialModule, decorators: [{
|
|
1947
1770
|
type: NgModule,
|
|
1948
1771
|
args: [{
|
|
1949
1772
|
imports: [
|
|
@@ -2016,19 +1839,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImpo
|
|
|
2016
1839
|
}] });
|
|
2017
1840
|
|
|
2018
1841
|
class EqpAttachmentsModule {
|
|
2019
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2020
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
1842
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
1843
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentsModule, declarations: [EqpAttachmentsComponent], imports: [MaterialModule,
|
|
2021
1844
|
FormsModule,
|
|
2022
1845
|
CommonModule,
|
|
2023
1846
|
ReactiveFormsModule,
|
|
2024
1847
|
ImageCropperComponent], exports: [EqpAttachmentsComponent] });
|
|
2025
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
1848
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentsModule, imports: [MaterialModule,
|
|
2026
1849
|
FormsModule,
|
|
2027
1850
|
CommonModule,
|
|
2028
1851
|
ReactiveFormsModule,
|
|
2029
1852
|
ImageCropperComponent] });
|
|
2030
1853
|
}
|
|
2031
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
1854
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.5", ngImport: i0, type: EqpAttachmentsModule, decorators: [{
|
|
2032
1855
|
type: NgModule,
|
|
2033
1856
|
args: [{
|
|
2034
1857
|
declarations: [EqpAttachmentsComponent],
|