@esfaenza/extensions 15.2.4 → 15.2.6

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.
@@ -1,13 +1,13 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, NgModule, Injector, Injectable, Inject, Optional } from '@angular/core';
2
+ import { InjectionToken, Injectable, Optional, Inject, Pipe, NgModule, Injector } from '@angular/core';
3
3
  import * as i1 from '@esfaenza/localizations';
4
- import { BaseLocalization } from '@esfaenza/localizations';
4
+ import { LocalizationModule } from '@esfaenza/localizations';
5
5
  import { __awaiter } from 'tslib';
6
- import swal from 'sweetalert2';
7
6
  import { first, map } from 'rxjs/operators';
7
+ import { Deserialize } from 'cerialize';
8
+ import swal from 'sweetalert2';
8
9
  import { ToastrService } from 'ngx-toastr';
9
10
  import { of, Subject } from 'rxjs';
10
- import { Deserialize } from 'cerialize';
11
11
 
12
12
  /**
13
13
  * Token che indica il prefisso delle searchView che serve per storicizzarle evitando di tirarsi in memoria anche tutti gli oggetti. Se vuoto viene supposto 'Hot'
@@ -16,1404 +16,1444 @@ const APPSEARCH_PREFIX = new InjectionToken('APPSEARCH_PREFIX');
16
16
  /**
17
17
  * Token che indica se i metodi di estensione che utilizzano le date permettono l'uso di date in utc
18
18
  */
19
- const EXT_ALLOW_UTC = new InjectionToken('EXT_ALLOW_UTC');
20
-
21
- // Angular
22
- /**
23
- * Modulo di estensione che non registra nessun servizio di estensione, dovranno essere dichiarati 1 per 1 dall'applicazione che li utilizza
24
- */
25
- class ExtensionsModule {
26
- static forRoot(config) {
27
- return {
28
- ngModule: ExtensionsModule,
29
- providers: [
30
- { provide: APPSEARCH_PREFIX, useValue: (config === null || config === void 0 ? void 0 : config.appsearch_prefix) || 'Hot' },
31
- { provide: EXT_ALLOW_UTC, useValue: (config === null || config === void 0 ? void 0 : config.allow_utc) == null ? false : config === null || config === void 0 ? void 0 : config.allow_utc }
32
- ]
33
- };
34
- }
35
- }
36
- ExtensionsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
37
- ExtensionsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule });
38
- ExtensionsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, providers: [BaseLocalization] });
39
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, decorators: [{
40
- type: NgModule,
41
- args: [{
42
- providers: [BaseLocalization]
43
- }]
44
- }] });
19
+ const EXT_ALLOW_UTC = new InjectionToken('EXT_ALLOW_UTC');
20
+ /** Modalità di Debug */
21
+ const EXT_DEBUG_MODE = new InjectionToken('EXT_DEBUG_MODE');
45
22
 
