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