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