@esfaenza/extensions 15.2.25 → 15.2.27

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