@esfaenza/extensions 15.2.24 → 15.2.26

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.
@@ -3,10 +3,11 @@ import { InjectionToken, Injectable, Optional, Inject, Pipe, NgModule, Injector
3
3
  import * as i1 from '@esfaenza/localizations';
4
4
  import { LocalizationModule } from '@esfaenza/localizations';
5
5
  import { __awaiter } from 'tslib';
6
- import { first, map } from 'rxjs/operators';
7
- import swal from 'sweetalert2';
8
- import { ToastrService } from 'ngx-toastr';
6
+ import { first, filter, take, map } from 'rxjs/operators';
9
7
  import { of, Subject } from 'rxjs';
8
+ import { ToastrService } from 'ngx-toastr';
9
+ import swal from 'sweetalert2';
10
+ import * as i2 from '@angular/router';
10
11
 
11
12
  /**
12
13
  * Token che indica il prefisso delle searchView che serve per storicizzarle evitando di tirarsi in memoria anche tutti gli oggetti. Se vuoto viene supposto 'Hot'
@@ -316,921 +317,738 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
316
317
  }]
317
318
  }] });
318
319
 
319
- /**
320
- * Suffisso della proprietà da generare in cui salvare il navigatore
321
- * utilizzato dal servizio di esportazione per prendere il valore delle proprietà di un oggetto
322
- */
323
- const csvValueNavigator = "_csvnav";
324
- /** Suffisso con le informazioni del tipo per le esportazioni di oggetti */
325
- const csvValueType = "_csvtype";
326
- /** Suffisso della proprietà da generare in cui salvare l'ordine di esportazione */
327
- const csvOrdPrefix = "_csvord";
328
- /** Suffisso della proprietà da generare in cui salvare la visibilità di questa proprietà */
329
- const csvVisPrefix = "_csvvis";
330
- /** Suffisso della proprietà da generare in cui salvare il nome della colonna in cui salvare questa proprietà */
331
- const csvHdrPrefix = "_csvhdr";
332
- /** Suffisso della proprietà da generare in cui salvare il codice del th a cui si riferisce questo campo */
333
- const csvPropKey = "_csvkey";
334
- /** Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Lista */
335
- const listCsvValPrefix = "_listcsvval";
336
- /** Suffisso della proprietà da generare in cui salvare l'Header della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix** */
337
- const listCsvHdrPrefix = "_listcsvhdr";
338
- /** Suffisso della proprietà da generare in cui salvare il formato della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix** */
339
- const listCsvValFormat = "_listcsvvalformat";
340
- /** Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Dizionario */
341
- const dictionaryCsvValPrefix = "_flatlistcsvval";
342
- /** Suffisso della proprietà da generare in cui salvare l'Header della proprietà di un Dizionario relativo al valore esportato nella proprietà con suffisso **dictionaryCsvValPrefix** */
343
- const dictionaryCsvHdrPrefix = "_flatlistcsvhdr";
344
- /** Suffisso della proprietà da generare in cui salvare il formato della proprietà che si sta esportando */
345
- const csvFormatPrefix = "_csvfmt";
346
- /** Nome della proprietà che contiene tutti i nomi di tutte le proprietà da esportare */
347
- const exportList = "__export_list__";
348
- /** Nome della proprietà che contiene la classe di localizzazione da utilizzare per una data esportazione */
349
- const locProperty = "__loc__";
350
-
351
- /**
352
- * Mappatura del TypeCode del C#
353
- */
354
- var TypeCode;
355
- (function (TypeCode) {
356
- /** @ignore */ TypeCode[TypeCode["Empty"] = 0] = "Empty";
357
- /** @ignore */ TypeCode[TypeCode["Obj"] = 1] = "Obj";
358
- /** @ignore */ TypeCode[TypeCode["DBNull"] = 2] = "DBNull";
359
- /** @ignore */ TypeCode[TypeCode["Boolean"] = 3] = "Boolean";
360
- /** @ignore */ TypeCode[TypeCode["Char"] = 4] = "Char";
361
- /** @ignore */ TypeCode[TypeCode["SByte"] = 5] = "SByte";
362
- /** @ignore */ TypeCode[TypeCode["Byte"] = 6] = "Byte";
363
- /** @ignore */ TypeCode[TypeCode["Int16"] = 7] = "Int16";
364
- /** @ignore */ TypeCode[TypeCode["UInt16"] = 8] = "UInt16";
365
- /** @ignore */ TypeCode[TypeCode["Int32"] = 9] = "Int32";
366
- /** @ignore */ TypeCode[TypeCode["UInt32"] = 10] = "UInt32";
367
- /** @ignore */ TypeCode[TypeCode["Int64"] = 11] = "Int64";
368
- /** @ignore */ TypeCode[TypeCode["UInt64"] = 12] = "UInt64";
369
- /** @ignore */ TypeCode[TypeCode["Single"] = 13] = "Single";
370
- /** @ignore */ TypeCode[TypeCode["Double"] = 14] = "Double";
371
- /** @ignore */ TypeCode[TypeCode["Decimal"] = 15] = "Decimal";
372
- /** @ignore */ TypeCode[TypeCode["DateTime"] = 16] = "DateTime";
373
- /** @ignore */ TypeCode[TypeCode["String"] = 18] = "String";
374
- })(TypeCode || (TypeCode = {}));
375
-
376
320
  // Angular
377
321
  /**
378
- * Service che fornisce metodi di pubblica utilità
322
+ * Service che fornisce alcuni semplici funzioni di Hashing / GUID / ecc...
379
323
  */
380
- class UtilityService {
381
- /**
382
- * Deseleziona il testo eventualmente selezionato
383
- */
384
- clearTextSelection() {
385
- if (window.getSelection) {
386
- if (window.getSelection().empty) // Chrome
387
- window.getSelection().empty();
388
- else if (window.getSelection().removeAllRanges) // Firefox
389
- window.getSelection().removeAllRanges();
390
- }
391
- else if (document.selection) // IE?
392
- document.selection.empty();
324
+ class HashingService {
325
+ constructor() {
326
+ /**
327
+ * Blacklist dei tipi da ignorare quando si effettua l'hashing degli oggetti
328
+ */
329
+ this.objBlacklist = {
330
+ "NgForm": true, "ElementRef": true, "ExtensionsService": true, "ToastrService": true, "LocaleService": true, "AppState": true, "Router": true,
331
+ "ActivatedRoute": true, "HTTPService": true, "Location": true, "CanvasComponent": true, "ModalDirective": true, "ChangeDetectorRef": true,
332
+ "DateService": true, "EventEmitter": true, "ViewRef_": true, "Subscriber": true, "ItemLocalization": true
333
+ };
334
+ /**
335
+ * Array dei possibili valori di un simbolo esadecimale
336
+ */
337
+ this.hex_chr = '0123456789abcdef'.split('');
393
338
  }
394
339
  /**
395
- * Partendo da una lista, dato il nome della proprietà chiave e il valore della chiave selezionata,
396
- * trova e restituisce l'oggetto desiderato
397
- *
398
- * @param {T[]} sourceList Lista di oggetti dentro cui cercare
399
- * @param {string} sourceItemIdField Nome della proprietà che rappresenta la chiave di un oggetto di tipo T
400
- * @param {string} selectedValue Valore di chiave selezionato
340
+ * Generazione di un GUID pseudo-univoco
401
341
  *
402
- * @returns {T} Oggetto la cui proprietà **sourceItemIdField** assume il valore **selectedValue**
342
+ * @returns {string} il GUID generato
403
343
  */
404
- getSelectedItem(sourceList, sourceItemIdField, selectedValue) {
405
- for (let i = 0; i < sourceList.length; i++) {
406
- var item = sourceList[i];
407
- if (item[sourceItemIdField] == selectedValue)
408
- return item;
409
- }
410
- return null;
344
+ getGUID() {
345
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
346
+ var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);
347
+ return v.toString(16);
348
+ });
411
349
  }
412
350
  /**
413
- * Effettua il reset di un Form di Angular
351
+ * Calcolo dell'hash su un oggetto
414
352
  *
415
- * @param {NgForm} form Form da resettare
416
- * @param {string} exception1 Campo da non resettare
417
- * @param {string} exception2 Campo da non resettare
418
- */
419
- cleanForm(form, exception1 = null, exception2 = null) {
420
- for (let name in form.controls) {
421
- if (name && name != exception1 && name != exception1 + "_internal" && name != exception2 && name != exception2 + "_internal") {
422
- form.controls[name].reset();
423
- }
424
- else {
425
- form.controls[name].markAsPristine();
426
- form.controls[name].markAsUntouched();
427
- }
428
- }
429
- //Reimposto il submitted
430
- form.submitted = false;
431
- }
432
- /**
433
- * Helper che permette di scaricare un file dato un URL (Generato da una chiamata ad **window.URL.createObjectURL**)
353
+ * @param {any} o Oggetto di cui calcolare l'hash
354
+ * @param {number} level Livello di ricorsione nel caso venga effettuato l'hash di un oggetto che contiene altri oggetti
355
+ * @param {boolean} navigateFullDepth Indica se navigare l'oggetto per l'intera lunghezza. In caso contrario si ferma al secondo livello
434
356
  *
435
- * @param {string} url ObjectURL che rappresenta il file da scaricare
436
- * @param {string} filename Nome del file suggerito in fase di salvataggio
357
+ * @returns {string} Hash generato per l'oggetto in questione
437
358
  */
438
- fileDownload(url, fileName) {
439
- var a = document.createElement("a");
440
- document.body.appendChild(a);
441
- a.className = "ta-display-none";
442
- a.href = url;
443
- a.download = fileName;
444
- a.click();
445
- window.URL.revokeObjectURL(url);
446
- document.body.removeChild(a);
359
+ hashObject(o, level = 0, navigateFullDepth = false, precise = false) {
360
+ var strDef = this.stringify(o, level, navigateFullDepth);
361
+ var hash = precise ? this.md5(strDef) : this.simpleHash(strDef);
362
+ return hash;
447
363
  }
448
364
  /**
449
- * Helper per la formattazione di un numero di millisecondi in una stringa più comprensibile per un umano
365
+ * Hash più semplice e più veloce dell'md5, ma meno sicuro
450
366
  *
451
- * @param {number} duration Tempo espresso in millisecondi
367
+ * Vedi https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
452
368
  *
453
- * @returns {string} Durata formattata
369
+ * @param {string} str Stringa di cui calcolare l'hash
454
370
  */
455
- msToTime(duration) {
456
- if (!duration)
457
- return "";
458
- var milliseconds = parseInt(((duration % 1000) / 100).toString()), seconds = parseInt(((duration / 1000) % 60).toString()), minutes = parseInt(((duration / (1000 * 60)) % 60).toString()), hours = parseInt(((duration / (1000 * 60 * 60)) % 24).toString());
459
- var st_hours = (hours < 10) ? "0" + hours : hours;
460
- var st_minutes = (minutes < 10) ? "0" + minutes : minutes;
461
- var st_seconds = (seconds < 10) ? "0" + seconds : seconds;
462
- return st_hours + ":" + st_minutes + ":" + st_seconds + "." + milliseconds;
371
+ simpleHash(str, seed = 0) {
372
+ let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
373
+ for (let i = 0, ch; i < str.length; i++) {
374
+ ch = str.charCodeAt(i);
375
+ h1 = Math.imul(h1 ^ ch, 2654435761);
376
+ h2 = Math.imul(h2 ^ ch, 1597334677);
377
+ }
378
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
379
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
380
+ return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString();
463
381
  }
464
382
  /**
465
- * Helper che permette di scaricare un file in Base64
383
+ * Genera una stringa che identifica univocamente l'oggetto in questione
466
384
  *
467
- * @param {string} base64Data Base64 che rappresenta il file da scaricare
468
- * @param {string} filename Nome del file suggerito in fase di salvataggio
385
+ * @param {any} o Oggetto di cui calcolare la stringa univoca
386
+ * @param {number} level Livello di ricorsione nel caso venga effettuato l'hash di un oggetto che contiene altri oggetti
387
+ * @param {boolean} navigateFullDepth Indica se navigare l'oggetto per l'intera lunghezza. In caso contrario si ferma al secondo livello
469
388
  */
470
- saveFile(base64Data, filename) {
471
- var sampleArr = this.base64ToArrayBuffer(base64Data);
472
- this.saveByteArray(sampleArr, filename);
389
+ stringify(o, level, navigateFullDepth) {
390
+ var i, r;
391
+ if (o === null)
392
+ return "n";
393
+ if (o === true)
394
+ return "t";
395
+ if (o === false)
396
+ return "f";
397
+ if (o instanceof Date)
398
+ return 'd:' + o.valueOf().toString();
399
+ i = typeof o;
400
+ if (i === "string")
401
+ return "s:" + o;
402
+ if (i === "number")
403
+ return "n:" + o;
404
+ if (o instanceof Function)
405
+ return "m:" + o.toString();
406
+ if (o instanceof Array) {
407
+ r = [];
408
+ for (i = 0; i < o.length; i++) {
409
+ let res = this.stringify(o[i], level, navigateFullDepth);
410
+ if (res)
411
+ r.push(res);
412
+ }
413
+ return r.length > 0 ? "a:" + r.join(";") : "";
414
+ }
415
+ r = [];
416
+ //Se è oggetto, escludo tutti quelli di sistema/inutili
417
+ if (o) {
418
+ var name = o.__proto__.constructor.name;
419
+ if (!this.objBlacklist[name]) {
420
+ for (i in o) {
421
+ if (o.hasOwnProperty(i) && (level <= 2 || navigateFullDepth)) {
422
+ let res = this.stringify(o[i], level + 1, navigateFullDepth);
423
+ if (res)
424
+ r.push(i + ":" + res);
425
+ }
426
+ }
427
+ }
428
+ }
429
+ return r.length > 0 ? "o:" + r.join(";") : "";
473
430
  }
474
431
  /**
475
- * Trasforma un Base64 in un ArrayBuffer
476
- *
477
- * @param {string} base64Data Base64 da trasformare
432
+ * Data una stringa restituisce l'md5
478
433
  *
479
- * @returns {Uint8Array} Array UTF8
434
+ * @param {string} s Stringa di cui calcolare l'md5
435
+ * @returns {string} md5 della stringa **s**
480
436
  */
481
- base64ToArrayBuffer(base64Data) {
482
- var binaryString = window.atob(base64Data);
483
- var binaryLen = binaryString.length;
484
- var bytes = new Uint8Array(binaryLen);
485
- for (var i = 0; i < binaryLen; i++) {
486
- var ascii = binaryString.charCodeAt(i);
487
- bytes[i] = ascii;
488
- }
489
- return bytes;
437
+ md5(s) {
438
+ return this.hex(this.md51(s));
490
439
  }
491
440
  /**
492
- * Helper che permette di scaricare un file dato un array di Byte (**Uint8Array**)
441
+ * @ignore
493
442
  *
494
- * @param {Uint8Array} byte Rappresentazione del file da scaricare
495
- * @param {string} filename Nome del file suggerito in fase di salvataggio
443
+ * Metodo di utilità per il calcolo dell'md5
496
444
  */
497
- saveByteArray(byte, filename) {
498
- var blob = new Blob([byte]);
499
- var link = document.createElement("a");
500
- document.body.appendChild(link);
501
- link.href = window.URL.createObjectURL(blob);
502
- var fileName = filename;
503
- link.download = fileName;
504
- link.click();
505
- document.body.removeChild(link);
445
+ md5cycle(x, k) {
446
+ var a = x[0], b = x[1], c = x[2], d = x[3];
447
+ a = this.ff(a, b, c, d, k[0], 7, -680876936);
448
+ d = this.ff(d, a, b, c, k[1], 12, -389564586);
449
+ c = this.ff(c, d, a, b, k[2], 17, 606105819);
450
+ b = this.ff(b, c, d, a, k[3], 22, -1044525330);
451
+ a = this.ff(a, b, c, d, k[4], 7, -176418897);
452
+ d = this.ff(d, a, b, c, k[5], 12, 1200080426);
453
+ c = this.ff(c, d, a, b, k[6], 17, -1473231341);
454
+ b = this.ff(b, c, d, a, k[7], 22, -45705983);
455
+ a = this.ff(a, b, c, d, k[8], 7, 1770035416);
456
+ d = this.ff(d, a, b, c, k[9], 12, -1958414417);
457
+ c = this.ff(c, d, a, b, k[10], 17, -42063);
458
+ b = this.ff(b, c, d, a, k[11], 22, -1990404162);
459
+ a = this.ff(a, b, c, d, k[12], 7, 1804603682);
460
+ d = this.ff(d, a, b, c, k[13], 12, -40341101);
461
+ c = this.ff(c, d, a, b, k[14], 17, -1502002290);
462
+ b = this.ff(b, c, d, a, k[15], 22, 1236535329);
463
+ a = this.gg(a, b, c, d, k[1], 5, -165796510);
464
+ d = this.gg(d, a, b, c, k[6], 9, -1069501632);
465
+ c = this.gg(c, d, a, b, k[11], 14, 643717713);
466
+ b = this.gg(b, c, d, a, k[0], 20, -373897302);
467
+ a = this.gg(a, b, c, d, k[5], 5, -701558691);
468
+ d = this.gg(d, a, b, c, k[10], 9, 38016083);
469
+ c = this.gg(c, d, a, b, k[15], 14, -660478335);
470
+ b = this.gg(b, c, d, a, k[4], 20, -405537848);
471
+ a = this.gg(a, b, c, d, k[9], 5, 568446438);
472
+ d = this.gg(d, a, b, c, k[14], 9, -1019803690);
473
+ c = this.gg(c, d, a, b, k[3], 14, -187363961);
474
+ b = this.gg(b, c, d, a, k[8], 20, 1163531501);
475
+ a = this.gg(a, b, c, d, k[13], 5, -1444681467);
476
+ d = this.gg(d, a, b, c, k[2], 9, -51403784);
477
+ c = this.gg(c, d, a, b, k[7], 14, 1735328473);
478
+ b = this.gg(b, c, d, a, k[12], 20, -1926607734);
479
+ a = this.hh(a, b, c, d, k[5], 4, -378558);
480
+ d = this.hh(d, a, b, c, k[8], 11, -2022574463);
481
+ c = this.hh(c, d, a, b, k[11], 16, 1839030562);
482
+ b = this.hh(b, c, d, a, k[14], 23, -35309556);
483
+ a = this.hh(a, b, c, d, k[1], 4, -1530992060);
484
+ d = this.hh(d, a, b, c, k[4], 11, 1272893353);
485
+ c = this.hh(c, d, a, b, k[7], 16, -155497632);
486
+ b = this.hh(b, c, d, a, k[10], 23, -1094730640);
487
+ a = this.hh(a, b, c, d, k[13], 4, 681279174);
488
+ d = this.hh(d, a, b, c, k[0], 11, -358537222);
489
+ c = this.hh(c, d, a, b, k[3], 16, -722521979);
490
+ b = this.hh(b, c, d, a, k[6], 23, 76029189);
491
+ a = this.hh(a, b, c, d, k[9], 4, -640364487);
492
+ d = this.hh(d, a, b, c, k[12], 11, -421815835);
493
+ c = this.hh(c, d, a, b, k[15], 16, 530742520);
494
+ b = this.hh(b, c, d, a, k[2], 23, -995338651);
495
+ a = this.ii(a, b, c, d, k[0], 6, -198630844);
496
+ d = this.ii(d, a, b, c, k[7], 10, 1126891415);
497
+ c = this.ii(c, d, a, b, k[14], 15, -1416354905);
498
+ b = this.ii(b, c, d, a, k[5], 21, -57434055);
499
+ a = this.ii(a, b, c, d, k[12], 6, 1700485571);
500
+ d = this.ii(d, a, b, c, k[3], 10, -1894986606);
501
+ c = this.ii(c, d, a, b, k[10], 15, -1051523);
502
+ b = this.ii(b, c, d, a, k[1], 21, -2054922799);
503
+ a = this.ii(a, b, c, d, k[8], 6, 1873313359);
504
+ d = this.ii(d, a, b, c, k[15], 10, -30611744);
505
+ c = this.ii(c, d, a, b, k[6], 15, -1560198380);
506
+ b = this.ii(b, c, d, a, k[13], 21, 1309151649);
507
+ a = this.ii(a, b, c, d, k[4], 6, -145523070);
508
+ d = this.ii(d, a, b, c, k[11], 10, -1120210379);
509
+ c = this.ii(c, d, a, b, k[2], 15, 718787259);
510
+ b = this.ii(b, c, d, a, k[9], 21, -343485551);
511
+ x[0] = this.add32(a, x[0]);
512
+ x[1] = this.add32(b, x[1]);
513
+ x[2] = this.add32(c, x[2]);
514
+ x[3] = this.add32(d, x[3]);
506
515
  }
507
- ;
508
516
  /**
509
- * Utility per lo swap di due elementi di un array
517
+ * @ignore
510
518
  *
511
- * @param {any[]} array Array di cui invertire due elementi
512
- * @param {number} x Indice del primo elemento
513
- * @param {number} y Indice del secondo elemento
519
+ * Metodo di utilità per il calcolo dell'md5
514
520
  */
515
- swap(array, x, y) {
516
- var b = array[x];
517
- array[x] = array[y];
518
- array[y] = b;
521
+ cmn(q, a, b, x, s, t) {
522
+ a = this.add32(this.add32(a, q), this.add32(x, t));
523
+ return this.add32((a << s) | (a >>> (32 - s)), b);
519
524
  }
520
525
  /**
521
- * Helper di trascodifica da tipo c# a tipo Typescript
526
+ * @ignore
522
527
  *
523
- * @param {TypeCode} type Tipo da trascodificare
528
+ * Metodo di utilità per il calcolo dell'md5
529
+ */
530
+ ff(a, b, c, d, x, s, t) {
531
+ return this.cmn((b & c) | ((~b) & d), a, b, x, s, t);
532
+ }
533
+ /**
534
+ * @ignore
524
535
  *
525
- * @returns {"boolean" | "number" | "string" | "date"} Tipo Typescript corrispondente
536
+ * Metodo di utilità per il calcolo dell'md5
526
537
  */
527
- getJsTypeFromTypeCode(type) {
528
- switch (type) {
529
- case TypeCode.Boolean:
530
- return "boolean";
531
- case TypeCode.Decimal:
532
- case TypeCode.Double:
533
- case TypeCode.Single:
534
- case TypeCode.Int16:
535
- case TypeCode.Int32:
536
- case TypeCode.Int64:
537
- case TypeCode.Byte:
538
- case TypeCode.SByte:
539
- case TypeCode.UInt16:
540
- case TypeCode.UInt32:
541
- case TypeCode.UInt64:
542
- return "number";
543
- case TypeCode.Char:
544
- case TypeCode.String:
545
- return "string";
546
- case TypeCode.DateTime:
547
- return "date";
548
- default:
549
- console.log("Unrecognized input type. Typecode:" + type);
550
- return "string";
551
- }
538
+ gg(a, b, c, d, x, s, t) {
539
+ return this.cmn((b & d) | (c & (~d)), a, b, x, s, t);
552
540
  }
553
541
  /**
554
- * Effettua la clonazione profonda di un oggetto in maniera molto più performante che JSON.parse(JSON.stringify()).
542
+ * @ignore
555
543
  *
556
- * Usare solo per oggetti puri e quantomeno semplici per evitare complicazioni derivanti dalle semplificazioni che questo metodo assume
544
+ * Metodo di utilità per il calcolo dell'md5
545
+ */
546
+ hh(a, b, c, d, x, s, t) {
547
+ return this.cmn(b ^ c ^ d, a, b, x, s, t);
548
+ }
549
+ /**
550
+ * @ignore
557
551
  *
558
- * @param {any} source Oggetto da clonare
552
+ * Metodo di utilità per il calcolo dell'md5
553
+ */
554
+ ii(a, b, c, d, x, s, t) {
555
+ return this.cmn(c ^ (b | (~d)), a, b, x, s, t);
556
+ }
557
+ /**
558
+ * @ignore
559
559
  *
560
- * @return {any} Clone dell'oggetto passato
560
+ * Metodo di utilità per il calcolo dell'md5
561
561
  */
562
- deepClone(source) {
563
- // Valori semplici
564
- if (source == null || typeof source !== 'object')
565
- return source;
566
- // Pseudo Struct
567
- switch (toString.call(source)) {
568
- case '[object Boolean]':
569
- case '[object Number]':
570
- case '[object String]':
571
- case '[object Date]':
572
- return new source.constructor(source.valueOf());
573
- // Clonazione di un file -> Restituisco il riferimento al file stesso
574
- case "[object File]":
575
- return source;
576
- default: break;
562
+ md51(s) {
563
+ var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
564
+ for (i = 64; i <= s.length; i += 64)
565
+ this.md5cycle(state, this.md5blk(s.substring(i - 64, i)));
566
+ s = s.substring(i - 64);
567
+ var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
568
+ for (i = 0; i < s.length; i++)
569
+ tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
570
+ tail[i >> 2] |= 0x80 << ((i % 4) << 3);
571
+ if (i > 55) {
572
+ this.md5cycle(state, tail);
573
+ for (i = 0; i < 16; i++)
574
+ tail[i] = 0;
577
575
  }
578
- // Oggetti Complessi
579
- return this.recursiveStep(source, Array.isArray(source) || source instanceof Array ? [] : Object.create(Object.getPrototypeOf(source)));
576
+ tail[14] = n * 8;
577
+ this.md5cycle(state, tail);
578
+ return state;
580
579
  }
581
580
  /**
582
581
  * @ignore
583
- * Step ricorsivo per la clonatura degli oggetti. Vedere **deepClone**
582
+ *
583
+ * Metodo di utilità per il calcolo dell'md5
584
584
  */
585
- recursiveStep(source, destination) {
586
- if (Array.isArray(source) || source instanceof Array) {
587
- for (var i = 0, ii = source.length; i < ii; i++)
588
- destination.push(this.deepClone(source[i]));
589
- }
590
- else if (source && typeof source.hasOwnProperty === 'function') {
591
- for (let key in source) {
592
- if (source.hasOwnProperty(key))
593
- destination[key] = this.deepClone(source[key]);
594
- }
595
- }
596
- return destination;
585
+ md5blk(s) {
586
+ var md5blks = [], i;
587
+ for (i = 0; i < 64; i += 4)
588
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
589
+ return md5blks;
590
+ }
591
+ /**
592
+ * @ignore
593
+ *
594
+ * Metodo di utilità per il calcolo dell'md5
595
+ */
596
+ rhex(n) {
597
+ var s = '', j = 0;
598
+ for (; j < 4; j++)
599
+ s += this.hex_chr[(n >> (j * 8 + 4)) & 0x0F] + this.hex_chr[(n >> (j * 8)) & 0x0F];
600
+ return s;
601
+ }
602
+ /**
603
+ * @ignore
604
+ *
605
+ * Metodo di utilità per il calcolo dell'md5
606
+ */
607
+ hex(x) {
608
+ for (var i = 0; i < x.length; i++)
609
+ x[i] = this.rhex(x[i]);
610
+ return x.join('');
611
+ }
612
+ /**
613
+ * @ignore
614
+ *
615
+ * Metodo di utilità per il calcolo dell'md5
616
+ */
617
+ add32(a, b) {
618
+ return (a + b) & 0xFFFFFFFF;
597
619
  }
598
620
  }
599
- UtilityService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
600
- UtilityService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, providedIn: "root" });
601
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, decorators: [{
621
+ HashingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
622
+ HashingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, providedIn: "root" });
623
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, decorators: [{
602
624
  type: Injectable,
603
625
  args: [{ providedIn: "root" }]
604
626
  }] });
605
627
 
606
628
  /**
607
- * Decoratore che fornisce la classe di localizzazione per tutte le proprietà esportate con @Export e qualsiasi altro tag che richieda localizzazioni.
608
- *
609
- * Sostanzilamente aggiunge la proprietà **__loc__** all'oggetto creato dalla classe corrente assegnandogli come valore il tipo del LocalizationService da usare per la traduzione
610
- *
611
- * @param {Type<LocalizationService>} loc Tipo ereditato dal LocalizationService che può essere creato a runtime sotto contesto della DI di Angular
629
+ * Service che fornisce funzionalità di alert nei tipi fondamentali: success, info, warning e danger
612
630
  */
613
- function ExportLocalization(loc) {
614
- return function integrateLoc(constructor) {
615
- return class extends constructor {
616
- constructor() {
617
- super(...arguments);
618
- this.__loc__ = loc;
619
- }
620
- };
621
- };
622
- }
623
- /**
624
- * Decoratore di esportazione utilizzabile su una proprietà singola.
625
- * Verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
626
- *
627
- * Ad esempio, da questa configurazione:
628
- *
629
- * @example
630
- * ```
631
- * @Export(true, "MyHeader")
632
- * ciao: string;
633
- * ```
634
- *
635
- * Nasceranno le seguenti proprietà nell'oggetto esportabile:
636
- *
637
- * @example
638
- * ```
639
- * ciao_csvvis: string; => true
640
- * ciao: string;
641
- * ciao_csvhdr: string => "MyHeader"
642
- * ```
643
- *
644
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
645
- * @param {string} header Titolo della colonna nel file CSV esportato
646
- * @param {string} format Formato di esportazione. Può essere un formato data per i campi data o 'F' per i campi floating point
647
- */
648
- const Export = (order, header, format = null, tableid = null) => (target, propertyKey) => {
649
- if (format)
650
- Object.defineProperty(target, propertyKey + csvFormatPrefix, { value: format, writable: false });
651
- Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
652
- Object.defineProperty(target, propertyKey + csvVisPrefix, { value: !!header, writable: false });
653
- Object.defineProperty(target, propertyKey + csvHdrPrefix, { value: header, writable: false });
654
- if (tableid)
655
- Object.defineProperty(target, propertyKey + csvPropKey, { value: tableid, writable: false });
656
- if (target[exportList])
657
- target[exportList].push(propertyKey + csvVisPrefix);
658
- else
659
- target[exportList] = [propertyKey + csvVisPrefix];
660
- };
661
- /**
662
- * Decoratore di esportazione utilizzabile su un oggetto.
663
- * Per ogni proprietà dell'oggetto verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
664
- * Per essere esportate, le proprietà dell'oggetto devono essere marcate con i Decoratori di esportazione
665
- *
666
- * Ad esempio, da questa configurazione:
667
- *
668
- * @example
669
- * ```
670
- * MyObj {
671
- * @Export(true, "MyHeader")
672
- * ciao: string;
673
- * }
674
- *
675
- * @ExportObject(true, "MyHeader")
676
- * test: MyObj;
677
- * ```
678
- *
679
- * Nasceranno le seguenti proprietà nell'oggetto esportabile:
680
- *
681
- * @example
682
- * ```
683
- * testciao: string; => Valore di MyObj.ciao
684
- * testciao_csvvis: string; => true
685
- * testciao_csvhdr: string => "MyHeader"
686
- * ```
687
- *
688
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
689
- * @param {any} type Tipo da esportare
690
- */
691
- const ExportAs = (order, type, prefix) => (target, propertyKey) => {
692
- var t = new type();
693
- var props = t[exportList];
694
- for (let i = 0; i < props.length; i++) {
695
- let prop = props[i].replace(csvVisPrefix, '');
696
- if (typeof t[prop + csvVisPrefix] !== "undefined") {
697
- var toEmit = t[prop + csvVisPrefix];
698
- var lbl = t[prop + csvHdrPrefix];
699
- var format = t[prop + csvFormatPrefix];
700
- var orderProp = t[prop + csvOrdPrefix];
701
- if (format)
702
- Object.defineProperty(target, propertyKey + prop + csvFormatPrefix, { value: format, writable: false });
703
- Object.defineProperty(target, propertyKey + prop + csvOrdPrefix, { value: orderProp + order, writable: false });
704
- Object.defineProperty(target, propertyKey + prop, { value: null, writable: true, enumerable: true });
705
- Object.defineProperty(target, propertyKey + prop + csvValueNavigator, { value: propertyKey + "." + prop, writable: false });
706
- Object.defineProperty(target, propertyKey + prop + csvVisPrefix, { value: toEmit, writable: false });
707
- Object.defineProperty(target, propertyKey + prop + csvHdrPrefix, { value: (prefix ? prefix + ' ' : '') + lbl, writable: false });
708
- Object.defineProperty(target, propertyKey + prop + csvValueType, { value: type, writable: false });
709
- if (target[exportList])
710
- target[exportList].push(propertyKey + prop + csvVisPrefix);
711
- else
712
- target[exportList] = [propertyKey + prop + csvVisPrefix];
713
- }
714
- }
715
- };
716
- /**
717
- * Decoratore di esportazione utilizzabile su una lista,
718
- * si utilizzano 2 navigator rispettivamente per la valorizzazione dell'Header e del Valore e
719
- * per ogni elemento dell'array verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr)
720
- *
721
- * ATTENZIONE: Gli oggetti esportati in questa modalità non devono presentare altri tag di tipo @Export{...} all'interno. Fa tutto questo decoratore
722
- *
723
- * I navigator hanno questa convenzione:
724
- *
725
- * . --> divide due proprietà da richiamare consecutivamente: "a.b" richiamerà "obj.a.b";
726
- *
727
- * | --> divide più proprietà per le concatenazioni con uno spazio fra una e l'altra: "regdesc|slice.slicename" diventerà obj.regdesc + " " + obj.slice.slicename
728
- *
729
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
730
- * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
731
- * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
732
- * @param {string} valueformat Formato di esportazione per i valori selezionati dal **valuenavigator**. Può essere un formato data per i campi data o 'F' per i campi floating point
733
- */
734
- const ExportList = (order, headernavigator, valuenavigator, valueformat = null) => (target, propertyKey) => {
735
- Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
736
- Object.defineProperty(target, propertyKey + listCsvValPrefix, { value: valuenavigator, writable: false });
737
- Object.defineProperty(target, propertyKey + listCsvHdrPrefix, { value: headernavigator, writable: false });
738
- Object.defineProperty(target, propertyKey + listCsvValFormat, { value: valueformat, writable: false });
739
- if (target[exportList])
740
- target[exportList].push(propertyKey + listCsvHdrPrefix);
741
- else
742
- target[exportList] = [propertyKey + listCsvHdrPrefix];
743
- };
744
- /**
745
- * Decoratore di esportazione utilizzabile su un dizionario. Se ad esempio si vogliono generare le colonne
746
- *
747
- * Valore A = 1
748
- *
749
- * Valore B = 2
750
- *
751
- * Valore C = 3
752
- *
753
- * partendo da un oggetto iniziale { Valore { A: 1, B: 2, C: 3 } }
754
- *
755
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
756
- * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
757
- * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
758
- */
759
- const ExportDictionary = (order, headernavigator, valuenavigator) => (target, propertyKey) => {
760
- Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
761
- Object.defineProperty(target, propertyKey + dictionaryCsvValPrefix, { value: valuenavigator, writable: false });
762
- Object.defineProperty(target, propertyKey + dictionaryCsvHdrPrefix, { value: headernavigator, writable: false });
763
- if (target[exportList])
764
- target[exportList].push(propertyKey + dictionaryCsvHdrPrefix);
765
- else
766
- target[exportList] = [propertyKey + dictionaryCsvHdrPrefix];
767
- };
768
- /**
769
- * Service che si occupa dell'esportazione degli oggetti marcati dai Decoratori **ExportDictionary**, **ExportList**, **ExportAs** o **Export**
770
- */
771
- class ExportService {
631
+ class MessageService {
772
632
  /**
773
633
  * Costruttore
774
634
  *
775
635
  * @ignore
776
636
  */
777
- constructor(dates, utiExts, lc) {
778
- this.dates = dates;
779
- this.utiExts = utiExts;
780
- this.lc = lc;
637
+ constructor(injector, locProvider, emb, hash) {
638
+ this.injector = injector;
639
+ this.locProvider = locProvider;
640
+ this.emb = emb;
641
+ this.hash = hash;
642
+ /**
643
+ * Oggetto statico in supporto alla localizzazione
644
+ */
645
+ this.loc = {
646
+ 'Confirm': { 'en-US': "Confirm", 'it-IT': "Conferma", },
647
+ 'Cancel': { 'en-US': "Cancel", 'it-IT': "Annulla", },
648
+ 'Close': { 'en-US': "Close", 'it-IT': "Chiudi", },
649
+ 'Error': { 'en-US': "Error", 'it-IT': "Errore", },
650
+ 'Info': { 'en-US': "Info", 'it-IT': "Informazione", },
651
+ 'Success': { 'en-US': "Success", 'it-IT': "Successo", },
652
+ 'Warning': { 'en-US': "Warning", 'it-IT': "Attenzione", }
653
+ };
654
+ this.GuidRepsonseFunctionsMap = {};
655
+ this.init();
781
656
  }
782
- /**
783
- * Data una lista di oggetti genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
784
- *
785
- * @param {any[]} objs Oggetti da esportare
786
- *
787
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
788
- */
789
- setupForExport(objs, columns = []) {
790
- let headers = [];
791
- let headersCache = {};
792
- if (!objs || objs.length == 0)
793
- return headers;
794
- // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
795
- // Gli header li raccolgo tutti poi faccio uan distinct in modo da esportare tutte le proprietà per bene
796
- let columnSelectionDictionary = {};
797
- if ((columns === null || columns === void 0 ? void 0 : columns.length) > 0)
798
- for (let i = 0; i < (columns === null || columns === void 0 ? void 0 : columns.length); i++)
799
- columnSelectionDictionary[columns[i]] = true;
800
- for (let i = 0; i < objs.length; i++) {
801
- let hds = this.parseAndGetHeaders(objs[i], columnSelectionDictionary);
802
- // Aggiungo gli header facendo in modo di non aggiungerne mai due uguali per non dover fare una distinct dopo
803
- // che costerebbe comunque risorse. Utilizzo un dizionario d'appoggio per lookup istantanei
804
- for (let k = 0; k < hds.length; k++) {
805
- if (!headersCache[hds[k].key]) {
806
- headersCache[hds[k].key] = true;
807
- headers.push(hds[k]);
808
- }
809
- }
810
- }
811
- if (!columns || columns.length == 0)
812
- return headers.sort((a, b) => a.order - b.order);
813
- else {
814
- // Se mi arriva la lista di colonne non mi dà solo la visibilità, ma anche l'ordinamento
815
- // le esporto di conseguenza
816
- let orderedHeaders = [];
817
- for (let i = 0; i < columns.length; i++) {
818
- let thisId = columns[i];
819
- for (let i = 0; i < headers.length; i++) {
820
- if (headers[i].propKey == thisId) {
821
- orderedHeaders.push(headers[i]);
822
- break;
823
- }
824
- }
825
- }
826
- return orderedHeaders;
827
- }
657
+ get toastr() {
658
+ return this.injector.get(ToastrService);
828
659
  }
829
- /**
830
- * Data una lista di oggetti generici genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
831
- *
832
- * @param {GenericItem[]} objs Oggetti generici da esportare
833
- * @param {CsvHeaders[]} columns Colonne richieste dall'esportazione
834
- *
835
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
836
- */
837
- setupForGenericExport(objs, columns) {
838
- let headers = [];
839
- if (!objs || objs.length == 0)
840
- return headers;
841
- // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
842
- objs.forEach((obj, index) => {
843
- if (index == 0)
844
- headers = this.parseAndGetGenericHeaders(obj, columns);
845
- else
846
- this.parseAndGetGenericHeaders(obj, columns);
660
+ init() {
661
+ return __awaiter(this, void 0, void 0, function* () {
662
+ let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
663
+ this.expiredSessionSwal = swal.mixin({
664
+ showCancelButton: false,
665
+ confirmButtonText: 'Login',
666
+ customClass: {
667
+ confirmButton: "btn btn-primary",
668
+ container: "app-wrap",
669
+ },
670
+ buttonsStyling: false,
671
+ reverseButtons: false,
672
+ allowOutsideClick: false,
673
+ icon: "warning"
674
+ });
675
+ this.successSwalWithCancel = swal.mixin({
676
+ title: this.loc["Success"][LOCALE],
677
+ customClass: {
678
+ confirmButton: "btn btn-primary",
679
+ cancelButton: "btn btn-secondary app-margin-right-10",
680
+ container: "app-wrap",
681
+ },
682
+ buttonsStyling: false,
683
+ reverseButtons: true,
684
+ showCancelButton: true,
685
+ confirmButtonText: this.loc["Confirm"][LOCALE],
686
+ cancelButtonText: this.loc["Cancel"][LOCALE],
687
+ icon: "success"
688
+ });
689
+ this.warningSwalWithCancel = swal.mixin({
690
+ title: this.loc["Warning"][LOCALE],
691
+ customClass: {
692
+ confirmButton: "btn btn-primary",
693
+ cancelButton: "btn btn-secondary app-margin-right-10",
694
+ container: "app-wrap",
695
+ },
696
+ buttonsStyling: false,
697
+ reverseButtons: true,
698
+ showCancelButton: true,
699
+ confirmButtonText: this.loc["Confirm"][LOCALE],
700
+ cancelButtonText: this.loc["Cancel"][LOCALE],
701
+ icon: "warning"
702
+ });
703
+ this.warningSwal = swal.mixin({
704
+ title: this.loc["Warning"][LOCALE],
705
+ customClass: {
706
+ confirmButton: "btn btn-primary",
707
+ container: "app-wrap",
708
+ },
709
+ buttonsStyling: false,
710
+ reverseButtons: true,
711
+ showCancelButton: false,
712
+ confirmButtonText: this.loc["Close"][LOCALE],
713
+ icon: "warning"
714
+ });
715
+ this.successSwal = swal.mixin({
716
+ title: this.loc["Success"][LOCALE],
717
+ customClass: {
718
+ confirmButton: "btn btn-primary",
719
+ container: "app-wrap",
720
+ },
721
+ buttonsStyling: false,
722
+ reverseButtons: true,
723
+ showCancelButton: false,
724
+ confirmButtonText: this.loc["Close"][LOCALE],
725
+ icon: "success"
726
+ });
727
+ this.errorSwal = swal.mixin({
728
+ title: this.loc["Error"][LOCALE],
729
+ customClass: {
730
+ confirmButton: "btn btn-primary",
731
+ container: "app-wrap",
732
+ },
733
+ buttonsStyling: false,
734
+ reverseButtons: true,
735
+ showCancelButton: false,
736
+ confirmButtonText: this.loc["Close"][LOCALE],
737
+ icon: "error"
738
+ });
739
+ this.infoSwal = swal.mixin({
740
+ title: this.loc["Info"][LOCALE],
741
+ customClass: {
742
+ confirmButton: "btn btn-primary",
743
+ container: "app-wrap",
744
+ },
745
+ buttonsStyling: false,
746
+ reverseButtons: true,
747
+ showCancelButton: false,
748
+ confirmButtonText: this.loc["Close"][LOCALE],
749
+ icon: "info"
750
+ });
847
751
  });
848
- return headers;
849
752
  }
850
753
  /**
851
- * Dato un oggetto generico genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
852
- *
853
- * Metodo interno richiamato da **setupForGenericExport**
754
+ * Presentazione di un semplice messaggio di successo
854
755
  *
855
- * @param {GenericItem} obj Oggetto generico da esportare
856
- * @param {CsvColumn[]} columns Colonne richieste dall'esportazione
756
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
757
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
857
758
  *
858
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
759
+ * @param {string} text Testo da mostrare
760
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
859
761
  */
860
- parseAndGetGenericHeaders(obj, columns) {
861
- if (!obj.properties)
862
- return null;
863
- var headers = [];
864
- //Miracle incoming
865
- columns.forEach(t => {
866
- var propValue = obj.properties[t.key];
867
- Object.defineProperty(obj, t.key + "_exp", { value: propValue, writable: false, enumerable: true });
868
- headers.push({ label: t.label, key: t.key + "_exp", order: t.order, type: t.type, propKey: null });
869
- });
870
- //Tirati fuori tutti gli header faccio sort sull'ordinamento
871
- return headers.sort((a, b) => { return a.order - b.order; });
762
+ simpleSuccess(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
763
+ if (this.emb.Embedded) {
764
+ this.emb.MainWindow.postMessage({ type: "alert", level: 'success', msg: text }, "*");
765
+ return;
766
+ }
767
+ let tos = this.toastrOrSwal(secondaryNotificationType);
768
+ if (tos == "swal")
769
+ this.successSwal.fire("", text);
770
+ else
771
+ this.toastr.success(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
872
772
  }
873
773
  /**
874
- * Dato un oggetto genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
875
- *
876
- * Metodo interno richiamato da **setupForExport**
774
+ * Presentazione di un semplice messaggio di informazione
877
775
  *
878
- * @param {any} obj Oggetto generico da esportare
776
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
777
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
879
778
  *
880
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
779
+ * @param {string} text Testo da mostrare
780
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
881
781
  */
882
- parseAndGetHeaders(obj, columnsSelection) {
883
- var headers = [];
884
- // Miracle incoming
885
- let exportProps = obj[exportList] || [];
886
- let loc = obj[locProperty] ? this.lc.generateFromType(obj[locProperty]) : null;
887
- if (exportProps.length == 0)
888
- console.warn("[@esfaenza/extensions] Nessuna colonna configurata da esportare!");
889
- for (let i = 0; i < exportProps.length; i++) {
890
- let prop = exportProps[i];
891
- let propBase = "";
892
- let toCall;
893
- if (prop.endsWith(listCsvHdrPrefix)) {
894
- propBase = prop.replace(listCsvHdrPrefix, '');
895
- toCall = this.parseList.bind(this);
896
- }
897
- else if (prop.endsWith(dictionaryCsvHdrPrefix)) {
898
- propBase = prop.replace(dictionaryCsvHdrPrefix, '');
899
- toCall = this.parseDictionary.bind(this);
900
- }
901
- else if (prop.endsWith(csvVisPrefix)) {
902
- propBase = prop.replace(csvVisPrefix, '');
903
- if (typeof obj[propBase + csvValueNavigator] !== "undefined")
904
- toCall = this.parseObject.bind(this);
905
- else
906
- toCall = this.parseProperty.bind(this);
907
- }
908
- if (toCall)
909
- toCall(obj, propBase, headers, columnsSelection, loc);
782
+ simpleInfo(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
783
+ if (this.emb.Embedded) {
784
+ this.emb.MainWindow.postMessage({ type: "alert", level: 'info', msg: text }, "*");
785
+ return;
910
786
  }
911
- return headers;
787
+ let tos = this.toastrOrSwal(secondaryNotificationType);
788
+ if (tos == "swal")
789
+ this.infoSwal.fire("", text);
790
+ else
791
+ this.toastr.info(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
912
792
  }
913
793
  /**
914
- * Setup per l'esportazione di una singola proprietà.
915
- * Viene generato l'header e la proprietà relativa al valore formattato o no
794
+ * Presentazione di un semplice messaggio di errore
916
795
  *
917
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
918
- * @param {string} prop Proprietà da esportare
919
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
920
- * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
796
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
797
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
798
+ *
799
+ * @param {string} text Testo da mostrare
800
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
921
801
  */
922
- parseProperty(obj, prop, headers, columnsSelection, loc) {
923
- let toEmit = obj[prop + csvVisPrefix];
924
- let format = obj[prop + csvFormatPrefix];
925
- let propKey = obj[prop + csvPropKey];
926
- if (propKey && !columnsSelection[propKey] && Object.keys(columnsSelection).length > 0) {
927
- console.log("[@esfaenza/extensions] Colonna da non esportare: " + propKey);
928
- return;
929
- }
930
- let text = obj[prop + csvHdrPrefix];
931
- let label = loc && text ? loc.loc(text) : text || "";
932
- let order = obj[prop + csvOrdPrefix];
933
- if (!toEmit)
802
+ simpleError(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
803
+ if (this.emb.Embedded) {
804
+ this.emb.MainWindow.postMessage({ type: "alert", level: 'error', msg: text }, "*");
934
805
  return;
935
- // Se non ho un formato esporto direttamente
936
- if (!format) {
937
- // Se è un formato data mi assicuro di non stampare mai una data 00:00:00 altrimenti in esportazione viene uno schifo
938
- let val = obj[prop] ? this.dates.trimSeconds(obj[prop].toString()) : "";
939
- let key = prop + "_nofmt";
940
- Object.defineProperty(obj, key, { value: val, writable: false, enumerable: true });
941
- headers.push({ label, key, order, type: "string", propKey });
942
- }
943
- else {
944
- let key = prop + "_fmt";
945
- // Caso formato numerico
946
- if (format == "F") {
947
- // Check considerando la possibilità di zeri
948
- let val = obj[prop] != null ? obj[prop].toString() : "";
949
- // Elimino tutte le virgole (indicatori di migliaia per la culture default en-US)
950
- val = val.replace(/,/, "");
951
- // Il singolo punto che c'è, se presente (separatore decimali) lo trasformo in virgola
952
- let valConverted = val.replace(".", ",");
953
- Object.defineProperty(obj, key, { value: valConverted, writable: false, enumerable: true });
954
- headers.push({ label, key, order, type: "number", propKey });
955
- }
956
- else {
957
- // Se ho un formato data trasformo in dayjs, formatto ed esporto
958
- // Per la trasformazione in dayjs provo prima a passargli la stringa di netto, sperando la riconosca
959
- // Se non funziona provo a definirgli la formattazione standard del metering per quel linguaggio
960
- let val = this.dates.getFormatted(obj[prop], format.length <= 10, format.length > 16);
961
- Object.defineProperty(obj, key, { value: val !== null && val !== void 0 ? val : "", writable: false, enumerable: true });
962
- headers.push({ label, key, order, type: "date", propKey });
963
- }
964
806
  }
807
+ let tos = this.toastrOrSwal(secondaryNotificationType);
808
+ if (tos == "swal")
809
+ this.errorSwal.fire("", text);
810
+ else
811
+ this.toastr.error(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
965
812
  }
966
813
  /**
967
- * Setup per l'esportazione di una singola proprietà da un oggetto.
968
- * Viene generato l'header e la proprietà relativa al valore formattato o no.
814
+ * Presentazione di un semplice messaggio di avviso
969
815
  *
970
- * Per ottenere il valore e l'header della proprietà vengono utilizzati i navigatori auto-generati nel decoratore **ExportAs**
816
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
817
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
971
818
  *
972
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
973
- * @param {string} prop Proprietà da esportare
974
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
975
- * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
819
+ * @param {string} text Testo da mostrare
820
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
976
821
  */
977
- parseObject(obj, prop, headers, columnsSelection, loc) {
978
- //se questa proprietà ha un navigator significa che deriva da un oggetto interno, recupero il valore in questa fase dato che prima non ce l'ho
979
- let valuenavigator = obj[prop + csvValueNavigator];
980
- //Es. di valuenavigator obj.subobj.subsubobj.property
981
- let jmps = valuenavigator.split(".");
982
- // Localizzazione presa dalla classe base se c'è, altrimenti dalla classe interna (cioè dal primo saltino)
983
- if (!loc) {
984
- let type = obj[prop + csvValueType];
985
- let proto = new type();
986
- loc = proto[locProperty] ? this.lc.generateFromType(proto[locProperty]) : null;
987
- }
988
- //Mi clono l'oggetto originale per non uccidergli i riferimenti
989
- let clone = JSON.parse(JSON.stringify(obj));
990
- //Salto ricorsivamente su me stesso per arrivare alla proprietà
991
- //Salto 1 > diventa obj
992
- //Salto 2 > diventa obj.subobj
993
- //ecc...
994
- jmps.forEach(pp => { clone = clone[pp]; });
995
- //Valore finale :D
996
- let value = clone;
997
- let text = obj[prop + csvHdrPrefix];
998
- let label = loc && text ? loc.loc(text) : text || "";
999
- let order = obj[prop + csvOrdPrefix];
1000
- //Se per questa proprietà ho un formato lo applico
1001
- let format = obj[prop + csvFormatPrefix];
1002
- let type = "string";
1003
- if (format == "F") {
1004
- let val = value.toString();
1005
- val = val.replace(/,/, "");
1006
- value = val.replace(".", ",");
1007
- type = "number";
1008
- }
1009
- else if (format) {
1010
- value = this.dates.getFormatted(value, format.length <= 10, format.length > 16);
1011
- type = "date";
822
+ simpleWarning(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
823
+ if (this.emb.Embedded) {
824
+ this.emb.MainWindow.postMessage({ type: "alert", level: 'warning', msg: text }, "*");
825
+ return;
1012
826
  }
1013
- Object.defineProperty(obj, prop, { value: value !== null && value !== void 0 ? value : "", writable: false, enumerable: true });
1014
- headers.push({ label, key: prop, order, type, propKey: null });
827
+ let tos = this.toastrOrSwal(secondaryNotificationType);
828
+ if (tos == "swal")
829
+ this.warningSwal.fire("", text);
830
+ else
831
+ this.toastr.warning(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1015
832
  }
1016
833
  /**
1017
- * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
834
+ * Ripulisce tutti i messaggi presenti in un dato momento sullo schermo
835
+ */
836
+ clearMessages() {
837
+ this.toastr.clear();
838
+ swal.close();
839
+ }
840
+ /**
841
+ * Mostra un messaggio di avviso con richiesta di conferma
1018
842
  *
1019
- * => Recupero il valore utilizzando i navigatori
843
+ * @param {string} title Titolo del messaggio
844
+ * @param {string} text Contenuto del messaggio
1020
845
  *
1021
- * => Recupero l'header utilizzando i navigatori
846
+ * @returns {Promise} Restituisce una Promise col risultato scelto dall'utente (conferma o no)
847
+ */
848
+ promiseWarningWithChoice(title, text) {
849
+ return this.warningSwalWithCancel.fire(title, text);
850
+ }
851
+ /**
852
+ * In base alla configurazione attuale e all'eventuale override per la chiamata del caso indica se bisogna utilizzare toastr o sweetalert
1022
853
  *
1023
- * => Con il valore ci creo la property
854
+ * @param {"toastr" | "swal" | null} providerOverride Override alla modalità configurata
1024
855
  *
1025
- * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
856
+ * @returns {"toastr" | "swal"} Indicazione su che provider di messaggi di avviso debba essere utilizzato
857
+ */
858
+ toastrOrSwal(providerOverride) {
859
+ if (providerOverride != null)
860
+ return providerOverride;
861
+ return "swal";
862
+ }
863
+ /**
864
+ * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
1026
865
  *
1027
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1028
- * @param {string} prop Proprietà da esportare
1029
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1030
- * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
866
+ * @param {string} title Titolo del messaggio
867
+ * @param {string} text Contenuto del messaggio
868
+ * @param {Function} onsuccess Callback da chimare su conferma
869
+ * @param {Function} onerror Callback da chimare su errori
1031
870
  */
1032
- parseList(obj, prop, headers, columnsSelection, loc) {
1033
- let headernavigator = obj[prop + listCsvHdrPrefix];
1034
- let valuenavigator = obj[prop + listCsvValPrefix];
1035
- let valueformat = obj[prop + listCsvValFormat];
1036
- let order = obj[prop + csvOrdPrefix];
1037
- var jumps, tmpRes;
1038
- var objs = obj[prop];
1039
- for (let idx = 0; idx < objs.length; idx++) {
1040
- let listitem = objs[idx];
1041
- var headersplit = headernavigator.split(" ");
1042
- var label = "";
1043
- // Per l'header si considera a se stante ogni pezzo separato da spazio per fare le concatenazioni
1044
- headersplit.forEach(pr => {
1045
- jumps = pr.split(".");
1046
- tmpRes = JSON.parse(JSON.stringify(listitem));
1047
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1048
- let localized = !!loc ? loc.loc(tmpRes) : tmpRes;
1049
- if (!label)
1050
- label = localized;
1051
- else
1052
- label += " " + localized;
1053
- });
1054
- jumps = valuenavigator.split(".");
1055
- tmpRes = JSON.parse(JSON.stringify(listitem));
1056
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1057
- let value = tmpRes;
1058
- let type = "string";
1059
- if (valueformat == "F") {
1060
- let val = value != null ? value.toString() : "";
1061
- val = val.replace(/,/, "");
1062
- value = val.replace(".", ",");
1063
- type = "number";
1064
- }
1065
- else if (valueformat) {
1066
- value = this.dates.getFormatted(obj[prop], valueformat.length <= 10, valueformat.length > 16);
1067
- type = "date";
1068
- }
1069
- Object.defineProperty(obj, prop + idx, { value: value !== null && value !== void 0 ? value : "", writable: false });
1070
- headers.push({ label, key: prop + idx, order: order + idx, type, propKey: null });
871
+ _simpleWarningWithChoice(title, text, onsuccess = null, onerror = null) {
872
+ this.warningSwalWithCancel.fire(title, text).then((result) => {
873
+ if (result.value && onsuccess)
874
+ onsuccess();
875
+ else if (onerror)
876
+ onerror();
877
+ });
878
+ }
879
+ simpleWarningWithChoice(title, text, onsuccess, onerror) {
880
+ this.withChoiceBase("warning", title, text, onsuccess, onerror);
881
+ }
882
+ simpleSuccessWithChoice(title, text, onsuccess, onerror) {
883
+ this.withChoiceBase("success", title, text, onsuccess, onerror);
884
+ }
885
+ withChoiceBase(level, title, text, onsuccess, onerror) {
886
+ if (this.emb.Embedded) {
887
+ let guid = this.hash.getGUID();
888
+ this.GuidRepsonseFunctionsMap[guid] = { onsuccess, onerror };
889
+ this.emb.MainWindow.postMessage({ type: "confirm", level, title, text, guid }, "*");
890
+ // Observe sulla risposta
891
+ console.log("Inviata confirm request alla pagina principale, in attesa di risposta...");
892
+ this.emb.MessageObserver.pipe(filter(event => { var _a, _b; return ((_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.type) == "confirm-response" && ((_b = event === null || event === void 0 ? void 0 : event.data) === null || _b === void 0 ? void 0 : _b.guid) == guid; }), take(1)).subscribe(event => {
893
+ var _a, _b;
894
+ console.log("Event listener su window-message. Risposta pergiunta");
895
+ if (((_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.result) === true)
896
+ this.GuidRepsonseFunctionsMap[guid].onsuccess();
897
+ else if (((_b = event === null || event === void 0 ? void 0 : event.data) === null || _b === void 0 ? void 0 : _b.result) === true)
898
+ this.GuidRepsonseFunctionsMap[guid].onerror();
899
+ });
1071
900
  }
901
+ else
902
+ (level == "warning" ? this._simpleWarningWithChoice : this._simpleSuccessWithChoice)(title, text, onsuccess, onerror);
1072
903
  }
1073
904
  /**
1074
- * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1075
- *
1076
- * => Recupero il valore utilizzando i navigatori
905
+ * Mostra un messaggio di success con richiesta di conferma e gestisce il risultato chiamato i callback **onconfirm** o **onabort**
1077
906
  *
1078
- * => Recupero l'header utilizzando i navigatori
907
+ * @param {string} title Titolo del messaggio
908
+ * @param {string} text Contenuto del messaggio
909
+ * @param {Function} onconfirm Callback da chimare su conferma
910
+ * @param {Function} onabort Callback da chimare su annullamento
911
+ * @param {string} confirmtext Testo del pulsante di azione
912
+ * @param {string} aborttext Testo del pulsante di annullamento
913
+ */
914
+ _simpleSuccessWithChoice(title, text, onconfirm = null, onabort = null, confirmtext = "", aborttext = '') {
915
+ var configuration = {
916
+ title: title,
917
+ html: text
918
+ };
919
+ if (confirmtext)
920
+ configuration["confirmButtonText"] = confirmtext;
921
+ if (aborttext)
922
+ configuration["cancelButtonText"] = aborttext;
923
+ this.successSwalWithCancel.fire(configuration).then((result) => {
924
+ if (result.value && onconfirm)
925
+ onconfirm();
926
+ else if (onabort)
927
+ onabort();
928
+ });
929
+ }
930
+ /**
931
+ * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
1079
932
  *
1080
- * => Con il valore ci creo la property
933
+ * @param {string} title Titolo del messaggio
934
+ * @param {string} text Contenuto del messaggio
935
+ */
936
+ observableSimpleWarningWithChoice(title, text) {
937
+ return of(this.warningSwalWithCancel.fire(title, text)).pipe(map(t => !!t.value));
938
+ }
939
+ /**
940
+ * Mostra un messaggio di avviso che la sessione corrente è scaduta e propone all'utente di navigare al login. Qualora l'utente decidesse di farlo
941
+ * verrà chiamata la funzione di callback **onnavigate
1081
942
  *
1082
- * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
943
+ * @param {string} title Titolo del messaggio
944
+ * @param {string} text Contenuto del messaggio
945
+ * @param {Function} onnavigate Callback da chimare su navigazione in corso
946
+ */
947
+ expiredSessionMessage(title, text, onnavigate = null) {
948
+ this.expiredSessionSwal.fire(title, text).then((result) => {
949
+ if (result.value && onnavigate)
950
+ onnavigate();
951
+ });
952
+ }
953
+ /**
954
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **CallResult**
1083
955
  *
1084
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1085
- * @param {string} prop Proprietà da esportare
1086
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1087
- * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
956
+ * @param {CallResult} response Risposta ricevuta dal server
957
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
958
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
959
+ * @param {Function} postSuccess Callback da chimare in caso di successo
960
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
1088
961
  */
1089
- parseDictionary(obj, prop, headers, columnsSelection, loc) {
1090
- let headernavigator = obj[prop + dictionaryCsvHdrPrefix];
1091
- let valuenavigator = obj[prop + dictionaryCsvValPrefix];
1092
- let order = obj[prop + csvOrdPrefix];
1093
- var jumps, tmpRes;
1094
- var objs = obj[prop];
1095
- for (let idx = 0; idx < objs.length; idx++) {
1096
- let listitem = objs[idx];
1097
- var headersplit = headernavigator.split(" ");
1098
- var label = "";
1099
- headersplit.forEach(pr => {
1100
- jumps = pr.split(".");
1101
- tmpRes = JSON.parse(JSON.stringify(listitem));
1102
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1103
- if (!label)
1104
- label = !!loc ? loc.loc(tmpRes) : tmpRes;
1105
- else
1106
- label += " " + !!loc ? loc.loc(tmpRes) : tmpRes;
1107
- });
1108
- var valuesplit = valuenavigator.split(",");
1109
- valuesplit.forEach((t, idxinternal) => {
1110
- var navig = t.split("-")[1];
1111
- var desc = t.split("-")[0];
1112
- jumps = navig.split(".");
1113
- tmpRes = JSON.parse(JSON.stringify(listitem));
1114
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1115
- let value = tmpRes;
1116
- let propname = prop + idx.toString() + idxinternal.toString();
1117
- Object.defineProperty(obj, propname, { value: value !== null && value !== void 0 ? value : "", writable: false });
1118
- headers.push({ label: label + " " + !!loc ? loc.loc(desc) : desc, key: propname, order: order + idx, type: 'string', propKey: null });
1119
- });
962
+ manageCallResultResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
963
+ if (response.success) {
964
+ if (response.haswarning)
965
+ this.simpleWarning(response.warning);
966
+ else if (successMsg)
967
+ this.simpleSuccess(successMsg);
968
+ if (postSuccess)
969
+ postSuccess();
970
+ }
971
+ else {
972
+ this.simpleError((errorMsg ? errorMsg + ": " : "") + response.haserror ? response.error : '[NO ERR.]');
973
+ if (postFailure)
974
+ postFailure();
1120
975
  }
1121
976
  }
1122
977
  /**
1123
- * Effettua l'esportazione in file CSV
978
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **string**, considerando che:
979
+ *
980
+ * Stringa vuota --> Tutto bene
981
+ *
982
+ * Stringa piena --> Questo è il messaggio d'errore per cui la chiamata è fallita
983
+ *
984
+ * @param {string} response Risposta ricevuta dal server
985
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
986
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
987
+ * @param {Function} postSuccess Callback da chimare in caso di successo
988
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
1124
989
  */
1125
- exportCSV(fn, headers, data) {
1126
- let csvData = '', row = '', sep = ';';
1127
- for (let i = 0; i < headers.length; i++) {
1128
- let h = headers[i];
1129
- row += `${row != '' ? sep : ''}"${h.label}"`;
990
+ manageStringResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
991
+ if (!response) {
992
+ if (successMsg)
993
+ this.simpleSuccess(successMsg);
994
+ if (postSuccess)
995
+ postSuccess();
1130
996
  }
1131
- csvData += row + '\r\n';
1132
- for (let i = 0; i < data.length; i++) {
1133
- row = '';
1134
- let item = data[i];
1135
- for (let j = 0; j < headers.length; j++) {
1136
- let val = item[headers[j].key];
1137
- row += `${row != '' ? sep : ''}"${val}"`;
1138
- }
1139
- csvData += row + '\r\n';
997
+ else {
998
+ if (errorMsg)
999
+ this.simpleError(errorMsg + ": " + response);
1000
+ if (postFailure)
1001
+ postFailure();
1140
1002
  }
1141
- var BOM = new Uint8Array([0xEF, 0xBB, 0xBF]);
1142
- var blob = new Blob([BOM, csvData], { type: 'text/csv' });
1143
- var objectUrl = URL.createObjectURL(blob);
1144
- this.utiExts.fileDownload(objectUrl, fn.endsWith('.xlsx') ? fn.replace('.xlsx', '.csv') : fn.endsWith('.csv') ? fn : fn + ".csv");
1145
- }
1146
- /** Effettua l'esportazione del file Excel basandosi sul modulo **ExcelJS**, sugli header **headers** e sui dati **data** */
1147
- exportExcel(fn, headers, data) {
1148
- return __awaiter(this, void 0, void 0, function* () {
1149
- try {
1150
- this.ExcelJS = this.ExcelJS || (yield import('exceljs'));
1151
- }
1152
- catch (_a) {
1153
- throw "Impossibile caricare la libreria per l'esportazione in Excel";
1154
- }
1155
- let iFix = 1;
1156
- let workbook = new this.ExcelJS.Workbook();
1157
- workbook.creator = "Ema's big Es-Table";
1158
- workbook.created = new Date();
1159
- let sheet = workbook.addWorksheet('Data');
1160
- let header = sheet.getRow(1);
1161
- header.font = { bold: true };
1162
- headers = headers.sort((a, b) => a.order - b.order);
1163
- for (let i = 0; i < headers.length; i++) {
1164
- let h = headers[i];
1165
- header.getCell(i + iFix).value = h.label;
1166
- }
1167
- for (let i = 0; i < data.length; i++) {
1168
- let row = sheet.getRow(i + iFix + 1);
1169
- let item = data[i];
1170
- for (let i = 0; i < headers.length; i++) {
1171
- let h = headers[i];
1172
- let cell = row.getCell(i + 1);
1173
- let val = item[h.key];
1174
- if (!val) {
1175
- cell.value = "";
1176
- continue;
1177
- }
1178
- switch (h.type) {
1179
- case 'date':
1180
- // ExcelJS va di default in UTC quindi rischierebbe di tirare giù 2 ore ad ogni esportazione
1181
- // Bisogna aggiungere l'utc offset alla data attuale
1182
- let date = this.dates.getDateConvertion(val);
1183
- if (date) {
1184
- let correctedDate = date.add(date.utcOffset(), 'minute');
1185
- cell.value = correctedDate.toDate();
1186
- cell.numFmt = val.length > 10 ? 'dd/mm/yyyy h:m:s' : '';
1187
- }
1188
- break;
1189
- case 'number':
1190
- let converted = parseFloat(val.replace(',', '.'));
1191
- cell.value = isNaN(converted) ? "" : converted;
1192
- break;
1193
- default:
1194
- cell.value = val;
1195
- break;
1196
- }
1197
- }
1198
- }
1199
- let buffer = yield workbook.xlsx.writeBuffer();
1200
- let blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;" });
1201
- let objectUrl = URL.createObjectURL(blob);
1202
- this.utiExts.fileDownload(objectUrl, fn.endsWith('.csv') ? fn.replace('.csv', '.xlsx') : fn.endsWith('.xlsx') ? fn : fn + ".xlsx");
1203
- });
1204
1003
  }
1205
1004
  /**
1206
- * Metodo che effettivamente genera gli header e i dati per l'esportazione con **ngx-csv**
1005
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **boolean**
1207
1006
  *
1208
- * @param {any[]} items Oggetti da esportare
1007
+ * @param {string} response Risposta ricevuta dal server
1008
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
1009
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1010
+ * @param {Function} postSuccess Callback da chimare in caso di successo
1011
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
1209
1012
  */
1210
- export(items, format, fileName, type, columnsFilter, genericHeaders) {
1211
- var createdItems = items.map(t => {
1212
- let tmp = new type();
1213
- for (let property in t)
1214
- tmp[property] = t[property];
1215
- return tmp;
1216
- });
1217
- let headers = genericHeaders ? this.setupForGenericExport(createdItems, genericHeaders) : this.setupForExport(createdItems, columnsFilter);
1218
- (format == "CSV" ? this.exportCSV : this.exportExcel).bind(this)(fileName, headers, createdItems);
1013
+ manageStringResponseBool(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1014
+ if (response) {
1015
+ if (successMsg)
1016
+ this.simpleSuccess(successMsg);
1017
+ if (postSuccess)
1018
+ postSuccess();
1019
+ }
1020
+ else {
1021
+ if (errorMsg)
1022
+ this.simpleError(errorMsg);
1023
+ if (postFailure)
1024
+ postFailure();
1025
+ }
1219
1026
  }
1220
1027
  }
1221
- ExportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, deps: [{ token: DateService }, { token: UtilityService }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Injectable });
1222
- ExportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, providedIn: "root" });
1223
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, decorators: [{
1028
+ MessageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, deps: [{ token: Injector }, { token: i1.BaseLocalization, optional: true }, { token: AppEmbeddingExtensions }, { token: HashingService }], target: i0.ɵɵFactoryTarget.Injectable });
1029
+ MessageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, providedIn: "root" });
1030
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, decorators: [{
1224
1031
  type: Injectable,
1225
1032
  args: [{ providedIn: "root" }]
1226
- }], ctorParameters: function () { return [{ type: DateService }, { type: UtilityService }, { type: i1.LocalizationService }]; } });
1033
+ }], ctorParameters: function () {
1034
+ return [{ type: i0.Injector, decorators: [{
1035
+ type: Inject,
1036
+ args: [Injector]
1037
+ }] }, { type: i1.BaseLocalization, decorators: [{
1038
+ type: Optional
1039
+ }] }, { type: AppEmbeddingExtensions }, { type: HashingService }];
1040
+ } });
1227
1041
 
1228
1042
  // Angular
1229
1043
  /* Classe che contiene tutte le informazioni sull'embedding in un unico contenitore per semplicità */
1230
1044
  class AppEmbeddingExtensions {
1231
- constructor() {
1045
+ constructor(msgService, router) {
1046
+ this.msgService = msgService;
1047
+ this.router = router;
1232
1048
  this.Embedded = false;
1233
1049
  this.EmbeddingLevel = 0;
1050
+ this.MessageObserver = new Subject();
1051
+ this.setupEmbeddability();
1234
1052
  this.MainWindow = window;
1235
1053
  while (this.MainWindow.parent != this.MainWindow) {
1236
1054
  this.MainWindow = this.MainWindow.parent;
@@ -1238,925 +1056,1301 @@ class AppEmbeddingExtensions {
1238
1056
  this.Embedded = true;
1239
1057
  }
1240
1058
  }
1059
+ setupEmbeddability() {
1060
+ window.onmessage = (event) => {
1061
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7;
1062
+ // Ignoro i miei messaggi dato che mi interessano solo quelli degli altri iframe
1063
+ if (event.source == window && ((_a = event === null || event === void 0 ? void 0 : event.data) === null || _a === void 0 ? void 0 : _a.type) != "modal-open")
1064
+ return;
1065
+ this.MessageObserver.next({ event: "window-message", data: event === null || event === void 0 ? void 0 : event.data });
1066
+ if (((_b = event === null || event === void 0 ? void 0 : event.data) === null || _b === void 0 ? void 0 : _b.type) == "alert") {
1067
+ console.log(`Window message - alert -> Level: ${(_c = event === null || event === void 0 ? void 0 : event.data) === null || _c === void 0 ? void 0 : _c.level}, Message: ${(_d = event === null || event === void 0 ? void 0 : event.data) === null || _d === void 0 ? void 0 : _d.msg}`);
1068
+ switch ((_e = event === null || event === void 0 ? void 0 : event.data) === null || _e === void 0 ? void 0 : _e.level) {
1069
+ case "success":
1070
+ this.msgService.simpleSuccess((_f = event === null || event === void 0 ? void 0 : event.data) === null || _f === void 0 ? void 0 : _f.msg);
1071
+ break;
1072
+ case "warning":
1073
+ this.msgService.simpleWarning((_g = event === null || event === void 0 ? void 0 : event.data) === null || _g === void 0 ? void 0 : _g.msg);
1074
+ break;
1075
+ case "error":
1076
+ this.msgService.simpleError((_h = event === null || event === void 0 ? void 0 : event.data) === null || _h === void 0 ? void 0 : _h.msg);
1077
+ break;
1078
+ case "info":
1079
+ this.msgService.simpleInfo((_j = event === null || event === void 0 ? void 0 : event.data) === null || _j === void 0 ? void 0 : _j.msg);
1080
+ break;
1081
+ }
1082
+ }
1083
+ else if (((_k = event === null || event === void 0 ? void 0 : event.data) === null || _k === void 0 ? void 0 : _k.type) == "confirm") {
1084
+ console.log(`Window message - confirm -> Level: ${(_l = event === null || event === void 0 ? void 0 : event.data) === null || _l === void 0 ? void 0 : _l.level}, Message: ${(_m = event === null || event === void 0 ? void 0 : event.data) === null || _m === void 0 ? void 0 : _m.text}, Title: ${(_o = event === null || event === void 0 ? void 0 : event.data) === null || _o === void 0 ? void 0 : _o.title}, ID: ${(_p = event === null || event === void 0 ? void 0 : event.data) === null || _p === void 0 ? void 0 : _p.guid}`);
1085
+ var sourceWindow = event.source;
1086
+ var baseResponse = { type: "confirm-response", guid: (_q = event === null || event === void 0 ? void 0 : event.data) === null || _q === void 0 ? void 0 : _q.guid };
1087
+ switch ((_r = event === null || event === void 0 ? void 0 : event.data) === null || _r === void 0 ? void 0 : _r.level) {
1088
+ case "success":
1089
+ this.msgService.simpleSuccessWithChoice((_s = event === null || event === void 0 ? void 0 : event.data) === null || _s === void 0 ? void 0 : _s.title, (_t = event === null || event === void 0 ? void 0 : event.data) === null || _t === void 0 ? void 0 : _t.text, () => {
1090
+ debugger;
1091
+ sourceWindow.postMessage(Object.assign({ result: true }, baseResponse), "*");
1092
+ }, () => {
1093
+ sourceWindow.postMessage(Object.assign({ result: false }, baseResponse), "*");
1094
+ });
1095
+ break;
1096
+ case "warning":
1097
+ this.msgService.simpleWarningWithChoice((_u = event === null || event === void 0 ? void 0 : event.data) === null || _u === void 0 ? void 0 : _u.title, (_v = event === null || event === void 0 ? void 0 : event.data) === null || _v === void 0 ? void 0 : _v.text, () => {
1098
+ debugger;
1099
+ sourceWindow.postMessage(Object.assign({ result: true }, baseResponse), "*");
1100
+ }, () => {
1101
+ sourceWindow.postMessage(Object.assign({ result: false }, baseResponse), "*");
1102
+ });
1103
+ break;
1104
+ }
1105
+ }
1106
+ else if (((_w = event === null || event === void 0 ? void 0 : event.data) === null || _w === void 0 ? void 0 : _w.type) == "navigate") {
1107
+ console.log(`Window message - navigate -> ${(_x = event === null || event === void 0 ? void 0 : event.data) === null || _x === void 0 ? void 0 : _x.url}`);
1108
+ this.router.navigate([(_y = event === null || event === void 0 ? void 0 : event.data) === null || _y === void 0 ? void 0 : _y.url]);
1109
+ }
1110
+ else if (((_z = event === null || event === void 0 ? void 0 : event.data) === null || _z === void 0 ? void 0 : _z.type) == "redirect") {
1111
+ console.log(`Window message - redirect -> ${(_0 = event === null || event === void 0 ? void 0 : event.data) === null || _0 === void 0 ? void 0 : _0.url}`);
1112
+ window.location.href = (_1 = event === null || event === void 0 ? void 0 : event.data) === null || _1 === void 0 ? void 0 : _1.url;
1113
+ }
1114
+ else if (((_2 = event === null || event === void 0 ? void 0 : event.data) === null || _2 === void 0 ? void 0 : _2.type) == "navigation") {
1115
+ console.log(`Window message - Navigation -> ${((_3 = event === null || event === void 0 ? void 0 : event.data) === null || _3 === void 0 ? void 0 : _3.internalNavigation) ? "[internal]" : ""} ${(_4 = event === null || event === void 0 ? void 0 : event.data) === null || _4 === void 0 ? void 0 : _4.title}`);
1116
+ this.MessageObserver.next({ event: "navigation", data: event === null || event === void 0 ? void 0 : event.data });
1117
+ }
1118
+ else if (((_5 = event === null || event === void 0 ? void 0 : event.data) === null || _5 === void 0 ? void 0 : _5.type) == "modal-open") {
1119
+ const wrapper = document.body.getElementsByClassName("main-wrapper")[0];
1120
+ let wrapperStyles = window.getComputedStyle(wrapper);
1121
+ const wrapperPaddingLeft = parseInt(wrapperStyles.getPropertyValue("padding-left"));
1122
+ const wrapperPaddingRight = parseInt(wrapperStyles.getPropertyValue("padding-right"));
1123
+ console.log(`Window message - Modal Open -> Backdrop Height: ${(_6 = event === null || event === void 0 ? void 0 : event.data) === null || _6 === void 0 ? void 0 : _6.backdropHeight}`);
1124
+ var topHeight = 116; // valore fisso, distanza fra il top e l'inizio dell'iframe, non sarà mai diverso
1125
+ var rightSpace = wrapperPaddingRight; // valore fisso, distanza fra la fine dell'iframe e il lato sinistro dello schermo, non sarà mai diverso
1126
+ var leftSpace = 230 + wrapperPaddingLeft; // 230 è la variabile $sidebar-width
1127
+ let commonStyles = "position: absolute; z-index: 9999; background-color: #000; opacity: 0.5; ";
1128
+ wrapper.style.setProperty("overflow", "hidden", "important");
1129
+ const top = document.createElement("div");
1130
+ top.className = "embedded-modal-top";
1131
+ top.style.cssText = commonStyles + `height: ${topHeight}px; top: 0; width: calc(100% - ${leftSpace}px); left: ${leftSpace}px`;
1132
+ top.id = "top";
1133
+ const left = document.createElement("div");
1134
+ left.className = "embedded-modal-left";
1135
+ left.style.cssText = commonStyles + `height: 100%; top: 0; width: ${leftSpace}px;`;
1136
+ left.id = "left";
1137
+ const right = document.createElement("div");
1138
+ right.className = "embedded-modal-right";
1139
+ right.style.cssText = commonStyles + `height: calc(100% - ${topHeight}px); top: ${topHeight}px; right: 0; width: ${rightSpace}px;`;
1140
+ right.id = "right";
1141
+ document.body.appendChild(top);
1142
+ document.body.appendChild(left);
1143
+ document.body.appendChild(right);
1144
+ }
1145
+ else if (((_7 = event === null || event === void 0 ? void 0 : event.data) === null || _7 === void 0 ? void 0 : _7.type) == "modal-close") {
1146
+ console.log(`Window message - Modal Close`);
1147
+ let wrapper = document.body.getElementsByClassName("main-wrapper")[0];
1148
+ wrapper.style.removeProperty("overflow");
1149
+ const top = document.getElementById("top");
1150
+ const left = document.getElementById("left");
1151
+ const right = document.getElementById("right");
1152
+ if (top)
1153
+ document.body.removeChild(top);
1154
+ if (left)
1155
+ document.body.removeChild(left);
1156
+ if (right)
1157
+ document.body.removeChild(right);
1158
+ }
1159
+ };
1160
+ if (this.Embedded)
1161
+ document.body.style.setProperty("overflow-y", "auto", "important");
1162
+ }
1163
+ refreshBoundariesOnMenuCollapse() {
1164
+ const wrapper = document.body.getElementsByClassName("main-wrapper")[0];
1165
+ let wrapperStyles = window.getComputedStyle(wrapper);
1166
+ const wrapperPaddingLeft = parseInt(wrapperStyles.getPropertyValue("padding-left"));
1167
+ var leftSpace = 230 + wrapperPaddingLeft;
1168
+ const left = document.getElementById("left");
1169
+ const top = document.getElementById("top");
1170
+ if (top) {
1171
+ top.style.setProperty("left", (leftSpace) + "px");
1172
+ top.style.setProperty("width", `calc(100% - ${leftSpace}px)`);
1173
+ }
1174
+ if (left)
1175
+ left.style.setProperty("width", leftSpace + "px");
1176
+ }
1241
1177
  }
1242
- AppEmbeddingExtensions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AppEmbeddingExtensions, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1178
+ AppEmbeddingExtensions.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AppEmbeddingExtensions, deps: [{ token: MessageService }, { token: i2.Router }], target: i0.ɵɵFactoryTarget.Injectable });
1243
1179
  AppEmbeddingExtensions.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AppEmbeddingExtensions, providedIn: "root" });
1244
1180
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: AppEmbeddingExtensions, decorators: [{
1245
1181
  type: Injectable,
1246
1182
  args: [{ providedIn: "root" }]
1247
- }], ctorParameters: function () { return []; } });
1183
+ }], ctorParameters: function () { return [{ type: MessageService }, { type: i2.Router }]; } });
1248
1184
 
1185
+ // Angular
1249
1186
  /**
1250
- * Service che fornisce funzionalità di alert nei tipi fondamentali: success, info, warning e danger
1187
+ * Service che fornisce un accesso base in lettura/scrittura sulla clipboard
1251
1188
  */
1252
- class MessageService {
1253
- /**
1254
- * Costruttore
1255
- *
1256
- * @ignore
1257
- */
1258
- constructor(injector, locProvider, emb) {
1259
- this.injector = injector;
1260
- this.locProvider = locProvider;
1189
+ class BaseExtensionsService {
1190
+ constructor(emb) {
1261
1191
  this.emb = emb;
1262
- /**
1263
- * Oggetto statico in supporto alla localizzazione
1264
- */
1265
- this.loc = {
1266
- 'Confirm': { 'en-US': "Confirm", 'it-IT': "Conferma", },
1267
- 'Cancel': { 'en-US': "Cancel", 'it-IT': "Annulla", },
1268
- 'Close': { 'en-US': "Close", 'it-IT': "Chiudi", },
1269
- 'Error': { 'en-US': "Error", 'it-IT': "Errore", },
1270
- 'Info': { 'en-US': "Info", 'it-IT': "Informazione", },
1271
- 'Success': { 'en-US': "Success", 'it-IT': "Successo", },
1272
- 'Warning': { 'en-US': "Warning", 'it-IT': "Attenzione", }
1273
- };
1274
- this.init();
1275
- }
1276
- get toastr() {
1277
- return this.injector.get(ToastrService);
1278
- }
1279
- init() {
1280
- return __awaiter(this, void 0, void 0, function* () {
1281
- let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
1282
- this.expiredSessionSwal = swal.mixin({
1283
- showCancelButton: false,
1284
- confirmButtonText: 'Login',
1285
- customClass: {
1286
- confirmButton: "btn btn-primary",
1287
- container: "app-wrap",
1288
- },
1289
- buttonsStyling: false,
1290
- reverseButtons: false,
1291
- allowOutsideClick: false,
1292
- icon: "warning"
1293
- });
1294
- this.successSwalWithCancel = swal.mixin({
1295
- title: this.loc["Success"][LOCALE],
1296
- customClass: {
1297
- confirmButton: "btn btn-primary",
1298
- cancelButton: "btn btn-secondary app-margin-right-10",
1299
- container: "app-wrap",
1300
- },
1301
- buttonsStyling: false,
1302
- reverseButtons: true,
1303
- showCancelButton: true,
1304
- confirmButtonText: this.loc["Confirm"][LOCALE],
1305
- cancelButtonText: this.loc["Cancel"][LOCALE],
1306
- icon: "success"
1307
- });
1308
- this.warningSwalWithCancel = swal.mixin({
1309
- title: this.loc["Warning"][LOCALE],
1310
- customClass: {
1311
- confirmButton: "btn btn-primary",
1312
- cancelButton: "btn btn-secondary app-margin-right-10",
1313
- container: "app-wrap",
1314
- },
1315
- buttonsStyling: false,
1316
- reverseButtons: true,
1317
- showCancelButton: true,
1318
- confirmButtonText: this.loc["Confirm"][LOCALE],
1319
- cancelButtonText: this.loc["Cancel"][LOCALE],
1320
- icon: "warning"
1321
- });
1322
- this.warningSwal = swal.mixin({
1323
- title: this.loc["Warning"][LOCALE],
1324
- customClass: {
1325
- confirmButton: "btn btn-primary",
1326
- container: "app-wrap",
1327
- },
1328
- buttonsStyling: false,
1329
- reverseButtons: true,
1330
- showCancelButton: false,
1331
- confirmButtonText: this.loc["Close"][LOCALE],
1332
- icon: "warning"
1333
- });
1334
- this.successSwal = swal.mixin({
1335
- title: this.loc["Success"][LOCALE],
1336
- customClass: {
1337
- confirmButton: "btn btn-primary",
1338
- container: "app-wrap",
1339
- },
1340
- buttonsStyling: false,
1341
- reverseButtons: true,
1342
- showCancelButton: false,
1343
- confirmButtonText: this.loc["Close"][LOCALE],
1344
- icon: "success"
1345
- });
1346
- this.errorSwal = swal.mixin({
1347
- title: this.loc["Error"][LOCALE],
1348
- customClass: {
1349
- confirmButton: "btn btn-primary",
1350
- container: "app-wrap",
1351
- },
1352
- buttonsStyling: false,
1353
- reverseButtons: true,
1354
- showCancelButton: false,
1355
- confirmButtonText: this.loc["Close"][LOCALE],
1356
- icon: "error"
1357
- });
1358
- this.infoSwal = swal.mixin({
1359
- title: this.loc["Info"][LOCALE],
1360
- customClass: {
1361
- confirmButton: "btn btn-primary",
1362
- container: "app-wrap",
1363
- },
1364
- buttonsStyling: false,
1365
- reverseButtons: true,
1366
- showCancelButton: false,
1367
- confirmButtonText: this.loc["Close"][LOCALE],
1368
- icon: "info"
1369
- });
1370
- });
1371
- }
1372
- /**
1373
- * Presentazione di un semplice messaggio di successo
1374
- *
1375
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1376
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1377
- *
1378
- * @param {string} text Testo da mostrare
1379
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1380
- */
1381
- simpleSuccess(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1382
- if (this.emb.Embedded) {
1383
- this.emb.MainWindow.postMessage({ type: "alert", level: 'success', msg: text }, "*");
1384
- return;
1192
+ this.RedirectMap = {};
1193
+ this.RoutesMap = {};
1194
+ for (let prop in this.RedirectMap) {
1195
+ this.RoutesMap[prop] = { route: null };
1196
+ this.RoutesMap[prop].route = (param) => {
1197
+ let obj = {};
1198
+ obj[this.RedirectMap[prop].params[0]] = param;
1199
+ return [(this.emb.Embedded ? "pages_ext/" : "pages/") + this.RedirectMap[prop].url, obj];
1200
+ };
1385
1201
  }
1386
- let tos = this.toastrOrSwal(secondaryNotificationType);
1387
- if (tos == "swal")
1388
- this.successSwal.fire("", text);
1389
- else
1390
- this.toastr.success(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1202
+ }
1203
+ }
1204
+ BaseExtensionsService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseExtensionsService, deps: [{ token: AppEmbeddingExtensions }], target: i0.ɵɵFactoryTarget.Injectable });
1205
+ BaseExtensionsService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseExtensionsService, providedIn: "root" });
1206
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: BaseExtensionsService, decorators: [{
1207
+ type: Injectable,
1208
+ args: [{ providedIn: "root" }]
1209
+ }], ctorParameters: function () { return [{ type: AppEmbeddingExtensions }]; } });
1210
+
1211
+ /**
1212
+ * Suffisso della proprietà da generare in cui salvare il navigatore
1213
+ * utilizzato dal servizio di esportazione per prendere il valore delle proprietà di un oggetto
1214
+ */
1215
+ const csvValueNavigator = "_csvnav";
1216
+ /** Suffisso con le informazioni del tipo per le esportazioni di oggetti */
1217
+ const csvValueType = "_csvtype";
1218
+ /** Suffisso della proprietà da generare in cui salvare l'ordine di esportazione */
1219
+ const csvOrdPrefix = "_csvord";
1220
+ /** Suffisso della proprietà da generare in cui salvare la visibilità di questa proprietà */
1221
+ const csvVisPrefix = "_csvvis";
1222
+ /** Suffisso della proprietà da generare in cui salvare il nome della colonna in cui salvare questa proprietà */
1223
+ const csvHdrPrefix = "_csvhdr";
1224
+ /** Suffisso della proprietà da generare in cui salvare il codice del th a cui si riferisce questo campo */
1225
+ const csvPropKey = "_csvkey";
1226
+ /** Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Lista */
1227
+ const listCsvValPrefix = "_listcsvval";
1228
+ /** Suffisso della proprietà da generare in cui salvare l'Header della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix** */
1229
+ const listCsvHdrPrefix = "_listcsvhdr";
1230
+ /** Suffisso della proprietà da generare in cui salvare il formato della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix** */
1231
+ const listCsvValFormat = "_listcsvvalformat";
1232
+ /** Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Dizionario */
1233
+ const dictionaryCsvValPrefix = "_flatlistcsvval";
1234
+ /** Suffisso della proprietà da generare in cui salvare l'Header della proprietà di un Dizionario relativo al valore esportato nella proprietà con suffisso **dictionaryCsvValPrefix** */
1235
+ const dictionaryCsvHdrPrefix = "_flatlistcsvhdr";
1236
+ /** Suffisso della proprietà da generare in cui salvare il formato della proprietà che si sta esportando */
1237
+ const csvFormatPrefix = "_csvfmt";
1238
+ /** Nome della proprietà che contiene tutti i nomi di tutte le proprietà da esportare */
1239
+ const exportList = "__export_list__";
1240
+ /** Nome della proprietà che contiene la classe di localizzazione da utilizzare per una data esportazione */
1241
+ const locProperty = "__loc__";
1242
+
1243
+ /**
1244
+ * Mappatura del TypeCode del C#
1245
+ */
1246
+ var TypeCode;
1247
+ (function (TypeCode) {
1248
+ /** @ignore */ TypeCode[TypeCode["Empty"] = 0] = "Empty";
1249
+ /** @ignore */ TypeCode[TypeCode["Obj"] = 1] = "Obj";
1250
+ /** @ignore */ TypeCode[TypeCode["DBNull"] = 2] = "DBNull";
1251
+ /** @ignore */ TypeCode[TypeCode["Boolean"] = 3] = "Boolean";
1252
+ /** @ignore */ TypeCode[TypeCode["Char"] = 4] = "Char";
1253
+ /** @ignore */ TypeCode[TypeCode["SByte"] = 5] = "SByte";
1254
+ /** @ignore */ TypeCode[TypeCode["Byte"] = 6] = "Byte";
1255
+ /** @ignore */ TypeCode[TypeCode["Int16"] = 7] = "Int16";
1256
+ /** @ignore */ TypeCode[TypeCode["UInt16"] = 8] = "UInt16";
1257
+ /** @ignore */ TypeCode[TypeCode["Int32"] = 9] = "Int32";
1258
+ /** @ignore */ TypeCode[TypeCode["UInt32"] = 10] = "UInt32";
1259
+ /** @ignore */ TypeCode[TypeCode["Int64"] = 11] = "Int64";
1260
+ /** @ignore */ TypeCode[TypeCode["UInt64"] = 12] = "UInt64";
1261
+ /** @ignore */ TypeCode[TypeCode["Single"] = 13] = "Single";
1262
+ /** @ignore */ TypeCode[TypeCode["Double"] = 14] = "Double";
1263
+ /** @ignore */ TypeCode[TypeCode["Decimal"] = 15] = "Decimal";
1264
+ /** @ignore */ TypeCode[TypeCode["DateTime"] = 16] = "DateTime";
1265
+ /** @ignore */ TypeCode[TypeCode["String"] = 18] = "String";
1266
+ })(TypeCode || (TypeCode = {}));
1267
+
1268
+ // Angular
1269
+ /**
1270
+ * Service che fornisce metodi di pubblica utilità
1271
+ */
1272
+ class UtilityService {
1273
+ constructor() {
1274
+ // Funzione di throttling per non spammare richieste in caso di animazioni attivate
1275
+ //TODO: spostarla in un metodo di utilit� (esfaenza/extensions)
1276
+ /** @ignore */
1277
+ this.executionTimers = {};
1391
1278
  }
1392
1279
  /**
1393
- * Presentazione di un semplice messaggio di informazione
1394
- *
1395
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1396
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1397
- *
1398
- * @param {string} text Testo da mostrare
1399
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1280
+ * Deseleziona il testo eventualmente selezionato
1400
1281
  */
1401
- simpleInfo(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1402
- if (this.emb.Embedded) {
1403
- this.emb.MainWindow.postMessage({ type: "alert", level: 'info', msg: text }, "*");
1404
- return;
1282
+ clearTextSelection() {
1283
+ if (window.getSelection) {
1284
+ if (window.getSelection().empty) // Chrome
1285
+ window.getSelection().empty();
1286
+ else if (window.getSelection().removeAllRanges) // Firefox
1287
+ window.getSelection().removeAllRanges();
1405
1288
  }
1406
- let tos = this.toastrOrSwal(secondaryNotificationType);
1407
- if (tos == "swal")
1408
- this.infoSwal.fire("", text);
1409
- else
1410
- this.toastr.info(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1289
+ else if (document.selection) // IE?
1290
+ document.selection.empty();
1411
1291
  }
1412
1292
  /**
1413
- * Presentazione di un semplice messaggio di errore
1293
+ * Partendo da una lista, dato il nome della proprietà chiave e il valore della chiave selezionata,
1294
+ * trova e restituisce l'oggetto desiderato
1414
1295
  *
1415
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1416
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1296
+ * @param {T[]} sourceList Lista di oggetti dentro cui cercare
1297
+ * @param {string} sourceItemIdField Nome della proprietà che rappresenta la chiave di un oggetto di tipo T
1298
+ * @param {string} selectedValue Valore di chiave selezionato
1417
1299
  *
1418
- * @param {string} text Testo da mostrare
1419
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1300
+ * @returns {T} Oggetto la cui proprietà **sourceItemIdField** assume il valore **selectedValue**
1420
1301
  */
1421
- simpleError(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1422
- if (this.emb.Embedded) {
1423
- this.emb.MainWindow.postMessage({ type: "alert", level: 'error', msg: text }, "*");
1424
- return;
1302
+ getSelectedItem(sourceList, sourceItemIdField, selectedValue) {
1303
+ for (let i = 0; i < sourceList.length; i++) {
1304
+ var item = sourceList[i];
1305
+ if (item[sourceItemIdField] == selectedValue)
1306
+ return item;
1425
1307
  }
1426
- let tos = this.toastrOrSwal(secondaryNotificationType);
1427
- if (tos == "swal")
1428
- this.errorSwal.fire("", text);
1429
- else
1430
- this.toastr.error(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1308
+ return null;
1431
1309
  }
1432
1310
  /**
1433
- * Presentazione di un semplice messaggio di avviso
1434
- *
1435
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1436
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1311
+ * Effettua il reset di un Form di Angular
1437
1312
  *
1438
- * @param {string} text Testo da mostrare
1439
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1313
+ * @param {NgForm} form Form da resettare
1314
+ * @param {string} exception1 Campo da non resettare
1315
+ * @param {string} exception2 Campo da non resettare
1440
1316
  */
1441
- simpleWarning(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1442
- if (this.emb.Embedded) {
1443
- this.emb.MainWindow.postMessage({ type: "alert", level: 'warning', msg: text }, "*");
1444
- return;
1317
+ cleanForm(form, exception1 = null, exception2 = null) {
1318
+ for (let name in form.controls) {
1319
+ if (name && name != exception1 && name != exception1 + "_internal" && name != exception2 && name != exception2 + "_internal") {
1320
+ form.controls[name].reset();
1321
+ }
1322
+ else {
1323
+ form.controls[name].markAsPristine();
1324
+ form.controls[name].markAsUntouched();
1325
+ }
1445
1326
  }
1446
- let tos = this.toastrOrSwal(secondaryNotificationType);
1447
- if (tos == "swal")
1448
- this.warningSwal.fire("", text);
1449
- else
1450
- this.toastr.warning(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1451
- }
1452
- /**
1453
- * Ripulisce tutti i messaggi presenti in un dato momento sullo schermo
1454
- */
1455
- clearMessages() {
1456
- this.toastr.clear();
1457
- swal.close();
1327
+ //Reimposto il submitted
1328
+ form.submitted = false;
1458
1329
  }
1459
1330
  /**
1460
- * Mostra un messaggio di avviso con richiesta di conferma
1461
- *
1462
- * @param {string} title Titolo del messaggio
1463
- * @param {string} text Contenuto del messaggio
1331
+ * Helper che permette di scaricare un file dato un URL (Generato da una chiamata ad **window.URL.createObjectURL**)
1464
1332
  *
1465
- * @returns {Promise} Restituisce una Promise col risultato scelto dall'utente (conferma o no)
1333
+ * @param {string} url ObjectURL che rappresenta il file da scaricare
1334
+ * @param {string} filename Nome del file suggerito in fase di salvataggio
1466
1335
  */
1467
- promiseWarningWithChoice(title, text) {
1468
- return this.warningSwalWithCancel.fire(title, text);
1336
+ fileDownload(url, fileName) {
1337
+ var a = document.createElement("a");
1338
+ document.body.appendChild(a);
1339
+ a.className = "ta-display-none";
1340
+ a.href = url;
1341
+ a.download = fileName;
1342
+ a.click();
1343
+ window.URL.revokeObjectURL(url);
1344
+ document.body.removeChild(a);
1469
1345
  }
1470
1346
  /**
1471
- * In base alla configurazione attuale e all'eventuale override per la chiamata del caso indica se bisogna utilizzare toastr o sweetalert
1347
+ * Helper per la formattazione di un numero di millisecondi in una stringa più comprensibile per un umano
1472
1348
  *
1473
- * @param {"toastr" | "swal" | null} providerOverride Override alla modalità configurata
1349
+ * @param {number} duration Tempo espresso in millisecondi
1474
1350
  *
1475
- * @returns {"toastr" | "swal"} Indicazione su che provider di messaggi di avviso debba essere utilizzato
1351
+ * @returns {string} Durata formattata
1476
1352
  */
1477
- toastrOrSwal(providerOverride) {
1478
- if (providerOverride != null)
1479
- return providerOverride;
1480
- return "swal";
1353
+ msToTime(duration) {
1354
+ if (!duration)
1355
+ return "";
1356
+ var milliseconds = parseInt(((duration % 1000) / 100).toString()), seconds = parseInt(((duration / 1000) % 60).toString()), minutes = parseInt(((duration / (1000 * 60)) % 60).toString()), hours = parseInt(((duration / (1000 * 60 * 60)) % 24).toString());
1357
+ var st_hours = (hours < 10) ? "0" + hours : hours;
1358
+ var st_minutes = (minutes < 10) ? "0" + minutes : minutes;
1359
+ var st_seconds = (seconds < 10) ? "0" + seconds : seconds;
1360
+ return st_hours + ":" + st_minutes + ":" + st_seconds + "." + milliseconds;
1481
1361
  }
1482
1362
  /**
1483
- * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
1363
+ * Helper che permette di scaricare un file in Base64
1484
1364
  *
1485
- * @param {string} title Titolo del messaggio
1486
- * @param {string} text Contenuto del messaggio
1487
- * @param {Function} onsuccess Callback da chimare su conferma
1488
- * @param {Function} onerror Callback da chimare su errori
1365
+ * @param {string} base64Data Base64 che rappresenta il file da scaricare
1366
+ * @param {string} filename Nome del file suggerito in fase di salvataggio
1489
1367
  */
1490
- simpleWarningWithChoice(title, text, onsuccess = null, onerror = null) {
1491
- this.warningSwalWithCancel.fire(title, text).then((result) => {
1492
- if (result.value && onsuccess)
1493
- onsuccess();
1494
- else if (onerror)
1495
- onerror();
1496
- });
1368
+ saveFile(base64Data, filename) {
1369
+ var sampleArr = this.base64ToArrayBuffer(base64Data);
1370
+ this.saveByteArray(sampleArr, filename);
1497
1371
  }
1498
1372
  /**
1499
- * Mostra un messaggio di success con richiesta di conferma e gestisce il risultato chiamato i callback **onconfirm** o **onabort**
1373
+ * Trasforma un Base64 in un ArrayBuffer
1500
1374
  *
1501
- * @param {string} title Titolo del messaggio
1502
- * @param {string} text Contenuto del messaggio
1503
- * @param {Function} onconfirm Callback da chimare su conferma
1504
- * @param {Function} onabort Callback da chimare su annullamento
1505
- * @param {string} confirmtext Testo del pulsante di azione
1506
- * @param {string} aborttext Testo del pulsante di annullamento
1507
- */
1508
- simpleSuccessWithChoice(title, text, onconfirm = null, onabort = null, confirmtext = "", aborttext = '') {
1509
- var configuration = {
1510
- title: title,
1511
- html: text
1512
- };
1513
- if (confirmtext)
1514
- configuration["confirmButtonText"] = confirmtext;
1515
- if (aborttext)
1516
- configuration["cancelButtonText"] = aborttext;
1517
- this.successSwalWithCancel.fire(configuration).then((result) => {
1518
- if (result.value && onconfirm)
1519
- onconfirm();
1520
- else if (onabort)
1521
- onabort();
1522
- });
1523
- }
1524
- /**
1525
- * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
1375
+ * @param {string} base64Data Base64 da trasformare
1526
1376
  *
1527
- * @param {string} title Titolo del messaggio
1528
- * @param {string} text Contenuto del messaggio
1377
+ * @returns {Uint8Array} Array UTF8
1529
1378
  */
1530
- observableSimpleWarningWithChoice(title, text) {
1531
- return of(this.warningSwalWithCancel.fire(title, text)).pipe(map(t => !!t.value));
1379
+ base64ToArrayBuffer(base64Data) {
1380
+ var binaryString = window.atob(base64Data);
1381
+ var binaryLen = binaryString.length;
1382
+ var bytes = new Uint8Array(binaryLen);
1383
+ for (var i = 0; i < binaryLen; i++) {
1384
+ var ascii = binaryString.charCodeAt(i);
1385
+ bytes[i] = ascii;
1386
+ }
1387
+ return bytes;
1532
1388
  }
1533
1389
  /**
1534
- * Mostra un messaggio di avviso che la sessione corrente è scaduta e propone all'utente di navigare al login. Qualora l'utente decidesse di farlo
1535
- * verrà chiamata la funzione di callback **onnavigate
1390
+ * Helper che permette di scaricare un file dato un array di Byte (**Uint8Array**)
1536
1391
  *
1537
- * @param {string} title Titolo del messaggio
1538
- * @param {string} text Contenuto del messaggio
1539
- * @param {Function} onnavigate Callback da chimare su navigazione in corso
1392
+ * @param {Uint8Array} byte Rappresentazione del file da scaricare
1393
+ * @param {string} filename Nome del file suggerito in fase di salvataggio
1540
1394
  */
1541
- expiredSessionMessage(title, text, onnavigate = null) {
1542
- this.expiredSessionSwal.fire(title, text).then((result) => {
1543
- if (result.value && onnavigate)
1544
- onnavigate();
1545
- });
1395
+ saveByteArray(byte, filename) {
1396
+ var blob = new Blob([byte]);
1397
+ var link = document.createElement("a");
1398
+ document.body.appendChild(link);
1399
+ link.href = window.URL.createObjectURL(blob);
1400
+ var fileName = filename;
1401
+ link.download = fileName;
1402
+ link.click();
1403
+ document.body.removeChild(link);
1546
1404
  }
1405
+ ;
1547
1406
  /**
1548
- * Metodo helper per gestire in maniera standardizzata una risposta di tipo **CallResult**
1407
+ * Utility per lo swap di due elementi di un array
1549
1408
  *
1550
- * @param {CallResult} response Risposta ricevuta dal server
1551
- * @param {string} successMsg Messaggio da visualizzare in caso di successo
1552
- * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1553
- * @param {Function} postSuccess Callback da chimare in caso di successo
1554
- * @param {Function} postFailure Callback da chimare in caso di fallimento
1409
+ * @param {any[]} array Array di cui invertire due elementi
1410
+ * @param {number} x Indice del primo elemento
1411
+ * @param {number} y Indice del secondo elemento
1555
1412
  */
1556
- manageCallResultResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1557
- if (response.success) {
1558
- if (response.haswarning)
1559
- this.simpleWarning(response.warning);
1560
- else if (successMsg)
1561
- this.simpleSuccess(successMsg);
1562
- if (postSuccess)
1563
- postSuccess();
1564
- }
1565
- else {
1566
- this.simpleError((errorMsg ? errorMsg + ": " : "") + response.haserror ? response.error : '[NO ERR.]');
1567
- if (postFailure)
1568
- postFailure();
1569
- }
1413
+ swap(array, x, y) {
1414
+ var b = array[x];
1415
+ array[x] = array[y];
1416
+ array[y] = b;
1570
1417
  }
1571
1418
  /**
1572
- * Metodo helper per gestire in maniera standardizzata una risposta di tipo **string**, considerando che:
1573
- *
1574
- * Stringa vuota --> Tutto bene
1419
+ * Helper di trascodifica da tipo c# a tipo Typescript
1575
1420
  *
1576
- * Stringa piena --> Questo è il messaggio d'errore per cui la chiamata è fallita
1421
+ * @param {TypeCode} type Tipo da trascodificare
1577
1422
  *
1578
- * @param {string} response Risposta ricevuta dal server
1579
- * @param {string} successMsg Messaggio da visualizzare in caso di successo
1580
- * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1581
- * @param {Function} postSuccess Callback da chimare in caso di successo
1582
- * @param {Function} postFailure Callback da chimare in caso di fallimento
1423
+ * @returns {"boolean" | "number" | "string" | "date"} Tipo Typescript corrispondente
1583
1424
  */
1584
- manageStringResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1585
- if (!response) {
1586
- if (successMsg)
1587
- this.simpleSuccess(successMsg);
1588
- if (postSuccess)
1589
- postSuccess();
1590
- }
1591
- else {
1592
- if (errorMsg)
1593
- this.simpleError(errorMsg + ": " + response);
1594
- if (postFailure)
1595
- postFailure();
1425
+ getJsTypeFromTypeCode(type) {
1426
+ switch (type) {
1427
+ case TypeCode.Boolean:
1428
+ return "boolean";
1429
+ case TypeCode.Decimal:
1430
+ case TypeCode.Double:
1431
+ case TypeCode.Single:
1432
+ case TypeCode.Int16:
1433
+ case TypeCode.Int32:
1434
+ case TypeCode.Int64:
1435
+ case TypeCode.Byte:
1436
+ case TypeCode.SByte:
1437
+ case TypeCode.UInt16:
1438
+ case TypeCode.UInt32:
1439
+ case TypeCode.UInt64:
1440
+ return "number";
1441
+ case TypeCode.Char:
1442
+ case TypeCode.String:
1443
+ return "string";
1444
+ case TypeCode.DateTime:
1445
+ return "date";
1446
+ default:
1447
+ console.log("Unrecognized input type. Typecode:" + type);
1448
+ return "string";
1596
1449
  }
1597
1450
  }
1598
1451
  /**
1599
- * Metodo helper per gestire in maniera standardizzata una risposta di tipo **boolean**
1452
+ * Effettua la clonazione profonda di un oggetto in maniera molto più performante che JSON.parse(JSON.stringify()).
1600
1453
  *
1601
- * @param {string} response Risposta ricevuta dal server
1602
- * @param {string} successMsg Messaggio da visualizzare in caso di successo
1603
- * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1604
- * @param {Function} postSuccess Callback da chimare in caso di successo
1605
- * @param {Function} postFailure Callback da chimare in caso di fallimento
1454
+ * Usare solo per oggetti puri e quantomeno semplici per evitare complicazioni derivanti dalle semplificazioni che questo metodo assume
1455
+ *
1456
+ * @param {any} source Oggetto da clonare
1457
+ *
1458
+ * @return {any} Clone dell'oggetto passato
1606
1459
  */
1607
- manageStringResponseBool(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1608
- if (response) {
1609
- if (successMsg)
1610
- this.simpleSuccess(successMsg);
1611
- if (postSuccess)
1612
- postSuccess();
1460
+ deepClone(source) {
1461
+ // Valori semplici
1462
+ if (source == null || typeof source !== 'object')
1463
+ return source;
1464
+ // Pseudo Struct
1465
+ switch (toString.call(source)) {
1466
+ case '[object Boolean]':
1467
+ case '[object Number]':
1468
+ case '[object String]':
1469
+ case '[object Date]':
1470
+ return new source.constructor(source.valueOf());
1471
+ // Clonazione di un file -> Restituisco il riferimento al file stesso
1472
+ case "[object File]":
1473
+ return source;
1474
+ default: break;
1613
1475
  }
1614
- else {
1615
- if (errorMsg)
1616
- this.simpleError(errorMsg);
1617
- if (postFailure)
1618
- postFailure();
1476
+ // Oggetti Complessi
1477
+ return this.recursiveStep(source, Array.isArray(source) || source instanceof Array ? [] : Object.create(Object.getPrototypeOf(source)));
1478
+ }
1479
+ /**
1480
+ * @ignore
1481
+ * Step ricorsivo per la clonatura degli oggetti. Vedere **deepClone**
1482
+ */
1483
+ recursiveStep(source, destination) {
1484
+ if (Array.isArray(source) || source instanceof Array) {
1485
+ for (var i = 0, ii = source.length; i < ii; i++)
1486
+ destination.push(this.deepClone(source[i]));
1487
+ }
1488
+ else if (source && typeof source.hasOwnProperty === 'function') {
1489
+ for (let key in source) {
1490
+ if (source.hasOwnProperty(key))
1491
+ destination[key] = this.deepClone(source[key]);
1492
+ }
1619
1493
  }
1494
+ return destination;
1495
+ }
1496
+ cast(object, clss) {
1497
+ let ret = Object.assign(Object.create(clss.prototype), object);
1498
+ return ret;
1499
+ }
1500
+ /** @ignore */
1501
+ throttla(id, func, throttleTime) {
1502
+ //Se ho la funzione che vuole eseguire ripulisco quel timeout
1503
+ if (this.executionTimers[id])
1504
+ clearTimeout(this.executionTimers[id]);
1505
+ //Ricreo il timeout per eseguire quella funzione dopo throttleTime millisecondi
1506
+ this.executionTimers[id] = setTimeout(() => { func(); this.executionTimers[id] = null; }, throttleTime);
1620
1507
  }
1621
1508
  }
1622
- MessageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, deps: [{ token: Injector }, { token: i1.BaseLocalization, optional: true }, { token: AppEmbeddingExtensions }], target: i0.ɵɵFactoryTarget.Injectable });
1623
- MessageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, providedIn: "root" });
1624
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, decorators: [{
1509
+ UtilityService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1510
+ UtilityService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, providedIn: "root" });
1511
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, decorators: [{
1625
1512
  type: Injectable,
1626
1513
  args: [{ providedIn: "root" }]
1627
- }], ctorParameters: function () {
1628
- return [{ type: i0.Injector, decorators: [{
1629
- type: Inject,
1630
- args: [Injector]
1631
- }] }, { type: i1.BaseLocalization, decorators: [{
1632
- type: Optional
1633
- }] }, { type: AppEmbeddingExtensions }];
1634
- } });
1514
+ }] });
1635
1515
 
1636
1516
  /**
1637
- * Service che fornisce un accesso base in lettura/scrittura sulla clipboard
1517
+ * Decoratore che fornisce la classe di localizzazione per tutte le proprietà esportate con @Export e qualsiasi altro tag che richieda localizzazioni.
1518
+ *
1519
+ * Sostanzilamente aggiunge la proprietà **__loc__** all'oggetto creato dalla classe corrente assegnandogli come valore il tipo del LocalizationService da usare per la traduzione
1520
+ *
1521
+ * @param {Type<LocalizationService>} loc Tipo ereditato dal LocalizationService che può essere creato a runtime sotto contesto della DI di Angular
1638
1522
  */
1639
- class ClipboardService {
1640
- /**
1641
- * Costruttore
1642
- *
1643
- * @ignore
1644
- */
1645
- constructor(msgService, locProvider) {
1646
- this.msgService = msgService;
1647
- this.locProvider = locProvider;
1648
- /**
1649
- * Oggetto statico di localizzazione per i messaggi di questa Service
1650
- */
1651
- this.loc = {
1652
- "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation": {
1653
- 'en-US': "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation",
1654
- 'it-IT': "Mi dispiace ma Firefox non supporta l'accesso diretto alla Clipboard, se non attraverso le estensioni. Si prega di usare Chrome"
1655
- },
1656
- "Generic error during 'copy' command execution": {
1657
- 'en-US': "Generic error during 'copy' command execution",
1658
- 'it-IT': "Errore generico durante l'esecuzione del comando 'copy'"
1659
- },
1660
- "Error during Clipboard content read operation": {
1661
- 'en-US': "Error during Clipboard content read operation",
1662
- 'it-IT': "Errore nella lettura del contenuto della Clipboard"
1663
- },
1664
- "Error during Clipboard content copy operation": {
1665
- 'en-US': "Error during Clipboard content copy operation",
1666
- 'it-IT': "Errore nella scrittura del contenuto nella Clipboard"
1667
- },
1668
- "Please insert your clipboard content": {
1669
- 'en-US': "Please insert your clipboard content",
1670
- 'it-IT': "Si prega di incollare il contenuto della Clipboard"
1671
- },
1672
- "User input required": {
1673
- 'en-US': "User input required",
1674
- 'it-IT': "Richiesto Input utente"
1675
- },
1676
- "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation": {
1677
- 'en-US': "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation",
1678
- 'it-IT': "Il browser corrente non supporta la lettura diretta dei dati della Clipboard, si prega di effettuare un'incolla (CTRL + V) nella casella di testo e confermare l'operazione"
1679
- },
1680
- "Confirm": {
1681
- 'en-US': "Confirm",
1682
- 'it-IT': "Conferma"
1683
- },
1684
- "Cancel": {
1685
- 'en-US': "Cancel",
1686
- 'it-IT': "Annulla"
1687
- },
1688
- };
1689
- }
1690
- /**
1691
- * Prende il valore della clipboard.
1692
- * Si può specificare se ci si aspetta una lista o una matrice di valori in modo da ricevere già un risultato utilizzabile
1693
- *
1694
- * @param {'array' | 'matrix'} style Stile dell'output desiderato, se array o matrice
1695
- * @param {Function} valueFoundCallback Callback che questa funzione chiamerà una volta ottenuto i valori richiesti dalla clipboard
1696
- */
1697
- getClipboard(style, valueFoundCallback) {
1698
- return __awaiter(this, void 0, void 0, function* () {
1699
- let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
1700
- if (navigator.userAgent.indexOf("Firefox") != -1) {
1701
- swal.fire({
1702
- title: this.loc["User input required"][LOCALE],
1703
- text: this.loc["Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation"][LOCALE],
1704
- input: 'textarea',
1705
- icon: "warning",
1706
- confirmButtonText: this.loc["Confirm"][LOCALE],
1707
- cancelButtonText: this.loc["Cancel"][LOCALE],
1708
- showCancelButton: true,
1709
- customClass: {
1710
- confirmButton: "btn btn-primary",
1711
- cancelButton: "btn btn-secondary app-margin-right-15",
1712
- container: "app-wrap",
1713
- },
1714
- reverseButtons: true,
1715
- allowOutsideClick: false,
1716
- inputValidator: (value) => {
1717
- if (!value)
1718
- return this.loc["Please insert your clipboard content"][LOCALE];
1719
- }
1720
- }).then(t => {
1721
- if (t.isConfirmed) {
1722
- console.log("[@esfaenza/extensions] Retrieving input data from user input");
1723
- this.doClipboardDataGet(t.value, style, valueFoundCallback);
1724
- }
1725
- });
1726
- return;
1727
- }
1728
- if (window.clipboardData) {
1729
- console.log("[@esfaenza/extensions] Found clipboardData");
1730
- let data = window.clipboardData.getData("Text");
1731
- this.doClipboardDataGet(data, style, valueFoundCallback);
1732
- }
1733
- else if (window.navigator.clipboard) {
1734
- console.log("[@esfaenza/extensions] Found navigator clipboard");
1735
- window.navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
1736
- if (!(result.state === 'granted' || result.state === 'prompt')) {
1737
- console.error("[@esfaenza/extensions] Clipboard permission not granted");
1738
- if (valueFoundCallback)
1739
- valueFoundCallback([]);
1740
- return;
1741
- }
1742
- console.log("[@esfaenza/extensions] Clipboard permission granted, retrieving values");
1743
- window.navigator.clipboard.readText()
1744
- .then((t) => this.doClipboardDataGet(t, style, valueFoundCallback))
1745
- .catch((err) => this.msgService.simpleError(this.loc["Error during Clipboard content read operation"][LOCALE] + ": " + err));
1746
- });
1523
+ function ExportLocalization(loc) {
1524
+ return function integrateLoc(constructor) {
1525
+ return class extends constructor {
1526
+ constructor() {
1527
+ super(...arguments);
1528
+ this.__loc__ = loc;
1747
1529
  }
1748
- });
1749
- }
1750
- /** @ignore */
1751
- doClipboardDataGet(clipboardText, style, valueFoundCallback) {
1752
- console.log("[@esfaenza/extensions] Retrieved clipboard values: " + clipboardText);
1753
- let value = style == "array" ? this.getClipboardLines(clipboardText) :
1754
- style == "matrix" ? this.getClipboardMatrix(clipboardText) : [];
1755
- console.log(`[@esfaenza/extensions] Adapted for ${style}: ${JSON.stringify(value)}`);
1756
- if (valueFoundCallback)
1757
- valueFoundCallback(value);
1530
+ };
1531
+ };
1532
+ }
1533
+ /**
1534
+ * Decoratore di esportazione utilizzabile su una proprietà singola.
1535
+ * Verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
1536
+ *
1537
+ * Ad esempio, da questa configurazione:
1538
+ *
1539
+ * @example
1540
+ * ```
1541
+ * @Export(true, "MyHeader")
1542
+ * ciao: string;
1543
+ * ```
1544
+ *
1545
+ * Nasceranno le seguenti proprietà nell'oggetto esportabile:
1546
+ *
1547
+ * @example
1548
+ * ```
1549
+ * ciao_csvvis: string; => true
1550
+ * ciao: string;
1551
+ * ciao_csvhdr: string => "MyHeader"
1552
+ * ```
1553
+ *
1554
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
1555
+ * @param {string} header Titolo della colonna nel file CSV esportato
1556
+ * @param {string} format Formato di esportazione. Può essere un formato data per i campi data o 'F' per i campi floating point
1557
+ */
1558
+ const Export = (order, header, format = null, tableid = null) => (target, propertyKey) => {
1559
+ if (format)
1560
+ Object.defineProperty(target, propertyKey + csvFormatPrefix, { value: format, writable: false });
1561
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
1562
+ Object.defineProperty(target, propertyKey + csvVisPrefix, { value: !!header, writable: false });
1563
+ Object.defineProperty(target, propertyKey + csvHdrPrefix, { value: header, writable: false });
1564
+ if (tableid)
1565
+ Object.defineProperty(target, propertyKey + csvPropKey, { value: tableid, writable: false });
1566
+ if (target[exportList])
1567
+ target[exportList].push(propertyKey + csvVisPrefix);
1568
+ else
1569
+ target[exportList] = [propertyKey + csvVisPrefix];
1570
+ };
1571
+ /**
1572
+ * Decoratore di esportazione utilizzabile su un oggetto.
1573
+ * Per ogni proprietà dell'oggetto verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
1574
+ * Per essere esportate, le proprietà dell'oggetto devono essere marcate con i Decoratori di esportazione
1575
+ *
1576
+ * Ad esempio, da questa configurazione:
1577
+ *
1578
+ * @example
1579
+ * ```
1580
+ * MyObj {
1581
+ * @Export(true, "MyHeader")
1582
+ * ciao: string;
1583
+ * }
1584
+ *
1585
+ * @ExportObject(true, "MyHeader")
1586
+ * test: MyObj;
1587
+ * ```
1588
+ *
1589
+ * Nasceranno le seguenti proprietà nell'oggetto esportabile:
1590
+ *
1591
+ * @example
1592
+ * ```
1593
+ * testciao: string; => Valore di MyObj.ciao
1594
+ * testciao_csvvis: string; => true
1595
+ * testciao_csvhdr: string => "MyHeader"
1596
+ * ```
1597
+ *
1598
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
1599
+ * @param {any} type Tipo da esportare
1600
+ */
1601
+ const ExportAs = (order, type, prefix) => (target, propertyKey) => {
1602
+ var t = new type();
1603
+ var props = t[exportList];
1604
+ for (let i = 0; i < props.length; i++) {
1605
+ let prop = props[i].replace(csvVisPrefix, '');
1606
+ if (typeof t[prop + csvVisPrefix] !== "undefined") {
1607
+ var toEmit = t[prop + csvVisPrefix];
1608
+ var lbl = t[prop + csvHdrPrefix];
1609
+ var format = t[prop + csvFormatPrefix];
1610
+ var orderProp = t[prop + csvOrdPrefix];
1611
+ if (format)
1612
+ Object.defineProperty(target, propertyKey + prop + csvFormatPrefix, { value: format, writable: false });
1613
+ Object.defineProperty(target, propertyKey + prop + csvOrdPrefix, { value: orderProp + order, writable: false });
1614
+ Object.defineProperty(target, propertyKey + prop, { value: null, writable: true, enumerable: true });
1615
+ Object.defineProperty(target, propertyKey + prop + csvValueNavigator, { value: propertyKey + "." + prop, writable: false });
1616
+ Object.defineProperty(target, propertyKey + prop + csvVisPrefix, { value: toEmit, writable: false });
1617
+ Object.defineProperty(target, propertyKey + prop + csvHdrPrefix, { value: (prefix ? prefix + ' ' : '') + lbl, writable: false });
1618
+ Object.defineProperty(target, propertyKey + prop + csvValueType, { value: type, writable: false });
1619
+ if (target[exportList])
1620
+ target[exportList].push(propertyKey + prop + csvVisPrefix);
1621
+ else
1622
+ target[exportList] = [propertyKey + prop + csvVisPrefix];
1623
+ }
1758
1624
  }
1625
+ };
1626
+ /**
1627
+ * Decoratore di esportazione utilizzabile su una lista,
1628
+ * si utilizzano 2 navigator rispettivamente per la valorizzazione dell'Header e del Valore e
1629
+ * per ogni elemento dell'array verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr)
1630
+ *
1631
+ * ATTENZIONE: Gli oggetti esportati in questa modalità non devono presentare altri tag di tipo @Export{...} all'interno. Fa tutto questo decoratore
1632
+ *
1633
+ * I navigator hanno questa convenzione:
1634
+ *
1635
+ * . --> divide due proprietà da richiamare consecutivamente: "a.b" richiamerà "obj.a.b";
1636
+ *
1637
+ * | --> divide più proprietà per le concatenazioni con uno spazio fra una e l'altra: "regdesc|slice.slicename" diventerà obj.regdesc + " " + obj.slice.slicename
1638
+ *
1639
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
1640
+ * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
1641
+ * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
1642
+ * @param {string} valueformat Formato di esportazione per i valori selezionati dal **valuenavigator**. Può essere un formato data per i campi data o 'F' per i campi floating point
1643
+ */
1644
+ const ExportList = (order, headernavigator, valuenavigator, valueformat = null) => (target, propertyKey) => {
1645
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
1646
+ Object.defineProperty(target, propertyKey + listCsvValPrefix, { value: valuenavigator, writable: false });
1647
+ Object.defineProperty(target, propertyKey + listCsvHdrPrefix, { value: headernavigator, writable: false });
1648
+ Object.defineProperty(target, propertyKey + listCsvValFormat, { value: valueformat, writable: false });
1649
+ if (target[exportList])
1650
+ target[exportList].push(propertyKey + listCsvHdrPrefix);
1651
+ else
1652
+ target[exportList] = [propertyKey + listCsvHdrPrefix];
1653
+ };
1654
+ /**
1655
+ * Decoratore di esportazione utilizzabile su un dizionario. Se ad esempio si vogliono generare le colonne
1656
+ *
1657
+ * Valore A = 1
1658
+ *
1659
+ * Valore B = 2
1660
+ *
1661
+ * Valore C = 3
1662
+ *
1663
+ * partendo da un oggetto iniziale { Valore { A: 1, B: 2, C: 3 } }
1664
+ *
1665
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
1666
+ * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
1667
+ * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
1668
+ */
1669
+ const ExportDictionary = (order, headernavigator, valuenavigator) => (target, propertyKey) => {
1670
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
1671
+ Object.defineProperty(target, propertyKey + dictionaryCsvValPrefix, { value: valuenavigator, writable: false });
1672
+ Object.defineProperty(target, propertyKey + dictionaryCsvHdrPrefix, { value: headernavigator, writable: false });
1673
+ if (target[exportList])
1674
+ target[exportList].push(propertyKey + dictionaryCsvHdrPrefix);
1675
+ else
1676
+ target[exportList] = [propertyKey + dictionaryCsvHdrPrefix];
1677
+ };
1678
+ /**
1679
+ * Service che si occupa dell'esportazione degli oggetti marcati dai Decoratori **ExportDictionary**, **ExportList**, **ExportAs** o **Export**
1680
+ */
1681
+ class ExportService {
1759
1682
  /**
1760
- * Ottiene il contenuto della clipboard diviso per righe (separate da newline)
1761
- *
1762
- * @param {string} data contenuto letto dalla clipboard
1683
+ * Costruttore
1763
1684
  *
1764
- * @returns {string[]} Array contenente il testo preso dalla clipboard diviso per riga
1685
+ * @ignore
1765
1686
  */
1766
- getClipboardLines(data) {
1767
- let trimmedData = data.trim();
1768
- if (!trimmedData.includes("\r\n") && trimmedData.includes("\n"))
1769
- return trimmedData.split("\n");
1770
- return trimmedData.split("\r\n");
1687
+ constructor(dates, utiExts, lc) {
1688
+ this.dates = dates;
1689
+ this.utiExts = utiExts;
1690
+ this.lc = lc;
1771
1691
  }
1772
1692
  /**
1773
- * Ottiene il contenuto della clipboard diviso per righe (separate da newline) e colonne (separate da tab)
1693
+ * Data una lista di oggetti genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1774
1694
  *
1775
- * @param {string} data contenuto letto dalla clipboard
1695
+ * @param {any[]} objs Oggetti da esportare
1776
1696
  *
1777
- * @returns {string[][]} Matrice contenente il testo preso dalla clipboard diviso per riga e colonna
1697
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1778
1698
  */
1779
- getClipboardMatrix(data) {
1780
- var ret = [];
1781
- var rows = !data.includes("\r\n") && data.includes("\n") ? data.split("\n") : data.split("\r\n");
1782
- // A quanto pare ogni valore è separato da un \t... spero che sia uno standard di quando si copia da excel altrimenti ciao
1783
- for (let i = 0; i < rows.length; i++)
1784
- ret.push(rows[i].split('\t').map(t => t.trim()));
1785
- return ret;
1699
+ setupForExport(objs, columns = []) {
1700
+ let headers = [];
1701
+ let headersCache = {};
1702
+ if (!objs || objs.length == 0)
1703
+ return headers;
1704
+ // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
1705
+ // Gli header li raccolgo tutti poi faccio uan distinct in modo da esportare tutte le proprietà per bene
1706
+ let columnSelectionDictionary = {};
1707
+ if ((columns === null || columns === void 0 ? void 0 : columns.length) > 0)
1708
+ for (let i = 0; i < (columns === null || columns === void 0 ? void 0 : columns.length); i++)
1709
+ columnSelectionDictionary[columns[i]] = true;
1710
+ for (let i = 0; i < objs.length; i++) {
1711
+ let hds = this.parseAndGetHeaders(objs[i], columnSelectionDictionary);
1712
+ // Aggiungo gli header facendo in modo di non aggiungerne mai due uguali per non dover fare una distinct dopo
1713
+ // che costerebbe comunque risorse. Utilizzo un dizionario d'appoggio per lookup istantanei
1714
+ for (let k = 0; k < hds.length; k++) {
1715
+ if (!headersCache[hds[k].key]) {
1716
+ headersCache[hds[k].key] = true;
1717
+ headers.push(hds[k]);
1718
+ }
1719
+ }
1720
+ }
1721
+ if (!columns || columns.length == 0)
1722
+ return headers.sort((a, b) => a.order - b.order);
1723
+ else {
1724
+ // Se mi arriva la lista di colonne non mi dà solo la visibilità, ma anche l'ordinamento
1725
+ // le esporto di conseguenza
1726
+ let orderedHeaders = [];
1727
+ for (let i = 0; i < columns.length; i++) {
1728
+ let thisId = columns[i];
1729
+ for (let i = 0; i < headers.length; i++) {
1730
+ if (headers[i].propKey == thisId) {
1731
+ orderedHeaders.push(headers[i]);
1732
+ break;
1733
+ }
1734
+ }
1735
+ }
1736
+ return orderedHeaders;
1737
+ }
1786
1738
  }
1787
1739
  /**
1788
- * Metodo che copia un testo all'interno della clipboard
1740
+ * Data una lista di oggetti generici genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1789
1741
  *
1790
- * @param {string} text Testo da inserire nella clipboard
1742
+ * @param {GenericItem[]} objs Oggetti generici da esportare
1743
+ * @param {CsvHeaders[]} columns Colonne richieste dall'esportazione
1744
+ *
1745
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1791
1746
  */
1792
- copyTextToClipboard(text) {
1793
- return __awaiter(this, void 0, void 0, function* () {
1794
- let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
1795
- var textArea = document.createElement("textarea");
1796
- //
1797
- // *** This styling is an extra step which is likely not required. ***
1798
- //
1799
- // Why is it here? To ensure:
1800
- // 1. the element is able to have focus and selection.
1801
- // 2. if element was to flash render it has minimal visual impact.
1802
- // 3. less flakyness with selection and copying which **might** occur if
1803
- // the textarea element is not visible.
1804
- //
1805
- // The likelihood is the element won't even render, not even a flash,
1806
- // so some of these are just precautions. However in IE the element
1807
- // is visible whilst the popup box asking the user for permission for
1808
- // the web page to copy to the clipboard.
1809
- //
1810
- // Place in top-left corner of screen regardless of scroll position.
1811
- textArea.style.position = "fixed";
1812
- textArea.style.top = "0";
1813
- textArea.style.left = "0";
1814
- // Ensure it has a small width and height. Setting to 1px / 1em
1815
- // doesn't work as this gives a negative w/h on some browsers.
1816
- textArea.style.width = "2em";
1817
- textArea.style.height = "2em";
1818
- // We don't need padding, reducing the size if it does flash render.
1819
- textArea.style.padding = "0";
1820
- // Clean up any borders.
1821
- textArea.style.border = "none";
1822
- textArea.style.outline = "none";
1823
- textArea.style.boxShadow = "none";
1824
- // Avoid flash of white box if rendered for any reason.
1825
- textArea.style.background = "transparent";
1826
- textArea.value = text;
1827
- document.body.appendChild(textArea);
1828
- textArea.focus();
1829
- textArea.select();
1830
- try {
1831
- var successful = document.execCommand("copy");
1832
- if (!successful)
1833
- this.msgService.simpleError(this.loc["Generic error during 'copy' command execution"][LOCALE]);
1834
- }
1835
- catch (err) {
1836
- this.msgService.simpleError(this.loc["Error during Clipboard content copy operation"][LOCALE] + ": " + err);
1837
- }
1838
- document.body.removeChild(textArea);
1839
- });
1840
- }
1841
- }
1842
- ClipboardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, deps: [{ token: MessageService }, { token: i1.BaseLocalization, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1843
- ClipboardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, providedIn: "root" });
1844
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, decorators: [{
1845
- type: Injectable,
1846
- args: [{ providedIn: "root" }]
1847
- }], ctorParameters: function () {
1848
- return [{ type: MessageService }, { type: i1.BaseLocalization, decorators: [{
1849
- type: Optional
1850
- }] }];
1851
- } });
1852
-
1853
- // Angular
1854
- /**
1855
- * Service che fornisce alcuni semplici funzioni di Hashing / GUID / ecc...
1856
- */
1857
- class HashingService {
1858
- constructor() {
1859
- /**
1860
- * Blacklist dei tipi da ignorare quando si effettua l'hashing degli oggetti
1861
- */
1862
- this.objBlacklist = {
1863
- "NgForm": true, "ElementRef": true, "ExtensionsService": true, "ToastrService": true, "LocaleService": true, "AppState": true, "Router": true,
1864
- "ActivatedRoute": true, "HTTPService": true, "Location": true, "CanvasComponent": true, "ModalDirective": true, "ChangeDetectorRef": true,
1865
- "DateService": true, "EventEmitter": true, "ViewRef_": true, "Subscriber": true, "ItemLocalization": true
1866
- };
1867
- /**
1868
- * Array dei possibili valori di un simbolo esadecimale
1869
- */
1870
- this.hex_chr = '0123456789abcdef'.split('');
1747
+ setupForGenericExport(objs, columns) {
1748
+ let headers = [];
1749
+ if (!objs || objs.length == 0)
1750
+ return headers;
1751
+ // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
1752
+ objs.forEach((obj, index) => {
1753
+ if (index == 0)
1754
+ headers = this.parseAndGetGenericHeaders(obj, columns);
1755
+ else
1756
+ this.parseAndGetGenericHeaders(obj, columns);
1757
+ });
1758
+ return headers;
1871
1759
  }
1872
1760
  /**
1873
- * Generazione di un GUID pseudo-univoco
1761
+ * Dato un oggetto generico genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1874
1762
  *
1875
- * @returns {string} il GUID generato
1763
+ * Metodo interno richiamato da **setupForGenericExport**
1764
+ *
1765
+ * @param {GenericItem} obj Oggetto generico da esportare
1766
+ * @param {CsvColumn[]} columns Colonne richieste dall'esportazione
1767
+ *
1768
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1876
1769
  */
1877
- getGUID() {
1878
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
1879
- var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);
1880
- return v.toString(16);
1770
+ parseAndGetGenericHeaders(obj, columns) {
1771
+ if (!obj.properties)
1772
+ return null;
1773
+ var headers = [];
1774
+ //Miracle incoming
1775
+ columns.forEach(t => {
1776
+ var propValue = obj.properties[t.key];
1777
+ Object.defineProperty(obj, t.key + "_exp", { value: propValue, writable: false, enumerable: true });
1778
+ headers.push({ label: t.label, key: t.key + "_exp", order: t.order, type: t.type, propKey: null });
1881
1779
  });
1780
+ //Tirati fuori tutti gli header faccio sort sull'ordinamento
1781
+ return headers.sort((a, b) => { return a.order - b.order; });
1882
1782
  }
1883
1783
  /**
1884
- * Calcolo dell'hash su un oggetto
1784
+ * Dato un oggetto genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1885
1785
  *
1886
- * @param {any} o Oggetto di cui calcolare l'hash
1887
- * @param {number} level Livello di ricorsione nel caso venga effettuato l'hash di un oggetto che contiene altri oggetti
1888
- * @param {boolean} navigateFullDepth Indica se navigare l'oggetto per l'intera lunghezza. In caso contrario si ferma al secondo livello
1786
+ * Metodo interno richiamato da **setupForExport**
1889
1787
  *
1890
- * @returns {string} Hash generato per l'oggetto in questione
1788
+ * @param {any} obj Oggetto generico da esportare
1789
+ *
1790
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1891
1791
  */
1892
- hashObject(o, level = 0, navigateFullDepth = false, precise = false) {
1893
- var strDef = this.stringify(o, level, navigateFullDepth);
1894
- var hash = precise ? this.md5(strDef) : this.simpleHash(strDef);
1895
- return hash;
1792
+ parseAndGetHeaders(obj, columnsSelection) {
1793
+ var headers = [];
1794
+ // Miracle incoming
1795
+ let exportProps = obj[exportList] || [];
1796
+ let loc = obj[locProperty] ? this.lc.generateFromType(obj[locProperty]) : null;
1797
+ if (exportProps.length == 0)
1798
+ console.warn("[@esfaenza/extensions] Nessuna colonna configurata da esportare!");
1799
+ for (let i = 0; i < exportProps.length; i++) {
1800
+ let prop = exportProps[i];
1801
+ let propBase = "";
1802
+ let toCall;
1803
+ if (prop.endsWith(listCsvHdrPrefix)) {
1804
+ propBase = prop.replace(listCsvHdrPrefix, '');
1805
+ toCall = this.parseList.bind(this);
1806
+ }
1807
+ else if (prop.endsWith(dictionaryCsvHdrPrefix)) {
1808
+ propBase = prop.replace(dictionaryCsvHdrPrefix, '');
1809
+ toCall = this.parseDictionary.bind(this);
1810
+ }
1811
+ else if (prop.endsWith(csvVisPrefix)) {
1812
+ propBase = prop.replace(csvVisPrefix, '');
1813
+ if (typeof obj[propBase + csvValueNavigator] !== "undefined")
1814
+ toCall = this.parseObject.bind(this);
1815
+ else
1816
+ toCall = this.parseProperty.bind(this);
1817
+ }
1818
+ if (toCall)
1819
+ toCall(obj, propBase, headers, columnsSelection, loc);
1820
+ }
1821
+ return headers;
1896
1822
  }
1897
1823
  /**
1898
- * Hash più semplice e più veloce dell'md5, ma meno sicuro
1824
+ * Setup per l'esportazione di una singola proprietà.
1825
+ * Viene generato l'header e la proprietà relativa al valore formattato o no
1899
1826
  *
1900
- * Vedi https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
1827
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1828
+ * @param {string} prop Proprietà da esportare
1829
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1830
+ * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
1831
+ */
1832
+ parseProperty(obj, prop, headers, columnsSelection, loc) {
1833
+ let toEmit = obj[prop + csvVisPrefix];
1834
+ let format = obj[prop + csvFormatPrefix];
1835
+ let propKey = obj[prop + csvPropKey];
1836
+ if (propKey && !columnsSelection[propKey] && Object.keys(columnsSelection).length > 0) {
1837
+ console.log("[@esfaenza/extensions] Colonna da non esportare: " + propKey);
1838
+ return;
1839
+ }
1840
+ let text = obj[prop + csvHdrPrefix];
1841
+ let label = loc && text ? loc.loc(text) : text || "";
1842
+ let order = obj[prop + csvOrdPrefix];
1843
+ if (!toEmit)
1844
+ return;
1845
+ // Se non ho un formato esporto direttamente
1846
+ if (!format) {
1847
+ // Se è un formato data mi assicuro di non stampare mai una data 00:00:00 altrimenti in esportazione viene uno schifo
1848
+ let val = obj[prop] ? this.dates.trimSeconds(obj[prop].toString()) : "";
1849
+ let key = prop + "_nofmt";
1850
+ Object.defineProperty(obj, key, { value: val, writable: false, enumerable: true });
1851
+ headers.push({ label, key, order, type: "string", propKey });
1852
+ }
1853
+ else {
1854
+ let key = prop + "_fmt";
1855
+ // Caso formato numerico
1856
+ if (format == "F") {
1857
+ // Check considerando la possibilità di zeri
1858
+ let val = obj[prop] != null ? obj[prop].toString() : "";
1859
+ // Elimino tutte le virgole (indicatori di migliaia per la culture default en-US)
1860
+ val = val.replace(/,/, "");
1861
+ // Il singolo punto che c'è, se presente (separatore decimali) lo trasformo in virgola
1862
+ let valConverted = val.replace(".", ",");
1863
+ Object.defineProperty(obj, key, { value: valConverted, writable: false, enumerable: true });
1864
+ headers.push({ label, key, order, type: "number", propKey });
1865
+ }
1866
+ else {
1867
+ // Se ho un formato data trasformo in dayjs, formatto ed esporto
1868
+ // Per la trasformazione in dayjs provo prima a passargli la stringa di netto, sperando la riconosca
1869
+ // Se non funziona provo a definirgli la formattazione standard del metering per quel linguaggio
1870
+ let val = this.dates.getFormatted(obj[prop], format.length <= 10, format.length > 16);
1871
+ Object.defineProperty(obj, key, { value: val !== null && val !== void 0 ? val : "", writable: false, enumerable: true });
1872
+ headers.push({ label, key, order, type: "date", propKey });
1873
+ }
1874
+ }
1875
+ }
1876
+ /**
1877
+ * Setup per l'esportazione di una singola proprietà da un oggetto.
1878
+ * Viene generato l'header e la proprietà relativa al valore formattato o no.
1901
1879
  *
1902
- * @param {string} str Stringa di cui calcolare l'hash
1880
+ * Per ottenere il valore e l'header della proprietà vengono utilizzati i navigatori auto-generati nel decoratore **ExportAs**
1881
+ *
1882
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1883
+ * @param {string} prop Proprietà da esportare
1884
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1885
+ * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
1903
1886
  */
1904
- simpleHash(str, seed = 0) {
1905
- let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
1906
- for (let i = 0, ch; i < str.length; i++) {
1907
- ch = str.charCodeAt(i);
1908
- h1 = Math.imul(h1 ^ ch, 2654435761);
1909
- h2 = Math.imul(h2 ^ ch, 1597334677);
1887
+ parseObject(obj, prop, headers, columnsSelection, loc) {
1888
+ //se questa proprietà ha un navigator significa che deriva da un oggetto interno, recupero il valore in questa fase dato che prima non ce l'ho
1889
+ let valuenavigator = obj[prop + csvValueNavigator];
1890
+ //Es. di valuenavigator obj.subobj.subsubobj.property
1891
+ let jmps = valuenavigator.split(".");
1892
+ // Localizzazione presa dalla classe base se c'è, altrimenti dalla classe interna (cioè dal primo saltino)
1893
+ if (!loc) {
1894
+ let type = obj[prop + csvValueType];
1895
+ let proto = new type();
1896
+ loc = proto[locProperty] ? this.lc.generateFromType(proto[locProperty]) : null;
1910
1897
  }
1911
- h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
1912
- h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
1913
- return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString();
1898
+ //Mi clono l'oggetto originale per non uccidergli i riferimenti
1899
+ let clone = JSON.parse(JSON.stringify(obj));
1900
+ //Salto ricorsivamente su me stesso per arrivare alla proprietà
1901
+ //Salto 1 > diventa obj
1902
+ //Salto 2 > diventa obj.subobj
1903
+ //ecc...
1904
+ jmps.forEach(pp => { clone = clone[pp]; });
1905
+ //Valore finale :D
1906
+ let value = clone;
1907
+ let text = obj[prop + csvHdrPrefix];
1908
+ let label = loc && text ? loc.loc(text) : text || "";
1909
+ let order = obj[prop + csvOrdPrefix];
1910
+ //Se per questa proprietà ho un formato lo applico
1911
+ let format = obj[prop + csvFormatPrefix];
1912
+ let type = "string";
1913
+ if (format == "F") {
1914
+ let val = value.toString();
1915
+ val = val.replace(/,/, "");
1916
+ value = val.replace(".", ",");
1917
+ type = "number";
1918
+ }
1919
+ else if (format) {
1920
+ value = this.dates.getFormatted(value, format.length <= 10, format.length > 16);
1921
+ type = "date";
1922
+ }
1923
+ Object.defineProperty(obj, prop, { value: value !== null && value !== void 0 ? value : "", writable: false, enumerable: true });
1924
+ headers.push({ label, key: prop, order, type, propKey: null });
1914
1925
  }
1915
1926
  /**
1916
- * Genera una stringa che identifica univocamente l'oggetto in questione
1927
+ * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1917
1928
  *
1918
- * @param {any} o Oggetto di cui calcolare la stringa univoca
1919
- * @param {number} level Livello di ricorsione nel caso venga effettuato l'hash di un oggetto che contiene altri oggetti
1920
- * @param {boolean} navigateFullDepth Indica se navigare l'oggetto per l'intera lunghezza. In caso contrario si ferma al secondo livello
1929
+ * => Recupero il valore utilizzando i navigatori
1930
+ *
1931
+ * => Recupero l'header utilizzando i navigatori
1932
+ *
1933
+ * => Con il valore ci creo la property
1934
+ *
1935
+ * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
1936
+ *
1937
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1938
+ * @param {string} prop Proprietà da esportare
1939
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1940
+ * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
1921
1941
  */
1922
- stringify(o, level, navigateFullDepth) {
1923
- var i, r;
1924
- if (o === null)
1925
- return "n";
1926
- if (o === true)
1927
- return "t";
1928
- if (o === false)
1929
- return "f";
1930
- if (o instanceof Date)
1931
- return 'd:' + o.valueOf().toString();
1932
- i = typeof o;
1933
- if (i === "string")
1934
- return "s:" + o;
1935
- if (i === "number")
1936
- return "n:" + o;
1937
- if (o instanceof Function)
1938
- return "m:" + o.toString();
1939
- if (o instanceof Array) {
1940
- r = [];
1941
- for (i = 0; i < o.length; i++) {
1942
- let res = this.stringify(o[i], level, navigateFullDepth);
1943
- if (res)
1944
- r.push(res);
1942
+ parseList(obj, prop, headers, columnsSelection, loc) {
1943
+ let headernavigator = obj[prop + listCsvHdrPrefix];
1944
+ let valuenavigator = obj[prop + listCsvValPrefix];
1945
+ let valueformat = obj[prop + listCsvValFormat];
1946
+ let order = obj[prop + csvOrdPrefix];
1947
+ var jumps, tmpRes;
1948
+ var objs = obj[prop];
1949
+ for (let idx = 0; idx < objs.length; idx++) {
1950
+ let listitem = objs[idx];
1951
+ var headersplit = headernavigator.split(" ");
1952
+ var label = "";
1953
+ // Per l'header si considera a se stante ogni pezzo separato da spazio per fare le concatenazioni
1954
+ headersplit.forEach(pr => {
1955
+ jumps = pr.split(".");
1956
+ tmpRes = JSON.parse(JSON.stringify(listitem));
1957
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1958
+ let localized = !!loc ? loc.loc(tmpRes) : tmpRes;
1959
+ if (!label)
1960
+ label = localized;
1961
+ else
1962
+ label += " " + localized;
1963
+ });
1964
+ jumps = valuenavigator.split(".");
1965
+ tmpRes = JSON.parse(JSON.stringify(listitem));
1966
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1967
+ let value = tmpRes;
1968
+ let type = "string";
1969
+ if (valueformat == "F") {
1970
+ let val = value != null ? value.toString() : "";
1971
+ val = val.replace(/,/, "");
1972
+ value = val.replace(".", ",");
1973
+ type = "number";
1945
1974
  }
1946
- return r.length > 0 ? "a:" + r.join(";") : "";
1947
- }
1948
- r = [];
1949
- //Se è oggetto, escludo tutti quelli di sistema/inutili
1950
- if (o) {
1951
- var name = o.__proto__.constructor.name;
1952
- if (!this.objBlacklist[name]) {
1953
- for (i in o) {
1954
- if (o.hasOwnProperty(i) && (level <= 2 || navigateFullDepth)) {
1955
- let res = this.stringify(o[i], level + 1, navigateFullDepth);
1956
- if (res)
1957
- r.push(i + ":" + res);
1958
- }
1959
- }
1975
+ else if (valueformat) {
1976
+ value = this.dates.getFormatted(obj[prop], valueformat.length <= 10, valueformat.length > 16);
1977
+ type = "date";
1960
1978
  }
1979
+ Object.defineProperty(obj, prop + idx, { value: value !== null && value !== void 0 ? value : "", writable: false });
1980
+ headers.push({ label, key: prop + idx, order: order + idx, type, propKey: null });
1961
1981
  }
1962
- return r.length > 0 ? "o:" + r.join(";") : "";
1963
1982
  }
1964
1983
  /**
1965
- * Data una stringa restituisce l'md5
1984
+ * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1966
1985
  *
1967
- * @param {string} s Stringa di cui calcolare l'md5
1968
- * @returns {string} md5 della stringa **s**
1969
- */
1970
- md5(s) {
1971
- return this.hex(this.md51(s));
1972
- }
1973
- /**
1974
- * @ignore
1986
+ * => Recupero il valore utilizzando i navigatori
1975
1987
  *
1976
- * Metodo di utilità per il calcolo dell'md5
1988
+ * => Recupero l'header utilizzando i navigatori
1989
+ *
1990
+ * => Con il valore ci creo la property
1991
+ *
1992
+ * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
1993
+ *
1994
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1995
+ * @param {string} prop Proprietà da esportare
1996
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1997
+ * @param {LocalizationService} loc Servizio di localizzazione che traduce tutti i nomi che può
1977
1998
  */
1978
- md5cycle(x, k) {
1979
- var a = x[0], b = x[1], c = x[2], d = x[3];
1980
- a = this.ff(a, b, c, d, k[0], 7, -680876936);
1981
- d = this.ff(d, a, b, c, k[1], 12, -389564586);
1982
- c = this.ff(c, d, a, b, k[2], 17, 606105819);
1983
- b = this.ff(b, c, d, a, k[3], 22, -1044525330);
1984
- a = this.ff(a, b, c, d, k[4], 7, -176418897);
1985
- d = this.ff(d, a, b, c, k[5], 12, 1200080426);
1986
- c = this.ff(c, d, a, b, k[6], 17, -1473231341);
1987
- b = this.ff(b, c, d, a, k[7], 22, -45705983);
1988
- a = this.ff(a, b, c, d, k[8], 7, 1770035416);
1989
- d = this.ff(d, a, b, c, k[9], 12, -1958414417);
1990
- c = this.ff(c, d, a, b, k[10], 17, -42063);
1991
- b = this.ff(b, c, d, a, k[11], 22, -1990404162);
1992
- a = this.ff(a, b, c, d, k[12], 7, 1804603682);
1993
- d = this.ff(d, a, b, c, k[13], 12, -40341101);
1994
- c = this.ff(c, d, a, b, k[14], 17, -1502002290);
1995
- b = this.ff(b, c, d, a, k[15], 22, 1236535329);
1996
- a = this.gg(a, b, c, d, k[1], 5, -165796510);
1997
- d = this.gg(d, a, b, c, k[6], 9, -1069501632);
1998
- c = this.gg(c, d, a, b, k[11], 14, 643717713);
1999
- b = this.gg(b, c, d, a, k[0], 20, -373897302);
2000
- a = this.gg(a, b, c, d, k[5], 5, -701558691);
2001
- d = this.gg(d, a, b, c, k[10], 9, 38016083);
2002
- c = this.gg(c, d, a, b, k[15], 14, -660478335);
2003
- b = this.gg(b, c, d, a, k[4], 20, -405537848);
2004
- a = this.gg(a, b, c, d, k[9], 5, 568446438);
2005
- d = this.gg(d, a, b, c, k[14], 9, -1019803690);
2006
- c = this.gg(c, d, a, b, k[3], 14, -187363961);
2007
- b = this.gg(b, c, d, a, k[8], 20, 1163531501);
2008
- a = this.gg(a, b, c, d, k[13], 5, -1444681467);
2009
- d = this.gg(d, a, b, c, k[2], 9, -51403784);
2010
- c = this.gg(c, d, a, b, k[7], 14, 1735328473);
2011
- b = this.gg(b, c, d, a, k[12], 20, -1926607734);
2012
- a = this.hh(a, b, c, d, k[5], 4, -378558);
2013
- d = this.hh(d, a, b, c, k[8], 11, -2022574463);
2014
- c = this.hh(c, d, a, b, k[11], 16, 1839030562);
2015
- b = this.hh(b, c, d, a, k[14], 23, -35309556);
2016
- a = this.hh(a, b, c, d, k[1], 4, -1530992060);
2017
- d = this.hh(d, a, b, c, k[4], 11, 1272893353);
2018
- c = this.hh(c, d, a, b, k[7], 16, -155497632);
2019
- b = this.hh(b, c, d, a, k[10], 23, -1094730640);
2020
- a = this.hh(a, b, c, d, k[13], 4, 681279174);
2021
- d = this.hh(d, a, b, c, k[0], 11, -358537222);
2022
- c = this.hh(c, d, a, b, k[3], 16, -722521979);
2023
- b = this.hh(b, c, d, a, k[6], 23, 76029189);
2024
- a = this.hh(a, b, c, d, k[9], 4, -640364487);
2025
- d = this.hh(d, a, b, c, k[12], 11, -421815835);
2026
- c = this.hh(c, d, a, b, k[15], 16, 530742520);
2027
- b = this.hh(b, c, d, a, k[2], 23, -995338651);
2028
- a = this.ii(a, b, c, d, k[0], 6, -198630844);
2029
- d = this.ii(d, a, b, c, k[7], 10, 1126891415);
2030
- c = this.ii(c, d, a, b, k[14], 15, -1416354905);
2031
- b = this.ii(b, c, d, a, k[5], 21, -57434055);
2032
- a = this.ii(a, b, c, d, k[12], 6, 1700485571);
2033
- d = this.ii(d, a, b, c, k[3], 10, -1894986606);
2034
- c = this.ii(c, d, a, b, k[10], 15, -1051523);
2035
- b = this.ii(b, c, d, a, k[1], 21, -2054922799);
2036
- a = this.ii(a, b, c, d, k[8], 6, 1873313359);
2037
- d = this.ii(d, a, b, c, k[15], 10, -30611744);
2038
- c = this.ii(c, d, a, b, k[6], 15, -1560198380);
2039
- b = this.ii(b, c, d, a, k[13], 21, 1309151649);
2040
- a = this.ii(a, b, c, d, k[4], 6, -145523070);
2041
- d = this.ii(d, a, b, c, k[11], 10, -1120210379);
2042
- c = this.ii(c, d, a, b, k[2], 15, 718787259);
2043
- b = this.ii(b, c, d, a, k[9], 21, -343485551);
2044
- x[0] = this.add32(a, x[0]);
2045
- x[1] = this.add32(b, x[1]);
2046
- x[2] = this.add32(c, x[2]);
2047
- x[3] = this.add32(d, x[3]);
1999
+ parseDictionary(obj, prop, headers, columnsSelection, loc) {
2000
+ let headernavigator = obj[prop + dictionaryCsvHdrPrefix];
2001
+ let valuenavigator = obj[prop + dictionaryCsvValPrefix];
2002
+ let order = obj[prop + csvOrdPrefix];
2003
+ var jumps, tmpRes;
2004
+ var objs = obj[prop];
2005
+ for (let idx = 0; idx < objs.length; idx++) {
2006
+ let listitem = objs[idx];
2007
+ var headersplit = headernavigator.split(" ");
2008
+ var label = "";
2009
+ headersplit.forEach(pr => {
2010
+ jumps = pr.split(".");
2011
+ tmpRes = JSON.parse(JSON.stringify(listitem));
2012
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
2013
+ if (!label)
2014
+ label = !!loc ? loc.loc(tmpRes) : tmpRes;
2015
+ else
2016
+ label += " " + !!loc ? loc.loc(tmpRes) : tmpRes;
2017
+ });
2018
+ var valuesplit = valuenavigator.split(",");
2019
+ valuesplit.forEach((t, idxinternal) => {
2020
+ var navig = t.split("-")[1];
2021
+ var desc = t.split("-")[0];
2022
+ jumps = navig.split(".");
2023
+ tmpRes = JSON.parse(JSON.stringify(listitem));
2024
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
2025
+ let value = tmpRes;
2026
+ let propname = prop + idx.toString() + idxinternal.toString();
2027
+ Object.defineProperty(obj, propname, { value: value !== null && value !== void 0 ? value : "", writable: false });
2028
+ headers.push({ label: label + " " + !!loc ? loc.loc(desc) : desc, key: propname, order: order + idx, type: 'string', propKey: null });
2029
+ });
2030
+ }
2048
2031
  }
2049
2032
  /**
2050
- * @ignore
2051
- *
2052
- * Metodo di utilità per il calcolo dell'md5
2033
+ * Effettua l'esportazione in file CSV
2053
2034
  */
2054
- cmn(q, a, b, x, s, t) {
2055
- a = this.add32(this.add32(a, q), this.add32(x, t));
2056
- return this.add32((a << s) | (a >>> (32 - s)), b);
2035
+ exportCSV(fn, headers, data) {
2036
+ let csvData = '', row = '', sep = ';';
2037
+ for (let i = 0; i < headers.length; i++) {
2038
+ let h = headers[i];
2039
+ row += `${row != '' ? sep : ''}"${h.label}"`;
2040
+ }
2041
+ csvData += row + '\r\n';
2042
+ for (let i = 0; i < data.length; i++) {
2043
+ row = '';
2044
+ let item = data[i];
2045
+ for (let j = 0; j < headers.length; j++) {
2046
+ let val = item[headers[j].key];
2047
+ row += `${row != '' ? sep : ''}"${val}"`;
2048
+ }
2049
+ csvData += row + '\r\n';
2050
+ }
2051
+ var BOM = new Uint8Array([0xEF, 0xBB, 0xBF]);
2052
+ var blob = new Blob([BOM, csvData], { type: 'text/csv' });
2053
+ var objectUrl = URL.createObjectURL(blob);
2054
+ this.utiExts.fileDownload(objectUrl, fn.endsWith('.xlsx') ? fn.replace('.xlsx', '.csv') : fn.endsWith('.csv') ? fn : fn + ".csv");
2055
+ }
2056
+ /** Effettua l'esportazione del file Excel basandosi sul modulo **ExcelJS**, sugli header **headers** e sui dati **data** */
2057
+ exportExcel(fn, headers, data) {
2058
+ return __awaiter(this, void 0, void 0, function* () {
2059
+ try {
2060
+ this.ExcelJS = this.ExcelJS || (yield import('exceljs'));
2061
+ }
2062
+ catch (_a) {
2063
+ throw "Impossibile caricare la libreria per l'esportazione in Excel";
2064
+ }
2065
+ let iFix = 1;
2066
+ let workbook = new this.ExcelJS.Workbook();
2067
+ workbook.creator = "Ema's big Es-Table";
2068
+ workbook.created = new Date();
2069
+ let sheet = workbook.addWorksheet('Data');
2070
+ let header = sheet.getRow(1);
2071
+ header.font = { bold: true };
2072
+ headers = headers.sort((a, b) => a.order - b.order);
2073
+ for (let i = 0; i < headers.length; i++) {
2074
+ let h = headers[i];
2075
+ header.getCell(i + iFix).value = h.label;
2076
+ }
2077
+ for (let i = 0; i < data.length; i++) {
2078
+ let row = sheet.getRow(i + iFix + 1);
2079
+ let item = data[i];
2080
+ for (let i = 0; i < headers.length; i++) {
2081
+ let h = headers[i];
2082
+ let cell = row.getCell(i + 1);
2083
+ let val = item[h.key];
2084
+ if (!val) {
2085
+ cell.value = "";
2086
+ continue;
2087
+ }
2088
+ switch (h.type) {
2089
+ case 'date':
2090
+ // ExcelJS va di default in UTC quindi rischierebbe di tirare giù 2 ore ad ogni esportazione
2091
+ // Bisogna aggiungere l'utc offset alla data attuale
2092
+ let date = this.dates.getDateConvertion(val);
2093
+ if (date) {
2094
+ let correctedDate = date.add(date.utcOffset(), 'minute');
2095
+ cell.value = correctedDate.toDate();
2096
+ cell.numFmt = val.length > 10 ? 'dd/mm/yyyy h:m:s' : '';
2097
+ }
2098
+ break;
2099
+ case 'number':
2100
+ let converted = parseFloat(val.replace(',', '.'));
2101
+ cell.value = isNaN(converted) ? "" : converted;
2102
+ break;
2103
+ default:
2104
+ cell.value = val;
2105
+ break;
2106
+ }
2107
+ }
2108
+ }
2109
+ let buffer = yield workbook.xlsx.writeBuffer();
2110
+ let blob = new Blob([buffer], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;" });
2111
+ let objectUrl = URL.createObjectURL(blob);
2112
+ this.utiExts.fileDownload(objectUrl, fn.endsWith('.csv') ? fn.replace('.csv', '.xlsx') : fn.endsWith('.xlsx') ? fn : fn + ".xlsx");
2113
+ });
2057
2114
  }
2058
2115
  /**
2059
- * @ignore
2116
+ * Metodo che effettivamente genera gli header e i dati per l'esportazione con **ngx-csv**
2060
2117
  *
2061
- * Metodo di utilità per il calcolo dell'md5
2118
+ * @param {any[]} items Oggetti da esportare
2062
2119
  */
2063
- ff(a, b, c, d, x, s, t) {
2064
- return this.cmn((b & c) | ((~b) & d), a, b, x, s, t);
2120
+ export(items, format, fileName, type, columnsFilter, genericHeaders) {
2121
+ var createdItems = items.map(t => {
2122
+ let tmp = new type();
2123
+ for (let property in t)
2124
+ tmp[property] = t[property];
2125
+ return tmp;
2126
+ });
2127
+ let headers = genericHeaders ? this.setupForGenericExport(createdItems, genericHeaders) : this.setupForExport(createdItems, columnsFilter);
2128
+ (format == "CSV" ? this.exportCSV : this.exportExcel).bind(this)(fileName, headers, createdItems);
2065
2129
  }
2130
+ }
2131
+ ExportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, deps: [{ token: DateService }, { token: UtilityService }, { token: i1.LocalizationService }], target: i0.ɵɵFactoryTarget.Injectable });
2132
+ ExportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, providedIn: "root" });
2133
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, decorators: [{
2134
+ type: Injectable,
2135
+ args: [{ providedIn: "root" }]
2136
+ }], ctorParameters: function () { return [{ type: DateService }, { type: UtilityService }, { type: i1.LocalizationService }]; } });
2137
+
2138
+ /**
2139
+ * Service che fornisce un accesso base in lettura/scrittura sulla clipboard
2140
+ */
2141
+ class ClipboardService {
2066
2142
  /**
2067
- * @ignore
2143
+ * Costruttore
2068
2144
  *
2069
- * Metodo di utilità per il calcolo dell'md5
2070
- */
2071
- gg(a, b, c, d, x, s, t) {
2072
- return this.cmn((b & d) | (c & (~d)), a, b, x, s, t);
2073
- }
2074
- /**
2075
2145
  * @ignore
2076
- *
2077
- * Metodo di utilità per il calcolo dell'md5
2078
2146
  */
2079
- hh(a, b, c, d, x, s, t) {
2080
- return this.cmn(b ^ c ^ d, a, b, x, s, t);
2147
+ constructor(msgService, locProvider) {
2148
+ this.msgService = msgService;
2149
+ this.locProvider = locProvider;
2150
+ /**
2151
+ * Oggetto statico di localizzazione per i messaggi di questa Service
2152
+ */
2153
+ this.loc = {
2154
+ "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation": {
2155
+ 'en-US': "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation",
2156
+ 'it-IT': "Mi dispiace ma Firefox non supporta l'accesso diretto alla Clipboard, se non attraverso le estensioni. Si prega di usare Chrome"
2157
+ },
2158
+ "Generic error during 'copy' command execution": {
2159
+ 'en-US': "Generic error during 'copy' command execution",
2160
+ 'it-IT': "Errore generico durante l'esecuzione del comando 'copy'"
2161
+ },
2162
+ "Error during Clipboard content read operation": {
2163
+ 'en-US': "Error during Clipboard content read operation",
2164
+ 'it-IT': "Errore nella lettura del contenuto della Clipboard"
2165
+ },
2166
+ "Error during Clipboard content copy operation": {
2167
+ 'en-US': "Error during Clipboard content copy operation",
2168
+ 'it-IT': "Errore nella scrittura del contenuto nella Clipboard"
2169
+ },
2170
+ "Please insert your clipboard content": {
2171
+ 'en-US': "Please insert your clipboard content",
2172
+ 'it-IT': "Si prega di incollare il contenuto della Clipboard"
2173
+ },
2174
+ "User input required": {
2175
+ 'en-US': "User input required",
2176
+ 'it-IT': "Richiesto Input utente"
2177
+ },
2178
+ "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation": {
2179
+ 'en-US': "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation",
2180
+ 'it-IT': "Il browser corrente non supporta la lettura diretta dei dati della Clipboard, si prega di effettuare un'incolla (CTRL + V) nella casella di testo e confermare l'operazione"
2181
+ },
2182
+ "Confirm": {
2183
+ 'en-US': "Confirm",
2184
+ 'it-IT': "Conferma"
2185
+ },
2186
+ "Cancel": {
2187
+ 'en-US': "Cancel",
2188
+ 'it-IT': "Annulla"
2189
+ },
2190
+ };
2081
2191
  }
2082
2192
  /**
2083
- * @ignore
2193
+ * Prende il valore della clipboard.
2194
+ * Si può specificare se ci si aspetta una lista o una matrice di valori in modo da ricevere già un risultato utilizzabile
2084
2195
  *
2085
- * Metodo di utilità per il calcolo dell'md5
2196
+ * @param {'array' | 'matrix'} style Stile dell'output desiderato, se array o matrice
2197
+ * @param {Function} valueFoundCallback Callback che questa funzione chiamerà una volta ottenuto i valori richiesti dalla clipboard
2086
2198
  */
2087
- ii(a, b, c, d, x, s, t) {
2088
- return this.cmn(c ^ (b | (~d)), a, b, x, s, t);
2199
+ getClipboard(style, valueFoundCallback) {
2200
+ return __awaiter(this, void 0, void 0, function* () {
2201
+ let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
2202
+ if (navigator.userAgent.indexOf("Firefox") != -1) {
2203
+ swal.fire({
2204
+ title: this.loc["User input required"][LOCALE],
2205
+ text: this.loc["Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation"][LOCALE],
2206
+ input: 'textarea',
2207
+ icon: "warning",
2208
+ confirmButtonText: this.loc["Confirm"][LOCALE],
2209
+ cancelButtonText: this.loc["Cancel"][LOCALE],
2210
+ showCancelButton: true,
2211
+ customClass: {
2212
+ confirmButton: "btn btn-primary",
2213
+ cancelButton: "btn btn-secondary app-margin-right-15",
2214
+ container: "app-wrap",
2215
+ },
2216
+ reverseButtons: true,
2217
+ allowOutsideClick: false,
2218
+ inputValidator: (value) => {
2219
+ if (!value)
2220
+ return this.loc["Please insert your clipboard content"][LOCALE];
2221
+ }
2222
+ }).then(t => {
2223
+ if (t.isConfirmed) {
2224
+ console.log("[@esfaenza/extensions] Retrieving input data from user input");
2225
+ this.doClipboardDataGet(t.value, style, valueFoundCallback);
2226
+ }
2227
+ });
2228
+ return;
2229
+ }
2230
+ if (window.clipboardData) {
2231
+ console.log("[@esfaenza/extensions] Found clipboardData");
2232
+ let data = window.clipboardData.getData("Text");
2233
+ this.doClipboardDataGet(data, style, valueFoundCallback);
2234
+ }
2235
+ else if (window.navigator.clipboard) {
2236
+ console.log("[@esfaenza/extensions] Found navigator clipboard");
2237
+ window.navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
2238
+ if (!(result.state === 'granted' || result.state === 'prompt')) {
2239
+ console.error("[@esfaenza/extensions] Clipboard permission not granted");
2240
+ if (valueFoundCallback)
2241
+ valueFoundCallback([]);
2242
+ return;
2243
+ }
2244
+ console.log("[@esfaenza/extensions] Clipboard permission granted, retrieving values");
2245
+ window.navigator.clipboard.readText()
2246
+ .then((t) => this.doClipboardDataGet(t, style, valueFoundCallback))
2247
+ .catch((err) => this.msgService.simpleError(this.loc["Error during Clipboard content read operation"][LOCALE] + ": " + err));
2248
+ });
2249
+ }
2250
+ });
2089
2251
  }
2090
- /**
2091
- * @ignore
2092
- *
2093
- * Metodo di utilità per il calcolo dell'md5
2094
- */
2095
- md51(s) {
2096
- var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
2097
- for (i = 64; i <= s.length; i += 64)
2098
- this.md5cycle(state, this.md5blk(s.substring(i - 64, i)));
2099
- s = s.substring(i - 64);
2100
- var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
2101
- for (i = 0; i < s.length; i++)
2102
- tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
2103
- tail[i >> 2] |= 0x80 << ((i % 4) << 3);
2104
- if (i > 55) {
2105
- this.md5cycle(state, tail);
2106
- for (i = 0; i < 16; i++)
2107
- tail[i] = 0;
2108
- }
2109
- tail[14] = n * 8;
2110
- this.md5cycle(state, tail);
2111
- return state;
2252
+ /** @ignore */
2253
+ doClipboardDataGet(clipboardText, style, valueFoundCallback) {
2254
+ console.log("[@esfaenza/extensions] Retrieved clipboard values: " + clipboardText);
2255
+ let value = style == "array" ? this.getClipboardLines(clipboardText) :
2256
+ style == "matrix" ? this.getClipboardMatrix(clipboardText) : [];
2257
+ console.log(`[@esfaenza/extensions] Adapted for ${style}: ${JSON.stringify(value)}`);
2258
+ if (valueFoundCallback)
2259
+ valueFoundCallback(value);
2112
2260
  }
2113
2261
  /**
2114
- * @ignore
2262
+ * Ottiene il contenuto della clipboard diviso per righe (separate da newline)
2115
2263
  *
2116
- * Metodo di utilità per il calcolo dell'md5
2117
- */
2118
- md5blk(s) {
2119
- var md5blks = [], i;
2120
- for (i = 0; i < 64; i += 4)
2121
- md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
2122
- return md5blks;
2123
- }
2124
- /**
2125
- * @ignore
2264
+ * @param {string} data contenuto letto dalla clipboard
2126
2265
  *
2127
- * Metodo di utilità per il calcolo dell'md5
2266
+ * @returns {string[]} Array contenente il testo preso dalla clipboard diviso per riga
2128
2267
  */
2129
- rhex(n) {
2130
- var s = '', j = 0;
2131
- for (; j < 4; j++)
2132
- s += this.hex_chr[(n >> (j * 8 + 4)) & 0x0F] + this.hex_chr[(n >> (j * 8)) & 0x0F];
2133
- return s;
2268
+ getClipboardLines(data) {
2269
+ let trimmedData = data.trim();
2270
+ if (!trimmedData.includes("\r\n") && trimmedData.includes("\n"))
2271
+ return trimmedData.split("\n");
2272
+ return trimmedData.split("\r\n");
2134
2273
  }
2135
2274
  /**
2136
- * @ignore
2275
+ * Ottiene il contenuto della clipboard diviso per righe (separate da newline) e colonne (separate da tab)
2137
2276
  *
2138
- * Metodo di utilità per il calcolo dell'md5
2277
+ * @param {string} data contenuto letto dalla clipboard
2278
+ *
2279
+ * @returns {string[][]} Matrice contenente il testo preso dalla clipboard diviso per riga e colonna
2139
2280
  */
2140
- hex(x) {
2141
- for (var i = 0; i < x.length; i++)
2142
- x[i] = this.rhex(x[i]);
2143
- return x.join('');
2281
+ getClipboardMatrix(data) {
2282
+ var ret = [];
2283
+ var rows = !data.includes("\r\n") && data.includes("\n") ? data.split("\n") : data.split("\r\n");
2284
+ // A quanto pare ogni valore è separato da un \t... spero che sia uno standard di quando si copia da excel altrimenti ciao
2285
+ for (let i = 0; i < rows.length; i++)
2286
+ ret.push(rows[i].split('\t').map(t => t.trim()));
2287
+ return ret;
2144
2288
  }
2145
2289
  /**
2146
- * @ignore
2290
+ * Metodo che copia un testo all'interno della clipboard
2147
2291
  *
2148
- * Metodo di utilità per il calcolo dell'md5
2292
+ * @param {string} text Testo da inserire nella clipboard
2149
2293
  */
2150
- add32(a, b) {
2151
- return (a + b) & 0xFFFFFFFF;
2294
+ copyTextToClipboard(text) {
2295
+ return __awaiter(this, void 0, void 0, function* () {
2296
+ let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
2297
+ var textArea = document.createElement("textarea");
2298
+ //
2299
+ // *** This styling is an extra step which is likely not required. ***
2300
+ //
2301
+ // Why is it here? To ensure:
2302
+ // 1. the element is able to have focus and selection.
2303
+ // 2. if element was to flash render it has minimal visual impact.
2304
+ // 3. less flakyness with selection and copying which **might** occur if
2305
+ // the textarea element is not visible.
2306
+ //
2307
+ // The likelihood is the element won't even render, not even a flash,
2308
+ // so some of these are just precautions. However in IE the element
2309
+ // is visible whilst the popup box asking the user for permission for
2310
+ // the web page to copy to the clipboard.
2311
+ //
2312
+ // Place in top-left corner of screen regardless of scroll position.
2313
+ textArea.style.position = "fixed";
2314
+ textArea.style.top = "0";
2315
+ textArea.style.left = "0";
2316
+ // Ensure it has a small width and height. Setting to 1px / 1em
2317
+ // doesn't work as this gives a negative w/h on some browsers.
2318
+ textArea.style.width = "2em";
2319
+ textArea.style.height = "2em";
2320
+ // We don't need padding, reducing the size if it does flash render.
2321
+ textArea.style.padding = "0";
2322
+ // Clean up any borders.
2323
+ textArea.style.border = "none";
2324
+ textArea.style.outline = "none";
2325
+ textArea.style.boxShadow = "none";
2326
+ // Avoid flash of white box if rendered for any reason.
2327
+ textArea.style.background = "transparent";
2328
+ textArea.value = text;
2329
+ document.body.appendChild(textArea);
2330
+ textArea.focus();
2331
+ textArea.select();
2332
+ try {
2333
+ var successful = document.execCommand("copy");
2334
+ if (!successful)
2335
+ this.msgService.simpleError(this.loc["Generic error during 'copy' command execution"][LOCALE]);
2336
+ }
2337
+ catch (err) {
2338
+ this.msgService.simpleError(this.loc["Error during Clipboard content copy operation"][LOCALE] + ": " + err);
2339
+ }
2340
+ document.body.removeChild(textArea);
2341
+ });
2152
2342
  }
2153
2343
  }
2154
- HashingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2155
- HashingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, providedIn: "root" });
2156
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, decorators: [{
2344
+ ClipboardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, deps: [{ token: MessageService }, { token: i1.BaseLocalization, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
2345
+ ClipboardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, providedIn: "root" });
2346
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, decorators: [{
2157
2347
  type: Injectable,
2158
2348
  args: [{ providedIn: "root" }]
2159
- }] });
2349
+ }], ctorParameters: function () {
2350
+ return [{ type: MessageService }, { type: i1.BaseLocalization, decorators: [{
2351
+ type: Optional
2352
+ }] }];
2353
+ } });
2160
2354
 
2161
2355
  /**
2162
2356
  * Classe che rappresenta una risposta ricevuta da un Backend
@@ -2253,5 +2447,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImpor
2253
2447
  * Generated bundle index. Do not edit.
2254
2448
  */
2255
2449
 
2256
- export { APPSEARCH_PREFIX, AppEmbeddingExtensions, CallResult, ClipboardService, CsvHeaders, DateService, EXT_ALLOW_UTC, EXT_DEBUG_MODE, Export, ExportAs, ExportDictionary, ExportList, ExportLocalization, ExportService, ExtensionsModule, GenericItem, HashingService, InboundMessageTypes, InterComMessage, InterComService, LocDatePipe, MessageService, UtilityService };
2450
+ export { APPSEARCH_PREFIX, AppEmbeddingExtensions, BaseExtensionsService, CallResult, ClipboardService, CsvHeaders, DateService, EXT_ALLOW_UTC, EXT_DEBUG_MODE, Export, ExportAs, ExportDictionary, ExportList, ExportLocalization, ExportService, ExtensionsModule, GenericItem, HashingService, InboundMessageTypes, InterComMessage, InterComService, LocDatePipe, MessageService, UtilityService };
2257
2451
  //# sourceMappingURL=esfaenza-extensions.mjs.map