@esfaenza/extensions 15.2.4 → 15.2.5

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