@esfaenza/extensions 12.2.13 → 13.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/esfaenza-extensions.d.ts +1 -2
  2. package/esm2020/esfaenza-extensions.mjs +5 -0
  3. package/{esm2015/lib/models/CallResult.js → esm2020/lib/models/CallResult.mjs} +0 -0
  4. package/{esm2015/lib/models/CsvHeaders.js → esm2020/lib/models/CsvHeaders.mjs} +1 -1
  5. package/{esm2015/lib/models/ExportConsts.js → esm2020/lib/models/ExportConsts.mjs} +0 -0
  6. package/{esm2015/lib/models/ExtensionsModuleConfig.js → esm2020/lib/models/ExtensionsModuleConfig.mjs} +0 -0
  7. package/{esm2015/lib/models/GenericItem.js → esm2020/lib/models/GenericItem.mjs} +0 -0
  8. package/{esm2015/lib/models/TypeCode.js → esm2020/lib/models/TypeCode.mjs} +0 -0
  9. package/{esm2015/lib/models/providers/base/BaseStorageProvider.js → esm2020/lib/models/providers/base/BaseStorageProvider.mjs} +0 -0
  10. package/esm2020/lib/models/providers/implementation/DefaultStorageProvider.mjs +79 -0
  11. package/{esm2015/lib/models/session/base/BaseSessionRetriever.js → esm2020/lib/models/session/base/BaseSessionRetriever.mjs} +0 -0
  12. package/esm2020/lib/models/session/implementation/DefaultSessionRetriever.mjs +28 -0
  13. package/esm2020/lib/modules/extensions.full.module.mjs +58 -0
  14. package/esm2020/lib/modules/extensions.module.mjs +28 -0
  15. package/esm2020/lib/services/extensions.clipboard.service.mjs +165 -0
  16. package/esm2020/lib/services/extensions.dates.service.mjs +232 -0
  17. package/{esm2015/lib/services/extensions.exports.service.js → esm2020/lib/services/extensions.exports.service.mjs} +24 -17
  18. package/esm2020/lib/services/extensions.hashing.service.mjs +309 -0
  19. package/esm2020/lib/services/extensions.messages.service.mjs +323 -0
  20. package/esm2020/lib/services/extensions.storage.service.mjs +103 -0
  21. package/esm2020/lib/services/extensions.utilities.service.mjs +188 -0
  22. package/{esm2015/lib/tokens.js → esm2020/lib/tokens.mjs} +0 -0
  23. package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
  24. package/fesm2015/{esfaenza-extensions.js → esfaenza-extensions.mjs} +120 -75
  25. package/fesm2015/esfaenza-extensions.mjs.map +1 -0
  26. package/fesm2020/esfaenza-extensions.mjs +2055 -0
  27. package/fesm2020/esfaenza-extensions.mjs.map +1 -0
  28. package/lib/models/CsvHeaders.d.ts +4 -0
  29. package/lib/models/providers/implementation/DefaultStorageProvider.d.ts +3 -0
  30. package/lib/models/session/implementation/DefaultSessionRetriever.d.ts +3 -0
  31. package/lib/modules/extensions.full.module.d.ts +4 -0
  32. package/lib/modules/extensions.module.d.ts +4 -0
  33. package/lib/services/extensions.clipboard.service.d.ts +3 -0
  34. package/lib/services/extensions.dates.service.d.ts +3 -0
  35. package/lib/services/extensions.exports.service.d.ts +3 -0
  36. package/lib/services/extensions.hashing.service.d.ts +3 -0
  37. package/lib/services/extensions.messages.service.d.ts +3 -0
  38. package/lib/services/extensions.storage.service.d.ts +3 -0
  39. package/lib/services/extensions.utilities.service.d.ts +3 -0
  40. package/package.json +22 -10
  41. package/bundles/esfaenza-extensions.umd.js +0 -2435
  42. package/bundles/esfaenza-extensions.umd.js.map +0 -1
  43. package/esfaenza-extensions.metadata.json +0 -1
  44. package/esm2015/esfaenza-extensions.js +0 -7
  45. package/esm2015/lib/models/providers/implementation/DefaultStorageProvider.js +0 -79
  46. package/esm2015/lib/models/session/implementation/DefaultSessionRetriever.js +0 -26
  47. package/esm2015/lib/modules/extensions.full.module.js +0 -54
  48. package/esm2015/lib/modules/extensions.module.js +0 -24
  49. package/esm2015/lib/services/extensions.clipboard.service.js +0 -165
  50. package/esm2015/lib/services/extensions.dates.service.js +0 -224
  51. package/esm2015/lib/services/extensions.hashing.service.js +0 -306
  52. package/esm2015/lib/services/extensions.messages.service.js +0 -317
  53. package/esm2015/lib/services/extensions.storage.service.js +0 -100
  54. package/esm2015/lib/services/extensions.utilities.service.js +0 -185
  55. package/fesm2015/esfaenza-extensions.js.map +0 -1
