@esfaenza/es-table 11.2.19 → 11.2.22-beta2
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/bundles/esfaenza-es-table.umd.js +1883 -539
- package/bundles/esfaenza-es-table.umd.js.map +1 -1
- package/bundles/esfaenza-es-table.umd.min.js +2 -2
- package/bundles/esfaenza-es-table.umd.min.js.map +1 -1
- package/esfaenza-es-table.d.ts +5 -5
- package/esfaenza-es-table.metadata.json +1 -1
- package/esm2015/esfaenza-es-table.js +6 -6
- package/esm2015/lib/directives/es_td.directive.js +2 -4
- package/esm2015/lib/directives/es_th.directive.js +17 -8
- package/esm2015/lib/domain/externals/classes/CornerMenuOption.js +4 -0
- package/esm2015/lib/domain/externals/classes/EsTableColumnsDefinition.js +31 -0
- package/esm2015/lib/domain/externals/classes/EsTableOperationDefinition.js +22 -0
- package/esm2015/lib/domain/externals/classes/appsearch/AppOrdering.js +16 -0
- package/esm2015/lib/domain/externals/classes/appsearch/AppSearch.js +35 -0
- package/esm2015/lib/domain/externals/classes/appsearch/GenericItem.js +11 -0
- package/esm2015/lib/domain/externals/classes/appsearch/Group.js +17 -0
- package/esm2015/lib/domain/externals/classes/appsearch/GroupAggregation.js +16 -0
- package/esm2015/lib/domain/externals/classes/appsearch/GroupFilter.js +14 -0
- package/esm2015/lib/domain/externals/classes/appsearch/GroupOrAggregation.js +16 -0
- package/esm2015/lib/domain/externals/classes/appsearch/ItemsSelection.js +23 -0
- package/esm2015/lib/domain/externals/classes/report/ReportColumn.js +4 -0
- package/esm2015/lib/domain/externals/classes/report/ReportDefinition.js +4 -0
- package/esm2015/lib/domain/externals/classes/report/ReportOrder.js +4 -0
- package/esm2015/lib/domain/externals/classes/report/ReportParam.js +4 -0
- package/esm2015/lib/domain/externals/classes/report/ReportResult.js +4 -0
- package/esm2015/lib/domain/externals/classes/report/ReportRow.js +4 -0
- package/esm2015/lib/domain/externals/index.js +18 -0
- package/esm2015/lib/domain/index.js +3 -16
- package/esm2015/lib/domain/internals/classes/CacheTriptic.js +16 -0
- package/esm2015/lib/domain/internals/classes/EsTableColumn.js +24 -0
- package/esm2015/lib/domain/internals/classes/GroupPager.js +21 -0
- package/esm2015/lib/domain/internals/classes/GroupRouteFragment.js +17 -0
- package/esm2015/lib/domain/internals/classes/ThAggregation.js +16 -0
- package/esm2015/lib/domain/internals/index.js +6 -0
- package/esm2015/lib/es-table.module.js +9 -4
- package/esm2015/lib/es_table.component.js +1498 -323
- package/esm2015/lib/es_table.component.loc.js +4 -7
- package/esm2015/lib/es_td.component.js +9 -20
- package/esm2015/lib/es_th.component.js +16 -44
- package/esm2015/lib/models/EsTableDefaultable.js +4 -0
- package/esm2015/lib/models/EsTableModuleConfig.js +2 -4
- package/esm2015/lib/pager/table_pager.component.js +48 -26
- package/esm2015/lib/pager/table_pager.component.loc.js +5 -7
- package/esm2015/lib/tokens.js +6 -4
- package/esm2015/public-api.js +3 -2
- package/fesm2015/esfaenza-es-table.js +1764 -510
- package/fesm2015/esfaenza-es-table.js.map +1 -1
- package/lib/directives/es_td.directive.d.ts +1 -3
- package/lib/directives/es_th.directive.d.ts +14 -7
- package/lib/domain/externals/classes/CornerMenuOption.d.ts +7 -0
- package/lib/domain/{classes → externals/classes}/EsTableColumnsDefinition.d.ts +2 -6
- package/lib/domain/{classes → externals/classes}/EsTableOperationDefinition.d.ts +1 -3
- package/lib/domain/{classes → externals/classes/appsearch}/AppOrdering.d.ts +0 -0
- package/lib/domain/externals/classes/appsearch/AppSearch.d.ts +67 -0
- package/lib/domain/externals/classes/appsearch/GenericItem.d.ts +13 -0
- package/lib/domain/externals/classes/appsearch/Group.d.ts +17 -0
- package/lib/domain/externals/classes/appsearch/GroupAggregation.d.ts +14 -0
- package/lib/domain/externals/classes/appsearch/GroupFilter.d.ts +12 -0
- package/lib/domain/externals/classes/appsearch/GroupOrAggregation.d.ts +14 -0
- package/lib/domain/externals/classes/appsearch/ItemsSelection.d.ts +22 -0
- package/lib/domain/externals/classes/report/ReportColumn.d.ts +15 -0
- package/lib/domain/externals/classes/report/ReportDefinition.d.ts +24 -0
- package/lib/domain/externals/classes/report/ReportOrder.d.ts +7 -0
- package/lib/domain/externals/classes/report/ReportParam.d.ts +40 -0
- package/lib/domain/externals/classes/report/ReportResult.d.ts +12 -0
- package/lib/domain/externals/classes/report/ReportRow.d.ts +5 -0
- package/lib/domain/externals/index.d.ts +17 -0
- package/lib/domain/index.d.ts +2 -15
- package/lib/domain/internals/classes/CacheTriptic.d.ts +14 -0
- package/lib/domain/{classes → internals/classes}/EsTableColumn.d.ts +6 -4
- package/lib/domain/internals/classes/GroupPager.d.ts +22 -0
- package/lib/domain/internals/classes/GroupRouteFragment.d.ts +15 -0
- package/lib/domain/internals/classes/ThAggregation.d.ts +14 -0
- package/lib/domain/internals/index.d.ts +5 -0
- package/lib/es_table.component.d.ts +349 -52
- package/lib/es_table.component.loc.d.ts +2 -6
- package/lib/es_td.component.d.ts +13 -36
- package/lib/es_th.component.d.ts +21 -61
- package/lib/models/EsTableDefaultable.d.ts +19 -0
- package/lib/models/EsTableModuleConfig.d.ts +8 -7
- package/lib/pager/table_pager.component.d.ts +27 -30
- package/lib/pager/table_pager.component.loc.d.ts +2 -6
- package/lib/tokens.d.ts +6 -3
- package/package.json +2 -1
- package/public-api.d.ts +2 -1
- package/esm2015/lib/domain/classes/AppOrdering.js +0 -16
- package/esm2015/lib/domain/classes/AppSearch.js +0 -56
- package/esm2015/lib/domain/classes/CornerMenuOption.js +0 -6
- package/esm2015/lib/domain/classes/EsTableColumn.js +0 -22
- package/esm2015/lib/domain/classes/EsTableColumnsDefinition.js +0 -33
- package/esm2015/lib/domain/classes/EsTableOperationDefinition.js +0 -24
- package/esm2015/lib/domain/classes/GenericItem.js +0 -15
- package/esm2015/lib/domain/classes/IAppSearch.js +0 -2
- package/esm2015/lib/domain/classes/ItemsSelection.js +0 -25
- package/esm2015/lib/domain/classes/ReportColumn.js +0 -6
- package/esm2015/lib/domain/classes/ReportDefinition.js +0 -6
- package/esm2015/lib/domain/classes/ReportOrder.js +0 -6
- package/esm2015/lib/domain/classes/ReportParam.js +0 -6
- package/esm2015/lib/domain/classes/ReportResult.js +0 -6
- package/esm2015/lib/domain/classes/ReportRow.js +0 -6
- package/lib/domain/classes/AppSearch.d.ts +0 -110
- package/lib/domain/classes/CornerMenuOption.d.ts +0 -13
- package/lib/domain/classes/GenericItem.d.ts +0 -25
- package/lib/domain/classes/IAppSearch.d.ts +0 -67
- package/lib/domain/classes/ItemsSelection.d.ts +0 -27
- package/lib/domain/classes/ReportColumn.d.ts +0 -29
- package/lib/domain/classes/ReportDefinition.d.ts +0 -46
- package/lib/domain/classes/ReportOrder.d.ts +0 -13
- package/lib/domain/classes/ReportParam.d.ts +0 -76
- package/lib/domain/classes/ReportResult.d.ts +0 -22
- package/lib/domain/classes/ReportRow.d.ts +0 -9
|
@@ -7,6 +7,8 @@ import { PreferencesService } from '@esfaenza/preferences';
|
|
|
7
7
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
8
8
|
import { CommonModule } from '@angular/common';
|
|
9
9
|
import { RouterModule } from '@angular/router';
|
|
10
|
+
import { MatSelectModule } from '@angular/material/select';
|
|
11
|
+
import { MatInputModule } from '@angular/material/input';
|
|
10
12
|
import { ModalModule } from 'ngx-bootstrap/modal';
|
|
11
13
|
import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
|
|
12
14
|
import { CsvModule } from '@ctrl/ngx-csv';
|
|
@@ -61,32 +63,9 @@ class AppSearch {
|
|
|
61
63
|
this.column_ordering = [];
|
|
62
64
|
this.savedstate = false;
|
|
63
65
|
}
|
|
64
|
-
}
|
|
65
|
-
class Group {
|
|
66
|
-
constructor(column, value) {
|
|
67
|
-
this.column = column;
|
|
68
|
-
this.value = value;
|
|
69
|
-
this.aggregations = [];
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
class GroupAggregation {
|
|
73
|
-
}
|
|
74
|
-
class GroupFilter {
|
|
75
|
-
constructor(column, value) {
|
|
76
|
-
this.column = column;
|
|
77
|
-
this.value = value;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
class GroupOrAggregation {
|
|
81
|
-
constructor(column, aggregation) {
|
|
82
|
-
this.column = column;
|
|
83
|
-
this.aggregation = aggregation;
|
|
84
|
-
}
|
|
85
66
|
}
|
|
86
67
|
|
|
87
|
-
/**
|
|
88
|
-
* Classe che identifica una colonna. Utilizzata in modalità "Colonne dinamiche"
|
|
89
|
-
*/
|
|
68
|
+
/** Classe che identifica una colonna. Utilizzata in modalità "Colonne dinamiche" */
|
|
90
69
|
class EsTableColumnsDefinition {
|
|
91
70
|
/**
|
|
92
71
|
* Costruttore
|
|
@@ -117,66 +96,46 @@ class EsTableColumnsDefinition {
|
|
|
117
96
|
}
|
|
118
97
|
}
|
|
119
98
|
|
|
120
|
-
/**
|
|
121
|
-
* Classe che definisce un oggetto generico come lista di proprietà-valore
|
|
122
|
-
*/
|
|
99
|
+
/** Classe che definisce un oggetto generico come lista di proprietà-valore */
|
|
123
100
|
class GenericItem {
|
|
124
|
-
/**
|
|
125
|
-
* @ignore
|
|
126
|
-
*/
|
|
101
|
+
/** @ignore */
|
|
127
102
|
constructor() {
|
|
128
103
|
this._selected = false;
|
|
129
104
|
this._rowClass = null;
|
|
130
|
-
this.
|
|
105
|
+
this._hash = null;
|
|
131
106
|
this.properties = {};
|
|
132
107
|
}
|
|
133
108
|
}
|
|
134
109
|
|
|
135
|
-
/**
|
|
136
|
-
* Indica un'opzione cliccabile nel Corner Menù della tabella (il menù richiamabile dai 3 pallini verticli in alto a destra)
|
|
137
|
-
*/
|
|
110
|
+
/** Indica un'opzione cliccabile nel Corner Menù della tabella (il menù richiamabile dai 3 pallini verticli in alto a destra) */
|
|
138
111
|
class CornerMenuOption {
|
|
139
112
|
}
|
|
140
113
|
|
|
141
|
-
/**
|
|
142
|
-
* Definizione generica di un report che può o no disporre di paginazione/export e la cui richiesta è basata su uno o più parametri
|
|
143
|
-
*/
|
|
114
|
+
/** Definizione generica di un report che può o no disporre di paginazione/export e la cui richiesta è basata su uno o più parametri */
|
|
144
115
|
class ReportDefinition {
|
|
145
116
|
}
|
|
146
117
|
|
|
147
|
-
/**
|
|
148
|
-
* Classe che identifica una direttiva di ordinamento per un report
|
|
149
|
-
*/
|
|
118
|
+
/** Classe che identifica una direttiva di ordinamento per un report */
|
|
150
119
|
class ReportOrder {
|
|
151
120
|
}
|
|
152
121
|
|
|
153
|
-
/**
|
|
154
|
-
* Classe che rappresenta una colonna di un report
|
|
155
|
-
*/
|
|
122
|
+
/** Classe che rappresenta una colonna di un report */
|
|
156
123
|
class ReportColumn {
|
|
157
124
|
}
|
|
158
125
|
|
|
159
|
-
/**
|
|
160
|
-
* Classe che rappresenta una lista di oggetti generati da un report
|
|
161
|
-
*/
|
|
126
|
+
/** Classe che rappresenta una lista di oggetti generati da un report */
|
|
162
127
|
class ReportResult {
|
|
163
128
|
}
|
|
164
129
|
|
|
165
|
-
/**
|
|
166
|
-
* Classe che rappresenta i valori delle proprietà di un oggetto Report
|
|
167
|
-
*/
|
|
130
|
+
/** Classe che rappresenta i valori delle proprietà di un oggetto Report */
|
|
168
131
|
class ReportRow {
|
|
169
132
|
}
|
|
170
133
|
|
|
171
|
-
/**
|
|
172
|
-
* Classe che identifica un parametro generico per un report
|
|
173
|
-
*/
|
|
134
|
+
/** Classe che identifica un parametro generico per un report */
|
|
174
135
|
class ReportParam {
|
|
175
136
|
}
|
|
176
137
|
|
|
177
|
-
/**
|
|
178
|
-
* Indica operazioni dinamiche generiche che possono essere effettuate per riga. Appaiono come colonne extra sul lato sinistro della tabella
|
|
179
|
-
*/
|
|
138
|
+
/** Indica operazioni dinamiche generiche che possono essere effettuate per riga. Appaiono come colonne extra sul lato sinistro della tabella */
|
|
180
139
|
class EsTableOperationDefinition {
|
|
181
140
|
/**
|
|
182
141
|
* Costruttore
|
|
@@ -198,9 +157,109 @@ class EsTableOperationDefinition {
|
|
|
198
157
|
}
|
|
199
158
|
}
|
|
200
159
|
|
|
201
|
-
/**
|
|
202
|
-
|
|
203
|
-
|
|
160
|
+
/** Identifica una selezione applicabile agli oggetti presentati in una tabella */
|
|
161
|
+
class ItemsSelection {
|
|
162
|
+
/**
|
|
163
|
+
* Costruttore
|
|
164
|
+
*
|
|
165
|
+
* @param {T[]} selected Oggetti da considerare selezionati
|
|
166
|
+
*/
|
|
167
|
+
constructor(selected) {
|
|
168
|
+
/** Indica se tutti gli elementi sono da considerarsi selezionati (anche quelli di altre pagine) */
|
|
169
|
+
this.all = false;
|
|
170
|
+
/** Se **all** è **true**, indica gli elementi da escludere, altrimenti è insensato */
|
|
171
|
+
this.exclusions = [];
|
|
172
|
+
/** Se **all** è **true**, indica i gruppi da escludere, altrimenti è insensato */
|
|
173
|
+
this.group_exclusions = [];
|
|
174
|
+
this.count = selected.length;
|
|
175
|
+
this.items = selected;
|
|
176
|
+
this.all = false;
|
|
177
|
+
this.exclusions = [];
|
|
178
|
+
this.groups = [];
|
|
179
|
+
this.group_exclusions = [];
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Classe che rappresenta un Gruppo con le proprie aggregazioni */
|
|
184
|
+
class Group {
|
|
185
|
+
/**
|
|
186
|
+
* Costruttore
|
|
187
|
+
*
|
|
188
|
+
* @param {string} column ID della colonna raggruppata
|
|
189
|
+
* @param {number} count Numero di elementi raggruppati sotto questa colonna
|
|
190
|
+
* @param {string} value Valore del Gruppo
|
|
191
|
+
*/
|
|
192
|
+
constructor(column, count, value) {
|
|
193
|
+
this.column = column;
|
|
194
|
+
this.count = count;
|
|
195
|
+
this.value = value;
|
|
196
|
+
this.aggregations = [];
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Classe che rappresenta un'aggregazione */
|
|
201
|
+
class GroupAggregation {
|
|
202
|
+
/**
|
|
203
|
+
* Costruttore
|
|
204
|
+
*
|
|
205
|
+
* @param {string} column ID della colonna aggregata
|
|
206
|
+
* @param {'min' | 'max' | 'sum' } aggregation Aggregazione da effettuare su questa colonna
|
|
207
|
+
* @param {string} value Valore dell'aggregazione
|
|
208
|
+
*/
|
|
209
|
+
constructor(column, aggregation, value) {
|
|
210
|
+
this.column = column;
|
|
211
|
+
this.aggregation = aggregation;
|
|
212
|
+
this.value = value;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Classe che rappresenta un filtro su un gruppo */
|
|
217
|
+
class GroupFilter {
|
|
218
|
+
/**
|
|
219
|
+
* Costruttore
|
|
220
|
+
*
|
|
221
|
+
* @param {string} column ID della colonna gruppata per cui si richiede di filtrare
|
|
222
|
+
* @param {string} value Valore del gruppo su questa **column** per cui si richiede di filtrare
|
|
223
|
+
*/
|
|
224
|
+
constructor(column, value) {
|
|
225
|
+
this.column = column;
|
|
226
|
+
this.value = value;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/** Classe che rappresenta o un gruppo o una aggregazione su una colonna. Usata solo internamente */
|
|
231
|
+
class GroupOrAggregation {
|
|
232
|
+
/**
|
|
233
|
+
* Costruttore
|
|
234
|
+
*
|
|
235
|
+
* @param {string} column Colonna su cui è presente o un gruppo o un'aggregazione
|
|
236
|
+
* @param {'min' | 'max' | 'sum' } aggregation Aggregazione presente sulla **column**. Se questo campo è nullo significa che è un gruppo.
|
|
237
|
+
* @param {'string' | 'date' | 'number'} datatype Tipo di dati contenuto nella colonna **column** se non c'è alcuna aggregazione è inutile, pertanto non sarà valorizzato
|
|
238
|
+
*/
|
|
239
|
+
constructor(column, aggregation, datatype) {
|
|
240
|
+
this.column = column;
|
|
241
|
+
this.aggregation = aggregation;
|
|
242
|
+
this.datatype = datatype;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/** Rappresenta un trittico formato da un array e due cache relative a tale array per un accesso estremamente veloce per tutte le operazioni del caso */
|
|
247
|
+
class CacheTriptic {
|
|
248
|
+
/**
|
|
249
|
+
* Costruttore
|
|
250
|
+
*
|
|
251
|
+
* @param {Map<string, any>} cache Cache Chiave-Oggetto
|
|
252
|
+
* @param {Map<string, number>} index_cache Cache Indice-Oggetto
|
|
253
|
+
* @param {any[]} array Array contenente gli oggetti
|
|
254
|
+
*/
|
|
255
|
+
constructor(cache, index_cache, array) {
|
|
256
|
+
this.cache = cache;
|
|
257
|
+
this.index_cache = index_cache;
|
|
258
|
+
this.array = array;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** Definizione di una colonna, utilizzato nella dialog che permette di modificare le posizioni e le visibilità */
|
|
204
263
|
class EsTableColumn {
|
|
205
264
|
/**
|
|
206
265
|
* Costruttore
|
|
@@ -209,66 +268,89 @@ class EsTableColumn {
|
|
|
209
268
|
* @param {string} description Descrizione (Header)
|
|
210
269
|
* @param {boolean} visible Indica se di default mostrarla o meno
|
|
211
270
|
* @param {boolean} fixed Indica se è una colonna fixed
|
|
271
|
+
* @param {boolean} pinned Indica se è una colonna pinnata
|
|
272
|
+
* @param {number} pinnedWidth Indica la dimensione da assegnare a questa colonna quando è pinnata
|
|
212
273
|
* @param {TemplateRef<any>} template Indica il template da usare per mostrare il testo dell'Header
|
|
213
274
|
*/
|
|
214
|
-
constructor(id, description, visible, fixed, template) {
|
|
275
|
+
constructor(id, description, visible, fixed, pinned, pinnedWidth, template) {
|
|
215
276
|
this.id = id;
|
|
216
277
|
this.description = description;
|
|
217
278
|
this.visible = visible;
|
|
218
279
|
this.fixed = fixed;
|
|
280
|
+
this.pinned = pinned;
|
|
281
|
+
this.pinnedWidth = pinnedWidth;
|
|
219
282
|
this.template = template;
|
|
220
283
|
}
|
|
221
284
|
}
|
|
222
285
|
|
|
223
|
-
/**
|
|
224
|
-
|
|
225
|
-
*/
|
|
226
|
-
class ItemsSelection {
|
|
286
|
+
/** Classe che rappresenta un separatore da inserire fra gli oggetti dell'es-table per le operazioni di paginazione dei raggruppamenti per riga */
|
|
287
|
+
class GroupPager {
|
|
227
288
|
/**
|
|
228
289
|
* Costruttore
|
|
229
290
|
*
|
|
230
|
-
* @param {
|
|
291
|
+
* @param {number} groupLevel Livello del gruppo a cui questo separatore fa riferimento
|
|
292
|
+
* @param {string} parentKey Chiave del gruppo parent se esiste
|
|
293
|
+
* @param {AppSearch<any>} view Vista di ricerca collegata a questo elemento
|
|
294
|
+
* @param {'groups' | 'items'} searches Indica che cosa cerca questo separatore, se sottogruppi o oggetti
|
|
231
295
|
*/
|
|
232
|
-
constructor(
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
this.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
this.exclusions = [];
|
|
241
|
-
this.count = selected.length;
|
|
242
|
-
this.items = selected;
|
|
243
|
-
this.all = false;
|
|
244
|
-
this.exclusions = [];
|
|
296
|
+
constructor(_grouplevel, _thisRoute, _parent, view, searches) {
|
|
297
|
+
this._grouplevel = _grouplevel;
|
|
298
|
+
this._thisRoute = _thisRoute;
|
|
299
|
+
this._parent = _parent;
|
|
300
|
+
this.view = view;
|
|
301
|
+
this.searches = searches;
|
|
302
|
+
this._sep = true;
|
|
303
|
+
this.buttons = [];
|
|
245
304
|
}
|
|
246
305
|
}
|
|
247
306
|
|
|
248
|
-
//Angular
|
|
249
307
|
/**
|
|
250
|
-
*
|
|
308
|
+
* Classe che rappresenta un singolo frammento di route di un elemento gruppo o non. Un array di questi indica tutte le colonne di gruppo con i loro valori
|
|
309
|
+
* per arrivare ad una ricerca su sottogruppi o elementi relativi
|
|
251
310
|
*/
|
|
252
|
-
class
|
|
311
|
+
class GroupRouteFragment {
|
|
253
312
|
/**
|
|
254
|
-
*
|
|
313
|
+
* Costruttore
|
|
314
|
+
*
|
|
315
|
+
* @param {string} column Colonna di raggruppamento
|
|
316
|
+
* @param {string} value Valore della colonna di raggruppamento
|
|
255
317
|
*/
|
|
318
|
+
constructor(column, value) {
|
|
319
|
+
this.column = column;
|
|
320
|
+
this.value = value;
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** Classe rappresentante una singola aggregazione effettuata su una colonna */
|
|
325
|
+
class ThAggregation {
|
|
326
|
+
/**
|
|
327
|
+
* Costruttore
|
|
328
|
+
*
|
|
329
|
+
* @param {'min' | 'max' | 'sum'} func Funzione di aggergazione, può essere **min**, **max** o **sum**
|
|
330
|
+
* @param {string} format Formato richiesto per il valore dell'aggregazione
|
|
331
|
+
* @param {string} match Match intero del pezzo di testo da cui si è estrapolata l'aggregazione, da rimpiazzare col valore calcolato
|
|
332
|
+
*/
|
|
333
|
+
constructor(func, format, match) {
|
|
334
|
+
this.func = func;
|
|
335
|
+
this.format = format;
|
|
336
|
+
this.match = match;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
//Angular
|
|
341
|
+
/** Componente rappresentante una singola cella del body della tabella */
|
|
342
|
+
class EsTd {
|
|
343
|
+
/** @ignore */
|
|
256
344
|
constructor(myself, renderer, _viewContainer, sanitizer) {
|
|
257
345
|
this.myself = myself;
|
|
258
346
|
this.renderer = renderer;
|
|
259
347
|
this._viewContainer = _viewContainer;
|
|
260
348
|
this.sanitizer = sanitizer;
|
|
261
|
-
/**
|
|
262
|
-
* Id della cella, dev'essere lo stesso della colonna **EsTh** relativa
|
|
263
|
-
*/
|
|
349
|
+
/** Id della cella, dev'essere lo stesso della colonna **EsTh** relativa */
|
|
264
350
|
this.ID = "";
|
|
265
|
-
/**
|
|
266
|
-
* Valore da mostrare all'interno della cella. Se omesso verrà proiettato il contenuto dal template in cui è stata usata
|
|
267
|
-
*/
|
|
351
|
+
/** Valore da mostrare all'interno della cella. Se omesso verrà proiettato il contenuto dal template in cui è stata usata */
|
|
268
352
|
this.Display = null;
|
|
269
|
-
/**
|
|
270
|
-
* Template Angular da istanziare per questo TD
|
|
271
|
-
*/
|
|
353
|
+
/** Template Angular da istanziare per questo TD */
|
|
272
354
|
this.Template = null;
|
|
273
355
|
}
|
|
274
356
|
/**
|
|
@@ -293,18 +375,17 @@ class EsTd {
|
|
|
293
375
|
this._Visible = true;
|
|
294
376
|
return this._Visible;
|
|
295
377
|
}
|
|
296
|
-
/**
|
|
297
|
-
* @ignore
|
|
298
|
-
*/
|
|
378
|
+
/** @ignore */
|
|
299
379
|
ngAfterViewInit() {
|
|
300
380
|
// Se è Internal significa che è gestita internamente da ES-TABLE quindi evito di fare sti due passaggi di lettura del DOM
|
|
301
381
|
if (this.Internal)
|
|
302
382
|
return;
|
|
303
383
|
// L'hash è calcolato dalla ES-table in fase di binding
|
|
304
|
-
this.Context = this.Context || this.getTemplateContext().
|
|
384
|
+
this.Context = this.Context || this.getTemplateContext()._hash;
|
|
305
385
|
this.Content = this.Display === null || this.Display === "" ? this.sanitizer.bypassSecurityTrustHtml(this.myself.nativeElement.innerHTML) : this.sanitizer.bypassSecurityTrustHtml(this.Display);
|
|
306
386
|
this.Class = this.myself.nativeElement.className.replace("app-display-none", "");
|
|
307
387
|
}
|
|
388
|
+
/** Ottiene il contesto della view su cui è istanziato il componente */
|
|
308
389
|
getTemplateContext() {
|
|
309
390
|
// NGBUG: (<any>this._viewContainer)._view non esiste più in IVY: https://stackoverflow.com/questions/60398827/getting-the-context-of-the-template-inside-of-which-my-component-has-been-render
|
|
310
391
|
let vc = this._viewContainer;
|
|
@@ -361,23 +442,15 @@ EsTd.propDecorators = {
|
|
|
361
442
|
};
|
|
362
443
|
|
|
363
444
|
//Angular
|
|
364
|
-
/**
|
|
365
|
-
* Componente rappresentante una Colonna della tabella
|
|
366
|
-
*/
|
|
445
|
+
/** Componente rappresentante una Colonna della tabella */
|
|
367
446
|
class EsTh {
|
|
368
|
-
/**
|
|
369
|
-
* @ignore
|
|
370
|
-
*/
|
|
447
|
+
/** @ignore */
|
|
371
448
|
constructor(myself, renderer) {
|
|
372
449
|
this.myself = myself;
|
|
373
450
|
this.renderer = renderer;
|
|
374
|
-
/**
|
|
375
|
-
* Dizionario di mappatura con ordinamento attuale e ordinamento successivo per gestire i passaggi di stato
|
|
376
|
-
*/
|
|
451
|
+
/** Dizionario di mappatura con ordinamento attuale e ordinamento successivo per gestire i passaggi di stato */
|
|
377
452
|
this.orderNext = { "NONE": "DESC", "DESC": "ASC", "ASC": null };
|
|
378
|
-
/**
|
|
379
|
-
* Indica se si sta effettuando un'operazione di resize su questa colonna
|
|
380
|
-
*/
|
|
453
|
+
/** Indica se si sta effettuando un'operazione di resize su questa colonna */
|
|
381
454
|
this.resizingThis = false;
|
|
382
455
|
/**
|
|
383
456
|
* Storicizza l'offset di partenza del resize dell'elemento HTML per poter calcolare la nuova dimensione richiesta durente il resize
|
|
@@ -385,21 +458,13 @@ class EsTh {
|
|
|
385
458
|
* nuova width = startOffset + posizione X del mouse
|
|
386
459
|
*/
|
|
387
460
|
this.startOffset = null;
|
|
388
|
-
/**
|
|
389
|
-
* Id della colonna, dev'essere lo stesso per tutti gli **EsTd** relativi
|
|
390
|
-
*/
|
|
461
|
+
/** Id della colonna, dev'essere lo stesso per tutti gli **EsTd** relativi */
|
|
391
462
|
this.ID = "";
|
|
392
|
-
/**
|
|
393
|
-
* Indica se questa colonna è ordinabile o meno
|
|
394
|
-
*/
|
|
463
|
+
/** Indica se questa colonna è ordinabile o meno */
|
|
395
464
|
this.Orderable = true;
|
|
396
|
-
/**
|
|
397
|
-
* Valore da mostrare all'interno della colonna. Se omesso verrà proiettato il contenuto dal template in cui è stata usata
|
|
398
|
-
*/
|
|
465
|
+
/** Valore da mostrare all'interno della colonna. Se omesso verrà proiettato il contenuto dal template in cui è stata usata */
|
|
399
466
|
this.Display = "";
|
|
400
|
-
/**
|
|
401
|
-
* Indica se le dimnsioni di questa colonna sono modificabili o meno
|
|
402
|
-
*/
|
|
467
|
+
/** Indica se le dimnsioni di questa colonna sono modificabili o meno */
|
|
403
468
|
this.Resizable = false;
|
|
404
469
|
/**
|
|
405
470
|
* Indica se sta venendo eseguita una operazione di ricerca o meno, serve per evitare l'esecuzione di eventuale codice che potrebbe dare fastidio
|
|
@@ -410,18 +475,12 @@ class EsTh {
|
|
|
410
475
|
this.Wrap = false;
|
|
411
476
|
/** Indica se la colonna è fixed, cioè se non può né essere nascosta, né riposizionata. Solo le prime colonne possono essere Fixed */
|
|
412
477
|
this.Fixed = false;
|
|
413
|
-
/**
|
|
414
|
-
* Template Angular da istanziare per questo TH
|
|
415
|
-
*/
|
|
478
|
+
/** Template Angular da istanziare per questo TH */
|
|
416
479
|
this.Template = null;
|
|
417
|
-
/**
|
|
418
|
-
* Evento emesso al cambio di ordinamento effettuato su questa colonna
|
|
419
|
-
*/
|
|
480
|
+
/** Evento emesso al cambio di ordinamento effettuato su questa colonna */
|
|
420
481
|
this.onOrderChange = new EventEmitter();
|
|
421
|
-
/**
|
|
422
|
-
|
|
423
|
-
*/
|
|
424
|
-
this.Referenced = false;
|
|
482
|
+
/** Impostato dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header */
|
|
483
|
+
this._referenced = false;
|
|
425
484
|
}
|
|
426
485
|
/**
|
|
427
486
|
* Imposta la visibilità o meno della colonna, si traduce nell'applicazione o rimozione della classe **app-display-none**
|
|
@@ -445,9 +504,7 @@ class EsTh {
|
|
|
445
504
|
this._Visible = true;
|
|
446
505
|
return this._Visible;
|
|
447
506
|
}
|
|
448
|
-
/**
|
|
449
|
-
* @ignore
|
|
450
|
-
*/
|
|
507
|
+
/** @ignore */
|
|
451
508
|
ngAfterViewInit() {
|
|
452
509
|
//Assegnare direttamente il content è più veloce che passare dal native element per qualche motivo
|
|
453
510
|
this.Description = this.Display === null || this.Display === "" ? this.content.nativeElement.innerText : this.Display;
|
|
@@ -456,9 +513,7 @@ class EsTh {
|
|
|
456
513
|
if (this.Resizable)
|
|
457
514
|
this.renderer.addClass(this.myself.nativeElement, "app-relative");
|
|
458
515
|
}
|
|
459
|
-
/**
|
|
460
|
-
* Gestisce la modifica dell'ordinamento qualora venisse cliccato su questa colonna
|
|
461
|
-
*/
|
|
516
|
+
/** Gestisce la modifica dell'ordinamento qualora venisse cliccato su questa colonna */
|
|
462
517
|
setupNextOrderAndNotify() {
|
|
463
518
|
if (!this.ID) {
|
|
464
519
|
console.log("Attempt to order a column without ID. Operation ignored");
|
|
@@ -485,9 +540,7 @@ class EsTh {
|
|
|
485
540
|
this.resizingThis = true;
|
|
486
541
|
this.startOffset = this.myself.nativeElement.offsetWidth - ev.pageX;
|
|
487
542
|
}
|
|
488
|
-
/**
|
|
489
|
-
* Listener per la fine dell'operazione di resize
|
|
490
|
-
*/
|
|
543
|
+
/** Listener per la fine dell'operazione di resize */
|
|
491
544
|
onMouseUp() {
|
|
492
545
|
if (!this.Resizable)
|
|
493
546
|
return;
|
|
@@ -537,9 +590,7 @@ EsTh.propDecorators = {
|
|
|
537
590
|
onMouseMove: [{ type: HostListener, args: ['window:mousemove.out-zone', ['$event'],] }]
|
|
538
591
|
};
|
|
539
592
|
|
|
540
|
-
/**
|
|
541
|
-
* Direttiva per la dichiarazione snella di un EsTd da emettere per ogni elemento, data una colonna
|
|
542
|
-
*/
|
|
593
|
+
/** Direttiva per la dichiarazione snella di un EsTd da emettere per ogni elemento, data una colonna */
|
|
543
594
|
class EsTdDirective {
|
|
544
595
|
/**
|
|
545
596
|
* @ignore
|
|
@@ -567,23 +618,31 @@ EsTdDirective.propDecorators = {
|
|
|
567
618
|
tdClass: [{ type: Input }]
|
|
568
619
|
};
|
|
569
620
|
|
|
570
|
-
/**
|
|
571
|
-
* Direttiva per la dichiarazione snella di un EsTh da emettere come header
|
|
572
|
-
*/
|
|
621
|
+
/** Direttiva per la dichiarazione snella di un EsTh da emettere come header */
|
|
573
622
|
class EsThDirective {
|
|
574
623
|
/**
|
|
575
624
|
* @ignore
|
|
576
625
|
*/
|
|
577
626
|
constructor(Template) {
|
|
578
627
|
this.Template = Template;
|
|
628
|
+
/** Variabile interna all'interno della quale viene raccolta la cache delle aggregazioni specificate in thAggregation */
|
|
629
|
+
this._thAggregations = null;
|
|
579
630
|
/** Variabile interna che indica il fatto che questo componente è una direttiva. Serve per disambigualrlo dell'EsThComponent */
|
|
580
631
|
this._directive = true;
|
|
632
|
+
/** Variabile interna impostata dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header */
|
|
633
|
+
this._referenced = false;
|
|
581
634
|
/** Id della colonna, dev'essere lo stesso per tutti i **td** relativi */
|
|
582
635
|
this.th = "";
|
|
636
|
+
/** Indica se la colonna è pinnata o no */
|
|
637
|
+
this.thPinned = false;
|
|
638
|
+
/** Indica le dimensioni che deve avere questa colonna quando viene pinnata, senza questo tutte le colonne mi collasserebbero l'una sull'altra */
|
|
639
|
+
this.thPinnedWidth = 150;
|
|
583
640
|
/** Indicazione sulla visibilità della colonna */
|
|
584
641
|
this.thVisible = true;
|
|
585
642
|
/** Indica se la colonna è fixed, cioè se non può né essere nascosta, né riposizionata. Solo le prime colonne possono essere Fixed */
|
|
586
643
|
this.thFixed = false;
|
|
644
|
+
/** Indica che la colonna è sotto ad un raggruppamento padre, con questo nome nel **th** */
|
|
645
|
+
this.thParent = "";
|
|
587
646
|
/** Indica se questa colonna è ordinabile o meno */
|
|
588
647
|
this.thOrderable = true;
|
|
589
648
|
/** Indica se il testo presente in questo Header può andare a capo o meno, di default non può */
|
|
@@ -592,12 +651,10 @@ class EsThDirective {
|
|
|
592
651
|
this.thResizable = false;
|
|
593
652
|
/** Equivalente dell'NgIf sul th */
|
|
594
653
|
this.thIf = true;
|
|
595
|
-
/**
|
|
654
|
+
/** Indica che bisogna fare un raggruppamento su questa colonna */
|
|
596
655
|
this.thGroup = false;
|
|
597
|
-
/**
|
|
656
|
+
/** Indica che bisogna fare una aggregazione su questa colonna, a fronte di almeno un altra con un raggruppamento */
|
|
598
657
|
this.thAggregation = null;
|
|
599
|
-
/** Impostato dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header */
|
|
600
|
-
this.Referenced = false;
|
|
601
658
|
}
|
|
602
659
|
}
|
|
603
660
|
EsThDirective.decorators = [
|
|
@@ -608,8 +665,11 @@ EsThDirective.ctorParameters = () => [
|
|
|
608
665
|
];
|
|
609
666
|
EsThDirective.propDecorators = {
|
|
610
667
|
th: [{ type: Input }],
|
|
668
|
+
thPinned: [{ type: Input }],
|
|
669
|
+
thPinnedWidth: [{ type: Input }],
|
|
611
670
|
thVisible: [{ type: Input }],
|
|
612
671
|
thFixed: [{ type: Input }],
|
|
672
|
+
thParent: [{ type: Input }],
|
|
613
673
|
thOrder: [{ type: Input }],
|
|
614
674
|
thOrderable: [{ type: Input }],
|
|
615
675
|
thWrap: [{ type: Input }],
|
|
@@ -621,21 +681,20 @@ EsThDirective.propDecorators = {
|
|
|
621
681
|
thAggregation: [{ type: Input }]
|
|
622
682
|
};
|
|
623
683
|
|
|
624
|
-
/**
|
|
625
|
-
|
|
626
|
-
*/
|
|
627
|
-
const
|
|
684
|
+
/** Token che indica il locale da utilizzare all'interno del componente. Supportati solo "it-IT" ed "en-US" */
|
|
685
|
+
const EST_LOCALE = new InjectionToken('EST_LOCALE');
|
|
686
|
+
/** Token che indica se emettere log a console o meno */
|
|
687
|
+
const EST_DEBUG = new InjectionToken('EST_DEBUG');
|
|
688
|
+
/** Token che indica i default da assegnare agli Input */
|
|
689
|
+
const EST_DEFAULTS = new InjectionToken('EST_DEFAULTS');
|
|
628
690
|
|
|
629
|
-
/**
|
|
630
|
-
* Classe di localizzazione per il componente **EsTableComponent**
|
|
631
|
-
*/
|
|
691
|
+
/** Classe di localizzazione per il componente **EsTableComponent** */
|
|
632
692
|
class EsTableLoc extends LocalizationService {
|
|
633
|
-
/**
|
|
634
|
-
* @ignore
|
|
635
|
-
*/
|
|
693
|
+
/** @ignore */
|
|
636
694
|
constructor(LOC_LOCALE) {
|
|
637
695
|
super(LOC_LOCALE !== null && LOC_LOCALE !== void 0 ? LOC_LOCALE : 'it-IT');
|
|
638
696
|
super.set("en->it", "All", ["Tutto"]);
|
|
697
|
+
super.set("en->it", "Groups", ["Gruppi"]);
|
|
639
698
|
super.set("en->it", "Cannot export an empty dataset", ["Impossibile esportare un dataset vuoto"]);
|
|
640
699
|
super.set("en->it", "Performing Table bootstrap", ["Sto caricando la Tabella"]);
|
|
641
700
|
super.set("en->it", "Update every", ["Aggiorna ogni"]);
|
|
@@ -661,12 +720,19 @@ EsTableLoc.ctorParameters = () => [
|
|
|
661
720
|
{ type: String, decorators: [{ type: Optional }, { type: Inject, args: [EST_LOCALE,] }] }
|
|
662
721
|
];
|
|
663
722
|
|
|
723
|
+
/** Raccolta di tutti gli Input dell'EsTable a cui può essere logicamente sensato assegnare default per progetto */
|
|
724
|
+
class EsTableDefaultable {
|
|
725
|
+
}
|
|
726
|
+
|
|
664
727
|
/** Componente che permette di rappresentare una griglia di valori */
|
|
665
728
|
class EsTableComponent {
|
|
666
729
|
/** @ignore */
|
|
667
|
-
constructor(ngControl, prefService, lc, cdr, hashExts, utiExts, expExts, dateExts, msgExts) {
|
|
730
|
+
constructor(ngControl, prefService, deafults, locale, lc, cdr, hashExts, utiExts, expExts, dateExts, msgExts) {
|
|
731
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
|
|
668
732
|
this.ngControl = ngControl;
|
|
669
733
|
this.prefService = prefService;
|
|
734
|
+
this.deafults = deafults;
|
|
735
|
+
this.locale = locale;
|
|
670
736
|
this.lc = lc;
|
|
671
737
|
this.cdr = cdr;
|
|
672
738
|
this.hashExts = hashExts;
|
|
@@ -678,10 +744,7 @@ class EsTableComponent {
|
|
|
678
744
|
this.View = null;
|
|
679
745
|
/** Indica se l'es-table deve mostrare il check globale nell'header per fare il "seleziona tutto" */
|
|
680
746
|
this.globalCheck = false;
|
|
681
|
-
/**
|
|
682
|
-
* Tiene da conto l'ultimo elemento selezionato in modo da fare ragionamenti del tipo
|
|
683
|
-
* "Ho selezionato questo, l'ultimo selezionato era **lastSelected**, devo selezionare tutti quelli in mezzo", ad esempio per la selezione multipla
|
|
684
|
-
*/
|
|
747
|
+
/** Tiene da conto l'ultimo elemento selezionato in modo da poter effettuare il SHIFT+CLICK */
|
|
685
748
|
this.lastSelected = null;
|
|
686
749
|
/** Conteggio interno per il numero di elementi selezionati */
|
|
687
750
|
this.selectedObjects = 0;
|
|
@@ -720,6 +783,10 @@ class EsTableComponent {
|
|
|
720
783
|
this.RowTHs = null;
|
|
721
784
|
/** Modello di appoggio temporaneo per i **RowTHs** */
|
|
722
785
|
this.TMPRowTHs = null;
|
|
786
|
+
/** Modello di appoggio temporaneo per i **RowThGroups** */
|
|
787
|
+
this.TMPRowThGroups = null;
|
|
788
|
+
/** Modello rappresentante un singolo header group della tabella. Questa lista è già ordinata e pronta per essere utilizzata in ngFor */
|
|
789
|
+
this.RowThGroups = null;
|
|
723
790
|
/** Cache per i routerLink generati nelle tabelle dinamiche */
|
|
724
791
|
this.DynamicTableRouterLinkCache = {};
|
|
725
792
|
/**
|
|
@@ -786,14 +853,14 @@ class EsTableComponent {
|
|
|
786
853
|
this.UseCustomCells = null;
|
|
787
854
|
/** Permette di impostare l'altezza massima della tabella. Se null la dimensione si adatta al numero di elementi attualmente in visualizzazione */
|
|
788
855
|
this.MaxHeight = null;
|
|
789
|
-
/** Classi da applicare
|
|
790
|
-
this.
|
|
856
|
+
/** Classi da applicare al contenitore della tabella */
|
|
857
|
+
this.ContainerClass = null;
|
|
791
858
|
/** Permette o meno l'export in formato XLSX */
|
|
792
859
|
this.XLSXExport = null;
|
|
793
860
|
/** Permette o meno l'export in formato CSV */
|
|
794
861
|
this.CSVExport = true;
|
|
795
862
|
/** Permette di visualizzare o meno l'opzione di paginazione "Tutti" */
|
|
796
|
-
this.AllSearch =
|
|
863
|
+
this.AllSearch = null;
|
|
797
864
|
/** Diminuisce gli spazi fra una cella e l'altra, e internamente il padding del font in modo da presentare molti più dati in un'unica pagina */
|
|
798
865
|
this.HighCellDensity = null;
|
|
799
866
|
/** Abilita o meno la possibilità di selezionare oggetti */
|
|
@@ -812,8 +879,6 @@ class EsTableComponent {
|
|
|
812
879
|
this.Export = null;
|
|
813
880
|
/** Indica se permettere la selezione multipla Windows-like cliccando un oggetto e facendo poi Shift + click su un oggetto successivo */
|
|
814
881
|
this.ShiftClick = null;
|
|
815
|
-
/** Mostra o nasconde le informazioni di paginazione, sia i pulsanti, sia il selettore degli oggetti per pagina */
|
|
816
|
-
this.ShowPaging = true;
|
|
817
882
|
/** Indica se nascondere o mostrare il componente di paginazione */
|
|
818
883
|
this.HidePaging = null;
|
|
819
884
|
/** Indica se nascondere o mostrare il conteggio degli elementi trovati */
|
|
@@ -825,12 +890,10 @@ class EsTableComponent {
|
|
|
825
890
|
/** Nome dell'esportazione generata da questa tabella */
|
|
826
891
|
this.ExportFileName = 'Export.csv';
|
|
827
892
|
/** Classe (HTML) di default della tabella */
|
|
828
|
-
this.TableClass =
|
|
829
|
-
/**
|
|
830
|
-
this.CountLabel = this.lc.loc('Found objects');
|
|
831
|
-
/** Indica la presenza di raggruppamenti a livello di header */
|
|
893
|
+
this.TableClass = null;
|
|
894
|
+
/** @deprecated Indica la presenza di raggruppamenti a livello di header */
|
|
832
895
|
this.HasHeaderGroup = null;
|
|
833
|
-
/** Indica la presenza di raggruppamenti a livello del raggruppamento precedentemente esistente, chiaramente è insensata senza **HasHeaderGroup** */
|
|
896
|
+
/** @deprecated Indica la presenza di raggruppamenti a livello del raggruppamento precedentemente esistente, chiaramente è insensata senza **HasHeaderGroup** */
|
|
834
897
|
this.HasSecondaryHeaderGroup = null;
|
|
835
898
|
/** Utilizzato per dividere la sorgente in modalità EndlessScroll */
|
|
836
899
|
this.SliceSize = 100;
|
|
@@ -862,11 +925,7 @@ class EsTableComponent {
|
|
|
862
925
|
this.HiddenColumns = null;
|
|
863
926
|
/** Permette di riordinare le colonne in base alle impostazioni effettuate dal Menù contestuale in alto a destra */
|
|
864
927
|
this.ColumnsOrdering = null;
|
|
865
|
-
/**
|
|
866
|
-
* Eventuale supporto alle ricerche applicate alla modalità Array
|
|
867
|
-
*
|
|
868
|
-
* @deprecated Utilizzato solo per un caso particolare del Metering
|
|
869
|
-
*/
|
|
928
|
+
/** Eventuale supporto alle ricerche applicate alla modalità Array */
|
|
870
929
|
this.SearchView = null;
|
|
871
930
|
/** Abilita o disabilita il sistema che permette di selezionare tutti gli elementi nella vista */
|
|
872
931
|
this.SelectAll = null;
|
|
@@ -886,6 +945,10 @@ class EsTableComponent {
|
|
|
886
945
|
this.StartsExpanded = true;
|
|
887
946
|
/** Indica se effettuare il salvataggio delle preferenze di ricerca */
|
|
888
947
|
this.SavePreferences = null;
|
|
948
|
+
/** Indica dove visualizzare le informazioni di paginazione, se sopra, sotto o in entrambi */
|
|
949
|
+
this.PagingStyle = null;
|
|
950
|
+
/** Indica dove visualizzare le informazioni di paginazione, se sopra, sotto o in entrambi */
|
|
951
|
+
this.RowGroupingPagingStyle = null;
|
|
889
952
|
/**
|
|
890
953
|
* Sorgente dati secondaria
|
|
891
954
|
*
|
|
@@ -899,7 +962,9 @@ class EsTableComponent {
|
|
|
899
962
|
*/
|
|
900
963
|
this.TertiarySource = null;
|
|
901
964
|
/** Indica se utilizzare la cache di selezione che permette di mantenere gli stati di selezione dei vari oggetti navigando da una pagina all'altra */
|
|
902
|
-
this.UseSelectionCache =
|
|
965
|
+
this.UseSelectionCache = null;
|
|
966
|
+
/** Permette di decidere se, in modalità raggruppamento, mostrare o meno il valore delle colonne di gruppo negli oggetti finali. Di default sono nascosti */
|
|
967
|
+
this.ShowItemGroupsColumns = null;
|
|
903
968
|
/** Evento che viene richiamato al cambio di oridnamento di una colonna */
|
|
904
969
|
this.onOrderChanged = new EventEmitter();
|
|
905
970
|
/**
|
|
@@ -908,6 +973,8 @@ class EsTableComponent {
|
|
|
908
973
|
*
|
|
909
974
|
* Solo in caso venga utilizzata la modalità a raggruppamenti di righe può succedere che l'es-table passi un intero AppSearch come parametro di ricerca,
|
|
910
975
|
* in quel caso l'applicazione ricevente dovrà onorare la richiesta spedendo al backand l'oggetto di ricerca AS-IS
|
|
976
|
+
*
|
|
977
|
+
* il tipo dell'Emitter invece di essere [boolean | AppSearch<any>] è stato impostato a "any" per evitare problemi di retrocompatibilità
|
|
911
978
|
*/
|
|
912
979
|
this.onSearchRequest = new EventEmitter();
|
|
913
980
|
/** Evento che parte ad ogni modifica di "checkaggio" in forma di comodo array. Espone l'oggetto con lo stato di check attuale */
|
|
@@ -930,32 +997,91 @@ class EsTableComponent {
|
|
|
930
997
|
/** Numero di pagine (durante la paginazione in modalità Array) */
|
|
931
998
|
this.arraymodePages = 1;
|
|
932
999
|
/** Oggetti per ogni pagina (durante la paginazione in modalità Array) */
|
|
933
|
-
this.ArraymodeItemsPerPage =
|
|
1000
|
+
this.ArraymodeItemsPerPage = null;
|
|
1001
|
+
/** Colonne da visualizzare in modalità array */
|
|
1002
|
+
this.arrayColumns = [];
|
|
1003
|
+
/** Ordine delle colonne da visualizzare in modalità array */
|
|
1004
|
+
this.arrayColumnOrdering = [];
|
|
1005
|
+
/** Ordinamenti ASC-DESC sulle colonne in modalità array */
|
|
1006
|
+
this.arrayOrders = [];
|
|
934
1007
|
/**
|
|
935
1008
|
* Variabile che serve a gestire il momento in cui l'es-table aggiorna la paginazione (pulsanti ecc).
|
|
936
1009
|
* Essendo operazioni comunque costose le effettuo solo su binding esterni, non su rewrite generati internamente
|
|
937
1010
|
*/
|
|
938
1011
|
this.internalWriteCall = false;
|
|
939
|
-
/** Cache di selezione Hash - Oggetto */
|
|
940
|
-
this.selOrDeselCache = {};
|
|
941
|
-
/**
|
|
942
|
-
* Variabile d'appoggio per capire se c'è bisogno di ri-effettuare una ricerca o meno
|
|
943
|
-
*/
|
|
944
|
-
this.ResearchNeeded = false;
|
|
945
1012
|
/**
|
|
946
|
-
*
|
|
1013
|
+
* Cache che conterrà tutte le ricerche effettuate su gruppi diversi dal primo e su elementi contenuti nei gruppi.
|
|
1014
|
+
* In caso di cambi di ordinamento delle colonne diverse dalla prima tutte le chiamate fatte dal secondo livello in poi devono essere rieseguite secondo la seguente logica:
|
|
947
1015
|
*
|
|
948
|
-
* Di base dovrebbe essere la somma dei RowTH con l'aggiunta di tutti gli Header extra in base alle situazioni. Dato che diventa una logica deficiente me la cavo così
|
|
949
1016
|
*
|
|
950
|
-
*
|
|
1017
|
+
* **Cambio ordinamento sul primo gruppo**: reload completo, non mi occupo di ripulire gli elementi bindati in alcun modo
|
|
951
1018
|
*
|
|
1019
|
+
* **Cambio ordinamento sulla colonna relativa all'N-esimo gruppo**: reload completo del contenuto dei gruppi precedenti, ripulendo precedentemente
|
|
1020
|
+
* tutti gli elementi con **_grouplevel** = N
|
|
1021
|
+
*
|
|
1022
|
+
* **Cambio ordinamento su una colonna non raggruppata**: reload completo per tutti i gruppi finali aperti, devo precedentemente ripulire tutti gli elementi con **_item** = true
|
|
1023
|
+
*
|
|
1024
|
+
* Altri eventi non dovrebbero rappresentare problemi:
|
|
1025
|
+
* - Selezione: non cambia nulla
|
|
1026
|
+
* - Paginazione: cambia a livello root quindi viene ricaricato tutto comunque, stesso vale per le paginazioni interne
|
|
952
1027
|
*/
|
|
953
|
-
this.
|
|
1028
|
+
this.groupSearchRequestsCache = [];
|
|
1029
|
+
/** Variabile d'appoggio per capire se c'è bisogno di ri-effettuare una ricerca o meno */
|
|
1030
|
+
this.ResearchNeeded = false;
|
|
1031
|
+
/** Colonne visibili della vista attuale. Valorizzato di default al numero massimo di colonne supportate dalla tabella per le casistiche in assenza di custom cells */
|
|
1032
|
+
this.Columns = { Visibile: 100, VisibleUnpinned: 100, Global: 100 };
|
|
1033
|
+
/** In caso di Row Grouping qui viene salvata la vista principale dei gruppi base */
|
|
1034
|
+
this.MainGroupView = null;
|
|
1035
|
+
/** Conteggio base degli oggetti. In modalità normale viene resettato ad ogni nuova View inserita, in modalità RowGrouping viene resettato solo ad una nuova View di livello "0" */
|
|
1036
|
+
this.BaseItemsCount = null;
|
|
1037
|
+
/** Cache per salvare per ogni chiave di ogni gruppo chi è il gruppo rappresentato */
|
|
1038
|
+
this.rgGroupCache = new Map();
|
|
1039
|
+
/** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
|
|
1040
|
+
this.rgItemCache = new Map();
|
|
1041
|
+
/** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
|
|
1042
|
+
this.rgChildGroupsCache = new Map();
|
|
1043
|
+
/** Cache di selezione Hash - Oggetto per la variabile **items** dell'itemSelector. Facilita le operazioni di lookup via hash*/
|
|
1044
|
+
this.itemsCache = new Map();
|
|
1045
|
+
/** Cache di selezione Hash - Oggetto per la variabile **groups** dell'itemSelector. Facilita le operazioni di lookup via hash */
|
|
1046
|
+
this.groupsCache = new Map();
|
|
1047
|
+
/** Cache di selezione Hash - Oggetto per la variabile **exclusions** dell'itemSelector. Facilita le operazioni di lookup via hash */
|
|
1048
|
+
this.exclusionsCache = new Map();
|
|
1049
|
+
/** Cache di selezione Hash - Oggetto per la variabile **group_exclusions** dell'itemSelector. Facilita le operazioni di lookup via hash */
|
|
1050
|
+
this.group_exclusionsCache = new Map();
|
|
1051
|
+
/** Cache di selezione Hash - Oggetto per la variabile **items** dell'itemSelector. Facilita le operazioni di lookup via indice*/
|
|
1052
|
+
this.i_itemsCache = new Map();
|
|
1053
|
+
/** Cache di selezione Hash - Oggetto per la variabile **groups** dell'itemSelector. Facilita le operazioni di lookup via indice */
|
|
1054
|
+
this.i_groupsCache = new Map();
|
|
1055
|
+
/** Cache di selezione Hash - Oggetto per la variabile **exclusions** dell'itemSelector. Facilita le operazioni di lookup via indice */
|
|
1056
|
+
this.i_exclusionsCache = new Map();
|
|
1057
|
+
/** Cache di selezione Hash - Oggetto per la variabile **group_exclusions** dell'itemSelector. Facilita le operazioni di lookup via indice */
|
|
1058
|
+
this.i_group_exclusionsCache = new Map();
|
|
1059
|
+
/** Indica se nonostante siamo in modalità array sono stati individuati dei gruppi. In tal caso es-table si comporta da pseudo backend ed effettua le aggregazioni e raggruppamenti completamente lato client */
|
|
1060
|
+
this.ArrayGrouping = false;
|
|
1061
|
+
this.PagerOptions = { PagerCount: null, ShowCount: true, ShowPaging: true, UsesView: true, View: null, Ready: false, Searches: 'items' };
|
|
954
1062
|
/** @ignore */
|
|
955
1063
|
this.propagateChange = (_) => { };
|
|
956
1064
|
if (ngControl)
|
|
957
1065
|
ngControl.valueAccessor = this;
|
|
1066
|
+
// Assegnazione per tutti gli Input di default
|
|
1067
|
+
this.ColumnsResizable = this.InputOrDefault(this.ColumnsResizable, (_a = this.deafults) === null || _a === void 0 ? void 0 : _a.ColumnsResizable);
|
|
1068
|
+
this.AutoUpdate = this.InputOrDefault(this.AutoUpdate, (_b = this.deafults) === null || _b === void 0 ? void 0 : _b.AutoUpdate);
|
|
1069
|
+
this.AllSearch = this.InputOrDefault(this.AllSearch, (_c = this.deafults) === null || _c === void 0 ? void 0 : _c.AllSearch, true);
|
|
1070
|
+
this.Export = this.InputOrDefault(this.Export, (_d = this.deafults) === null || _d === void 0 ? void 0 : _d.Export);
|
|
1071
|
+
this.HidePaging = this.InputOrDefault(this.HidePaging, (_e = this.deafults) === null || _e === void 0 ? void 0 : _e.HidePaging, false);
|
|
1072
|
+
this.HidePagingCount = this.InputOrDefault(this.HidePagingCount, (_f = this.deafults) === null || _f === void 0 ? void 0 : _f.HidePagingCount);
|
|
1073
|
+
this.HidePagingButtons = this.InputOrDefault(this.HidePagingButtons, (_g = this.deafults) === null || _g === void 0 ? void 0 : _g.HidePagingButtons);
|
|
1074
|
+
this.ContainerClass = this.InputOrDefault(this.ContainerClass, (_h = this.deafults) === null || _h === void 0 ? void 0 : _h.ContainerClass, '');
|
|
1075
|
+
this.TableClass = this.InputOrDefault(this.TableClass, (_j = this.deafults) === null || _j === void 0 ? void 0 : _j.TableClass, 'table table-striped table-hover table-sm');
|
|
1076
|
+
this.Selection = this.InputOrDefault(this.Selection, (_k = this.deafults) === null || _k === void 0 ? void 0 : _k.Selection);
|
|
1077
|
+
this.SavePreferences = this.InputOrDefault(this.SavePreferences, (_l = this.deafults) === null || _l === void 0 ? void 0 : _l.SavePreferences);
|
|
1078
|
+
this.PagingStyle = this.InputOrDefault(this.PagingStyle, (_m = this.deafults) === null || _m === void 0 ? void 0 : _m.PagingStyle, 'bottom');
|
|
1079
|
+
this.RowGroupingPagingStyle = this.InputOrDefault(this.RowGroupingPagingStyle, (_o = this.deafults) === null || _o === void 0 ? void 0 : _o.RowGroupingPagingStyle, 'left');
|
|
1080
|
+
this.UseSelectionCache = this.InputOrDefault(this.UseSelectionCache, (_p = this.deafults) === null || _p === void 0 ? void 0 : _p.UseSelectionCache, true);
|
|
1081
|
+
this.ShowItemGroupsColumns = this.InputOrDefault(this.ShowItemGroupsColumns, (_q = this.deafults) === null || _q === void 0 ? void 0 : _q.ShowItemGroupsColumns, false);
|
|
1082
|
+
this.ArraymodeItemsPerPage = this.InputOrDefault(this.ArraymodeItemsPerPage, (_r = this.deafults) === null || _r === void 0 ? void 0 : _r.ArraymodeItemsPerPage, 15);
|
|
958
1083
|
}
|
|
1084
|
+
// #region Ciclo di vita ES-Table - Inizializzazioni
|
|
959
1085
|
/** @ignore */
|
|
960
1086
|
ngOnInit() {
|
|
961
1087
|
//Per poter cambiare il layout in base al livello gerarchico il componente deva avere il pieno controllo di ogni cella,
|
|
@@ -964,6 +1090,9 @@ class EsTableComponent {
|
|
|
964
1090
|
throw "Es-table error: Per poter utilizzare l'es-table con [Hierarchy]=\"true\" è richiesto anche [UseCustomCells]=\"true\"";
|
|
965
1091
|
// click destro su una riga con selezione attiva: Tiro fuori il context menu e selezione l'elemento corrente
|
|
966
1092
|
this.ctxMenuSubscription = (this.ContextMenu || this.tableEmptyMenu).open.subscribe(t => {
|
|
1093
|
+
// Gruppi va bene, oggetti pure, ma separatori fra gruppi proprio no...
|
|
1094
|
+
if (t.item._sep)
|
|
1095
|
+
return;
|
|
967
1096
|
let shouldEmit = !t.item._selected;
|
|
968
1097
|
t.item._selected = true;
|
|
969
1098
|
var itemSelection = this.handleItemsSelection([t.item]);
|
|
@@ -991,6 +1120,26 @@ class EsTableComponent {
|
|
|
991
1120
|
this.ShiftClick = true;
|
|
992
1121
|
}
|
|
993
1122
|
}
|
|
1123
|
+
/**
|
|
1124
|
+
* Se l'Input è null (valore non settato) vede se c'è un default con cui valorizzarlo. Se non c'è utilizza il valore di fallback (qualora fornito)
|
|
1125
|
+
*
|
|
1126
|
+
* @param {T} inputValue Valore dell'Input
|
|
1127
|
+
* @param {T} defaultValue Valore di default impostato da configurazione
|
|
1128
|
+
* @param {T} fallbackValue Valore dell'Input per quando non è stato assegnato dal programmatore e non ha un default
|
|
1129
|
+
*/
|
|
1130
|
+
InputOrDefault(inputValue, defaultValue, fallbackValue) {
|
|
1131
|
+
// Input valorizzato dal programmatore
|
|
1132
|
+
if (inputValue != null && inputValue != undefined)
|
|
1133
|
+
return inputValue;
|
|
1134
|
+
// Input valorizzato da configurazione globale
|
|
1135
|
+
if (defaultValue != null && defaultValue != undefined)
|
|
1136
|
+
return defaultValue;
|
|
1137
|
+
//Input non valorizzato da niente e da nessuno
|
|
1138
|
+
if (fallbackValue != null && fallbackValue != undefined)
|
|
1139
|
+
return fallbackValue;
|
|
1140
|
+
// I casi in cui si arriva qui sono i casi di Input che di default va bene che siano nulli e che nessuno si caga
|
|
1141
|
+
return null;
|
|
1142
|
+
}
|
|
994
1143
|
/** @ignore */
|
|
995
1144
|
ngOnDestroy() {
|
|
996
1145
|
if (this.ctxMenuSubscription)
|
|
@@ -1004,6 +1153,7 @@ class EsTableComponent {
|
|
|
1004
1153
|
this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
|
|
1005
1154
|
});
|
|
1006
1155
|
}
|
|
1156
|
+
// #endregion
|
|
1007
1157
|
// #region Implementazione ControlValueAccessor ignorabile
|
|
1008
1158
|
/** @ignore */
|
|
1009
1159
|
registerOnChange(fn) { this.propagateChange = fn; }
|
|
@@ -1014,6 +1164,7 @@ class EsTableComponent {
|
|
|
1014
1164
|
// #endregion
|
|
1015
1165
|
/** @ignore */
|
|
1016
1166
|
writeValue(obj) {
|
|
1167
|
+
var _a;
|
|
1017
1168
|
this.View = obj ? obj : null;
|
|
1018
1169
|
// Mi è arrivata l'AppSearch quindi di sicuro non ho una ricerca in progress
|
|
1019
1170
|
this.researchInProgress = false;
|
|
@@ -1046,10 +1197,11 @@ class EsTableComponent {
|
|
|
1046
1197
|
else if (this.View && this.View instanceof AppSearch) {
|
|
1047
1198
|
// Se cambia l'oggetto intero significa che ho rimandato la ricerca
|
|
1048
1199
|
this.setMode('view');
|
|
1200
|
+
let firstItemGroupOrNoGrouping = (((_a = this.View.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) || 0) == 0;
|
|
1049
1201
|
// Se vengo da una ricerca interna mantengo lo stato di selezione precedente (quindi su cambio pagina, cambio ipp, ecc...)
|
|
1050
1202
|
// se invece l'utente ha fatto una ricerca lui (quindi cambiando filtri), secco le info di selezione
|
|
1051
|
-
if (!this.View.selection || !this.View.internalsearchrequest || !this.UseSelectionCache) {
|
|
1052
|
-
this.
|
|
1203
|
+
if (!this.View.selection || (!this.View.internalsearchrequest && firstItemGroupOrNoGrouping) || !this.UseSelectionCache) {
|
|
1204
|
+
this.clearSelectionCaches();
|
|
1053
1205
|
this.View.selection = new ItemsSelection([]);
|
|
1054
1206
|
this.onSelectionChanged.emit(this.View.selection);
|
|
1055
1207
|
}
|
|
@@ -1068,56 +1220,136 @@ class EsTableComponent {
|
|
|
1068
1220
|
}
|
|
1069
1221
|
}
|
|
1070
1222
|
}
|
|
1071
|
-
|
|
1223
|
+
// La paginazione devo farla solamente quando richiedo o un gruppo principale (se sono in row grouping) o se non richiedo gruppi (in tutti lgi altri casi)
|
|
1224
|
+
if (firstItemGroupOrNoGrouping)
|
|
1225
|
+
this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages || 1);
|
|
1072
1226
|
}
|
|
1073
1227
|
else if (this.View && (this.View.length != null && this.View.length != undefined)) {
|
|
1074
1228
|
this.setMode('array');
|
|
1075
1229
|
if (!this.UseSelectionCache || !this.arraymodeSelection) {
|
|
1076
|
-
this.
|
|
1230
|
+
this.clearSelectionCaches();
|
|
1077
1231
|
this.arraymodeSelection = new ItemsSelection([]);
|
|
1078
1232
|
;
|
|
1079
1233
|
this.onSelectionChanged.emit(this.arraymodeSelection);
|
|
1080
1234
|
}
|
|
1235
|
+
// Recupero Preference
|
|
1236
|
+
if (this.SavePreferences) {
|
|
1237
|
+
if (!this.ngControl.name)
|
|
1238
|
+
console.error("Non posso utilizzare le preference senza avere un 'name' per questa tabella");
|
|
1239
|
+
else if (!this.prefService)
|
|
1240
|
+
console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
|
|
1241
|
+
else {
|
|
1242
|
+
var prefs = this.prefService.retrieve(this.ngControl.name);
|
|
1243
|
+
if (prefs) {
|
|
1244
|
+
this.arrayColumns = prefs.columns;
|
|
1245
|
+
this.arrayColumnOrdering = prefs.column_ordering;
|
|
1246
|
+
}
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1081
1249
|
if (this.SearchView)
|
|
1082
1250
|
this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
|
|
1083
1251
|
}
|
|
1084
|
-
if (this.View && !(this.View instanceof ReportDefinition))
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1252
|
+
if (this.View && !(this.View instanceof ReportDefinition))
|
|
1253
|
+
this.finalizeContext();
|
|
1254
|
+
this.postBoundSourceCalculation();
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Successivamente al bind del nuovo input questa funzione si occupa di finalizzare tutti i parametri di funzionamento dell'es-table
|
|
1258
|
+
* in base a Input - Modello, e qualsiasi altra cosa possa servire
|
|
1259
|
+
*/
|
|
1260
|
+
finalizeContext() {
|
|
1261
|
+
let viewCasted = this.View;
|
|
1262
|
+
/*
|
|
1263
|
+
*Uso la tecnica di EndlessScroll se la variabile relativa è attiva e se
|
|
1264
|
+
* 1) Ho un Array, oppure
|
|
1265
|
+
* 2) Ho un AppSearch che sta cercando con paginazione "Tutto", oppure
|
|
1266
|
+
* 3) Ho un AppSearch che sta cercando con paginazione diversa da "Tutto" ma con la variabile EndlessScrollOnlyForAll a false
|
|
1267
|
+
*/
|
|
1268
|
+
let isAppSearchWithIppMax = this.viewMode && viewCasted.itemsperpageoverride == this.defaultAllPageOverride;
|
|
1269
|
+
let isAppSearchNoMaxIpp = this.viewMode && viewCasted.itemsperpageoverride != this.defaultAllPageOverride;
|
|
1270
|
+
this.UseEndlessscroll = this.EndlessScroll && (this.arrayMode || isAppSearchWithIppMax || (isAppSearchNoMaxIpp && !this.EndlessScrollOnlyForAll));
|
|
1271
|
+
let hasRowGroups = (viewCasted.groupings && viewCasted.groupings.filter(t => !t.aggregation).length > 0) || (this.arrayMode && this.EsThsDirective.some(t => t.thGroup));
|
|
1272
|
+
// Se ho dei gruppi in modalità array devo sistemare un po' di variabili che diventano insensate
|
|
1273
|
+
if (this.arrayMode) {
|
|
1274
|
+
if (hasRowGroups)
|
|
1275
|
+
this.UseArrayModePaging = false;
|
|
1276
|
+
}
|
|
1277
|
+
// Riempimento della TMPBoundSource con gli oggetti che verranno poi mostrati ad interfaccia
|
|
1278
|
+
if (this.UseEndlessscroll && !hasRowGroups) {
|
|
1279
|
+
this.addedSlices = [];
|
|
1280
|
+
this.boundSubSources = this.getItemSlices();
|
|
1281
|
+
let firstSub = this.boundSubSources[0];
|
|
1282
|
+
this.TMPBoundSource = firstSub ? firstSub : [];
|
|
1283
|
+
if (firstSub)
|
|
1284
|
+
this.addedSlices.push(0);
|
|
1285
|
+
}
|
|
1286
|
+
else
|
|
1287
|
+
this.TMPBoundSource = this.getItemsByMode(false, !this.internalWriteCall);
|
|
1288
|
+
// Se ho una gerarchia, assegno i livelli gerarchici alla TMPBoundSource
|
|
1289
|
+
if (this.Hierarchy && !hasRowGroups)
|
|
1290
|
+
this.assignHierarchyLevels(this.TMPBoundSource);
|
|
1291
|
+
// L'hashing degli oggetti lo faccio a prescindere
|
|
1292
|
+
this.calculateHash(this.TMPBoundSource);
|
|
1293
|
+
// Assegno a una variabile mia l'eventuale override per la classe della riga
|
|
1294
|
+
// Se poi sono in modalità gerarchica inietto anche la classe per la configurazione del livello della riga
|
|
1295
|
+
if ((this.TMPBoundSource && this.RowClassAssigner) || this.Hierarchy) {
|
|
1296
|
+
for (let i = 0; i < this.TMPBoundSource.length; i++) {
|
|
1297
|
+
let item = this.TMPBoundSource[i];
|
|
1298
|
+
item._rowClass = this.RowClassAssigner ? this.RowClassAssigner(item) : "";
|
|
1299
|
+
item._rowClass += this.Hierarchy ? " est-row-lvl-" + item._level : "";
|
|
1102
1300
|
}
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1301
|
+
}
|
|
1302
|
+
}
|
|
1303
|
+
/** Genera le informzioni di paginazione per la vista globale dell'es-table */
|
|
1304
|
+
setupPagingInformations() {
|
|
1305
|
+
this.PagerOptions.ShowCount = !this.HidePagingCount;
|
|
1306
|
+
if (this.arrayMode && this.UseArrayModePaging && !this.SearchView) {
|
|
1307
|
+
this.PagerOptions.PagerCount = this.View.length || 0;
|
|
1308
|
+
this.PagerOptions.ShowPaging = !this.HidePaging && this.View.length > 10;
|
|
1309
|
+
this.PagerOptions.View = this.View;
|
|
1310
|
+
this.PagerOptions.UsesView = false;
|
|
1311
|
+
}
|
|
1312
|
+
else if (this.arrayMode && (!this.UseArrayModePaging || this.SearchView)) {
|
|
1313
|
+
if (this.SearchView) {
|
|
1314
|
+
this.PagerOptions.View = this.SearchView;
|
|
1315
|
+
this.PagerOptions.PagerCount = this.SearchView.objectcount || 0;
|
|
1116
1316
|
}
|
|
1317
|
+
else
|
|
1318
|
+
this.PagerOptions.PagerCount = this.View.length || 0;
|
|
1319
|
+
this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (this.View && this.View.length) || (this.SearchView && this.SearchView.objectcount && this.SearchView.objectcount != -1);
|
|
1320
|
+
}
|
|
1321
|
+
else if (this.viewMode) {
|
|
1322
|
+
let tmpView = this.MainGroupView || this.View;
|
|
1323
|
+
let count = (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) || (tmpView === null || tmpView === void 0 ? void 0 : tmpView.objectcount);
|
|
1324
|
+
this.PagerOptions.Searches = (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) != null && (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) != undefined ? 'groups' : 'items';
|
|
1325
|
+
this.PagerOptions.PagerCount = count || 0;
|
|
1326
|
+
this.PagerOptions.View = tmpView;
|
|
1327
|
+
this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (tmpView && count && count != -1);
|
|
1328
|
+
this.PagerOptions.ShowPaging = !this.HidePaging;
|
|
1329
|
+
}
|
|
1330
|
+
else if (this.reportMode) {
|
|
1331
|
+
let rvc = this.ReportValues.count;
|
|
1332
|
+
this.PagerOptions.View = this.View;
|
|
1333
|
+
this.PagerOptions.PagerCount = rvc && rvc == -1 ? this.ReportValues.rows.length : rvc && rvc > 0 ? this.ReportValues.count : 0;
|
|
1334
|
+
this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (this.View && this.View.objectcount && this.View.objectcount != -1);
|
|
1335
|
+
this.PagerOptions.ShowPaging = !this.HidePaging && this.View.pagingavailable;
|
|
1117
1336
|
}
|
|
1118
|
-
this.postBoundSourceCalculation();
|
|
1119
1337
|
}
|
|
1120
|
-
|
|
1338
|
+
/**
|
|
1339
|
+
* Ripulisce le cache di selezione
|
|
1340
|
+
*
|
|
1341
|
+
* @todo: SELECTION
|
|
1342
|
+
*/
|
|
1343
|
+
clearSelectionCaches() {
|
|
1344
|
+
this.itemsCache.clear();
|
|
1345
|
+
this.groupsCache.clear();
|
|
1346
|
+
this.exclusionsCache.clear();
|
|
1347
|
+
this.group_exclusionsCache.clear();
|
|
1348
|
+
this.i_itemsCache.clear();
|
|
1349
|
+
this.i_groupsCache.clear();
|
|
1350
|
+
this.i_exclusionsCache.clear();
|
|
1351
|
+
this.i_group_exclusionsCache.clear();
|
|
1352
|
+
}
|
|
1121
1353
|
/**
|
|
1122
1354
|
* In base alla modalità specificata (ArrayMode, ViewMode, ecc...) questo metodo recupera l'array di oggetti da bindare ad interfaccia
|
|
1123
1355
|
*
|
|
@@ -1126,6 +1358,8 @@ class EsTableComponent {
|
|
|
1126
1358
|
* @param {boolean} allIfPossible [false] Indica se prendere tutti gli oggetti quaora possibile, usato solo in ArrayMode
|
|
1127
1359
|
*
|
|
1128
1360
|
* @returns {any[]} Lista degli oggetti su cui effettuare il bind lato interfaccia
|
|
1361
|
+
*
|
|
1362
|
+
* @todo: ITEMS
|
|
1129
1363
|
*/
|
|
1130
1364
|
getItemsByMode(onlyselected = false, refreshPaging = false, allIfPossible = false) {
|
|
1131
1365
|
let items = [];
|
|
@@ -1133,6 +1367,8 @@ class EsTableComponent {
|
|
|
1133
1367
|
items = this.getViewItemsBySource();
|
|
1134
1368
|
}
|
|
1135
1369
|
else if (this.arrayMode) {
|
|
1370
|
+
this.View.forEach(itm => { itm._item = true; });
|
|
1371
|
+
// Se faccio dei raggruppamenti ignoro la paginazione
|
|
1136
1372
|
if (this.UseArrayModePaging && !allIfPossible) {
|
|
1137
1373
|
// Se sono in modalità array ma la ricerca dipende da una view devo riallineare gli itemperpage
|
|
1138
1374
|
if (this.SearchView)
|
|
@@ -1151,7 +1387,11 @@ class EsTableComponent {
|
|
|
1151
1387
|
return items.filter(t => t._selected);
|
|
1152
1388
|
return items;
|
|
1153
1389
|
}
|
|
1154
|
-
/**
|
|
1390
|
+
/**
|
|
1391
|
+
* @ignore
|
|
1392
|
+
*
|
|
1393
|
+
* @todo: ITEMS
|
|
1394
|
+
*/
|
|
1155
1395
|
getViewItemsBySource() {
|
|
1156
1396
|
var _a, _b;
|
|
1157
1397
|
let castedView = this.View;
|
|
@@ -1159,8 +1399,12 @@ class EsTableComponent {
|
|
|
1159
1399
|
//Gruppi intermedi
|
|
1160
1400
|
if ((((_a = castedView.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) != groupKeys || ((_b = castedView.requestedgroups) === null || _b === void 0 ? void 0 : _b.length) == 0) && groupKeys > 0) {
|
|
1161
1401
|
let ret = castedView.groups;
|
|
1162
|
-
|
|
1163
|
-
|
|
1402
|
+
ret.forEach(itm => {
|
|
1403
|
+
// Setto variabile interna per capire che questo è in realtà un gruppo
|
|
1404
|
+
itm._group = true;
|
|
1405
|
+
// Le informazioni passate come lista le metto dentro a una cache per velocizzarne l'accesso quando devo tirare fuori il display della proprietà
|
|
1406
|
+
this.cacheAggregations(itm);
|
|
1407
|
+
});
|
|
1164
1408
|
return ret;
|
|
1165
1409
|
}
|
|
1166
1410
|
else {
|
|
@@ -1170,10 +1414,31 @@ class EsTableComponent {
|
|
|
1170
1414
|
return ret;
|
|
1171
1415
|
}
|
|
1172
1416
|
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Helper per effettuare il caching delle aggregazioni. Le sposta da una lista di **GroupAggregation** a una **<Map<string, Map<string, string>>**
|
|
1419
|
+
*
|
|
1420
|
+
* @todo: ROWGROUPING
|
|
1421
|
+
*/
|
|
1422
|
+
cacheAggregations(group) {
|
|
1423
|
+
group._aggregationsCache = new Map();
|
|
1424
|
+
let castedAgCache = group._aggregationsCache;
|
|
1425
|
+
for (let i = 0; i < group.aggregations.length; i++) {
|
|
1426
|
+
let agg = group.aggregations[i];
|
|
1427
|
+
if (castedAgCache.has(agg.column))
|
|
1428
|
+
castedAgCache.get(agg.column).set(agg.aggregation, agg.value);
|
|
1429
|
+
else {
|
|
1430
|
+
let tmp = new Map();
|
|
1431
|
+
tmp.set(agg.aggregation, agg.value);
|
|
1432
|
+
castedAgCache.set(agg.column, tmp);
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1173
1436
|
/**
|
|
1174
1437
|
* Metodo che prende tutti gli oggetti di cui dispone divisi in bucket da 100 elementi
|
|
1175
1438
|
*
|
|
1176
1439
|
* @returns {any[][]} Matrice di array Nx100
|
|
1440
|
+
*
|
|
1441
|
+
* @todo: ITEMS
|
|
1177
1442
|
*/
|
|
1178
1443
|
getItemSlices() {
|
|
1179
1444
|
// Se sono qui di sicuro non ho rowgrouping
|
|
@@ -1210,8 +1475,6 @@ class EsTableComponent {
|
|
|
1210
1475
|
}
|
|
1211
1476
|
}
|
|
1212
1477
|
}
|
|
1213
|
-
// #endregion
|
|
1214
|
-
// #region Gestione di tutto il ciclo di vita post binding oggetti
|
|
1215
1478
|
/**
|
|
1216
1479
|
* Metodo lanciato dopo che la sorgente dati è stata correttamente bindata, si occupa di ricalcolare tutto ciò che serve
|
|
1217
1480
|
* all'es-table per renderizzare i valori da mostrare
|
|
@@ -1221,69 +1484,322 @@ class EsTableComponent {
|
|
|
1221
1484
|
this.RowContexts = [];
|
|
1222
1485
|
this.OrderDirectives = [];
|
|
1223
1486
|
this.lastSelectedItemID = null;
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
this.
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1487
|
+
if (this.EsThsDirective && this.EsThsDirective.length > 0 && this.EsTdsDirective && this.EsTdsDirective.length > 0)
|
|
1488
|
+
this.internalPostBoundSource();
|
|
1489
|
+
else {
|
|
1490
|
+
this.cdr.detectChanges();
|
|
1491
|
+
setTimeout(() => { this.internalPostBoundSource(); });
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1494
|
+
/**
|
|
1495
|
+
* Per poter distinguere le chiamate a questo metodo: Dopo il setTimeout se uso gli EsTd/EsTh vecchi, senza il setTimeout se uso le nuove direttive
|
|
1496
|
+
*/
|
|
1497
|
+
internalPostBoundSource() {
|
|
1498
|
+
let View = this.View;
|
|
1499
|
+
let ths = this.EsThs && this.EsThs.length > 0 ? this.EsThs.toArray() : this.EsThsDirective && this.EsThsDirective.length > 0 ? this.EsThsDirective.toArray() : [];
|
|
1500
|
+
let tds = this.EsTds && this.EsTds.length > 0 ? this.EsTds.toArray() : this.EsTdsDirective && this.EsTdsDirective.length > 0 ? this.EsTdsDirective.toArray() : [];
|
|
1501
|
+
// Se non ho colonne dinamiche ma sono in modalità dinamica (lo capisco perché c'è una view piena di genericitem) metto il default delle colonne
|
|
1502
|
+
this.eventuallyReviewDynamicColumns();
|
|
1503
|
+
this.bindDisplayToLoadedItemsOrGroups(View);
|
|
1504
|
+
// Questo dev'essere per forza lanciato dopo **bindDisplayToLoadedItemsOrGroups** dato che è lì che alcune cose vengono valorizzate
|
|
1505
|
+
this.setupPagingInformations();
|
|
1506
|
+
// Molte cose sono ovviamente disponibili solo in modalità View
|
|
1507
|
+
if ((this.viewMode || this.arrayMode) && this.UseCustomCells) {
|
|
1508
|
+
let view = this.viewMode ? View : null;
|
|
1509
|
+
let itemsAndGroups = this.viewMode ? [...(view.items || []), ...(view.groups || [])] : View;
|
|
1510
|
+
let si = this.viewMode ? view.selection : this.arraymodeSelection;
|
|
1511
|
+
// N.B: Rispettare l'ordine di queste 3 macrocategorie è VITALE
|
|
1512
|
+
// ************************************* Sistemazioni di TH, TD, e visibilità varie *************************************
|
|
1513
|
+
let hI = this.evaluateHeadersGroupingInfos(ths); // Prepassaggio per tirare fuori tutte le info utili sugli headers in modo da non ricacolarseli sempre dopo
|
|
1514
|
+
if (this.arrayMode) { // In modalità array non ho un backend...
|
|
1515
|
+
this.arrayModeReviewOrderings(); // ... quindi gli ordinamenti li devo fare lato client, e ...
|
|
1516
|
+
this.arrayModeReviewGroupings(hI.leafs); // ... i raggruppamenti li devo fare lato client
|
|
1254
1517
|
}
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1518
|
+
this.reviewColumnsList(hI.leafs); // Aggiorna la lista delle colonne da mostrare nella dialog per ordinamento ecc
|
|
1519
|
+
this.moveFixedColumnsAtTheBeginning(hI.leafs, tds); // Sposto tutte le cose fixed all'inizio in modo che la creazione di th e td sia più snella (Utilizza le ColumnsList, quindi dev'essere richiamata PIRMA di reviewColumnsList)
|
|
1520
|
+
this.alignHeadersOrdering(hI.leafs, view); // Allineo gli ordinamenti agli header
|
|
1521
|
+
this.alignColumnsIfLoadedView(view); // Se sto caricando una View da hotpotato (quindi con savedstate = true) riallineo la visibilità delle colonne e il loro ordine.
|
|
1522
|
+
this.refreshColumnsVisibility(hI.leafs, tds, view); // Lavoro sui TH ed eventualmente modifico la visibilità anche dei TD.
|
|
1523
|
+
this.evaluatePinnedColumnsWidth(); // Se sono presenti colonne pinnate valuta la dimensione del contenitore
|
|
1524
|
+
this.generateDefaultOrder(hI.leafs, view); // Genero le direttive di ordinamento, che siano default o derivanti dalla AppSearch
|
|
1525
|
+
this.evaluateHeaderGroups(hI); // Valuto i raggruppamenti degli header se presenti
|
|
1526
|
+
// ************************************* Generazione binding per righe e colonne *************************************
|
|
1527
|
+
this.evaluateRowThs(hI.leafs); // Raccolgo i TH
|
|
1528
|
+
this.evaluateRowTds(hI.leafs, tds); // Raccolgo i TD in contesti separati, un contesto per ogni item o gruppo
|
|
1529
|
+
// ************************************* Ultimi aggiustmaenti dei binding *************************************
|
|
1530
|
+
this.applyOrdering(view, true); // Applico l'ordinamento sulle colonne (non ASC DESC, ma "prima questa o quella colonna")
|
|
1531
|
+
this.MoveTemporaryVariablesToRealOnes(); // Collego TH e TD aggiustati fino ad ora alle variabili di Binding HTML
|
|
1532
|
+
this.evaluateSelection(itemsAndGroups, si); // Riallineo le info di selezione degli elementi della View
|
|
1533
|
+
if (this.ResearchNeeded) {
|
|
1534
|
+
this.changed();
|
|
1535
|
+
this.emitSearchRequest(false);
|
|
1536
|
+
this.ResearchNeeded = false;
|
|
1259
1537
|
}
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
//
|
|
1263
|
-
this.
|
|
1264
|
-
this.
|
|
1265
|
-
|
|
1538
|
+
}
|
|
1539
|
+
else if ((this.viewMode || this.arrayMode) && !this.UseCustomCells) {
|
|
1540
|
+
// Riallineo le info di selezione degli elementi della View
|
|
1541
|
+
let items = this.viewMode ? View.items : View;
|
|
1542
|
+
let si = this.viewMode ? View.selection : this.arraymodeSelection;
|
|
1543
|
+
this.evaluateSelection(items, si);
|
|
1544
|
+
}
|
|
1545
|
+
// Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
|
|
1546
|
+
this.cdr.markForCheck();
|
|
1547
|
+
this.FirstBind = false;
|
|
1266
1548
|
}
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1549
|
+
/**
|
|
1550
|
+
* Se in modalità array applica gli ordinamenti ASC-DESC delle colonne
|
|
1551
|
+
*
|
|
1552
|
+
* @todo: INTERNALDB
|
|
1553
|
+
*/
|
|
1554
|
+
arrayModeReviewOrderings() {
|
|
1555
|
+
if (this.arrayOrders.length > 0)
|
|
1556
|
+
this.arrayOrders.forEach(t => {
|
|
1557
|
+
this.boundSource = this.boundSource.sort((a, b) => (a[t.id] > b[t.id] ? 1 : -1) * (t.order == 'DESC' ? -1 : 1));
|
|
1558
|
+
});
|
|
1559
|
+
}
|
|
1560
|
+
/**
|
|
1561
|
+
* Se in modalità array applica i raggruppamenti definiti lato row-grouping
|
|
1562
|
+
*
|
|
1563
|
+
* @param {ths: EsTh[] | EsThDirective[]} ths Header
|
|
1564
|
+
*
|
|
1565
|
+
* @todo: ROW GROUPING
|
|
1566
|
+
*/
|
|
1567
|
+
arrayModeReviewGroupings(ths) {
|
|
1568
|
+
if (ths.length == 0)
|
|
1569
|
+
return;
|
|
1570
|
+
if (this.isEsTh(ths[0]))
|
|
1270
1571
|
return;
|
|
1572
|
+
let headerGroups = [];
|
|
1573
|
+
let headerAggregations = [];
|
|
1574
|
+
for (let i = 0; i < ths.length; i++) {
|
|
1575
|
+
let th = ths[i];
|
|
1576
|
+
if (th.thGroup)
|
|
1577
|
+
headerGroups.push(new Group(th.th, 0, ""));
|
|
1578
|
+
else if (th.thAggregation)
|
|
1579
|
+
headerAggregations = [...headerAggregations, ...this.getGroupAggregations(th)];
|
|
1580
|
+
}
|
|
1581
|
+
if (headerGroups.length > 0) {
|
|
1582
|
+
// Pulizia delle cache
|
|
1583
|
+
this.rgGroupCache.clear();
|
|
1584
|
+
this.rgItemCache.clear();
|
|
1585
|
+
this.rgChildGroupsCache.clear();
|
|
1586
|
+
this.ArrayGrouping = true;
|
|
1587
|
+
this.boundSource = this.getGroupsRecursive(headerGroups, 0, this.boundSource, headerAggregations, null);
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Data la definizione dei gruppi da generare da una lista di oggetti, suddivide gli oggetti passati in gruppi e sottogruppi
|
|
1592
|
+
*
|
|
1593
|
+
* @param {Group[]} grps Definizione dei gruppi
|
|
1594
|
+
* @param {number} currentIndex Indice di elaborazione. Al livello 0 ho tutti gli oggetti e devo generare i primi gruppi, a livello 1 ho tutti i gruppi principali e devo
|
|
1595
|
+
* elaborare i sottogruppi, e così via ricorsivamente...
|
|
1596
|
+
* @param {any[]} items Oggetti da raggruppare
|
|
1597
|
+
* @param {GroupOrAggregation[]} aggregations Info di aggregazione
|
|
1598
|
+
* @param {any} parent Riferimento al gruppo padre
|
|
1599
|
+
*
|
|
1600
|
+
* @todo: INTERNALDB
|
|
1601
|
+
*/
|
|
1602
|
+
getGroupsRecursive(grps, currentIndex, items, aggregations, parent) {
|
|
1603
|
+
// Se l'indice è 0 devo sicuramente nascondere tutti gli oggetti. Solo i gruppi saranno visualizzati
|
|
1604
|
+
if (currentIndex == 0)
|
|
1605
|
+
items.forEach(i => i._visible = false);
|
|
1606
|
+
let grp = grps[currentIndex];
|
|
1607
|
+
let ret = [];
|
|
1608
|
+
let last = grps.length == currentIndex + 1;
|
|
1609
|
+
let groups = this.groupBy(items, grp.column);
|
|
1610
|
+
for (let prop in groups) {
|
|
1611
|
+
let itms = groups[prop];
|
|
1612
|
+
let gp = new Group(grp.column, itms.length, prop);
|
|
1613
|
+
gp.aggregations = this.generateAggregations(itms, aggregations);
|
|
1614
|
+
let anygp = gp;
|
|
1615
|
+
anygp._group = true;
|
|
1616
|
+
anygp._expanded = false;
|
|
1617
|
+
if (!parent) {
|
|
1618
|
+
anygp._thisRoute = [{ column: gp.column, value: gp.value }];
|
|
1619
|
+
anygp._thisKey = gp.value;
|
|
1620
|
+
anygp._grouplevel = 0;
|
|
1621
|
+
}
|
|
1622
|
+
else {
|
|
1623
|
+
anygp._parent = parent._thisKey;
|
|
1624
|
+
anygp._parentRoute = parent._thisRoute;
|
|
1625
|
+
anygp._thisRoute = [...parent._thisRoute, { column: gp.column, value: gp.value }];
|
|
1626
|
+
anygp._thisKey = parent._thisKey + gp.value;
|
|
1627
|
+
anygp._grouplevel = parent._grouplevel + 1;
|
|
1628
|
+
}
|
|
1629
|
+
// Pusho il gruppo, tutti i gruppi del livello sotto, o gli item se io sono l'ultimo gruppo.
|
|
1630
|
+
// La visibilità è solo per il gruppo a livello 0, tutti gli altri gruppi saranno mostrati o nascosti di conseguenza
|
|
1631
|
+
if (currentIndex == 0)
|
|
1632
|
+
anygp._visible = true;
|
|
1633
|
+
this.calculateHash([anygp]);
|
|
1634
|
+
this.cacheAggregations(anygp);
|
|
1635
|
+
// Aggiungo il gruppo padre
|
|
1636
|
+
ret.push(anygp);
|
|
1637
|
+
this.rgGroupCache.set(anygp._thisKey, anygp);
|
|
1638
|
+
if (!last) {
|
|
1639
|
+
//Dal gruppo padre, se non è l'ultimo gruppo della catena, calcolo ricorsivamente tutta la catena sotto
|
|
1640
|
+
let subGroupsAndItems = this.getGroupsRecursive(grps, currentIndex + 1, itms, aggregations, anygp);
|
|
1641
|
+
let childgroups = subGroupsAndItems.filter(t => t._group && t._parent == anygp._thisKey);
|
|
1642
|
+
anygp._groupscount = childgroups.length;
|
|
1643
|
+
// Aggiungo la catena del gruppo sotto, aggiungendo alla cache solo i gruppi padre
|
|
1644
|
+
ret.push(...subGroupsAndItems);
|
|
1645
|
+
this.rgChildGroupsCache.set(anygp._thisKey, childgroups);
|
|
1646
|
+
}
|
|
1647
|
+
else {
|
|
1648
|
+
// Al gruppo padre, se è l'ultimo assegno tutte le foglie assegnandogli anche la chiave del gruppo
|
|
1649
|
+
itms.forEach(i => i._thisKey = anygp._thisKey);
|
|
1650
|
+
ret.push(...itms);
|
|
1651
|
+
this.rgItemCache.set(anygp._thisKey, itms);
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
return ret;
|
|
1655
|
+
}
|
|
1656
|
+
/**
|
|
1657
|
+
* Data una lista di oggetti genera le aggregazioni specificate. Si considera di avere tutti gli oggetti
|
|
1658
|
+
*
|
|
1659
|
+
* @param {any[]} items Oggetti di cui calcolare le aggregazione
|
|
1660
|
+
* @param {GroupOrAggregation[]} aggregations Aggergazioni da generare
|
|
1661
|
+
*
|
|
1662
|
+
* @todo: INTERNALDB
|
|
1663
|
+
*/
|
|
1664
|
+
generateAggregations(items, aggregations) {
|
|
1665
|
+
let rets = [];
|
|
1666
|
+
let aggregationValue = "", feField = null, stringAgg = null, dateAgg = null, numberAgg = null;
|
|
1667
|
+
for (let i = 0; i < aggregations.length; i++) {
|
|
1668
|
+
let agg = aggregations[i];
|
|
1669
|
+
feField = agg.column;
|
|
1670
|
+
if (!feField)
|
|
1671
|
+
continue;
|
|
1672
|
+
switch (agg.datatype) {
|
|
1673
|
+
case 'string':
|
|
1674
|
+
stringAgg = items.map(i => i[feField].toString());
|
|
1675
|
+
break;
|
|
1676
|
+
case 'date':
|
|
1677
|
+
dateAgg = items.map(i => new Date(i[feField]).getTime());
|
|
1678
|
+
break;
|
|
1679
|
+
case 'number':
|
|
1680
|
+
numberAgg = items.map(i => parseFloat(i[feField]));
|
|
1681
|
+
break;
|
|
1682
|
+
}
|
|
1683
|
+
switch (agg.aggregation) {
|
|
1684
|
+
case 'max':
|
|
1685
|
+
switch (agg.datatype) {
|
|
1686
|
+
case 'string':
|
|
1687
|
+
aggregationValue = stringAgg.sort().reverse()[0];
|
|
1688
|
+
break;
|
|
1689
|
+
case 'date':
|
|
1690
|
+
aggregationValue = new Date(Math.max(...dateAgg)).toString();
|
|
1691
|
+
break;
|
|
1692
|
+
case 'number':
|
|
1693
|
+
aggregationValue = Math.max(...numberAgg).toString();
|
|
1694
|
+
break;
|
|
1695
|
+
}
|
|
1696
|
+
break;
|
|
1697
|
+
case 'min':
|
|
1698
|
+
switch (agg.datatype) {
|
|
1699
|
+
case 'string':
|
|
1700
|
+
aggregationValue = stringAgg.sort()[0];
|
|
1701
|
+
break;
|
|
1702
|
+
case 'date':
|
|
1703
|
+
aggregationValue = new Date(Math.min(...dateAgg)).toString();
|
|
1704
|
+
break;
|
|
1705
|
+
case 'number':
|
|
1706
|
+
aggregationValue = Math.min(...numberAgg).toString();
|
|
1707
|
+
break;
|
|
1708
|
+
}
|
|
1709
|
+
break;
|
|
1710
|
+
case 'sum':
|
|
1711
|
+
switch (agg.datatype) {
|
|
1712
|
+
case 'string':
|
|
1713
|
+
aggregationValue = stringAgg.join(", ");
|
|
1714
|
+
break;
|
|
1715
|
+
case 'date':
|
|
1716
|
+
aggregationValue = "";
|
|
1717
|
+
break;
|
|
1718
|
+
case 'number':
|
|
1719
|
+
aggregationValue = numberAgg.reduce((pre, curr) => pre + curr, 0).toString();
|
|
1720
|
+
break;
|
|
1721
|
+
}
|
|
1722
|
+
break;
|
|
1723
|
+
}
|
|
1724
|
+
rets.push(new GroupAggregation(agg.column, agg.aggregation, aggregationValue));
|
|
1725
|
+
}
|
|
1726
|
+
return rets;
|
|
1727
|
+
}
|
|
1728
|
+
/**
|
|
1729
|
+
* Data una lista di oggetti effettua dei raggruppamenti in base alla proprietà **field**, restituendo un oggetto del tipo { Gruppo1: oggetti[], Gruppo2: oggetti[], ecc... }
|
|
1730
|
+
*
|
|
1731
|
+
* @param {any[]} array Lista degli oggetti da raggruppare
|
|
1732
|
+
* @param {string} field Campo su cui effettuare i raggruppamenti
|
|
1733
|
+
*
|
|
1734
|
+
* @returns {{ [id: string]: any[] }} Dizionario dei gruppi
|
|
1735
|
+
*
|
|
1736
|
+
* @todo: INTERNALDB
|
|
1737
|
+
*/
|
|
1738
|
+
groupBy(array, field) {
|
|
1739
|
+
let ret = {};
|
|
1740
|
+
for (let i = 0; i < array.length; i++) {
|
|
1741
|
+
let x = array[i];
|
|
1742
|
+
(ret[x[field]] = ret[x[field]] || []).push(x);
|
|
1743
|
+
}
|
|
1744
|
+
return ret;
|
|
1745
|
+
}
|
|
1746
|
+
;
|
|
1747
|
+
/**
|
|
1748
|
+
* Effettua il binding degli oggetti pervenuti da questa chiamata con gli oggetti effettivamente da graficare
|
|
1749
|
+
*
|
|
1750
|
+
* @param {any} view View da cui sono arrivati gli oggetti. Può essere o un array se sono in **arrayMode** o una AppSearch<T> se sono in **viewMode**
|
|
1751
|
+
*/
|
|
1752
|
+
bindDisplayToLoadedItemsOrGroups(view) {
|
|
1753
|
+
var _a, _b;
|
|
1754
|
+
if (this.TMPBoundSource.length == 0) {
|
|
1755
|
+
this.BaseItemsCount = 0;
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1271
1758
|
if (this.arrayMode || !this.UseCustomCells) {
|
|
1272
1759
|
this.boundSource = this.TMPBoundSource;
|
|
1760
|
+
this.BaseItemsCount = (view === null || view === void 0 ? void 0 : view.objectcount) || view.length;
|
|
1273
1761
|
return;
|
|
1274
1762
|
}
|
|
1275
|
-
let view = this.View;
|
|
1276
1763
|
let groupingKeys = ((_b = (_a = view.groupings) === null || _a === void 0 ? void 0 : _a.filter(t => !t.aggregation)) === null || _b === void 0 ? void 0 : _b.length) || 0;
|
|
1277
1764
|
if (groupingKeys == 0) {
|
|
1278
1765
|
this.boundSource = this.TMPBoundSource;
|
|
1766
|
+
this.BaseItemsCount = view.objectcount;
|
|
1279
1767
|
return;
|
|
1280
1768
|
}
|
|
1769
|
+
this.handleNewDataOnRowGrouping(view, groupingKeys);
|
|
1770
|
+
}
|
|
1771
|
+
/**
|
|
1772
|
+
* In modalità rowgrouping quando mi arriva un nuovo blocco di oggetti devo aggiungerlo alla vista attuale:
|
|
1773
|
+
*
|
|
1774
|
+
* 1) Se non viene richiesto il dettaglio di alcun gruppo significa che devo considerare mi siano arrivati tutti i gruppi principali
|
|
1775
|
+
* 2) Se viene richiesto il dettaglio di un gruppo diverso dall'ultimo devo aggiungere dopo al gruppo cliccato la lista dei sottogruppi
|
|
1776
|
+
* 2) Se viene richiesto il dettaglio dell'ultimo gruppo devo aggiungere dopo al gruppo cliccato la lista degli oggetti
|
|
1777
|
+
*
|
|
1778
|
+
* @param {any} view AppSearch<T> da cui sono arrivati gli oggetti
|
|
1779
|
+
* @param {number} groupingKeys Livelli di raggruppamento da aspettarsi sui dati
|
|
1780
|
+
*
|
|
1781
|
+
* @todo: ROWGROUPING
|
|
1782
|
+
*/
|
|
1783
|
+
handleNewDataOnRowGrouping(view, groupingKeys) {
|
|
1784
|
+
var _a, _b;
|
|
1281
1785
|
// 1) Se non viene richiesto il dettaglio di alcun gruppo significa che la chiamata restituisce la lista paginata dei gruppi principali.
|
|
1282
1786
|
// Li tratto come se fosse una qualsiasi altra query paginata su N elementi
|
|
1283
|
-
if ((((
|
|
1787
|
+
if ((((_a = view.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) || 0) == 0) {
|
|
1284
1788
|
this.boundSource = this.TMPBoundSource;
|
|
1789
|
+
this.rgGroupCache = new Map();
|
|
1790
|
+
this.rgItemCache = new Map();
|
|
1791
|
+
this.rgChildGroupsCache = new Map();
|
|
1792
|
+
this.TMPBoundSource.forEach(itm => {
|
|
1793
|
+
itm._thisRoute = itm._group ? [{ column: itm.column, value: itm.value }] : [];
|
|
1794
|
+
itm._thisKey = itm._group ? itm.value : null;
|
|
1795
|
+
itm._grouplevel = 0;
|
|
1796
|
+
this.rgGroupCache.set(itm._thisKey, itm);
|
|
1797
|
+
});
|
|
1285
1798
|
// Resetto la ricerca alla cache di questa "sessione"
|
|
1286
|
-
|
|
1799
|
+
let firstItem = this.TMPBoundSource[0];
|
|
1800
|
+
this.MainGroupView = Object.assign({}, view);
|
|
1801
|
+
this.groupSearchRequestsCache = [{ path: '', route: [{ column: firstItem.column, value: firstItem.value }], view: this.MainGroupView, group_column: this.TMPBoundSource[0].column }];
|
|
1802
|
+
this.BaseItemsCount = view.objectcount;
|
|
1287
1803
|
}
|
|
1288
1804
|
else {
|
|
1289
1805
|
// 2) Se viene richiesto il dettaglio di un qualsiasi gruppo diverso dall'ultimo vuol dire che devo aggiungere
|
|
@@ -1324,22 +1840,68 @@ class EsTableComponent {
|
|
|
1324
1840
|
groupRoute.push({ column: rg.column, value: rg.value });
|
|
1325
1841
|
insertIndex = items.findIndex((t, i) => i >= insertIndex && t._group && t.column == rg.column && t.value == rg.value);
|
|
1326
1842
|
}
|
|
1843
|
+
let itemsCacheReference;
|
|
1844
|
+
let childGroupsCacheReference;
|
|
1845
|
+
// Se non è un gruppo intermedio devo ripulire la cache del gruppo su cui ho attualmente cliccato. Gli oggetti saranno riaggiunti dopo
|
|
1846
|
+
if (!intermediateGroup) {
|
|
1847
|
+
this.rgItemCache.set(groupKey, []);
|
|
1848
|
+
itemsCacheReference = this.rgItemCache.get(groupKey);
|
|
1849
|
+
}
|
|
1850
|
+
else {
|
|
1851
|
+
// Se invece è un gruppo intermedio devo ripulire sia tutti i child group ricorsivamente, sia tutti gli item
|
|
1852
|
+
for (let key of this.rgChildGroupsCache.keys())
|
|
1853
|
+
if (key.startsWith(groupKey))
|
|
1854
|
+
this.rgChildGroupsCache.delete(key);
|
|
1855
|
+
for (let key of this.rgItemCache.keys())
|
|
1856
|
+
if (key.startsWith(groupKey))
|
|
1857
|
+
this.rgItemCache.delete(key);
|
|
1858
|
+
this.rgChildGroupsCache.set(groupKey, []);
|
|
1859
|
+
childGroupsCacheReference = this.rgChildGroupsCache.get(groupKey);
|
|
1860
|
+
}
|
|
1327
1861
|
// Assegno un livello ai valori che arrivano da usare per formattare la parte grafica. Il primo gruppo cliccato sarà a livello 1,
|
|
1328
1862
|
// il secondo sarà a livello 2 e così via...
|
|
1329
1863
|
// Li marco inoltre con il parent in modo da poter eliminare i vecchi qualora servisse
|
|
1330
1864
|
this.TMPBoundSource.forEach(itm => {
|
|
1331
1865
|
itm._parent = groupKey;
|
|
1332
1866
|
itm._parentRoute = groupRoute;
|
|
1333
|
-
|
|
1867
|
+
itm._thisRoute = itm._group ? [...groupRoute, new GroupRouteFragment(itm.column, itm.value)] : [];
|
|
1868
|
+
itm._thisKey = itm._group ? groupKey + itm.value : groupKey;
|
|
1869
|
+
// Per le ricerca intermedie metto i gruppi nella cache dei gruppi
|
|
1870
|
+
if (intermediateGroup) {
|
|
1334
1871
|
itm._grouplevel = view.requestedgroups.length;
|
|
1872
|
+
this.rgGroupCache.set(itm._thisKey, itm);
|
|
1873
|
+
childGroupsCacheReference.push(itm);
|
|
1874
|
+
}
|
|
1875
|
+
else {
|
|
1876
|
+
// Metto anche gli oggetti nella cache non ricorsiva
|
|
1877
|
+
itemsCacheReference.push(itm);
|
|
1878
|
+
}
|
|
1335
1879
|
});
|
|
1336
|
-
//Elimino gli oggetti vecchi
|
|
1337
|
-
|
|
1880
|
+
// Elimino gli oggetti vecchi
|
|
1881
|
+
// 1) Ricerca intermedia, stato salvato - Elimino tutti gli item e tutti i gruppi la cui route è più lunga della corrente, tutti gli item relativi alla path corrente, e tutte
|
|
1882
|
+
// le cache di ricerca effettuate su una path più profonda dell'attuale
|
|
1883
|
+
// 2) Ricerca finale o ricerca intermedia senza stato salvato - Elimino tutti gli item relativi alla path corrente
|
|
1884
|
+
// Per "stato salvato" si intendono ricerche vecchie salvate per poter essere rieffettuate in caso di ordinamenti su colonne di interesse
|
|
1885
|
+
if (intermediateGroup && view.savedstate) {
|
|
1886
|
+
this.boundSource = this.boundSource.filter(t => !(t._item || t._thisRoute.length > groupRoute.length));
|
|
1887
|
+
this.groupSearchRequestsCache = this.groupSearchRequestsCache.filter(t => !(t.route.length > groupRoute.length));
|
|
1888
|
+
}
|
|
1889
|
+
this.boundSource = this.boundSource.filter(t => !(t._parent == groupKey));
|
|
1890
|
+
let thisGroup = this.boundSource[insertIndex];
|
|
1891
|
+
if (intermediateGroup)
|
|
1892
|
+
thisGroup._groupscount = (_b = this.View) === null || _b === void 0 ? void 0 : _b.groupcount;
|
|
1893
|
+
// Li sostituisco coi nuovi di questa ricerca
|
|
1338
1894
|
this.boundSource.splice(insertIndex + 1, 0, ...this.TMPBoundSource);
|
|
1339
|
-
// Aggiungo un separatore alla fine di questi gruppi che dovrà occuparsi di caricare ALTRI gruppi
|
|
1340
|
-
|
|
1895
|
+
// Aggiungo un separatore alla fine o all'inizio di questi gruppi che dovrà occuparsi di caricare ALTRI gruppi o oggetti (se sono all'ultimo gruppo)
|
|
1896
|
+
let addLast = false;
|
|
1897
|
+
this.boundSource.splice(insertIndex + 1 + (addLast ? this.TMPBoundSource.length : 0), 0, this.getGroupSeparator(view, groupKey, groupRoute, view.requestedgroups.length, intermediateGroup ? 'groups' : 'items'));
|
|
1341
1898
|
// Aggiungo la ricerca alla cache di questa "sessione"
|
|
1342
|
-
|
|
1899
|
+
let toAdd = { path: groupKey, route: groupRoute, view: Object.assign({}, view), group_column: intermediateGroup ? this.TMPBoundSource[0].column : '' };
|
|
1900
|
+
let prev = this.groupSearchRequestsCache.findIndex(t => t.path == toAdd.path && t.group_column == toAdd.group_column);
|
|
1901
|
+
if (prev == -1)
|
|
1902
|
+
this.groupSearchRequestsCache.push(toAdd);
|
|
1903
|
+
else
|
|
1904
|
+
this.groupSearchRequestsCache.splice(prev, 1, toAdd);
|
|
1343
1905
|
}
|
|
1344
1906
|
}
|
|
1345
1907
|
/**
|
|
@@ -1348,6 +1910,22 @@ class EsTableComponent {
|
|
|
1348
1910
|
MoveTemporaryVariablesToRealOnes() {
|
|
1349
1911
|
this.RowTDs = this.TMPRowTDs;
|
|
1350
1912
|
this.RowTHs = this.TMPRowTHs;
|
|
1913
|
+
this.RowThGroups = this.TMPRowThGroups ? this.TMPRowThGroups.reverse() : null;
|
|
1914
|
+
this.Columns.Visibile = this.RowTHs.filter(t => t.Visible).length;
|
|
1915
|
+
this.Columns.VisibleUnpinned = this.RowTHs.filter(t => t.Visible && !t.Pinned).length;
|
|
1916
|
+
this.Columns.Global = this.Columns.VisibleUnpinned + (this.HasPinnedColumns ? 1 : 0) + (this.Selection ? 1 : 0) + (this.Removal ? 1 : 0) + (this.Export || this.HiddenColumns || this.ColumnsOrdering || this.CornerMenuOptions ? 1 : 0);
|
|
1917
|
+
}
|
|
1918
|
+
/**
|
|
1919
|
+
* Permette di selezionare o deselezionare in maniera arbitraria degli oggetti
|
|
1920
|
+
*
|
|
1921
|
+
* @param {any[]} items Oggetti da selezionare o deselezionare
|
|
1922
|
+
* @param {boolean} select **true** per selezionarli, **false** per non toccarli
|
|
1923
|
+
*
|
|
1924
|
+
* @todo: SELECTION
|
|
1925
|
+
*/
|
|
1926
|
+
setSelectionStatus(items, select) {
|
|
1927
|
+
this.handleItemsSelection(items, select);
|
|
1928
|
+
this.cdr.markForCheck();
|
|
1351
1929
|
}
|
|
1352
1930
|
/**
|
|
1353
1931
|
* Se non ho l'Input **DynamicRowColumnsDefinition** in modalità dinamica lo riempio con il default nome della colonna = testo della colonna
|
|
@@ -1377,7 +1955,7 @@ class EsTableComponent {
|
|
|
1377
1955
|
* @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
|
|
1378
1956
|
*/
|
|
1379
1957
|
reviewColumnsList(ths) {
|
|
1380
|
-
this.
|
|
1958
|
+
this.TMPColumnsList = [];
|
|
1381
1959
|
if (ths.length == 0)
|
|
1382
1960
|
return;
|
|
1383
1961
|
// Appena il contentChildren è valorizzato scorro tutti gli header
|
|
@@ -1391,18 +1969,99 @@ class EsTableComponent {
|
|
|
1391
1969
|
// Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
|
|
1392
1970
|
// Di default la visibilità è quella impostata nel componente
|
|
1393
1971
|
if (this.HiddenColumns || th.Visible)
|
|
1394
|
-
this.
|
|
1972
|
+
this.TMPColumnsList.push(new EsTableColumn(th.ID, th.Description, th.Visible, th.Fixed, null, null, null));
|
|
1395
1973
|
}
|
|
1396
1974
|
else {
|
|
1975
|
+
let column = th.th;
|
|
1397
1976
|
// Se non ho un id il th è considerato inerte
|
|
1398
|
-
if (!
|
|
1977
|
+
if (!column)
|
|
1399
1978
|
continue;
|
|
1400
1979
|
// Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
|
|
1401
1980
|
// Di default la visibilità è quella impostata nel componente
|
|
1402
|
-
if (this.HiddenColumns || th.thVisible)
|
|
1403
|
-
this.ColumnsList.
|
|
1981
|
+
if (this.HiddenColumns || th.thVisible) {
|
|
1982
|
+
let previouslyPinned = !this.ColumnsList || this.ColumnsList.length == 0 || !this.ColumnsList.find(t => t.id == column) ? null : this.ColumnsList.find(t => t.id == column).pinned;
|
|
1983
|
+
this.TMPColumnsList.push(new EsTableColumn(column, null, th.thVisible, (th.thFixed || th.thGroup), previouslyPinned == null ? th.thPinned : previouslyPinned, th.thPinnedWidth, th.Template));
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
this.ColumnsList = [];
|
|
1988
|
+
this.TMPColumnsList.forEach(c => { this.ColumnsList.push(Object.assign({}, c)); });
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Prende i th e i td in modalità diretive e li ordina in base a se ci sono colonne fixed o meno
|
|
1992
|
+
*/
|
|
1993
|
+
moveFixedColumnsAtTheBeginning(ths, tds) {
|
|
1994
|
+
let thsCache = {};
|
|
1995
|
+
let fixeds = 0, pinneds = 0;
|
|
1996
|
+
let columnsCache = {};
|
|
1997
|
+
let columnsIndexCache = {};
|
|
1998
|
+
// Creo la cache delle colonne
|
|
1999
|
+
for (let coli = 0; coli < this.ColumnsList.length; coli++) {
|
|
2000
|
+
let col = this.ColumnsList[coli];
|
|
2001
|
+
columnsCache[col.id] = col;
|
|
2002
|
+
}
|
|
2003
|
+
// Sposto tutti gli header fixed o pinned all'inizio
|
|
2004
|
+
for (let i = 0; i < ths.length; i++) {
|
|
2005
|
+
let th = ths[i];
|
|
2006
|
+
if (this.isEsTh(th)) {
|
|
2007
|
+
thsCache[th.ID] = th;
|
|
2008
|
+
if (th.Fixed) {
|
|
2009
|
+
if (i != pinneds + fixeds)
|
|
2010
|
+
this.arrayMove(ths, i, pinneds + fixeds);
|
|
2011
|
+
fixeds++;
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
else {
|
|
2015
|
+
thsCache[th.th] = th;
|
|
2016
|
+
// Riassegno sempre per ripulire valori di partenza o per aggiornarli in caso di modifiche utente
|
|
2017
|
+
th.thPinned = (!columnsCache[th.th] && th.thPinned) || (columnsCache[th.th] && columnsCache[th.th].pinned);
|
|
2018
|
+
if (th.thPinned) {
|
|
2019
|
+
if (i != pinneds)
|
|
2020
|
+
this.arrayMove(ths, i, pinneds);
|
|
2021
|
+
pinneds++;
|
|
2022
|
+
}
|
|
2023
|
+
//In questo caso sono informazioni statiche invece, non modificabili dall'utente, quindi non mi dò preoccupazioni
|
|
2024
|
+
if (th.thFixed || th.thGroup) {
|
|
2025
|
+
if (i != pinneds + fixeds)
|
|
2026
|
+
this.arrayMove(ths, i, pinneds + fixeds);
|
|
2027
|
+
fixeds++;
|
|
2028
|
+
}
|
|
1404
2029
|
}
|
|
1405
2030
|
}
|
|
2031
|
+
if (this.isEsTh(ths[0]) || this.isEsTd(tds[0]))
|
|
2032
|
+
return;
|
|
2033
|
+
// Cache degli indici per riposizionare i td come i th
|
|
2034
|
+
for (let i = 0; i < ths.length; i++)
|
|
2035
|
+
columnsIndexCache[ths[i].th] = i;
|
|
2036
|
+
// Riordino le celle per fargli mantenere la stessa struttura dei th
|
|
2037
|
+
let newTds = new Array(ths.length);
|
|
2038
|
+
for (let i = 0; i < tds.length; i++) {
|
|
2039
|
+
let item = tds[i];
|
|
2040
|
+
newTds[columnsIndexCache[item.td]] = item;
|
|
2041
|
+
}
|
|
2042
|
+
this.HasPinnedColumns = pinneds > 0;
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* In base alla configurazione delle colonne calcola le dimenioni delle colonne pinnate
|
|
2046
|
+
*/
|
|
2047
|
+
evaluatePinnedColumnsWidth() {
|
|
2048
|
+
if (!this.HasPinnedColumns)
|
|
2049
|
+
return;
|
|
2050
|
+
this.PinnedContainerWidth = 0;
|
|
2051
|
+
for (let i = 0; i < this.ColumnsList.length; i++) {
|
|
2052
|
+
let col = this.ColumnsList[i];
|
|
2053
|
+
if (col.pinned && col.visible)
|
|
2054
|
+
this.PinnedContainerWidth += col.pinnedWidth;
|
|
2055
|
+
}
|
|
2056
|
+
this.PinnedContainerWidth += this.Selection ? 25 : 0;
|
|
2057
|
+
}
|
|
2058
|
+
/**
|
|
2059
|
+
* Helper per spostare un oggetto di un array da un indice all'altro, in place
|
|
2060
|
+
*/
|
|
2061
|
+
arrayMove(array, oldI, newI) {
|
|
2062
|
+
if (newI > array.length - 1 || oldI > array.length - 1 || newI < 0 || oldI < 0)
|
|
2063
|
+
throw "Gli indici passati non fanno riferimento a una posizione dell'array. Length: " + array.length + " Old:" + oldI + " New: " + newI;
|
|
2064
|
+
array.splice(newI, 0, array.splice(oldI, 1)[0]);
|
|
1406
2065
|
}
|
|
1407
2066
|
/**
|
|
1408
2067
|
* Terminato il binding delle colonne da **reviewColumnsList** e della **View** dal **writeValue** questo metodo si occupa
|
|
@@ -1411,14 +2070,19 @@ class EsTableComponent {
|
|
|
1411
2070
|
* @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
|
|
1412
2071
|
*/
|
|
1413
2072
|
alignColumnsIfLoadedView(view) {
|
|
1414
|
-
let emitChanged = view.savedstate;
|
|
2073
|
+
let emitChanged = this.viewMode && view.savedstate;
|
|
1415
2074
|
let newColset = [];
|
|
1416
2075
|
if (!this.ColumnsList || this.ColumnsList.length == 0)
|
|
1417
2076
|
return;
|
|
2077
|
+
let columns = this.viewMode ? view.columns : this.arrayColumns;
|
|
1418
2078
|
this.ColumnsList.forEach(c => {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
2079
|
+
// Se la colonna è pinnata mi arriva col simoleon
|
|
2080
|
+
let exCl = columns.filter(cc => cc.replace('§', '') == c.id);
|
|
2081
|
+
// Se la colonna è pinnata aggiorno l'informazione nella view
|
|
2082
|
+
if (exCl.length == 1)
|
|
2083
|
+
c.pinned = exCl[0].startsWith('§');
|
|
2084
|
+
// Se l'appsearch viene da uno stato precedente, uso le informazioni sulle colonne che ha dentro, altrimenti sovrascrivo tutto **
|
|
2085
|
+
if (c.visible && columns.length == 0)
|
|
1422
2086
|
newColset.push(c.id);
|
|
1423
2087
|
// Se ho una colonna lato AppSearch e nella ColumnList non è visibile, allineo all'AppSearch
|
|
1424
2088
|
else if (exCl.length == 1 && !c.visible)
|
|
@@ -1428,21 +2092,22 @@ class EsTableComponent {
|
|
|
1428
2092
|
c.visible = false;
|
|
1429
2093
|
});
|
|
1430
2094
|
// Non ho colonne nella appsearch, vuol dire che sono al primo binding
|
|
1431
|
-
if (
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
2095
|
+
if (columns.length == 0) {
|
|
2096
|
+
if (this.viewMode)
|
|
2097
|
+
view.columns = newColset;
|
|
2098
|
+
else
|
|
2099
|
+
this.arrayColumns = newColset;
|
|
2100
|
+
}
|
|
2101
|
+
if ((this.viewMode && view.savedstate) && this.ColumnsOrdering && view.column_ordering.length > 0) {
|
|
1435
2102
|
// Scorro gli ordinamenti che avevo salvato e ricreo la ColumnsList in base a loro
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
newColList.push(c);
|
|
1440
|
-
});
|
|
1441
|
-
});
|
|
2103
|
+
let newColList = [];
|
|
2104
|
+
view.column_ordering.forEach(co => { this.ColumnsList.forEach(c => { if (c.id == co)
|
|
2105
|
+
newColList.push(c); }); });
|
|
1442
2106
|
this.ColumnsList = newColList;
|
|
1443
2107
|
}
|
|
1444
2108
|
// In ogni caso questo non mi serve più, lo resetto **
|
|
1445
|
-
|
|
2109
|
+
if (this.viewMode)
|
|
2110
|
+
view.savedstate = false;
|
|
1446
2111
|
if (emitChanged)
|
|
1447
2112
|
this.changed();
|
|
1448
2113
|
}
|
|
@@ -1453,20 +2118,22 @@ class EsTableComponent {
|
|
|
1453
2118
|
* @param {'DESC' | 'ASC'} order Nuovo ordine selezionato per la colonna
|
|
1454
2119
|
*/
|
|
1455
2120
|
thOrderChanged(id, order) {
|
|
1456
|
-
if (!this.viewMode) {
|
|
1457
|
-
console.warn('Order changed on a table not in viewMode. Operation not supported');
|
|
2121
|
+
if (!this.viewMode && !this.arrayMode) {
|
|
2122
|
+
console.warn('Order changed on a table not in viewMode or Array mode. Operation not supported');
|
|
1458
2123
|
return;
|
|
1459
2124
|
}
|
|
1460
2125
|
if (!this.OrderByColumn)
|
|
1461
2126
|
return;
|
|
1462
|
-
let
|
|
2127
|
+
let orders = this.viewMode ? this.View.orders : this.arrayOrders;
|
|
1463
2128
|
let orderToAdd = true;
|
|
1464
2129
|
let orderToRemove = null;
|
|
1465
2130
|
// Se per qualche motivo il costruttore non è passato (cache tarpate o simila) fixo
|
|
1466
|
-
if (!
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
2131
|
+
if (!orders && this.viewMode)
|
|
2132
|
+
this.View.orders = [];
|
|
2133
|
+
else if (!orders && this.arrayMode)
|
|
2134
|
+
this.arrayOrders = [];
|
|
2135
|
+
for (let i = 0; i < orders.length; i++) {
|
|
2136
|
+
let t = orders[i];
|
|
1470
2137
|
if (t.id == id) {
|
|
1471
2138
|
if (order) {
|
|
1472
2139
|
t.order = order;
|
|
@@ -1477,19 +2144,27 @@ class EsTableComponent {
|
|
|
1477
2144
|
}
|
|
1478
2145
|
}
|
|
1479
2146
|
if (orderToRemove != null) {
|
|
1480
|
-
|
|
2147
|
+
orders.splice(orderToRemove, 1);
|
|
1481
2148
|
}
|
|
1482
2149
|
else if (orderToAdd) {
|
|
1483
2150
|
if (this.MultipleOrderingDirectives)
|
|
1484
|
-
|
|
1485
|
-
else
|
|
1486
|
-
|
|
2151
|
+
orders.push(new AppOrdering(id, order));
|
|
2152
|
+
else {
|
|
2153
|
+
if (this.viewMode)
|
|
2154
|
+
this.View.orders = [new AppOrdering(id, order)];
|
|
2155
|
+
else if (this.arrayMode)
|
|
2156
|
+
this.arrayOrders = [new AppOrdering(id, order)];
|
|
2157
|
+
}
|
|
1487
2158
|
}
|
|
1488
2159
|
this.onOrderChanged.emit({ id, order });
|
|
1489
|
-
if (this.
|
|
1490
|
-
this.
|
|
1491
|
-
|
|
1492
|
-
|
|
2160
|
+
if (this.viewMode) {
|
|
2161
|
+
if (this.groupSearchRequestsCache.length > 0)
|
|
2162
|
+
this.emitRowGroupingSearches(id, orders);
|
|
2163
|
+
else
|
|
2164
|
+
this.emitSearchRequest(false);
|
|
2165
|
+
}
|
|
2166
|
+
else if (this.arrayMode)
|
|
2167
|
+
this.internalWriteValue();
|
|
1493
2168
|
}
|
|
1494
2169
|
/**
|
|
1495
2170
|
* Metodo da chiamare ogni volta che si vuole dare evidenza all'esterno del bisogno di rieffettuare la ricerca
|
|
@@ -1502,6 +2177,11 @@ class EsTableComponent {
|
|
|
1502
2177
|
this.View.internalsearchrequest = true;
|
|
1503
2178
|
this.changed();
|
|
1504
2179
|
}
|
|
2180
|
+
if (viewOverride) {
|
|
2181
|
+
if (resetsPage)
|
|
2182
|
+
viewOverride.page = 1;
|
|
2183
|
+
viewOverride.internalsearchrequest = true;
|
|
2184
|
+
}
|
|
1505
2185
|
this.researchInProgress = true;
|
|
1506
2186
|
this.onSearchRequest.emit(viewOverride ? viewOverride : resetsPage);
|
|
1507
2187
|
}
|
|
@@ -1515,16 +2195,19 @@ class EsTableComponent {
|
|
|
1515
2195
|
* @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
|
|
1516
2196
|
*/
|
|
1517
2197
|
refreshColumnsVisibility(ths, tds, view) {
|
|
1518
|
-
let columnsCache = {};
|
|
1519
2198
|
let newColset = [];
|
|
1520
2199
|
let fixedThs = {};
|
|
2200
|
+
let columnsCache = {};
|
|
1521
2201
|
for (let coli = 0; coli < this.ColumnsList.length; coli++) {
|
|
1522
2202
|
let col = this.ColumnsList[coli];
|
|
1523
2203
|
columnsCache[col.id] = col;
|
|
1524
2204
|
if (col.visible)
|
|
1525
|
-
newColset.push(col.id);
|
|
2205
|
+
newColset.push((col.pinned ? "§" : "") + col.id);
|
|
1526
2206
|
}
|
|
1527
|
-
view
|
|
2207
|
+
if (view)
|
|
2208
|
+
view.columns = newColset;
|
|
2209
|
+
else
|
|
2210
|
+
this.arrayColumns = newColset;
|
|
1528
2211
|
// Da qui in poi devono essere eseguiti SOLO in fase di writeValue quindi devo assicurarmi di passarli null in tutti i passaggi diversi da quello
|
|
1529
2212
|
if (ths) {
|
|
1530
2213
|
// Definisco se la colonna è visibile in base alla sua rappresentazione locale in ColumnsList
|
|
@@ -1537,7 +2220,7 @@ class EsTableComponent {
|
|
|
1537
2220
|
}
|
|
1538
2221
|
else {
|
|
1539
2222
|
th.thVisible = th.thFixed || (columnsCache[th.th] ? columnsCache[th.th].visible : th.thVisible);
|
|
1540
|
-
if (th.thFixed)
|
|
2223
|
+
if (th.thFixed || th.thGroup)
|
|
1541
2224
|
fixedThs[th.th] = true;
|
|
1542
2225
|
}
|
|
1543
2226
|
}
|
|
@@ -1561,22 +2244,23 @@ class EsTableComponent {
|
|
|
1561
2244
|
* @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
|
|
1562
2245
|
*/
|
|
1563
2246
|
alignHeadersOrdering(ths, view) {
|
|
2247
|
+
let orders = view ? view.orders : this.arrayOrders;
|
|
1564
2248
|
for (let i = 0; i < ths.length; i++) {
|
|
1565
2249
|
let th = ths[i];
|
|
1566
2250
|
if (this.isEsTh(th)) {
|
|
1567
2251
|
th.Order = null;
|
|
1568
2252
|
// Assegno tutti gli ordinamenti che mi vengono da AppSearch. Sono i più importanti. Non faccio cache o cose strano perché tanto questa
|
|
1569
2253
|
// variabile sarà sempre massimo 3 elementi
|
|
1570
|
-
for (let i = 0; i <
|
|
1571
|
-
let or =
|
|
2254
|
+
for (let i = 0; i < orders.length; i++) {
|
|
2255
|
+
let or = orders[i];
|
|
1572
2256
|
if (or.id == th.ID)
|
|
1573
2257
|
th.Order = or.order;
|
|
1574
2258
|
}
|
|
1575
2259
|
}
|
|
1576
2260
|
else {
|
|
1577
2261
|
th.thOrder = null;
|
|
1578
|
-
for (let i = 0; i <
|
|
1579
|
-
let or =
|
|
2262
|
+
for (let i = 0; i < orders.length; i++) {
|
|
2263
|
+
let or = orders[i];
|
|
1580
2264
|
if (or.id == th.th)
|
|
1581
2265
|
th.thOrder = or.order;
|
|
1582
2266
|
}
|
|
@@ -1597,6 +2281,11 @@ class EsTableComponent {
|
|
|
1597
2281
|
if (tds.length == 0)
|
|
1598
2282
|
return;
|
|
1599
2283
|
let thsCache = {};
|
|
2284
|
+
let columnsCache = {};
|
|
2285
|
+
for (let coli = 0; coli < this.ColumnsList.length; coli++) {
|
|
2286
|
+
let col = this.ColumnsList[coli];
|
|
2287
|
+
columnsCache[col.id] = col;
|
|
2288
|
+
}
|
|
1600
2289
|
for (let i = 0; i < ths.length; i++) {
|
|
1601
2290
|
let th = ths[i];
|
|
1602
2291
|
thsCache[this.isEsTh(th) ? th.ID : th.th] = th;
|
|
@@ -1609,10 +2298,10 @@ class EsTableComponent {
|
|
|
1609
2298
|
if (this.isEsTd(td)) {
|
|
1610
2299
|
let th = thsCache[td.ID];
|
|
1611
2300
|
if (!!th)
|
|
1612
|
-
th.
|
|
2301
|
+
th._referenced = true;
|
|
1613
2302
|
else
|
|
1614
2303
|
throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.ID;
|
|
1615
|
-
let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && th.thFixed);
|
|
2304
|
+
let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && (th.thFixed || th.thGroup));
|
|
1616
2305
|
let itemToAdd = { GroupAggregation: false, GroupHeader: false, Wraps: true, ID: td.ID, Visible: td.Visible, Class: td.Class, Content: td.Content, RouterLink: td.RouterLink, Template: td.Template };
|
|
1617
2306
|
let ctx = td.Context;
|
|
1618
2307
|
if (this.TMPRowTDs[ctx]) {
|
|
@@ -1630,24 +2319,25 @@ class EsTableComponent {
|
|
|
1630
2319
|
else {
|
|
1631
2320
|
for (let i = 0; i < this.boundSource.length; i++) {
|
|
1632
2321
|
let item = this.boundSource[i];
|
|
1633
|
-
let ctx = item.
|
|
2322
|
+
let ctx = item._hash;
|
|
1634
2323
|
let key = td.td;
|
|
1635
2324
|
let th = thsCache[td.td];
|
|
1636
2325
|
if (!!th)
|
|
1637
|
-
th.
|
|
2326
|
+
th._referenced = true;
|
|
1638
2327
|
else
|
|
1639
2328
|
throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.td;
|
|
1640
2329
|
if (td.tdIf || (!this.isEsTh(th) && th.thGroup)) {
|
|
1641
2330
|
let thCasted = th;
|
|
1642
|
-
let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && th.thFixed);
|
|
2331
|
+
let isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && (th.thFixed || th.thGroup || th.thPinned));
|
|
1643
2332
|
let itemToAdd = item._item ?
|
|
1644
|
-
{ ID: key, GroupHeader: false, GroupAggregation: false, Visible: td.
|
|
1645
|
-
{ ID: key, GroupHeader: thCasted.thGroup, GroupAggregation: !!thCasted.thAggregation, Visible:
|
|
2333
|
+
{ LeftBorder: thCasted._lbord, RightBorder: thCasted._rbord, ID: key, Pinned: columnsCache[td.td].pinned, PinnedWidth: thCasted.thPinnedWidth, GroupHeader: false, GroupAggregation: false, Visible: columnsCache[td.td].visible, Wraps: false, Class: td.tdClass, Template: thCasted.thGroup && !this.ShowItemGroupsColumns ? null : td.Template } :
|
|
2334
|
+
{ LeftBorder: thCasted._lbord, RightBorder: thCasted._rbord, ID: key, Pinned: columnsCache[td.td].pinned, PinnedWidth: thCasted.thPinnedWidth, GroupHeader: thCasted.thGroup, GroupAggregation: !!thCasted.thAggregation, Visible: columnsCache[td.td].visible, Wraps: false, Class: thCasted.thGroupClass || '', Content: this.getGroupCellDisplay(item, key, th) };
|
|
1646
2335
|
if (this.TMPRowTDs[ctx]) {
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
2336
|
+
// Non serve più grazie al metodo **oveFixedColumnsAtTheBeginning**
|
|
2337
|
+
//if (isFixed)
|
|
2338
|
+
// this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
|
|
2339
|
+
//else
|
|
2340
|
+
this.TMPRowTDs[ctx].push(itemToAdd);
|
|
1651
2341
|
}
|
|
1652
2342
|
else {
|
|
1653
2343
|
this.RowContexts.push(ctx);
|
|
@@ -1664,7 +2354,7 @@ class EsTableComponent {
|
|
|
1664
2354
|
var errs = [];
|
|
1665
2355
|
for (let i = 0; i < ths.length; i++) {
|
|
1666
2356
|
let th = ths[i];
|
|
1667
|
-
if (!th.
|
|
2357
|
+
if (!th._referenced)
|
|
1668
2358
|
errs.push(this.isEsTh(th) ? th.ID : th.th);
|
|
1669
2359
|
}
|
|
1670
2360
|
if (errs.length > 0) {
|
|
@@ -1684,29 +2374,31 @@ class EsTableComponent {
|
|
|
1684
2374
|
evaluateRowThs(ths) {
|
|
1685
2375
|
if (ths.length == 0)
|
|
1686
2376
|
return;
|
|
2377
|
+
let columnsListCache = {};
|
|
1687
2378
|
let castedView = this.View;
|
|
1688
|
-
let groupingsUndefined = !castedView.groupings || castedView.groupings.length == 0;
|
|
2379
|
+
let groupingsUndefined = this.viewMode && (castedView && !castedView.groupings || castedView.groupings.length == 0);
|
|
2380
|
+
for (let i = 0; i < this.ColumnsList.length; i++) {
|
|
2381
|
+
let itm = this.ColumnsList[i];
|
|
2382
|
+
columnsListCache[itm.id] = itm;
|
|
2383
|
+
}
|
|
1689
2384
|
this.TMPRowTHs = [];
|
|
1690
2385
|
let fixed = 0;
|
|
1691
2386
|
for (let i = 0; i < ths.length; i++) {
|
|
1692
2387
|
let th = ths[i];
|
|
1693
2388
|
let toAdd;
|
|
1694
2389
|
if (this.isEsTh(th)) {
|
|
1695
|
-
toAdd = {
|
|
2390
|
+
toAdd = { Pinned: false, ID: th.ID, Visible: th.Visible, Class: th.Class, Order: th.Order, Orderable: th.Orderable, Template: null, Content: th.Description, Wrap: false };
|
|
1696
2391
|
if (th.Fixed)
|
|
1697
2392
|
this.TMPRowTHs.splice(0 + (fixed++), 0, toAdd);
|
|
1698
2393
|
else
|
|
1699
2394
|
this.TMPRowTHs.push(toAdd);
|
|
1700
2395
|
}
|
|
1701
2396
|
else if (th.thIf || th.thGroup) {
|
|
1702
|
-
// Mentre inserisco mi assicuro di mettere l'elemento per bene in ordine in base alla proprietà "Fixed". Tutte le colonne Fixed devono finire all'inizio
|
|
1703
|
-
// (Questo probabilmente diventerà il comportamento di default anche per le colonne "Pinned")
|
|
1704
2397
|
let thClass = (th.thClass || '') + (th.thGroup ? " est-col-min" : "");
|
|
1705
|
-
toAdd = {
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
this.TMPRowTHs.push(toAdd);
|
|
2398
|
+
toAdd = { Pinned: columnsListCache[th.th].pinned, PinnedWidth: th.thPinnedWidth, ID: th.th, Visible: th.thVisible, Class: thClass, Order: th.thOrder, Orderable: th.thOrderable, Template: th.Template, Content: null, Wrap: false, LeftBorder: th._lbord, RightBorder: th._rbord };
|
|
2399
|
+
this.TMPRowTHs.push(toAdd);
|
|
2400
|
+
// Se ho un modello che deve funzionare a rowgrouping ma non è ancora stata effettuata nessuna ricerca sui gruppi principali (groupingsUndefined)
|
|
2401
|
+
// li genero e mando la prima ricerca che dev'essere spedita al backend per il primo caricamento dei gruppi
|
|
1710
2402
|
if (groupingsUndefined && (th.thAggregation || th.thGroup)) {
|
|
1711
2403
|
let groupAggregations = this.getGroupAggregations(th);
|
|
1712
2404
|
if (!castedView.groupings)
|
|
@@ -1718,6 +2410,122 @@ class EsTableComponent {
|
|
|
1718
2410
|
}
|
|
1719
2411
|
}
|
|
1720
2412
|
}
|
|
2413
|
+
evaluateHeadersGroupingInfos(ths) {
|
|
2414
|
+
// Pregiro per trovare i parent
|
|
2415
|
+
let parentsCache = {};
|
|
2416
|
+
let thsCache = {};
|
|
2417
|
+
for (let i = 0; i < ths.length; i++) {
|
|
2418
|
+
let th = ths[i];
|
|
2419
|
+
if (this.isEsTh(th))
|
|
2420
|
+
continue;
|
|
2421
|
+
thsCache[th.th] = th;
|
|
2422
|
+
if (th.thParent && !parentsCache[th.thParent])
|
|
2423
|
+
parentsCache[th.thParent] = true;
|
|
2424
|
+
}
|
|
2425
|
+
// Secondo giro per beccare il livello massimo e la lista di foglie (th senza parent)
|
|
2426
|
+
let hMaxLevel = 0;
|
|
2427
|
+
let leafs = [];
|
|
2428
|
+
for (let i = 0; i < ths.length; i++) {
|
|
2429
|
+
let th = ths[i];
|
|
2430
|
+
if (this.isEsTh(th)) {
|
|
2431
|
+
leafs.push(th);
|
|
2432
|
+
continue;
|
|
2433
|
+
}
|
|
2434
|
+
// Se sono una foglia vedo quanti livelli ci sono sopra
|
|
2435
|
+
if (!parentsCache[th.th]) {
|
|
2436
|
+
leafs.push(th);
|
|
2437
|
+
let tmp = this.jumpsToFinalParent(th, thsCache);
|
|
2438
|
+
hMaxLevel = tmp > hMaxLevel ? tmp : hMaxLevel;
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
return { leafs: leafs, groupingLevel: hMaxLevel, parentsCache: parentsCache, thsCache: thsCache };
|
|
2442
|
+
}
|
|
2443
|
+
/**
|
|
2444
|
+
* Genera gli header groups da una lista di info sui th all'interno della variabile **TMPRowThGroups**
|
|
2445
|
+
*/
|
|
2446
|
+
evaluateHeaderGroups(infos) {
|
|
2447
|
+
if (infos.groupingLevel == 0)
|
|
2448
|
+
return;
|
|
2449
|
+
// Giro 2.5, creo l'output dei raggruppamenti per header in modo da non dovermi preoccupare di celle non inizializzate
|
|
2450
|
+
let expandedGroups = [];
|
|
2451
|
+
let visibleUnpinnedLeafs = infos.leafs.filter((t) => t.thVisible && !t.thPinned);
|
|
2452
|
+
for (let l = 0; l < infos.groupingLevel; l++) {
|
|
2453
|
+
expandedGroups.push([]);
|
|
2454
|
+
for (let i = 0; i < visibleUnpinnedLeafs.length; i++)
|
|
2455
|
+
expandedGroups[l].push("");
|
|
2456
|
+
}
|
|
2457
|
+
// Ordino le foglie in base agli ordinamenti delle colonne
|
|
2458
|
+
let orderedLeafs = [];
|
|
2459
|
+
for (let i = 0; i < this.OrderDirectives.length; i++) {
|
|
2460
|
+
let leaf = infos.thsCache[this.OrderDirectives[i]];
|
|
2461
|
+
if (leaf.thVisible && !leaf.thPinned)
|
|
2462
|
+
orderedLeafs.push(leaf);
|
|
2463
|
+
}
|
|
2464
|
+
// Terzo giro per creare l'array group con tutti i riferimenti del caso
|
|
2465
|
+
let currentParent = "";
|
|
2466
|
+
for (let i = 0; i < orderedLeafs.length; i++) {
|
|
2467
|
+
let refTh = orderedLeafs[i];
|
|
2468
|
+
let prevTh = i - 1 >= 0 ? orderedLeafs[i - 1] : null;
|
|
2469
|
+
// Parent diverso da prima, metto il bordo a sinistra e a destra della cella precedente (se c'è)
|
|
2470
|
+
// All'ultimo giro metto il bordo a destra. Tutto questo lo rieseguo per ogni cella in modo da ripulire eventuali a cui avevo assegnato tag precedentemente
|
|
2471
|
+
refTh._lbord = refTh.thParent != currentParent;
|
|
2472
|
+
refTh._rbord = visibleUnpinnedLeafs.length == i + 1;
|
|
2473
|
+
if (prevTh)
|
|
2474
|
+
prevTh._rbord = refTh.thParent != currentParent;
|
|
2475
|
+
currentParent = refTh.thParent;
|
|
2476
|
+
// Per ogni gruppo srotolo il parent nella matrice dei raggruppamenti
|
|
2477
|
+
for (let l = 0; l < infos.groupingLevel; l++) {
|
|
2478
|
+
let parent = refTh.thParent;
|
|
2479
|
+
if (parent && !refTh.thPinned) {
|
|
2480
|
+
expandedGroups[l][i] = parent;
|
|
2481
|
+
refTh = infos.thsCache[parent];
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
// Quarto giro per compattarlo nell'elemento finale su cui bindarmi
|
|
2486
|
+
currentParent = "";
|
|
2487
|
+
let currentSpan = 0;
|
|
2488
|
+
this.TMPRowThGroups = [];
|
|
2489
|
+
for (let l = 0; l < expandedGroups.length; l++) {
|
|
2490
|
+
let levelArray = [];
|
|
2491
|
+
this.TMPRowThGroups.push(levelArray);
|
|
2492
|
+
if (this.Selection || this.HasPinnedColumns)
|
|
2493
|
+
levelArray.push({ Span: 1, Template: null, Pinned: this.HasPinnedColumns });
|
|
2494
|
+
for (let h = 0; h < expandedGroups[l].length; h++) {
|
|
2495
|
+
let item = expandedGroups[l][h];
|
|
2496
|
+
if (item == currentParent)
|
|
2497
|
+
currentSpan++;
|
|
2498
|
+
else {
|
|
2499
|
+
if (currentSpan > 0)
|
|
2500
|
+
levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
|
|
2501
|
+
currentSpan = 1;
|
|
2502
|
+
currentParent = item;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
// Ultima aggiunta che altrimenti mi rimarrebbe in cache
|
|
2506
|
+
levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
|
|
2507
|
+
if (this.Removal)
|
|
2508
|
+
levelArray.push({ Span: 1, Template: null });
|
|
2509
|
+
if (this.Export || this.HiddenColumns || this.ColumnsOrdering || this.CornerMenuOptions)
|
|
2510
|
+
levelArray.push({ Span: 1, Template: null });
|
|
2511
|
+
currentSpan = 0;
|
|
2512
|
+
currentParent = "";
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
/**
|
|
2516
|
+
* Calcola il numero di salti da un header foglia all'ultimo parent della catena
|
|
2517
|
+
*/
|
|
2518
|
+
jumpsToFinalParent(th, thsCache) {
|
|
2519
|
+
let jumps = 0;
|
|
2520
|
+
let parent = null;
|
|
2521
|
+
do {
|
|
2522
|
+
parent = th.thParent;
|
|
2523
|
+
if (parent)
|
|
2524
|
+
jumps++;
|
|
2525
|
+
th = thsCache[parent];
|
|
2526
|
+
} while (parent);
|
|
2527
|
+
return jumps;
|
|
2528
|
+
}
|
|
1721
2529
|
/**
|
|
1722
2530
|
* Data una direttiva EsTh restituisce la lista delle aggregazioni richiesta per questa colonna o il gruppo che rappresenta
|
|
1723
2531
|
*
|
|
@@ -1730,7 +2538,11 @@ class EsTableComponent {
|
|
|
1730
2538
|
// Es: '{min:dd/MM/yyyy} - {max:dd/MM/yyyy}'
|
|
1731
2539
|
if (th.thAggregation) {
|
|
1732
2540
|
this.getEsThDirectiveListOfAggregations(th).forEach((agg) => {
|
|
1733
|
-
|
|
2541
|
+
let isdate = agg.format && ['small', 'long', 'verylong'].includes(agg.format);
|
|
2542
|
+
let isnumber = agg.format && agg.format.startsWith("F") && !Number.isNaN(agg.format.charAt(1)) && agg.format.length == 2;
|
|
2543
|
+
if (!isdate && !isnumber && agg.format)
|
|
2544
|
+
throw "Le aggergazioni supportate dall'es-table sono solo 'small', 'long', 'verylong' per le date e 'F0-9' per i numeri";
|
|
2545
|
+
ret.push(new GroupOrAggregation(th.th, agg.func, isdate ? 'date' : isnumber ? 'number' : 'string'));
|
|
1734
2546
|
});
|
|
1735
2547
|
}
|
|
1736
2548
|
else if (th.thGroup)
|
|
@@ -1747,6 +2559,9 @@ class EsTableComponent {
|
|
|
1747
2559
|
getEsThDirectiveListOfAggregations(th) {
|
|
1748
2560
|
if (!th.thAggregation)
|
|
1749
2561
|
return [];
|
|
2562
|
+
// Se ho già effettuato questo calcolo per questo th restituisco la versione in cache
|
|
2563
|
+
if (th._thAggregations)
|
|
2564
|
+
return th._thAggregations;
|
|
1750
2565
|
let ret = [];
|
|
1751
2566
|
let display = th.thAggregation;
|
|
1752
2567
|
var matches = display.match(/{[a-zA-Z0-9\/:]*}/gi);
|
|
@@ -1762,6 +2577,7 @@ class EsTableComponent {
|
|
|
1762
2577
|
}
|
|
1763
2578
|
ret.push({ func: func, format: format, match: m });
|
|
1764
2579
|
});
|
|
2580
|
+
th._thAggregations = ret;
|
|
1765
2581
|
return ret;
|
|
1766
2582
|
}
|
|
1767
2583
|
/**
|
|
@@ -1769,16 +2585,20 @@ class EsTableComponent {
|
|
|
1769
2585
|
*
|
|
1770
2586
|
* @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
|
|
1771
2587
|
*/
|
|
1772
|
-
generateDefaultOrder(view) {
|
|
1773
|
-
if (
|
|
2588
|
+
generateDefaultOrder(ths, view) {
|
|
2589
|
+
if (ths.length == 0)
|
|
1774
2590
|
return;
|
|
2591
|
+
let orderings = this.viewMode ? view.column_ordering : this.arrayColumnOrdering;
|
|
1775
2592
|
// Genero ordinamento di default da 0 fino a dove deve arrivare. Situazione attuale senza hotpotato
|
|
1776
|
-
if (!
|
|
1777
|
-
for (let i = 0; i <
|
|
1778
|
-
|
|
2593
|
+
if (!orderings || orderings.length == 0) {
|
|
2594
|
+
for (let i = 0; i < ths.length; i++) {
|
|
2595
|
+
let th = ths[i];
|
|
2596
|
+
let order = this.isEsTh(th) ? th.ID : th.th;
|
|
2597
|
+
this.OrderDirectives.push(order);
|
|
2598
|
+
}
|
|
1779
2599
|
}
|
|
1780
2600
|
else
|
|
1781
|
-
this.OrderDirectives =
|
|
2601
|
+
this.OrderDirectives = orderings;
|
|
1782
2602
|
}
|
|
1783
2603
|
/**
|
|
1784
2604
|
* Applica l'ordine specificato alle varie colonne
|
|
@@ -1787,7 +2607,7 @@ class EsTableComponent {
|
|
|
1787
2607
|
* @param {boolean} finalize Se **true** significa che non mi aspetto di dover effettuare altre operazioni e posso renderizzare la situazione in base ai RowContext
|
|
1788
2608
|
* Senza finalize significa che mi aspetto altre operazioni che prima o poi richiameranno questa funzione col finalize.
|
|
1789
2609
|
*
|
|
1790
|
-
* Ad esempio, una volta selezionato ordinamento fisico/logico delle colonne so che parte un altra ricerca che mi
|
|
2610
|
+
* Ad esempio, una volta selezionato ordinamento fisico/logico delle colonne so che parte un altra ricerca che mi rivalorizzerà da "writeValue", che già chiama questa funzione.
|
|
1791
2611
|
* Mettendo solo la chiamata da "writeValue" come "finalizzante" mi assicuro che smanattamenti a frontend non causino flickering fino a quando non servono
|
|
1792
2612
|
*/
|
|
1793
2613
|
applyOrdering(view, finalize) {
|
|
@@ -1811,7 +2631,10 @@ class EsTableComponent {
|
|
|
1811
2631
|
this.TMPRowTDs[this.RowContexts[i]] = newContext;
|
|
1812
2632
|
}
|
|
1813
2633
|
}
|
|
1814
|
-
|
|
2634
|
+
if (this.viewMode)
|
|
2635
|
+
view.column_ordering = this.OrderDirectives;
|
|
2636
|
+
else
|
|
2637
|
+
this.arrayColumnOrdering = this.OrderDirectives;
|
|
1815
2638
|
this.changed();
|
|
1816
2639
|
}
|
|
1817
2640
|
// #endregion
|
|
@@ -1822,24 +2645,40 @@ class EsTableComponent {
|
|
|
1822
2645
|
* @param {AppSearch<any>} view View utilizzata per la ricerca. Me ne salvo i parametri nel separatore attuale dato che ne ho bisogno per caricare altri elementi
|
|
1823
2646
|
* facenti riferimento allo stesso contesto
|
|
1824
2647
|
* @param {string} parent Parent path che rappresenta a quale gruppo è affibbiato questo separatore
|
|
2648
|
+
* @param {GroupRouteFragment[]} route Route path che rappresenta a quale gruppo è affibbiato questo separatore
|
|
1825
2649
|
* @param {number} level Livello del gruppo di cui questo elemento è separatore, viene usato per applicare la classe "est-lvl-{{level}}"
|
|
1826
2650
|
*
|
|
1827
2651
|
* @returns {any} Elemento di separazione contenente tutti i bind per presentare una paginazione sotto questo gruppo lato interfaccia
|
|
1828
2652
|
*/
|
|
1829
|
-
getGroupSeparator(view, parent, level) {
|
|
1830
|
-
let item = {
|
|
1831
|
-
|
|
1832
|
-
_parent: parent,
|
|
1833
|
-
_grouplevel: level,
|
|
1834
|
-
filters: view.requestedgroups.map(t => { return { column: t.column, value: t.value }; }),
|
|
1835
|
-
page: view.page,
|
|
1836
|
-
pages: view.pages,
|
|
1837
|
-
itemsperpage: view.itemsperpageoverride,
|
|
1838
|
-
count: view.objectcount
|
|
1839
|
-
};
|
|
2653
|
+
getGroupSeparator(view, parent, route, level, searches) {
|
|
2654
|
+
let item = new GroupPager(level, route, parent, Object.assign({}, view), searches);
|
|
2655
|
+
item.buttons = this.getPagesArray(6, view.page, view.pages);
|
|
1840
2656
|
this.calculateHash([item]);
|
|
1841
2657
|
return item;
|
|
1842
2658
|
}
|
|
2659
|
+
/**
|
|
2660
|
+
* Sposta la ricerca di una pagina in avanti (o indietro)
|
|
2661
|
+
*
|
|
2662
|
+
* @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
|
|
2663
|
+
* @param {any} pager Elemento di separazione su cui è effettuata la ricerca
|
|
2664
|
+
*/
|
|
2665
|
+
addToPageGroup(page, pager) {
|
|
2666
|
+
this.goToPageGroup(pager.view.page + page, pager);
|
|
2667
|
+
}
|
|
2668
|
+
/**
|
|
2669
|
+
* Sposta la ricerca alla pagina specificata
|
|
2670
|
+
*
|
|
2671
|
+
* @param {number} page Pagina a cui navigare
|
|
2672
|
+
* @param {any} pager Elemento di separazione su cui è effettuata la ricerca
|
|
2673
|
+
*/
|
|
2674
|
+
goToPageGroup(page, pager) {
|
|
2675
|
+
let appSearchElement = pager.view;
|
|
2676
|
+
if (page === 0 || page > appSearchElement.pages)
|
|
2677
|
+
return;
|
|
2678
|
+
appSearchElement.page = page;
|
|
2679
|
+
pager.buttons = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
|
|
2680
|
+
this.emitSearchRequest(false, appSearchElement);
|
|
2681
|
+
}
|
|
1843
2682
|
/**
|
|
1844
2683
|
* Data una colonna effettua la riemissione di tutte le ricerche relative.
|
|
1845
2684
|
*
|
|
@@ -1855,10 +2694,17 @@ class EsTableComponent {
|
|
|
1855
2694
|
*/
|
|
1856
2695
|
emitRowGroupingSearches(column, orderings) {
|
|
1857
2696
|
// Per tutte le ricerche intermedie che devo rivalutare le re-emitto in modo da aggiornargli i dati
|
|
1858
|
-
var meaningfulAppSearches = this.groupSearchRequestsCache.filter(t => t.
|
|
2697
|
+
var meaningfulAppSearches = this.groupSearchRequestsCache.filter(t => t.group_column == column).map(t => t.view);
|
|
2698
|
+
// Se non ne trovo significa che ho fatto l'ordinamento o sugli item, o su colonne relative a un sottogruppo non caricato
|
|
2699
|
+
if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
|
|
2700
|
+
meaningfulAppSearches = this.groupSearchRequestsCache.filter(t => !t.group_column).map(t => t.view);
|
|
2701
|
+
// Se non ne trovo qui significa che sto ordinando su colonne relative a un sottogruppo non caricato
|
|
2702
|
+
if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
|
|
2703
|
+
return;
|
|
1859
2704
|
meaningfulAppSearches.forEach(as => {
|
|
1860
2705
|
// Ovviamente gli oridnamenti devono essere quelli appena generati
|
|
1861
2706
|
as.orders = orderings;
|
|
2707
|
+
as.savedstate = true;
|
|
1862
2708
|
this.emitSearchRequest(false, as);
|
|
1863
2709
|
});
|
|
1864
2710
|
}
|
|
@@ -1875,15 +2721,16 @@ class EsTableComponent {
|
|
|
1875
2721
|
if (grp._sep)
|
|
1876
2722
|
return "";
|
|
1877
2723
|
let display = header.thAggregation;
|
|
1878
|
-
if (grp.column == cell)
|
|
1879
|
-
|
|
2724
|
+
if (grp.column == cell) {
|
|
2725
|
+
let groupsPart = grp._groupscount ? " - " + grp._groupscount + " " + this.lc.loc("Groups") : "";
|
|
2726
|
+
return grp.value + " (" + grp.count + groupsPart + ")";
|
|
2727
|
+
}
|
|
1880
2728
|
else {
|
|
1881
|
-
let agg = grp.
|
|
2729
|
+
let agg = grp._aggregationsCache.get(cell);
|
|
1882
2730
|
if (!agg)
|
|
1883
2731
|
return "";
|
|
1884
2732
|
this.getEsThDirectiveListOfAggregations(header).forEach((itm) => {
|
|
1885
|
-
|
|
1886
|
-
display = display.replace(itm.match, this.formatAggregationValue(aggValue, itm.format));
|
|
2733
|
+
display = display.replace(itm.match, this.formatAggregationValue(agg.get(itm.func), itm.format));
|
|
1887
2734
|
});
|
|
1888
2735
|
return display;
|
|
1889
2736
|
}
|
|
@@ -1898,20 +2745,30 @@ class EsTableComponent {
|
|
|
1898
2745
|
*/
|
|
1899
2746
|
handleGroupClick(group) {
|
|
1900
2747
|
let casted = this.View;
|
|
1901
|
-
let
|
|
1902
|
-
|
|
1903
|
-
|
|
2748
|
+
let anyG = group;
|
|
2749
|
+
anyG._expanded = !anyG._expanded;
|
|
2750
|
+
// Sono in modalità raggruppamento virtuale da array: Espandere significa rendere visibili tutti gli oggetti relativi a questo gruppo, viceversa il contrarre
|
|
2751
|
+
if (this.ArrayGrouping) {
|
|
2752
|
+
let allRelatives = this.boundSource.filter(t => (t._group && ((anyG._expanded && t._parent == anyG._thisKey) || (!anyG._expanded && t._parent && t._parent.startsWith(anyG._thisKey)))) ||
|
|
2753
|
+
(t._item && ((anyG._expanded && t._thisKey == anyG._thisKey) || (!anyG._expanded && t._thisKey.startsWith(anyG._thisKey)))));
|
|
2754
|
+
allRelatives.forEach(t => { t._visible = anyG._expanded; if (t._group)
|
|
2755
|
+
t._expanded = false; });
|
|
2756
|
+
return;
|
|
2757
|
+
}
|
|
2758
|
+
if (anyG._expanded) {
|
|
2759
|
+
// Resetto ipp
|
|
2760
|
+
casted.itemsperpageoverride = 15;
|
|
1904
2761
|
if (!casted.requestedgroups)
|
|
1905
2762
|
casted.requestedgroups = [new GroupFilter(group.column, group.value)];
|
|
1906
2763
|
else {
|
|
1907
|
-
let level =
|
|
2764
|
+
let level = anyG._grouplevel;
|
|
1908
2765
|
// se il gruppo cliccato non ha un livello è il primo gruppo, quindi ordinamento unico
|
|
1909
2766
|
// altrimenti devo rimuovere tutti i filtri su livelli superiori al level cliccato e aggiungere il level cliccato
|
|
1910
2767
|
if (!level)
|
|
1911
2768
|
casted.requestedgroups = [new GroupFilter(group.column, group.value)];
|
|
1912
2769
|
else {
|
|
1913
2770
|
casted.requestedgroups = [];
|
|
1914
|
-
|
|
2771
|
+
anyG._parentRoute.forEach((step) => {
|
|
1915
2772
|
casted.requestedgroups.push(new GroupFilter(step.column, step.value));
|
|
1916
2773
|
});
|
|
1917
2774
|
casted.requestedgroups.push(new GroupFilter(group.column, group.value));
|
|
@@ -1921,7 +2778,7 @@ class EsTableComponent {
|
|
|
1921
2778
|
this.emitSearchRequest(true);
|
|
1922
2779
|
}
|
|
1923
2780
|
else {
|
|
1924
|
-
let path = (
|
|
2781
|
+
let path = (anyG._parent || '') + group.value;
|
|
1925
2782
|
// Se ho chiuso un gruppo non mi serve rieffettuare ricerce, mi basta eliminare dagli oggetti bindati tutti gli elementi sottostanti a quel gruppo
|
|
1926
2783
|
this.boundSource = this.boundSource.filter(t => !t._parent || !t._parent.startsWith(path));
|
|
1927
2784
|
// devo però anche rimuovere eventuali cache relative
|
|
@@ -1940,7 +2797,9 @@ class EsTableComponent {
|
|
|
1940
2797
|
formatAggregationValue(value, format) {
|
|
1941
2798
|
if (!format)
|
|
1942
2799
|
return value;
|
|
1943
|
-
let isNumber = !Number.isNaN(value) && !format || format.startsWith("F");
|
|
2800
|
+
let isNumber = !Number.isNaN(value) && (!format || format.startsWith("F"));
|
|
2801
|
+
if (isNumber && format.startsWith("F") && !Number.isNaN(format.substr(1)))
|
|
2802
|
+
return parseFloat(value).toFixed(parseInt(format.substr(1)));
|
|
1944
2803
|
let date = null;
|
|
1945
2804
|
// Alcune versione di extensions rischiano di crashare con cose non date... è stato risolto dopo quindi questo try - catch in realtà
|
|
1946
2805
|
// torna utile solo con versioni vecchie/deprecate della libreria @esfaenza/extensions
|
|
@@ -1950,10 +2809,6 @@ class EsTableComponent {
|
|
|
1950
2809
|
catch (_a) { }
|
|
1951
2810
|
if (date)
|
|
1952
2811
|
return this.dateExts.getFormatted(date, format == 'small', format == 'verylong');
|
|
1953
|
-
else if (isNumber) {
|
|
1954
|
-
if (format.startsWith("F") && !Number.isNaN(format.substr(1)))
|
|
1955
|
-
return parseFloat(value).toFixed(parseInt(format.substr(1)));
|
|
1956
|
-
}
|
|
1957
2812
|
// Qui ci finisco sia per input che non sono né date né numeri, sia per formati non riconosciuti
|
|
1958
2813
|
return value;
|
|
1959
2814
|
}
|
|
@@ -1966,7 +2821,7 @@ class EsTableComponent {
|
|
|
1966
2821
|
*/
|
|
1967
2822
|
sendUp(columnItem) {
|
|
1968
2823
|
let itemIndex = this.TMPColumnsList.indexOf(columnItem);
|
|
1969
|
-
if (this.TMPColumnsList[itemIndex - 1].fixed)
|
|
2824
|
+
if (this.TMPColumnsList[itemIndex - 1].fixed || this.TMPColumnsList[itemIndex - 1].pinned)
|
|
1970
2825
|
return;
|
|
1971
2826
|
this.utiExts.swap(this.TMPColumnsList, itemIndex, itemIndex - 1);
|
|
1972
2827
|
// Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
|
|
@@ -1987,6 +2842,25 @@ class EsTableComponent {
|
|
|
1987
2842
|
this.TMPColumnsList.forEach(c => { tmp.push(Object.assign({}, c)); });
|
|
1988
2843
|
this.TMPColumnsList = tmp;
|
|
1989
2844
|
}
|
|
2845
|
+
/**
|
|
2846
|
+
* All'interno della dialog "Ordinamento e Visibilità Colonne" pinna la colonna specificata
|
|
2847
|
+
*
|
|
2848
|
+
* @param {EsTableColumn} columnItem Colonna da spostare
|
|
2849
|
+
*/
|
|
2850
|
+
pinOrUnpinColumn(columnItem) {
|
|
2851
|
+
let itemIndex = this.TMPColumnsList.indexOf(columnItem);
|
|
2852
|
+
// Sposto la colonna alla fine di tutte quelle pinnate. La cosa funziona in entrambi sensi:
|
|
2853
|
+
// 1) Se sto pinnando, devo metterla come ultima pinnata
|
|
2854
|
+
// 2) Se sto spinnando devo metterla come prima non pinnata
|
|
2855
|
+
// Coincidenza vuole che il punto 1 e 2 siano equivalenti
|
|
2856
|
+
for (let i = 0; i < this.TMPColumnsList.length; i++) {
|
|
2857
|
+
if (!this.TMPColumnsList[i].pinned) {
|
|
2858
|
+
this.arrayMove(this.TMPColumnsList, itemIndex, i);
|
|
2859
|
+
break;
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
columnItem.pinned = !columnItem.pinned;
|
|
2863
|
+
}
|
|
1990
2864
|
/**
|
|
1991
2865
|
* All'interno della dialog "Ordinamento e Visibilità Colonne" inverte le impostazioni di visibilità della colonna
|
|
1992
2866
|
*
|
|
@@ -2045,12 +2919,12 @@ class EsTableComponent {
|
|
|
2045
2919
|
// Non permetto di non selezionare nulla
|
|
2046
2920
|
if (this.TMPColumnsList.every(t => !t.visible))
|
|
2047
2921
|
return false;
|
|
2048
|
-
let castedView = this.View;
|
|
2922
|
+
let castedView = this.viewMode ? this.View : null;
|
|
2049
2923
|
this.ColumnsList = [];
|
|
2050
2924
|
this.TMPColumnsList.forEach(c => { this.ColumnsList.push(Object.assign({}, c)); });
|
|
2051
2925
|
this.refreshColumnOrdering();
|
|
2052
|
-
this.refreshColumnsVisibility(null, null, castedView);
|
|
2053
2926
|
this.applyOrdering(castedView, false);
|
|
2927
|
+
this.refreshColumnsVisibility(null, null, castedView);
|
|
2054
2928
|
//Salvo le preferences di questa view
|
|
2055
2929
|
//Di default registro ordinamento e visibilità delle colonne nella vista. Solo le cose di UI
|
|
2056
2930
|
if (this.SavePreferences) {
|
|
@@ -2062,11 +2936,17 @@ class EsTableComponent {
|
|
|
2062
2936
|
console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
|
|
2063
2937
|
return false;
|
|
2064
2938
|
}
|
|
2065
|
-
|
|
2939
|
+
let columns = this.arrayMode ? this.arrayColumns : castedView.columns;
|
|
2940
|
+
let columnsOrderings = this.arrayMode ? this.arrayColumnOrdering : castedView.column_ordering;
|
|
2941
|
+
var toStore = { columns: JSON.parse(JSON.stringify(columns)), column_ordering: JSON.parse(JSON.stringify(columnsOrderings)) };
|
|
2066
2942
|
this.prefService.store(this.ngControl.name, toStore);
|
|
2067
2943
|
}
|
|
2944
|
+
// Rieseguo l'ultima ricerca bindata alla tabella
|
|
2068
2945
|
// Mi assicuro di farlo dopo l'espansione del changed o rischio che la ricerca mi ridia colonne che in realtà non esistono
|
|
2069
|
-
|
|
2946
|
+
if (this.viewMode)
|
|
2947
|
+
setTimeout(() => { this.emitSearchRequest(false); });
|
|
2948
|
+
else if (this.arrayMode)
|
|
2949
|
+
setTimeout(() => { this.internalWriteValue(); });
|
|
2070
2950
|
// Lo vorrei mettere lato template ma no
|
|
2071
2951
|
this.lastSelectedItemID = null;
|
|
2072
2952
|
return true;
|
|
@@ -2075,7 +2955,8 @@ class EsTableComponent {
|
|
|
2075
2955
|
* Sul click nella checkbox di selezione globale si scorrono tutte le colonne e si impostano al valore della check globale
|
|
2076
2956
|
*/
|
|
2077
2957
|
globalColVisCheckChanged() {
|
|
2078
|
-
this.TMPColumnsList.forEach(t => { t.
|
|
2958
|
+
this.TMPColumnsList.forEach(t => { if (!t.fixed)
|
|
2959
|
+
t.visible = this.globalColVisCheck; });
|
|
2079
2960
|
}
|
|
2080
2961
|
// #endregion
|
|
2081
2962
|
// #region Gestione data source gerarchici
|
|
@@ -2123,9 +3004,9 @@ class EsTableComponent {
|
|
|
2123
3004
|
let obj = objs[i];
|
|
2124
3005
|
// Se la parentKey non è valorizzata, questo è il livello 0 (1... perché gli 0 son perciolosi)
|
|
2125
3006
|
if (!obj[this.ParentKey] && levelToAssign == 1) {
|
|
2126
|
-
obj.
|
|
2127
|
-
obj.
|
|
2128
|
-
obj.
|
|
3007
|
+
obj._level = 1;
|
|
3008
|
+
obj._visible = true;
|
|
3009
|
+
obj._expanded = this.StartsExpanded;
|
|
2129
3010
|
assigned++;
|
|
2130
3011
|
continue;
|
|
2131
3012
|
}
|
|
@@ -2135,13 +3016,13 @@ class EsTableComponent {
|
|
|
2135
3016
|
for (let p = 0; p < objs.length; p++) {
|
|
2136
3017
|
let possibleParent = objs[p];
|
|
2137
3018
|
// Trovato il parent dell'item, assegno all'item il livello giusto
|
|
2138
|
-
if (possibleParent[this.OwnKey] == obj[this.ParentKey] && possibleParent.
|
|
2139
|
-
obj.
|
|
3019
|
+
if (possibleParent[this.OwnKey] == obj[this.ParentKey] && possibleParent._level == levelToAssign - 1) {
|
|
3020
|
+
obj._level = levelToAssign;
|
|
2140
3021
|
// So che questo item ha un parent. Ribadisco che il parent è espanso in base alle impostazione e stessa logica
|
|
2141
3022
|
// per la visibilità del figlio
|
|
2142
|
-
possibleParent.
|
|
3023
|
+
possibleParent._expanded = this.StartsExpanded;
|
|
2143
3024
|
possibleParent.parent = true;
|
|
2144
|
-
obj.
|
|
3025
|
+
obj._visible = this.StartsExpanded;
|
|
2145
3026
|
assigned++;
|
|
2146
3027
|
break;
|
|
2147
3028
|
}
|
|
@@ -2160,12 +3041,12 @@ class EsTableComponent {
|
|
|
2160
3041
|
let obj = this.boundSource[i];
|
|
2161
3042
|
// Trovo il parent con quell'id e lo espando
|
|
2162
3043
|
if (obj[this.OwnKey] == key) {
|
|
2163
|
-
obj.
|
|
3044
|
+
obj._expanded = true;
|
|
2164
3045
|
for (let ic = 0; ic < this.boundSource.length; ic++) {
|
|
2165
3046
|
let child = this.boundSource[ic];
|
|
2166
3047
|
// Trovo tutti i child di quel parent e li rendo visibili
|
|
2167
3048
|
if (child[this.ParentKey] == key)
|
|
2168
|
-
child.
|
|
3049
|
+
child._visible = true;
|
|
2169
3050
|
}
|
|
2170
3051
|
return;
|
|
2171
3052
|
}
|
|
@@ -2181,7 +3062,7 @@ class EsTableComponent {
|
|
|
2181
3062
|
let obj = this.boundSource[i];
|
|
2182
3063
|
// Trovo il parent con quell'id e lo collasso
|
|
2183
3064
|
if (obj[this.OwnKey] == key) {
|
|
2184
|
-
obj.
|
|
3065
|
+
obj._expanded = false;
|
|
2185
3066
|
// Collasso/nascondo tutti i child del parent
|
|
2186
3067
|
this.collapseChildOfParent(key);
|
|
2187
3068
|
return;
|
|
@@ -2199,10 +3080,10 @@ class EsTableComponent {
|
|
|
2199
3080
|
// Trovo tutti i child di quel parent e li rendo invisibili. Se il child trovato è a sua volta un parent,
|
|
2200
3081
|
// lo collasso e vado in ricorsione sui figli
|
|
2201
3082
|
if (child[this.ParentKey] == parentKey && !child.parent)
|
|
2202
|
-
child.
|
|
3083
|
+
child._visible = false;
|
|
2203
3084
|
else if (child[this.ParentKey] == parentKey && child.parent) {
|
|
2204
|
-
child.
|
|
2205
|
-
child.
|
|
3085
|
+
child._expanded = false;
|
|
3086
|
+
child._visible = false;
|
|
2206
3087
|
this.collapseChildOfParent(child[this.OwnKey]);
|
|
2207
3088
|
}
|
|
2208
3089
|
}
|
|
@@ -2237,22 +3118,29 @@ class EsTableComponent {
|
|
|
2237
3118
|
* @param {ItemsSelection<any>} selectionItem Oggetto contenente lo stato attuale di selezione
|
|
2238
3119
|
*/
|
|
2239
3120
|
handleSelectionEvaluation(items, selectionItem) {
|
|
2240
|
-
let allSelected = items.length > 0;
|
|
2241
3121
|
for (let i = 0; i < items.length; i++) {
|
|
2242
3122
|
let itm = items[i];
|
|
3123
|
+
let hash = itm._hash;
|
|
3124
|
+
let itemGroup = itm._group ? null : this.getItemGroup(itm);
|
|
2243
3125
|
// Reidrato la cache di selezione coi nuovi oggetti altrimenti non riuscirei a beccare gli indici giusti
|
|
2244
3126
|
// Dopodiché la uso per calcolare istantaneamente se gli oggetti sono selezionati o no
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
3127
|
+
this.rehidrateCache(itm);
|
|
3128
|
+
if (itm._item) {
|
|
3129
|
+
if (selectionItem.all)
|
|
3130
|
+
itm._selected = !this.exclusionsCache.has(hash) && ((!this.groupsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash) && this.itemsCache.has(hash)) || !this.group_exclusionsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash));
|
|
3131
|
+
else
|
|
3132
|
+
itm._selected = !this.exclusionsCache.has(hash) && (this.groupsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash) || this.itemsCache.has(hash) || (this.parentTreeStatus(itemGroup) == 'included' && !this.group_exclusionsCache.has(itemGroup === null || itemGroup === void 0 ? void 0 : itemGroup._hash)));
|
|
3133
|
+
}
|
|
3134
|
+
else if (itm._group) {
|
|
3135
|
+
if (selectionItem.all)
|
|
3136
|
+
itm._selected = !this.group_exclusionsCache.has(hash) && this.parentTreeStatus(itm) != 'excluded';
|
|
3137
|
+
else
|
|
3138
|
+
itm._selected = this.groupsCache.has(hash) || (this.parentTreeStatus(itm) == 'included' && !this.group_exclusionsCache.has(hash));
|
|
3139
|
+
}
|
|
2252
3140
|
}
|
|
2253
3141
|
// Se tutti gli oggetti di questa pagina sono solezionati allora posso mettere il global check a true
|
|
2254
3142
|
// Se sono in situazione di all-select anche metto la global checkbox, nonostante ci possano essere delle esclusioni
|
|
2255
|
-
this.globalCheck =
|
|
3143
|
+
this.globalCheck = this.boundSource.filter(t => t._group || t._item).every(t => t._selected);
|
|
2256
3144
|
this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
|
|
2257
3145
|
// Potrebbe cambiare qualora qualcuno inserisse dati a manazza in modalità Array e desse il refresh manuale alla tabella
|
|
2258
3146
|
// Comunque costa 0 quindi mi permetto di refreshare
|
|
@@ -2263,14 +3151,52 @@ class EsTableComponent {
|
|
|
2263
3151
|
this.onSelectionChanged.emit(selectionItem);
|
|
2264
3152
|
}
|
|
2265
3153
|
}
|
|
3154
|
+
/**
|
|
3155
|
+
* Dato un oggetto trova la cella di cache in cui è registrato e aggiorna il contenuto
|
|
3156
|
+
*
|
|
3157
|
+
* @param {any} item Oggetto da aggiornare
|
|
3158
|
+
*/
|
|
3159
|
+
rehidrateCache(item) {
|
|
3160
|
+
let ctx = item._hash;
|
|
3161
|
+
if (this.itemsCache.has(ctx))
|
|
3162
|
+
this.itemsCache.set(ctx, item);
|
|
3163
|
+
if (this.group_exclusionsCache.has(ctx))
|
|
3164
|
+
this.group_exclusionsCache.set(ctx, item);
|
|
3165
|
+
if (this.groupsCache.has(ctx))
|
|
3166
|
+
this.groupsCache.set(ctx, item);
|
|
3167
|
+
if (this.exclusionsCache.has(ctx))
|
|
3168
|
+
this.exclusionsCache.set(ctx, item);
|
|
3169
|
+
}
|
|
3170
|
+
/**
|
|
3171
|
+
* Dato un gruppo controlla ricorsivamente l'albero di cui fa parte se c'è stata una inclusione o esclusione diretta
|
|
3172
|
+
*
|
|
3173
|
+
* @param {any} grp Gruppo da controllare
|
|
3174
|
+
*
|
|
3175
|
+
* @returns {'none' | 'excluded' | 'included'}
|
|
3176
|
+
* 'none' se non ci sono informazioni su inclusioni o esclusioni
|
|
3177
|
+
* 'included' se il gruppo controllato è stato incluso in maniera esplicita dall'albero dei gruppi padri
|
|
3178
|
+
* 'excluded' se il gruppo controllato è stato escluso in maniera esplicita dall'albero dei gruppi padri
|
|
3179
|
+
*/
|
|
3180
|
+
parentTreeStatus(grp) {
|
|
3181
|
+
if (!grp)
|
|
3182
|
+
return 'none';
|
|
3183
|
+
let parentGroup = this.rgGroupCache.get(grp._parent);
|
|
3184
|
+
if (!parentGroup)
|
|
3185
|
+
return 'none';
|
|
3186
|
+
if (this.group_exclusionsCache.has(parentGroup._hash))
|
|
3187
|
+
return 'excluded';
|
|
3188
|
+
if (this.groupsCache.has(parentGroup._hash))
|
|
3189
|
+
return 'included';
|
|
3190
|
+
return this.parentTreeStatus(parentGroup);
|
|
3191
|
+
}
|
|
2266
3192
|
/**
|
|
2267
3193
|
* Gestisce la selezione globale degli oggetti, sia per pagina che a livello di **SelectAll**
|
|
2268
3194
|
*
|
|
2269
3195
|
* @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
|
|
2270
3196
|
*/
|
|
2271
3197
|
globalCheckChanged(forcedVal = null) {
|
|
2272
|
-
// Prendo tutti gli elementi presenti in questa vista
|
|
2273
|
-
let items = this.boundSource.filter(t => !t.
|
|
3198
|
+
// Prendo tutti gli elementi presenti in questa vista. Se ho gruppi prendo solo i gruppi a livello 0, altrimenti prendo tutti gli oggetti per selezionarli
|
|
3199
|
+
let items = this.boundSource.find(t => t._group) ? this.boundSource.filter(t => t._group && !t._parent) : this.boundSource;
|
|
2274
3200
|
var itemSelection = this.handleItemsSelection(items, forcedVal, this.globalCheck);
|
|
2275
3201
|
this.changed();
|
|
2276
3202
|
this.onSelectionChanged.emit(itemSelection);
|
|
@@ -2282,18 +3208,19 @@ class EsTableComponent {
|
|
|
2282
3208
|
*
|
|
2283
3209
|
* @param {any[]} items Oggetti da selezionare o deselezionare
|
|
2284
3210
|
* @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
|
|
3211
|
+
* @param {boolean} globalCheck Valore del check globale
|
|
2285
3212
|
*
|
|
2286
3213
|
* @returns {ItemsSelection<any>} Oggetto di selezione aggiornato con le informazioni sull'ultima operazione effettuata
|
|
2287
3214
|
*/
|
|
2288
3215
|
handleItemsSelection(items, forcedVal = null, globalCheck = null) {
|
|
2289
|
-
var _a, _b;
|
|
2290
|
-
let
|
|
3216
|
+
var _a, _b, _c;
|
|
3217
|
+
let si = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
|
|
2291
3218
|
// Se sono in modalità di selezione singola e devo selezionare un'oggetto, per prima cosa devo deselezionare tutti gli altri
|
|
2292
|
-
if (this.SingleSelection && ((_b = items[0]) === null || _b === void 0 ? void 0 : _b._selected)) {
|
|
3219
|
+
if (this.SingleSelection && ((_b = items[0]) === null || _b === void 0 ? void 0 : _b._selected) && !((_c = items[0]) === null || _c === void 0 ? void 0 : _c._group)) {
|
|
2293
3220
|
if (items.length > 1 && forcedVal == null)
|
|
2294
3221
|
throw "Tentativo di selezionare o deselezionare più di un elemento con SingleSelection attivo";
|
|
2295
3222
|
if (items.length == 1 && forcedVal == null) {
|
|
2296
|
-
|
|
3223
|
+
si = this.handleItemsSelection(this.boundSource.filter(t => !t._group), false, null);
|
|
2297
3224
|
items[0]._selected = true;
|
|
2298
3225
|
}
|
|
2299
3226
|
}
|
|
@@ -2303,59 +3230,343 @@ class EsTableComponent {
|
|
|
2303
3230
|
// Se dev'essere overridato il valore di check effettuo l'override o col valore forzato o col valore globale
|
|
2304
3231
|
if (toChange && !item.locked)
|
|
2305
3232
|
item._selected = forcedVal != null ? forcedVal : this.globalCheck;
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
3233
|
+
// Se il valore non dev'essere variato e vengo da una selezione globale semplicemente evito di effettuare operaizoni inutili. L'item/gruppo è già nello stato giusto
|
|
3234
|
+
if (!toChange && globalCheck != null)
|
|
3235
|
+
continue;
|
|
3236
|
+
let allSelection = si.all;
|
|
3237
|
+
let isGroup = item._group;
|
|
3238
|
+
let isSelection = item._selected;
|
|
3239
|
+
let itemGroup = null, allItems = null, selectedItems = null, unselectedItems = null, allGroups = null, selectedGroups = null, unselectedGroups = null, parentGroupSelected = null, parentGroupUnselected = null;
|
|
3240
|
+
if (isGroup) {
|
|
3241
|
+
let pts = this.parentTreeStatus(item);
|
|
3242
|
+
parentGroupSelected = pts == 'included';
|
|
3243
|
+
parentGroupUnselected = pts == 'excluded';
|
|
3244
|
+
allItems = this.getGroupItems(si, item, null, true);
|
|
3245
|
+
selectedItems = this.getGroupItems(si, item, 'selected', true, allItems);
|
|
3246
|
+
unselectedItems = this.getGroupItems(si, item, 'unselected', true, allItems);
|
|
3247
|
+
allGroups = this.getGroupChildGroups(si, item, null, true);
|
|
3248
|
+
selectedGroups = this.getGroupChildGroups(si, item, 'selected', true, allGroups);
|
|
3249
|
+
unselectedGroups = this.getGroupChildGroups(si, item, 'unselected', true, allGroups);
|
|
2319
3250
|
}
|
|
2320
3251
|
else {
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
// Oggetto selezionato: lo aggiungo alla selezione attuale
|
|
2325
|
-
this.selOrDeselCache[item.hash] = item;
|
|
2326
|
-
selectionItem.items.push(item);
|
|
2327
|
-
}
|
|
2328
|
-
else if (!item._selected && this.selOrDeselCache[item.hash]) {
|
|
2329
|
-
// Oggetto deselezionato: lo rimuovo dalla selezione attuale
|
|
2330
|
-
selectionItem.items.splice(selectionItem.items.indexOf(this.selOrDeselCache[item.hash]), 1);
|
|
2331
|
-
delete this.selOrDeselCache[item.hash];
|
|
2332
|
-
}
|
|
3252
|
+
itemGroup = this.getItemGroup(item);
|
|
3253
|
+
parentGroupSelected = itemGroup == null ? null : itemGroup._selected;
|
|
3254
|
+
parentGroupUnselected = itemGroup == null ? null : !itemGroup._selected;
|
|
2333
3255
|
}
|
|
3256
|
+
if (!this.ArrayGrouping)
|
|
3257
|
+
this.performSelectionOperations(si, item, allSelection, isGroup, isSelection, selectedItems, selectedGroups, unselectedItems, unselectedGroups, allItems, allGroups, parentGroupSelected, parentGroupUnselected);
|
|
3258
|
+
else
|
|
3259
|
+
this.performSimpleSelectionOperations(si, item, isGroup, isSelection, itemGroup, selectedItems, unselectedItems, allItems, allGroups);
|
|
2334
3260
|
}
|
|
2335
3261
|
// Imposto il check globale in base a se tutti gli elementi sono selezionati o meno.
|
|
2336
3262
|
// Evito di fare queste operazioni se la selezione deriva proprio dal global Check
|
|
2337
|
-
// Non è ottimizzatissimo mettere 2 some ma scrivere questo codice a for sono tipo 25 righe....
|
|
2338
3263
|
if (globalCheck == null)
|
|
2339
|
-
this.globalCheck = !
|
|
2340
|
-
this.finalizeSelectionInformations(
|
|
2341
|
-
return
|
|
3264
|
+
this.globalCheck = !this.boundSource.some(t => !t._selected && !t._sep);
|
|
3265
|
+
this.finalizeSelectionInformations(si);
|
|
3266
|
+
return si;
|
|
3267
|
+
}
|
|
3268
|
+
/**
|
|
3269
|
+
* Dato L'oggetto di selezione, l'oggetto da selezionare/deselezionare e tutti i parametri del caso effettua le operazioni che servono.
|
|
3270
|
+
*
|
|
3271
|
+
* Logica semplificata rispetto all'originale **performSelectionOperations** per lavorare in una modalità in cui tutti gli elementi sono caricati (**ArrayGrouping** = true)
|
|
3272
|
+
*/
|
|
3273
|
+
performSimpleSelectionOperations(base, item, group, sel, itm_group, sel_itm, desel_itm, all_itms, all_grps) {
|
|
3274
|
+
let tripticItem = this.getTriptic('item', base);
|
|
3275
|
+
if (group) {
|
|
3276
|
+
if (sel) {
|
|
3277
|
+
all_grps.forEach(gr => { gr._selected = true; });
|
|
3278
|
+
if (desel_itm)
|
|
3279
|
+
desel_itm.forEach(el => { el._selected = true; this.addItem(el, tripticItem); });
|
|
3280
|
+
}
|
|
3281
|
+
else {
|
|
3282
|
+
all_grps.forEach(gr => { gr._selected = false; });
|
|
3283
|
+
if (sel_itm)
|
|
3284
|
+
sel_itm.forEach(el => { el._selected = false; this.removeItem(el, tripticItem); });
|
|
3285
|
+
}
|
|
3286
|
+
}
|
|
3287
|
+
else {
|
|
3288
|
+
if (sel) {
|
|
3289
|
+
this.addItem(item, tripticItem);
|
|
3290
|
+
if (itm_group && all_itms && all_itms.every(t => t._selected))
|
|
3291
|
+
this.selectGroup(itm_group);
|
|
3292
|
+
}
|
|
3293
|
+
else {
|
|
3294
|
+
this.removeItem(item, tripticItem);
|
|
3295
|
+
if (itm_group)
|
|
3296
|
+
itm_group._selected = false;
|
|
3297
|
+
}
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
/**
|
|
3301
|
+
* Helper per selezionare un gruppo e, ricorsivamente, se tutti i gruppi sottostanti al parent sono selezionati, selezionare i gruppi padri
|
|
3302
|
+
*
|
|
3303
|
+
* @param {any} group Gruppo da selezionare
|
|
3304
|
+
*/
|
|
3305
|
+
selectGroup(group) {
|
|
3306
|
+
group._selected = true;
|
|
3307
|
+
let parent = this.getGroupParent(group);
|
|
3308
|
+
if (parent && this.getGroupChildGroups(null, parent, null, true).every(t => t._selected))
|
|
3309
|
+
this.selectGroup(parent);
|
|
3310
|
+
}
|
|
3311
|
+
/**
|
|
3312
|
+
* Dato L'oggetto di selezione, l'oggetto da selezionare/deselezionare e tutti i parametri del caso effettua le operazioni che servono.
|
|
3313
|
+
*
|
|
3314
|
+
* La logica di questa funzione è nata essenzialmente da spam di trial & error ed è stata testata solo fino a due livelli di raggruppamento,
|
|
3315
|
+
* qualsiasi cosa vada oltre non è 100% detto che funzioni...
|
|
3316
|
+
*/
|
|
3317
|
+
performSelectionOperations(base, item, all, group, sel, sel_itm, sel_grp, desel_itm, desel_grp, all_itms, all_grps, parent_incl, parent_excl) {
|
|
3318
|
+
let tripticGroup = this.getTriptic('group', base);
|
|
3319
|
+
let tripticItem = this.getTriptic('item', base);
|
|
3320
|
+
let tripticExcl = this.getTriptic('exclusion', base);
|
|
3321
|
+
let tripticgrpExcl = this.getTriptic('group_exclusion', base);
|
|
3322
|
+
if (group) {
|
|
3323
|
+
if (sel) {
|
|
3324
|
+
if (all || parent_incl)
|
|
3325
|
+
this.removeItem(item, tripticgrpExcl);
|
|
3326
|
+
else
|
|
3327
|
+
this.addItem(item, tripticGroup);
|
|
3328
|
+
if (sel_itm)
|
|
3329
|
+
sel_itm.forEach(el => this.removeItem(el, tripticItem));
|
|
3330
|
+
if (sel_grp)
|
|
3331
|
+
sel_grp.forEach(gr => this.removeItem(gr, tripticGroup));
|
|
3332
|
+
if (all_itms)
|
|
3333
|
+
all_itms.forEach(el => { el._selected = true; this.removeItem(el, tripticExcl); });
|
|
3334
|
+
if (all_grps)
|
|
3335
|
+
all_grps.forEach(gr => { gr._selected = true; this.removeItem(gr, tripticgrpExcl); });
|
|
3336
|
+
}
|
|
3337
|
+
else {
|
|
3338
|
+
if (all || parent_incl)
|
|
3339
|
+
this.addItem(item, tripticgrpExcl);
|
|
3340
|
+
else
|
|
3341
|
+
this.removeItem(item, tripticGroup);
|
|
3342
|
+
if (desel_itm)
|
|
3343
|
+
desel_itm.forEach(el => this.removeItem(el, tripticExcl));
|
|
3344
|
+
if (desel_grp)
|
|
3345
|
+
desel_grp.forEach(gr => this.removeItem(gr, tripticExcl));
|
|
3346
|
+
if (all_itms)
|
|
3347
|
+
all_itms.forEach(el => { el._selected = false; this.removeItem(el, tripticItem); });
|
|
3348
|
+
if (all_grps)
|
|
3349
|
+
all_grps.forEach(gr => { gr._selected = false; this.removeItem(gr, tripticGroup); });
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
else {
|
|
3353
|
+
if (sel) {
|
|
3354
|
+
if ((parent_excl == null && all) || parent_incl)
|
|
3355
|
+
this.removeItem(item, tripticExcl);
|
|
3356
|
+
else
|
|
3357
|
+
this.addItem(item, tripticItem);
|
|
3358
|
+
}
|
|
3359
|
+
else {
|
|
3360
|
+
if (parent_excl || (!all && parent_excl == null))
|
|
3361
|
+
this.removeItem(item, tripticItem);
|
|
3362
|
+
else
|
|
3363
|
+
this.addItem(item, tripticExcl);
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
/**
|
|
3368
|
+
* Helper per evitare di riscrivere ogni santa volta array.splice(array.indexof(item), 1);
|
|
3369
|
+
*/
|
|
3370
|
+
removeItem(item, triptic) {
|
|
3371
|
+
let index = triptic.index_cache.get(item._hash);
|
|
3372
|
+
if (index != null) {
|
|
3373
|
+
triptic.cache.delete(item._hash);
|
|
3374
|
+
triptic.index_cache.delete(item._hash);
|
|
3375
|
+
triptic.array[index] = null;
|
|
3376
|
+
}
|
|
3377
|
+
return !!index;
|
|
3378
|
+
}
|
|
3379
|
+
/**
|
|
3380
|
+
* Helper per evitare di riscrivere ogni santa volta array.push(item); e la gestione della
|
|
3381
|
+
*/
|
|
3382
|
+
addItem(item, triptic) {
|
|
3383
|
+
if (triptic.index_cache.get(item._hash) == null) {
|
|
3384
|
+
let i = triptic.array.push(item) - 1;
|
|
3385
|
+
triptic.cache.set(item._hash, item);
|
|
3386
|
+
triptic.index_cache.set(item._hash, i);
|
|
3387
|
+
return true;
|
|
3388
|
+
}
|
|
3389
|
+
return false;
|
|
3390
|
+
}
|
|
3391
|
+
/**
|
|
3392
|
+
* Ottiene il trittico di selezione: L'array degli oggetti e le due cache
|
|
3393
|
+
*/
|
|
3394
|
+
getTriptic(subject, base) {
|
|
3395
|
+
switch (subject) {
|
|
3396
|
+
case 'group':
|
|
3397
|
+
return new CacheTriptic(this.groupsCache, this.i_groupsCache, base.groups);
|
|
3398
|
+
case 'item':
|
|
3399
|
+
return new CacheTriptic(this.itemsCache, this.i_itemsCache, base.items);
|
|
3400
|
+
case 'group_exclusion':
|
|
3401
|
+
return new CacheTriptic(this.group_exclusionsCache, this.i_group_exclusionsCache, base.group_exclusions);
|
|
3402
|
+
case 'exclusion':
|
|
3403
|
+
return new CacheTriptic(this.exclusionsCache, this.i_exclusionsCache, base.exclusions);
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
/**
|
|
3407
|
+
* Dato un oggetto restituisce il gruppo di cui fa parte, se esiste
|
|
3408
|
+
*
|
|
3409
|
+
* @param {any} item Oggetto di cui trovare il gruppo
|
|
3410
|
+
*/
|
|
3411
|
+
getItemGroup(item) {
|
|
3412
|
+
let parent = this.rgGroupCache.get(item._thisKey);
|
|
3413
|
+
if (parent)
|
|
3414
|
+
return parent;
|
|
3415
|
+
return null;
|
|
3416
|
+
}
|
|
3417
|
+
/**
|
|
3418
|
+
* Data la chiave di un gruppo restituisce tutti gli oggetti con quella chiave
|
|
3419
|
+
*
|
|
3420
|
+
* @param {any} group Chiave da cercare
|
|
3421
|
+
* @param {'selected' | 'unselected'} status Stato degli elementi, selezionati o no
|
|
3422
|
+
* @param {boolean} recursive Indica se cercare solo gli elementi direttamente collegati o se prendere anche quelli dei gruppi figli
|
|
3423
|
+
*
|
|
3424
|
+
* @returns {any[]} Oggetti di tipo **_item** facenti capo alla chiave **groupKey**
|
|
3425
|
+
*/
|
|
3426
|
+
getGroupItems(sel, group, status, recursive = false, allbase = null) {
|
|
3427
|
+
let items = [];
|
|
3428
|
+
if (allbase)
|
|
3429
|
+
items = allbase;
|
|
3430
|
+
else {
|
|
3431
|
+
if (recursive) {
|
|
3432
|
+
// In modalità ricorsiva prendo gli oggetti di tutte le chiavi simili che trovo
|
|
3433
|
+
for (let key of this.rgItemCache.keys())
|
|
3434
|
+
if (key.startsWith(group._thisKey))
|
|
3435
|
+
items.push(...this.rgItemCache.get(key));
|
|
3436
|
+
}
|
|
3437
|
+
else
|
|
3438
|
+
items = this.rgItemCache.get(group._thisKey);
|
|
3439
|
+
}
|
|
3440
|
+
items = items.filter(t => !status || (t._selected && status == 'selected') || (!t._selected && status == 'unselected'));
|
|
3441
|
+
// Non trovo nessun oggetto, però magari di oggetti ne ho all'interno dell'oggetto di selezione.
|
|
3442
|
+
// Questo può essere vero solo se NON sono in modalità array, in caso contrario gli oggetti li devo per forza avere tutti
|
|
3443
|
+
if (items.length != 0 || !sel || this.arrayMode)
|
|
3444
|
+
return items;
|
|
3445
|
+
if (status == 'unselected')
|
|
3446
|
+
items = sel.exclusions.filter(t => t != null &&
|
|
3447
|
+
(!recursive && t._thisKey == group._thisKey) ||
|
|
3448
|
+
(recursive && t._thisKey.startsWith(group._thisKey)));
|
|
3449
|
+
else if (status == 'selected')
|
|
3450
|
+
items = sel.items.filter(t => t != null &&
|
|
3451
|
+
(!recursive && t._thisKey == group._thisKey) ||
|
|
3452
|
+
(recursive && t._thisKey.startsWith(group._thisKey)));
|
|
3453
|
+
return items;
|
|
3454
|
+
}
|
|
3455
|
+
/**
|
|
3456
|
+
* Data la chiave di un gruppo restituisce tutti gli oggetti con quella chiave
|
|
3457
|
+
*
|
|
3458
|
+
* @param {any} group Gruppo di cui cercare il parent
|
|
3459
|
+
*
|
|
3460
|
+
* @returns {any} Oggetto di tipo **_group** rappresentante il parent del **group** attuale
|
|
3461
|
+
*/
|
|
3462
|
+
getGroupParent(group) {
|
|
3463
|
+
let parent = this.rgGroupCache.get(group._parent);
|
|
3464
|
+
if (parent)
|
|
3465
|
+
return parent;
|
|
3466
|
+
return null;
|
|
3467
|
+
}
|
|
3468
|
+
/**
|
|
3469
|
+
* Data la chiave di un gruppo restituisce tutti i gruppi figli
|
|
3470
|
+
*
|
|
3471
|
+
* @param {string} group Gruppo che rappresenta il padre di cui cercare i figli
|
|
3472
|
+
* @param {'selected' | 'unselected'} status Stato dei gruppi, selezionati o no
|
|
3473
|
+
* @param {boolean} recursive Indica se cercare solo i gruppi direttamente collegati o se prendere anche quelli dei gruppi figli
|
|
3474
|
+
*
|
|
3475
|
+
* @returns {any[]} Oggetti di tipo **_group** facenti capo alla chiave **groupKey**
|
|
3476
|
+
*/
|
|
3477
|
+
getGroupChildGroups(sel, group, status, recursive = false, allbase = null) {
|
|
3478
|
+
let thisGroup = this.rgGroupCache.get(group._thisKey);
|
|
3479
|
+
let items = [];
|
|
3480
|
+
if (allbase)
|
|
3481
|
+
items = allbase;
|
|
3482
|
+
else {
|
|
3483
|
+
if (recursive) {
|
|
3484
|
+
// In modalità ricorsiva prendo gli oggetti di tutte le chiavi simili che trovo
|
|
3485
|
+
for (let key of this.rgChildGroupsCache.keys())
|
|
3486
|
+
if (key.startsWith(group._thisKey))
|
|
3487
|
+
items.push(...this.rgChildGroupsCache.get(key));
|
|
3488
|
+
}
|
|
3489
|
+
else
|
|
3490
|
+
items = this.rgChildGroupsCache.get(group._thisKey);
|
|
3491
|
+
}
|
|
3492
|
+
items = items.filter(t => !status || (t._selected && status == 'selected') || (!t._selected && status == 'unselected'));
|
|
3493
|
+
// Non trovo nessun oggetto, però magari di oggetti ne ho all'interno dell'oggetto di selezione
|
|
3494
|
+
if (items.length != 0 || !sel)
|
|
3495
|
+
return items;
|
|
3496
|
+
if (status == 'unselected')
|
|
3497
|
+
items = sel.group_exclusions.filter((t) => t != null && ((!recursive && t._thisRoute.length == thisGroup._thisRoute.length + 1 && t._thisRoute.startsWith(group._thisKey)) ||
|
|
3498
|
+
(recursive && t._thisKey.startsWith(group._thisKey))));
|
|
3499
|
+
else
|
|
3500
|
+
items = sel.groups.filter((t) => t != null && ((!recursive && t._thisRoute.length == thisGroup._thisRoute.length + 1 && t._thisRoute.startsWith(group._thisKey)) ||
|
|
3501
|
+
(recursive && t._thisKey.startsWith(group._thisKey))));
|
|
3502
|
+
return items;
|
|
2342
3503
|
}
|
|
2343
3504
|
/**
|
|
2344
3505
|
* Finalizza le informazioni di selezione del **ItemsSelection** corrente
|
|
2345
3506
|
*/
|
|
2346
3507
|
finalizeSelectionInformations(selectionItem) {
|
|
3508
|
+
// Dato che le delete sono logiche dato che tengo la cache degli indici devo renderle fisiche
|
|
3509
|
+
let tmpGrp = [], tmpItems = [], tmpExcl = [], tmpGrpExcl = [];
|
|
3510
|
+
let grpRemoved = false, itemsRemoved = false, exclRemoved = false, grpExclRemoved = false;
|
|
3511
|
+
for (let i = 0; i < selectionItem.items.length; i++)
|
|
3512
|
+
if (selectionItem.items[i] != null)
|
|
3513
|
+
tmpItems.push(selectionItem.items[i]);
|
|
3514
|
+
else
|
|
3515
|
+
itemsRemoved = true;
|
|
3516
|
+
for (let i = 0; i < selectionItem.groups.length; i++)
|
|
3517
|
+
if (selectionItem.groups[i] != null)
|
|
3518
|
+
tmpGrp.push(selectionItem.groups[i]);
|
|
3519
|
+
else
|
|
3520
|
+
grpRemoved = true;
|
|
3521
|
+
for (let i = 0; i < selectionItem.exclusions.length; i++)
|
|
3522
|
+
if (selectionItem.exclusions[i] != null)
|
|
3523
|
+
tmpExcl.push(selectionItem.exclusions[i]);
|
|
3524
|
+
else
|
|
3525
|
+
exclRemoved = true;
|
|
3526
|
+
for (let i = 0; i < selectionItem.group_exclusions.length; i++)
|
|
3527
|
+
if (selectionItem.group_exclusions[i] != null)
|
|
3528
|
+
tmpGrpExcl.push(selectionItem.group_exclusions[i]);
|
|
3529
|
+
else
|
|
3530
|
+
grpExclRemoved = true;
|
|
3531
|
+
selectionItem.items = tmpItems;
|
|
3532
|
+
selectionItem.group_exclusions = tmpGrpExcl;
|
|
3533
|
+
selectionItem.exclusions = tmpExcl;
|
|
3534
|
+
selectionItem.groups = tmpGrp;
|
|
3535
|
+
// Le cache degli indici potrebbero avere buchi, risolvo
|
|
3536
|
+
if (grpRemoved)
|
|
3537
|
+
this.i_groupsCache = this.compactIndexMap(this.i_groupsCache);
|
|
3538
|
+
if (itemsRemoved)
|
|
3539
|
+
this.i_itemsCache = this.compactIndexMap(this.i_itemsCache);
|
|
3540
|
+
if (exclRemoved)
|
|
3541
|
+
this.i_exclusionsCache = this.compactIndexMap(this.i_exclusionsCache);
|
|
3542
|
+
if (grpExclRemoved)
|
|
3543
|
+
this.i_group_exclusionsCache = this.compactIndexMap(this.i_group_exclusionsCache);
|
|
3544
|
+
// Poi riprendo a fare tutto in normalità
|
|
2347
3545
|
selectionItem.count = this.evaluateSelected();
|
|
2348
3546
|
// Se ho fatto selezione "all" ma poi mi sono messo a togliere tutti gli elementi fino a rimanerne 0 resetto l'oggetto di selezione
|
|
2349
|
-
if (selectionItem.count == 0
|
|
3547
|
+
if (selectionItem.count == 0) {
|
|
3548
|
+
this.boundSource.forEach(t => t._selected = false);
|
|
2350
3549
|
selectionItem.all = false;
|
|
2351
3550
|
selectionItem.exclusions = [];
|
|
2352
3551
|
selectionItem.items = [];
|
|
3552
|
+
selectionItem.groups = [];
|
|
3553
|
+
selectionItem.group_exclusions = [];
|
|
2353
3554
|
// Ripulisco la cache altrimenti mi rimane piena di tutte le esclusioni
|
|
2354
|
-
this.
|
|
3555
|
+
this.clearSelectionCaches();
|
|
2355
3556
|
}
|
|
2356
3557
|
// Se la possibilità di fare "Seleziona tutto" è abilitata allora la considero appena mi viene selezionato qualcosa
|
|
2357
3558
|
this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
|
|
2358
3559
|
}
|
|
3560
|
+
/**
|
|
3561
|
+
* Compatta una cache di indici
|
|
3562
|
+
*/
|
|
3563
|
+
compactIndexMap(map) {
|
|
3564
|
+
let index = 0;
|
|
3565
|
+
let ret = new Map();
|
|
3566
|
+
for (let key of map.keys())
|
|
3567
|
+
ret.set(key, index++);
|
|
3568
|
+
return ret;
|
|
3569
|
+
}
|
|
2359
3570
|
/**
|
|
2360
3571
|
* Gestisce i click sulla tabella, gestendo eventualmente anche gli Shift + Click per selezionare un range di oggetti
|
|
2361
3572
|
*
|
|
@@ -2374,7 +3585,7 @@ class EsTableComponent {
|
|
|
2374
3585
|
let selecteditems = [];
|
|
2375
3586
|
if (event.shiftKey && this.ShiftClick && !this.SingleSelection) {
|
|
2376
3587
|
let startSelecting = false;
|
|
2377
|
-
let items = this.boundSource.filter(t => !t.
|
|
3588
|
+
let items = this.boundSource.filter(t => !t._group && !t._sep);
|
|
2378
3589
|
for (let i = 0; i < items.length; i++) {
|
|
2379
3590
|
let t = items[i];
|
|
2380
3591
|
if (startSelecting) {
|
|
@@ -2407,8 +3618,10 @@ class EsTableComponent {
|
|
|
2407
3618
|
*/
|
|
2408
3619
|
evaluateSelected() {
|
|
2409
3620
|
var _a;
|
|
2410
|
-
let
|
|
2411
|
-
|
|
3621
|
+
let si = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
|
|
3622
|
+
let excByGroup = si.group_exclusions.reduce((prev, curr) => prev + curr.count, 0);
|
|
3623
|
+
let incByGroup = si.groups.reduce((prev, curr) => prev + curr.count, 0);
|
|
3624
|
+
this.selectedObjects = (si.all ? this.BaseItemsCount : incByGroup) - excByGroup + si.items.length - si.exclusions.length;
|
|
2412
3625
|
return this.selectedObjects;
|
|
2413
3626
|
}
|
|
2414
3627
|
/**
|
|
@@ -2416,9 +3629,11 @@ class EsTableComponent {
|
|
|
2416
3629
|
*/
|
|
2417
3630
|
selectAllOrResetSelection() {
|
|
2418
3631
|
let selectionItem = this.View.selection || this.arraymodeSelection;
|
|
2419
|
-
this.
|
|
3632
|
+
this.clearSelectionCaches();
|
|
2420
3633
|
selectionItem.all = !selectionItem.all;
|
|
2421
3634
|
selectionItem.exclusions = [];
|
|
3635
|
+
selectionItem.groups = [];
|
|
3636
|
+
selectionItem.group_exclusions = [];
|
|
2422
3637
|
selectionItem.items = [];
|
|
2423
3638
|
// Ripulisco gli stati UI di selezione globale se l'ho disattivata
|
|
2424
3639
|
if (!selectionItem.all) {
|
|
@@ -2428,7 +3643,7 @@ class EsTableComponent {
|
|
|
2428
3643
|
this.finalizeSelectionInformations(selectionItem);
|
|
2429
3644
|
this.onSelectionChanged.emit(selectionItem);
|
|
2430
3645
|
// Dopo aver resettato direttamente il solo oggetto this.View.selection devo anche riallineare a tutti gli oggetti bindati
|
|
2431
|
-
this.evaluateSelection(this.
|
|
3646
|
+
this.evaluateSelection(this.boundSource, selectionItem);
|
|
2432
3647
|
}
|
|
2433
3648
|
// #endregion
|
|
2434
3649
|
// #region Gestione Paginazione
|
|
@@ -2438,9 +3653,9 @@ class EsTableComponent {
|
|
|
2438
3653
|
* @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
|
|
2439
3654
|
*/
|
|
2440
3655
|
addToPage(page) {
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
this.goToPage((this.SearchView ||
|
|
3656
|
+
var _a;
|
|
3657
|
+
let view = this.MainGroupView ? this.MainGroupView : this.View;
|
|
3658
|
+
this.goToPage((((_a = (this.SearchView || view)) === null || _a === void 0 ? void 0 : _a.page) || 0) + page);
|
|
2444
3659
|
}
|
|
2445
3660
|
/**
|
|
2446
3661
|
* Sposta la ricerca alla pagina specificata
|
|
@@ -2448,21 +3663,35 @@ class EsTableComponent {
|
|
|
2448
3663
|
* @param {number} page Pagina a cui navigare
|
|
2449
3664
|
*/
|
|
2450
3665
|
goToPage(page) {
|
|
2451
|
-
|
|
3666
|
+
let view = this.MainGroupView ? this.MainGroupView : this.View;
|
|
3667
|
+
if (!view.page || !view.pages)
|
|
2452
3668
|
return;
|
|
2453
|
-
let appSearchElement = this.SearchView ||
|
|
3669
|
+
let appSearchElement = this.SearchView || view;
|
|
2454
3670
|
if (page === 0 || page > appSearchElement.pages)
|
|
2455
3671
|
return;
|
|
2456
3672
|
appSearchElement.page = page;
|
|
2457
3673
|
this.arrayPulsanti = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
|
|
2458
|
-
this.
|
|
3674
|
+
let hasGroupings = !!this.MainGroupView;
|
|
3675
|
+
this.emitSearchRequest(false, hasGroupings ? view : null);
|
|
2459
3676
|
}
|
|
2460
3677
|
/**
|
|
2461
3678
|
* Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest**
|
|
2462
3679
|
* per comunicare al componente che utilizza questa tabella che i dati sono da aggiornare
|
|
2463
3680
|
*/
|
|
2464
|
-
onItemsPerPageChanged() {
|
|
2465
|
-
this.
|
|
3681
|
+
onItemsPerPageChanged(newIpp) {
|
|
3682
|
+
this.PagerOptions.View.itemsperpageoverride = newIpp;
|
|
3683
|
+
this.changed();
|
|
3684
|
+
if (this.MainGroupView)
|
|
3685
|
+
this.emitSearchRequest(true, this.MainGroupView);
|
|
3686
|
+
else
|
|
3687
|
+
this.emitSearchRequest(true);
|
|
3688
|
+
}
|
|
3689
|
+
/**
|
|
3690
|
+
* Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest** con la vista del separatore
|
|
3691
|
+
*/
|
|
3692
|
+
onGroupItemsPerPageChanged(pager, newIpp) {
|
|
3693
|
+
pager.view.itemsperpageoverride = newIpp;
|
|
3694
|
+
this.emitSearchRequest(true, pager.view);
|
|
2466
3695
|
}
|
|
2467
3696
|
// #endregion
|
|
2468
3697
|
// #region Gestione Export
|
|
@@ -2609,12 +3838,12 @@ class EsTableComponent {
|
|
|
2609
3838
|
* @returns {any} Router link generato in base al parametri
|
|
2610
3839
|
*/
|
|
2611
3840
|
generateRouterLink(path, parameterProps, item) {
|
|
2612
|
-
if (this.DynamicTableRouterLinkCache[item.
|
|
2613
|
-
return this.DynamicTableRouterLinkCache[item.
|
|
3841
|
+
if (this.DynamicTableRouterLinkCache[item._hash + path]) {
|
|
3842
|
+
return this.DynamicTableRouterLinkCache[item._hash + path];
|
|
2614
3843
|
}
|
|
2615
3844
|
else {
|
|
2616
3845
|
let link = this.getRouterLink(path, parameterProps, item);
|
|
2617
|
-
this.DynamicTableRouterLinkCache[item.
|
|
3846
|
+
this.DynamicTableRouterLinkCache[item._hash + path] = link;
|
|
2618
3847
|
return link;
|
|
2619
3848
|
}
|
|
2620
3849
|
}
|
|
@@ -2797,11 +4026,13 @@ class EsTableComponent {
|
|
|
2797
4026
|
for (let i = 0; i < items.length; i++) {
|
|
2798
4027
|
let item = items[i];
|
|
2799
4028
|
// Prima di calcolare l'hash rimuovo le proprietà interne prima che mi scompensino i calcoli successivi
|
|
2800
|
-
|
|
2801
|
-
delete
|
|
2802
|
-
|
|
4029
|
+
let tmp = Object.assign({}, items[i]);
|
|
4030
|
+
delete tmp._selected;
|
|
4031
|
+
delete tmp._visible;
|
|
4032
|
+
delete tmp._hash;
|
|
4033
|
+
let hash = this.hashExts.hashObject(tmp);
|
|
2803
4034
|
usedHashesCache[hash] = usedHashesCache[hash] ? usedHashesCache[hash] + 1 : 1;
|
|
2804
|
-
item.
|
|
4035
|
+
item._hash = hash + (usedHashesCache[hash] > 1 ? "_" + usedHashesCache[hash] : "");
|
|
2805
4036
|
}
|
|
2806
4037
|
}
|
|
2807
4038
|
/**
|
|
@@ -2829,13 +4060,15 @@ EsTableComponent.decorators = [
|
|
|
2829
4060
|
viewProviders: [{ provide: LocalizationService, useClass: EsTableLoc }],
|
|
2830
4061
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
2831
4062
|
encapsulation: ViewEncapsulation.None,
|
|
2832
|
-
template: "<!-- Patacchino di autoaggiornamento -->\r\n<div class=\"w-100\" *ngIf=\"AutoUpdate\">\r\n <div class=\"pull-right\">\r\n {{'Update every' | localize : lc}} <input [readonly]=\"autoUpdate\" maxlength=\"3\" class=\"form-control est-custom-input\" type=\"text\" [(ngModel)]=\"seconds\" /> {{'second/s' | localize : lc}}\r\n </div>\r\n <div class=\"pull-right m-t-2\">\r\n <label class=\"est-switch\">\r\n <input type=\"checkbox\" [(ngModel)]=\"autoUpdate\" (ngModelChange)=\"autoUpdateChanged();\" />\r\n <div class=\"est-slider round\"></div>\r\n </label>\r\n </div>\r\n</div>\r\n\r\n<!--\r\nI TH sono contenuto statico, questo significa che senza condizione per RowTHs arriverebbero sia qui sia nell ng-container dell'header in fase non inizializzata, duplicando fisicamente le colonne.\r\nPer ovviare al problema, questo pezzo lo faccio apparire solo se ci sono gi\u00E0 dei RowTHs, quindi su valorizzazione della View succeder\u00E0:\r\n1) appaiono i th nell' ng-container dell'header, e NON qui\r\n2) i TH vengono presi, elaborati e trasformati in RowTHs\r\n3) l'ng-container dell'header sparisce (per la condizione !UseCustomCells || !RowTHs) e qui appaiono i nuovi TH (che poi sono gli stessi di prima che girano)\r\n4) Vengono presi i nuovi TH da qui e trasformati a loro volta in RowTHs\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && RowTHs\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Qui invece ci sono tutti i TH-->\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<!--\r\nQuesta parte \u00E8 un po' pi\u00F9 semplice del sopra. Infatti i TD vengono s\u00EC bindati in entrambi i punti (qui e nell'ng-container del body), ma avr\u00F2 le TD statiche prima di generare la TMPBoundSource.\r\nQuesto significa che il workflow di binding sar\u00E0:\r\n1) Appaiono i TD statici nel body e NON qui, perch\u00E9 i TMPBoundSource non sono ancora stati emessi\r\n2) Contemporaneamente all'emissione dei TMPBoundSource vengono anche emessi i RowTds\r\n3) Considerando il punto 2, al giro dopo appariranno i TD qui, perch\u00E9 \u00E8 stata generata la TMPBoundSource, e spariranno contemporaneamente dall'ng-container del body (per la condizione !UseCustomCells || !RowTDs)\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && bodyRef\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Tutti i TD che dopo verranno presi ed elaborati internamente-->\r\n <ng-container *ngFor=\"let item of TMPBoundSource\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-container *ngIf=\"View\">\r\n <div *ngIf=\"FirstBind && ShowLoadingOnBootstrap\" class=\"est-loading-box\">\r\n <div class=\"est-loading-content\">\r\n <span class=\"fa fa-spinner fa-spin\"></span> {{'Performing Table bootstrap' | localize: lc}}...\r\n </div>\r\n </div>\r\n\r\n <div class=\"table-responsive datatable {{Class}}\" [class.est-scrollable]=\"UseEndlessscroll\" (scroll)=\"UseEndlessscroll && onScroll($event)\" [style.max-height.px]=\"MaxHeight\">\r\n <table class=\"{{ TableClass }}\" [class.est-high-density]=\"HighCellDensity\">\r\n <thead [hidden]=\"HeaderHidden || FirstBind\">\r\n\r\n <!-- Aggiungo il pezzo che gestisce la selezione di tutto se attivo da config -->\r\n <tr *ngIf=\"SelectAll\">\r\n <th [attr.colspan]=\"allColumns\" [class.est-hidden]=\"!canSelectAll && !(View?.selection || arraymodeSelection).all\">\r\n <span>{{ (selectedObjects || 0).toString() + ' ' + ((selectedObjects == 1 ? 'Object Selected' : 'Objects Selected') | localize : lc) }}</span> \r\n <span class=\"app-link app-inline\" (click)=\"selectAllOrResetSelection()\">{{ (View?.selection || arraymodeSelection).all ? ('Reset Selection' | localize : lc) : ('Select Everything' | localize : lc)}}</span>\r\n </th>\r\n </tr>\r\n\r\n <!-- Blocco header group -->\r\n <tr *ngIf=\"HasHeaderGroup\">\r\n <ng-container *ngTemplateOutlet=\"headerGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n\r\n <!-- Blocco header group secondario -->\r\n <tr *ngIf=\"HasSecondaryHeaderGroup\">\r\n <ng-container *ngTemplateOutlet=\"secondaryHeaderGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n\r\n <!-- Blocco effettivo degli header -->\r\n <tr>\r\n <!-- Aggiungo una checkbox se la selezione \u00E8 attiva -->\r\n <th class=\"est-col-min\" *ngIf=\"Selection\">\r\n <input *ngIf=\"!SingleSelection\" class=\"est-pointer\" type=\"checkbox\" [disabled]=\"SelectionDisabled\" [(ngModel)]=\"globalCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalCheckChanged();\">\r\n </th>\r\n\r\n <!-- Header che valgono per view mode e array mode -->\r\n <ng-container *ngIf=\"(viewMode || arrayMode)\">\r\n\r\n <!-- In una tabella base prendo semplicemente i th scritti dall'utente nell'HTML -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n\r\n <!-- Se ho un modello dinamico dell'oggetto creo le colonne in base alle propriet\u00E0 -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && DynamicRowColumnsDefinition\">\r\n <ng-container *ngFor=\"let operation of DynamicOperations\">\r\n <th class=\"est-col-min est-no-side-padding\"></th>\r\n </ng-container>\r\n \r\n <ng-container *ngFor=\"let rowHeader of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowHeader.visible\">\r\n <th *ngIf=\"OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"thOrderChanged(rowHeader.propertyName, $event)\">{{rowHeader.description}}</th>\r\n <th *ngIf=\"!OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\">{{rowHeader.description}}</th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- Se non ho un modello dinamico ma invece delle celle custom, genero gli header in base ai row th -->\r\n <ng-container *ngIf=\"UseCustomCells && RowTHs\">\r\n <ng-container *ngFor=\"let rowHeader of RowTHs\">\r\n <ng-container *ngIf=\"rowHeader && rowHeader.Visible\">\r\n <th es-th=\"{{rowHeader.ID}}\" [class.est-nowrap]=\"!rowHeader.Wrap\" class=\"{{rowHeader.Class || ''}}\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"OrderByColumn && thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowHeader.Template;\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowHeader.Template\">\r\n {{rowHeader.Content}}\r\n </ng-container>\r\n </th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!--Casistica in cui ho il setup proveniente da un report. Gli header sono definiti da come \u00E8 fatto il report-->\r\n <ng-container *ngIf=\"reportMode\">\r\n <th [style.color]=\"clm.color\" *ngFor=\"let clm of ReportValues.columns\" class=\"app-no-selection app-pointer est-nowrap\" (click)=\"setupNextOrderAndSearch(clm)\">\r\n {{clm.description}}<span class=\"fa\" [class.fa-chevron-down]=\"clm.order == 'DESC'\" [class.fa-chevron-up]=\"clm.order == 'ASC'\"></span>\r\n </th>\r\n </ng-container>\r\n\r\n <!--Per l'eliminazione mi serve un header aggiuntivo-->\r\n <th *ngIf=\"Removal\" [class.app-right-10]=\"Export || HiddenColumns\" class=\"est-col-min app-sticky-last-column\"><span class=\"fa fa-trash\"></span></th>\r\n\r\n <!--Per l'esportazione mi serve l'header extra da cui faccio uscire i 3 pallocchi-->\r\n <th *ngIf=\"Export || HiddenColumns || ColumnsOrdering || CornerMenuOptions\" class=\"app-table-dotted-menu app-sticky-last-column est-col-min text-sm-center\">\r\n \r\n <!-- Link nascosto che serve a scaricare il file -->\r\n <a *ngIf=\"headers\" hidden #exportDownloader csvLink [data]=\"data\" [headers]=\"headers\" [delimiter]=\"';'\" [filename]=\"ExportFileName\"></a>\r\n\r\n <!-- Blocco con i 3 pallocchi che tira fuori il context menu delle operazioni -->\r\n <div class=\"btn-group\" container=\"body\" placement=\"bottom right\" dropdown #dropdown=\"bs-dropdown\" [autoClose]=\"true\">\r\n <span dropdownToggle class=\"fa fa-ellipsis-v app-fs-18 app-pointer app-padding-3\"></span>\r\n\r\n <div *dropdownMenu class=\"dropdown-menu dropdown-menu-right app-bring-to-front-strong\">\r\n <div class=\"est-pointer\">\r\n <a class=\"dropdown-item\" *ngIf=\"(HiddenColumns || ColumnsOrdering)\" (click)=\"resetColumnVisSelection(); changeColumnVisibilityModal.show();\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && CSVExport\" (click)=\"tryExport('CSV')\">{{'Export View' | localize : lc}} (CSV)</a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && XLSXExport\" (click)=\"tryExport('XLSX')\">{{'Export View' | localize : lc}} (XLSX)</a>\r\n <a class=\"dropdown-item\" *ngFor=\"let option of CornerMenuOptions\" (click)=\"cornerActionClicked(option.id)\">{{option.description}}</a>\r\n </div>\r\n </div>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n \r\n <!-- Valido per modalit\u00E0 View o Array. Se sono in report mode il body \u00E8 creato in altro modo -->\r\n <tbody [hidden]=\"BodyHidden || FirstBind\" *ngIf=\"(arrayMode || viewMode)\">\r\n <!--Con selection attiva richiamo il template che gestisce il context menu-->\r\n <ng-container *ngIf=\"Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBodySelection; context: { $implicit: { selDisabled: arrayMode ? false : SelectionDisabled, sel: Selection }}\"></ng-container>\r\n </ng-container>\r\n\r\n <!--Senza selection richiamo il template che NON gestisce il context menu-->\r\n <ng-container *ngIf=\"!Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBody\"></ng-container>\r\n </ng-container>\r\n </tbody>\r\n\r\n <!-- Per la modalit\u00E0 a report c'\u00E8 un body particolare semi-dinamico -->\r\n <tbody [hidden]=\"BodyHidden\" *ngIf=\"reportMode\">\r\n <tr *ngFor=\"let row of ReportValues.rows; let even = even;\">\r\n <td class=\"est-nowrap\" *ngFor=\"let val of row.values\">{{val}}</td>\r\n <td class=\"app-sticky-last-column{{even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <ng-container *ngIf=\"ShowPaging && !FirstBind\">\r\n\r\n <!-- Paginatore dove appare la count e le opzioni di paginazione -->\r\n <div class=\"pull-left m-t-min-3\">\r\n <ng-container *ngIf=\"viewMode\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount || (View && View.objectcount && View.objectcount != -1), ShowPaging: !HidePaging, View: View, UsesView: true }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && (!UseArrayModePaging || SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount || (View && View.length) || (SearchView && SearchView.objectcount && SearchView.objectcount != -1), ShowPaging: !HidePaging && SearchView, View: SearchView, SecondaryView: View, UsesView: true }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && (UseArrayModePaging && !SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount, ShowPaging: !HidePaging && View.length > 10, View: View, UsesView: false }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"reportMode\">\r\n <ng-container *ngTemplateOutlet=\"pagerSelector; context: { $implicit: { ShowCount: !HidePagingCount || (View && View.objectcount && View.objectcount != -1), ShowPaging: View.pagingavailable, MightBeNoPaging: true, View: View, Report: ReportValues, UsesView: true }}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n \r\n <!-- Pulsanti avanti-indietro di paginazione -->\r\n <div class=\"pull-right btn-toolbar\" *ngIf=\"ShowPaging && !HidePagingButtons\">\r\n <ng-container *ngIf=\"(!reportMode || View?.pagingavailable) && (!arrayMode || SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: addToPage.bind(this), GTP: goToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && UseArrayModePaging && !SearchView\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: arrayAddToPage.bind(this), GTP: arrayGoToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <div class=\"clearfix\"></div>\r\n </ng-container>\r\n</ng-container>\r\n\r\n<!-- Template che contiene i pulsanti per cambiare pagina -->\r\n<ng-template #pagingButtons let-options>\r\n <a class=\"btn app-white-button app-no-margin\" (click)=\"options.ATP(-1)\"><span class=\"fa fa-chevron-left\"></span></a>\r\n <div *ngIf=\"options.Array\" class=\"app-inline\">\r\n <a *ngFor=\"let p of options.Array\" class=\"btn {{p.cssClass}} app-no-margin\" (click)=\"options.GTP(p.val)\">{{p.val}}</a>\r\n </div>\r\n <a class=\"btn app-white-button app-no-margin\" (click)=\"options.ATP(1)\"><span class=\"fa fa-chevron-right\"></span></a>\r\n</ng-template>\r\n\r\n<!-- Template che mostra le informazioni base di paginazione: conteggio oggetti, paginazione attuale e pulsanti per cambiarla -->\r\n<ng-template #pagerSelector let-options>\r\n <div *ngIf=\"options.ShowCount\">\r\n {{ CountLabel }}: \r\n <strong *ngIf=\"options.UsesView && !options.Report\">\r\n {{ options.View?.objectcount ? options.View.objectcount : options.SecondaryView && options.SecondaryView.length ? options.SecondaryView.length : \"0\" }}\r\n </strong>\r\n <strong *ngIf=\"!options.UsesView && !options.Report\">\r\n {{ options.View.length ? options.View.length : \"0\" }}\r\n </strong>\r\n <strong *ngIf=\"options.Report\">\r\n {{ options.Report.count && options.Report.count == -1 ? options.Report.rows.length : options.Report.count && options.Report.count > 0 ? options.Report.count : 0 }}\r\n </strong>\r\n </div>\r\n <div *ngIf=\"options.ShowPaging\">\r\n <app-paging *ngIf=\"!options.UsesView\" [Hidden]=\"!options.View || options.View.length == 0\" [WarnOnAll]=\"false\" [CurrentPageSize]=\"ArraymodeItemsPerPage\" (pagingSelected)=\"refreshPaging($event)\"></app-paging>\r\n <app-paging *ngIf=\"options.UsesView\" [AllSearch]=\"AllSearch\" [DefaultAll]=\"defaultAllPageOverride\" [View]=\"options.View\" (pagingSelected)=\"options.View.itemsperpageoverride = $event; changed(); onItemsPerPageChanged();\"></app-paging>\r\n </div>\r\n <div *ngIf=\"options.MightBeNoPaging && !options.ShowPaging\">\r\n <em>{{'Paging options are not available for this report' | localize: lc}}</em>\r\n </div>\r\n</ng-template>\r\n\r\n<!-- Questi due template rappresentano effettivamente il body della tabella. essendo il tr l'unica cosa che davvero cambia, il resto \u00E8 templatizzato -->\r\n<ng-template #TBodySelection let-templateOptions>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even; let i=index;\">\r\n <tr *ngIf=\"item.visible || !Hierarchy\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\" \r\n [class.est-pointer]=\"!item.locked\" \r\n [class.est-white-selected]=\"item._selected && !item.locked\"\r\n [class.est-rg]=\"item._group\"\r\n [contextMenu]=\"!item.locked ? (ContextMenu || emptyMenu) : emptyMenu\" [contextMenuSubject]=\"item\"\r\n (click)=\"(!item.locked && !item._group && !item._sep && handleClick($event, item)) || item._group && handleGroupClick(item)\">\r\n \r\n <td *ngIf=\"!item.locked && !item._group && !item._sep;\"><input type=\"checkbox\" [disabled]=\"templateOptions.selDisabled\" [class.est-pointer]=\"!item.locked\" [(ngModel)]=\"item._selected\" name=\"check{{i}}\"></td>\r\n <td *ngIf=\"item.locked || item._group || item._sep\"></td>\r\n\r\n <ng-container *ngIf=\"item._sep\">\r\n <td [attr.colspan]=\"allColumns\" class=\"est-rg-sep est-l-{{item._grouplevel}}\">\r\n <div class=\"est-rg-ipp\"> \r\n <span class=\"est-rg-ipp-sel\">10</span> | \r\n <span class=\"est-rg-ipp-sel\">15</span> | \r\n <span class=\"est-rg-ipp-sel\">30</span> | \r\n <span class=\"est-rg-ipp-sel\">45</span> | \r\n <span class=\"est-rg-ipp-sel\">100</span> | \r\n <span class=\"est-rg-ipp-sel-all\">{{'All' | localize: lc}}</span>\r\n </div>\r\n <div class=\"est-rg-page\">\r\n <span class=\"est-rg-page-prev\"><</span>\r\n <span class=\"est-rg-page-sel\">1</span>\r\n <span class=\"est-rg-page-sel\">2</span>\r\n <span class=\"est-rg-page-sel\">3</span>\r\n <span class=\"est-rg-page-sel\">4</span>\r\n <span class=\"est-rg-page-sel\">5</span>\r\n <span class=\"est-rg-page-next\">></span>\r\n </div>\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!item._sep\">\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n </ng-container>\r\n </tr>\r\n </ng-container>\r\n</ng-template> \r\n\r\n<ng-template #TBody>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even;\">\r\n <tr *ngIf=\"item.visible || !Hierarchy\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\"\r\n [class.est-rg]=\"item._group\"\r\n (click)=\"item._group && handleGroupClick(item)\">\r\n\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n\r\n </tr>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle semplici, con header e body scritti a manazza -->\r\n<ng-template #basicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle definite in maniera dinamica dal modello -->\r\n<ng-template #dynamicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && DynamicRowColumnsDefinition\">\r\n <ng-container *ngFor=\"let operation of DynamicOperations; let first = first; let last = last;\">\r\n <ng-container *ngIf=\"!operation.conditionField || (item.properties[operation.conditionField] == operation.conditionValue)\">\r\n <td [class.est-no-right-padding]=\"last\" [class.est-no-left-padding]=\"!first\" class=\"est-col-min\"><span title=\"{{operation.title}}\" class=\"{{operation.iconClass}} app-pointer\" (click)=\"dynamicOperation(item, operation.id)\">{{operation.text}}</span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"operation.conditionField && (item.properties[operation.conditionField] != operation.conditionValue)\">\r\n <td class=\"est-col-min est-no-side-padding\"></td>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let rowItem of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowItem.routePath && rowItem.visible\">\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\" [Internal]=\"false\" [Context]=\"item.hash\">\r\n <a [routerLink]=\"generateRouterLink(rowItem.routePath, rowItem.routeParameterProperties, item)\" class=\"app-link\" [innerHTML]=\"item.properties[rowItem.propertyName]\"></a>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowItem.routePath && rowItem.visible\">\r\n <ng-container *ngTemplateOutlet=\"findEsTd(rowItem.propertyName) || defaultEsTd; context: { $implicit: item.properties[rowItem.propertyName], rowItem : rowItem, item : item }\"> </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEsTd let-value let-rowItem='rowItem' let-item='item'>\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\"\r\n [class.app-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + rowItem.propertyName + '$') != -1\"\r\n (click)=\"cellClicked(rowItem.propertyName, item) && !CellActionPropagates && $event.stopPropagation()\"\r\n [Internal]=\"false\" [Context]=\"item.hash\">\r\n {{value}}\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale delle celle custom se configurate -->\r\n<ng-template #customCells let-item>\r\n <ng-container *ngIf=\"UseCustomCells && RowTDs\">\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item.hash]; let i = index\">\r\n <ng-container *ngIf=\"rowItem\">\r\n\r\n <!-- Casistica senza bodyRef, quindi con direttive per i td -->\r\n <ng-container *ngIf=\"!bodyRef && rowItem.Visible\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" \r\n [class.est-rg-hdr]=\"rowItem.GroupHeader\"\r\n [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\"\r\n [Internal]=\"true\">\r\n\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <span *ngIf=\"!rowItem.Template\">{{rowItem.Content}}</span>\r\n\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <a [routerLink]='rowItem.RouterLink' class=\"app-link\" [innerHTML]=\"rowItem.Content\"></a>\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (NON RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"!rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [class.app-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + $any(rowItem).ID + '$') != -1\" (click)=\"cellClicked(rowItem.ID, item) && !CellActionPropagates && $event.stopPropagation()\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <span *ngIf=\"!rowItem.Template\" [innerHTML]=\"rowItem.Content\"></span>\r\n </td>\r\n </ng-container>\r\n\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #HierarchyNavigator let-item>\r\n <span *ngIf=\"!item.parent\" class=\"fa fa-chevron-down\" style=\"visibility:hidden\"></span>\r\n <span *ngIf=\"item.parent && item.expanded\" class=\"fa fa-chevron-down est-pointer app-no-selection\" (click)=\"collapseParent(item[this.OwnKey])\"></span>\r\n <span *ngIf=\"item.parent && !item.expanded\" class=\"fa fa-chevron-up est-pointer app-no-selection\" (click)=\"expandParent(item[this.OwnKey])\"></span>\r\n \r\n</ng-template>\r\n\r\n<!-- Questo template contiene i pulsanti di eliminazione/undo eliminazione ed esportazione che vanno in fondo ad un record edlla tabella -->\r\n<ng-template #bodyDeleteAndExport let-options>\r\n <ng-container *ngIf=\"Removal && !RemovalCondition\">\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted)\"><span class=\"fa fa-remove app-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted)\"><span class=\"fa fa-undo text-warning app-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"Removal && RemovalCondition\">\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-remove app-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-undo text-warning app-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n <td class=\"app-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!options.item[RemovalCondition]\"><span class=\"fa fa-remove app-hidden-view\"></span></td>\r\n </ng-container>\r\n <td *ngIf=\"Export || HiddenColumns || CornerMenuOptions\" class=\"app-sticky-last-column{{options.even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n</ng-template>\r\n\r\n<!-- Context menu vuoto default per tutte le tabella che non ce l'hanno, in modo che al click destro appaia \"nessuna op disponibile\" -->\r\n<context-menu #emptyMenu>\r\n <ng-template contextMenuItem>\r\n <span>\r\n <em>{{'No operations available' | localize : lc}}...</em>\r\n </span>\r\n </ng-template>\r\n</context-menu>\r\n\r\n<!-- Modal per cambiare posizione e visibilit\u00E0 delle colonne dell'es-table -->\r\n<div bsModal #changeColumnVisibilityModal=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\r\n <div class=\"modal-dialog modal-lg\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title pull-left\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </h5>\r\n <button type=\"button\" class=\"close pull-right\" (click)=\"changeColumnVisibilityModal.hide();\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">×</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div *ngIf=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"card card-info app-padding-10 app-margin-bottom-0\">\r\n {{'There are no columns configured to be hidden/shown in this view' | localize : lc}}\r\n </div>\r\n <div *ngIf=\"TMPColumnsList && TMPColumnsList.length > 0\" style=\"max-height:500px; overflow-y:auto\">\r\n <!--Aaaaaaah la tristezza... qui mi servirebbe l'es-table per facilitare la selezione multipla ecc... peccato che se la linko qui entro in un loop impressionante-->\r\n <table class=\"table table-striped table-sm app-margin-bottom-0\">\r\n <thead>\r\n <tr>\r\n <th class=\"est-col-min\" *ngIf=\"HiddenColumns\">\r\n <input class=\"est-pointer\" type=\"checkbox\" [(ngModel)]=\"globalColVisCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalColVisCheckChanged();\">\r\n </th>\r\n <th class=\"est-col-min\" *ngIf=\"ColumnsOrdering\"></th>\r\n <th class=\"est-col-min est-nowrap\">{{'Column Name' | localize : lc}}</th>\r\n <!--Filler-->\r\n <th></th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let item of TMPColumnsList; let i = index; let last = last\" class=\"est-pointer\" [class.est-white-selected]=\"lastSelectedItemID == item.id\" [class.est-no-selection]=\"!item.visible\" (click)=\"columnClicked(item);\">\r\n <td *ngIf=\"HiddenColumns\">\r\n <input type=\"checkbox\" [class.est-hidden-view]=\"item.fixed\" class=\"est-pointer\" [(ngModel)]=\"item.visible\" name=\"visible{{i}}\" (ngModelChange)=\"updateGlobalColVisCheck();\" />\r\n </td>\r\n <td class=\"est-nowrap\" *ngIf=\"ColumnsOrdering\">\r\n <span class=\"fa fa-arrow-up\" [class.est-hidden-view]=\"item.fixed\" (click)=\"lastSelectedItemID = item.id; i != 0 && !item.fixed && sendUp(item); $event.stopPropagation();\"></span>\r\n <span class=\"fa fa-arrow-down\" [class.est-hidden-view]=\"item.fixed\" (click)=\"lastSelectedItemID = item.id; !last && !item.fixed && sendDown(item); $event.stopPropagation();\"></span>\r\n </td>\r\n <td class=\"est-nowrap\">\r\n <ng-container *ngIf=\"item.template\">\r\n <ng-container *ngTemplateOutlet=\"item.template\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.template\">{{item.description}}</ng-container>\r\n </td>\r\n <!--Filler-->\r\n <td></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary app-margin-right-10\" (click)=\"lastSelectedItemID = null; changeColumnVisibilityModal.hide();\">{{'Close' | localize : lc}}</button>\r\n <button type=\"button\" [disabled]=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"btn btn-primary\" (click)=\"confirmColumnVisibilitySelection() && changeColumnVisibilityModal.hide()\">{{'Confirm' | localize : lc}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>",
|
|
2833
|
-
styles: [".est-loading-box{height:200px;text-align:center;position:relative;background:#ccc}.est-loading-content{margin:0;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:35px}.est-scrollable{max-height:600px;overflow:auto}.est-pointer{cursor:pointer}.est-high-density td,.est-high-density th{padding:0 .2rem}.est-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.est-hidden-view{visibility:hidden}.est-nowrap{white-space:nowrap}.est-white-selected{background-color:#ddd!important}.est-line-through{text-decoration:line-through}.est-no-side-padding{padding-left:0;padding-right:0}.est-no-left-padding,.est-no-right-padding{padding-left:0}.est-col-min{width:1px}.est-switch{position:relative;display:inline-block;width:30px;height:17px;margin-bottom:0;margin-right:5px;margin-left:5px}.est-switch input{display:none}.est-slider{cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc}.est-slider,.est-slider:before{position:absolute;transition:.4s}.est-slider:before{content:\"\";height:13px;width:13px;left:3px;bottom:2px;background-color:#fff}input:checked+.est-slider{background-color:#2196f3}input:focus+.est-slider{box-shadow:0 0 1px #2196f3}input:checked+.est-slider:before{transform:translateX(11px)}.est-slider.round{border-radius:10px}.est-slider.round:before{border-radius:50%}.est-custom-input{width:30px;display:inline;padding:1px;height:20px}.est-row-lvl-1 td:first-child{padding-left:5px}.est-row-lvl-2 td:first-child{padding-left:20px}.est-row-lvl-3 td:first-child{padding-left:35px}.est-row-lvl-4 td:first-child{padding-left:50px}.est-row-lvl-5 td:first-child{padding-left:65px}.est-row-lvl-6 td:first-child{padding-left:80px}.est-row-lvl-7 td:first-child{padding-left:95px}.est-row-lvl-8 td:first-child{padding-left:110px}.est-row-lvl-9 td:first-child{padding-left:125px}.est-row-lvl-10 td:first-child{padding-left:140px}.est-row-lvl-11 td:first-child{padding-left:155px}.est-row-lvl-12 td:first-child{padding-left:170px}.est-row-lvl-13 td:first-child{padding-left:185px}.est-row-lvl-14 td:first-child{padding-left:200px}.est-row-lvl-15 td:first-child{padding-left:215px}.est-row-lvl-16 td:first-child{padding-left:230px}.est-row-lvl-17 td:first-child{padding-left:245px}.est-row-lvl-18 td:first-child{padding-left:260px}.est-row-lvl-19 td:first-child{padding-left:275px}.est-row-lvl-20 td:first-child{padding-left:290px}.est-row-lvl-21 td:first-child{padding-left:305px}.est-row-lvl-22 td:first-child{padding-left:320px}.est-row-lvl-23 td:first-child{padding-left:335px}.est-row-lvl-24 td:first-child{padding-left:350px}.est-row-lvl-25 td:first-child{padding-left:365px}.est-row-lvl-26 td:first-child{padding-left:380px}.est-row-lvl-27 td:first-child{padding-left:395px}.est-row-lvl-28 td:first-child{padding-left:410px}.est-row-lvl-29 td:first-child{padding-left:425px}.est-row-lvl-30 td:first-child{padding-left:440px}.est-row-lvl-31 td:first-child{padding-left:455px}.est-row-lvl-32 td:first-child{padding-left:470px}.est-row-lvl-33 td:first-child{padding-left:485px}.est-row-lvl-34 td:first-child{padding-left:500px}.est-row-lvl-35 td:first-child{padding-left:515px}.est-row-lvl-36 td:first-child{padding-left:530px}.est-row-lvl-37 td:first-child{padding-left:545px}.est-row-lvl-38 td:first-child{padding-left:560px}.est-row-lvl-39 td:first-child{padding-left:575px}.est-row-lvl-40 td:first-child{padding-left:590px}.est-row-lvl-41 td:first-child{padding-left:605px}.est-row-lvl-42 td:first-child{padding-left:620px}.est-row-lvl-43 td:first-child{padding-left:635px}.est-row-lvl-44 td:first-child{padding-left:650px}.est-row-lvl-45 td:first-child{padding-left:665px}.est-row-lvl-46 td:first-child{padding-left:680px}.est-row-lvl-47 td:first-child{padding-left:695px}.est-row-lvl-48 td:first-child{padding-left:710px}.est-row-lvl-49 td:first-child{padding-left:725px}.est-row-lvl-50 td:first-child{padding-left:740px}.est-row-lvl-51 td:first-child{padding-left:755px}.est-row-lvl-52 td:first-child{padding-left:770px}.est-row-lvl-53 td:first-child{padding-left:785px}.est-row-lvl-54 td:first-child{padding-left:800px}.est-row-lvl-55 td:first-child{padding-left:815px}.est-row-lvl-56 td:first-child{padding-left:830px}.est-row-lvl-57 td:first-child{padding-left:845px}.est-row-lvl-58 td:first-child{padding-left:860px}.est-row-lvl-59 td:first-child{padding-left:875px}.est-row-lvl-60 td:first-child{padding-left:890px}.est-row-lvl-61 td:first-child{padding-left:905px}.est-row-lvl-62 td:first-child{padding-left:920px}.est-row-lvl-63 td:first-child{padding-left:935px}.est-row-lvl-64 td:first-child{padding-left:950px}.est-row-lvl-65 td:first-child{padding-left:965px}.est-row-lvl-66 td:first-child{padding-left:980px}.est-row-lvl-67 td:first-child{padding-left:995px}.est-row-lvl-68 td:first-child{padding-left:1010px}.est-row-lvl-69 td:first-child{padding-left:1025px}.est-row-lvl-70 td:first-child{padding-left:1040px}.est-row-lvl-71 td:first-child{padding-left:1055px}.est-row-lvl-72 td:first-child{padding-left:1070px}.est-row-lvl-73 td:first-child{padding-left:1085px}.est-row-lvl-74 td:first-child{padding-left:1100px}.est-row-lvl-75 td:first-child{padding-left:1115px}.est-row-lvl-76 td:first-child{padding-left:1130px}.est-row-lvl-77 td:first-child{padding-left:1145px}.est-row-lvl-78 td:first-child{padding-left:1160px}.est-row-lvl-79 td:first-child{padding-left:1175px}.est-row-lvl-80 td:first-child{padding-left:1190px}.est-row-lvl-81 td:first-child{padding-left:1205px}.est-row-lvl-82 td:first-child{padding-left:1220px}.est-row-lvl-83 td:first-child{padding-left:1235px}.est-row-lvl-84 td:first-child{padding-left:1250px}.est-row-lvl-85 td:first-child{padding-left:1265px}.est-row-lvl-86 td:first-child{padding-left:1280px}.est-row-lvl-87 td:first-child{padding-left:1295px}.est-row-lvl-88 td:first-child{padding-left:1310px}.est-row-lvl-89 td:first-child{padding-left:1325px}.est-row-lvl-90 td:first-child{padding-left:1340px}.est-row-lvl-91 td:first-child{padding-left:1355px}.est-row-lvl-92 td:first-child{padding-left:1370px}.est-row-lvl-93 td:first-child{padding-left:1385px}.est-row-lvl-94 td:first-child{padding-left:1400px}.est-row-lvl-95 td:first-child{padding-left:1415px}.est-row-lvl-96 td:first-child{padding-left:1430px}.est-row-lvl-97 td:first-child{padding-left:1445px}.est-row-lvl-98 td:first-child{padding-left:1460px}.est-row-lvl-99 td:first-child{padding-left:1475px}.est-right-10{right:10px}.est-hidden{visibility:hidden}.est-
|
|
4063
|
+
template: "<!-- Patacchino di autoaggiornamento -->\r\n<div class=\"w-100\" *ngIf=\"AutoUpdate\">\r\n <div class=\"pull-right\">\r\n {{'Update every' | localize : lc}} <input [readonly]=\"autoUpdate\" maxlength=\"3\" class=\"form-control est-custom-input\" type=\"text\" [(ngModel)]=\"seconds\" /> {{'second/s' | localize : lc}}\r\n </div>\r\n <div class=\"pull-right m-t-2\">\r\n <label class=\"est-switch\">\r\n <input type=\"checkbox\" [(ngModel)]=\"autoUpdate\" (ngModelChange)=\"autoUpdateChanged();\" />\r\n <div class=\"est-slider round\"></div>\r\n </label>\r\n </div>\r\n</div>\r\n\r\n<!--\r\nI TH sono contenuto statico, questo significa che senza condizione per RowTHs arriverebbero sia qui sia nell ng-container dell'header in fase non inizializzata, duplicando fisicamente le colonne.\r\nPer ovviare al problema, questo pezzo lo faccio apparire solo se ci sono gi\u00E0 dei RowTHs, quindi su valorizzazione della View succeder\u00E0:\r\n1) appaiono i th nell' ng-container dell'header, e NON qui\r\n2) i TH vengono presi, elaborati e trasformati in RowTHs\r\n3) l'ng-container dell'header sparisce (per la condizione !UseCustomCells || !RowTHs) e qui appaiono i nuovi TH (che poi sono gli stessi di prima che girano)\r\n4) Vengono presi i nuovi TH da qui e trasformati a loro volta in RowTHs\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && RowTHs\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Qui invece ci sono tutti i TH-->\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<!--\r\nQuesta parte \u00E8 un po' pi\u00F9 semplice del sopra. Infatti i TD vengono s\u00EC bindati in entrambi i punti (qui e nell'ng-container del body), ma avr\u00F2 le TD statiche prima di generare la TMPBoundSource.\r\nQuesto significa che il workflow di binding sar\u00E0:\r\n1) Appaiono i TD statici nel body e NON qui, perch\u00E9 i TMPBoundSource non sono ancora stati emessi\r\n2) Contemporaneamente all'emissione dei TMPBoundSource vengono anche emessi i RowTds\r\n3) Considerando il punto 2, al giro dopo appariranno i TD qui, perch\u00E9 \u00E8 stata generata la TMPBoundSource, e spariranno contemporaneamente dall'ng-container del body (per la condizione !UseCustomCells || !RowTDs)\r\n-->\r\n<div hidden *ngIf=\"UseCustomCells && bodyRef\">\r\n <ng-container *ngIf=\"View\">\r\n <!--Tutti i TD che dopo verranno presi ed elaborati internamente-->\r\n <ng-container *ngFor=\"let item of TMPBoundSource\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</div>\r\n\r\n<ng-container *ngIf=\"View\">\r\n <div *ngIf=\"FirstBind && ShowLoadingOnBootstrap\" class=\"est-loading-box\">\r\n <div class=\"est-loading-content\">\r\n <span class=\"fa fa-spinner fa-spin\"></span> {{'Performing Table bootstrap' | localize: lc}}...\r\n </div>\r\n </div>\r\n\r\n <div *ngIf=\"PagingStyle == 'both' || PagingStyle == 'top'\">\r\n <ng-container *ngTemplateOutlet=\"pagingElement\"></ng-container>\r\n </div>\r\n\r\n <div class=\"table-responsive datatable {{ContainerClass}}\" [class.est-scrollable]=\"UseEndlessscroll\" (scroll)=\"UseEndlessscroll && onScroll($event)\" [style.max-height.px]=\"MaxHeight\">\r\n <table class=\"{{ TableClass }} est-margin-bottom-10\" [class.est-high-density]=\"HighCellDensity\">\r\n <thead [hidden]=\"HeaderHidden || FirstBind\">\r\n <!-- Aggiungo il pezzo che gestisce la selezione di tutto se attivo da config -->\r\n <tr *ngIf=\"SelectAll\">\r\n <th class=\"est-no-selection\" [attr.colspan]=\"Columns.Global\" [class.est-hidden]=\"!canSelectAll && !(View?.selection || arraymodeSelection).all\">\r\n <span>{{ ((selectedObjects || 0) | number : '0.0-0' : locale) + ' ' + ((selectedObjects == 1 ? 'Object Selected' : 'Objects Selected') | localize : lc) }}</span> \r\n <span class=\"est-link est-inline\" (click)=\"selectAllOrResetSelection()\">{{ (View?.selection || arraymodeSelection).all ? ('Reset Selection' | localize : lc) : ('Select Everything' | localize : lc)}}</span>\r\n </th>\r\n </tr>\r\n\r\n <!-- Blocco header group -->\r\n <ng-container *ngIf=\"RowThGroups\">\r\n <tr *ngFor=\"let level of RowThGroups\">\r\n <th *ngFor=\"let cell of level\" [attr.colspan]=\"cell.Span\" \r\n [class.est-pinned-header]=\"cell.Pinned\" [class.est-col-min]=\"cell.Pinned\"\r\n [class.est-ltab-border]=\"cell.Borders\" [class.est-rtab-border]=\"cell.Borders\"\r\n class=\"est-text-center\">\r\n <ng-container *ngIf=\"cell.Pinned; Else: cell.Template\">\r\n <div class=\"est-pinned-border est-cell-group-padding\"></div>\r\n </ng-container>\r\n </th>\r\n </tr>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!RowThGroups\">\r\n <tr *ngIf=\"headerGroupRef\">\r\n <ng-container *ngTemplateOutlet=\"headerGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n \r\n <!-- Blocco header group secondario -->\r\n <tr *ngIf=\"secondaryHeaderGroupRef\">\r\n <ng-container *ngTemplateOutlet=\"secondaryHeaderGroupRef\"></ng-container>\r\n <th *ngIf=\"Export\"></th>\r\n </tr>\r\n </ng-container>\r\n\r\n <!-- Blocco effettivo degli header -->\r\n <tr>\r\n <!-- Aggiungo una checkbox se la selezione \u00E8 attiva -->\r\n <th class=\"est-col-min\" *ngIf=\"Selection && !HasPinnedColumns\">\r\n <input *ngIf=\"!SingleSelection\" class=\"est-pointer\" type=\"checkbox\" [disabled]=\"SelectionDisabled\" [(ngModel)]=\"globalCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalCheckChanged();\">\r\n </th>\r\n\r\n <!-- Header che valgono per view mode e array mode -->\r\n <ng-container *ngIf=\"(viewMode || arrayMode)\">\r\n\r\n <!-- In una tabella base prendo semplicemente i th scritti dall'utente nell'HTML -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"headerRef\"></ng-container>\r\n </ng-container>\r\n\r\n <!-- Se ho un modello dinamico dell'oggetto creo le colonne in base alle propriet\u00E0 -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs) && DynamicRowColumnsDefinition\">\r\n <th *ngFor=\"let operation of DynamicOperations\" class=\"est-col-min est-no-side-padding\"></th>\r\n \r\n <ng-container *ngFor=\"let rowHeader of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowHeader.visible\">\r\n <th *ngIf=\"OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"thOrderChanged(rowHeader.propertyName, $event)\">{{rowHeader.description}}</th>\r\n <th *ngIf=\"!OrderByColumn\" es-th=\"{{rowHeader.propertyName}}\" class=\"{{UserDefinedDynamicCols ? ((rowHeader.clss || '') + (rowHeader.headerWraps ? '' : ' est-nowrap')) : ' est-nowrap'}}\" [Order]=\"rowHeader.dataOrder\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.orderable\" [OrderBy]=\"OrderByColumn\">{{rowHeader.description}}</th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- Se non ho un modello dinamico ma invece delle celle custom, genero gli header in base ai row th -->\r\n <ng-container *ngIf=\"UseCustomCells && RowTHs\">\r\n <th *ngIf=\"HasPinnedColumns\" class=\"est-pinned-header est-col-min\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border\">\r\n <th class=\"est-col-min est-no-border\" *ngIf=\"Selection\">\r\n <input *ngIf=\"!SingleSelection\" class=\"est-pointer\" type=\"checkbox\" [disabled]=\"SelectionDisabled\" [(ngModel)]=\"globalCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalCheckChanged();\">\r\n </th>\r\n <ng-container *ngFor=\"let rowHeader of RowTHs\">\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && rowHeader.Pinned\" [style.width.px]=\"rowHeader.PinnedWidth\" es-th=\"{{rowHeader.ID}}\" [class.est-no-border]=\"true\" [class.est-nowrap]=\"!rowHeader.Wrap\" class=\"{{rowHeader.Class || ''}}\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"OrderByColumn && thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template;\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowHeader.Template\">{{rowHeader.Content}}</span>\r\n </th>\r\n </ng-container>\r\n </div>\r\n </th>\r\n <ng-container *ngFor=\"let rowHeader of RowTHs\">\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && !rowHeader.Pinned\" es-th=\"{{rowHeader.ID}}\" [class.est-ltab-border]=\"rowHeader.LeftBorder\" [class.est-rtab-border]=\"rowHeader.RightBorder\" [class.est-nowrap]=\"!rowHeader.Wrap\" class=\"{{rowHeader.Class || ''}}\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"OrderByColumn && thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template;\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowHeader.Template\">{{rowHeader.Content}}</span>\r\n </th>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!--Casistica in cui ho il setup proveniente da un report. Gli header sono definiti da come \u00E8 fatto il report-->\r\n <ng-container *ngIf=\"reportMode\">\r\n <th [style.color]=\"clm.color\" *ngFor=\"let clm of ReportValues.columns\" class=\"est-no-selection est-pointer est-nowrap\" (click)=\"setupNextOrderAndSearch(clm)\">\r\n {{clm.description}}<span class=\"fa\" [class.fa-chevron-down]=\"clm.order == 'DESC'\" [class.fa-chevron-up]=\"clm.order == 'ASC'\"></span>\r\n </th>\r\n </ng-container>\r\n\r\n <!--Per l'eliminazione mi serve un header aggiuntivo-->\r\n <th *ngIf=\"Removal\" [class.est-right-10]=\"Export || HiddenColumns\" class=\"est-col-min est-sticky-last-column\"><span class=\"fa fa-trash\"></span></th>\r\n\r\n <!--Per l'esportazione mi serve l'header extra da cui faccio uscire i 3 pallocchi-->\r\n <th *ngIf=\"Export || HiddenColumns || ColumnsOrdering || CornerMenuOptions\" class=\"est-table-dotted-menu est-sticky-last-column est-col-min text-sm-center\">\r\n \r\n <!-- Link nascosto che serve a scaricare il file -->\r\n <a *ngIf=\"headers\" hidden #exportDownloader csvLink [data]=\"data\" [headers]=\"headers\" [delimiter]=\"';'\" [filename]=\"ExportFileName\"></a>\r\n\r\n <!-- Blocco con i 3 pallocchi che tira fuori il context menu delle operazioni -->\r\n <div class=\"btn-group\" container=\"body\" placement=\"bottom right\" dropdown #dropdown=\"bs-dropdown\" [autoClose]=\"true\">\r\n <span dropdownToggle class=\"fa fa-ellipsis-v est-fs-18 est-pointer est-padding-3\"></span>\r\n\r\n <div *dropdownMenu class=\"dropdown-menu dropdown-menu-right est-bring-to-front-strong\">\r\n <div class=\"est-pointer\">\r\n <a class=\"dropdown-item\" *ngIf=\"HiddenColumns || ColumnsOrdering\" (click)=\"resetColumnVisSelection(); changeColumnVisibilityModal.show();\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && CSVExport\" (click)=\"tryExport('CSV')\">{{'Export View' | localize : lc}} (CSV)</a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && XLSXExport\" (click)=\"tryExport('XLSX')\">{{'Export View' | localize : lc}} (XLSX)</a>\r\n <a class=\"dropdown-item\" *ngFor=\"let option of CornerMenuOptions\" (click)=\"cornerActionClicked(option.id)\">{{option.description}}</a>\r\n </div>\r\n </div>\r\n </div>\r\n </th>\r\n </tr>\r\n </thead>\r\n \r\n <!-- Valido per modalit\u00E0 View o Array. Se sono in report mode il body \u00E8 creato in altro modo -->\r\n <tbody [hidden]=\"BodyHidden || FirstBind\" *ngIf=\"(arrayMode || viewMode)\">\r\n <!--Con selection attiva richiamo il template che gestisce il context menu-->\r\n <ng-container *ngIf=\"Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBodySelection; context: { $implicit: { selDisabled: arrayMode ? false : SelectionDisabled, sel: Selection }}\"></ng-container>\r\n </ng-container>\r\n\r\n <!--Senza selection richiamo il template che NON gestisce il context menu-->\r\n <ng-container *ngIf=\"!Selection\">\r\n <ng-container *ngTemplateOutlet=\"TBody\"></ng-container>\r\n </ng-container>\r\n </tbody>\r\n\r\n <!-- Per la modalit\u00E0 a report c'\u00E8 un body particolare semi-dinamico -->\r\n <tbody [hidden]=\"BodyHidden\" *ngIf=\"reportMode\">\r\n <tr *ngFor=\"let row of ReportValues.rows; let even = even;\">\r\n <td class=\"est-nowrap\" *ngFor=\"let val of row.values\">{{val}}</td>\r\n <td class=\"est-sticky-last-column{{even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n\r\n <div *ngIf=\"PagingStyle == 'both' || PagingStyle == 'bottom'\">\r\n <ng-container *ngTemplateOutlet=\"pagingElement\"></ng-container>\r\n </div>\r\n</ng-container>\r\n\r\n<!-- Template che contiene tutte le info di paginazione in modo da poterlo replicare anche sopra -->\r\n<ng-template #pagingElement>\r\n <ng-container *ngIf=\"!FirstBind\">\r\n <!-- Pulsanti avanti-indietro di paginazione -->\r\n <div *ngIf=\"PagerOptions.ShowPaging && !HidePagingButtons\" class=\"pull-right btn-toolbar\">\r\n <ng-container *ngIf=\"(!reportMode || View?.pagingavailable) && (!arrayMode || SearchView)\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: addToPage.bind(this), GTP: goToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"arrayMode && UseArrayModePaging && !SearchView\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { ATP: arrayAddToPage.bind(this), GTP: arrayGoToPage.bind(this), Array: arrayPulsanti }}\"></ng-container>\r\n </ng-container>\r\n </div>\r\n <!-- Paginatore dove appare la count e le opzioni di paginazione -->\r\n <div class=\"pull-right m-t-min-3 est-margin-right-50\">\r\n <div *ngIf=\"PagerOptions.ShowPaging && (PagerOptions.PagerCount > 10 || reportMode && View.pagingavailable)\">\r\n <app-paging *ngIf=\"!PagerOptions.UsesView\" [ShowCount]=\"PagerOptions.ShowCount\" [PagerCount]=\"PagerOptions.PagerCount\" [WarnOnAll]=\"false\" [CurrentPageSize]=\"ArraymodeItemsPerPage\" (pagingSelected)=\"refreshPaging($event)\"></app-paging>\r\n <app-paging *ngIf=\"PagerOptions.UsesView\" [ShowCount]=\"PagerOptions.ShowCount\" [PagerCount]=\"PagerOptions.PagerCount\" [GroupMode]=\"PagerOptions.Searches == 'groups'\" [AllSearch]=\"AllSearch\" [View]=\"PagerOptions.View\" (pagingSelected)=\"onItemsPerPageChanged($event);\"></app-paging>\r\n </div>\r\n <div *ngIf=\"reportMode && !PagerOptions.ShowPaging\"><em>{{'Paging options are not available for this report' | localize: lc}}</em></div>\r\n </div>\r\n <div class=\"clearfix\"></div>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Template che contiene i pulsanti per cambiare pagina -->\r\n<ng-template #pagingButtons let-options>\r\n <a class=\"btn\" class=\"est-page-prev app-pointer\" (click)=\"options.ATP(-1, options.separator)\">\r\n <span class=\"fa fa-chevron-left\"></span>\r\n </a>\r\n <div *ngIf=\"options.Array\" class=\"est-inline\">\r\n <a *ngFor=\"let p of options.Array\" class=\"est-page-sel\" class=\"btn {{p.cssClass}}\"\r\n (click)=\"options.GTP(p.val, options.separator)\">{{p.val}}</a>\r\n </div>\r\n <a class=\"btn\" class=\"est-page-next app-pointer\" (click)=\"options.ATP(1, options.separator)\">\r\n <span class=\"fa fa-chevron-right\"></span>\r\n </a>\r\n</ng-template>\r\n\r\n<!-- Questi due template rappresentano effettivamente il body della tabella. essendo il tr l'unica cosa che davvero cambia, il resto \u00E8 templatizzato -->\r\n<ng-template #TBodySelection let-templateOptions>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even; let i=index;\">\r\n <tr *ngIf=\"item._visible || (!Hierarchy && !ArrayGrouping)\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\" \r\n [class.est-pointer]=\"!item.locked\" \r\n [class.est-white-selected]=\"item._selected && !item.locked\"\r\n [class.est-rg]=\"item._group\"\r\n [class.est-rg-sep]=\"item._sep\"\r\n [contextMenu]=\"!item.locked ? (ContextMenu || emptyMenu) : emptyMenu\" [contextMenuSubject]=\"item\"\r\n (click)=\"(!item.locked && !item._sep && !item._group && handleClick($event, item)) || item._group && handleGroupClick(item)\">\r\n\r\n <td *ngIf=\"!item.locked && !item._sep && !HasPinnedColumns\">\r\n <input type=\"checkbox\" \r\n [disabled]=\"templateOptions.selDisabled\" \r\n [class.est-pointer]=\"!item.locked\"\r\n [(ngModel)]=\"item._selected\" name=\"check{{i}}\" \r\n (click)=\"$event.stopPropagation(); handleClick($event, item);\">\r\n </td>\r\n <td *ngIf=\"(item.locked || item._sep) && !HasPinnedColumns\"></td>\r\n\r\n <ng-container *ngIf=\"item._sep\"><ng-container *ngTemplateOutlet=\"groupPager; context: { $implicit: item }\"></ng-container> </ng-container>\r\n\r\n <ng-container *ngIf=\"!item._sep\">\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item, templateOptions: templateOptions }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n </tr>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #TBody>\r\n <ng-container *ngFor=\"let item of boundSource; let even = even;\">\r\n <tr *ngIf=\"item._visible || !Hierarchy\" \r\n [class]=\"item._rowClass ? item._rowClass : ''\" \r\n [class.est-line-through]=\"item.removed || item.deleted\"\r\n [class.est-rg]=\"item._group\"\r\n [class.est-rg-sep]=\"item._sep\"\r\n (click)=\"item._group && handleGroupClick(item)\">\r\n\r\n <ng-container *ngIf=\"item._sep\"><ng-container *ngTemplateOutlet=\"groupPager; context: { $implicit: item }\"></ng-container></ng-container>\r\n\r\n <ng-container *ngIf=\"!item._sep\">\r\n <ng-container *ngTemplateOutlet=\"basicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"dynamicColumns; context: { $implicit: item }\"></ng-container>\r\n <ng-container *ngTemplateOutlet=\"customCells; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngTemplateOutlet=\"bodyDeleteAndExport; context: { $implicit: { even: even, item: item }}\"></ng-container>\r\n </tr>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #groupPager let-item>\r\n <td *ngIf=\"HasPinnedColumns\"></td>\r\n <td *ngIf=\"item._grouplevel > 1\" [attr.colspan]=\"item._grouplevel-1\"></td>\r\n <td [attr.colspan]=\"Columns.VisibleUnpinned - (item._grouplevel > 0 ? item._grouplevel - 1 : 0)\">\r\n <div class=\"est-rg-sep-flex-right\" *ngIf=\"RowGroupingPagingStyle == 'right'\">\r\n <div class=\"est-rg-page\"><ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { separator: item, ATP: addToPageGroup.bind(this), GTP: goToPageGroup.bind(this), Array: item.buttons }}\"></ng-container></div>\r\n <div class=\"est-rg-ipp\"><app-paging [AllSearch]=\"AllSearch\" [GroupMode]=\"item.searches == 'groups'\" [PagerCount]=\"item.searches == 'groups' ? item.view.groupcount : item.view.objectcount\" [View]=\"item.view\" (pagingSelected)=\"onGroupItemsPerPageChanged(item, $event);\"></app-paging></div>\r\n </div>\r\n\r\n <div class=\"est-rg-sep-flex-left\" *ngIf=\"RowGroupingPagingStyle == 'left'\">\r\n <div class=\"est-rg-ipp\"><app-paging [AllSearch]=\"AllSearch\" [GroupMode]=\"item.searches == 'groups'\" [PagerCount]=\"item.searches == 'groups' ? item.view.groupcount : item.view.objectcount\" [View]=\"item.view\" (pagingSelected)=\"onGroupItemsPerPageChanged(item, $event);\"></app-paging></div>\r\n <div class=\"est-rg-page\"><ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { separator: item, ATP: addToPageGroup.bind(this), GTP: goToPageGroup.bind(this), Array: item.buttons }}\"></ng-container></div>\r\n </div>\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle semplici, con header e body scritti a manazza -->\r\n<ng-template #basicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale su tabelle definite in maniera dinamica dal modello -->\r\n<ng-template #dynamicColumns let-item>\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTDs) && DynamicRowColumnsDefinition\">\r\n <ng-container *ngFor=\"let operation of DynamicOperations; let first = first; let last = last;\">\r\n <ng-container *ngIf=\"!operation.conditionField || (item.properties[operation.conditionField] == operation.conditionValue)\">\r\n <td [class.est-no-right-padding]=\"last\" [class.est-no-left-padding]=\"!first\" class=\"est-col-min\"><span title=\"{{operation.title}}\" class=\"{{operation.iconClass}} est-pointer\" (click)=\"dynamicOperation(item, operation.id)\">{{operation.text}}</span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"operation.conditionField && (item.properties[operation.conditionField] != operation.conditionValue)\">\r\n <td class=\"est-col-min est-no-side-padding\"></td>\r\n </ng-container>\r\n </ng-container>\r\n <ng-container *ngFor=\"let rowItem of DynamicRowColumnsDefinition\">\r\n <ng-container *ngIf=\"rowItem.routePath && rowItem.visible\">\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\" [Internal]=\"false\" [Context]=\"item._hash\">\r\n <a [routerLink]=\"generateRouterLink(rowItem.routePath, rowItem.routeParameterProperties, item)\" class=\"est-link\" [innerHTML]=\"item.properties[rowItem.propertyName]\"></a>\r\n </td>\r\n </ng-container>\r\n <ng-container *ngIf=\"!rowItem.routePath && rowItem.visible\">\r\n <ng-container *ngTemplateOutlet=\"findEsTd(rowItem.propertyName) || defaultEsTd; context: { $implicit: item.properties[rowItem.propertyName], rowItem : rowItem, item : item }\"> </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEsTd let-value let-rowItem='rowItem' let-item='item'>\r\n <td es-td=\"{{rowItem.propertyName}}\" class=\"{{UserDefinedDynamicCols ? rowItem.clss : 'est-nowrap'}}\"\r\n [class.est-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + rowItem.propertyName + '$') != -1\"\r\n (click)=\"cellClicked(rowItem.propertyName, item) && !CellActionPropagates && $event.stopPropagation()\"\r\n [Internal]=\"false\" [Context]=\"item._hash\">\r\n {{value}}\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Questo template contiene la print condizionale delle celle custom se configurate -->\r\n<ng-template #customCells let-item let-opt=\"templateOptions\">\r\n <ng-container *ngIf=\"UseCustomCells && RowTDs\">\r\n\r\n <td *ngIf=\"HasPinnedColumns\" class=\"est-pinned-body est-col-min\" [class.est-white-selected]=\"item._selected\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border\">\r\n <td *ngIf=\"!item.locked && !item._sep && Selection\" class=\"est-no-border est-col-min\">\r\n <input type=\"checkbox\" [disabled]=\"opt.selDisabled\" [class.est-pointer]=\"!item.locked\" [(ngModel)]=\"item._selected\" name=\"check{{item._hash}}\" (click)=\"$event.stopPropagation(); handleClick($event, item);\">\r\n </td>\r\n <td class=\"est-no-border est-col-min\" *ngIf=\"(item.locked || item._sep) && Selection\"></td>\r\n\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item._hash]; let i = index\">\r\n <td *ngIf=\"rowItem && rowItem.Pinned\" [style.width.px]=\"rowItem.PinnedWidth\" es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-no-border]=\"true\" [class.est-rg-hdr]=\"rowItem.GroupHeader\" [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\"><ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowItem.Template\">{{rowItem.Content}}</span>\r\n </td>\r\n </ng-container>\r\n </div>\r\n </td>\r\n\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item._hash]; let i = index\">\r\n <ng-container *ngIf=\"rowItem && !rowItem.Pinned\">\r\n\r\n <!-- Casistica senza bodyRef, quindi con direttive per i td -->\r\n <ng-container *ngIf=\"!bodyRef && rowItem.Visible\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-ltab-border]=\"rowItem.LeftBorder\" [class.est-rtab-border]=\"rowItem.RightBorder\" [class.est-rg-hdr]=\"rowItem.GroupHeader\" [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\"><ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container></ng-container>\r\n <span *ngIf=\"!rowItem.Template\">{{rowItem.Content}}</span>\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <a [routerLink]='rowItem.RouterLink' class=\"est-link\" [innerHTML]=\"rowItem.Content\"></a>\r\n </td>\r\n </ng-container>\r\n\r\n <!-- Casistica bodyRef, quindi con componenti per i td (NON RouterLink) DEPRECATO -->\r\n <ng-container *ngIf=\"!rowItem.RouterLink && rowItem.Visible && bodyRef\">\r\n <td es-td=\"{{rowItem.ID}}\" class=\"{{rowItem.Class}}\" [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [class.est-pointer]=\"UseCustomCellActions && CustomCellActionsOn.indexOf('$' + $any(rowItem).ID + '$') != -1\" (click)=\"cellClicked(rowItem.ID, item) && !CellActionPropagates && $event.stopPropagation()\" [Internal]=\"true\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\">\r\n <ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"rowItem.Template\">\r\n <ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container>\r\n </ng-container>\r\n <span *ngIf=\"!rowItem.Template\" [innerHTML]=\"rowItem.Content\"></span>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #HierarchyNavigator let-item>\r\n <span *ngIf=\"!item.parent\" class=\"fa fa-chevron-down\" style=\"visibility:hidden\"></span>\r\n <span *ngIf=\"item.parent && item._expanded\" class=\"fa fa-chevron-down est-pointer est-no-selection\" (click)=\"collapseParent(item[this.OwnKey])\"></span>\r\n <span *ngIf=\"item.parent && !item._expanded\" class=\"fa fa-chevron-up est-pointer est-no-selection\" (click)=\"expandParent(item[this.OwnKey])\"></span>\r\n \r\n</ng-template>\r\n\r\n<!-- Questo template contiene i pulsanti di eliminazione/undo eliminazione ed esportazione che vanno in fondo ad un record edlla tabella -->\r\n<ng-template #bodyDeleteAndExport let-options>\r\n <ng-container *ngIf=\"Removal && !RemovalCondition\">\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted)\"><span class=\"fa fa-remove est-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted)\"><span class=\"fa fa-undo text-warning est-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n </ng-container>\r\n <ng-container *ngIf=\"Removal && RemovalCondition\">\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-remove est-pointer text-danger\" [hidden]=\"options.item.removable != undefined && !options.item.removable\" (click)=\"onRemoval.emit(options.item)\"></span></td>\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"(options.item.removed || options.item.deleted) && options.item[RemovalCondition]\"><span class=\"fa fa-undo text-warning est-pointer\" (click)=\"onAbortRemoval.emit(options.item)\"></span></td>\r\n <td class=\"est-sticky-last-column{{options.even? '-alt' : ''}} {{Export || HiddenColumns || CornerMenuOptions ? 'est-right-10' : ''}}\" *ngIf=\"!options.item[RemovalCondition]\"><span class=\"fa fa-remove est-hidden-view\"></span></td>\r\n </ng-container>\r\n <td *ngIf=\"Export || HiddenColumns || CornerMenuOptions\" class=\"est-sticky-last-column{{options.even && !Hierarchy ? '-alt' : ''}}\"></td>\r\n</ng-template>\r\n\r\n<!-- Context menu vuoto default per tutte le tabella che non ce l'hanno, in modo che al click destro appaia \"nessuna op disponibile\" -->\r\n<context-menu #emptyMenu>\r\n <ng-template contextMenuItem>\r\n <span>\r\n <em>{{'No operations available' | localize : lc}}...</em>\r\n </span>\r\n </ng-template>\r\n</context-menu>\r\n\r\n<!-- Modal per cambiare posizione e visibilit\u00E0 delle colonne dell'es-table -->\r\n<div bsModal #changeColumnVisibilityModal=\"bs-modal\" class=\"modal fade\" role=\"dialog\" aria-hidden=\"true\">\r\n <div class=\"modal-dialog modal-lg\">\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header\">\r\n <h5 class=\"modal-title pull-left\">\r\n <ng-container *ngIf=\"!HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Order' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && !ColumnsOrdering\">\r\n {{'Columns Visibility' | localize : lc}}\r\n </ng-container>\r\n <ng-container *ngIf=\"HiddenColumns && ColumnsOrdering\">\r\n {{'Columns Visibility and Order' | localize : lc}}\r\n </ng-container>\r\n </h5>\r\n <button type=\"button\" class=\"close pull-right\" (click)=\"changeColumnVisibilityModal.hide();\" aria-label=\"Close\">\r\n <span aria-hidden=\"true\">×</span>\r\n </button>\r\n </div>\r\n <div class=\"modal-body\">\r\n <div *ngIf=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"card card-info est-padding-10 est-margin-bottom-0\">\r\n {{'There are no columns configured to be hidden/shown in this view' | localize : lc}}\r\n </div>\r\n <div *ngIf=\"TMPColumnsList && TMPColumnsList.length > 0\" style=\"max-height:500px; overflow-y:auto\">\r\n <!--Aaaaaaah la tristezza... qui mi servirebbe l'es-table per facilitare la selezione multipla ecc... peccato che se la linko qui entro in un loop impressionante-->\r\n <table class=\"table table-striped table-sm est-margin-bottom-0\">\r\n <thead>\r\n <tr>\r\n <th class=\"est-col-min\" *ngIf=\"HiddenColumns\">\r\n <input class=\"est-pointer\" type=\"checkbox\" [(ngModel)]=\"globalColVisCheck\" [ngModelOptions]=\"{'standalone': true}\" (ngModelChange)=\"globalColVisCheckChanged();\">\r\n </th>\r\n <th class=\"est-col-min\" *ngIf=\"ColumnsOrdering\"></th>\r\n <th class=\"est-col-min est-nowrap\">{{'Column Name' | localize : lc}}</th>\r\n <!--Filler-->\r\n <th></th>\r\n <!-- Pinner -->\r\n <th class=\"est-col-min\"></th>\r\n </tr>\r\n </thead>\r\n <tbody>\r\n <tr *ngFor=\"let item of TMPColumnsList; let i = index; let last = last\" class=\"est-pointer\" [class.est-white-selected]=\"lastSelectedItemID == item.id\" [class.est-no-selection]=\"!item.visible\">\r\n <td *ngIf=\"HiddenColumns\">\r\n <input type=\"checkbox\" [class.est-hidden-view]=\"item.fixed\" class=\"est-pointer\" [(ngModel)]=\"item.visible\" name=\"visible{{i}}\" (ngModelChange)=\"updateGlobalColVisCheck();\" />\r\n </td>\r\n <td class=\"est-nowrap\" *ngIf=\"ColumnsOrdering\">\r\n <span class=\"fa fa-arrow-up\" [class.est-hidden-view]=\"item.fixed || item.pinned\" (click)=\"lastSelectedItemID = item.id; i != 0 && !item.fixed && sendUp(item); $event.stopPropagation();\"></span>\r\n <span class=\"fa fa-arrow-down\" [class.est-hidden-view]=\"item.fixed || item.pinned\" (click)=\"lastSelectedItemID = item.id; !last && !item.fixed && sendDown(item); $event.stopPropagation();\"></span>\r\n </td>\r\n <td class=\"est-nowrap\" (click)=\"columnClicked(item);\">\r\n <ng-container *ngIf=\"item.template\">\r\n <ng-container *ngTemplateOutlet=\"item.template\"></ng-container>\r\n </ng-container>\r\n <ng-container *ngIf=\"!item.template\">{{item.description}}</ng-container>\r\n </td>\r\n <!--Filler-->\r\n <td (click)=\"columnClicked(item);\"></td>\r\n <!-- Pinner -->\r\n <td><span *ngIf=\"!item.fixed\" class=\"fa fa-thumb-tack\" [class.text-success]=\"item.pinned\" (click)=\"pinOrUnpinColumn(item)\"></span></td>\r\n </tr>\r\n </tbody>\r\n </table>\r\n </div>\r\n </div>\r\n <div class=\"modal-footer\">\r\n <button type=\"button\" class=\"btn btn-secondary est-margin-right-10\" (click)=\"lastSelectedItemID = null; changeColumnVisibilityModal.hide();\">{{'Close' | localize : lc}}</button>\r\n <button type=\"button\" [disabled]=\"!TMPColumnsList || TMPColumnsList.length == 0\" class=\"btn btn-primary\" (click)=\"confirmColumnVisibilitySelection() && changeColumnVisibilityModal.hide()\">{{'Confirm' | localize : lc}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>",
|
|
4064
|
+
styles: [".est-loading-box{height:200px;text-align:center;position:relative;background:#ccc}.est-loading-content{margin:0;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:35px}.est-scrollable{max-height:600px;overflow:auto}.est-pointer{cursor:pointer}.est-high-density td,.est-high-density th{padding:0 .2rem}.est-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.est-hidden-view{visibility:hidden}.est-no-border{border:none!important}.est-nowrap{white-space:nowrap}.est-white-selected{background-color:#ddd!important}.est-line-through{text-decoration:line-through}.est-no-side-padding{padding-left:0;padding-right:0}.est-no-left-padding,.est-no-right-padding{padding-left:0}.est-col-min{width:1px}.est-margin-bottom-0{margin-bottom:0!important}.est-margin-right-10{margin-right:10px!important}.est-right-10{right:10px!important}.est-table-dotted-menu{padding:0 0 2px!important;color:#999}.est-fs-18{font-size:18px}.est-fs-14{font-size:14px}.est-padding-3{padding:3px!important}.est-page-container{position:relative}.est-bring-to-front-strong{z-index:99999999!important}.est-switch{position:relative;display:inline-block;width:30px;height:17px;margin-bottom:0;margin-right:5px;margin-left:5px}.est-switch input{display:none}.est-slider{cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc}.est-slider,.est-slider:before{position:absolute;transition:.4s}.est-slider:before{content:\"\";height:13px;width:13px;left:3px;bottom:2px;background-color:#fff}input:checked+.est-slider{background-color:#2196f3}input:focus+.est-slider{box-shadow:0 0 1px #2196f3}input:checked+.est-slider:before{transform:translateX(11px)}.est-slider.round{border-radius:10px}.est-slider.round:before{border-radius:50%}.est-custom-input{width:30px;display:inline;padding:1px;height:20px}.est-row-lvl-1 td:first-child{padding-left:5px}.est-row-lvl-2 td:first-child{padding-left:20px}.est-row-lvl-3 td:first-child{padding-left:35px}.est-row-lvl-4 td:first-child{padding-left:50px}.est-row-lvl-5 td:first-child{padding-left:65px}.est-row-lvl-6 td:first-child{padding-left:80px}.est-row-lvl-7 td:first-child{padding-left:95px}.est-row-lvl-8 td:first-child{padding-left:110px}.est-row-lvl-9 td:first-child{padding-left:125px}.est-row-lvl-10 td:first-child{padding-left:140px}.est-row-lvl-11 td:first-child{padding-left:155px}.est-row-lvl-12 td:first-child{padding-left:170px}.est-row-lvl-13 td:first-child{padding-left:185px}.est-row-lvl-14 td:first-child{padding-left:200px}.est-row-lvl-15 td:first-child{padding-left:215px}.est-row-lvl-16 td:first-child{padding-left:230px}.est-row-lvl-17 td:first-child{padding-left:245px}.est-row-lvl-18 td:first-child{padding-left:260px}.est-row-lvl-19 td:first-child{padding-left:275px}.est-row-lvl-20 td:first-child{padding-left:290px}.est-row-lvl-21 td:first-child{padding-left:305px}.est-row-lvl-22 td:first-child{padding-left:320px}.est-row-lvl-23 td:first-child{padding-left:335px}.est-row-lvl-24 td:first-child{padding-left:350px}.est-row-lvl-25 td:first-child{padding-left:365px}.est-row-lvl-26 td:first-child{padding-left:380px}.est-row-lvl-27 td:first-child{padding-left:395px}.est-row-lvl-28 td:first-child{padding-left:410px}.est-row-lvl-29 td:first-child{padding-left:425px}.est-row-lvl-30 td:first-child{padding-left:440px}.est-row-lvl-31 td:first-child{padding-left:455px}.est-row-lvl-32 td:first-child{padding-left:470px}.est-row-lvl-33 td:first-child{padding-left:485px}.est-row-lvl-34 td:first-child{padding-left:500px}.est-row-lvl-35 td:first-child{padding-left:515px}.est-row-lvl-36 td:first-child{padding-left:530px}.est-row-lvl-37 td:first-child{padding-left:545px}.est-row-lvl-38 td:first-child{padding-left:560px}.est-row-lvl-39 td:first-child{padding-left:575px}.est-row-lvl-40 td:first-child{padding-left:590px}.est-row-lvl-41 td:first-child{padding-left:605px}.est-row-lvl-42 td:first-child{padding-left:620px}.est-row-lvl-43 td:first-child{padding-left:635px}.est-row-lvl-44 td:first-child{padding-left:650px}.est-row-lvl-45 td:first-child{padding-left:665px}.est-row-lvl-46 td:first-child{padding-left:680px}.est-row-lvl-47 td:first-child{padding-left:695px}.est-row-lvl-48 td:first-child{padding-left:710px}.est-row-lvl-49 td:first-child{padding-left:725px}.est-row-lvl-50 td:first-child{padding-left:740px}.est-row-lvl-51 td:first-child{padding-left:755px}.est-row-lvl-52 td:first-child{padding-left:770px}.est-row-lvl-53 td:first-child{padding-left:785px}.est-row-lvl-54 td:first-child{padding-left:800px}.est-row-lvl-55 td:first-child{padding-left:815px}.est-row-lvl-56 td:first-child{padding-left:830px}.est-row-lvl-57 td:first-child{padding-left:845px}.est-row-lvl-58 td:first-child{padding-left:860px}.est-row-lvl-59 td:first-child{padding-left:875px}.est-row-lvl-60 td:first-child{padding-left:890px}.est-row-lvl-61 td:first-child{padding-left:905px}.est-row-lvl-62 td:first-child{padding-left:920px}.est-row-lvl-63 td:first-child{padding-left:935px}.est-row-lvl-64 td:first-child{padding-left:950px}.est-row-lvl-65 td:first-child{padding-left:965px}.est-row-lvl-66 td:first-child{padding-left:980px}.est-row-lvl-67 td:first-child{padding-left:995px}.est-row-lvl-68 td:first-child{padding-left:1010px}.est-row-lvl-69 td:first-child{padding-left:1025px}.est-row-lvl-70 td:first-child{padding-left:1040px}.est-row-lvl-71 td:first-child{padding-left:1055px}.est-row-lvl-72 td:first-child{padding-left:1070px}.est-row-lvl-73 td:first-child{padding-left:1085px}.est-row-lvl-74 td:first-child{padding-left:1100px}.est-row-lvl-75 td:first-child{padding-left:1115px}.est-row-lvl-76 td:first-child{padding-left:1130px}.est-row-lvl-77 td:first-child{padding-left:1145px}.est-row-lvl-78 td:first-child{padding-left:1160px}.est-row-lvl-79 td:first-child{padding-left:1175px}.est-row-lvl-80 td:first-child{padding-left:1190px}.est-row-lvl-81 td:first-child{padding-left:1205px}.est-row-lvl-82 td:first-child{padding-left:1220px}.est-row-lvl-83 td:first-child{padding-left:1235px}.est-row-lvl-84 td:first-child{padding-left:1250px}.est-row-lvl-85 td:first-child{padding-left:1265px}.est-row-lvl-86 td:first-child{padding-left:1280px}.est-row-lvl-87 td:first-child{padding-left:1295px}.est-row-lvl-88 td:first-child{padding-left:1310px}.est-row-lvl-89 td:first-child{padding-left:1325px}.est-row-lvl-90 td:first-child{padding-left:1340px}.est-row-lvl-91 td:first-child{padding-left:1355px}.est-row-lvl-92 td:first-child{padding-left:1370px}.est-row-lvl-93 td:first-child{padding-left:1385px}.est-row-lvl-94 td:first-child{padding-left:1400px}.est-row-lvl-95 td:first-child{padding-left:1415px}.est-row-lvl-96 td:first-child{padding-left:1430px}.est-row-lvl-97 td:first-child{padding-left:1445px}.est-row-lvl-98 td:first-child{padding-left:1460px}.est-row-lvl-99 td:first-child{padding-left:1475px}.est-right-10{right:10px}.est-hidden{visibility:hidden}.est-padding-10{padding:10px!important}.est-margin-right-50{margin-right:50px}.est-page-sel{color:#000;margin-left:3px;margin-right:3px;padding:0 5px;font-size:inherit}.est-page-next,.est-page-prev{color:#000;font-size:inherit;padding:3px 0 0}.est-pinned-header{background-color:#fff;left:0;top:0;position:sticky;z-index:1;border-bottom:1px solid #dee2e6!important;padding:0!important}.est-pinned-border{border-right:2px solid #dee2e6!important}.est-cell-padding{padding:.3rem}.est-pinned-body{background-color:#fff;left:0;position:sticky;z-index:1;border-top:1px solid #dee2e6!important;padding:0!important}.est-inline{display:inline!important}.est-inline-block{display:inline-block!important}.est-link{color:#0275d8!important;cursor:pointer;text-decoration:none;display:block}.est-link:hover{color:#23527c!important;cursor:pointer;text-decoration:underline!important}.est-sticky-last-column{right:-1px;position:sticky;z-index:0;background-color:#fff}.est-sticky-last-column-alt{right:-1px;position:sticky;z-index:0;background-color:#f2f2f2}.est-ltab-border{border-left:2px solid #bbb}.est-rtab-border{border-right:2px solid #bbb}.est-cell-group-padding{padding:calc(.3rem + 1px);position:absolute;top:0;left:0;height:100%;width:100%}.est-margin-bottom-10{margin-bottom:10px}.est-text-center{text-align:center}.est-rg-sep-flex-right{display:flex;flex-direction:row-reverse;width:100%;margin:-5px}.est-rg-sep-flex-left{display:flex;flex-direction:row;width:100%;margin:-5px}.est-rg-hdr{font-weight:700}.est-rg-agg{font-style:italic}.est-rg{background-color:hsla(0,0%,46.7%,.4666666666666667)!important}.est-rg-sep{font-size:12px;padding-right:20px!important;background-color:hsla(0,0%,73.3%,.7333333333333333)!important}.est-rg-ipp{text-align:left;display:inline-flex;margin-right:25px}.est-rg-page{text-align:right;display:inline-flex;font-size:inherit;padding-top:5px}"]
|
|
2834
4065
|
},] }
|
|
2835
4066
|
];
|
|
2836
4067
|
EsTableComponent.ctorParameters = () => [
|
|
2837
4068
|
{ type: NgControl, decorators: [{ type: Self }, { type: Optional }] },
|
|
2838
4069
|
{ type: PreferencesService, decorators: [{ type: Optional }] },
|
|
4070
|
+
{ type: EsTableDefaultable, decorators: [{ type: Optional }, { type: Inject, args: [EST_DEFAULTS,] }] },
|
|
4071
|
+
{ type: String, decorators: [{ type: Optional }, { type: Inject, args: [EST_LOCALE,] }] },
|
|
2839
4072
|
{ type: LocalizationService },
|
|
2840
4073
|
{ type: ChangeDetectorRef },
|
|
2841
4074
|
{ type: HashingService },
|
|
@@ -2861,7 +4094,7 @@ EsTableComponent.propDecorators = {
|
|
|
2861
4094
|
CellActionPropagates: [{ type: Input }],
|
|
2862
4095
|
UseCustomCells: [{ type: Input }],
|
|
2863
4096
|
MaxHeight: [{ type: Input }],
|
|
2864
|
-
|
|
4097
|
+
ContainerClass: [{ type: Input }],
|
|
2865
4098
|
XLSXExport: [{ type: Input }],
|
|
2866
4099
|
CSVExport: [{ type: Input }],
|
|
2867
4100
|
AllSearch: [{ type: Input }],
|
|
@@ -2872,14 +4105,12 @@ EsTableComponent.propDecorators = {
|
|
|
2872
4105
|
RemovalCondition: [{ type: Input }],
|
|
2873
4106
|
Export: [{ type: Input }],
|
|
2874
4107
|
ShiftClick: [{ type: Input }],
|
|
2875
|
-
ShowPaging: [{ type: Input }],
|
|
2876
4108
|
HidePaging: [{ type: Input }],
|
|
2877
4109
|
HidePagingCount: [{ type: Input }],
|
|
2878
4110
|
HidePagingButtons: [{ type: Input }],
|
|
2879
4111
|
ContextMenu: [{ type: Input }],
|
|
2880
4112
|
ExportFileName: [{ type: Input }],
|
|
2881
4113
|
TableClass: [{ type: Input }],
|
|
2882
|
-
CountLabel: [{ type: Input }],
|
|
2883
4114
|
ExportFunction: [{ type: Input }],
|
|
2884
4115
|
HasHeaderGroup: [{ type: Input }],
|
|
2885
4116
|
HasSecondaryHeaderGroup: [{ type: Input }],
|
|
@@ -2905,9 +4136,12 @@ EsTableComponent.propDecorators = {
|
|
|
2905
4136
|
OwnKey: [{ type: Input }],
|
|
2906
4137
|
StartsExpanded: [{ type: Input }],
|
|
2907
4138
|
SavePreferences: [{ type: Input }],
|
|
4139
|
+
PagingStyle: [{ type: Input }],
|
|
4140
|
+
RowGroupingPagingStyle: [{ type: Input }],
|
|
2908
4141
|
SecondarySource: [{ type: Input }],
|
|
2909
4142
|
TertiarySource: [{ type: Input }],
|
|
2910
4143
|
UseSelectionCache: [{ type: Input }],
|
|
4144
|
+
ShowItemGroupsColumns: [{ type: Input }],
|
|
2911
4145
|
onOrderChanged: [{ type: Output }],
|
|
2912
4146
|
onSearchRequest: [{ type: Output }],
|
|
2913
4147
|
onSelectionChanged: [{ type: Output }],
|
|
@@ -2921,22 +4155,18 @@ EsTableComponent.propDecorators = {
|
|
|
2921
4155
|
ArraymodeItemsPerPage: [{ type: Input }]
|
|
2922
4156
|
};
|
|
2923
4157
|
|
|
2924
|
-
/**
|
|
2925
|
-
* Modello di configurazione per L'EsTable
|
|
2926
|
-
*/
|
|
4158
|
+
/** Modello di configurazione per L'EsTable */
|
|
2927
4159
|
class EsTableModuleConfig {
|
|
2928
4160
|
}
|
|
2929
4161
|
|
|
2930
|
-
/**
|
|
2931
|
-
* Classe di localizzazione per il componente **TablePagerComponent**
|
|
2932
|
-
*/
|
|
4162
|
+
/** Classe di localizzazione per il componente **TablePagerComponent** */
|
|
2933
4163
|
class TablePagerLoc extends LocalizationService {
|
|
2934
|
-
/**
|
|
2935
|
-
* @ignore
|
|
2936
|
-
*/
|
|
4164
|
+
/** @ignore */
|
|
2937
4165
|
constructor(LOC_LOCALE) {
|
|
2938
4166
|
super(LOC_LOCALE !== null && LOC_LOCALE !== void 0 ? LOC_LOCALE : 'it-IT');
|
|
2939
4167
|
super.set("en->it", "All", ["Tutto"]);
|
|
4168
|
+
super.set("en->it", "Shown Elements", ["Elementi visualizzati"]);
|
|
4169
|
+
super.set("en->it", "Shown Groups", ["Gruppi visualizzati"]);
|
|
2940
4170
|
super.set("en->it", "Are you sure you want to retrieve all results?", ["Si è sicuri di voler caricare tutti i risultati?"]);
|
|
2941
4171
|
super.set("en->it", "This might slow down the page and possibly crash the entire application", ["L'operazione potrebbe rallentare la pagina fino al crash dell'applicazione"]);
|
|
2942
4172
|
}
|
|
@@ -2949,32 +4179,35 @@ TablePagerLoc.ctorParameters = () => [
|
|
|
2949
4179
|
];
|
|
2950
4180
|
|
|
2951
4181
|
// Angular
|
|
2952
|
-
/**
|
|
2953
|
-
* Componente che si occupa della paginazione di una tabella
|
|
2954
|
-
*/
|
|
4182
|
+
/** Componente che si occupa della paginazione di una tabella */
|
|
2955
4183
|
class TablePagerComponent {
|
|
2956
|
-
/**
|
|
2957
|
-
|
|
2958
|
-
*/
|
|
2959
|
-
constructor(msgExts, lc) {
|
|
4184
|
+
/** @ignore */
|
|
4185
|
+
constructor(msgExts, lc, cdr, locale) {
|
|
2960
4186
|
this.msgExts = msgExts;
|
|
2961
4187
|
this.lc = lc;
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
4188
|
+
this.cdr = cdr;
|
|
4189
|
+
this.locale = locale;
|
|
4190
|
+
/** Indica se deve mostrare un warning quando si cercano di solezionare come elementi da visualizzare "Tutti" */
|
|
2965
4191
|
this.WarnOnAll = true;
|
|
2966
|
-
/**
|
|
2967
|
-
* Indica se dare la possibilità o meno di selezionare "Tutti" nelle opzioni di paginazione
|
|
2968
|
-
*/
|
|
4192
|
+
/** Indica se dare la possibilità o meno di selezionare "Tutti" nelle opzioni di paginazione */
|
|
2969
4193
|
this.AllSearch = true;
|
|
2970
|
-
/**
|
|
2971
|
-
* Placeholder che identifica il "Tutti"
|
|
2972
|
-
*/
|
|
4194
|
+
/** Placeholder che identifica il "Tutti" */
|
|
2973
4195
|
this.DefaultAll = 999999;
|
|
2974
|
-
/**
|
|
2975
|
-
|
|
2976
|
-
|
|
4196
|
+
/** Indica se attivare la modalità gruppo con stili più snelli per apparire sotto ai raggruppamenti */
|
|
4197
|
+
this.GroupMode = false;
|
|
4198
|
+
/** Indica se utilizzare il conteggio dei gruppi o degli oggetti */
|
|
4199
|
+
this.GroupCount = false;
|
|
4200
|
+
/** Indica se visualizzare il numero totale di oggeti presenti */
|
|
4201
|
+
this.ShowCount = true;
|
|
4202
|
+
/** Output invocato quando il numero di elementi per pagina viene modificato da un click utente */
|
|
2977
4203
|
this.pagingSelected = new EventEmitter();
|
|
4204
|
+
/** Opzioni di paginazione */
|
|
4205
|
+
this.PagingOptions = [10, 15, 30, 45, 100];
|
|
4206
|
+
}
|
|
4207
|
+
ngOnInit() {
|
|
4208
|
+
this.Model = this.View ? this.View.itemsperpageoverride : this.CurrentPageSize;
|
|
4209
|
+
if (this.AllSearch)
|
|
4210
|
+
this.PagingOptions.push(this.DefaultAll);
|
|
2978
4211
|
}
|
|
2979
4212
|
/**
|
|
2980
4213
|
* Funzione richiamata dal template quando un utente clicca su un numero di paginazione.
|
|
@@ -2985,30 +4218,48 @@ class TablePagerComponent {
|
|
|
2985
4218
|
*/
|
|
2986
4219
|
choice(pageSize) {
|
|
2987
4220
|
if (pageSize == this.DefaultAll && this.WarnOnAll) {
|
|
2988
|
-
this.msgExts.simpleWarningWithChoice(this.lc.loc("Are you sure you want to retrieve all results?"), this.lc.loc("This might slow down the page and possibly crash the entire application"), () => { this.pagingSelected.emit(pageSize); })
|
|
4221
|
+
this.msgExts.simpleWarningWithChoice(this.lc.loc("Are you sure you want to retrieve all results?"), this.lc.loc("This might slow down the page and possibly crash the entire application"), () => { this.pagingSelected.emit(pageSize); this.Model = pageSize; }, () => {
|
|
4222
|
+
// Dio solo sa perché mi tocca fare sta roba... qui dentro per qualche motivo la CD non prende
|
|
4223
|
+
let prevModel = this.Model;
|
|
4224
|
+
this.Model = null;
|
|
4225
|
+
this.cdr.detectChanges();
|
|
4226
|
+
this.Model = prevModel;
|
|
4227
|
+
this.cdr.detectChanges();
|
|
4228
|
+
});
|
|
2989
4229
|
}
|
|
2990
|
-
else
|
|
4230
|
+
else {
|
|
2991
4231
|
this.pagingSelected.emit(pageSize);
|
|
4232
|
+
this.Model = pageSize;
|
|
4233
|
+
}
|
|
2992
4234
|
}
|
|
2993
4235
|
}
|
|
2994
4236
|
TablePagerComponent.decorators = [
|
|
2995
4237
|
{ type: Component, args: [{
|
|
2996
4238
|
selector: "app-paging",
|
|
2997
4239
|
viewProviders: [{ provide: LocalizationService, useClass: TablePagerLoc }],
|
|
2998
|
-
template: "
|
|
4240
|
+
template: "<ng-container *ngIf=\"!Hidden\">\r\n <span class=\"est-fs-14\"> {{(GroupMode ? 'Shown Groups' : 'Shown Elements') | localize : lc}}: </span>\r\n <mat-form-field [appearance]=\"'legacy'\" class=\"mat-paginator-page-size-select est-fs-14 est-ipp-bold\" *ngIf=\"Model\">\r\n <select matNativeControl [ngModel]=\"Model\" name=\"input\" (ngModelChange)=\"choice($event)\">\r\n <ng-container *ngFor=\"let pOpt of PagingOptions\">\r\n <option *ngIf=\"pOpt == DefaultAll || PagerCount > pOpt\" [value]=\"pOpt\">{{ pOpt == DefaultAll ? ('All' | localize : lc) : pOpt.toString()}}</option>\r\n </ng-container>\r\n </select>\r\n </mat-form-field>\r\n <span class=\"est-fs-14 est-ipp-bold\" *ngIf=\"ShowCount\"> / {{PagerCount | number : '0.0-0' : locale}}\r\n </span>\r\n</ng-container>",
|
|
4241
|
+
encapsulation: ViewEncapsulation.None,
|
|
4242
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
4243
|
+
styles: [".est-ipp-sel,.est-ipp-sel-all,.est-rg-ipp-sel,.est-rg-ipp-sel-all{color:#0275d8!important;cursor:pointer;text-decoration:none;display:block;display:inline}.est-ipp-bold{font-weight:700}.mat-paginator-page-size-select{margin:6px 4px 0;width:50px}.mat-paginator-page-size-select .mat-form-field-wrapper{height:52px!important;margin-top:-15px!important;padding:0!important}.mat-form-field-type-mat-native-select .mat-form-field-infix:after{margin-top:-5.5px!important}"]
|
|
2999
4244
|
},] }
|
|
3000
4245
|
];
|
|
3001
4246
|
TablePagerComponent.ctorParameters = () => [
|
|
3002
4247
|
{ type: MessageService },
|
|
3003
|
-
{ type: LocalizationService }
|
|
4248
|
+
{ type: LocalizationService },
|
|
4249
|
+
{ type: ChangeDetectorRef },
|
|
4250
|
+
{ type: String, decorators: [{ type: Optional }, { type: Inject, args: [EST_LOCALE,] }] }
|
|
3004
4251
|
];
|
|
3005
4252
|
TablePagerComponent.propDecorators = {
|
|
3006
4253
|
CurrentPageSize: [{ type: Input }],
|
|
3007
4254
|
View: [{ type: Input }],
|
|
3008
|
-
Hidden: [{ type: Input }],
|
|
3009
4255
|
WarnOnAll: [{ type: Input }],
|
|
3010
4256
|
AllSearch: [{ type: Input }],
|
|
3011
4257
|
DefaultAll: [{ type: Input }],
|
|
4258
|
+
GroupMode: [{ type: Input }],
|
|
4259
|
+
GroupCount: [{ type: Input }],
|
|
4260
|
+
ShowCount: [{ type: Input }],
|
|
4261
|
+
PagerCount: [{ type: Input }],
|
|
4262
|
+
Hidden: [{ type: Input }],
|
|
3012
4263
|
pagingSelected: [{ type: Output }]
|
|
3013
4264
|
};
|
|
3014
4265
|
|
|
@@ -3017,7 +4268,8 @@ class EsTableModule {
|
|
|
3017
4268
|
return {
|
|
3018
4269
|
ngModule: EsTableModule,
|
|
3019
4270
|
providers: [
|
|
3020
|
-
{ provide: EST_LOCALE, useValue: (config === null || config === void 0 ? void 0 : config.locale) || 'it-IT' }
|
|
4271
|
+
{ provide: EST_LOCALE, useValue: (config === null || config === void 0 ? void 0 : config.locale) || 'it-IT' },
|
|
4272
|
+
{ provide: EST_DEBUG, useValue: (config === null || config === void 0 ? void 0 : config.debugMode) || false }
|
|
3021
4273
|
]
|
|
3022
4274
|
};
|
|
3023
4275
|
}
|
|
@@ -3032,7 +4284,9 @@ EsTableModule.decorators = [
|
|
|
3032
4284
|
ModalModule,
|
|
3033
4285
|
BsDropdownModule,
|
|
3034
4286
|
CsvModule,
|
|
3035
|
-
ContextMenuModule
|
|
4287
|
+
ContextMenuModule,
|
|
4288
|
+
MatSelectModule,
|
|
4289
|
+
MatInputModule
|
|
3036
4290
|
],
|
|
3037
4291
|
declarations: [EsTh, EsTd, EsTableComponent, EsTdDirective, EsThDirective, TablePagerComponent],
|
|
3038
4292
|
providers: [UtilityService, ExportService, HashingService, MessageService],
|
|
@@ -3048,5 +4302,5 @@ EsTableModule.decorators = [
|
|
|
3048
4302
|
* Generated bundle index. Do not edit.
|
|
3049
4303
|
*/
|
|
3050
4304
|
|
|
3051
|
-
export { AppOrdering, AppSearch, CornerMenuOption,
|
|
4305
|
+
export { AppOrdering, AppSearch, CornerMenuOption, EsTableColumnsDefinition, EsTableComponent, EsTableDefaultable, EsTableModule, EsTableModuleConfig, EsTableOperationDefinition, EsTd, EsTh, GenericItem, Group, GroupAggregation, GroupFilter, GroupOrAggregation, ItemsSelection, ReportColumn, ReportDefinition, ReportOrder, ReportParam, ReportResult, ReportRow, EsTableLoc as ɵa, EST_LOCALE as ɵb, EST_DEBUG as ɵc, EST_DEFAULTS as ɵd, EsTdDirective as ɵe, EsThDirective as ɵf, TablePagerComponent as ɵg, TablePagerLoc as ɵh };
|
|
3052
4306
|
//# sourceMappingURL=esfaenza-es-table.js.map
|