46
23
  /**
47
- * Service che fornisce funzionalità di alert nei tipi fondamentali: success, info, warning e danger
48
- */
49
- class MessageService {
24
+ * Service che fornisce dei metodi di estensione per la gestione/manipolazione delle date
25
+ */
26
+ class DateService {
50
27
  /**
51
28
  * Costruttore
52
29
  *
53
30
  * @ignore
54
31
  */
55
- constructor(injector, locProvider) {
56
- this.injector = injector;
32
+ constructor(locProvider, allowUtc) {
57
33
  this.locProvider = locProvider;
34
+ this.allowUtc = allowUtc;
58
35
  /**
59
- * Oggetto statico in supporto alla localizzazione
36
+ * Oggetto statico di localizzazione per i messaggi di questa Service
60
37
  */
61
38
  this.loc = {
62
- 'Confirm': { 'en-US': "Confirm", 'it-IT': "Conferma", },
63
- 'Cancel': { 'en-US': "Cancel", 'it-IT': "Annulla", },
64
- 'Close': { 'en-US': "Close", 'it-IT': "Chiudi", },
65
- 'Error': { 'en-US': "Error", 'it-IT': "Errore", },
66
- 'Info': { 'en-US': "Info", 'it-IT': "Informazione", },
67
- 'Success': { 'en-US': "Success", 'it-IT': "Successo", },
68
- 'Warning': { 'en-US': "Warning", 'it-IT': "Attenzione", }
39
+ "SMALL_DATE_FORMAT": { 'en-US': "MM/DD/YYYY", 'it-IT': "DD/MM/YYYY" },
40
+ "FULL_DATE_FORMAT": { 'en-US': "MM/DD/YYYY HH:mm:ss", 'it-IT': "DD/MM/YYYY HH:mm:ss" },
41
+ "FULL_DATE_FORMAT_NO_SS": { 'en-US': "MM/DD/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" },
42
+ "SMALL_DATE_DISPLAY_FORMAT": { 'en-US': "DD/MM/YYYY", 'it-IT': "DD/MM/YYYY" },
43
+ "SMALL_DATE_DISPLAY_FORMAT_WITH_HOUR": { 'en-US': "DD/MM/YYYY HH", 'it-IT': "DD/MM/YYYY HH" },
44
+ "SMALL_DATE_DISPLAY_FORMAT_WITH_MINUTE": { 'en-US': "DD/MM/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" },
45
+ "FULL_DATE_DISPLAY_FORMAT": { 'en-US': "DD/MM/YYYY HH:mm:ss", 'it-IT': "DD/MM/YYYY HH:mm:ss" },
46
+ "FULL_DATE_DISPLAY_FORMAT_NO_SS": { 'en-US': "DD/MM/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" }
47
+ };
48
+ /**
49
+ * Oggetto di configurazione per tenere da conto le informazioni sui formati
50
+ */
51
+ this.cfg = {
52
+ fulldate: "",
53
+ fulldateDisplay: "",
54
+ smallDate: "",
55
+ fulldateNoSS: "",
56
+ smallDateWithH: "",
57
+ smallDateWithM: "",
58
+ fulldateDisplayNoSS: ""
69
59
  };
70
60
  this.init();
71
61
  }
72
- get toastr() {
73
- return this.injector.get(ToastrService);
74
- }
75
62
  init() {
76
63
  return __awaiter(this, void 0, void 0, function* () {
77
64
  let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
78
- this.expiredSessionSwal = swal.mixin({
79
- showCancelButton: false,
80
- confirmButtonText: 'Login',
81
- customClass: {
82
- confirmButton: "btn btn-primary",
83
- container: "app-wrap",
84
- },
85
- buttonsStyling: false,
86
- reverseButtons: false,
87
- allowOutsideClick: false,
88
- icon: "warning"
89
- });
90
- this.successSwalWithCancel = swal.mixin({
91
- title: this.loc["Success"][LOCALE],
92
- customClass: {
93
- confirmButton: "btn btn-primary",
94
- cancelButton: "btn btn-secondary app-margin-right-10",
95
- container: "app-wrap",
96
- },
97
- buttonsStyling: false,
98
- reverseButtons: true,
99
- showCancelButton: true,
100
- confirmButtonText: this.loc["Confirm"][LOCALE],
101
- cancelButtonText: this.loc["Cancel"][LOCALE],
102
- icon: "success"
103
- });
104
- this.warningSwalWithCancel = swal.mixin({
105
- title: this.loc["Warning"][LOCALE],
106
- customClass: {
107
- confirmButton: "btn btn-primary",
108
- cancelButton: "btn btn-secondary app-margin-right-10",
109
- container: "app-wrap",
110
- },
111
- buttonsStyling: false,
112
- reverseButtons: true,
113
- showCancelButton: true,
114
- confirmButtonText: this.loc["Confirm"][LOCALE],
115
- cancelButtonText: this.loc["Cancel"][LOCALE],
116
- icon: "warning"
117
- });
118
- this.warningSwal = swal.mixin({
119
- title: this.loc["Warning"][LOCALE],
120
- customClass: {
121
- confirmButton: "btn btn-primary",
122
- container: "app-wrap",
123
- },
124
- buttonsStyling: false,
125
- reverseButtons: true,
126
- showCancelButton: false,
127
- confirmButtonText: this.loc["Close"][LOCALE],
128
- icon: "warning"
129
- });
130
- this.successSwal = swal.mixin({
131
- title: this.loc["Success"][LOCALE],
132
- customClass: {
133
- confirmButton: "btn btn-primary",
134
- container: "app-wrap",
135
- },
136
- buttonsStyling: false,
137
- reverseButtons: true,
138
- showCancelButton: false,
139
- confirmButtonText: this.loc["Close"][LOCALE],
140
- icon: "success"
141
- });
142
- this.errorSwal = swal.mixin({
143
- title: this.loc["Error"][LOCALE],
144
- customClass: {
145
- confirmButton: "btn btn-primary",
146
- container: "app-wrap",
147
- },
148
- buttonsStyling: false,
149
- reverseButtons: true,
150
- showCancelButton: false,
151
- confirmButtonText: this.loc["Close"][LOCALE],
152
- icon: "error"
153
- });
154
- this.infoSwal = swal.mixin({
155
- title: this.loc["Info"][LOCALE],
156
- customClass: {
157
- confirmButton: "btn btn-primary",
158
- container: "app-wrap",
159
- },
160
- buttonsStyling: false,
161
- reverseButtons: true,
162
- showCancelButton: false,
163
- confirmButtonText: this.loc["Close"][LOCALE],
164
- icon: "info"
165
- });
65
+ this.cfg.smallDate = this.loc["SMALL_DATE_FORMAT"][LOCALE];
66
+ this.cfg.fulldate = this.loc["FULL_DATE_FORMAT"][LOCALE];
67
+ this.cfg.fulldateNoSS = this.loc["FULL_DATE_FORMAT_NO_SS"][LOCALE];
68
+ this.cfg.fulldateDisplay = this.loc["FULL_DATE_DISPLAY_FORMAT"][LOCALE];
69
+ this.cfg.fulldateDisplayNoSS = this.loc["FULL_DATE_DISPLAY_FORMAT_NO_SS"][LOCALE];
70
+ this.cfg.smallDate = this.loc["SMALL_DATE_DISPLAY_FORMAT"][LOCALE];
71
+ this.cfg.smallDateWithH = this.loc["SMALL_DATE_DISPLAY_FORMAT_WITH_HOUR"][LOCALE];
72
+ this.cfg.smallDateWithM = this.loc["SMALL_DATE_DISPLAY_FORMAT_WITH_MINUTE"][LOCALE];
166
73
  });
167
74
  }
168
75
  /**
169
- * Presentazione di un semplice messaggio di successo
76
+ * Aggiusta una data in "istante finale" in base a qual è la parte di data significativa.
170
77
  *
171
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
172
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
78
+ * Es. Istante finale delle ore: 05/10/1992 --> 04/10/1992 24:00(:00)
173
79
  *
174
- * @param {string} text Testo da mostrare
175
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
80
+ * @param {any} date Data qualsiasi (Date, stringa, dayjs...), verrà ricondotta ad un oggetto dayJs
81
+ * @param {'day' | 'hour' | 'minute'} timepart Parte significativa della data
82
+ * @param {boolean} printSeconds Indica se effettuare la stampa dei secondi o no
176
83
  */
177
- simpleSuccess(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
178
- let tos = this.toastrOrSwal(secondaryNotificationType);
179
- if (tos == "swal")
180
- this.successSwal.fire("", text);
181
- else
182
- this.toastr.success(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
84
+ adjustDateToFinalInstant(date, timepart, printSeconds = true) {
85
+ let mydt = this.getDateConvertion(date);
86
+ if (mydt == null)
87
+ return "FE: Not a Date";
88
+ let isZeroTime = mydt.startOf(timepart).valueOf() === mydt.valueOf();
89
+ if (!isZeroTime) {
90
+ if (timepart == "day" && mydt.subtract(1, "hour").hour() == mydt.hour()) {
91
+ // Se l'ora precedente è lo stesso orario dell'ora attuale l'istante finale dev'essere mandato avanti di 1
92
+ mydt = mydt.add(1, "hour");
93
+ }
94
+ return printSeconds ? mydt.format(this.cfg.fulldateDisplay) : mydt.format(this.cfg.fulldateDisplayNoSS);
95
+ }
96
+ let tmpValue = mydt.subtract(1, timepart);
97
+ let value = "";
98
+ // Istante finale delle ore: 05/10/1992 --> 04/10/1992 24:00(:00)
99
+ if (timepart == 'day')
100
+ value = tmpValue.format(this.cfg.smallDate) + " 24:00" + (printSeconds ? ':00' : '');
101
+ // Istante finale dei minuti: giorno 05/10/1992 04:00:00 --> 05/10/1992 03:60(:00)
102
+ else if (timepart == 'hour')
103
+ value = tmpValue.format(this.cfg.smallDateWithH) + ":60" + (printSeconds ? ':00' : '');
104
+ // Istante finale dei secondi: giorno 05/10/1992 04:10:00 --> 05/10/1992 04:09:60
105
+ else if (timepart == 'minute')
106
+ value = tmpValue.format(this.cfg.smallDateWithM) + ":60";
107
+ return value;
183
108
  }
184
109
  /**
185
- * Presentazione di un semplice messaggio di informazione
110
+ * Funzione che effettua l'ordinamento fra 2 date in base alla direzione specificata
186
111
  *
187
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
188
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
112
+ * @param {any} a Prima data per il confronto
113
+ * @param {any} b Seconda data per il confronto
114
+ * @param {'asc' | 'desc'} direction Direzione rispetto a cui ordinare le due date
189
115
  *
190
- * @param {string} text Testo da mostrare
191
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
116
+ * @returns {number} 0 se le date sono uguali, 1 se la data A deve venire logicamente prima della data B, -1 altrimenti
192
117
  */
193
- simpleInfo(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
194
- let tos = this.toastrOrSwal(secondaryNotificationType);
195
- if (tos == "swal")
196
- this.infoSwal.fire("", text);
197
- else
198
- this.toastr.info(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
118
+ dateSort(a, b, direction) {
119
+ if (a < b)
120
+ return direction == 'asc' ? 1 : -1;
121
+ else if (a > b)
122
+ return direction == 'asc' ? -1 : 1;
123
+ // con a uguale a b
124
+ return 0;
199
125
  }
200
126
  /**
201
- * Presentazione di un semplice messaggio di errore
127
+ * Effettua il trim dei secondi da una data espressa come stringa
202
128
  *
203
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
204
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
129
+ * @param {string} value Data espressa come stringa
205
130
  *
206
- * @param {string} text Testo da mostrare
207
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
131
+ * @returns {string} Data senza i secondi
208
132
  */
209
- simpleError(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
210
- let tos = this.toastrOrSwal(secondaryNotificationType);
211
- if (tos == "swal")
212
- this.errorSwal.fire("", text);
213
- else
214
- this.toastr.error(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
133
+ trimSeconds(value) {
134
+ //I numeri mangiati da dayjs spesso vengono ricondotti a date vere. Mi assicuro che se ci sono solo numeri proseguo
135
+ if (!isNaN(value))
136
+ return value;
137
+ //Se non ho qualcosa del tipo XX/YY/ZZZZ aa:bb:cc di sicuro non è una data che mi interessa
138
+ if (!/^\d\d\/\d\d\/\d\d\d\d \d\d:\d\d:\d\d$/g.test(value))
139
+ return value;
140
+ //In questo caso mi arrivano valori che devono essere stampati as-is, solo tagliando i secondi
141
+ return "'" + value.substr(0, value.length - 3);
215
142
  }
216
143
  /**
217
- * Presentazione di un semplice messaggio di avviso
144
+ * Data una lista di date Da e una lista di date A restituisce un oggetto rappresentante il range che include tutte le date passate
218
145
  *
219
- * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
220
- * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
146
+ * @param {any[]} fromDates Lista dei Da
147
+ * @param {any[]} toDates Lista dei A
221
148
  *
222
- * @param {string} text Testo da mostrare
223
- * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
224
- */
225
- simpleWarning(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
226
- let tos = this.toastrOrSwal(secondaryNotificationType);
227
- if (tos == "swal")
228
- this.warningSwal.fire("", text);
229
- else
230
- this.toastr.warning(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
231
- }
232
- /**
233
- * Ripulisce tutti i messaggi presenti in un dato momento sullo schermo
234
- */
235
- clearMessages() {
236
- this.toastr.clear();
237
- swal.close();
238
- }
239
- /**
240
- * Mostra un messaggio di avviso con richiesta di conferma
241
- *
242
- * @param {string} title Titolo del messaggio
243
- * @param {string} text Contenuto del messaggio
244
- *
245
- * @returns {Promise} Restituisce una Promise col risultato scelto dall'utente (conferma o no)
246
- */
247
- promiseWarningWithChoice(title, text) {
248
- return this.warningSwalWithCancel.fire(title, text);
249
- }
250
- /**
251
- * In base alla configurazione attuale e all'eventuale override per la chiamata del caso indica se bisogna utilizzare toastr o sweetalert
252
- *
253
- * @param {"toastr" | "swal" | null} providerOverride Override alla modalità configurata
254
- *
255
- * @returns {"toastr" | "swal"} Indicazione su che provider di messaggi di avviso debba essere utilizzato
149
+ * @returns {{ from: any, to: any }} Range di date Da - A che include tutti i valori di **fromDates** e **toDates**
256
150
  */
257
- toastrOrSwal(providerOverride) {
258
- if (providerOverride != null)
259
- return providerOverride;
260
- return "swal";
151
+ getMinMaxDatesRange(fromDates, toDates) {
152
+ let datesFroms = [];
153
+ let datesTo = [];
154
+ for (let i = 0; i < fromDates.length; i++) {
155
+ let d = fromDates[i];
156
+ var convertion = this.getDateConvertion(d);
157
+ if (convertion)
158
+ datesFroms.push(convertion);
159
+ }
160
+ for (let i = 0; i < toDates.length; i++) {
161
+ let d = toDates[i];
162
+ var convertion = this.getDateConvertion(d);
163
+ if (convertion)
164
+ datesTo.push(convertion);
165
+ }
166
+ return { from: dayjs.min(datesFroms), to: dayjs.max(datesTo) };
261
167
  }
262
168
  /**
263
- * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
169
+ * Ottiene la conversione di una data in qualsiasi formato al formato standard DayJs
264
170
  *
265
- * @param {string} title Titolo del messaggio
266
- * @param {string} text Contenuto del messaggio
267
- * @param {Function} onsuccess Callback da chimare su conferma
268
- * @param {Function} onerror Callback da chimare su errori
269
- */
270
- simpleWarningWithChoice(title, text, onsuccess = null, onerror = null) {
271
- this.warningSwalWithCancel.fire(title, text).then((result) => {
272
- if (result.value && onsuccess)
273
- onsuccess();
274
- else if (onerror)
275
- onerror();
276
- });
277
- }
278
- /**
279
- * Mostra un messaggio di success con richiesta di conferma e gestisce il risultato chiamato i callback **onconfirm** o **onabort**
171
+ * @param {any} date Oggetto rappresentante una data. Potrebbe essere una stringa, un Date o già un DayJs
172
+ * @param {boolean} useUtc Indica se usare l'estensione utc di Dayjs per parsare la data o no
280
173
  *
281
- * @param {string} title Titolo del messaggio
282
- * @param {string} text Contenuto del messaggio
283
- * @param {Function} onconfirm Callback da chimare su conferma
284
- * @param {Function} onabort Callback da chimare su annullamento
285
- * @param {string} confirmtext Testo del pulsante di azione
286
- * @param {string} aborttext Testo del pulsante di annullamento
174
+ * @returns {any} Data in modalità DayJs
287
175
  */
288
- simpleSuccessWithChoice(title, text, onconfirm = null, onabort = null, confirmtext = "", aborttext = '') {
289
- var configuration = {
290
- title: title,
291
- html: text
292
- };
293
- if (confirmtext)
294
- configuration["confirmButtonText"] = confirmtext;
295
- if (aborttext)
296
- configuration["cancelButtonText"] = aborttext;
297
- this.successSwalWithCancel.fire(configuration).then((result) => {
298
- if (result.value && onconfirm)
299
- onconfirm();
300
- else if (onabort)
301
- onabort();
302
- });
176
+ getDateConvertion(date, useUtc = false) {
177
+ if (!date)
178
+ return null;
179
+ if (this.isDayJs(date))
180
+ return date;
181
+ if (this.isJsDate(date))
182
+ return useUtc ? dayjs.utc(date) : dayjs(date);
183
+ // Se non c'è la proprietà length vuol dire che non è una stringa e a questo punto non ho idea di che minchia sia
184
+ let length = date.length;
185
+ if (!length)
186
+ return null;
187
+ if (useUtc && !this.allowUtc)
188
+ throw "@esfaenza/extensions: Richiesta data UTC ma da configurazione la libreria non lo supporta";
189
+ // Per risparmiare chiamate a tentoni, in base alla lunghezza della stringa chiamo direttamente il metodo giusto,
190
+ // controllando poi che mi generi una data come me la aspetto io
191
+ let tryThis = null;
192
+ let toCall = useUtc ? dayjs.utc : dayjs;
193
+ // 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.
194
+ // Per il resto mi baso sulla lunghezza della stringa
195
+ if (date.includes("T"))
196
+ tryThis = toCall(date);
197
+ else if (length == this.cfg.fulldate.length)
198
+ tryThis = toCall(date, this.cfg.fulldate);
199
+ else if (length == this.cfg.smallDate.length)
200
+ tryThis = toCall(date, this.cfg.smallDate);
201
+ else if (length == this.cfg.fulldateNoSS.length)
202
+ tryThis = toCall(date, this.cfg.fulldateNoSS);
203
+ if (tryThis && tryThis.isValid && tryThis.isValid())
204
+ return tryThis;
205
+ // Se niente funziona, null.
206
+ // Ricondurre l'Input ad una data non è possibile.
207
+ return null;
303
208
  }
304
209
  /**
305
- * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
210
+ * Helper che restituisce **true** qualora l'oggetto passato fosse una data vera e propria, **false** altrimenti
306
211
  *
307
- * @param {string} title Titolo del messaggio
308
- * @param {string} text Contenuto del messaggio
309
- */
310
- observableSimpleWarningWithChoice(title, text) {
311
- return of(this.warningSwalWithCancel.fire(title, text)).pipe(map(t => !!t.value));
312
- }
313
- /**
314
- * Mostra un messaggio di avviso che la sessione corrente è scaduta e propone all'utente di navigare al login. Qualora l'utente decidesse di farlo
315
- * verrà chiamata la funzione di callback **onnavigate
212
+ * @param {any} check Oggetto da controllare
316
213
  *
317
- * @param {string} title Titolo del messaggio
318
- * @param {string} text Contenuto del messaggio
319
- * @param {Function} onnavigate Callback da chimare su navigazione in corso
214
+ * @returns {boolean} Indicazione se l'oggetto è un vero Date di Javascript o no
320
215
  */
321
- expiredSessionMessage(title, text, onnavigate = null) {
322
- this.expiredSessionSwal.fire(title, text).then((result) => {
323
- if (result.value && onnavigate)
324
- onnavigate();
325
- });
216
+ isJsDate(check) {
217
+ return check && Object.prototype.toString.call(check) === "[object Date]" && !isNaN(check);
326
218
  }
327
219
  /**
328
- * Metodo helper per gestire in maniera standardizzata una risposta di tipo **CallResult**
220
+ * Helper che restituisce **true** qualora l'oggetto passato fosse un DayJs vero e proprio, **false** altrimenti
329
221
  *
330
- * @param {CallResult} 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
222
+ * @param {any} check Oggetto da controllare
223
+ * @returns {boolean} Indicazione se l'oggetto è un vero DayJs o no
335
224
  */
336
- manageCallResultResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
337
- if (response.success) {
338
- if (response.haswarning)
339
- this.simpleWarning(response.warning);
340
- else if (successMsg)
341
- this.simpleSuccess(successMsg);
342
- if (postSuccess)
343
- postSuccess();
344
- }
345
- else {
346
- this.simpleError((errorMsg ? errorMsg + ": " : "") + response.haserror ? response.error : '[NO ERR.]');
347
- if (postFailure)
348
- postFailure();
349
- }
225
+ isDayJs(check) {
226
+ // Non uso instanceof perché sarebbe estremamente più lento
227
+ // Non uso nemmeno isDayjs() della libreria Dayjs dato che ha lo stesso problema: https://github.com/iamkun/dayjs/blob/06f88f425828b1ce96b737332d25145a95a4ee9d/src/index.js#L9
228
+ return check.$D !== undefined && check.$M !== undefined && check.$y !== undefined;
350
229
  }
351
230
  /**
352
- * Metodo helper per gestire in maniera standardizzata una risposta di tipo **string**, considerando che:
353
- *
354
- * Stringa vuota --> Tutto bene
355
- *
356
- * Stringa piena --> Questo è il messaggio d'errore per cui la chiamata è fallita
231
+ * Ottiene la formattazione di una data in base alla versione richiesta "small" o "long" e a se stampare o meno i secondi
357
232
  *
358
- * @param {string} response Risposta ricevuta dal server
359
- * @param {string} successMsg Messaggio da visualizzare in caso di successo
360
- * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
361
- * @param {Function} postSuccess Callback da chimare in caso di successo
362
- * @param {Function} postFailure Callback da chimare in caso di fallimento
363
- */
364
- manageStringResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
365
- if (!response) {
366
- if (successMsg)
367
- this.simpleSuccess(successMsg);
368
- if (postSuccess)
369
- postSuccess();
370
- }
371
- else {
372
- if (errorMsg)
373
- this.simpleError(errorMsg + ": " + response);
374
- if (postFailure)
375
- postFailure();
376
- }
377
- }
378
- /**
379
- * Metodo helper per gestire in maniera standardizzata una risposta di tipo **boolean**
233
+ * @param {any} date Oggetto rappresentante una data. Potrebbe essere una stringa, un Date o già un DayJs
234
+ * @param {boolean} small Indica se formattarla con un formato breve (se **true**) o un formato più lungo (se **false**)
380
235
  *
381
- * @param {string} response Risposta ricevuta dal server
382
- * @param {string} successMsg Messaggio da visualizzare in caso di successo
383
- * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
384
- * @param {Function} postSuccess Callback da chimare in caso di successo
385
- * @param {Function} postFailure Callback da chimare in caso di fallimento
236
+ * @returns {string} Data formattata nel formato richiesto
386
237
  */
387
- manageStringResponseBool(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
388
- if (response) {
389
- if (successMsg)
390
- this.simpleSuccess(successMsg);
391
- if (postSuccess)
392
- postSuccess();
393
- }
394
- else {
395
- if (errorMsg)
396
- this.simpleError(errorMsg);
397
- if (postFailure)
398
- postFailure();
399
- }
238
+ getFormatted(date, small, seconds) {
239
+ var date = this.getDateConvertion(date);
240
+ if (!date)
241
+ return null;
242
+ return date.format(small ? this.cfg.smallDate : seconds ? this.cfg.fulldateDisplay : this.cfg.fulldateDisplayNoSS);
400
243
  }
401
244
  }
402
- MessageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, deps: [{ token: Injector }, { token: i1.BaseLocalization, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
403
- MessageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService });
404
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, decorators: [{
405
- type: Injectable
245
+ DateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DateService, deps: [{ token: i1.BaseLocalization, optional: true }, { token: EXT_ALLOW_UTC, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
246
+ DateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DateService, providedIn: "root" });
247
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DateService, decorators: [{
248
+ type: Injectable,
249
+ args: [{ providedIn: "root" }]
406
250
  }], ctorParameters: function () {
407
- return [{ type: i0.Injector, decorators: [{
408
- type: Inject,
409
- args: [Injector]
410
- }] }, { type: i1.BaseLocalization, decorators: [{
251
+ return [{ type: i1.BaseLocalization, decorators: [{
252
+ type: Optional
253
+ }] }, { type: undefined, decorators: [{
411
254
  type: Optional
255
+ }, {
256
+ type: Inject,
257
+ args: [EXT_ALLOW_UTC]
412
258
  }] }];
413
259
  } });
414
260
 
261
+ // Angular
415
262
  /**
416
- * Service che fornisce un accesso base in lettura/scrittura sulla clipboard
263
+ * Pipe che permette di formattare una data in base al formato specificato. Utilizza il **DateService** di **@esfaenza/extensions** per ricondurre l'input a una data valida
417
264
  */
418
- class ClipboardService {
265
+ class LocDatePipe {
419
266
  /**
420
- * Costruttore
421
- *
422
267
  * @ignore
423
268
  */
424
- constructor(msgService, locProvider) {
425
- this.msgService = msgService;
426
- this.locProvider = locProvider;
427
- /**
428
- * Oggetto statico di localizzazione per i messaggi di questa Service
429
- */
430
- this.loc = {
431
- "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation": {
432
- 'en-US': "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation",
433
- 'it-IT': "Mi dispiace ma Firefox non supporta l'accesso diretto alla Clipboard, se non attraverso le estensioni. Si prega di usare Chrome"
434
- },
435
- "Generic error during 'copy' command execution": {
436
- 'en-US': "Generic error during 'copy' command execution",
437
- 'it-IT': "Errore generico durante l'esecuzione del comando 'copy'"
438
- },
439
- "Error during Clipboard content read operation": {
440
- 'en-US': "Error during Clipboard content read operation",
441
- 'it-IT': "Errore nella lettura del contenuto della Clipboard"
442
- },
443
- "Error during Clipboard content copy operation": {
444
- 'en-US': "Error during Clipboard content copy operation",
445
- 'it-IT': "Errore nella scrittura del contenuto nella Clipboard"
446
- },
447
- "Please insert your clipboard content": {
448
- 'en-US': "Please insert your clipboard content",
449
- 'it-IT': "Si prega di incollare il contenuto della Clipboard"
450
- },
451
- "User input required": {
452
- 'en-US': "User input required",
453
- 'it-IT': "Richiesto Input utente"
454
- },
455
- "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation": {
456
- 'en-US': "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation",
457
- 'it-IT': "Il browser corrente non supporta la lettura diretta dei dati della Clipboard, si prega di effettuare un'incolla (CTRL + V) nella casella di testo e confermare l'operazione"
458
- },
459
- "Confirm": {
460
- 'en-US': "Confirm",
461
- 'it-IT': "Conferma"
462
- },
463
- "Cancel": {
464
- 'en-US': "Cancel",
465
- 'it-IT': "Annulla"
466
- },
467
- };
468
- }
469
- /**
470
- * Prende il valore della clipboard.
471
- * Si può specificare se ci si aspetta una lista o una matrice di valori in modo da ricevere già un risultato utilizzabile
472
- *
473
- * @param {'array' | 'matrix'} style Stile dell'output desiderato, se array o matrice
474
- * @param {Function} valueFoundCallback Callback che questa funzione chiamerà una volta ottenuto i valori richiesti dalla clipboard
475
- */
476
- getClipboard(style, valueFoundCallback) {
477
- return __awaiter(this, void 0, void 0, function* () {
478
- let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
479
- if (navigator.userAgent.indexOf("Firefox") != -1) {
480
- swal.fire({
481
- title: this.loc["User input required"][LOCALE],
482
- text: this.loc["Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation"][LOCALE],
483
- input: 'textarea',
484
- icon: "warning",
485
- confirmButtonText: this.loc["Confirm"][LOCALE],
486
- cancelButtonText: this.loc["Cancel"][LOCALE],
487
- showCancelButton: true,
488
- customClass: {
489
- confirmButton: "btn btn-primary",
490
- cancelButton: "btn btn-secondary app-margin-right-15",
491
- container: "app-wrap",
492
- },
493
- reverseButtons: true,
494
- allowOutsideClick: false,
495
- inputValidator: (value) => {
496
- if (!value)
497
- return this.loc["Please insert your clipboard content"][LOCALE];
498
- }
499
- }).then(t => {
500
- if (t.isConfirmed) {
501
- console.log("[@esfaenza/extensions] Retrieving input data from user input");
502
- this.doClipboardDataGet(t.value, style, valueFoundCallback);
503
- }
504
- });
505
- return;
506
- }
507
- if (window.clipboardData) {
508
- console.log("[@esfaenza/extensions] Found clipboardData");
509
- let data = window.clipboardData.getData("Text");
510
- this.doClipboardDataGet(data, style, valueFoundCallback);
511
- }
512
- else if (window.navigator.clipboard) {
513
- console.log("[@esfaenza/extensions] Found navigator clipboard");
514
- window.navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
515
- if (!(result.state === 'granted' || result.state === 'prompt')) {
516
- console.error("[@esfaenza/extensions] Clipboard permission not granted");
517
- if (valueFoundCallback)
518
- valueFoundCallback([]);
519
- return;
520
- }
521
- console.log("[@esfaenza/extensions] Clipboard permission granted, retrieving values");
522
- window.navigator.clipboard.readText()
523
- .then((t) => this.doClipboardDataGet(t, style, valueFoundCallback))
524
- .catch((err) => this.msgService.simpleError(this.loc["Error during Clipboard content read operation"][LOCALE] + ": " + err));
525
- });
526
- }
527
- });
528
- }
529
- /** @ignore */
530
- doClipboardDataGet(clipboardText, style, valueFoundCallback) {
531
- console.log("[@esfaenza/extensions] Retrieved clipboard values: " + clipboardText);
532
- let value = style == "array" ? this.getClipboardLines(clipboardText) :
533
- style == "matrix" ? this.getClipboardMatrix(clipboardText) : [];
534
- console.log(`[@esfaenza/extensions] Adapted for ${style}: ${JSON.stringify(value)}`);
535
- if (valueFoundCallback)
536
- valueFoundCallback(value);
537
- }
538
- /**
539
- * Ottiene il contenuto della clipboard diviso per righe (separate da newline)
540
- *
541
- * @param {string} data contenuto letto dalla clipboard
542
- *
543
- * @returns {string[]} Array contenente il testo preso dalla clipboard diviso per riga
544
- */
545
- getClipboardLines(data) {
546
- let trimmedData = data.trim();
547
- if (!trimmedData.includes("\r\n") && trimmedData.includes("\n"))
548
- return trimmedData.split("\n");
549
- return trimmedData.split("\r\n");
269
+ constructor(dts) {
270
+ this.dts = dts;
550
271
  }
551
272
  /**
552
- * Ottiene il contenuto della clipboard diviso per righe (separate da newline) e colonne (separate da tab)
273
+ * Trasformazione della data in input in base al formato richiesto
553
274
  *
554
- * @param {string} data contenuto letto dalla clipboard
275
+ * @param {any} value Valore da ricondurre ad una data e formattare
276
+ * @param {string} format Formato in output della data da visualizzare
555
277
  *
556
- * @returns {string[][]} Matrice contenente il testo preso dalla clipboard diviso per riga e colonna
278
+ * @returns {string} Data formattata in base al formato
557
279
  */
558
- getClipboardMatrix(data) {
559
- var ret = [];
560
- var rows = !data.includes("\r\n") && data.includes("\n") ? data.split("\n") : data.split("\r\n");
561
- // A quanto pare ogni valore è separato da un \t... spero che sia uno standard di quando si copia da excel altrimenti ciao
562
- for (let i = 0; i < rows.length; i++)
563
- ret.push(rows[i].split('\t').map(t => t.trim()));
564
- return ret;
280
+ transform(value, format = "DD/MM/YYYY") {
281
+ if (value == null || value === "")
282
+ return null;
283
+ var detatchedValue = JSON.parse(JSON.stringify(value));
284
+ var dt = this.dts.getDateConvertion(detatchedValue);
285
+ return dt.format(format);
565
286
  }
566
- /**
567
- * Metodo che copia un testo all'interno della clipboard
568
- *
569
- * @param {string} text Testo da inserire nella clipboard
570
- */
571
- copyTextToClipboard(text) {
572
- return __awaiter(this, void 0, void 0, function* () {
573
- let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
574
- var textArea = document.createElement("textarea");
575
- //
576
- // *** This styling is an extra step which is likely not required. ***
577
- //
578
- // Why is it here? To ensure:
579
- // 1. the element is able to have focus and selection.
580
- // 2. if element was to flash render it has minimal visual impact.
581
- // 3. less flakyness with selection and copying which **might** occur if
582
- // the textarea element is not visible.
583
- //
584
- // The likelihood is the element won't even render, not even a flash,
585
- // so some of these are just precautions. However in IE the element
586
- // is visible whilst the popup box asking the user for permission for
587
- // the web page to copy to the clipboard.
588
- //
589
- // Place in top-left corner of screen regardless of scroll position.
590
- textArea.style.position = "fixed";
591
- textArea.style.top = "0";
592
- textArea.style.left = "0";
593
- // Ensure it has a small width and height. Setting to 1px / 1em
594
- // doesn't work as this gives a negative w/h on some browsers.
595
- textArea.style.width = "2em";
596
- textArea.style.height = "2em";
597
- // We don't need padding, reducing the size if it does flash render.
598
- textArea.style.padding = "0";
599
- // Clean up any borders.
600
- textArea.style.border = "none";
601
- textArea.style.outline = "none";
602
- textArea.style.boxShadow = "none";
603
- // Avoid flash of white box if rendered for any reason.
604
- textArea.style.background = "transparent";
605
- textArea.value = text;
606
- document.body.appendChild(textArea);
607
- textArea.focus();
608
- textArea.select();
609
- try {
610
- var successful = document.execCommand("copy");
611
- if (!successful)
612
- this.msgService.simpleError(this.loc["Generic error during 'copy' command execution"][LOCALE]);
613
- }
614
- catch (err) {
615
- this.msgService.simpleError(this.loc["Error during Clipboard content copy operation"][LOCALE] + ": " + err);
616
- }
617
- document.body.removeChild(textArea);
618
- });
287
+ }
288
+ LocDatePipe.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: LocDatePipe, deps: [{ token: DateService }], target: i0.ɵɵFactoryTarget.Pipe });
289
+ LocDatePipe.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: LocDatePipe, name: "loc_date" });
290
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: LocDatePipe, decorators: [{
291
+ type: Pipe,
292
+ args: [{ name: "loc_date", pure: true }]
293
+ }], ctorParameters: function () { return [{ type: DateService }]; } });
294
+
295
+ // Angular
296
+ class ExtensionsModule {
297
+ static forRoot(config) {
298
+ return {
299
+ ngModule: ExtensionsModule,
300
+ providers: [
301
+ { provide: APPSEARCH_PREFIX, useValue: (config === null || config === void 0 ? void 0 : config.appsearch_prefix) || 'Hot' },
302
+ { provide: EXT_ALLOW_UTC, useValue: (config === null || config === void 0 ? void 0 : config.allow_utc) == null ? false : config === null || config === void 0 ? void 0 : config.allow_utc },
303
+ { provide: EXT_DEBUG_MODE, useValue: (config === null || config === void 0 ? void 0 : config.debugMode) || false },
304
+ ]
305
+ };
619
306
  }
620
307
  }
621
- ClipboardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, deps: [{ token: MessageService }, { token: i1.BaseLocalization, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
622
- ClipboardServiceprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService });
623
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, decorators: [{
624
- type: Injectable
625
- }], ctorParameters: function () {
626
- return [{ type: MessageService }, { type: i1.BaseLocalization, decorators: [{
627
- type: Optional
628
- }] }];
629
- } });
308
+ ExtensionsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
309
+ ExtensionsModulemod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, declarations: [LocDatePipe], imports: [LocalizationModule], exports: [LocDatePipe] });
310
+ ExtensionsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, imports: [LocalizationModule] });
311
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExtensionsModule, decorators: [{
312
+ type: NgModule,
313
+ args: [{
314
+ imports: [LocalizationModule],
315
+ declarations: [LocDatePipe],
316
+ exports: [LocDatePipe]
317
+ }]
318
+ }] });
630
319
 
631
320
  /**
632
- * Service che fornisce dei metodi di estensione per la gestione/manipolazione delle date
321
+ * Suffisso della proprietà da generare in cui salvare il navigatore
322
+ * utilizzato dal servizio di esportazione per prendere il valore delle proprietà di un oggetto
323
+ */
324
+ const csvValueNavigator = "_csvnav";
325
+ /**
326
+ * Suffisso della proprietà da generare in cui salvare l'ordine di esportazione
327
+ */
328
+ const csvOrdPrefix = "_csvord";
329
+ /**
330
+ * Suffisso della proprietà da generare in cui salvare la visibilità di questa proprietà
331
+ */
332
+ const csvVisPrefix = "_csvvis";
333
+ /**
334
+ * Suffisso della proprietà da generare in cui salvare il nome della colonna in cui salvare questa proprietà
335
+ */
336
+ const csvHdrPrefix = "_csvhdr";
337
+ /**
338
+ * Suffisso della proprietà da generare in cui salvare il codice del th a cui si riferisce questo campo
339
+ */
340
+ const csvPropKey = "_csvkey";
341
+ /**
342
+ * Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Lista
343
+ */
344
+ const listCsvValPrefix = "_listcsvval";
345
+ /**
346
+ * Suffisso della proprietà da generare in cui salvare l'Header della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix**
347
+ */
348
+ const listCsvHdrPrefix = "_listcsvhdr";
349
+ /**
350
+ * Suffisso della proprietà da generare in cui salvare il formato della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix**
351
+ */
352
+ const listCsvValFormat = "_listcsvvalformat";
353
+ /**
354
+ * Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Dizionario
355
+ */
356
+ const dictionaryCsvValPrefix = "_flatlistcsvval";
357
+ /**
358
+ * Suffisso della proprietà da generare in cui salvare l'Header della proprietà di un Dizionario relativo al valore esportato nella proprietà con suffisso **dictionaryCsvValPrefix**
359
+ */
360
+ const dictionaryCsvHdrPrefix = "_flatlistcsvhdr";
361
+ /**
362
+ * Suffisso della proprietà da generare in cui salvare il formato della proprietà che si sta esportando
363
+ */
364
+ const csvFormatPrefix = "_csvfmt";
365
+ /**
366
+ * Nome della proprietà che contiene tutti i nomi di tutte le proprietà da esportare
633
367
  */
634
- class DateService {
368
+ const exportList = "__export_list__";
369
+
370
+ // Angular
371
+ /**
372
+ * Decoratore di esportazione utilizzabile su una proprietà singola.
373
+ * Verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
374
+ *
375
+ * Ad esempio, da questa configurazione:
376
+ *
377
+ * @example
378
+ * ```
379
+ * @Export(true, "MyHeader")
380
+ * ciao: string;
381
+ * ```
382
+ *
383
+ * Nasceranno le seguenti proprietà nell'oggetto esportabile:
384
+ *
385
+ * @example
386
+ * ```
387
+ * ciao_csvvis: string; => true
388
+ * ciao: string;
389
+ * ciao_csvhdr: string => "MyHeader"
390
+ * ```
391
+ *
392
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
393
+ * @param {string} header Titolo della colonna nel file CSV esportato
394
+ * @param {string} format Formato di esportazione. Può essere un formato data per i campi data o 'F' per i campi floating point
395
+ */
396
+ const Export = (order, header, format = null, tableid = null) => (target, propertyKey) => {
397
+ if (format)
398
+ Object.defineProperty(target, propertyKey + csvFormatPrefix, { value: format, writable: false });
399
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
400
+ Object.defineProperty(target, propertyKey + csvVisPrefix, { value: !!header, writable: false });
401
+ Object.defineProperty(target, propertyKey + csvHdrPrefix, { value: header, writable: false });
402
+ if (tableid)
403
+ Object.defineProperty(target, propertyKey + csvPropKey, { value: tableid, writable: false });
404
+ if (target[exportList])
405
+ target[exportList].push(propertyKey + csvVisPrefix);
406
+ else
407
+ target[exportList] = [propertyKey + csvVisPrefix];
408
+ };
409
+ /**
410
+ * Decoratore di esportazione utilizzabile su un oggetto.
411
+ * Per ogni proprietà dell'oggetto verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
412
+ * Per essere esportate, le proprietà dell'oggetto devono essere marcate con i Decoratori di esportazione
413
+ *
414
+ * Ad esempio, da questa configurazione:
415
+ *
416
+ * @example
417
+ * ```
418
+ * MyObj {
419
+ * @Export(true, "MyHeader")
420
+ * ciao: string;
421
+ * }
422
+ *
423
+ * @ExportObject(true, "MyHeader")
424
+ * test: MyObj;
425
+ * ```
426
+ *
427
+ * Nasceranno le seguenti proprietà nell'oggetto esportabile:
428
+ *
429
+ * @example
430
+ * ```
431
+ * testciao: string; => Valore di MyObj.ciao
432
+ * testciao_csvvis: string; => true
433
+ * testciao_csvhdr: string => "MyHeader"
434
+ * ```
435
+ *
436
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
437
+ * @param {any} type Tipo da esportare
438
+ */
439
+ const ExportAs = (order, type, prefix) => (target, propertyKey) => {
440
+ var t = new type();
441
+ var props = t[exportList];
442
+ for (let i = 0; i < props.length; i++) {
443
+ let prop = props[i].replace(csvVisPrefix, '');
444
+ if (typeof t[prop + csvVisPrefix] !== "undefined") {
445
+ var toEmit = t[prop + csvVisPrefix];
446
+ var lbl = t[prop + csvHdrPrefix];
447
+ var format = t[prop + csvFormatPrefix];
448
+ var orderProp = t[prop + csvOrdPrefix];
449
+ if (format)
450
+ Object.defineProperty(target, propertyKey + prop + csvFormatPrefix, { value: format, writable: false });
451
+ Object.defineProperty(target, propertyKey + prop + csvOrdPrefix, { value: orderProp + order, writable: false });
452
+ Object.defineProperty(target, propertyKey + prop, { value: null, writable: true, enumerable: true });
453
+ Object.defineProperty(target, propertyKey + prop + csvValueNavigator, { value: propertyKey + "." + prop, writable: false });
454
+ Object.defineProperty(target, propertyKey + prop + csvVisPrefix, { value: toEmit, writable: false });
455
+ Object.defineProperty(target, propertyKey + prop + csvHdrPrefix, { value: (prefix ? prefix + ' ' : '') + lbl, writable: false });
456
+ if (target[exportList])
457
+ target[exportList].push(propertyKey + prop + csvVisPrefix);
458
+ else
459
+ target[exportList] = [propertyKey + prop + csvVisPrefix];
460
+ }
461
+ }
462
+ };
463
+ /**
464
+ * Decoratore di esportazione utilizzabile su una lista,
465
+ * si utilizzano 2 navigator rispettivamente per la valorizzazione dell'Header e del Valore e
466
+ * per ogni elemento dell'array verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr)
467
+ *
468
+ * ATTENZIONE: Gli oggetti esportati in questa modalità non devono presentare altri tag di tipo @Export{...} all'interno. Fa tutto questo decoratore
469
+ *
470
+ * I navigator hanno questa convenzione:
471
+ *
472
+ * . --> divide due proprietà da richiamare consecutivamente: "a.b" richiamerà "obj.a.b";
473
+ *
474
+ * | --> divide più proprietà per le concatenazioni con uno spazio fra una e l'altra: "regdesc|slice.slicename" diventerà obj.regdesc + " " + obj.slice.slicename
475
+ *
476
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
477
+ * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
478
+ * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
479
+ * @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
480
+ */
481
+ const ExportList = (order, headernavigator, valuenavigator, valueformat = null) => (target, propertyKey) => {
482
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
483
+ Object.defineProperty(target, propertyKey + listCsvValPrefix, { value: valuenavigator, writable: false });
484
+ Object.defineProperty(target, propertyKey + listCsvHdrPrefix, { value: headernavigator, writable: false });
485
+ Object.defineProperty(target, propertyKey + listCsvValFormat, { value: valueformat, writable: false });
486
+ if (target[exportList])
487
+ target[exportList].push(propertyKey + listCsvHdrPrefix);
488
+ else
489
+ target[exportList] = [propertyKey + listCsvHdrPrefix];
490
+ };
491
+ /**
492
+ * Decoratore di esportazione utilizzabile su un dizionario. Se ad esempio si vogliono generare le colonne
493
+ *
494
+ * Valore A = 1
495
+ *
496
+ * Valore B = 2
497
+ *
498
+ * Valore C = 3
499
+ *
500
+ * partendo da un oggetto iniziale { Valore { A: 1, B: 2, C: 3 } }
501
+ *
502
+ * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
503
+ * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
504
+ * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
505
+ */
506
+ const ExportDictionary = (order, headernavigator, valuenavigator) => (target, propertyKey) => {
507
+ Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
508
+ Object.defineProperty(target, propertyKey + dictionaryCsvValPrefix, { value: valuenavigator, writable: false });
509
+ Object.defineProperty(target, propertyKey + dictionaryCsvHdrPrefix, { value: headernavigator, writable: false });
510
+ if (target[exportList])
511
+ target[exportList].push(propertyKey + dictionaryCsvHdrPrefix);
512
+ else
513
+ target[exportList] = [propertyKey + dictionaryCsvHdrPrefix];
514
+ };
515
+ /**
516
+ * Service che si occupa dell'esportazione degli oggetti marcati dai Decoratori **ExportDictionary**, **ExportList**, **ExportAs** o **Export**
517
+ */
518
+ class ExportService {
635
519
  /**
636
520
  * Costruttore
637
521
  *
638
522
  * @ignore
639
523
  */
640
- constructor(locProvider, allowUtc) {
641
- this.locProvider = locProvider;
642
- this.allowUtc = allowUtc;
643
- /**
644
- * Oggetto statico di localizzazione per i messaggi di questa Service
645
- */
646
- this.loc = {
647
- "SMALL_DATE_FORMAT": { 'en-US': "MM/DD/YYYY", 'it-IT': "DD/MM/YYYY" },
648
- "FULL_DATE_FORMAT": { 'en-US': "MM/DD/YYYY HH:mm:ss", 'it-IT': "DD/MM/YYYY HH:mm:ss" },
649
- "FULL_DATE_FORMAT_NO_SS": { 'en-US': "MM/DD/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" },
650
- "SMALL_DATE_DISPLAY_FORMAT": { 'en-US': "DD/MM/YYYY", 'it-IT': "DD/MM/YYYY" },
651
- "SMALL_DATE_DISPLAY_FORMAT_WITH_HOUR": { 'en-US': "DD/MM/YYYY HH", 'it-IT': "DD/MM/YYYY HH" },
652
- "SMALL_DATE_DISPLAY_FORMAT_WITH_MINUTE": { 'en-US': "DD/MM/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" },
653
- "FULL_DATE_DISPLAY_FORMAT": { 'en-US': "DD/MM/YYYY HH:mm:ss", 'it-IT': "DD/MM/YYYY HH:mm:ss" },
654
- "FULL_DATE_DISPLAY_FORMAT_NO_SS": { 'en-US': "DD/MM/YYYY HH:mm", 'it-IT': "DD/MM/YYYY HH:mm" }
655
- };
656
- /**
657
- * Oggetto di configurazione per tenere da conto le informazioni sui formati
658
- */
659
- this.cfg = {
660
- fulldate: "",
661
- fulldateDisplay: "",
662
- smallDate: "",
663
- fulldateNoSS: "",
664
- smallDateWithH: "",
665
- smallDateWithM: "",
666
- fulldateDisplayNoSS: ""
667
- };
668
- this.init();
669
- }
670
- init() {
671
- return __awaiter(this, void 0, void 0, function* () {
672
- let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
673
- this.cfg.smallDate = this.loc["SMALL_DATE_FORMAT"][LOCALE];
674
- this.cfg.fulldate = this.loc["FULL_DATE_FORMAT"][LOCALE];
675
- this.cfg.fulldateNoSS = this.loc["FULL_DATE_FORMAT_NO_SS"][LOCALE];
676
- this.cfg.fulldateDisplay = this.loc["FULL_DATE_DISPLAY_FORMAT"][LOCALE];
677
- this.cfg.fulldateDisplayNoSS = this.loc["FULL_DATE_DISPLAY_FORMAT_NO_SS"][LOCALE];
678
- this.cfg.smallDate = this.loc["SMALL_DATE_DISPLAY_FORMAT"][LOCALE];
679
- this.cfg.smallDateWithH = this.loc["SMALL_DATE_DISPLAY_FORMAT_WITH_HOUR"][LOCALE];
680
- this.cfg.smallDateWithM = this.loc["SMALL_DATE_DISPLAY_FORMAT_WITH_MINUTE"][LOCALE];
681
- });
524
+ constructor(dates) {
525
+ this.dates = dates;
682
526
  }
683
527
  /**
684
- * Aggiusta una data in "istante finale" in base a qual è la parte di data significativa.
528
+ * Data una lista di oggetti genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
685
529
  *
686
- * Es. Istante finale delle ore: 05/10/1992 --> 04/10/1992 24:00(:00)
530
+ * @param {any[]} objs Oggetti da esportare
687
531
  *
688
- * @param {any} date Data qualsiasi (Date, stringa, dayjs...), verrà ricondotta ad un oggetto dayJs
689
- * @param {'day' | 'hour' | 'minute'} timepart Parte significativa della data
690
- * @param {boolean} printSeconds Indica se effettuare la stampa dei secondi o no
532
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
691
533
  */
692
- adjustDateToFinalInstant(date, timepart, printSeconds = true) {
693
- let mydt = this.getDateConvertion(date);
694
- if (mydt == null)
695
- return "FE: Not a Date";
696
- let isZeroTime = mydt.startOf(timepart).valueOf() === mydt.valueOf();
697
- if (!isZeroTime) {
698
- if (timepart == "day" && mydt.subtract(1, "hour").hour() == mydt.hour()) {
699
- // Se l'ora precedente è lo stesso orario dell'ora attuale l'istante finale dev'essere mandato avanti di 1
700
- mydt = mydt.add(1, "hour");
534
+ setupForExport(objs, columns = []) {
535
+ let headers = [];
536
+ let headersCache = {};
537
+ if (!objs || objs.length == 0)
538
+ return headers;
539
+ // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
540
+ // Gli header li raccolgo tutti poi faccio uan distinct in modo da esportare tutte le proprietà per bene
541
+ let columnSelectionDictionary = {};
542
+ if ((columns === null || columns === void 0 ? void 0 : columns.length) > 0)
543
+ for (let i = 0; i < (columns === null || columns === void 0 ? void 0 : columns.length); i++)
544
+ columnSelectionDictionary[columns[i]] = true;
545
+ for (let i = 0; i < objs.length; i++) {
546
+ let hds = this.parseAndGetHeaders(objs[i], columnSelectionDictionary);
547
+ // Aggiungo gli header facendo in modo di non aggiungerne mai due uguali per non dover fare una distinct dopo
548
+ // che costerebbe comunque risorse. Utilizzo un dizionario d'appoggio per lookup istantanei
549
+ for (let k = 0; k < hds.length; k++) {
550
+ if (!headersCache[hds[k].key]) {
551
+ headersCache[hds[k].key] = true;
552
+ headers.push(hds[k]);
553
+ }
701
554
  }
702
- return printSeconds ? mydt.format(this.cfg.fulldateDisplay) : mydt.format(this.cfg.fulldateDisplayNoSS);
703
555
  }
704
- let tmpValue = mydt.subtract(1, timepart);
705
- let value = "";
706
- // Istante finale delle ore: 05/10/1992 --> 04/10/1992 24:00(:00)
707
- if (timepart == 'day')
708
- value = tmpValue.format(this.cfg.smallDate) + " 24:00" + (printSeconds ? ':00' : '');
709
- // Istante finale dei minuti: giorno 05/10/1992 04:00:00 --> 05/10/1992 03:60(:00)
710
- else if (timepart == 'hour')
711
- value = tmpValue.format(this.cfg.smallDateWithH) + ":60" + (printSeconds ? ':00' : '');
712
- // Istante finale dei secondi: giorno 05/10/1992 04:10:00 --> 05/10/1992 04:09:60
713
- else if (timepart == 'minute')
714
- value = tmpValue.format(this.cfg.smallDateWithM) + ":60";
715
- return value;
716
- }
717
- /**
718
- * Funzione che effettua l'ordinamento fra 2 date in base alla direzione specificata
719
- *
720
- * @param {any} a Prima data per il confronto
721
- * @param {any} b Seconda data per il confronto
722
- * @param {'asc' | 'desc'} direction Direzione rispetto a cui ordinare le due date
723
- *
724
- * @returns {number} 0 se le date sono uguali, 1 se la data A deve venire logicamente prima della data B, -1 altrimenti
725
- */
726
- dateSort(a, b, direction) {
727
- if (a < b)
728
- return direction == 'asc' ? 1 : -1;
729
- else if (a > b)
730
- return direction == 'asc' ? -1 : 1;
731
- // con a uguale a b
732
- return 0;
556
+ if (!columns || columns.length == 0)
557
+ return headers.sort((a, b) => a.order - b.order);
558
+ else {
559
+ // Se mi arriva la lista di colonne non mi dà solo la visibilità, ma anche l'ordinamento
560
+ // le esporto di conseguenza
561
+ let orderedHeaders = [];
562
+ for (let i = 0; i < columns.length; i++) {
563
+ let thisId = columns[i];
564
+ for (let i = 0; i < headers.length; i++) {
565
+ if (headers[i].propKey == thisId) {
566
+ orderedHeaders.push(headers[i]);
567
+ break;
568
+ }
569
+ }
570
+ }
571
+ return orderedHeaders;
572
+ }
733
573
  }
734
574
  /**
735
- * Effettua il trim dei secondi da una data espressa come stringa
575
+ * 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**
736
576
  *
737
- * @param {string} value Data espressa come stringa
577
+ * @param {GenericItem[]} objs Oggetti generici da esportare
578
+ * @param {CsvHeaders[]} columns Colonne richieste dall'esportazione
738
579
  *
739
- * @returns {string} Data senza i secondi
580
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
740
581
  */
741
- trimSeconds(value) {
742
- //I numeri mangiati da dayjs spesso vengono ricondotti a date vere. Mi assicuro che se ci sono solo numeri proseguo
743
- if (!isNaN(value))
744
- return value;
745
- //Se non ho qualcosa del tipo XX/YY/ZZZZ aa:bb:cc di sicuro non è una data che mi interessa
746
- if (!/^\d\d\/\d\d\/\d\d\d\d \d\d:\d\d:\d\d$/g.test(value))
747
- return value;
748
- //In questo caso mi arrivano valori che devono essere stampati as-is, solo tagliando i secondi
749
- return "'" + value.substr(0, value.length - 3);
582
+ setupForGenericExport(objs, columns) {
583
+ let headers = [];
584
+ if (!objs || objs.length == 0)
585
+ return headers;
586
+ // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
587
+ objs.forEach((obj, index) => {
588
+ if (index == 0)
589
+ headers = this.parseAndGetGenericHeaders(obj, columns);
590
+ else
591
+ this.parseAndGetGenericHeaders(obj, columns);
592
+ });
593
+ return headers;
750
594
  }
751
595
  /**
752
- * Data una lista di date Da e una lista di date A restituisce un oggetto rappresentante il range che include tutte le date passate
753
- *
754
- * @param {any[]} fromDates Lista dei Da
755
- * @param {any[]} toDates Lista dei A
596
+ * Dato un oggetto generico genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
756
597
  *
757
- * @returns {{ from: any, to: any }} Range di date Da - A che include tutti i valori di **fromDates** e **toDates**
758
- */
759
- getMinMaxDatesRange(fromDates, toDates) {
760
- let datesFroms = [];
761
- let datesTo = [];
762
- for (let i = 0; i < fromDates.length; i++) {
763
- let d = fromDates[i];
764
- var convertion = this.getDateConvertion(d);
765
- if (convertion)
766
- datesFroms.push(convertion);
767
- }
768
- for (let i = 0; i < toDates.length; i++) {
769
- let d = toDates[i];
770
- var convertion = this.getDateConvertion(d);
771
- if (convertion)
772
- datesTo.push(convertion);
773
- }
774
- return { from: dayjs.min(datesFroms), to: dayjs.max(datesTo) };
775
- }
776
- /**
777
- * Ottiene la conversione di una data in qualsiasi formato al formato standard DayJs
598
+ * Metodo interno richiamato da **setupForGenericExport**
778
599
  *
779
- * @param {any} date Oggetto rappresentante una data. Potrebbe essere una stringa, un Date o già un DayJs
780
- * @param {boolean} useUtc Indica se usare l'estensione utc di Dayjs per parsare la data o no
600
+ * @param {GenericItem} obj Oggetto generico da esportare
601
+ * @param {CsvColumn[]} columns Colonne richieste dall'esportazione
781
602
  *
782
- * @returns {any} Data in modalità DayJs
603
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
783
604
  */
784
- getDateConvertion(date, useUtc = false) {
785
- if (!date)
786
- return null;
787
- if (this.isDayJs(date))
788
- return date;
789
- if (this.isJsDate(date))
790
- return useUtc ? dayjs.utc(date) : dayjs(date);
791
- // Se non c'è la proprietà length vuol dire che non è una stringa e a questo punto non ho idea di che minchia sia
792
- let length = date.length;
793
- if (!length)
605
+ parseAndGetGenericHeaders(obj, columns) {
606
+ if (!obj.properties)
794
607
  return null;
795
- if (useUtc && !this.allowUtc)
796
- throw "@esfaenza/extensions: Richiesta data UTC ma da configurazione la libreria non lo supporta";
797
- // Per risparmiare chiamate a tentoni, in base alla lunghezza della stringa chiamo direttamente il metodo giusto,
798
- // controllando poi che mi generi una data come me la aspetto io
799
- let tryThis = null;
800
- let toCall = useUtc ? dayjs.utc : dayjs;
801
- // 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.
802
- // Per il resto mi baso sulla lunghezza della stringa
803
- if (date.includes("T"))
804
- tryThis = toCall(date);
805
- else if (length == this.cfg.fulldate.length)
806
- tryThis = toCall(date, this.cfg.fulldate);
807
- else if (length == this.cfg.smallDate.length)
808
- tryThis = toCall(date, this.cfg.smallDate);
809
- else if (length == this.cfg.fulldateNoSS.length)
810
- tryThis = toCall(date, this.cfg.fulldateNoSS);
811
- if (tryThis && tryThis.isValid && tryThis.isValid())
812
- return tryThis;
813
- // Se niente funziona, null.
814
- // Ricondurre l'Input ad una data non è possibile.
815
- return null;
608
+ var headers = [];
609
+ //Miracle incoming
610
+ columns.forEach(t => {
611
+ var propValue = obj.properties[t.key];
612
+ Object.defineProperty(obj, t.key + "_exp", { value: propValue, writable: false, enumerable: true });
613
+ headers.push({ label: t.label, key: t.key + "_exp", order: t.order, type: t.type, propKey: null });
614
+ });
615
+ //Tirati fuori tutti gli header faccio sort sull'ordinamento
616
+ return headers.sort((a, b) => { return a.order - b.order; });
816
617
  }
817
618
  /**
818
- * Helper che restituisce **true** qualora l'oggetto passato fosse una data vera e propria, **false** altrimenti
619
+ * Dato un oggetto genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
819
620
  *
820
- * @param {any} check Oggetto da controllare
621
+ * Metodo interno richiamato da **setupForExport**
821
622
  *
822
- * @returns {boolean} Indicazione se l'oggetto è un vero Date di Javascript o no
623
+ * @param {any} obj Oggetto generico da esportare
624
+ *
625
+ * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
823
626
  */
824
- isJsDate(check) {
825
- return check && Object.prototype.toString.call(check) === "[object Date]" && !isNaN(check);
627
+ parseAndGetHeaders(obj, columnsSelection) {
628
+ var headers = [];
629
+ // Miracle incoming
630
+ let exportProps = obj[exportList] || [];
631
+ if (exportProps.length == 0)
632
+ console.warn("[@esfaenza/extensions] Nessuna colonna configurata da esportare!");
633
+ for (let i = 0; i < exportProps.length; i++) {
634
+ let prop = exportProps[i];
635
+ let propBase = "";
636
+ let toCall;
637
+ if (prop.endsWith(listCsvHdrPrefix)) {
638
+ propBase = prop.replace(listCsvHdrPrefix, '');
639
+ toCall = this.parseList.bind(this);
640
+ }
641
+ else if (prop.endsWith(dictionaryCsvHdrPrefix)) {
642
+ toCall = this.parseDictionary.bind(this);
643
+ propBase = prop.replace(dictionaryCsvHdrPrefix, '');
644
+ }
645
+ else if (prop.endsWith(csvVisPrefix)) {
646
+ propBase = prop.replace(csvVisPrefix, '');
647
+ if (typeof obj[propBase + csvValueNavigator] !== "undefined")
648
+ toCall = this.parseObject.bind(this);
649
+ else
650
+ toCall = this.parseProperty.bind(this);
651
+ }
652
+ if (toCall)
653
+ toCall(obj, propBase, headers, columnsSelection);
654
+ }
655
+ return headers;
826
656
  }
827
657
  /**
828
- * Helper che restituisce **true** qualora l'oggetto passato fosse un DayJs vero e proprio, **false** altrimenti
658
+ * Setup per l'esportazione di una singola proprietà.
659
+ * Viene generato l'header e la proprietà relativa al valore formattato o no
829
660
  *
830
- * @param {any} check Oggetto da controllare
831
- * @returns {boolean} Indicazione se l'oggetto è un vero DayJs o no
661
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
662
+ * @param {string} prop Proprietà da esportare
663
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
832
664
  */
833
- isDayJs(check) {
834
- // Non uso instanceof perché sarebbe estremamente più lento
835
- // Non uso nemmeno isDayjs() della libreria Dayjs dato che ha lo stesso problema: https://github.com/iamkun/dayjs/blob/06f88f425828b1ce96b737332d25145a95a4ee9d/src/index.js#L9
836
- return check.$D !== undefined && check.$M !== undefined && check.$y !== undefined;
665
+ parseProperty(obj, prop, headers, columnsSelection) {
666
+ let toEmit = obj[prop + csvVisPrefix];
667
+ let format = obj[prop + csvFormatPrefix];
668
+ let propKey = obj[prop + csvPropKey];
669
+ if (propKey && !columnsSelection[propKey] && Object.keys(columnsSelection).length > 0) {
670
+ console.log("[@esfaenza/extensions] Colonna da non esportare: " + propKey);
671
+ return;
672
+ }
673
+ let lbl = obj[prop + csvHdrPrefix];
674
+ let order = obj[prop + csvOrdPrefix];
675
+ if (toEmit && lbl !== "undefined") {
676
+ // Se non ho un formato esporto direttamente
677
+ if (!format) {
678
+ // Se è un formato data mi assicuro di non stampare mai una data 00:00:00 altrimenti in esportazione viene uno schifo
679
+ var val = obj[prop] ? this.dates.trimSeconds(obj[prop].toString()) : "";
680
+ Object.defineProperty(obj, prop + "_nofmt", { value: val, writable: false, enumerable: true });
681
+ headers.push({ label: lbl ? lbl : prop + "_nofmt", key: prop + "_nofmt", order: order, type: "string", propKey: propKey });
682
+ }
683
+ else {
684
+ // Caso formato numerico
685
+ if (format == "F") {
686
+ // Check considerando la possibilità di zeri
687
+ let val = obj[prop] != null ? obj[prop].toString() : "";
688
+ // Elimino tutte le virgole (indicatori di migliaia per la culture default en-US)
689
+ val = val.replace(/,/, "");
690
+ // Il singolo punto che c'è, se presente (separatore decimali) lo trasformo in virgola
691
+ let valConverted = val.replace(".", ",");
692
+ Object.defineProperty(obj, prop + "_fmt", { value: valConverted, writable: false, enumerable: true });
693
+ headers.push({ label: lbl ? lbl : prop + "_fmt", key: prop + "_fmt", order: order, type: "number", propKey: propKey });
694
+ }
695
+ else {
696
+ // Se ho un formato data trasformo in dayjs, formatto ed esporto
697
+ // Per la trasformazione in dayjs provo prima a passargli la stringa di netto, sperando la riconosca
698
+ // Se non funziona provo a definirgli la formattazione standard del metering per quel linguaggio
699
+ let val = this.dates.getFormatted(obj[prop], format.length <= 10, format.length > 16);
700
+ Object.defineProperty(obj, prop + "_fmt", { value: val !== null && val !== void 0 ? val : "", writable: false, enumerable: true });
701
+ headers.push({ label: lbl ? lbl : prop + "_fmt", key: prop + "_fmt", order: order, type: "date", propKey: propKey });
702
+ }
703
+ }
704
+ }
837
705
  }
838
706
  /**
839
- * Ottiene la formattazione di una data in base alla versione richiesta "small" o "long" e a se stampare o meno i secondi
707
+ * Setup per l'esportazione di una singola proprietà da un oggetto.
708
+ * Viene generato l'header e la proprietà relativa al valore formattato o no.
840
709
  *
841
- * @param {any} date Oggetto rappresentante una data. Potrebbe essere una stringa, un Date o già un DayJs
842
- * @param {boolean} small Indica se formattarla con un formato breve (se **true**) o un formato più lungo (se **false**)
710
+ * Per ottenere il valore e l'header della proprietà vengono utilizzati i navigatori auto-generati nel decoratore **ExportAs**
843
711
  *
844
- * @returns {string} Data formattata nel formato richiesto
712
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
713
+ * @param {string} prop Proprietà da esportare
714
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
845
715
  */
846
- getFormatted(date, small, seconds) {
847
- var date = this.getDateConvertion(date);
848
- if (!date)
849
- return null;
850
- return date.format(small ? this.cfg.smallDate : seconds ? this.cfg.fulldateDisplay : this.cfg.fulldateDisplayNoSS);
851
- }
852
- }
853
- DateService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DateService, deps: [{ token: i1.BaseLocalization, optional: true }, { token: EXT_ALLOW_UTC, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
854
- DateService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DateService });
855
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: DateService, decorators: [{
856
- type: Injectable
857
- }], ctorParameters: function () {
858
- return [{ type: i1.BaseLocalization, decorators: [{
859
- type: Optional
860
- }] }, { type: undefined, decorators: [{
861
- type: Optional
862
- }, {
863
- type: Inject,
864
- args: [EXT_ALLOW_UTC]
865
- }] }];
866
- } });
867
-
868
- /**
869
- * Suffisso della proprietà da generare in cui salvare il navigatore
870
- * utilizzato dal servizio di esportazione per prendere il valore delle proprietà di un oggetto
871
- */
872
- const csvValueNavigator = "_csvnav";
873
- /**
874
- * Suffisso della proprietà da generare in cui salvare l'ordine di esportazione
875
- */
876
- const csvOrdPrefix = "_csvord";
877
- /**
878
- * Suffisso della proprietà da generare in cui salvare la visibilità di questa proprietà
879
- */
880
- const csvVisPrefix = "_csvvis";
881
- /**
882
- * Suffisso della proprietà da generare in cui salvare il nome della colonna in cui salvare questa proprietà
883
- */
884
- const csvHdrPrefix = "_csvhdr";
885
- /**
886
- * Suffisso della proprietà da generare in cui salvare il codice del th a cui si riferisce questo campo
887
- */
888
- const csvPropKey = "_csvkey";
889
- /**
890
- * Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Lista
891
- */
892
- const listCsvValPrefix = "_listcsvval";
893
- /**
894
- * Suffisso della proprietà da generare in cui salvare l'Header della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix**
895
- */
896
- const listCsvHdrPrefix = "_listcsvhdr";
897
- /**
898
- * Suffisso della proprietà da generare in cui salvare il formato della proprietà di tipo Lista relativo al valore esportato nella proprietà con suffisso **listCsvValPrefix**
899
- */
900
- const listCsvValFormat = "_listcsvvalformat";
901
- /**
902
- * Suffisso della proprietà da generare in cui salvare il valore da prendere per una proprietà di tipo Dizionario
903
- */
904
- const dictionaryCsvValPrefix = "_flatlistcsvval";
905
- /**
906
- * Suffisso della proprietà da generare in cui salvare l'Header della proprietà di un Dizionario relativo al valore esportato nella proprietà con suffisso **dictionaryCsvValPrefix**
907
- */
908
- const dictionaryCsvHdrPrefix = "_flatlistcsvhdr";
909
- /**
910
- * Suffisso della proprietà da generare in cui salvare il formato della proprietà che si sta esportando
911
- */
912
- const csvFormatPrefix = "_csvfmt";
913
- /**
914
- * Nome della proprietà che contiene tutti i nomi di tutte le proprietà da esportare
915
- */
916
- const exportList = "__export_list__";
917
-
918
- // Angular
919
- /**
920
- * Decoratore di esportazione utilizzabile su una proprietà singola.
921
- * Verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
922
- *
923
- * Ad esempio, da questa configurazione:
924
- *
925
- * @example
926
- * ```
927
- * @Export(true, "MyHeader")
928
- * ciao: string;
929
- * ```
930
- *
931
- * Nasceranno le seguenti proprietà nell'oggetto esportabile:
932
- *
933
- * @example
934
- * ```
935
- * ciao_csvvis: string; => true
936
- * ciao: string;
937
- * ciao_csvhdr: string => "MyHeader"
938
- * ```
939
- *
940
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
941
- * @param {string} header Titolo della colonna nel file CSV esportato
942
- * @param {string} format Formato di esportazione. Può essere un formato data per i campi data o 'F' per i campi floating point
943
- */
944
- const Export = (order, header, format = null, tableid = null) => (target, propertyKey) => {
945
- if (format)
946
- Object.defineProperty(target, propertyKey + csvFormatPrefix, { value: format, writable: false });
947
- Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
948
- Object.defineProperty(target, propertyKey + csvVisPrefix, { value: !!header, writable: false });
949
- Object.defineProperty(target, propertyKey + csvHdrPrefix, { value: header, writable: false });
950
- if (tableid)
951
- Object.defineProperty(target, propertyKey + csvPropKey, { value: tableid, writable: false });
952
- if (target[exportList])
953
- target[exportList].push(propertyKey + csvVisPrefix);
954
- else
955
- target[exportList] = [propertyKey + csvVisPrefix];
956
- };
957
- /**
958
- * Decoratore di esportazione utilizzabile su un oggetto.
959
- * Per ogni proprietà dell'oggetto verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr).
960
- * Per essere esportate, le proprietà dell'oggetto devono essere marcate con i Decoratori di esportazione
961
- *
962
- * Ad esempio, da questa configurazione:
963
- *
964
- * @example
965
- * ```
966
- * MyObj {
967
- * @Export(true, "MyHeader")
968
- * ciao: string;
969
- * }
970
- *
971
- * @ExportObject(true, "MyHeader")
972
- * test: MyObj;
973
- * ```
974
- *
975
- * Nasceranno le seguenti proprietà nell'oggetto esportabile:
976
- *
977
- * @example
978
- * ```
979
- * testciao: string; => Valore di MyObj.ciao
980
- * testciao_csvvis: string; => true
981
- * testciao_csvhdr: string => "MyHeader"
982
- * ```
983
- *
984
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
985
- * @param {any} type Tipo da esportare
986
- */
987
- const ExportAs = (order, type, prefix) => (target, propertyKey) => {
988
- var t = new type();
989
- var props = t[exportList];
990
- for (let i = 0; i < props.length; i++) {
991
- let prop = props[i].replace(csvVisPrefix, '');
992
- if (typeof t[prop + csvVisPrefix] !== "undefined") {
993
- var toEmit = t[prop + csvVisPrefix];
994
- var lbl = t[prop + csvHdrPrefix];
995
- var format = t[prop + csvFormatPrefix];
996
- var orderProp = t[prop + csvOrdPrefix];
997
- if (format)
998
- Object.defineProperty(target, propertyKey + prop + csvFormatPrefix, { value: format, writable: false });
999
- Object.defineProperty(target, propertyKey + prop + csvOrdPrefix, { value: orderProp + order, writable: false });
1000
- Object.defineProperty(target, propertyKey + prop, { value: null, writable: true, enumerable: true });
1001
- Object.defineProperty(target, propertyKey + prop + csvValueNavigator, { value: propertyKey + "." + prop, writable: false });
1002
- Object.defineProperty(target, propertyKey + prop + csvVisPrefix, { value: toEmit, writable: false });
1003
- Object.defineProperty(target, propertyKey + prop + csvHdrPrefix, { value: (prefix ? prefix + ' ' : '') + lbl, writable: false });
1004
- if (target[exportList])
1005
- target[exportList].push(propertyKey + prop + csvVisPrefix);
1006
- else
1007
- target[exportList] = [propertyKey + prop + csvVisPrefix];
716
+ parseObject(obj, prop, headers) {
717
+ //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
718
+ let valuenavigator = obj[prop + csvValueNavigator];
719
+ //Es. di valuenavigator obj.subobj.subsubobj.property
720
+ let jmps = valuenavigator.split(".");
721
+ //Mi clono l'oggetto originale per non uccidergli i riferimenti
722
+ let clone = JSON.parse(JSON.stringify(obj));
723
+ //Salto ricorsivamente su me stesso per arrivare alla proprietà
724
+ //Salto 1 > diventa obj
725
+ //Salto 2 > diventa obj.subobj
726
+ //ecc...
727
+ jmps.forEach(pp => { clone = clone[pp]; });
728
+ //Valore finale :D
729
+ let value = clone;
730
+ let lbl = obj[prop + csvHdrPrefix];
731
+ let order = obj[prop + csvOrdPrefix];
732
+ //Se per questa proprietà ho un formato lo applico
733
+ let format = obj[prop + csvFormatPrefix];
734
+ let type = "string";
735
+ if (format == "F") {
736
+ let val = value.toString();
737
+ val = val.replace(/,/, "");
738
+ value = val.replace(".", ",");
739
+ type = "number";
740
+ }
741
+ else if (format) {
742
+ value = this.dates.getFormatted(value, format.length <= 10, format.length > 16);
743
+ type = "date";
1008
744
  }
745
+ Object.defineProperty(obj, prop, { value: value !== null && value !== void 0 ? value : "", writable: false, enumerable: true });
746
+ headers.push({ label: lbl ? lbl : prop, key: prop, order: order, type: type, propKey: null });
1009
747
  }
1010
- };
1011
- /**
1012
- * Decoratore di esportazione utilizzabile su una lista,
1013
- * si utilizzano 2 navigator rispettivamente per la valorizzazione dell'Header e del Valore e
1014
- * per ogni elemento dell'array verranno generate 3 proprietà che gestiranno l'esportazione: (prop, prop_csvvis, prop_csvhdr)
1015
- *
1016
- * ATTENZIONE: Gli oggetti esportati in questa modalità non devono presentare altri tag di tipo @Export{...} all'interno. Fa tutto questo decoratore
1017
- *
1018
- * I navigator hanno questa convenzione:
1019
- *
1020
- * . --> divide due proprietà da richiamare consecutivamente: "a.b" richiamerà "obj.a.b";
1021
- *
1022
- * | --> divide più proprietà per le concatenazioni con uno spazio fra una e l'altra: "regdesc|slice.slicename" diventerà obj.regdesc + " " + obj.slice.slicename
1023
- *
1024
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
1025
- * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
1026
- * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
1027
- * @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
1028
- */
1029
- const ExportList = (order, headernavigator, valuenavigator, valueformat = null) => (target, propertyKey) => {
1030
- Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
1031
- Object.defineProperty(target, propertyKey + listCsvValPrefix, { value: valuenavigator, writable: false });
1032
- Object.defineProperty(target, propertyKey + listCsvHdrPrefix, { value: headernavigator, writable: false });
1033
- Object.defineProperty(target, propertyKey + listCsvValFormat, { value: valueformat, writable: false });
1034
- if (target[exportList])
1035
- target[exportList].push(propertyKey + listCsvHdrPrefix);
1036
- else
1037
- target[exportList] = [propertyKey + listCsvHdrPrefix];
1038
- };
1039
- /**
1040
- * Decoratore di esportazione utilizzabile su un dizionario. Se ad esempio si vogliono generare le colonne
1041
- *
1042
- * Valore A = 1
1043
- *
1044
- * Valore B = 2
1045
- *
1046
- * Valore C = 3
1047
- *
1048
- * partendo da un oggetto iniziale { Valore { A: 1, B: 2, C: 3 } }
1049
- *
1050
- * @param {number} order Ordine di esportazione. Più piccolo è, prima appare il valore
1051
- * @param {string} headernavigator Navigator col compito di selezionare il titolo per la colonna
1052
- * @param {string} valuenavigator Navigator col compito di selezionare il valore per la colonna
1053
- */
1054
- const ExportDictionary = (order, headernavigator, valuenavigator) => (target, propertyKey) => {
1055
- Object.defineProperty(target, propertyKey + csvOrdPrefix, { value: order, writable: false });
1056
- Object.defineProperty(target, propertyKey + dictionaryCsvValPrefix, { value: valuenavigator, writable: false });
1057
- Object.defineProperty(target, propertyKey + dictionaryCsvHdrPrefix, { value: headernavigator, writable: false });
1058
- if (target[exportList])
1059
- target[exportList].push(propertyKey + dictionaryCsvHdrPrefix);
1060
- else
1061
- target[exportList] = [propertyKey + dictionaryCsvHdrPrefix];
1062
- };
748
+ /**
749
+ * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
750
+ *
751
+ * => Recupero il valore utilizzando i navigatori
752
+ *
753
+ * => Recupero l'header utilizzando i navigatori
754
+ *
755
+ * => Con il valore ci creo la property
756
+ *
757
+ * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
758
+ *
759
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
760
+ * @param {string} prop Proprietà da esportare
761
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
762
+ */
763
+ parseList(obj, prop, headers) {
764
+ let headernavigator = obj[prop + listCsvHdrPrefix];
765
+ let valuenavigator = obj[prop + listCsvValPrefix];
766
+ let valueformat = obj[prop + listCsvValFormat];
767
+ let order = obj[prop + csvOrdPrefix];
768
+ var jumps, tmpRes;
769
+ var objs = obj[prop];
770
+ for (let idx = 0; idx < objs.length; idx++) {
771
+ let listitem = objs[idx];
772
+ var headersplit = headernavigator.split(" ");
773
+ var header = "";
774
+ // Per l'header si considera a se stante ogni pezzo separato da spazio per fare le concatenazioni
775
+ headersplit.forEach(pr => {
776
+ jumps = pr.split(".");
777
+ tmpRes = JSON.parse(JSON.stringify(listitem));
778
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
779
+ if (!header)
780
+ header = tmpRes;
781
+ else
782
+ header += " " + tmpRes;
783
+ });
784
+ jumps = valuenavigator.split(".");
785
+ tmpRes = JSON.parse(JSON.stringify(listitem));
786
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
787
+ let value = tmpRes;
788
+ let type = "string";
789
+ if (valueformat == "F") {
790
+ let val = value != null ? value.toString() : "";
791
+ val = val.replace(/,/, "");
792
+ value = val.replace(".", ",");
793
+ type = "number";
794
+ }
795
+ else if (valueformat) {
796
+ value = this.dates.getFormatted(obj[prop], valueformat.length <= 10, valueformat.length > 16);
797
+ type = "date";
798
+ }
799
+ Object.defineProperty(obj, prop + idx, { value: value !== null && value !== void 0 ? value : "", writable: false });
800
+ headers.push({ label: header, key: prop + idx, order: order + idx, type: type, propKey: null });
801
+ }
802
+ }
803
+ /**
804
+ * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
805
+ *
806
+ * => Recupero il valore utilizzando i navigatori
807
+ *
808
+ * => Recupero l'header utilizzando i navigatori
809
+ *
810
+ * => Con il valore ci creo la property
811
+ *
812
+ * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
813
+ *
814
+ * @param {any} obj Oggetto di cui esportare la proprietà **prop**
815
+ * @param {string} prop Proprietà da esportare
816
+ * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
817
+ */
818
+ parseDictionary(obj, prop, headers) {
819
+ let headernavigator = obj[prop + dictionaryCsvHdrPrefix];
820
+ let valuenavigator = obj[prop + dictionaryCsvValPrefix];
821
+ let order = obj[prop + csvOrdPrefix];
822
+ var jumps, tmpRes;
823
+ var objs = obj[prop];
824
+ for (let idx = 0; idx < objs.length; idx++) {
825
+ let listitem = objs[idx];
826
+ var headersplit = headernavigator.split(" ");
827
+ var header = "";
828
+ headersplit.forEach(pr => {
829
+ jumps = pr.split(".");
830
+ tmpRes = JSON.parse(JSON.stringify(listitem));
831
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
832
+ if (!header)
833
+ header = tmpRes;
834
+ else
835
+ header += " " + tmpRes;
836
+ });
837
+ var valuesplit = valuenavigator.split(",");
838
+ valuesplit.forEach((t, idxinternal) => {
839
+ var navig = t.split("-")[1];
840
+ var desc = t.split("-")[0];
841
+ jumps = navig.split(".");
842
+ tmpRes = JSON.parse(JSON.stringify(listitem));
843
+ jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
844
+ let value = tmpRes;
845
+ let propname = prop + idx.toString() + idxinternal.toString();
846
+ Object.defineProperty(obj, propname, { value: value !== null && value !== void 0 ? value : "", writable: false });
847
+ headers.push({ label: header + " " + desc, key: propname, order: order + idx, type: 'string', propKey: null });
848
+ });
849
+ }
850
+ }
851
+ /**
852
+ * Metodo che si occupa della deserializzazione degli oggetti da esportare. Messo a livello di libreria in modo che qualora ci fosse da cambiare libreria
853
+ * tutte le manutenzioni siano concentrate qui
854
+ *
855
+ * @param {any[]} items Oggetti da deserializzare
856
+ * @param {any} type Tipo da usare come prototipo per la deserializzazione
857
+ *
858
+ * @returns {any} Oggetti deserializzati
859
+ */
860
+ deserializeForExport(items, type) {
861
+ return Deserialize(items, type);
862
+ }
863
+ }
864
+ ExportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, deps: [{ token: DateService }], target: i0.ɵɵFactoryTarget.Injectable });
865
+ ExportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, providedIn: "root" });
866
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, decorators: [{
867
+ type: Injectable,
868
+ args: [{ providedIn: "root" }]
869
+ }], ctorParameters: function () { return [{ type: DateService }]; } });
870
+
1063
871
  /**
1064
- * Service che si occupa dell'esportazione degli oggetti marcati dai Decoratori **ExportDictionary**, **ExportList**, **ExportAs** o **Export**
872
+ * Service che fornisce funzionalità di alert nei tipi fondamentali: success, info, warning e danger
1065
873
  */
1066
- class ExportService {
874
+ class MessageService {
875
+ /**
876
+ * Costruttore
877
+ *
878
+ * @ignore
879
+ */
880
+ constructor(injector, locProvider) {
881
+ this.injector = injector;
882
+ this.locProvider = locProvider;
883
+ /**
884
+ * Oggetto statico in supporto alla localizzazione
885
+ */
886
+ this.loc = {
887
+ 'Confirm': { 'en-US': "Confirm", 'it-IT': "Conferma", },
888
+ 'Cancel': { 'en-US': "Cancel", 'it-IT': "Annulla", },
889
+ 'Close': { 'en-US': "Close", 'it-IT': "Chiudi", },
890
+ 'Error': { 'en-US': "Error", 'it-IT': "Errore", },
891
+ 'Info': { 'en-US': "Info", 'it-IT': "Informazione", },
892
+ 'Success': { 'en-US': "Success", 'it-IT': "Successo", },
893
+ 'Warning': { 'en-US': "Warning", 'it-IT': "Attenzione", }
894
+ };
895
+ this.init();
896
+ }
897
+ get toastr() {
898
+ return this.injector.get(ToastrService);
899
+ }
900
+ init() {
901
+ return __awaiter(this, void 0, void 0, function* () {
902
+ let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
903
+ this.expiredSessionSwal = swal.mixin({
904
+ showCancelButton: false,
905
+ confirmButtonText: 'Login',
906
+ customClass: {
907
+ confirmButton: "btn btn-primary",
908
+ container: "app-wrap",
909
+ },
910
+ buttonsStyling: false,
911
+ reverseButtons: false,
912
+ allowOutsideClick: false,
913
+ icon: "warning"
914
+ });
915
+ this.successSwalWithCancel = swal.mixin({
916
+ title: this.loc["Success"][LOCALE],
917
+ customClass: {
918
+ confirmButton: "btn btn-primary",
919
+ cancelButton: "btn btn-secondary app-margin-right-10",
920
+ container: "app-wrap",
921
+ },
922
+ buttonsStyling: false,
923
+ reverseButtons: true,
924
+ showCancelButton: true,
925
+ confirmButtonText: this.loc["Confirm"][LOCALE],
926
+ cancelButtonText: this.loc["Cancel"][LOCALE],
927
+ icon: "success"
928
+ });
929
+ this.warningSwalWithCancel = swal.mixin({
930
+ title: this.loc["Warning"][LOCALE],
931
+ customClass: {
932
+ confirmButton: "btn btn-primary",
933
+ cancelButton: "btn btn-secondary app-margin-right-10",
934
+ container: "app-wrap",
935
+ },
936
+ buttonsStyling: false,
937
+ reverseButtons: true,
938
+ showCancelButton: true,
939
+ confirmButtonText: this.loc["Confirm"][LOCALE],
940
+ cancelButtonText: this.loc["Cancel"][LOCALE],
941
+ icon: "warning"
942
+ });
943
+ this.warningSwal = swal.mixin({
944
+ title: this.loc["Warning"][LOCALE],
945
+ customClass: {
946
+ confirmButton: "btn btn-primary",
947
+ container: "app-wrap",
948
+ },
949
+ buttonsStyling: false,
950
+ reverseButtons: true,
951
+ showCancelButton: false,
952
+ confirmButtonText: this.loc["Close"][LOCALE],
953
+ icon: "warning"
954
+ });
955
+ this.successSwal = swal.mixin({
956
+ title: this.loc["Success"][LOCALE],
957
+ customClass: {
958
+ confirmButton: "btn btn-primary",
959
+ container: "app-wrap",
960
+ },
961
+ buttonsStyling: false,
962
+ reverseButtons: true,
963
+ showCancelButton: false,
964
+ confirmButtonText: this.loc["Close"][LOCALE],
965
+ icon: "success"
966
+ });
967
+ this.errorSwal = swal.mixin({
968
+ title: this.loc["Error"][LOCALE],
969
+ customClass: {
970
+ confirmButton: "btn btn-primary",
971
+ container: "app-wrap",
972
+ },
973
+ buttonsStyling: false,
974
+ reverseButtons: true,
975
+ showCancelButton: false,
976
+ confirmButtonText: this.loc["Close"][LOCALE],
977
+ icon: "error"
978
+ });
979
+ this.infoSwal = swal.mixin({
980
+ title: this.loc["Info"][LOCALE],
981
+ customClass: {
982
+ confirmButton: "btn btn-primary",
983
+ container: "app-wrap",
984
+ },
985
+ buttonsStyling: false,
986
+ reverseButtons: true,
987
+ showCancelButton: false,
988
+ confirmButtonText: this.loc["Close"][LOCALE],
989
+ icon: "info"
990
+ });
991
+ });
992
+ }
1067
993
  /**
1068
- * Costruttore
994
+ * Presentazione di un semplice messaggio di successo
1069
995
  *
1070
- * @ignore
996
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
997
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
998
+ *
999
+ * @param {string} text Testo da mostrare
1000
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1071
1001
  */
1072
- constructor(dates) {
1073
- this.dates = dates;
1002
+ simpleSuccess(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1003
+ let tos = this.toastrOrSwal(secondaryNotificationType);
1004
+ if (tos == "swal")
1005
+ this.successSwal.fire("", text);
1006
+ else
1007
+ this.toastr.success(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1074
1008
  }
1075
1009
  /**
1076
- * Data una lista di oggetti genera gli header per l'esportazione e integra ogni oggetto con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1010
+ * Presentazione di un semplice messaggio di informazione
1077
1011
  *
1078
- * @param {any[]} objs Oggetti da esportare
1012
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1013
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1079
1014
  *
1080
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1015
+ * @param {string} text Testo da mostrare
1016
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1081
1017
  */
1082
- setupForExport(objs, columns = []) {
1083
- let headers = [];
1084
- let headersCache = {};
1085
- if (!objs || objs.length == 0)
1086
- return headers;
1087
- // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
1088
- // Gli header li raccolgo tutti poi faccio uan distinct in modo da esportare tutte le proprietà per bene
1089
- let columnSelectionDictionary = {};
1090
- if ((columns === null || columns === void 0 ? void 0 : columns.length) > 0)
1091
- for (let i = 0; i < (columns === null || columns === void 0 ? void 0 : columns.length); i++)
1092
- columnSelectionDictionary[columns[i]] = true;
1093
- for (let i = 0; i < objs.length; i++) {
1094
- let hds = this.parseAndGetHeaders(objs[i], columnSelectionDictionary);
1095
- // Aggiungo gli header facendo in modo di non aggiungerne mai due uguali per non dover fare una distinct dopo
1096
- // che costerebbe comunque risorse. Utilizzo un dizionario d'appoggio per lookup istantanei
1097
- for (let k = 0; k < hds.length; k++) {
1098
- if (!headersCache[hds[k].key]) {
1099
- headersCache[hds[k].key] = true;
1100
- headers.push(hds[k]);
1101
- }
1102
- }
1103
- }
1104
- if (!columns || columns.length == 0)
1105
- return headers.sort((a, b) => a.order - b.order);
1106
- else {
1107
- // Se mi arriva la lista di colonne non mi dà solo la visibilità, ma anche l'ordinamento
1108
- // le esporto di conseguenza
1109
- let orderedHeaders = [];
1110
- for (let i = 0; i < columns.length; i++) {
1111
- let thisId = columns[i];
1112
- for (let i = 0; i < headers.length; i++) {
1113
- if (headers[i].propKey == thisId) {
1114
- orderedHeaders.push(headers[i]);
1115
- break;
1116
- }
1117
- }
1118
- }
1119
- return orderedHeaders;
1120
- }
1018
+ simpleInfo(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1019
+ let tos = this.toastrOrSwal(secondaryNotificationType);
1020
+ if (tos == "swal")
1021
+ this.infoSwal.fire("", text);
1022
+ else
1023
+ this.toastr.info(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1121
1024
  }
1122
1025
  /**
1123
- * 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**
1026
+ * Presentazione di un semplice messaggio di errore
1124
1027
  *
1125
- * @param {GenericItem[]} objs Oggetti generici da esportare
1126
- * @param {CsvHeaders[]} columns Colonne richieste dall'esportazione
1028
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1029
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1127
1030
  *
1128
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1031
+ * @param {string} text Testo da mostrare
1032
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1129
1033
  */
1130
- setupForGenericExport(objs, columns) {
1131
- let headers = [];
1132
- if (!objs || objs.length == 0)
1133
- return headers;
1134
- // Devo per forza farlo per tutti gli oggetti dato che devo esporre le proprietà che mi servono da esportare
1135
- objs.forEach((obj, index) => {
1136
- if (index == 0)
1137
- headers = this.parseAndGetGenericHeaders(obj, columns);
1138
- else
1139
- this.parseAndGetGenericHeaders(obj, columns);
1140
- });
1141
- return headers;
1034
+ simpleError(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1035
+ let tos = this.toastrOrSwal(secondaryNotificationType);
1036
+ if (tos == "swal")
1037
+ this.errorSwal.fire("", text);
1038
+ else
1039
+ this.toastr.error(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1142
1040
  }
1143
1041
  /**
1144
- * Dato un oggetto generico genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1042
+ * Presentazione di un semplice messaggio di avviso
1145
1043
  *
1146
- * Metodo interno richiamato da **setupForGenericExport**
1044
+ * Se viene chiamato con le impostazioni di default e toastr è abilitato, viene mostrato al centro
1045
+ * Se viene chiamato con override su toastr vuol dire che è una notifica secondaria e appare in alto a destra
1147
1046
  *
1148
- * @param {GenericItem} obj Oggetto generico da esportare
1149
- * @param {CsvColumn[]} columns Colonne richieste dall'esportazione
1047
+ * @param {string} text Testo da mostrare
1048
+ * @param {"toastr" | "swal" | null} secondaryNotificationType Qualora sia una notifica secondaria, ne indica il tipo
1049
+ */
1050
+ simpleWarning(text, secondaryNotificationType = null, secondaryNotificationTimeout = null) {
1051
+ let tos = this.toastrOrSwal(secondaryNotificationType);
1052
+ if (tos == "swal")
1053
+ this.warningSwal.fire("", text);
1054
+ else
1055
+ this.toastr.warning(text, null, { positionClass: tos == "toastr" ? "toast-top-right" : "toast-top-center", timeOut: secondaryNotificationTimeout || (tos == "toastr" ? 0 : 5000), extendedTimeOut: tos == "toastr" ? 0 : 1000 });
1056
+ }
1057
+ /**
1058
+ * Ripulisce tutti i messaggi presenti in un dato momento sullo schermo
1059
+ */
1060
+ clearMessages() {
1061
+ this.toastr.clear();
1062
+ swal.close();
1063
+ }
1064
+ /**
1065
+ * Mostra un messaggio di avviso con richiesta di conferma
1150
1066
  *
1151
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1067
+ * @param {string} title Titolo del messaggio
1068
+ * @param {string} text Contenuto del messaggio
1069
+ *
1070
+ * @returns {Promise} Restituisce una Promise col risultato scelto dall'utente (conferma o no)
1152
1071
  */
1153
- parseAndGetGenericHeaders(obj, columns) {
1154
- if (!obj.properties)
1155
- return null;
1156
- var headers = [];
1157
- //Miracle incoming
1158
- columns.forEach(t => {
1159
- var propValue = obj.properties[t.key];
1160
- Object.defineProperty(obj, t.key + "_exp", { value: propValue, writable: false, enumerable: true });
1161
- headers.push({ label: t.label, key: t.key + "_exp", order: t.order, type: t.type, propKey: null });
1072
+ promiseWarningWithChoice(title, text) {
1073
+ return this.warningSwalWithCancel.fire(title, text);
1074
+ }
1075
+ /**
1076
+ * In base alla configurazione attuale e all'eventuale override per la chiamata del caso indica se bisogna utilizzare toastr o sweetalert
1077
+ *
1078
+ * @param {"toastr" | "swal" | null} providerOverride Override alla modalità configurata
1079
+ *
1080
+ * @returns {"toastr" | "swal"} Indicazione su che provider di messaggi di avviso debba essere utilizzato
1081
+ */
1082
+ toastrOrSwal(providerOverride) {
1083
+ if (providerOverride != null)
1084
+ return providerOverride;
1085
+ return "swal";
1086
+ }
1087
+ /**
1088
+ * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
1089
+ *
1090
+ * @param {string} title Titolo del messaggio
1091
+ * @param {string} text Contenuto del messaggio
1092
+ * @param {Function} onsuccess Callback da chimare su conferma
1093
+ * @param {Function} onerror Callback da chimare su errori
1094
+ */
1095
+ simpleWarningWithChoice(title, text, onsuccess = null, onerror = null) {
1096
+ this.warningSwalWithCancel.fire(title, text).then((result) => {
1097
+ if (result.value && onsuccess)
1098
+ onsuccess();
1099
+ else if (onerror)
1100
+ onerror();
1162
1101
  });
1163
- //Tirati fuori tutti gli header faccio sort sull'ordinamento
1164
- return headers.sort((a, b) => { return a.order - b.order; });
1165
1102
  }
1166
1103
  /**
1167
- * Dato un oggetto genera gli header per l'esportazione e lo integra con le proprietà esportabili dalla libreria **@ctrl/ngx-csv**
1104
+ * Mostra un messaggio di success con richiesta di conferma e gestisce il risultato chiamato i callback **onconfirm** o **onabort**
1168
1105
  *
1169
- * Metodo interno richiamato da **setupForExport**
1106
+ * @param {string} title Titolo del messaggio
1107
+ * @param {string} text Contenuto del messaggio
1108
+ * @param {Function} onconfirm Callback da chimare su conferma
1109
+ * @param {Function} onabort Callback da chimare su annullamento
1110
+ * @param {string} confirmtext Testo del pulsante di azione
1111
+ * @param {string} aborttext Testo del pulsante di annullamento
1112
+ */
1113
+ simpleSuccessWithChoice(title, text, onconfirm = null, onabort = null, confirmtext = "", aborttext = '') {
1114
+ var configuration = {
1115
+ title: title,
1116
+ html: text
1117
+ };
1118
+ if (confirmtext)
1119
+ configuration["confirmButtonText"] = confirmtext;
1120
+ if (aborttext)
1121
+ configuration["cancelButtonText"] = aborttext;
1122
+ this.successSwalWithCancel.fire(configuration).then((result) => {
1123
+ if (result.value && onconfirm)
1124
+ onconfirm();
1125
+ else if (onabort)
1126
+ onabort();
1127
+ });
1128
+ }
1129
+ /**
1130
+ * Mostra un messaggio di avviso con richiesta di conferma e gestisce il risultato chiamato i callback **onsuccess** o **onerror**
1170
1131
  *
1171
- * @param {any} obj Oggetto generico da esportare
1132
+ * @param {string} title Titolo del messaggio
1133
+ * @param {string} text Contenuto del messaggio
1134
+ */
1135
+ observableSimpleWarningWithChoice(title, text) {
1136
+ return of(this.warningSwalWithCancel.fire(title, text)).pipe(map(t => !!t.value));
1137
+ }
1138
+ /**
1139
+ * Mostra un messaggio di avviso che la sessione corrente è scaduta e propone all'utente di navigare al login. Qualora l'utente decidesse di farlo
1140
+ * verrà chiamata la funzione di callback **onnavigate
1172
1141
  *
1173
- * @returns {CsvHeaders[]} Header di esportazione già ordinati correttamente
1142
+ * @param {string} title Titolo del messaggio
1143
+ * @param {string} text Contenuto del messaggio
1144
+ * @param {Function} onnavigate Callback da chimare su navigazione in corso
1174
1145
  */
1175
- parseAndGetHeaders(obj, columnsSelection) {
1176
- var headers = [];
1177
- // Miracle incoming
1178
- let exportProps = obj[exportList] || [];
1179
- if (exportProps.length == 0)
1180
- console.warn("[@esfaenza/extensions] Nessuna colonna configurata da esportare!");
1181
- for (let i = 0; i < exportProps.length; i++) {
1182
- let prop = exportProps[i];
1183
- let propBase = "";
1184
- let toCall;
1185
- if (prop.endsWith(listCsvHdrPrefix)) {
1186
- propBase = prop.replace(listCsvHdrPrefix, '');
1187
- toCall = this.parseList.bind(this);
1188
- }
1189
- else if (prop.endsWith(dictionaryCsvHdrPrefix)) {
1190
- toCall = this.parseDictionary.bind(this);
1191
- propBase = prop.replace(dictionaryCsvHdrPrefix, '');
1192
- }
1193
- else if (prop.endsWith(csvVisPrefix)) {
1194
- propBase = prop.replace(csvVisPrefix, '');
1195
- if (typeof obj[propBase + csvValueNavigator] !== "undefined")
1196
- toCall = this.parseObject.bind(this);
1197
- else
1198
- toCall = this.parseProperty.bind(this);
1199
- }
1200
- if (toCall)
1201
- toCall(obj, propBase, headers, columnsSelection);
1146
+ expiredSessionMessage(title, text, onnavigate = null) {
1147
+ this.expiredSessionSwal.fire(title, text).then((result) => {
1148
+ if (result.value && onnavigate)
1149
+ onnavigate();
1150
+ });
1151
+ }
1152
+ /**
1153
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **CallResult**
1154
+ *
1155
+ * @param {CallResult} response Risposta ricevuta dal server
1156
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
1157
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1158
+ * @param {Function} postSuccess Callback da chimare in caso di successo
1159
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
1160
+ */
1161
+ manageCallResultResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1162
+ if (response.success) {
1163
+ if (response.haswarning)
1164
+ this.simpleWarning(response.warning);
1165
+ else if (successMsg)
1166
+ this.simpleSuccess(successMsg);
1167
+ if (postSuccess)
1168
+ postSuccess();
1169
+ }
1170
+ else {
1171
+ this.simpleError((errorMsg ? errorMsg + ": " : "") + response.haserror ? response.error : '[NO ERR.]');
1172
+ if (postFailure)
1173
+ postFailure();
1202
1174
  }
1203
- return headers;
1204
1175
  }
1205
1176
  /**
1206
- * Setup per l'esportazione di una singola proprietà.
1207
- * Viene generato l'header e la proprietà relativa al valore formattato o no
1177
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **string**, considerando che:
1208
1178
  *
1209
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1210
- * @param {string} prop Proprietà da esportare
1211
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1179
+ * Stringa vuota --> Tutto bene
1180
+ *
1181
+ * Stringa piena --> Questo è il messaggio d'errore per cui la chiamata è fallita
1182
+ *
1183
+ * @param {string} response Risposta ricevuta dal server
1184
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
1185
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1186
+ * @param {Function} postSuccess Callback da chimare in caso di successo
1187
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
1212
1188
  */
1213
- parseProperty(obj, prop, headers, columnsSelection) {
1214
- let toEmit = obj[prop + csvVisPrefix];
1215
- let format = obj[prop + csvFormatPrefix];
1216
- let propKey = obj[prop + csvPropKey];
1217
- if (propKey && !columnsSelection[propKey] && Object.keys(columnsSelection).length > 0) {
1218
- console.log("[@esfaenza/extensions] Colonna da non esportare: " + propKey);
1219
- return;
1189
+ manageStringResponse(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1190
+ if (!response) {
1191
+ if (successMsg)
1192
+ this.simpleSuccess(successMsg);
1193
+ if (postSuccess)
1194
+ postSuccess();
1220
1195
  }
1221
- let lbl = obj[prop + csvHdrPrefix];
1222
- let order = obj[prop + csvOrdPrefix];
1223
- if (toEmit && lbl !== "undefined") {
1224
- // Se non ho un formato esporto direttamente
1225
- if (!format) {
1226
- // Se è un formato data mi assicuro di non stampare mai una data 00:00:00 altrimenti in esportazione viene uno schifo
1227
- var val = obj[prop] ? this.dates.trimSeconds(obj[prop].toString()) : "";
1228
- Object.defineProperty(obj, prop + "_nofmt", { value: val, writable: false, enumerable: true });
1229
- headers.push({ label: lbl ? lbl : prop + "_nofmt", key: prop + "_nofmt", order: order, type: "string", propKey: propKey });
1230
- }
1231
- else {
1232
- // Caso formato numerico
1233
- if (format == "F") {
1234
- // Check considerando la possibilità di zeri
1235
- let val = obj[prop] != null ? obj[prop].toString() : "";
1236
- // Elimino tutte le virgole (indicatori di migliaia per la culture default en-US)
1237
- val = val.replace(/,/, "");
1238
- // Il singolo punto che c'è, se presente (separatore decimali) lo trasformo in virgola
1239
- let valConverted = val.replace(".", ",");
1240
- Object.defineProperty(obj, prop + "_fmt", { value: valConverted, writable: false, enumerable: true });
1241
- headers.push({ label: lbl ? lbl : prop + "_fmt", key: prop + "_fmt", order: order, type: "number", propKey: propKey });
1242
- }
1243
- else {
1244
- // Se ho un formato data trasformo in dayjs, formatto ed esporto
1245
- // Per la trasformazione in dayjs provo prima a passargli la stringa di netto, sperando la riconosca
1246
- // Se non funziona provo a definirgli la formattazione standard del metering per quel linguaggio
1247
- let val = this.dates.getFormatted(obj[prop], format.length <= 10, format.length > 16);
1248
- Object.defineProperty(obj, prop + "_fmt", { value: val !== null && val !== void 0 ? val : "", writable: false, enumerable: true });
1249
- headers.push({ label: lbl ? lbl : prop + "_fmt", key: prop + "_fmt", order: order, type: "date", propKey: propKey });
1250
- }
1251
- }
1196
+ else {
1197
+ if (errorMsg)
1198
+ this.simpleError(errorMsg + ": " + response);
1199
+ if (postFailure)
1200
+ postFailure();
1252
1201
  }
1253
1202
  }
1254
1203
  /**
1255
- * Setup per l'esportazione di una singola proprietà da un oggetto.
1256
- * Viene generato l'header e la proprietà relativa al valore formattato o no.
1257
- *
1258
- * Per ottenere il valore e l'header della proprietà vengono utilizzati i navigatori auto-generati nel decoratore **ExportAs**
1204
+ * Metodo helper per gestire in maniera standardizzata una risposta di tipo **boolean**
1259
1205
  *
1260
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1261
- * @param {string} prop Proprietà da esportare
1262
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1206
+ * @param {string} response Risposta ricevuta dal server
1207
+ * @param {string} successMsg Messaggio da visualizzare in caso di successo
1208
+ * @param {string} errorMsg Messaggio da visualizzare in caso di fallimento
1209
+ * @param {Function} postSuccess Callback da chimare in caso di successo
1210
+ * @param {Function} postFailure Callback da chimare in caso di fallimento
1263
1211
  */
1264
- parseObject(obj, prop, headers) {
1265
- //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
1266
- let valuenavigator = obj[prop + csvValueNavigator];
1267
- //Es. di valuenavigator obj.subobj.subsubobj.property
1268
- let jmps = valuenavigator.split(".");
1269
- //Mi clono l'oggetto originale per non uccidergli i riferimenti
1270
- let clone = JSON.parse(JSON.stringify(obj));
1271
- //Salto ricorsivamente su me stesso per arrivare alla proprietà
1272
- //Salto 1 > diventa obj
1273
- //Salto 2 > diventa obj.subobj
1274
- //ecc...
1275
- jmps.forEach(pp => { clone = clone[pp]; });
1276
- //Valore finale :D
1277
- let value = clone;
1278
- let lbl = obj[prop + csvHdrPrefix];
1279
- let order = obj[prop + csvOrdPrefix];
1280
- //Se per questa proprietà ho un formato lo applico
1281
- let format = obj[prop + csvFormatPrefix];
1282
- let type = "string";
1283
- if (format == "F") {
1284
- let val = value.toString();
1285
- val = val.replace(/,/, "");
1286
- value = val.replace(".", ",");
1287
- type = "number";
1212
+ manageStringResponseBool(response, successMsg, errorMsg, postSuccess = null, postFailure = null) {
1213
+ if (response) {
1214
+ if (successMsg)
1215
+ this.simpleSuccess(successMsg);
1216
+ if (postSuccess)
1217
+ postSuccess();
1288
1218
  }
1289
- else if (format) {
1290
- value = this.dates.getFormatted(value, format.length <= 10, format.length > 16);
1291
- type = "date";
1219
+ else {
1220
+ if (errorMsg)
1221
+ this.simpleError(errorMsg);
1222
+ if (postFailure)
1223
+ postFailure();
1292
1224
  }
1293
- Object.defineProperty(obj, prop, { value: value !== null && value !== void 0 ? value : "", writable: false, enumerable: true });
1294
- headers.push({ label: lbl ? lbl : prop, key: prop, order: order, type: type, propKey: null });
1225
+ }
1226
+ }
1227
+ MessageService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, deps: [{ token: Injector }, { token: i1.BaseLocalization, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1228
+ MessageService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, providedIn: "root" });
1229
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: MessageService, decorators: [{
1230
+ type: Injectable,
1231
+ args: [{ providedIn: "root" }]
1232
+ }], ctorParameters: function () {
1233
+ return [{ type: i0.Injector, decorators: [{
1234
+ type: Inject,
1235
+ args: [Injector]
1236
+ }] }, { type: i1.BaseLocalization, decorators: [{
1237
+ type: Optional
1238
+ }] }];
1239
+ } });
1240
+
1241
+ /**
1242
+ * Service che fornisce un accesso base in lettura/scrittura sulla clipboard
1243
+ */
1244
+ class ClipboardService {
1245
+ /**
1246
+ * Costruttore
1247
+ *
1248
+ * @ignore
1249
+ */
1250
+ constructor(msgService, locProvider) {
1251
+ this.msgService = msgService;
1252
+ this.locProvider = locProvider;
1253
+ /**
1254
+ * Oggetto statico di localizzazione per i messaggi di questa Service
1255
+ */
1256
+ this.loc = {
1257
+ "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation": {
1258
+ 'en-US': "Unfortunately Firefox doesn't yet support direct Clipboard access if not via extensions, Please use Chrome to do this operation",
1259
+ 'it-IT': "Mi dispiace ma Firefox non supporta l'accesso diretto alla Clipboard, se non attraverso le estensioni. Si prega di usare Chrome"
1260
+ },
1261
+ "Generic error during 'copy' command execution": {
1262
+ 'en-US': "Generic error during 'copy' command execution",
1263
+ 'it-IT': "Errore generico durante l'esecuzione del comando 'copy'"
1264
+ },
1265
+ "Error during Clipboard content read operation": {
1266
+ 'en-US': "Error during Clipboard content read operation",
1267
+ 'it-IT': "Errore nella lettura del contenuto della Clipboard"
1268
+ },
1269
+ "Error during Clipboard content copy operation": {
1270
+ 'en-US': "Error during Clipboard content copy operation",
1271
+ 'it-IT': "Errore nella scrittura del contenuto nella Clipboard"
1272
+ },
1273
+ "Please insert your clipboard content": {
1274
+ 'en-US': "Please insert your clipboard content",
1275
+ 'it-IT': "Si prega di incollare il contenuto della Clipboard"
1276
+ },
1277
+ "User input required": {
1278
+ 'en-US': "User input required",
1279
+ 'it-IT': "Richiesto Input utente"
1280
+ },
1281
+ "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation": {
1282
+ 'en-US': "Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation",
1283
+ 'it-IT': "Il browser corrente non supporta la lettura diretta dei dati della Clipboard, si prega di effettuare un'incolla (CTRL + V) nella casella di testo e confermare l'operazione"
1284
+ },
1285
+ "Confirm": {
1286
+ 'en-US': "Confirm",
1287
+ 'it-IT': "Conferma"
1288
+ },
1289
+ "Cancel": {
1290
+ 'en-US': "Cancel",
1291
+ 'it-IT': "Annulla"
1292
+ },
1293
+ };
1294
+ }
1295
+ /**
1296
+ * Prende il valore della clipboard.
1297
+ * Si può specificare se ci si aspetta una lista o una matrice di valori in modo da ricevere già un risultato utilizzabile
1298
+ *
1299
+ * @param {'array' | 'matrix'} style Stile dell'output desiderato, se array o matrice
1300
+ * @param {Function} valueFoundCallback Callback che questa funzione chiamerà una volta ottenuto i valori richiesti dalla clipboard
1301
+ */
1302
+ getClipboard(style, valueFoundCallback) {
1303
+ return __awaiter(this, void 0, void 0, function* () {
1304
+ let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
1305
+ if (navigator.userAgent.indexOf("Firefox") != -1) {
1306
+ swal.fire({
1307
+ title: this.loc["User input required"][LOCALE],
1308
+ text: this.loc["Your current browser does not support reading from the clipboard directly. Please paste your clipboard's content in this Input field and confirm the operation"][LOCALE],
1309
+ input: 'textarea',
1310
+ icon: "warning",
1311
+ confirmButtonText: this.loc["Confirm"][LOCALE],
1312
+ cancelButtonText: this.loc["Cancel"][LOCALE],
1313
+ showCancelButton: true,
1314
+ customClass: {
1315
+ confirmButton: "btn btn-primary",
1316
+ cancelButton: "btn btn-secondary app-margin-right-15",
1317
+ container: "app-wrap",
1318
+ },
1319
+ reverseButtons: true,
1320
+ allowOutsideClick: false,
1321
+ inputValidator: (value) => {
1322
+ if (!value)
1323
+ return this.loc["Please insert your clipboard content"][LOCALE];
1324
+ }
1325
+ }).then(t => {
1326
+ if (t.isConfirmed) {
1327
+ console.log("[@esfaenza/extensions] Retrieving input data from user input");
1328
+ this.doClipboardDataGet(t.value, style, valueFoundCallback);
1329
+ }
1330
+ });
1331
+ return;
1332
+ }
1333
+ if (window.clipboardData) {
1334
+ console.log("[@esfaenza/extensions] Found clipboardData");
1335
+ let data = window.clipboardData.getData("Text");
1336
+ this.doClipboardDataGet(data, style, valueFoundCallback);
1337
+ }
1338
+ else if (window.navigator.clipboard) {
1339
+ console.log("[@esfaenza/extensions] Found navigator clipboard");
1340
+ window.navigator.permissions.query({ name: 'clipboard-read' }).then(result => {
1341
+ if (!(result.state === 'granted' || result.state === 'prompt')) {
1342
+ console.error("[@esfaenza/extensions] Clipboard permission not granted");
1343
+ if (valueFoundCallback)
1344
+ valueFoundCallback([]);
1345
+ return;
1346
+ }
1347
+ console.log("[@esfaenza/extensions] Clipboard permission granted, retrieving values");
1348
+ window.navigator.clipboard.readText()
1349
+ .then((t) => this.doClipboardDataGet(t, style, valueFoundCallback))
1350
+ .catch((err) => this.msgService.simpleError(this.loc["Error during Clipboard content read operation"][LOCALE] + ": " + err));
1351
+ });
1352
+ }
1353
+ });
1354
+ }
1355
+ /** @ignore */
1356
+ doClipboardDataGet(clipboardText, style, valueFoundCallback) {
1357
+ console.log("[@esfaenza/extensions] Retrieved clipboard values: " + clipboardText);
1358
+ let value = style == "array" ? this.getClipboardLines(clipboardText) :
1359
+ style == "matrix" ? this.getClipboardMatrix(clipboardText) : [];
1360
+ console.log(`[@esfaenza/extensions] Adapted for ${style}: ${JSON.stringify(value)}`);
1361
+ if (valueFoundCallback)
1362
+ valueFoundCallback(value);
1295
1363
  }
1296
1364
  /**
1297
- * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1298
- *
1299
- * => Recupero il valore utilizzando i navigatori
1300
- *
1301
- * => Recupero l'header utilizzando i navigatori
1302
- *
1303
- * => Con il valore ci creo la property
1365
+ * Ottiene il contenuto della clipboard diviso per righe (separate da newline)
1304
1366
  *
1305
- * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
1367
+ * @param {string} data contenuto letto dalla clipboard
1306
1368
  *
1307
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1308
- * @param {string} prop Proprietà da esportare
1309
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1369
+ * @returns {string[]} Array contenente il testo preso dalla clipboard diviso per riga
1310
1370
  */
1311
- parseList(obj, prop, headers) {
1312
- let headernavigator = obj[prop + listCsvHdrPrefix];
1313
- let valuenavigator = obj[prop + listCsvValPrefix];
1314
- let valueformat = obj[prop + listCsvValFormat];
1315
- let order = obj[prop + csvOrdPrefix];
1316
- var jumps, tmpRes;
1317
- var objs = obj[prop];
1318
- for (let idx = 0; idx < objs.length; idx++) {
1319
- let listitem = objs[idx];
1320
- var headersplit = headernavigator.split(" ");
1321
- var header = "";
1322
- // Per l'header si considera a se stante ogni pezzo separato da spazio per fare le concatenazioni
1323
- headersplit.forEach(pr => {
1324
- jumps = pr.split(".");
1325
- tmpRes = JSON.parse(JSON.stringify(listitem));
1326
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1327
- if (!header)
1328
- header = tmpRes;
1329
- else
1330
- header += " " + tmpRes;
1331
- });
1332
- jumps = valuenavigator.split(".");
1333
- tmpRes = JSON.parse(JSON.stringify(listitem));
1334
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1335
- let value = tmpRes;
1336
- let type = "string";
1337
- if (valueformat == "F") {
1338
- let val = value != null ? value.toString() : "";
1339
- val = val.replace(/,/, "");
1340
- value = val.replace(".", ",");
1341
- type = "number";
1342
- }
1343
- else if (valueformat) {
1344
- value = this.dates.getFormatted(obj[prop], valueformat.length <= 10, valueformat.length > 16);
1345
- type = "date";
1346
- }
1347
- Object.defineProperty(obj, prop + idx, { value: value !== null && value !== void 0 ? value : "", writable: false });
1348
- headers.push({ label: header, key: prop + idx, order: order + idx, type: type, propKey: null });
1349
- }
1371
+ getClipboardLines(data) {
1372
+ let trimmedData = data.trim();
1373
+ if (!trimmedData.includes("\r\n") && trimmedData.includes("\n"))
1374
+ return trimmedData.split("\n");
1375
+ return trimmedData.split("\r\n");
1350
1376
  }
1351
1377
  /**
1352
- * Setup per l'esportazione di una lista di valori pivottati dinamicamente:
1353
- *
1354
- * => Recupero il valore utilizzando i navigatori
1355
- *
1356
- * => Recupero l'header utilizzando i navigatori
1357
- *
1358
- * => Con il valore ci creo la property
1378
+ * Ottiene il contenuto della clipboard diviso per righe (separate da newline) e colonne (separate da tab)
1359
1379
  *
1360
- * => Con l'header e il riferimento alla property appena creata creo un record negli header da esportare
1380
+ * @param {string} data contenuto letto dalla clipboard
1361
1381
  *
1362
- * @param {any} obj Oggetto di cui esportare la proprietà **prop**
1363
- * @param {string} prop Proprietà da esportare
1364
- * @param {CsvHeaders} headers Contenitore degli header, verrà riempito da questa funzione
1382
+ * @returns {string[][]} Matrice contenente il testo preso dalla clipboard diviso per riga e colonna
1365
1383
  */
1366
- parseDictionary(obj, prop, headers) {
1367
- let headernavigator = obj[prop + dictionaryCsvHdrPrefix];
1368
- let valuenavigator = obj[prop + dictionaryCsvValPrefix];
1369
- let order = obj[prop + csvOrdPrefix];
1370
- var jumps, tmpRes;
1371
- var objs = obj[prop];
1372
- for (let idx = 0; idx < objs.length; idx++) {
1373
- let listitem = objs[idx];
1374
- var headersplit = headernavigator.split(" ");
1375
- var header = "";
1376
- headersplit.forEach(pr => {
1377
- jumps = pr.split(".");
1378
- tmpRes = JSON.parse(JSON.stringify(listitem));
1379
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1380
- if (!header)
1381
- header = tmpRes;
1382
- else
1383
- header += " " + tmpRes;
1384
- });
1385
- var valuesplit = valuenavigator.split(",");
1386
- valuesplit.forEach((t, idxinternal) => {
1387
- var navig = t.split("-")[1];
1388
- var desc = t.split("-")[0];
1389
- jumps = navig.split(".");
1390
- tmpRes = JSON.parse(JSON.stringify(listitem));
1391
- jumps.forEach(pp => { tmpRes = tmpRes[pp]; });
1392
- let value = tmpRes;
1393
- let propname = prop + idx.toString() + idxinternal.toString();
1394
- Object.defineProperty(obj, propname, { value: value !== null && value !== void 0 ? value : "", writable: false });
1395
- headers.push({ label: header + " " + desc, key: propname, order: order + idx, type: 'string', propKey: null });
1396
- });
1397
- }
1384
+ getClipboardMatrix(data) {
1385
+ var ret = [];
1386
+ var rows = !data.includes("\r\n") && data.includes("\n") ? data.split("\n") : data.split("\r\n");
1387
+ // A quanto pare ogni valore è separato da un \t... spero che sia uno standard di quando si copia da excel altrimenti ciao
1388
+ for (let i = 0; i < rows.length; i++)
1389
+ ret.push(rows[i].split('\t').map(t => t.trim()));
1390
+ return ret;
1398
1391
  }
1399
1392
  /**
1400
- * Metodo che si occupa della deserializzazione degli oggetti da esportare. Messo a livello di libreria in modo che qualora ci fosse da cambiare libreria
1401
- * tutte le manutenzioni siano concentrate qui
1402
- *
1403
- * @param {any[]} items Oggetti da deserializzare
1404
- * @param {any} type Tipo da usare come prototipo per la deserializzazione
1393
+ * Metodo che copia un testo all'interno della clipboard
1405
1394
  *
1406
- * @returns {any} Oggetti deserializzati
1395
+ * @param {string} text Testo da inserire nella clipboard
1407
1396
  */
1408
- deserializeForExport(items, type) {
1409
- return Deserialize(items, type);
1397
+ copyTextToClipboard(text) {
1398
+ return __awaiter(this, void 0, void 0, function* () {
1399
+ let LOCALE = this.locProvider ? yield this.locProvider.Locale.pipe(first()).toPromise() : 'it-IT';
1400
+ var textArea = document.createElement("textarea");
1401
+ //
1402
+ // *** This styling is an extra step which is likely not required. ***
1403
+ //
1404
+ // Why is it here? To ensure:
1405
+ // 1. the element is able to have focus and selection.
1406
+ // 2. if element was to flash render it has minimal visual impact.
1407
+ // 3. less flakyness with selection and copying which **might** occur if
1408
+ // the textarea element is not visible.
1409
+ //
1410
+ // The likelihood is the element won't even render, not even a flash,
1411
+ // so some of these are just precautions. However in IE the element
1412
+ // is visible whilst the popup box asking the user for permission for
1413
+ // the web page to copy to the clipboard.
1414
+ //
1415
+ // Place in top-left corner of screen regardless of scroll position.
1416
+ textArea.style.position = "fixed";
1417
+ textArea.style.top = "0";
1418
+ textArea.style.left = "0";
1419
+ // Ensure it has a small width and height. Setting to 1px / 1em
1420
+ // doesn't work as this gives a negative w/h on some browsers.
1421
+ textArea.style.width = "2em";
1422
+ textArea.style.height = "2em";
1423
+ // We don't need padding, reducing the size if it does flash render.
1424
+ textArea.style.padding = "0";
1425
+ // Clean up any borders.
1426
+ textArea.style.border = "none";
1427
+ textArea.style.outline = "none";
1428
+ textArea.style.boxShadow = "none";
1429
+ // Avoid flash of white box if rendered for any reason.
1430
+ textArea.style.background = "transparent";
1431
+ textArea.value = text;
1432
+ document.body.appendChild(textArea);
1433
+ textArea.focus();
1434
+ textArea.select();
1435
+ try {
1436
+ var successful = document.execCommand("copy");
1437
+ if (!successful)
1438
+ this.msgService.simpleError(this.loc["Generic error during 'copy' command execution"][LOCALE]);
1439
+ }
1440
+ catch (err) {
1441
+ this.msgService.simpleError(this.loc["Error during Clipboard content copy operation"][LOCALE] + ": " + err);
1442
+ }
1443
+ document.body.removeChild(textArea);
1444
+ });
1410
1445
  }
1411
1446
  }
1412
- ExportService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, deps: [{ token: DateService }], target: i0.ɵɵFactoryTarget.Injectable });
1413
- ExportService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService });
1414
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ExportService, decorators: [{
1415
- type: Injectable
1416
- }], ctorParameters: function () { return [{ type: DateService }]; } });
1447
+ ClipboardService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, deps: [{ token: MessageService }, { token: i1.BaseLocalization, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
1448
+ ClipboardService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, providedIn: "root" });
1449
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: ClipboardService, decorators: [{
1450
+ type: Injectable,
1451
+ args: [{ providedIn: "root" }]
1452
+ }], ctorParameters: function () {
1453
+ return [{ type: MessageService }, { type: i1.BaseLocalization, decorators: [{
1454
+ type: Optional
1455
+ }] }];
1456
+ } });
1417
1457
 
1418
1458
  // Angular
1419
1459
  /**
@@ -1717,9 +1757,10 @@ class HashingService {
1717
1757
  }
1718
1758
  }
1719
1759
  HashingService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1720
- HashingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService });
1760
+ HashingService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, providedIn: "root" });
1721
1761
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: HashingService, decorators: [{
1722
- type: Injectable
1762
+ type: Injectable,
1763
+ args: [{ providedIn: "root" }]
1723
1764
  }] });
1724
1765
 
1725
1766
  /**
@@ -1968,11 +2009,37 @@ class UtilityService {
1968
2009
  }
1969
2010
  }
1970
2011
  UtilityService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
1971
- UtilityService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService });
2012
+ UtilityService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, providedIn: "root" });
1972
2013
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: UtilityService, decorators: [{
1973
- type: Injectable
2014
+ type: Injectable,
2015
+ args: [{ providedIn: "root" }]
1974
2016
  }] });
1975
2017
 
2018
+ /**
2019
+ * Classe che rappresenta una risposta ricevuta da un Backend
2020
+ */
2021
+ class CallResult {
2022
+ }
2023
+
2024
+ /**
2025
+ * Header per il file CSV che sta venendo generato
2026
+ */
2027
+ class CsvHeaders {
2028
+ }
2029
+
2030
+ /**
2031
+ * Rappresentazione di un oggetto generico
2032
+ */
2033
+ class GenericItem {
2034
+ }
2035
+
2036
+ /** Enumeratore dei tipi di messaggio che i moduli esterni possono contattare sull'applicazione principale */
2037
+ var InboundMessageTypes;
2038
+ (function (InboundMessageTypes) {
2039
+ /** Evento di navigazione */
2040
+ InboundMessageTypes[InboundMessageTypes["Navigation"] = 0] = "Navigation";
2041
+ })(InboundMessageTypes || (InboundMessageTypes = {}));
2042
+
1976
2043
  /** Classe che rappresenta un generico messaggio scambiato fra applicazione e moduli */
1977
2044
  class InterComMessage {
1978
2045
  /**
@@ -2029,77 +2096,12 @@ class InterComService {
2029
2096
  }
2030
2097
  }
2031
2098
  InterComService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: InterComService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
2032
- InterComService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: InterComService });
2099
+ InterComService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: InterComService, providedIn: "root" });
2033
2100
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: InterComService, decorators: [{
2034
- type: Injectable
2035
- }] });
2036
-
2037
- // Angular
2038
- /**
2039
- * Modulo di estensione che registra autonomamente **TUTTI** i servizi di estensione:
2040
- * ClipboardService,
2041
- * DateService,
2042
- * ExportService,
2043
- * HashingService,
2044
- * MessageService,
2045
- * UtilityService
2046
- * InterComService
2047
- *
2048
- * con eventuali provider che utilizzano
2049
- */
2050
- class FullExtensionsModule {
2051
- static forRoot(config) {
2052
- return {
2053
- ngModule: FullExtensionsModule,
2054
- providers: [
2055
- ClipboardService,
2056
- DateService,
2057
- ExportService,
2058
- HashingService,
2059
- MessageService,
2060
- UtilityService,
2061
- InterComService,
2062
- { provide: APPSEARCH_PREFIX, useValue: (config === null || config === void 0 ? void 0 : config.appsearch_prefix) || 'Hot' },
2063
- { provide: EXT_ALLOW_UTC, useValue: (config === null || config === void 0 ? void 0 : config.allow_utc) == null ? false : config === null || config === void 0 ? void 0 : config.allow_utc }
2064
- ]
2065
- };
2066
- }
2067
- }
2068
- FullExtensionsModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FullExtensionsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2069
- FullExtensionsModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "15.2.9", ngImport: i0, type: FullExtensionsModule });
2070
- FullExtensionsModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FullExtensionsModule, providers: [BaseLocalization] });
2071
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FullExtensionsModule, decorators: [{
2072
- type: NgModule,
2073
- args: [{
2074
- providers: [BaseLocalization]
2075
- }]
2101
+ type: Injectable,
2102
+ args: [{ providedIn: "root" }]
2076
2103
  }] });
2077
2104
 
2078
- /**
2079
- * Classe che rappresenta una risposta ricevuta da un Backend
2080
- */
2081
- class CallResult {
2082
- }
2083
-
2084
- /**
2085
- * Header per il file CSV che sta venendo generato
2086
- */
2087
- class CsvHeaders {
2088
- }
2089
-
2090
- /**
2091
- * Rappresentazione di un oggetto generico
2092
- */
2093
- class GenericItem {
2094
- }
2095
-
2096
- /** Enumeratore dei tipi di messaggio che i moduli esterni possono contattare sull'applicazione principale */
2097
- var InboundMessageTypes;
2098
- (function (InboundMessageTypes) {
2099
- /** Evento di navigazione */
2100
- InboundMessageTypes[InboundMessageTypes["Navigation"] = 0] = "Navigation";
2101
- })(InboundMessageTypes || (InboundMessageTypes = {}));
2102
-
2103
2105
  /*
2104
2106
  * Public API Surface of extensions
2105
2107
  */
@@ -2108,5 +2110,5 @@ var InboundMessageTypes;
2108
2110
  * Generated bundle index. Do not edit.
2109
2111
  */
2110
2112
 
2111
- export { APPSEARCH_PREFIX, CallResult, ClipboardService, CsvHeaders, DateService, EXT_ALLOW_UTC, Export, ExportAs, ExportDictionary, ExportList, ExportService, ExtensionsModule, FullExtensionsModule, GenericItem, HashingService, InboundMessageTypes, InterComMessage, InterComService, MessageService, UtilityService };
2113
+ export { APPSEARCH_PREFIX, CallResult, ClipboardService, CsvHeaders, DateService, EXT_ALLOW_UTC, EXT_DEBUG_MODE, Export, ExportAs, ExportDictionary, ExportList, ExportService, ExtensionsModule, GenericItem, HashingService, InboundMessageTypes, InterComMessage, InterComService, LocDatePipe, MessageService, UtilityService };
2112
2114
  //# sourceMappingURL=esfaenza-extensions.mjs.map