@@ -0,0 +1,2055 @@
1
+ import * as i0 from '@angular/core';
2
+ import { InjectionToken, NgModule, Injectable, Optional, Inject } from '@angular/core';
3
+ import swal from 'sweetalert2';
4
+ import * as i1 from 'ngx-toastr';
5
+ import { Deserialize } from 'cerialize';
6
+ import { first, tap } from 'rxjs/operators';
7
+ import { of } from 'rxjs';
8
+
9
+ /**
10
+ * Token che identifica il locale da utilizzare per questa libreria, sono supportati i locali 'it-IT' ed 'en-US'
11
+ */
12
+ const EXT_LOCALE = new InjectionToken('EXT_LOCALE');
13
+ /**
14
+ * Token che indica se la libreria deve utilizzare la libreria 'sweetalerts2' (più graficamente piacevolo) o se limitarsi ad usare 'toastr'
15
+ */
16
+ const EXT_FANCY_ALERTS = new InjectionToken('EXT_FANCY_ALERTS');
17
+ /**
18
+ * 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'
19
+ */
20
+ const APPSEARCH_PREFIX = new InjectionToken('APPSEARCH_PREFIX');
21
+ /**
22
+ * Token che indica se i metodi di estensione che utilizzano le date permettono l'uso di date in utc
23
+ */
24
+ const EXT_ALLOW_UTC = new InjectionToken('EXT_ALLOW_UTC');
25
+
26
+ // Angular
27
+ /**
28
+ * Modulo di estensione che non registra nessun servizio di estensione, dovranno essere dichiarati 1 per 1 dall'applicazione che li utilizza
29
+ */
30
+ class ExtensionsModule {
31
+ static forRoot(config) {
32
+ return {
33
+ ngModule: ExtensionsModule,
34
+ providers: [
35
+ { provide: EXT_LOCALE, useValue: config?.locale || 'it-IT' },
36
+ { provide: EXT_FANCY_ALERTS, useValue: config?.fancy_alerts || true },
37
+ { provide: APPSEARCH_PREFIX, useValue: config?.appsearch_prefix || 'Hot' },
38
+ { provide: EXT_ALLOW_UTC, useValue: config?.allow_utc == null ? false : config?.allow_utc }
39
+ ]
40
+ };
41
+ }
42
+ }
43
+ ExtensionsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExtensionsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
44
+ ExtensionsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExtensionsModule });
45
+ ExtensionsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExtensionsModule });
46
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExtensionsModule, decorators: [{
47
+ type: NgModule
48
+ }] });
49
+
50
+ // Angular
51
+ /**
52
+ * Service che fornisce funzionalità di alert nei tipi fondamentali: success, info, warning e danger
53
+ */
54
+ class MessageService {
55
+ /**
56
+ * Costruttore
57
+ *
58
+ * @ignore
59
+ */
60
+ constructor(toastr, FANCY_ALERTS, LOCALE) {
61
+ this.toastr = toastr;
62
+ this.FANCY_ALERTS = FANCY_ALERTS;
63
+ this.LOCALE = LOCALE;
64
+ /**
65
+ * Oggetto statico in supporto alla localizzazione
66
+ */
67
+ this.loc = {
68
+ 'Confirm': { 'en-US': "Confirm", 'it-IT': "Conferma", },
69
+ 'Cancel': { 'en-US': "Cancel", 'it-IT': "Annulla", },
70
+ 'Close': { 'en-US': "Close", 'it-IT': "Chiudi", },
71
+ 'Error': { 'en-US': "Error", 'it-IT': "Errore", },
72
+ 'Info': { 'en-US': "Info", 'it-IT': "Informazione", },
73
+ 'Success': { 'en-US': "Success", 'it-IT': "Successo", },
74
+ 'Warning': { 'en-US': "Warning", 'it-IT': "Attenzione", }
75
+ };
76
+ this.expiredSessionSwal = swal.mixin({
77
+ showCancelButton: false,
78
+ confirmButtonText: 'Login',
79
+ customClass: {
80
+ confirmButton: "btn btn-primary",
81
+ container: "app-wrap",
82
+ },
83
+ buttonsStyling: false,
84
+ reverseButtons: false,
85
+ allowOutsideClick: false,
86
+ icon: "warning"
87
+ });
88
+ this.warningSwalWithCancel = swal.mixin({
89
+ title: this.loc["Warning"][this.LOCALE ?? 'it-IT'],
90
+ customClass: {
91
+ confirmButton: "btn btn-primary",
92
+ cancelButton: "btn btn-secondary app-margin-right-10",
93
+ container: "app-wrap",
94
+ },
95
+ buttonsStyling: false,
96
+ reverseButtons: true,
97
+ showCancelButton: true,
98
+ confirmButtonText: this.loc["Confirm"][this.LOCALE ?? 'it-IT'],
99
+ cancelButtonText: this.loc["Cancel"][this.LOCALE ?? 'it-IT'],
100
+ icon: "warning"
101
+ });
102
+ this.warningSwal = swal.mixin({
103
+ title: this.loc["Warning"][this.LOCALE ?? 'it-IT'],
104
+ customClass: {
105
+ confirmButton: "btn btn-primary",
106
+ container: "app-wrap",
107
+ },
108
+ buttonsStyling: false,
109
+ reverseButtons: true,
110
+ showCancelButton: false,
111
+ confirmButtonText: this.loc["Close"][this.LOCALE ?? 'it-IT'],
112
+ icon: "warning"
113
+ });
114
+ this.successSwal = swal.mixin({
115
+ title: this.loc["Success"][this.LOCALE ?? 'it-IT'],
116
+ customClass: {
117
+ confirmButton: "btn btn-primary",
118
+ container: "app-wrap",
119
+ },
120
+ buttonsStyling: false,
121
+ reverseButtons: true,
122
+ showCancelButton: false,
123
+ confirmButtonText: this.loc["Close"][this.LOCALE ?? 'it-IT'],
124
+ icon: "success"
125
+ });
126
+ this.errorSwal = swal.mixin({
127
+ title: this.loc["Error"][this.LOCALE ?? 'it-IT'],
128
+ customClass: {
129
+ confirmButton: "btn btn-primary",
130
+ container: "app-wrap",
131
+ },
132
+ buttonsStyling: false,
133
+ reverseButtons: true,
134
+ showCancelButton: false,
135
+ confirmButtonText: this.loc["Close"][this.LOCALE ?? 'it-IT'],
136
+ icon: "error"
137
+ });
138
+ this.infoSwal = swal.mixin({
139
+ title: this.loc["Info"][this.LOCALE ?? 'it-IT'],
140
+ customClass: {
141
+ confirmButton: "btn btn-primary",
142
+ container: "app-wrap",
143
+ },
144
+ buttonsStyling: false,
145
+ reverseButtons: true,
146
+ showCancelButton: false,
147
+ confirmButtonText: this.loc["Close"][this.LOCALE ?? 'it-IT'],
148
+ icon: "info"
149
+ });
150
+ }
151
+ /**
152
+ * Presentazione di un semplice messaggio di successo
153
+ *
154
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
155
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
156
+ *
157
+ * @param {string} text Testo da mostrare
158
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
159
+ */
160
+ simpleSuccess(text, secondaryNotificationType = null) {
161
+ let tos = this.toastrOrSwal(secondaryNotificationType);
162
+ if (tos == "swal")
163
+ this.successSwal.fire("", text);
164
+ else
165
+ this.toastr.success(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: tos == "toastr" ? 0 : 5000, extendedTimeOut: tos == "toastr" ? 0 : 1000 });
166
+ }
167
+ /**
168
+ * Presentazione di un semplice messaggio di informazione
169
+ *
170
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
171
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
172
+ *
173
+ * @param {string} text Testo da mostrare
174
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
175
+ */
176
+ simpleInfo(text, secondaryNotificationType = null) {
177
+ let tos = this.toastrOrSwal(secondaryNotificationType);
178
+ if (tos == "swal")
179
+ this.infoSwal.fire("", text);
180
+ else
181
+ this.toastr.info(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: tos == "toastr" ? 0 : 5000, extendedTimeOut: tos == "toastr" ? 0 : 1000 });
182
+ }
183
+ /**
184
+ * Presentazione di un semplice messaggio di errore
185
+ *
186
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
187
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
188
+ *
189
+ * @param {string} text Testo da mostrare
190
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
191
+ */
192
+ simpleError(text, secondaryNotificationType = null) {
193
+ let tos = this.toastrOrSwal(secondaryNotificationType);
194
+ if (tos == "swal")
195
+ this.errorSwal.fire("", text);
196
+ else
197
+ this.toastr.error(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: tos == "toastr" ? 0 : 5000, extendedTimeOut: tos == "toastr" ? 0 : 1000 });
198
+ }
199
+ /**
200
+ * Presentazione di un semplice messaggio di avviso
201
+ *
202
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
203
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
204
+ *
205
+ * @param {string} text Testo da mostrare
206
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
207
+ */
208
+ simpleWarning(text, secondaryNotificationType = null) {
209
+ let tos = this.toastrOrSwal(secondaryNotificationType);
210
+ if (tos == "swal")
211
+ this.warningSwal.fire("", text);
212
+ else
213
+ this.toastr.warning(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: tos == "toastr" ? 0 : 5000, extendedTimeOut: tos == "toastr" ? 0 : 1000 });
214
+ }
215
+ /**
216
+ * Ripulisce tutti i messaggi presenti in un dato momento sullo schermo
217
+ */
218
+ clearMessages() {
219
+ this.toastr.clear();
220
+ swal.close();
221
+ }
222
+ /**
223
+ * Mostra un messaggio di avviso con richiesta di conferma
224
+ *
225
+ * @param {string} title Titolo del messaggio
226
+ * @param {string} text Contenuto del messaggio
227
+ *
228
+ * @returns {Promise} Restituisce una Promise col risultato scelto dall'utente (conferma o no)
229
+ */
230
+ promiseWarningWithChoice(title, text) {
231
+ return this.warningSwalWithCancel.fire(title, text);
232
+ }
233
+ /**
234
+ * In base alla configurazione attuale e all'eventuale override per la chiamata del caso indica se bisogna utilizzare toastr o sweetalert
235
+ *
236
+ * @param {"toastr" | "swal" | null} providerOverride Override alla modalità configurata
237
+ *
238
+ * @returns {"toastr" | "swal"} Indicazione su che provider di messaggi di avviso debba essere utilizzato
239
+ */
240
+ toastrOrSwal(providerOverride) {
241
+ if (providerOverride != null)
242
+ return providerOverride;
243
+ return this.FANCY_ALERTS == null ? "swal" : this.FANCY_ALERTS ? "swal" : "toastr";
244
+ }
245
+ /**
246
+ * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
247
+ *
248
+ * @param {string} title Titolo del messaggio
249
+ * @param {string} text Contenuto del messaggio
250
+ * @param {Function} onsuccess Callback da chimare su conferma
251
+ * @param {Function} onerror Callback da chimare su errori
252
+ */
253
+ simpleWarningWithChoice(title, text, onsuccess = null, onerror = null) {
254
+ this.warningSwalWithCancel.fire(title, text).then((result) => {
255
+ if (result.value && onsuccess)
256
+ onsuccess();
257
+ else if (onerror)
258
+ onerror();
259
+ });
260
+ }
261
+ /**
262
+ * Mostra un messaggio di avviso che la sessione corrente è scaduta e propone all'utente di navigare al login. Qualora l'utente decidesse di farlo
263
+ * verrà chiamata la funzione di callback **onnavigate
264
+ *
265
+ * @param {string} title Titolo del messaggio
266
+ * @param {string} text Contenuto del messaggio
267
+ * @param {Function} onnavigate Callback da chimare su navigazione in corso
268
+ */
269
+ expiredSessionMessage(title, text, onnavigate = null) {
270
+ this.expiredSessionSwal.fire(title, text).then((result) => {
271
+ if (result.value && onnavigate)
272
+ onnavigate();
273
+ });
274
+ }
275
+ /**
276
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **CallResult**
277
+ *
278
+ * @param {CallResult} response Risposta ricevuta dal server
279
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
280
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
281
+ * @param {Function} postSuccess Callback da chimare in caso di successo
282
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
283
+ */
284
+ manageCallResultResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
285
+ if (response.success) {
286
+ if (successMsg)
287
+ this.simpleSuccess(successMsg);
288
+ if (postSuccess)
289
+ postSuccess();
290
+ }
291
+ else if (response.haserror) {
292
+ this.simpleError((errorMsg ? errorMsg + ": " : "") + response.error);
293
+ if (postFailure)
294
+ postFailure();
295
+ }
296
+ else if (response.haswarning) {
297
+ this.simpleWarning(response.warning);
298
+ }
299
+ }
300
+ /**
301
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **string**, considerando che:
302
+ *
303
+ * Stringa vuota --> Tutto bene
304
+ *
305
+ * Stringa piena --> Questo è il messaggio d'errore per cui la chiamata è fallita
306
+ *
307
+ * @param {string} response Risposta ricevuta dal server
308
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
309
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
310
+ * @param {Function} postSuccess Callback da chimare in caso di successo
311
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
312
+ */
313
+ manageStringResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
314
+ if (!response) {
315
+ if (successMsg)
316
+ this.simpleSuccess(successMsg);
317
+ if (postSuccess)
318
+ postSuccess();
319
+ }
320
+ else {
321
+ if (errorMsg)
322
+ this.simpleError(errorMsg + ": " + response);
323
+ if (postFailure)
324
+ postFailure();
325
+ }
326
+ }
327
+ /**
328
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **boolean**
329
+ *
330
+ * @param {string} response Risposta ricevuta dal server
331
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
332
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
333
+ * @param {Function} postSuccess Callback da chimare in caso di successo
334
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
335
+ */
336
+ manageStringResponseBool(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
337
+ if (response) {
338
+ if (successMsg)
339
+ this.simpleSuccess(successMsg);
340
+ if (postSuccess)
341
+ postSuccess();
342
+ }
343
+ else {
344
+ if (errorMsg)
345
+ this.simpleError(errorMsg);
346
+ if (postFailure)
347
+ postFailure();
348
+ }
349
+ }
350
+ }
351
+ MessageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: MessageService, deps: [{ token: i1.ToastrService }, { token: EXT_FANCY_ALERTS, optional: true }, { token: EXT_LOCALE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
352
+ MessageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: MessageService });
353
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: MessageService, decorators: [{
354
+ type: Injectable
355
+ }], ctorParameters: function () { return [{ type: i1.ToastrService }, { type: undefined, decorators: [{
356
+ type: Optional
357
+ }, {
358
+ type: Inject,
359
+ args: [EXT_FANCY_ALERTS]
360
+ }] }, { type: undefined, decorators: [{
361
+ type: Optional
362
+ }, {
363
+ type: Inject,
364
+ args: [EXT_LOCALE]
365
+ }] }]; } });
366
+
367
+ // Angular
368
+ /**
369
+ * Service che fornisce un accesso base in lettura/scrittura sulla clipboard
370
+ */
371
+ class ClipboardService {
372
+ /**
373
+ * Costruttore
374
+ *
375
+ * @ignore
376
+ */
377
+ constructor(msgService, LOCALE) {
378
+ this.msgService = msgService;
379
+ this.LOCALE = LOCALE;
380
+ /**
381
+ * Oggetto statico di localizzazione per i messaggi di questa Service
382
+ */
383
+ this.loc = {
384
+ "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation": {
385
+ 'en-US': "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation",
386
+ 'it-IT': "Mi dispiace ma Firefox non supporta l'accesso diretto alla Clipboard, se non attraverso le estensioni. Si prega di usare Chrome"
387
+ },
388
+ "Generic error during 'copy' command execution": {
389
+ 'en-US': "Generic error during 'copy' command execution",
390
+ 'it-IT': "Errore generico durante l'esecuzione del comando 'copy'"
391
+ },
392
+ "Error during Clipboard content read operation": {
393
+ 'en-US': "Error during Clipboard content read operation",
394
+ 'it-IT': "Errore nella lettura del contenuto della Clipboard"
395
+ },
396
+ "Error during Clipboard content copy operation": {
397
+ 'en-US': "Error during Clipboard content copy operation",
398
+ 'it-IT': "Errore nella scrittura del contenuto nella Clipboard"
399
+ }
400
+ };
401
+ }
402
+ /**
403
+ * Prende il valore della clipboard.
404
+ * Si può specificare se ci si aspetta una lista o una matrice di valori in modo da ricevere già un risultato utilizzabile
405
+ *
406
+ * @param {'array' | 'matrix'} style Stile dell'output desiderato, se array o matrice
407
+ * @param {Function} valueFoundCallback Callback che questa funzione chiamerà una volta ottenuto i valori richiesti dalla clipboard
408
+ */
409
+ getClipboard(style, valueFoundCallback) {
410
+ if (navigator.userAgent.indexOf("Firefox") != -1) {
411
+ //https://developer.mozilla.org/en-US/docs/Web/API/Clipboard/readText
412
+ this.msgService.simpleError(this.loc["Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation"][this.LOCALE ?? 'it-IT']);
413
+ return;
414
+ }
415
+ if (window.clipboardData) {
416
+ let data = window.clipboardData.getData("Text");
417
+ var value = style == "array" ? this.getClipboardLines(data) :
418
+ style == "matrix" ? this.getClipboardMatrix(data) : [];
419
+ if (valueFoundCallback)
420
+ valueFoundCallback(value);
421
+ }
422
+ else if (window.navigator.clipboard) {
423
+ window.navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
424
+ if (!(result.state === 'granted' || result.state === 'prompt'))
425
+ if (valueFoundCallback)
426
+ valueFoundCallback([]);
427
+ window.navigator.clipboard.readText()
428
+ .then(t => {
429
+ var value = style == "array" ? this.getClipboardLines(t) :
430
+ style == "matrix" ? this.getClipboardMatrix(t) : [];
431
+ if (valueFoundCallback)
432
+ valueFoundCallback(value);
433
+ })
434
+ .catch(err => {
435
+ this.msgService.simpleError(this.loc["Error during Clipboard content read operation"][this.LOCALE ?? 'it-IT'] + ": " + err);
436
+ });
437
+ });
438
+ }
439
+ }
440
+ /**
441
+ * Ottiene il contenuto della clipboard diviso per righe (separate da newline)
442
+ *
443
+ * @param {string} data contenuto letto dalla clipboard
444
+ *
445
+ * @returns {string[]} Array contenente il testo preso dalla clipboard diviso per riga
446
+ */
447
+ getClipboardLines(data) {
448
+ return data.trim().split("\r\n");
449
+ }
450
+ /**
451
+ * Ottiene il contenuto della clipboard diviso per righe (separate da newline) e colonne (separate da tab)
452
+ *
453
+ * @param {string} data contenuto letto dalla clipboard
454
+ *
455
+ * @returns {string[][]} Matrice contenente il testo preso dalla clipboard diviso per riga e colonna
456
+ */
457
+ getClipboardMatrix(data) {
458
+ var ret = [];
459
+ var rows = data.split("\r\n");
460
+ // A quanto pare ogni valore è separato da un \t... spero che sia uno standard di quando si copia da excel altrimenti ciao
461
+ for (let i = 0; i < rows.length; i++)
462
+ ret.push(rows[i].split('\t').map(t => t.trim()));
463
+ return ret;
464
+ }
465
+ /**
466
+ * Metodo che copia un testo all'interno della clipboard
467
+ *
468
+ * @param {string} text Testo da inserire nella clipboard
469
+ */
470
+ copyTextToClipboard(text) {
471
+ var textArea = document.createElement("textarea");
472
+ //
473
+ // *** This styling is an extra step which is likely not required. ***
474
+ //
475
+ // Why is it here? To ensure:
476
+ // 1. the element is able to have focus and selection.
477
+ // 2. if element was to flash render it has minimal visual impact.
478
+ // 3. less flakyness with selection and copying which **might** occur if
479
+ // the textarea element is not visible.
480
+ //
481
+ // The likelihood is the element won't even render, not even a flash,
482
+ // so some of these are just precautions. However in IE the element
483
+ // is visible whilst the popup box asking the user for permission for
484
+ // the web page to copy to the clipboard.
485
+ //
486
+ // Place in top-left corner of screen regardless of scroll position.
487
+ textArea.style.position = "fixed";
488
+ textArea.style.top = "0";
489
+ textArea.style.left = "0";
490
+ // Ensure it has a small width and height. Setting to 1px / 1em
491
+ // doesn't work as this gives a negative w/h on some browsers.
492
+ textArea.style.width = "2em";
493
+ textArea.style.height = "2em";
494
+ // We don't need padding, reducing the size if it does flash render.
495
+ textArea.style.padding = "0";
496
+ // Clean up any borders.
497
+ textArea.style.border = "none";
498
+ textArea.style.outline = "none";
499
+ textArea.style.boxShadow = "none";
500
+ // Avoid flash of white box if rendered for any reason.
501
+ textArea.style.background = "transparent";
502
+ textArea.value = text;
503
+ document.body.appendChild(textArea);
504
+ textArea.focus();
505
+ textArea.select();
506
+ try {
507
+ var successful = document.execCommand("copy");
508
+ if (!successful)
509
+ this.msgService.simpleError(this.loc["Generic error during 'copy' command execution"][this.LOCALE ?? 'it-IT']);
510
+ }
511
+ catch (err) {
512
+ this.msgService.simpleError(this.loc["Error during Clipboard content copy operation"][this.LOCALE ?? 'it-IT'] + ": " + err);
513
+ }
514
+ document.body.removeChild(textArea);
515
+ }
516
+ }
517
+ ClipboardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ClipboardService, deps: [{ token: MessageService }, { token: EXT_LOCALE, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
518
+ ClipboardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ClipboardService });
519
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ClipboardService, decorators: [{
520
+ type: Injectable
521
+ }], ctorParameters: function () { return [{ type: MessageService }, { type: undefined, decorators: [{
522
+ type: Optional
523
+ }, {
524
+ type: Inject,
525
+ args: [EXT_LOCALE]
526
+ }] }]; } });
527
+
528
+ // Angular
529
+ /**
530
+ * Service che fornisce dei metodi di estensione per la gestione/manipolazione delle date
531
+ */
532
+ class DateService {
533
+ /**
534
+ * Costruttore
535
+ *
536
+ * @ignore
537
+ */
538
+ constructor(LOCALE, allowUtc) {
539
+ this.LOCALE = LOCALE;
540
+ this.allowUtc = allowUtc;
541
+ /**
542
+ * Oggetto statico di localizzazione per i messaggi di questa Service
543
+ */
544
+ this.loc = {
545
+ "SMALL_DATE_FORMAT": { 'en-US': "MM/DD/YYYY", 'it-IT': "DD/MM/YYYY" },
546
+ "FULL_DATE_FORMAT": { 'en-US': "MM/DD/YYYY HH:mm:ss", 'it-IT': "DD/MM/YYYY HH:mm:ss" },
547
+ "FULL_DATE_FORMAT_NO_SS": { 'en-US': "MM/DD/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" },
548
+ "SMALL_DATE_DISPLAY_FORMAT": { 'en-US': "DD/MM/YYYY", 'it-IT': "DD/MM/YYYY" },
549
+ "SMALL_DATE_DISPLAY_FORMAT_WITH_HOUR": { 'en-US': "DD/MM/YYYY HH", 'it-IT': "DD/MM/YYYY HH" },
550
+ "SMALL_DATE_DISPLAY_FORMAT_WITH_MINUTE": { 'en-US': "DD/MM/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" },
551
+ "FULL_DATE_DISPLAY_FORMAT": { 'en-US': "DD/MM/YYYY HH:mm:ss", 'it-IT': "DD/MM/YYYY HH:mm:ss" },
552
+ "FULL_DATE_DISPLAY_FORMAT_NO_SS": { 'en-US': "DD/MM/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" }
553
+ };
554
+ /**
555
+ * Oggetto di configurazione per tenere da conto le informazioni sui formati
556
+ */
557
+ this.cfg = {
558
+ fulldate: "",
559
+ fulldateDisplay: "",
560
+ smallDate: "",
561
+ fulldateNoSS: "",
562
+ smallDateWithH: "",
563
+ smallDateWithM: "",
564
+ fulldateDisplayNoSS: ""
565
+ };
566
+ this.cfg.smallDate = this.loc["SMALL_DATE_FORMAT"][this.LOCALE ?? 'it-IT'];
567
+ this.cfg.fulldate = this.loc["FULL_DATE_FORMAT"][this.LOCALE ?? 'it-IT'];
568
+ this.cfg.fulldateNoSS = this.loc["FULL_DATE_FORMAT_NO_SS"][this.LOCALE ?? 'it-IT'];
569
+ this.cfg.fulldateDisplay = this.loc["FULL_DATE_DISPLAY_FORMAT"][this.LOCALE ?? 'it-IT'];
570
+ this.cfg.fulldateDisplayNoSS = this.loc["FULL_DATE_DISPLAY_FORMAT_NO_SS"][this.LOCALE ?? 'it-IT'];
571
+ this.cfg.smallDate = this.loc["SMALL_DATE_DISPLAY_FORMAT"][this.LOCALE ?? 'it-IT'];
572
+ this.cfg.smallDateWithH = this.loc["SMALL_DATE_DISPLAY_FORMAT_WITH_HOUR"][this.LOCALE ?? 'it-IT'];
573
+ this.cfg.smallDateWithM = this.loc["SMALL_DATE_DISPLAY_FORMAT_WITH_MINUTE"][this.LOCALE ?? 'it-IT'];
574
+ }
575
+ /**
576
+ * Aggiusta una data in "istante finale" in base a qual è la parte di data significativa.
577
+ *
578
+ * Es. Istante finale delle ore: 05/10/1992 --> 04/10/1992 24:00(:00)
579
+ *
580
+ * @param {any} date Data qualsiasi (Date, stringa, dayjs...), verrà ricondotta ad un oggetto dayJs
581
+ * @param {'day' | 'hour' | 'minute'} timepart Parte significativa della data
582
+ * @param {boolean} printSeconds Indica se effettuare la stampa dei secondi o no
583
+ */
584
+ adjustDateToFinalInstant(date, timepart, printSeconds = true) {
585
+ let mydt = this.getDateConvertion(date);
586
+ if (mydt == null)
587
+ return "FE: Not a Date";
588
+ let isZeroTime = mydt.startOf(timepart).valueOf() === mydt.valueOf();
589
+ if (!isZeroTime)
590
+ return printSeconds ? mydt.format(this.cfg.fulldateDisplay) : mydt.format(this.cfg.fulldateDisplayNoSS);
591
+ let tmpValue = mydt.subtract(1, timepart);
592
+ let value = "";
593
+ // Istante finale delle ore: 05/10/1992 --> 04/10/1992 24:00(:00)
594
+ if (timepart == 'day')
595
+ value = tmpValue.format(this.cfg.smallDate) + " 24:00" + (printSeconds ? ':00' : '');
596
+ // Istante finale dei minuti: giorno 05/10/1992 04:00:00 --> 05/10/1992 03:60(:00)
597
+ else if (timepart == 'hour')
598
+ value = tmpValue.format(this.cfg.smallDateWithH) + ":60" + (printSeconds ? ':00' : '');
599
+ // Istante finale dei secondi: giorno 05/10/1992 04:10:00 --> 05/10/1992 04:09:60
600
+ else if (timepart == 'minute')
601
+ value = tmpValue.format(this.cfg.smallDateWithM) + ":60";
602
+ return value;
603
+ }
604
+ /**
605
+ * Funzione che effettua l'ordinamento fra 2 date in base alla direzione specificata
606
+ *
607
+ * @param {any} a Prima data per il confronto
608
+ * @param {any} b Seconda data per il confronto
609
+ * @param {'asc' | 'desc'} direction Direzione rispetto a cui ordinare le due date
610
+ *
611
+ * @returns {number} 0 se le date sono uguali, 1 se la data A deve venire logicamente prima della data B, -1 altrimenti
612
+ */
613
+ dateSort(a, b, direction) {
614
+ if (a < b)
615
+ return direction == 'asc' ? 1 : -1;
616
+ else if (a > b)
617
+ return direction == 'asc' ? -1 : 1;
618
+ // con a uguale a b
619
+ return 0;
620
+ }
621
+ /**
622
+ * Effettua il trim dei secondi da una data espressa come stringa
623
+ *
624
+ * @param {string} value Data espressa come stringa
625
+ *
626
+ * @returns {string} Data senza i secondi
627
+ */
628
+ trimSeconds(value) {
629
+ //I numeri mangiati da dayjs spesso vengono ricondotti a date vere. Mi assicuro che se ci sono solo numeri proseguo
630
+ if (!isNaN(value))
631
+ return value;
632
+ //Se non ho qualcosa del tipo XX/YY/ZZZZ aa:bb:cc di sicuro non è una data che mi interessa
633
+ if (!/^\d\d\/\d\d\/\d\d\d\d \d\d:\d\d:\d\d$/g.test(value))
634
+ return value;
635
+ //In questo caso mi arrivano valori che devono essere stampati as-is, solo tagliando i secondi
636
+ return "'" + value.substr(0, value.length - 3);
637
+ }
638
+ /**
639
+ * Data una lista di date Da e una lista di date A restituisce un oggetto rappresentante il range che include tutte le date passate
640
+ *
641
+ * @param {any[]} fromDates Lista dei Da
642
+ * @param {any[]} toDates Lista dei A
643
+ *
644
+ * @returns {{ from: any, to: any }} Range di date Da - A che include tutti i valori di **fromDates** e **toDates**
645
+ */
646
+ getMinMaxDatesRange(fromDates, toDates) {
647
+ let datesFroms = [];
648
+ let datesTo = [];
649
+ for (let i = 0; i < fromDates.length; i++) {
650
+ let d = fromDates[i];
651
+ var convertion = this.getDateConvertion(d);
652
+ if (convertion)
653
+ datesFroms.push(convertion);
654
+ }
655
+ for (let i = 0; i < toDates.length; i++) {
656
+ let d = toDates[i];
657
+ var convertion = this.getDateConvertion(d);
658
+ if (convertion)
659
+ datesTo.push(convertion);
660
+ }
661
+ return { from: dayjs.min(datesFroms), to: dayjs.max(datesTo) };
662
+ }
663
+ /**
664
+ * Ottiene la conversione di una data in qualsiasi formato al formato standard DayJs
665
+ *
666
+ * @param {any} date Oggetto rappresentante una data. Potrebbe essere una stringa, un Date o già un DayJs
667
+ * @param {boolean} useUtc Indica se usare l'estensione utc di Dayjs per parsare la data o no
668
+ *
669
+ * @returns {any} Data in modalità DayJs
670
+ */
671
+ getDateConvertion(date, useUtc = false) {
672
+ if (!date)
673
+ return null;
674
+ if (this.isDayJs(date))
675
+ return date;
676
+ if (this.isJsDate(date))
677
+ return useUtc ? dayjs.utc(date) : dayjs(date);
678
+ // Se non c'è la proprietà length vuol dire che non è una stringa e a questo punto non ho idea di che minchia sia
679
+ let length = date.length;
680
+ if (!length)
681
+ return null;
682
+ if (useUtc && !this.allowUtc)
683
+ throw "@esfaenza/extensions: Richiesta data UTC ma da configurazione la libreria non lo supporta";
684
+ // Per risparmiare chiamate a tentoni, in base alla lunghezza della stringa chiamo direttamente il metodo giusto,
685
+ // controllando poi che mi generi una data come me la aspetto io
686
+ let tryThis = null;
687
+ let toCall = useUtc ? dayjs.utc : dayjs;
688
+ // Se la data contiene la lettera "T" vuol dire che è una data del tipo 2020-10-15T00:00:00, direttamente parsabile dal dayjs col locale corretto.
689
+ // Per il resto mi baso sulla lunghezza della stringa
690
+ if (date.includes("T"))
691
+ tryThis = toCall(date);
692
+ else if (length == this.cfg.fulldate.length)
693
+ tryThis = toCall(date, this.cfg.fulldate);
694
+ else if (length == this.cfg.smallDate.length)
695
+ tryThis = toCall(date, this.cfg.smallDate);
696
+ else if (length == this.cfg.fulldateNoSS.length)
697
+ tryThis = toCall(date, this.cfg.fulldateNoSS);
698
+ if (tryThis.isValid())
699
+ return tryThis;
700
+ // Se niente funziona, null.
701
+ // Ricondurre l'Input ad una data non è possibile.
702
+ return null;
703
+ }
704
+ /**
705
+ * Helper che restituisce **true** qualora l'oggetto passato fosse una data vera e propria, **false** altrimenti
706
+ *
707
+ * @param {any} check Oggetto da controllare
708
+ *
709
+ * @returns {boolean} Indicazione se l'oggetto è un vero Date di Javascript o no
710
+ */
711
+ isJsDate(check) {
712
+ return check && Object.prototype.toString.call(check) === "[object Date]" && !isNaN(check);
713
+ }
714
+ /**
715
+ * Helper che restituisce **true** qualora l'oggetto passato fosse un DayJs vero e proprio, **false** altrimenti
716
+ *
717
+ * @param {any} check Oggetto da controllare
718
+ * @returns {boolean} Indicazione se l'oggetto è un vero DayJs o no
719
+ */
720
+ isDayJs(check) {
721
+ // Non uso instanceof perché sarebbe estremamente più lento
722
+ // Non uso nemmeno isDayjs() della libreria Dayjs dato che ha lo stesso problema: https://github.com/iamkun/dayjs/blob/06f88f425828b1ce96b737332d25145a95a4ee9d/src/index.js#L9
723
+ return check.$D !== undefined && check.$M !== undefined && check.$y !== undefined;
724
+ }
725
+ /**
726
+ * Ottiene la formattazione di una data in base alla versione richiesta "small" o "long" e a se stampare o meno i secondi
727
+ *
728
+ * @param {any} date Oggetto rappresentante una data. Potrebbe essere una stringa, un Date o già un DayJs
729
+ * @param {boolean} small Indica se formattarla con un formato breve (se **true**) o un formato più lungo (se **false**)
730
+ *
731
+ * @returns {string} Data formattata nel formato richiesto
732
+ */
733
+ getFormatted(date, small, seconds) {
734
+ var date = this.getDateConvertion(date);
735
+ if (!date)
736
+ return null;
737
+ return date.format(small ? this.cfg.smallDate : seconds ? this.cfg.fulldateDisplay : this.cfg.fulldateDisplayNoSS);
738
+ }
739
+ }
740
+ DateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DateService, deps: [{ token: EXT_LOCALE, optional: true }, { token: EXT_ALLOW_UTC, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
741
+ DateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DateService });
742
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DateService, decorators: [{
743
+ type: Injectable
744
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
745
+ type: Optional
746
+ }, {
747
+ type: Inject,
748
+ args: [EXT_LOCALE]
749
+ }] }, { type: undefined, decorators: [{
750
+ type: Optional
751
+ }, {
752
+ type: Inject,
753
+ args: [EXT_ALLOW_UTC]
754
+ }] }]; } });
755
+
756
+ /**
757
+ * Suffisso della proprietà da generare in cui salvare il navigatore
758
+ * utilizzato dal servizio di esportazione per prendere il valore delle proprietà di un oggetto
759
+ */
760
+ const csvValueNavigator = "_csvnav";
761
+ /**
762
+ * Suffisso della proprietà da generare in cui salvare l'ordine di esportazione
763
+ */
764
+ const csvOrdPrefix = "_csvord";
765
+ /**
766
+ * Suffisso della proprietà da generare in cui salvare la visibilità di questa proprietà
767
+ */
768
+ const csvVisPrefix = "_csvvis";
769
+ /**
770
+ * Suffisso della proprietà da generare in cui salvare il nome della colonna in cui salvare questa proprietà
771
+ */
772
+ const csvHdrPrefix = "_csvhdr";
773
+ /**
774
+ * Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Lista
775
+ */
776
+ const listCsvValPrefix = "_listcsvval";
777
+ /**
778
+ * Suffisso della proprietà da generare in cui salvare l'Header della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix**
779
+ */
780
+ const listCsvHdrPrefix = "_listcsvhdr";
781
+ /**
782
+ * Suffisso della proprietà da generare in cui salvare il formato della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix**
783
+ */
784
+ const listCsvValFormat = "_listcsvvalformat";
785
+ /**
786
+ * Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Dizionario
787
+ */
788
+ const dictionaryCsvValPrefix = "_flatlistcsvval";
789
+ /**
790
+ * Suffisso della proprietà da generare in cui salvare l'Header della proprietà di un Dizionario relativo al valore esportato nella proprietà con suffisso **dictionaryCsvValPrefix**
791
+ */
792
+ const dictionaryCsvHdrPrefix = "_flatlistcsvhdr";
793
+ /**
794
+ * Suffisso della proprietà da generare in cui salvare il formato della proprietà che si sta esportando
795
+ */
796
+ const csvFormatPrefix = "_csvfmt";
797
+
798
+ // Angular
799
+ /**
800
+ * Decoratore di esportazione utilizzabile su una proprietà singola.
801
+ * Verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
802
+ *
803
+ * Ad esempio, da questa configurazione:
804
+ *
805
+ * @example
806
+ * ```
807
+ * @Export(true, "MyHeader")
808
+ * ciao: string;
809
+ * ```
810
+ *
811
+ * Nasceranno le seguenti proprietà nell'oggetto esportabile:
812
+ *
813
+ * @example
814
+ * ```
815
+ * ciao_csvvis: string; => true
816
+ * ciao: string;
817
+ * ciao_csvhdr: string => "MyHeader"
818
+ * ```
819
+ *
820
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
821
+ * @param {string} header Titolo della colonna nel file CSV esportato
822
+ * @param {string} format Formato di esportazione. Può essere un formato data per i campi data o 'F' per i campi floating point
823
+ */
824
+ const Export = (order, header, format = null) => (target, propertyKey) => {
825
+ if (format)
826
+ Object.defineProperty(target, propertyKey + csvFormatPrefix, { value: format, writable: false });
827
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
828
+ Object.defineProperty(target, propertyKey + csvVisPrefix, { value: !!header, writable: false });
829
+ Object.defineProperty(target, propertyKey + csvHdrPrefix, { value: header, writable: false });
830
+ };
831
+ /**
832
+ * Decoratore di esportazione utilizzabile su un oggetto.
833
+ * Per ogni proprietà dell'oggetto verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
834
+ * Per essere esportate, le proprietà dell'oggetto devono essere marcate con i Decoratori di esportazione
835
+ *
836
+ * Ad esempio, da questa configurazione:
837
+ *
838
+ * @example
839
+ * ```
840
+ * MyObj {
841
+ * @Export(true, "MyHeader")
842
+ * ciao: string;
843
+ * }
844
+ *
845
+ * @ExportObject(true, "MyHeader")
846
+ * test: MyObj;
847
+ * ```
848
+ *
849
+ * Nasceranno le seguenti proprietà nell'oggetto esportabile:
850
+ *
851
+ * @example
852
+ * ```
853
+ * testciao: string; => Valore di MyObj.ciao
854
+ * testciao_csvvis: string; => true
855
+ * testciao_csvhdr: string => "MyHeader"
856
+ * ```
857
+ *
858
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
859
+ * @param {any} type Tipo da esportare
860
+ */
861
+ const ExportAs = (order, type) => (target, propertyKey) => {
862
+ var t = new type();
863
+ for (var prop in t) {
864
+ //Niente hasownproperty perché le proprietà dell'oggetto interno sono dentro al prototype
865
+ if (typeof t[prop + csvVisPrefix] !== "undefined") {
866
+ var toEmit = t[prop + csvVisPrefix];
867
+ var lbl = t[prop + csvHdrPrefix];
868
+ var format = t[prop + csvFormatPrefix];
869
+ var orderProp = t[prop + csvOrdPrefix];
870
+ if (format)
871
+ Object.defineProperty(target, propertyKey + prop + csvFormatPrefix, { value: format, writable: false });
872
+ Object.defineProperty(target, propertyKey + prop + csvOrdPrefix, { value: orderProp + order, writable: false });
873
+ Object.defineProperty(target, propertyKey + prop, { value: null, writable: true, enumerable: true });
874
+ Object.defineProperty(target, propertyKey + prop + csvValueNavigator, { value: propertyKey + "." + prop, writable: false });
875
+ Object.defineProperty(target, propertyKey + prop + csvVisPrefix, { value: toEmit, writable: false });
876
+ Object.defineProperty(target, propertyKey + prop + csvHdrPrefix, { value: lbl, writable: false });
877
+ }
878
+ }
879
+ };
880
+ /**
881
+ * Decoratore di esportazione utilizzabile su una lista,
882
+ * si utilizzano 2 navigator rispettivamente per la valorizzazione dell'Header e del Valore e
883
+ * per ogni elemento dell'array verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr)
884
+ *
885
+ * ATTENZIONE: Gli oggetti esportati in questa modalità non devono presentare altri tag di tipo @Export{...} all'interno. Fa tutto questo decoratore
886
+ *
887
+ * I navigator hanno questa convenzione:
888
+ *
889
+ * . --> divide due proprietà da richiamare consecutivamente: "a.b" richiamerà "obj.a.b";
890
+ *
891
+ * | --> divide più proprietà per le concatenazioni con uno spazio fra una e l'altra: "regdesc|slice.slicename" diventerà obj.regdesc + " " + obj.slice.slicename
892
+ *
893
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
894
+ * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
895
+ * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
896
+ * @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
897
+ */
898
+ const ExportList = (order, headernavigator, valuenavigator, valueformat = null) => (target, propertyKey) => {
899
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
900
+ Object.defineProperty(target, propertyKey + listCsvValPrefix, { value: valuenavigator, writable: false });
901
+ Object.defineProperty(target, propertyKey + listCsvHdrPrefix, { value: headernavigator, writable: false });
902
+ Object.defineProperty(target, propertyKey + listCsvValFormat, { value: valueformat, writable: false });
903
+ };
904
+ /**
905
+ * Decoratore di esportazione utilizzabile su un dizionario. Se ad esempio si vogliono generare le colonne
906
+ *
907
+ * Valore A = 1
908
+ *
909
+ * Valore B = 2
910
+ *
911
+ * Valore C = 3
912
+ *
913
+ * partendo da un oggetto iniziale { Valore { A: 1, B: 2, C: 3 } }
914
+ *
915
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
916
+ * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
917
+ * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
918
+ */
919
+ const ExportDictionary = (order, headernavigator, valuenavigator) => (target, propertyKey) => {
920
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
921
+ Object.defineProperty(target, propertyKey + dictionaryCsvValPrefix, { value: valuenavigator, writable: false });
922
+ Object.defineProperty(target, propertyKey + dictionaryCsvHdrPrefix, { value: headernavigator, writable: false });
923
+ };
924
+ /**
925
+ * Service che si occupa dell'esportazione degli oggetti marcati dai Decoratori **ExportDictionary**, **ExportList**, **ExportAs** o **Export**
926
+ */
927
+ class ExportService {
928
+ /**
929
+ * Costruttore
930
+ *
931
+ * @ignore
932
+ */
933
+ constructor(dates) {
934
+ this.dates = dates;
935
+ }
936
+ /**
937
+ * Data una lista di oggetti genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
938
+ *
939
+ * @param {any[]} objs Oggetti da esportare
940
+ *
941
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
942
+ */
943
+ setupForExport(objs) {
944
+ let headers = [];
945
+ let headersCache = {};
946
+ if (!objs || objs.length == 0)
947
+ return headers;
948
+ // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
949
+ // Gli header li raccolgo tutti poi faccio uan distinct in modo da esportare tutte le proprietà per bene
950
+ for (let i = 0; i < objs.length; i++) {
951
+ let hds = this.parseAndGetHeaders(objs[i]);
952
+ // Aggiungo gli header facendo in modo di non aggiungerne mai due uguali per non dover fare una distinct dopo
953
+ // che costerebbe comunque risorse. Utilizzo un dizionario d'appoggio per lookup istantanei
954
+ for (let k = 0; k < hds.length; k++) {
955
+ if (!headersCache[hds[k].key]) {
956
+ headersCache[hds[k].key] = true;
957
+ headers.push(hds[k]);
958
+ }
959
+ }
960
+ }
961
+ return headers.sort((a, b) => a.order - b.order);
962
+ }
963
+ /**
964
+ * 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**
965
+ *
966
+ * @param {GenericItem[]} objs Oggetti generici da esportare
967
+ * @param {CsvHeaders[]} columns Colonne richieste dall'esportazione
968
+ *
969
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
970
+ */
971
+ setupForGenericExport(objs, columns) {
972
+ let headers = [];
973
+ if (!objs || objs.length == 0)
974
+ return headers;
975
+ // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
976
+ objs.forEach((obj, index) => {
977
+ if (index == 0)
978
+ headers = this.parseAndGetGenericHeaders(obj, columns);
979
+ else
980
+ this.parseAndGetGenericHeaders(obj, columns);
981
+ });
982
+ return headers;
983
+ }
984
+ /**
985
+ * Dato un oggetto generico genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
986
+ *
987
+ * Metodo interno richiamato da **setupForGenericExport**
988
+ *
989
+ * @param {GenericItem} obj Oggetto generico da esportare
990
+ * @param {CsvColumn[]} columns Colonne richieste dall'esportazione
991
+ *
992
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
993
+ */
994
+ parseAndGetGenericHeaders(obj, columns) {
995
+ if (!obj.properties)
996
+ return null;
997
+ var headers = [];
998
+ //Miracle incoming
999
+ columns.forEach(t => {
1000
+ var propValue = obj.properties[t.key];
1001
+ Object.defineProperty(obj, t.key + "_exp", { value: propValue, writable: false, enumerable: true });
1002
+ headers.push({ label: t.label, key: t.key + "_exp", order: t.order, type: t.type });
1003
+ });
1004
+ //Tirati fuori tutti gli header faccio sort sull'ordinamento
1005
+ return headers.sort((a, b) => { return a.order - b.order; });
1006
+ }
1007
+ /**
1008
+ * Dato un oggetto genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1009
+ *
1010
+ * Metodo interno richiamato da **setupForExport**
1011
+ *
1012
+ * @param {any} obj Oggetto generico da esportare
1013
+ *
1014
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1015
+ */
1016
+ parseAndGetHeaders(obj) {
1017
+ var headers = [];
1018
+ // Miracle incoming
1019
+ for (var prop in obj) {
1020
+ let toCall;
1021
+ if (typeof obj[prop + listCsvHdrPrefix] !== "undefined")
1022
+ toCall = this.parseList.bind(this);
1023
+ else if (typeof obj[prop + dictionaryCsvHdrPrefix] !== "undefined")
1024
+ toCall = this.parseDictionary.bind(this);
1025
+ else if (typeof obj[prop + csvVisPrefix] !== "undefined") {
1026
+ if (typeof obj[prop + csvValueNavigator] !== "undefined")
1027
+ toCall = this.parseObject.bind(this);
1028
+ else
1029
+ toCall = this.parseProperty.bind(this);
1030
+ }
1031
+ if (toCall)
1032
+ toCall(obj, prop, headers);
1033
+ }
1034
+ return headers;
1035
+ }
1036
+ /**
1037
+ * Setup per l'esportazione di una singola proprietà.
1038
+ * Viene generato l'header e la proprietà relativa al valore formattato o no
1039
+ *
1040
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1041
+ * @param {string} prop Proprietà da esportare
1042
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1043
+ */
1044
+ parseProperty(obj, prop, headers) {
1045
+ let toEmit = obj[prop + csvVisPrefix];
1046
+ let format = obj[prop + csvFormatPrefix];
1047
+ let lbl = obj[prop + csvHdrPrefix];
1048
+ let order = obj[prop + csvOrdPrefix];
1049
+ if (toEmit && lbl !== "undefined") {
1050
+ // Se non ho un formato esporto direttamente
1051
+ if (!format) {
1052
+ // Se è un formato data mi assicuro di non stampare mai una data 00:00:00 altrimenti in esportazione viene uno schifo
1053
+ var val = obj[prop] ? this.dates.trimSeconds(obj[prop].toString()) : "";
1054
+ Object.defineProperty(obj, prop + "_nofmt", { value: val, writable: false, enumerable: true });
1055
+ headers.push({ label: lbl ? lbl : prop + "_nofmt", key: prop + "_nofmt", order: order, type: "string" });
1056
+ }
1057
+ else {
1058
+ // Caso formato numerico
1059
+ if (format == "F") {
1060
+ // Check considerando la possibilità di zeri
1061
+ let val = obj[prop] != null ? obj[prop].toString() : "";
1062
+ // Elimino tutte le virgole (indicatori di migliaia per la culture default en-US)
1063
+ val = val.replace(/,/, "");
1064
+ // Il singolo punto che c'è, se presente (separatore decimali) lo trasformo in virgola
1065
+ let valConverted = val.replace(".", ",");
1066
+ Object.defineProperty(obj, prop + "_fmt", { value: valConverted, writable: false, enumerable: true });
1067
+ headers.push({ label: lbl ? lbl : prop + "_fmt", key: prop + "_fmt", order: order, type: "number" });
1068
+ }
1069
+ else {
1070
+ // Se ho un formato data trasformo in dayjs, formatto ed esporto
1071
+ // Per la trasformazione in dayjs provo prima a passargli la stringa di netto, sperando la riconosca
1072
+ // Se non funziona provo a definirgli la formattazione standard del metering per quel linguaggio
1073
+ let val = this.dates.getFormatted(obj[prop], format.length <= 10, false);
1074
+ Object.defineProperty(obj, prop + "_fmt", { value: val ?? "", writable: false, enumerable: true });
1075
+ headers.push({ label: lbl ? lbl : prop + "_fmt", key: prop + "_fmt", order: order, type: "date" });
1076
+ }
1077
+ }
1078
+ }
1079
+ }
1080
+ /**
1081
+ * Setup per l'esportazione di una singola proprietà da un oggetto.
1082
+ * Viene generato l'header e la proprietà relativa al valore formattato o no.
1083
+ *
1084
+ * Per ottenere il valore e l'header della proprietà vengono utilizzati i navigatori auto-generati nel decoratore **ExportAs**
1085
+ *
1086
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1087
+ * @param {string} prop Proprietà da esportare
1088
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1089
+ */
1090
+ parseObject(obj, prop, headers) {
1091
+ //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
1092
+ let valuenavigator = obj[prop + csvValueNavigator];
1093
+ //Es. di valuenavigator obj.subobj.subsubobj.property
1094
+ let jmps = valuenavigator.split(".");
1095
+ //Mi clono l'oggetto originale per non uccidergli i riferimenti
1096
+ let clone = JSON.parse(JSON.stringify(obj));
1097
+ //Salto ricorsivamente su me stesso per arrivare alla proprietà
1098
+ //Salto 1 > diventa obj
1099
+ //Salto 2 > diventa obj.subobj
1100
+ //ecc...
1101
+ jmps.forEach(pp => { clone = clone[pp]; });
1102
+ //Valore finale :D
1103
+ let value = clone;
1104
+ let lbl = obj[prop + csvHdrPrefix];
1105
+ let order = obj[prop + csvOrdPrefix];
1106
+ //Se per questa proprietà ho un formato lo applico
1107
+ let format = obj[prop + csvFormatPrefix];
1108
+ let type = "string";
1109
+ if (format == "F") {
1110
+ let val = value.toString();
1111
+ val = val.replace(/,/, "");
1112
+ value = val.replace(".", ",");
1113
+ type = "number";
1114
+ }
1115
+ else if (format) {
1116
+ value = this.dates.getFormatted(value, format.length <= 10, false);
1117
+ type = "date";
1118
+ }
1119
+ Object.defineProperty(obj, prop, { value: value, writable: false, enumerable: true });
1120
+ headers.push({ label: lbl ? lbl : prop, key: prop, order: order, type: type });
1121
+ }
1122
+ /**
1123
+ * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1124
+ *
1125
+ * => Recupero il valore utilizzando i navigatori
1126
+ *
1127
+ * => Recupero l'header utilizzando i navigatori
1128
+ *
1129
+ * => Con il valore ci creo la property
1130
+ *
1131
+ * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
1132
+ *
1133
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1134
+ * @param {string} prop Proprietà da esportare
1135
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1136
+ */
1137
+ parseList(obj, prop, headers) {
1138
+ let headernavigator = obj[prop + listCsvHdrPrefix];
1139
+ let valuenavigator = obj[prop + listCsvValPrefix];
1140
+ let valueformat = obj[prop + listCsvValFormat];
1141
+ let order = obj[prop + csvOrdPrefix];
1142
+ var jumps, tmpRes;
1143
+ var objs = obj[prop];
1144
+ for (let idx = 0; idx < objs.length; idx++) {
1145
+ let listitem = objs[idx];
1146
+ var headersplit = headernavigator.split(" ");
1147
+ var header = "";
1148
+ // Per l'header si considera a se stante ogni pezzo separato da spazio per fare le concatenazioni
1149
+ headersplit.forEach(pr => {
1150
+ jumps = pr.split(".");
1151
+ tmpRes = JSON.parse(JSON.stringify(listitem));
1152
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1153
+ if (!header)
1154
+ header = tmpRes;
1155
+ else
1156
+ header += " " + tmpRes;
1157
+ });
1158
+ jumps = valuenavigator.split(".");
1159
+ tmpRes = JSON.parse(JSON.stringify(listitem));
1160
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1161
+ let value = tmpRes;
1162
+ let type = "string";
1163
+ if (valueformat == "F") {
1164
+ let val = value != null ? value.toString() : "";
1165
+ val = val.replace(/,/, "");
1166
+ value = val.replace(".", ",");
1167
+ type = "number";
1168
+ }
1169
+ else if (valueformat) {
1170
+ value = this.dates.getFormatted(obj[prop], valueformat.length <= 10, false);
1171
+ type = "date";
1172
+ }
1173
+ Object.defineProperty(obj, prop + idx, { value: value, writable: false });
1174
+ headers.push({ label: header, key: prop + idx, order: order + idx, type: type });
1175
+ }
1176
+ }
1177
+ /**
1178
+ * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1179
+ *
1180
+ * => Recupero il valore utilizzando i navigatori
1181
+ *
1182
+ * => Recupero l'header utilizzando i navigatori
1183
+ *
1184
+ * => Con il valore ci creo la property
1185
+ *
1186
+ * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
1187
+ *
1188
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1189
+ * @param {string} prop Proprietà da esportare
1190
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1191
+ */
1192
+ parseDictionary(obj, prop, headers) {
1193
+ let headernavigator = obj[prop + dictionaryCsvHdrPrefix];
1194
+ let valuenavigator = obj[prop + dictionaryCsvValPrefix];
1195
+ let order = obj[prop + csvOrdPrefix];
1196
+ var jumps, tmpRes;
1197
+ var objs = obj[prop];
1198
+ for (let idx = 0; idx < objs.length; idx++) {
1199
+ let listitem = objs[idx];
1200
+ var headersplit = headernavigator.split(" ");
1201
+ var header = "";
1202
+ headersplit.forEach(pr => {
1203
+ jumps = pr.split(".");
1204
+ tmpRes = JSON.parse(JSON.stringify(listitem));
1205
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1206
+ if (!header)
1207
+ header = tmpRes;
1208
+ else
1209
+ header += " " + tmpRes;
1210
+ });
1211
+ var valuesplit = valuenavigator.split(",");
1212
+ valuesplit.forEach((t, idxinternal) => {
1213
+ var navig = t.split("-")[1];
1214
+ var desc = t.split("-")[0];
1215
+ jumps = navig.split(".");
1216
+ tmpRes = JSON.parse(JSON.stringify(listitem));
1217
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1218
+ let value = tmpRes;
1219
+ let propname = prop + idx.toString() + idxinternal.toString();
1220
+ Object.defineProperty(obj, propname, { value: value, writable: false });
1221
+ headers.push({ label: header + " " + desc, key: propname, order: order + idx, type: 'string' });
1222
+ });
1223
+ }
1224
+ }
1225
+ /**
1226
+ * Metodo che si occupa della deserializzazione degli oggetti da esportare. Messo a livello di libreria in modo che qualora ci fosse da cambiare libreria
1227
+ * tutte le manutenzioni siano concentrate qui
1228
+ *
1229
+ * @param {any[]} items Oggetti da deserializzare
1230
+ * @param {any} type Tipo da usare come prototipo per la deserializzazione
1231
+ *
1232
+ * @returns {any} Oggetti deserializzati
1233
+ */
1234
+ deserializeForExport(items, type) {
1235
+ return Deserialize(items, type);
1236
+ }
1237
+ }
1238
+ ExportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExportService, deps: [{ token: DateService }], target: i0.ɵɵFactoryTarget.Injectable });
1239
+ ExportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExportService });
1240
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: ExportService, decorators: [{
1241
+ type: Injectable
1242
+ }], ctorParameters: function () { return [{ type: DateService }]; } });
1243
+
1244
+ // Angular
1245
+ /**
1246
+ * Service che fornisce alcuni semplici funzioni di Hashing / GUID / ecc...
1247
+ */
1248
+ class HashingService {
1249
+ constructor() {
1250
+ /**
1251
+ * Blacklist dei tipi da ignorare quando si effettua l'hashing degli oggetti
1252
+ */
1253
+ this.objBlacklist = {
1254
+ "NgForm": true, "ElementRef": true, "ExtensionsService": true, "ToastrService": true, "LocaleService": true, "AppState": true, "Router": true,
1255
+ "ActivatedRoute": true, "HTTPService": true, "Location": true, "CanvasComponent": true, "ModalDirective": true, "ChangeDetectorRef": true,
1256
+ "DateService": true, "EventEmitter": true, "ViewRef_": true, "Subscriber": true, "ItemLocalization": true
1257
+ };
1258
+ /**
1259
+ * Array dei possibili valori di un simbolo esadecimale
1260
+ */
1261
+ this.hex_chr = '0123456789abcdef'.split('');
1262
+ }
1263
+ /**
1264
+ * Generazione di un GUID pseudo-univoco
1265
+ *
1266
+ * @returns {string} il GUID generato
1267
+ */
1268
+ getGUID() {
1269
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, c => {
1270
+ var r = Math.random() * 16 | 0, v = c == "x" ? r : (r & 0x3 | 0x8);
1271
+ return v.toString(16);
1272
+ });
1273
+ }
1274
+ /**
1275
+ * Calcolo dell'hash su un oggetto
1276
+ *
1277
+ * @param {any} o Oggetto di cui calcolare l'hash
1278
+ * @param {number} level Livello di ricorsione nel caso venga effettuato l'hash di un oggetto che contiene altri oggetti
1279
+ * @param {boolean} navigateFullDepth Indica se navigare l'oggetto per l'intera lunghezza. In caso contrario si ferma al secondo livello
1280
+ *
1281
+ * @returns {string} Hash generato per l'oggetto in questione
1282
+ */
1283
+ hashObject(o, level = 0, navigateFullDepth = false, precise = false) {
1284
+ var strDef = this.stringify(o, level, navigateFullDepth);
1285
+ var hash = precise ? this.md5(strDef) : this.simpleHash(strDef);
1286
+ return hash;
1287
+ }
1288
+ /**
1289
+ * Hash più semplice e più veloce dell'md5, ma meno sicuro
1290
+ *
1291
+ * Vedi https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript
1292
+ *
1293
+ * @param {string} str Stringa di cui calcolare l'hash
1294
+ */
1295
+ simpleHash(str, seed = 0) {
1296
+ let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
1297
+ for (let i = 0, ch; i < str.length; i++) {
1298
+ ch = str.charCodeAt(i);
1299
+ h1 = Math.imul(h1 ^ ch, 2654435761);
1300
+ h2 = Math.imul(h2 ^ ch, 1597334677);
1301
+ }
1302
+ h1 = Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^ Math.imul(h2 ^ (h2 >>> 13), 3266489909);
1303
+ h2 = Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^ Math.imul(h1 ^ (h1 >>> 13), 3266489909);
1304
+ return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString();
1305
+ }
1306
+ /**
1307
+ * Genera una stringa che identifica univocamente l'oggetto in questione
1308
+ *
1309
+ * @param {any} o Oggetto di cui calcolare la stringa univoca
1310
+ * @param {number} level Livello di ricorsione nel caso venga effettuato l'hash di un oggetto che contiene altri oggetti
1311
+ * @param {boolean} navigateFullDepth Indica se navigare l'oggetto per l'intera lunghezza. In caso contrario si ferma al secondo livello
1312
+ */
1313
+ stringify(o, level, navigateFullDepth) {
1314
+ var i, r;
1315
+ if (o === null)
1316
+ return "n";
1317
+ if (o === true)
1318
+ return "t";
1319
+ if (o === false)
1320
+ return "f";
1321
+ if (o instanceof Date)
1322
+ return 'd:' + o.valueOf().toString();
1323
+ i = typeof o;
1324
+ if (i === "string")
1325
+ return "s:" + o;
1326
+ if (i === "number")
1327
+ return "n:" + o;
1328
+ if (o instanceof Function)
1329
+ return "m:" + o.toString();
1330
+ if (o instanceof Array) {
1331
+ r = [];
1332
+ for (i = 0; i < o.length; i++) {
1333
+ let res = this.stringify(o[i], level, navigateFullDepth);
1334
+ if (res)
1335
+ r.push(res);
1336
+ }
1337
+ return r.length > 0 ? "a:" + r.join(";") : "";
1338
+ }
1339
+ r = [];
1340
+ //Se è oggetto, escludo tutti quelli di sistema/inutili
1341
+ if (o) {
1342
+ var name = o.__proto__.constructor.name;
1343
+ if (!this.objBlacklist[name]) {
1344
+ for (i in o) {
1345
+ if (o.hasOwnProperty(i) && (level <= 2 || navigateFullDepth)) {
1346
+ let res = this.stringify(o[i], level + 1, navigateFullDepth);
1347
+ if (res)
1348
+ r.push(i + ":" + res);
1349
+ }
1350
+ }
1351
+ }
1352
+ }
1353
+ return r.length > 0 ? "o:" + r.join(";") : "";
1354
+ }
1355
+ /**
1356
+ * Data una stringa restituisce l'md5
1357
+ *
1358
+ * @param {string} s Stringa di cui calcolare l'md5
1359
+ * @returns {string} md5 della stringa **s**
1360
+ */
1361
+ md5(s) {
1362
+ return this.hex(this.md51(s));
1363
+ }
1364
+ /**
1365
+ * @ignore
1366
+ *
1367
+ * Metodo di utilità per il calcolo dell'md5
1368
+ */
1369
+ md5cycle(x, k) {
1370
+ var a = x[0], b = x[1], c = x[2], d = x[3];
1371
+ a = this.ff(a, b, c, d, k[0], 7, -680876936);
1372
+ d = this.ff(d, a, b, c, k[1], 12, -389564586);
1373
+ c = this.ff(c, d, a, b, k[2], 17, 606105819);
1374
+ b = this.ff(b, c, d, a, k[3], 22, -1044525330);
1375
+ a = this.ff(a, b, c, d, k[4], 7, -176418897);
1376
+ d = this.ff(d, a, b, c, k[5], 12, 1200080426);
1377
+ c = this.ff(c, d, a, b, k[6], 17, -1473231341);
1378
+ b = this.ff(b, c, d, a, k[7], 22, -45705983);
1379
+ a = this.ff(a, b, c, d, k[8], 7, 1770035416);
1380
+ d = this.ff(d, a, b, c, k[9], 12, -1958414417);
1381
+ c = this.ff(c, d, a, b, k[10], 17, -42063);
1382
+ b = this.ff(b, c, d, a, k[11], 22, -1990404162);
1383
+ a = this.ff(a, b, c, d, k[12], 7, 1804603682);
1384
+ d = this.ff(d, a, b, c, k[13], 12, -40341101);
1385
+ c = this.ff(c, d, a, b, k[14], 17, -1502002290);
1386
+ b = this.ff(b, c, d, a, k[15], 22, 1236535329);
1387
+ a = this.gg(a, b, c, d, k[1], 5, -165796510);
1388
+ d = this.gg(d, a, b, c, k[6], 9, -1069501632);
1389
+ c = this.gg(c, d, a, b, k[11], 14, 643717713);
1390
+ b = this.gg(b, c, d, a, k[0], 20, -373897302);
1391
+ a = this.gg(a, b, c, d, k[5], 5, -701558691);
1392
+ d = this.gg(d, a, b, c, k[10], 9, 38016083);
1393
+ c = this.gg(c, d, a, b, k[15], 14, -660478335);
1394
+ b = this.gg(b, c, d, a, k[4], 20, -405537848);
1395
+ a = this.gg(a, b, c, d, k[9], 5, 568446438);
1396
+ d = this.gg(d, a, b, c, k[14], 9, -1019803690);
1397
+ c = this.gg(c, d, a, b, k[3], 14, -187363961);
1398
+ b = this.gg(b, c, d, a, k[8], 20, 1163531501);
1399
+ a = this.gg(a, b, c, d, k[13], 5, -1444681467);
1400
+ d = this.gg(d, a, b, c, k[2], 9, -51403784);
1401
+ c = this.gg(c, d, a, b, k[7], 14, 1735328473);
1402
+ b = this.gg(b, c, d, a, k[12], 20, -1926607734);
1403
+ a = this.hh(a, b, c, d, k[5], 4, -378558);
1404
+ d = this.hh(d, a, b, c, k[8], 11, -2022574463);
1405
+ c = this.hh(c, d, a, b, k[11], 16, 1839030562);
1406
+ b = this.hh(b, c, d, a, k[14], 23, -35309556);
1407
+ a = this.hh(a, b, c, d, k[1], 4, -1530992060);
1408
+ d = this.hh(d, a, b, c, k[4], 11, 1272893353);
1409
+ c = this.hh(c, d, a, b, k[7], 16, -155497632);
1410
+ b = this.hh(b, c, d, a, k[10], 23, -1094730640);
1411
+ a = this.hh(a, b, c, d, k[13], 4, 681279174);
1412
+ d = this.hh(d, a, b, c, k[0], 11, -358537222);
1413
+ c = this.hh(c, d, a, b, k[3], 16, -722521979);
1414
+ b = this.hh(b, c, d, a, k[6], 23, 76029189);
1415
+ a = this.hh(a, b, c, d, k[9], 4, -640364487);
1416
+ d = this.hh(d, a, b, c, k[12], 11, -421815835);
1417
+ c = this.hh(c, d, a, b, k[15], 16, 530742520);
1418
+ b = this.hh(b, c, d, a, k[2], 23, -995338651);
1419
+ a = this.ii(a, b, c, d, k[0], 6, -198630844);
1420
+ d = this.ii(d, a, b, c, k[7], 10, 1126891415);
1421
+ c = this.ii(c, d, a, b, k[14], 15, -1416354905);
1422
+ b = this.ii(b, c, d, a, k[5], 21, -57434055);
1423
+ a = this.ii(a, b, c, d, k[12], 6, 1700485571);
1424
+ d = this.ii(d, a, b, c, k[3], 10, -1894986606);
1425
+ c = this.ii(c, d, a, b, k[10], 15, -1051523);
1426
+ b = this.ii(b, c, d, a, k[1], 21, -2054922799);
1427
+ a = this.ii(a, b, c, d, k[8], 6, 1873313359);
1428
+ d = this.ii(d, a, b, c, k[15], 10, -30611744);
1429
+ c = this.ii(c, d, a, b, k[6], 15, -1560198380);
1430
+ b = this.ii(b, c, d, a, k[13], 21, 1309151649);
1431
+ a = this.ii(a, b, c, d, k[4], 6, -145523070);
1432
+ d = this.ii(d, a, b, c, k[11], 10, -1120210379);
1433
+ c = this.ii(c, d, a, b, k[2], 15, 718787259);
1434
+ b = this.ii(b, c, d, a, k[9], 21, -343485551);
1435
+ x[0] = this.add32(a, x[0]);
1436
+ x[1] = this.add32(b, x[1]);
1437
+ x[2] = this.add32(c, x[2]);
1438
+ x[3] = this.add32(d, x[3]);
1439
+ }
1440
+ /**
1441
+ * @ignore
1442
+ *
1443
+ * Metodo di utilità per il calcolo dell'md5
1444
+ */
1445
+ cmn(q, a, b, x, s, t) {
1446
+ a = this.add32(this.add32(a, q), this.add32(x, t));
1447
+ return this.add32((a << s) | (a >>> (32 - s)), b);
1448
+ }
1449
+ /**
1450
+ * @ignore
1451
+ *
1452
+ * Metodo di utilità per il calcolo dell'md5
1453
+ */
1454
+ ff(a, b, c, d, x, s, t) {
1455
+ return this.cmn((b & c) | ((~b) & d), a, b, x, s, t);
1456
+ }
1457
+ /**
1458
+ * @ignore
1459
+ *
1460
+ * Metodo di utilità per il calcolo dell'md5
1461
+ */
1462
+ gg(a, b, c, d, x, s, t) {
1463
+ return this.cmn((b & d) | (c & (~d)), a, b, x, s, t);
1464
+ }
1465
+ /**
1466
+ * @ignore
1467
+ *
1468
+ * Metodo di utilità per il calcolo dell'md5
1469
+ */
1470
+ hh(a, b, c, d, x, s, t) {
1471
+ return this.cmn(b ^ c ^ d, a, b, x, s, t);
1472
+ }
1473
+ /**
1474
+ * @ignore
1475
+ *
1476
+ * Metodo di utilità per il calcolo dell'md5
1477
+ */
1478
+ ii(a, b, c, d, x, s, t) {
1479
+ return this.cmn(c ^ (b | (~d)), a, b, x, s, t);
1480
+ }
1481
+ /**
1482
+ * @ignore
1483
+ *
1484
+ * Metodo di utilità per il calcolo dell'md5
1485
+ */
1486
+ md51(s) {
1487
+ var n = s.length, state = [1732584193, -271733879, -1732584194, 271733878], i;
1488
+ for (i = 64; i <= s.length; i += 64)
1489
+ this.md5cycle(state, this.md5blk(s.substring(i - 64, i)));
1490
+ s = s.substring(i - 64);
1491
+ var tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
1492
+ for (i = 0; i < s.length; i++)
1493
+ tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
1494
+ tail[i >> 2] |= 0x80 << ((i % 4) << 3);
1495
+ if (i > 55) {
1496
+ this.md5cycle(state, tail);
1497
+ for (i = 0; i < 16; i++)
1498
+ tail[i] = 0;
1499
+ }
1500
+ tail[14] = n * 8;
1501
+ this.md5cycle(state, tail);
1502
+ return state;
1503
+ }
1504
+ /**
1505
+ * @ignore
1506
+ *
1507
+ * Metodo di utilità per il calcolo dell'md5
1508
+ */
1509
+ md5blk(s) {
1510
+ var md5blks = [], i;
1511
+ for (i = 0; i < 64; i += 4)
1512
+ md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
1513
+ return md5blks;
1514
+ }
1515
+ /**
1516
+ * @ignore
1517
+ *
1518
+ * Metodo di utilità per il calcolo dell'md5
1519
+ */
1520
+ rhex(n) {
1521
+ var s = '', j = 0;
1522
+ for (; j < 4; j++)
1523
+ s += this.hex_chr[(n >> (j * 8 + 4)) & 0x0F] + this.hex_chr[(n >> (j * 8)) & 0x0F];
1524
+ return s;
1525
+ }
1526
+ /**
1527
+ * @ignore
1528
+ *
1529
+ * Metodo di utilità per il calcolo dell'md5
1530
+ */
1531
+ hex(x) {
1532
+ for (var i = 0; i < x.length; i++)
1533
+ x[i] = this.rhex(x[i]);
1534
+ return x.join('');
1535
+ }
1536
+ /**
1537
+ * @ignore
1538
+ *
1539
+ * Metodo di utilità per il calcolo dell'md5
1540
+ */
1541
+ add32(a, b) {
1542
+ return (a + b) & 0xFFFFFFFF;
1543
+ }
1544
+ }
1545
+ HashingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: HashingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1546
+ HashingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: HashingService });
1547
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: HashingService, decorators: [{
1548
+ type: Injectable
1549
+ }] });
1550
+
1551
+ /**
1552
+ * Mappatura del TypeCode del C#
1553
+ */
1554
+ var TypeCode;
1555
+ (function (TypeCode) {
1556
+ /** @ignore */ TypeCode[TypeCode["Empty"] = 0] = "Empty";
1557
+ /** @ignore */ TypeCode[TypeCode["Obj"] = 1] = "Obj";
1558
+ /** @ignore */ TypeCode[TypeCode["DBNull"] = 2] = "DBNull";
1559
+ /** @ignore */ TypeCode[TypeCode["Boolean"] = 3] = "Boolean";
1560
+ /** @ignore */ TypeCode[TypeCode["Char"] = 4] = "Char";
1561
+ /** @ignore */ TypeCode[TypeCode["SByte"] = 5] = "SByte";
1562
+ /** @ignore */ TypeCode[TypeCode["Byte"] = 6] = "Byte";
1563
+ /** @ignore */ TypeCode[TypeCode["Int16"] = 7] = "Int16";
1564
+ /** @ignore */ TypeCode[TypeCode["UInt16"] = 8] = "UInt16";
1565
+ /** @ignore */ TypeCode[TypeCode["Int32"] = 9] = "Int32";
1566
+ /** @ignore */ TypeCode[TypeCode["UInt32"] = 10] = "UInt32";
1567
+ /** @ignore */ TypeCode[TypeCode["Int64"] = 11] = "Int64";
1568
+ /** @ignore */ TypeCode[TypeCode["UInt64"] = 12] = "UInt64";
1569
+ /** @ignore */ TypeCode[TypeCode["Single"] = 13] = "Single";
1570
+ /** @ignore */ TypeCode[TypeCode["Double"] = 14] = "Double";
1571
+ /** @ignore */ TypeCode[TypeCode["Decimal"] = 15] = "Decimal";
1572
+ /** @ignore */ TypeCode[TypeCode["DateTime"] = 16] = "DateTime";
1573
+ /** @ignore */ TypeCode[TypeCode["String"] = 18] = "String";
1574
+ })(TypeCode || (TypeCode = {}));
1575
+
1576
+ // Angular
1577
+ /**
1578
+ * Service che fornisce metodi di pubblica utilità
1579
+ */
1580
+ class UtilityService {
1581
+ /**
1582
+ * Deseleziona il testo eventualmente selezionato
1583
+ */
1584
+ clearTextSelection() {
1585
+ if (window.getSelection) {
1586
+ if (window.getSelection().empty) // Chrome
1587
+ window.getSelection().empty();
1588
+ else if (window.getSelection().removeAllRanges) // Firefox
1589
+ window.getSelection().removeAllRanges();
1590
+ }
1591
+ else if (document.selection) // IE?
1592
+ document.selection.empty();
1593
+ }
1594
+ /**
1595
+ * Partendo da una lista, dato il nome della proprietà chiave e il valore della chiave selezionata,
1596
+ * trova e restituisce l'oggetto desiderato
1597
+ *
1598
+ * @param {T[]} sourceList Lista di oggetti dentro cui cercare
1599
+ * @param {string} sourceItemIdField Nome della proprietà che rappresenta la chiave di un oggetto di tipo T
1600
+ * @param {string} selectedValue Valore di chiave selezionato
1601
+ *
1602
+ * @returns {T} Oggetto la cui proprietà **sourceItemIdField** assume il valore **selectedValue**
1603
+ */
1604
+ getSelectedItem(sourceList, sourceItemIdField, selectedValue) {
1605
+ for (let i = 0; i < sourceList.length; i++) {
1606
+ var item = sourceList[i];
1607
+ if (item[sourceItemIdField] == selectedValue)
1608
+ return item;
1609
+ }
1610
+ return null;
1611
+ }
1612
+ /**
1613
+ * Effettua il reset di un Form di Angular
1614
+ *
1615
+ * @param {NgForm} form Form da resettare
1616
+ * @param {string} exception1 Campo da non resettare
1617
+ * @param {string} exception2 Campo da non resettare
1618
+ */
1619
+ cleanForm(form, exception1 = null, exception2 = null) {
1620
+ for (let name in form.controls) {
1621
+ if (name && name != exception1 && name != exception1 + "_internal" && name != exception2 && name != exception2 + "_internal") {
1622
+ form.controls[name].reset();
1623
+ }
1624
+ else {
1625
+ form.controls[name].markAsPristine();
1626
+ form.controls[name].markAsUntouched();
1627
+ }
1628
+ }
1629
+ //Reimposto il submitted
1630
+ form.submitted = false;
1631
+ }
1632
+ /**
1633
+ * Helper che permette di scaricare un file dato un URL (Generato da una chiamata ad **window.URL.createObjectURL**)
1634
+ *
1635
+ * @param {string} url ObjectURL che rappresenta il file da scaricare
1636
+ * @param {string} filename Nome del file suggerito in fase di salvataggio
1637
+ */
1638
+ fileDownload(url, fileName) {
1639
+ var a = document.createElement("a");
1640
+ document.body.appendChild(a);
1641
+ a.className = "ta-display-none";
1642
+ a.href = url;
1643
+ a.download = fileName;
1644
+ a.click();
1645
+ window.URL.revokeObjectURL(url);
1646
+ document.body.removeChild(a);
1647
+ }
1648
+ /**
1649
+ * Helper per la formattazione di un numero di millisecondi in una stringa più comprensibile per un umano
1650
+ *
1651
+ * @param {number} duration Tempo espresso in millisecondi
1652
+ *
1653
+ * @returns {string} Durata formattata
1654
+ */
1655
+ msToTime(duration) {
1656
+ if (!duration)
1657
+ return "";
1658
+ 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());
1659
+ var st_hours = (hours < 10) ? "0" + hours : hours;
1660
+ var st_minutes = (minutes < 10) ? "0" + minutes : minutes;
1661
+ var st_seconds = (seconds < 10) ? "0" + seconds : seconds;
1662
+ return st_hours + ":" + st_minutes + ":" + st_seconds + "." + milliseconds;
1663
+ }
1664
+ /**
1665
+ * Helper che permette di scaricare un file in Base64
1666
+ *
1667
+ * @param {string} base64Data Base64 che rappresenta il file da scaricare
1668
+ * @param {string} filename Nome del file suggerito in fase di salvataggio
1669
+ */
1670
+ saveFile(base64Data, filename) {
1671
+ var sampleArr = this.base64ToArrayBuffer(base64Data);
1672
+ this.saveByteArray(sampleArr, filename);
1673
+ }
1674
+ /**
1675
+ * Trasforma un Base64 in un ArrayBuffer
1676
+ *
1677
+ * @param {string} base64Data Base64 da trasformare
1678
+ *
1679
+ * @returns {Uint8Array} Array UTF8
1680
+ */
1681
+ base64ToArrayBuffer(base64Data) {
1682
+ var binaryString = window.atob(base64Data);
1683
+ var binaryLen = binaryString.length;
1684
+ var bytes = new Uint8Array(binaryLen);
1685
+ for (var i = 0; i < binaryLen; i++) {
1686
+ var ascii = binaryString.charCodeAt(i);
1687
+ bytes[i] = ascii;
1688
+ }
1689
+ return bytes;
1690
+ }
1691
+ /**
1692
+ * Helper che permette di scaricare un file dato un array di Byte (**Uint8Array**)
1693
+ *
1694
+ * @param {Uint8Array} byte Rappresentazione del file da scaricare
1695
+ * @param {string} filename Nome del file suggerito in fase di salvataggio
1696
+ */
1697
+ saveByteArray(byte, filename) {
1698
+ var blob = new Blob([byte]);
1699
+ var link = document.createElement("a");
1700
+ document.body.appendChild(link);
1701
+ link.href = window.URL.createObjectURL(blob);
1702
+ var fileName = filename;
1703
+ link.download = fileName;
1704
+ link.click();
1705
+ document.body.removeChild(link);
1706
+ }
1707
+ ;
1708
+ /**
1709
+ * Utility per lo swap di due elementi di un array
1710
+ *
1711
+ * @param {any[]} array Array di cui invertire due elementi
1712
+ * @param {number} x Indice del primo elemento
1713
+ * @param {number} y Indice del secondo elemento
1714
+ */
1715
+ swap(array, x, y) {
1716
+ var b = array[x];
1717
+ array[x] = array[y];
1718
+ array[y] = b;
1719
+ }
1720
+ /**
1721
+ * Helper di trascodifica da tipo c# a tipo Typescript
1722
+ *
1723
+ * @param {TypeCode} type Tipo da trascodificare
1724
+ *
1725
+ * @returns {"boolean" | "number" | "string" | "date"} Tipo Typescript corrispondente
1726
+ */
1727
+ getJsTypeFromTypeCode(type) {
1728
+ switch (type) {
1729
+ case TypeCode.Boolean:
1730
+ return "boolean";
1731
+ case TypeCode.Decimal:
1732
+ case TypeCode.Double:
1733
+ case TypeCode.Single:
1734
+ case TypeCode.Int16:
1735
+ case TypeCode.Int32:
1736
+ case TypeCode.Int64:
1737
+ case TypeCode.Byte:
1738
+ case TypeCode.SByte:
1739
+ case TypeCode.UInt16:
1740
+ case TypeCode.UInt32:
1741
+ case TypeCode.UInt64:
1742
+ return "number";
1743
+ case TypeCode.Char:
1744
+ case TypeCode.String:
1745
+ return "string";
1746
+ case TypeCode.DateTime:
1747
+ return "date";
1748
+ default:
1749
+ console.log("Unrecognized input type. Typecode:" + type);
1750
+ return "string";
1751
+ }
1752
+ }
1753
+ }
1754
+ UtilityService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: UtilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1755
+ UtilityService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: UtilityService });
1756
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: UtilityService, decorators: [{
1757
+ type: Injectable
1758
+ }] });
1759
+
1760
+ /**
1761
+ * Classe astratta che si occupa di recuperare l'Id sessione univoco per applicazione ed utente collegato
1762
+ */
1763
+ class BaseSessionRetriever {
1764
+ }
1765
+
1766
+ /**
1767
+ * Classe che gestisce la scrittura delle informazioni nello store locale.
1768
+ * Questo store locale potrebbe essere il localStorage (implementazione di default data dal **DefaultStorageProvider**),
1769
+ * oppure un'implementazione custom facente capo a un DB esterno.
1770
+ *
1771
+ * In questo ultimo caso però sarà necessario implementarsi un proprio **BaseSessionRetriever**
1772
+ * che generi una chiave univoca di sessione su cui tutte le operazioni di questa classe saranno eseguite
1773
+ */
1774
+ class BaseStorageProvider {
1775
+ /** @ignore Costruttore */
1776
+ constructor(session) {
1777
+ this.session = session;
1778
+ }
1779
+ /**
1780
+ * Ottiene la chiave "Reale" da utilizzare per la persistenza di una chiave generica
1781
+ *
1782
+ * @param {string} key Chiave da storicizzare
1783
+ *
1784
+ * @returns {string} Unione fra l'identificativo della sessione e la chiave specificata
1785
+ */
1786
+ getKey(key) {
1787
+ return this.session.getSessionKey() + "§" + key + "§";
1788
+ }
1789
+ }
1790
+
1791
+ // Angular
1792
+ /**
1793
+ * Service che fornisce funzionalità di base per storicizzazione e recupero oggetti dallo Storage Locale
1794
+ *
1795
+ * N.B: In ogni chiamata è presente l'operatore rxjs **first()** per far sì che a prescindere dall'implementazione utente/default gli
1796
+ * observable effettuino l'unsubscribe automaticamente terminata la prima operazine
1797
+ */
1798
+ class StorageService {
1799
+ /**
1800
+ * Costruttore
1801
+ *
1802
+ * @ignore
1803
+ */
1804
+ constructor(APPSEARCH_PREFIX, _session, _storage) {
1805
+ this.APPSEARCH_PREFIX = APPSEARCH_PREFIX;
1806
+ this._session = _session;
1807
+ this._storage = _storage;
1808
+ }
1809
+ /**
1810
+ * Inserisce un oggetto che funga da contenitore di oggetti nel local storage, ripulendone gli oggetti (supponendo che sia una view di ricerca) e marcandolo come
1811
+ * salvato, in modo che quando viene recuperato il sistema non pensi che sia un oggetto vuoto ma che sappia che gli oggetti son stati ripuliti per risparmiare spazio
1812
+ *
1813
+ * @param {string} storeName Chiave del localStorage in cui storicizzare l'oggetto **itemsContainer**
1814
+ * @param {{ items: any[] }} itemsContainer Oggetto da storicizzare
1815
+ */
1816
+ setItem(storeName, item) {
1817
+ var finalItem;
1818
+ //Se sto salvando un oggetto con "items" e "page" vuol dire che è un appsearch, la ripulisco
1819
+ if (item.items && item.page) {
1820
+ finalItem = JSON.parse(JSON.stringify(item));
1821
+ finalItem.items = [];
1822
+ finalItem.savedstate = true;
1823
+ finalItem.savedprefix = this.APPSEARCH_PREFIX || 'Hot';
1824
+ }
1825
+ else
1826
+ finalItem = item;
1827
+ return this._storage.setItem(storeName, finalItem).pipe(first(), tap(res => {
1828
+ if (res == false)
1829
+ console.error("Impossibile effettuare il salvataggio dell'oggetto all'interno dello Storage Locale per la chiave " + storeName);
1830
+ }));
1831
+ }
1832
+ /**
1833
+ * Recupera un oggetto dallo Storage Locale
1834
+ *
1835
+ * @param {string} storeName Chiave del localStorage da cui recuperare l'oggetto
1836
+ *
1837
+ * @returns {any} Oggetto recuperato e deserializzato
1838
+ */
1839
+ getItem(storeName) {
1840
+ return this._storage.getItem(storeName).pipe(first(), tap(res => {
1841
+ if (res == null)
1842
+ console.warn("Impossibile ottenere l'oggetto salvato con chiave " + storeName);
1843
+ }));
1844
+ }
1845
+ /**
1846
+ * Ripulisce lo Storage Locale
1847
+ *
1848
+ * @param {string} storeName Chiave del localStorage da ripulire
1849
+ */
1850
+ removeItem(storeName) {
1851
+ return this._storage.removeItem(storeName).pipe(first(), tap(res => {
1852
+ if (res == false)
1853
+ console.warn("Impossibile rimuovere l'oggetto salvato con chiave " + storeName);
1854
+ }));
1855
+ }
1856
+ /**
1857
+ * Ripulisce lo Storage Locale di ogni cosa salvata
1858
+ *
1859
+ * @param {string} storeName Chiave del localStorage da ripulire
1860
+ */
1861
+ clear() {
1862
+ return this._storage.clear().pipe(first(), tap(res => {
1863
+ if (res == false)
1864
+ console.warn("Impossibile ripulire lo Storage Locale");
1865
+ }));
1866
+ }
1867
+ /**
1868
+ * Restituisce tutte le chiavi-valore associate alla sessione corrente
1869
+ *
1870
+ * @returns {Observable<{ [index: string]: string; }>} Risultato della query
1871
+ */
1872
+ getAll() {
1873
+ return this._storage.getAll().pipe(first());
1874
+ }
1875
+ }
1876
+ StorageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageService, deps: [{ token: APPSEARCH_PREFIX, optional: true }, { token: BaseSessionRetriever }, { token: BaseStorageProvider }], target: i0.ɵɵFactoryTarget.Injectable });
1877
+ StorageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageService });
1878
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: StorageService, decorators: [{
1879
+ type: Injectable
1880
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
1881
+ type: Optional
1882
+ }, {
1883
+ type: Inject,
1884
+ args: [APPSEARCH_PREFIX]
1885
+ }] }, { type: BaseSessionRetriever }, { type: BaseStorageProvider }]; } });
1886
+
1887
+ /**
1888
+ * Implementazione di default per la classe **BaseSessionRetriever**
1889
+ */
1890
+ class DefaultSessionRetriever extends BaseSessionRetriever {
1891
+ /**
1892
+ * Costruttore
1893
+ *
1894
+ * @ignore
1895
+ */
1896
+ constructor() { super(); }
1897
+ /**
1898
+ * Ottiene un ID sessione
1899
+ *
1900
+ * @returns {string} ID sessione
1901
+ */
1902
+ getSessionKey() {
1903
+ return "DUMMY_SESSION";
1904
+ }
1905
+ }
1906
+ DefaultSessionRetriever.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DefaultSessionRetriever, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1907
+ DefaultSessionRetriever.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DefaultSessionRetriever });
1908
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DefaultSessionRetriever, decorators: [{
1909
+ type: Injectable
1910
+ }], ctorParameters: function () { return []; } });
1911
+
1912
+ /** Implementazione di default per la classe **BaseStorageProvider** */
1913
+ class DefaultStorageProvider extends BaseStorageProvider {
1914
+ /** @ignore Costruttore */
1915
+ constructor(session) { super(session); }
1916
+ /** @ignore Implementazione di Default con localStorage. Identity viene ignorata perché essendo già nel localStorage è già per sito */
1917
+ setItem(key, value) {
1918
+ try {
1919
+ localStorage.setItem(key, JSON.stringify(value));
1920
+ return of(true);
1921
+ }
1922
+ catch {
1923
+ // Potrebbe arrivarmi un prefisso di salvataggio nella modalità di default. Questo serve per ripulire le stesse cose con quel prefisso e sperare di liberare spazio
1924
+ if (value.savedprefix) {
1925
+ console.warn("Spazio del local Storage insufficiente, prova a ripulirlo e risalvare");
1926
+ //Pulisco tutte le view con nome che parta per "Hot"
1927
+ for (let key in localStorage) {
1928
+ if (localStorage.hasOwnProperty(key) && key.startsWith(value.savedprefix))
1929
+ delete localStorage[key];
1930
+ }
1931
+ try {
1932
+ localStorage.setItem(key, JSON.stringify(value));
1933
+ }
1934
+ catch (e) {
1935
+ console.error("Spazio del local Storage insufficiente per salvare i risultati di ricerca con solo filtri. Non salvo nulla");
1936
+ }
1937
+ }
1938
+ return of(false);
1939
+ }
1940
+ }
1941
+ /** @ignore Implementazione di Default con localStorage. Identity viene ignorata perché essendo già nel localStorage è già per sito */
1942
+ getItem(key) {
1943
+ try {
1944
+ var ret = JSON.parse(localStorage.getItem(key));
1945
+ return of(ret);
1946
+ }
1947
+ catch {
1948
+ return of(null);
1949
+ }
1950
+ }
1951
+ /** @ignore Implementazione di Default con localStorage. Identity viene ignorata perché essendo già nel localStorage è già per sito */
1952
+ removeItem(key) {
1953
+ try {
1954
+ localStorage.removeItem(key);
1955
+ return of(true);
1956
+ }
1957
+ catch {
1958
+ return of(false);
1959
+ }
1960
+ }
1961
+ /** @ignore Implementazione di Default con localStorage. Identity viene ignorata perché essendo già nel localStorage è già per sito */
1962
+ clear() {
1963
+ try {
1964
+ localStorage.clear();
1965
+ return of(true);
1966
+ }
1967
+ catch {
1968
+ return of(false);
1969
+ }
1970
+ }
1971
+ /** @ignore Implementazione di Default con localStorage. Identity viene ignorata perché essendo già nel localStorage è già per sito */
1972
+ getAll() {
1973
+ var ret = {};
1974
+ for (let key in localStorage) {
1975
+ ret[key] = localStorage[key];
1976
+ }
1977
+ return of(ret);
1978
+ }
1979
+ }
1980
+ DefaultStorageProvider.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DefaultStorageProvider, deps: [{ token: BaseSessionRetriever }], target: i0.ɵɵFactoryTarget.Injectable });
1981
+ DefaultStorageProvider.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DefaultStorageProvider });
1982
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: DefaultStorageProvider, decorators: [{
1983
+ type: Injectable
1984
+ }], ctorParameters: function () { return [{ type: BaseSessionRetriever }]; } });
1985
+
1986
+ // Angular
1987
+ /**
1988
+ * Modulo di estensione che registra autonomamente **TUTTI** i servizi di estensione:
1989
+ * ClipboardService,
1990
+ * DateService,
1991
+ * ExportService,
1992
+ * HashingService,
1993
+ * MessageService,
1994
+ * UtilityService,
1995
+ * StorageService,
1996
+ *
1997
+ * con eventuali provider che utilizzano
1998
+ */
1999
+ class FullExtensionsModule {
2000
+ static forRoot(config) {
2001
+ return {
2002
+ ngModule: FullExtensionsModule,
2003
+ providers: [
2004
+ ClipboardService,
2005
+ DateService,
2006
+ ExportService,
2007
+ HashingService,
2008
+ MessageService,
2009
+ UtilityService,
2010
+ StorageService,
2011
+ { provide: EXT_LOCALE, useValue: config?.locale || 'it-IT' },
2012
+ { provide: EXT_FANCY_ALERTS, useValue: config?.fancy_alerts || true },
2013
+ { provide: APPSEARCH_PREFIX, useValue: config?.appsearch_prefix || 'Hot' },
2014
+ { provide: EXT_ALLOW_UTC, useValue: config?.allow_utc == null ? false : config?.allow_utc },
2015
+ { provide: BaseSessionRetriever, useClass: config?.sessionRetriever || DefaultSessionRetriever },
2016
+ { provide: BaseStorageProvider, useClass: config?.storageProvider || DefaultStorageProvider },
2017
+ ]
2018
+ };
2019
+ }
2020
+ }
2021
+ FullExtensionsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: FullExtensionsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2022
+ FullExtensionsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: FullExtensionsModule });
2023
+ FullExtensionsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: FullExtensionsModule });
2024
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.1", ngImport: i0, type: FullExtensionsModule, decorators: [{
2025
+ type: NgModule
2026
+ }] });
2027
+
2028
+ /**
2029
+ * Classe che rappresenta una risposta ricevuta da un Backend
2030
+ */
2031
+ class CallResult {
2032
+ }
2033
+
2034
+ /**
2035
+ * Header per il file CSV che sta venendo generato
2036
+ */
2037
+ class CsvHeaders {
2038
+ }
2039
+
2040
+ /**
2041
+ * Rappresentazione di un oggetto generico
2042
+ */
2043
+ class GenericItem {
2044
+ }
2045
+
2046
+ /*
2047
+ * Public API Surface of extensions
2048
+ */
2049
+
2050
+ /**
2051
+ * Generated bundle index. Do not edit.
2052
+ */
2053
+
2054
+ export { APPSEARCH_PREFIX, BaseSessionRetriever, BaseStorageProvider, CallResult, ClipboardService, CsvHeaders, DateService, EXT_ALLOW_UTC, EXT_FANCY_ALERTS, EXT_LOCALE, Export, ExportAs, ExportDictionary, ExportList, ExportService, ExtensionsModule, FullExtensionsModule, GenericItem, HashingService, MessageService, StorageService, UtilityService };
2055
+ //# sourceMappingURL=esfaenza-extensions.mjs.map