@esfaenza/es-table 11.2.20 → 11.2.22-beta3

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.
Files changed (111) hide show
  1. package/bundles/esfaenza-es-table.umd.js +1881 -539
  2. package/bundles/esfaenza-es-table.umd.js.map +1 -1
  3. package/bundles/esfaenza-es-table.umd.min.js +2 -2
  4. package/bundles/esfaenza-es-table.umd.min.js.map +1 -1
  5. package/esfaenza-es-table.d.ts +5 -5
  6. package/esfaenza-es-table.metadata.json +1 -1
  7. package/esm2015/esfaenza-es-table.js +6 -6
  8. package/esm2015/lib/directives/es_td.directive.js +2 -4
  9. package/esm2015/lib/directives/es_th.directive.js +17 -8
  10. package/esm2015/lib/domain/externals/classes/CornerMenuOption.js +4 -0
  11. package/esm2015/lib/domain/externals/classes/EsTableColumnsDefinition.js +31 -0
  12. package/esm2015/lib/domain/externals/classes/EsTableOperationDefinition.js +22 -0
  13. package/esm2015/lib/domain/externals/classes/appsearch/AppOrdering.js +16 -0
  14. package/esm2015/lib/domain/externals/classes/appsearch/AppSearch.js +35 -0
  15. package/esm2015/lib/domain/externals/classes/appsearch/GenericItem.js +11 -0
  16. package/esm2015/lib/domain/externals/classes/appsearch/Group.js +17 -0
  17. package/esm2015/lib/domain/externals/classes/appsearch/GroupAggregation.js +16 -0
  18. package/esm2015/lib/domain/externals/classes/appsearch/GroupFilter.js +14 -0
  19. package/esm2015/lib/domain/externals/classes/appsearch/GroupOrAggregation.js +16 -0
  20. package/esm2015/lib/domain/externals/classes/appsearch/ItemsSelection.js +23 -0
  21. package/esm2015/lib/domain/externals/classes/report/ReportColumn.js +4 -0
  22. package/esm2015/lib/domain/externals/classes/report/ReportDefinition.js +4 -0
  23. package/esm2015/lib/domain/externals/classes/report/ReportOrder.js +4 -0
  24. package/esm2015/lib/domain/externals/classes/report/ReportParam.js +4 -0
  25. package/esm2015/lib/domain/externals/classes/report/ReportResult.js +4 -0
  26. package/esm2015/lib/domain/externals/classes/report/ReportRow.js +4 -0
  27. package/esm2015/lib/domain/externals/index.js +18 -0
  28. package/esm2015/lib/domain/index.js +3 -16
  29. package/esm2015/lib/domain/internals/classes/CacheTriptic.js +16 -0
  30. package/esm2015/lib/domain/internals/classes/EsTableColumn.js +24 -0
  31. package/esm2015/lib/domain/internals/classes/GroupPager.js +21 -0
  32. package/esm2015/lib/domain/internals/classes/GroupRouteFragment.js +17 -0
  33. package/esm2015/lib/domain/internals/classes/ThAggregation.js +16 -0
  34. package/esm2015/lib/domain/internals/index.js +6 -0
  35. package/esm2015/lib/es-table.module.js +9 -4
  36. package/esm2015/lib/es_table.component.js +1496 -323
  37. package/esm2015/lib/es_table.component.loc.js +4 -7
  38. package/esm2015/lib/es_td.component.js +9 -20
  39. package/esm2015/lib/es_th.component.js +16 -44
  40. package/esm2015/lib/models/EsTableDefaultable.js +4 -0
  41. package/esm2015/lib/models/EsTableModuleConfig.js +2 -4
  42. package/esm2015/lib/pager/table_pager.component.js +48 -26
  43. package/esm2015/lib/pager/table_pager.component.loc.js +5 -7
  44. package/esm2015/lib/tokens.js +6 -4
  45. package/esm2015/public-api.js +3 -2
  46. package/fesm2015/esfaenza-es-table.js +1762 -510
  47. package/fesm2015/esfaenza-es-table.js.map +1 -1
  48. package/lib/directives/es_td.directive.d.ts +1 -3
  49. package/lib/directives/es_th.directive.d.ts +14 -7
  50. package/lib/domain/externals/classes/CornerMenuOption.d.ts +7 -0
  51. package/lib/domain/{classes → externals/classes}/EsTableColumnsDefinition.d.ts +2 -6
  52. package/lib/domain/{classes → externals/classes}/EsTableOperationDefinition.d.ts +1 -3
  53. package/lib/domain/{classes → externals/classes/appsearch}/AppOrdering.d.ts +0 -0
  54. package/lib/domain/externals/classes/appsearch/AppSearch.d.ts +67 -0
  55. package/lib/domain/externals/classes/appsearch/GenericItem.d.ts +13 -0
  56. package/lib/domain/externals/classes/appsearch/Group.d.ts +17 -0
  57. package/lib/domain/externals/classes/appsearch/GroupAggregation.d.ts +14 -0
  58. package/lib/domain/externals/classes/appsearch/GroupFilter.d.ts +12 -0
  59. package/lib/domain/externals/classes/appsearch/GroupOrAggregation.d.ts +14 -0
  60. package/lib/domain/externals/classes/appsearch/ItemsSelection.d.ts +22 -0
  61. package/lib/domain/externals/classes/report/ReportColumn.d.ts +15 -0
  62. package/lib/domain/externals/classes/report/ReportDefinition.d.ts +24 -0
  63. package/lib/domain/externals/classes/report/ReportOrder.d.ts +7 -0
  64. package/lib/domain/externals/classes/report/ReportParam.d.ts +40 -0
  65. package/lib/domain/externals/classes/report/ReportResult.d.ts +12 -0
  66. package/lib/domain/externals/classes/report/ReportRow.d.ts +5 -0
  67. package/lib/domain/externals/index.d.ts +17 -0
  68. package/lib/domain/index.d.ts +2 -15
  69. package/lib/domain/internals/classes/CacheTriptic.d.ts +14 -0
  70. package/lib/domain/{classes → internals/classes}/EsTableColumn.d.ts +6 -4
  71. package/lib/domain/internals/classes/GroupPager.d.ts +22 -0
  72. package/lib/domain/internals/classes/GroupRouteFragment.d.ts +15 -0
  73. package/lib/domain/internals/classes/ThAggregation.d.ts +14 -0
  74. package/lib/domain/internals/index.d.ts +5 -0
  75. package/lib/es_table.component.d.ts +346 -51
  76. package/lib/es_table.component.loc.d.ts +2 -6
  77. package/lib/es_td.component.d.ts +13 -36
  78. package/lib/es_th.component.d.ts +21 -61
  79. package/lib/models/EsTableDefaultable.d.ts +19 -0
  80. package/lib/models/EsTableModuleConfig.d.ts +8 -7
  81. package/lib/pager/table_pager.component.d.ts +27 -30
  82. package/lib/pager/table_pager.component.loc.d.ts +2 -6
  83. package/lib/tokens.d.ts +6 -3
  84. package/package.json +2 -1
  85. package/public-api.d.ts +2 -1
  86. package/esm2015/lib/domain/classes/AppOrdering.js +0 -16
  87. package/esm2015/lib/domain/classes/AppSearch.js +0 -56
  88. package/esm2015/lib/domain/classes/CornerMenuOption.js +0 -6
  89. package/esm2015/lib/domain/classes/EsTableColumn.js +0 -22
  90. package/esm2015/lib/domain/classes/EsTableColumnsDefinition.js +0 -33
  91. package/esm2015/lib/domain/classes/EsTableOperationDefinition.js +0 -24
  92. package/esm2015/lib/domain/classes/GenericItem.js +0 -15
  93. package/esm2015/lib/domain/classes/IAppSearch.js +0 -2
  94. package/esm2015/lib/domain/classes/ItemsSelection.js +0 -25
  95. package/esm2015/lib/domain/classes/ReportColumn.js +0 -6
  96. package/esm2015/lib/domain/classes/ReportDefinition.js +0 -6
  97. package/esm2015/lib/domain/classes/ReportOrder.js +0 -6
  98. package/esm2015/lib/domain/classes/ReportParam.js +0 -6
  99. package/esm2015/lib/domain/classes/ReportResult.js +0 -6
  100. package/esm2015/lib/domain/classes/ReportRow.js +0 -6
  101. package/lib/domain/classes/AppSearch.d.ts +0 -110
  102. package/lib/domain/classes/CornerMenuOption.d.ts +0 -13
  103. package/lib/domain/classes/GenericItem.d.ts +0 -25
  104. package/lib/domain/classes/IAppSearch.d.ts +0 -67
  105. package/lib/domain/classes/ItemsSelection.d.ts +0 -27
  106. package/lib/domain/classes/ReportColumn.d.ts +0 -29
  107. package/lib/domain/classes/ReportDefinition.d.ts +0 -46
  108. package/lib/domain/classes/ReportOrder.d.ts +0 -13
  109. package/lib/domain/classes/ReportParam.d.ts +0 -76
  110. package/lib/domain/classes/ReportResult.d.ts +0 -22
  111. package/lib/domain/classes/ReportRow.d.ts +0 -9
@@ -1,8 +1,8 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('@esfaenza/extensions'), require('@esfaenza/localizations'), require('@esfaenza/preferences'), require('@angular/platform-browser'), require('@angular/common'), require('@angular/router'), require('ngx-bootstrap/modal'), require('ngx-bootstrap/dropdown'), require('@ctrl/ngx-csv'), require('@esfaenza/ngx-contextmenu')) :
3
- typeof define === 'function' && define.amd ? define('@esfaenza/es-table', ['exports', '@angular/core', '@angular/forms', '@esfaenza/extensions', '@esfaenza/localizations', '@esfaenza/preferences', '@angular/platform-browser', '@angular/common', '@angular/router', 'ngx-bootstrap/modal', 'ngx-bootstrap/dropdown', '@ctrl/ngx-csv', '@esfaenza/ngx-contextmenu'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.esfaenza = global.esfaenza || {}, global.esfaenza['es-table'] = {}), global.ng.core, global.ng.forms, global.extensions, global.localizations, global.preferences, global.ng.platformBrowser, global.ng.common, global.ng.router, global.modal, global.dropdown, global.ngxCsv, global.ngxContextmenu));
5
- }(this, (function (exports, core, forms, extensions, localizations, preferences, platformBrowser, common, router, modal, dropdown, ngxCsv, ngxContextmenu) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@angular/core'), require('@angular/forms'), require('@esfaenza/extensions'), require('@esfaenza/localizations'), require('@esfaenza/preferences'), require('@angular/platform-browser'), require('@angular/common'), require('@angular/router'), require('@angular/material/select'), require('@angular/material/input'), require('ngx-bootstrap/modal'), require('ngx-bootstrap/dropdown'), require('@ctrl/ngx-csv'), require('@esfaenza/ngx-contextmenu')) :
3
+ typeof define === 'function' && define.amd ? define('@esfaenza/es-table', ['exports', '@angular/core', '@angular/forms', '@esfaenza/extensions', '@esfaenza/localizations', '@esfaenza/preferences', '@angular/platform-browser', '@angular/common', '@angular/router', '@angular/material/select', '@angular/material/input', 'ngx-bootstrap/modal', 'ngx-bootstrap/dropdown', '@ctrl/ngx-csv', '@esfaenza/ngx-contextmenu'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.esfaenza = global.esfaenza || {}, global.esfaenza['es-table'] = {}), global.ng.core, global.ng.forms, global.extensions, global.localizations, global.preferences, global.ng.platformBrowser, global.ng.common, global.ng.router, global.ng.material.select, global.ng.material.input, global.modal, global.dropdown, global.ngxCsv, global.ngxContextmenu));
5
+ }(this, (function (exports, core, forms, extensions, localizations, preferences, platformBrowser, common, router, select, input, modal, dropdown, ngxCsv, ngxContextmenu) { 'use strict';
6
6
 
7
7
  /*! *****************************************************************************
8
8
  Copyright (c) Microsoft Corporation.
@@ -364,38 +364,9 @@
364
364
  this.savedstate = false;
365
365
  };
366
366
  return AppSearch;
367
- }());
368
- var Group = /** @class */ (function () {
369
- function Group(column, value) {
370
- this.column = column;
371
- this.value = value;
372
- this.aggregations = [];
373
- }
374
- return Group;
375
- }());
376
- var GroupAggregation = /** @class */ (function () {
377
- function GroupAggregation() {
378
- }
379
- return GroupAggregation;
380
- }());
381
- var GroupFilter = /** @class */ (function () {
382
- function GroupFilter(column, value) {
383
- this.column = column;
384
- this.value = value;
385
- }
386
- return GroupFilter;
387
- }());
388
- var GroupOrAggregation = /** @class */ (function () {
389
- function GroupOrAggregation(column, aggregation) {
390
- this.column = column;
391
- this.aggregation = aggregation;
392
- }
393
- return GroupOrAggregation;
394
367
  }());
395
368
 
396
- /**
397
- * Classe che identifica una colonna. Utilizzata in modalità "Colonne dinamiche"
398
- */
369
+ /** Classe che identifica una colonna. Utilizzata in modalità "Colonne dinamiche" */
399
370
  var EsTableColumnsDefinition = /** @class */ (function () {
400
371
  /**
401
372
  * Costruttore
@@ -435,88 +406,68 @@
435
406
  return EsTableColumnsDefinition;
436
407
  }());
437
408
 
438
- /**
439
- * Classe che definisce un oggetto generico come lista di proprietà-valore
440
- */
409
+ /** Classe che definisce un oggetto generico come lista di proprietà-valore */
441
410
  var GenericItem = /** @class */ (function () {
442
- /**
443
- * @ignore
444
- */
411
+ /** @ignore */
445
412
  function GenericItem() {
446
413
  this._selected = false;
447
414
  this._rowClass = null;
448
- this.hash = null;
415
+ this._hash = null;
449
416
  this.properties = {};
450
417
  }
451
418
  return GenericItem;
452
419
  }());
453
420
 
454
- /**
455
- * Indica un'opzione cliccabile nel Corner Menù della tabella (il menù richiamabile dai 3 pallini verticli in alto a destra)
456
- */
421
+ /** Indica un'opzione cliccabile nel Corner Menù della tabella (il menù richiamabile dai 3 pallini verticli in alto a destra) */
457
422
  var CornerMenuOption = /** @class */ (function () {
458
423
  function CornerMenuOption() {
459
424
  }
460
425
  return CornerMenuOption;
461
426
  }());
462
427
 
463
- /**
464
- * Definizione generica di un report che può o no disporre di paginazione/export e la cui richiesta è basata su uno o più parametri
465
- */
428
+ /** Definizione generica di un report che può o no disporre di paginazione/export e la cui richiesta è basata su uno o più parametri */
466
429
  var ReportDefinition = /** @class */ (function () {
467
430
  function ReportDefinition() {
468
431
  }
469
432
  return ReportDefinition;
470
433
  }());
471
434
 
472
- /**
473
- * Classe che identifica una direttiva di ordinamento per un report
474
- */
435
+ /** Classe che identifica una direttiva di ordinamento per un report */
475
436
  var ReportOrder = /** @class */ (function () {
476
437
  function ReportOrder() {
477
438
  }
478
439
  return ReportOrder;
479
440
  }());
480
441
 
481
- /**
482
- * Classe che rappresenta una colonna di un report
483
- */
442
+ /** Classe che rappresenta una colonna di un report */
484
443
  var ReportColumn = /** @class */ (function () {
485
444
  function ReportColumn() {
486
445
  }
487
446
  return ReportColumn;
488
447
  }());
489
448
 
490
- /**
491
- * Classe che rappresenta una lista di oggetti generati da un report
492
- */
449
+ /** Classe che rappresenta una lista di oggetti generati da un report */
493
450
  var ReportResult = /** @class */ (function () {
494
451
  function ReportResult() {
495
452
  }
496
453
  return ReportResult;
497
454
  }());
498
455
 
499
- /**
500
- * Classe che rappresenta i valori delle proprietà di un oggetto Report
501
- */
456
+ /** Classe che rappresenta i valori delle proprietà di un oggetto Report */
502
457
  var ReportRow = /** @class */ (function () {
503
458
  function ReportRow() {
504
459
  }
505
460
  return ReportRow;
506
461
  }());
507
462
 
508
- /**
509
- * Classe che identifica un parametro generico per un report
510
- */
463
+ /** Classe che identifica un parametro generico per un report */
511
464
  var ReportParam = /** @class */ (function () {
512
465
  function ReportParam() {
513
466
  }
514
467
  return ReportParam;
515
468
  }());
516
469
 
517
- /**
518
- * Indica operazioni dinamiche generiche che possono essere effettuate per riga. Appaiono come colonne extra sul lato sinistro della tabella
519
- */
470
+ /** Indica operazioni dinamiche generiche che possono essere effettuate per riga. Appaiono come colonne extra sul lato sinistro della tabella */
520
471
  var EsTableOperationDefinition = /** @class */ (function () {
521
472
  /**
522
473
  * Costruttore
@@ -539,9 +490,115 @@
539
490
  return EsTableOperationDefinition;
540
491
  }());
541
492
 
542
- /**
543
- * Definizione di una colonna
544
- */
493
+ /** Identifica una selezione applicabile agli oggetti presentati in una tabella */
494
+ var ItemsSelection = /** @class */ (function () {
495
+ /**
496
+ * Costruttore
497
+ *
498
+ * @param {T[]} selected Oggetti da considerare selezionati
499
+ */
500
+ function ItemsSelection(selected) {
501
+ /** Indica se tutti gli elementi sono da considerarsi selezionati (anche quelli di altre pagine) */
502
+ this.all = false;
503
+ /** Se **all** è **true**, indica gli elementi da escludere, altrimenti è insensato */
504
+ this.exclusions = [];
505
+ /** Se **all** è **true**, indica i gruppi da escludere, altrimenti è insensato */
506
+ this.group_exclusions = [];
507
+ this.count = selected.length;
508
+ this.items = selected;
509
+ this.all = false;
510
+ this.exclusions = [];
511
+ this.groups = [];
512
+ this.group_exclusions = [];
513
+ }
514
+ return ItemsSelection;
515
+ }());
516
+
517
+ /** Classe che rappresenta un Gruppo con le proprie aggregazioni */
518
+ var Group = /** @class */ (function () {
519
+ /**
520
+ * Costruttore
521
+ *
522
+ * @param {string} column ID della colonna raggruppata
523
+ * @param {number} count Numero di elementi raggruppati sotto questa colonna
524
+ * @param {string} value Valore del Gruppo
525
+ */
526
+ function Group(column, count, value) {
527
+ this.column = column;
528
+ this.count = count;
529
+ this.value = value;
530
+ this.aggregations = [];
531
+ }
532
+ return Group;
533
+ }());
534
+
535
+ /** Classe che rappresenta un'aggregazione */
536
+ var GroupAggregation = /** @class */ (function () {
537
+ /**
538
+ * Costruttore
539
+ *
540
+ * @param {string} column ID della colonna aggregata
541
+ * @param {'min' | 'max' | 'sum' } aggregation Aggregazione da effettuare su questa colonna
542
+ * @param {string} value Valore dell'aggregazione
543
+ */
544
+ function GroupAggregation(column, aggregation, value) {
545
+ this.column = column;
546
+ this.aggregation = aggregation;
547
+ this.value = value;
548
+ }
549
+ return GroupAggregation;
550
+ }());
551
+
552
+ /** Classe che rappresenta un filtro su un gruppo */
553
+ var GroupFilter = /** @class */ (function () {
554
+ /**
555
+ * Costruttore
556
+ *
557
+ * @param {string} column ID della colonna gruppata per cui si richiede di filtrare
558
+ * @param {string} value Valore del gruppo su questa **column** per cui si richiede di filtrare
559
+ */
560
+ function GroupFilter(column, value) {
561
+ this.column = column;
562
+ this.value = value;
563
+ }
564
+ return GroupFilter;
565
+ }());
566
+
567
+ /** Classe che rappresenta o un gruppo o una aggregazione su una colonna. Usata solo internamente */
568
+ var GroupOrAggregation = /** @class */ (function () {
569
+ /**
570
+ * Costruttore
571
+ *
572
+ * @param {string} column Colonna su cui è presente o un gruppo o un'aggregazione
573
+ * @param {'min' | 'max' | 'sum' } aggregation Aggregazione presente sulla **column**. Se questo campo è nullo significa che è un gruppo.
574
+ * @param {'string' | 'date' | 'number'} datatype Tipo di dati contenuto nella colonna **column** se non c'è alcuna aggregazione è inutile, pertanto non sarà valorizzato
575
+ */
576
+ function GroupOrAggregation(column, aggregation, datatype) {
577
+ this.column = column;
578
+ this.aggregation = aggregation;
579
+ this.datatype = datatype;
580
+ }
581
+ return GroupOrAggregation;
582
+ }());
583
+
584
+ /** 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 */
585
+ var CacheTriptic = /** @class */ (function () {
586
+ /**
587
+ * Costruttore
588
+ *
589
+ * @param {Map<string, any>} cache Cache Chiave-Oggetto
590
+ * @param {Map<string, number>} index_cache Cache Indice-Oggetto
591
+ * @param {any[]} array Array contenente gli oggetti
592
+ */
593
+ function CacheTriptic(cache, index_cache, array) {
594
+ this.cache = cache;
595
+ this.index_cache = index_cache;
596
+ this.array = array;
597
+ }
598
+ return CacheTriptic;
599
+ }());
600
+
601
+ /** Definizione di una colonna, utilizzato nella dialog che permette di modificare le posizioni e le visibilità */
545
602
  var EsTableColumn = /** @class */ (function () {
546
603
  /**
547
604
  * Costruttore
@@ -550,68 +607,93 @@
550
607
  * @param {string} description Descrizione (Header)
551
608
  * @param {boolean} visible Indica se di default mostrarla o meno
552
609
  * @param {boolean} fixed Indica se è una colonna fixed
610
+ * @param {boolean} pinned Indica se è una colonna pinnata
611
+ * @param {number} pinnedWidth Indica la dimensione da assegnare a questa colonna quando è pinnata
553
612
  * @param {TemplateRef<any>} template Indica il template da usare per mostrare il testo dell'Header
554
613
  */
555
- function EsTableColumn(id, description, visible, fixed, template) {
614
+ function EsTableColumn(id, description, visible, fixed, pinned, pinnedWidth, template) {
556
615
  this.id = id;
557
616
  this.description = description;
558
617
  this.visible = visible;
559
618
  this.fixed = fixed;
619
+ this.pinned = pinned;
620
+ this.pinnedWidth = pinnedWidth;
560
621
  this.template = template;
561
622
  }
562
623
  return EsTableColumn;
563
624
  }());
564
625
 
565
- /**
566
- * Identifica una selezione applicabile agli oggetti presentati in una tabella
567
- */
568
- var ItemsSelection = /** @class */ (function () {
626
+ /** Classe che rappresenta un separatore da inserire fra gli oggetti dell'es-table per le operazioni di paginazione dei raggruppamenti per riga */
627
+ var GroupPager = /** @class */ (function () {
569
628
  /**
570
629
  * Costruttore
571
630
  *
572
- * @param {T[]} selected Oggetti da considerare selezionati
631
+ * @param {number} groupLevel Livello del gruppo a cui questo separatore fa riferimento
632
+ * @param {string} parentKey Chiave del gruppo parent se esiste
633
+ * @param {AppSearch<any>} view Vista di ricerca collegata a questo elemento
634
+ * @param {'groups' | 'items'} searches Indica che cosa cerca questo separatore, se sottogruppi o oggetti
573
635
  */
574
- function ItemsSelection(selected) {
575
- /**
576
- * Indica se tutti gli elementi sono da considerarsi selezionati (anche quelli di altre pagine)
577
- */
578
- this.all = false;
579
- /**
580
- * Se **all** è **true**, indica gli elementi da escludere, altrimenti è insensato
581
- */
582
- this.exclusions = [];
583
- this.count = selected.length;
584
- this.items = selected;
585
- this.all = false;
586
- this.exclusions = [];
636
+ function GroupPager(_grouplevel, _thisRoute, _parent, view, searches) {
637
+ this._grouplevel = _grouplevel;
638
+ this._thisRoute = _thisRoute;
639
+ this._parent = _parent;
640
+ this.view = view;
641
+ this.searches = searches;
642
+ this._sep = true;
643
+ this.buttons = [];
587
644
  }
588
- return ItemsSelection;
645
+ return GroupPager;
589
646
  }());
590
647
 
591
- //Angular
592
648
  /**
593
- * Componente rappresentante una singola cella del body della tabella
649
+ * 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
650
+ * per arrivare ad una ricerca su sottogruppi o elementi relativi
594
651
  */
595
- var EsTd = /** @class */ (function () {
652
+ var GroupRouteFragment = /** @class */ (function () {
596
653
  /**
597
- * @ignore
654
+ * Costruttore
655
+ *
656
+ * @param {string} column Colonna di raggruppamento
657
+ * @param {string} value Valore della colonna di raggruppamento
658
+ */
659
+ function GroupRouteFragment(column, value) {
660
+ this.column = column;
661
+ this.value = value;
662
+ }
663
+ return GroupRouteFragment;
664
+ }());
665
+
666
+ /** Classe rappresentante una singola aggregazione effettuata su una colonna */
667
+ var ThAggregation = /** @class */ (function () {
668
+ /**
669
+ * Costruttore
670
+ *
671
+ * @param {'min' | 'max' | 'sum'} func Funzione di aggergazione, può essere **min**, **max** o **sum**
672
+ * @param {string} format Formato richiesto per il valore dell'aggregazione
673
+ * @param {string} match Match intero del pezzo di testo da cui si è estrapolata l'aggregazione, da rimpiazzare col valore calcolato
598
674
  */
675
+ function ThAggregation(func, format, match) {
676
+ this.func = func;
677
+ this.format = format;
678
+ this.match = match;
679
+ }
680
+ return ThAggregation;
681
+ }());
682
+
683
+ //Angular
684
+ /** Componente rappresentante una singola cella del body della tabella */
685
+ var EsTd = /** @class */ (function () {
686
+ /** @ignore */
599
687
  function EsTd(myself, renderer, _viewContainer, sanitizer) {
600
688
  this.myself = myself;
601
689
  this.renderer = renderer;
602
690
  this._viewContainer = _viewContainer;
603
691
  this.sanitizer = sanitizer;
604
- /**
605
- * Id della cella, dev'essere lo stesso della colonna **EsTh** relativa
606
- */
692
+ /** Id della cella, dev'essere lo stesso della colonna **EsTh** relativa */
607
693
  this.ID = "";
608
- /**
609
- * Valore da mostrare all'interno della cella. Se omesso verrà proiettato il contenuto dal template in cui è stata usata
610
- */
694
+ /** Valore da mostrare all'interno della cella. Se omesso verrà proiettato il contenuto dal template in cui è stata usata */
611
695
  this.Display = null;
612
- /**
613
- * Template Angular da istanziare per questo TD
614
- */
696
+ /** Template Angular da istanziare per questo TD */
615
697
  this.Template = null;
616
698
  }
617
699
  Object.defineProperty(EsTd.prototype, "Visible", {
@@ -640,18 +722,17 @@
640
722
  enumerable: false,
641
723
  configurable: true
642
724
  });
643
- /**
644
- * @ignore
645
- */
725
+ /** @ignore */
646
726
  EsTd.prototype.ngAfterViewInit = function () {
647
727
  // Se è Internal significa che è gestita internamente da ES-TABLE quindi evito di fare sti due passaggi di lettura del DOM
648
728
  if (this.Internal)
649
729
  return;
650
730
  // L'hash è calcolato dalla ES-table in fase di binding
651
- this.Context = this.Context || this.getTemplateContext().hash;
731
+ this.Context = this.Context || this.getTemplateContext()._hash;
652
732
  this.Content = this.Display === null || this.Display === "" ? this.sanitizer.bypassSecurityTrustHtml(this.myself.nativeElement.innerHTML) : this.sanitizer.bypassSecurityTrustHtml(this.Display);
653
733
  this.Class = this.myself.nativeElement.className.replace("app-display-none", "");
654
734
  };
735
+ /** Ottiene il contesto della view su cui è istanziato il componente */
655
736
  EsTd.prototype.getTemplateContext = function () {
656
737
  // 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
657
738
  var vc = this._viewContainer;
@@ -709,23 +790,15 @@
709
790
  };
710
791
 
711
792
  //Angular
712
- /**
713
- * Componente rappresentante una Colonna della tabella
714
- */
793
+ /** Componente rappresentante una Colonna della tabella */
715
794
  var EsTh = /** @class */ (function () {
716
- /**
717
- * @ignore
718
- */
795
+ /** @ignore */
719
796
  function EsTh(myself, renderer) {
720
797
  this.myself = myself;
721
798
  this.renderer = renderer;
722
- /**
723
- * Dizionario di mappatura con ordinamento attuale e ordinamento successivo per gestire i passaggi di stato
724
- */
799
+ /** Dizionario di mappatura con ordinamento attuale e ordinamento successivo per gestire i passaggi di stato */
725
800
  this.orderNext = { "NONE": "DESC", "DESC": "ASC", "ASC": null };
726
- /**
727
- * Indica se si sta effettuando un'operazione di resize su questa colonna
728
- */
801
+ /** Indica se si sta effettuando un'operazione di resize su questa colonna */
729
802
  this.resizingThis = false;
730
803
  /**
731
804
  * Storicizza l'offset di partenza del resize dell'elemento HTML per poter calcolare la nuova dimensione richiesta durente il resize
@@ -733,21 +806,13 @@
733
806
  * nuova width = startOffset + posizione X del mouse
734
807
  */
735
808
  this.startOffset = null;
736
- /**
737
- * Id della colonna, dev'essere lo stesso per tutti gli **EsTd** relativi
738
- */
809
+ /** Id della colonna, dev'essere lo stesso per tutti gli **EsTd** relativi */
739
810
  this.ID = "";
740
- /**
741
- * Indica se questa colonna è ordinabile o meno
742
- */
811
+ /** Indica se questa colonna è ordinabile o meno */
743
812
  this.Orderable = true;
744
- /**
745
- * Valore da mostrare all'interno della colonna. Se omesso verrà proiettato il contenuto dal template in cui è stata usata
746
- */
813
+ /** Valore da mostrare all'interno della colonna. Se omesso verrà proiettato il contenuto dal template in cui è stata usata */
747
814
  this.Display = "";
748
- /**
749
- * Indica se le dimnsioni di questa colonna sono modificabili o meno
750
- */
815
+ /** Indica se le dimnsioni di questa colonna sono modificabili o meno */
751
816
  this.Resizable = false;
752
817
  /**
753
818
  * Indica se sta venendo eseguita una operazione di ricerca o meno, serve per evitare l'esecuzione di eventuale codice che potrebbe dare fastidio
@@ -758,18 +823,12 @@
758
823
  this.Wrap = false;
759
824
  /** Indica se la colonna è fixed, cioè se non può né essere nascosta, né riposizionata. Solo le prime colonne possono essere Fixed */
760
825
  this.Fixed = false;
761
- /**
762
- * Template Angular da istanziare per questo TH
763
- */
826
+ /** Template Angular da istanziare per questo TH */
764
827
  this.Template = null;
765
- /**
766
- * Evento emesso al cambio di ordinamento effettuato su questa colonna
767
- */
828
+ /** Evento emesso al cambio di ordinamento effettuato su questa colonna */
768
829
  this.onOrderChange = new core.EventEmitter();
769
- /**
770
- * Impostato dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header
771
- */
772
- this.Referenced = false;
830
+ /** Impostato dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header */
831
+ this._referenced = false;
773
832
  }
774
833
  Object.defineProperty(EsTh.prototype, "Visible", {
775
834
  /**
@@ -797,9 +856,7 @@
797
856
  enumerable: false,
798
857
  configurable: true
799
858
  });
800
- /**
801
- * @ignore
802
- */
859
+ /** @ignore */
803
860
  EsTh.prototype.ngAfterViewInit = function () {
804
861
  //Assegnare direttamente il content è più veloce che passare dal native element per qualche motivo
805
862
  this.Description = this.Display === null || this.Display === "" ? this.content.nativeElement.innerText : this.Display;
@@ -808,9 +865,7 @@
808
865
  if (this.Resizable)
809
866
  this.renderer.addClass(this.myself.nativeElement, "app-relative");
810
867
  };
811
- /**
812
- * Gestisce la modifica dell'ordinamento qualora venisse cliccato su questa colonna
813
- */
868
+ /** Gestisce la modifica dell'ordinamento qualora venisse cliccato su questa colonna */
814
869
  EsTh.prototype.setupNextOrderAndNotify = function () {
815
870
  if (!this.ID) {
816
871
  console.log("Attempt to order a column without ID. Operation ignored");
@@ -837,9 +892,7 @@
837
892
  this.resizingThis = true;
838
893
  this.startOffset = this.myself.nativeElement.offsetWidth - ev.pageX;
839
894
  };
840
- /**
841
- * Listener per la fine dell'operazione di resize
842
- */
895
+ /** Listener per la fine dell'operazione di resize */
843
896
  EsTh.prototype.onMouseUp = function () {
844
897
  if (!this.Resizable)
845
898
  return;
@@ -890,9 +943,7 @@
890
943
  onMouseMove: [{ type: core.HostListener, args: ['window:mousemove.out-zone', ['$event'],] }]
891
944
  };
892
945
 
893
- /**
894
- * Direttiva per la dichiarazione snella di un EsTd da emettere per ogni elemento, data una colonna
895
- */
946
+ /** Direttiva per la dichiarazione snella di un EsTd da emettere per ogni elemento, data una colonna */
896
947
  var EsTdDirective = /** @class */ (function () {
897
948
  /**
898
949
  * @ignore
@@ -921,23 +972,31 @@
921
972
  tdClass: [{ type: core.Input }]
922
973
  };
923
974
 
924
- /**
925
- * Direttiva per la dichiarazione snella di un EsTh da emettere come header
926
- */
975
+ /** Direttiva per la dichiarazione snella di un EsTh da emettere come header */
927
976
  var EsThDirective = /** @class */ (function () {
928
977
  /**
929
978
  * @ignore
930
979
  */
931
980
  function EsThDirective(Template) {
932
981
  this.Template = Template;
982
+ /** Variabile interna all'interno della quale viene raccolta la cache delle aggregazioni specificate in thAggregation */
983
+ this._thAggregations = null;
933
984
  /** Variabile interna che indica il fatto che questo componente è una direttiva. Serve per disambigualrlo dell'EsThComponent */
934
985
  this._directive = true;
986
+ /** Variabile interna impostata dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header */
987
+ this._referenced = false;
935
988
  /** Id della colonna, dev'essere lo stesso per tutti i **td** relativi */
936
989
  this.th = "";
990
+ /** Indica se la colonna è pinnata o no */
991
+ this.thPinned = false;
992
+ /** Indica le dimensioni che deve avere questa colonna quando viene pinnata, senza questo tutte le colonne mi collasserebbero l'una sull'altra */
993
+ this.thPinnedWidth = 150;
937
994
  /** Indicazione sulla visibilità della colonna */
938
995
  this.thVisible = true;
939
996
  /** Indica se la colonna è fixed, cioè se non può né essere nascosta, né riposizionata. Solo le prime colonne possono essere Fixed */
940
997
  this.thFixed = false;
998
+ /** Indica che la colonna è sotto ad un raggruppamento padre, con questo nome nel **th** */
999
+ this.thParent = "";
941
1000
  /** Indica se questa colonna è ordinabile o meno */
942
1001
  this.thOrderable = true;
943
1002
  /** Indica se il testo presente in questo Header può andare a capo o meno, di default non può */
@@ -946,12 +1005,10 @@
946
1005
  this.thResizable = false;
947
1006
  /** Equivalente dell'NgIf sul th */
948
1007
  this.thIf = true;
949
- /** @ignore Sperimentale: Indica che bisogna fare un raggruppamento su questa colonna */
1008
+ /** Indica che bisogna fare un raggruppamento su questa colonna */
950
1009
  this.thGroup = false;
951
- /** @ignore Sperimentale: Indica che bisogna fare una aggregazione su questa colonna, a fronte di almeno un altra con un raggruppamento */
1010
+ /** Indica che bisogna fare una aggregazione su questa colonna, a fronte di almeno un altra con un raggruppamento */
952
1011
  this.thAggregation = null;
953
- /** Impostato dall'**EsTable**, per controllare che ci sia almeno un TD che utilizzi quest'header */
954
- this.Referenced = false;
955
1012
  }
956
1013
  return EsThDirective;
957
1014
  }());
@@ -963,8 +1020,11 @@
963
1020
  ]; };
964
1021
  EsThDirective.propDecorators = {
965
1022
  th: [{ type: core.Input }],
1023
+ thPinned: [{ type: core.Input }],
1024
+ thPinnedWidth: [{ type: core.Input }],
966
1025
  thVisible: [{ type: core.Input }],
967
1026
  thFixed: [{ type: core.Input }],
1027
+ thParent: [{ type: core.Input }],
968
1028
  thOrder: [{ type: core.Input }],
969
1029
  thOrderable: [{ type: core.Input }],
970
1030
  thWrap: [{ type: core.Input }],
@@ -976,22 +1036,21 @@
976
1036
  thAggregation: [{ type: core.Input }]
977
1037
  };
978
1038
 
979
- /**
980
- * Token che indica il locale da utilizzare all'interno del componente. Supportati solo "it-IT" ed "en-US"
981
- */
982
- var EST_LOCALE = new core.InjectionToken('EST_LOCALE');
1039
+ /** Token che indica il locale da utilizzare all'interno del componente. Supportati solo "it-IT" ed "en-US" */
1040
+ var EST_LOCALE = new core.InjectionToken('EST_LOCALE');
1041
+ /** Token che indica se emettere log a console o meno */
1042
+ var EST_DEBUG = new core.InjectionToken('EST_DEBUG');
1043
+ /** Token che indica i default da assegnare agli Input */
1044
+ var EST_DEFAULTS = new core.InjectionToken('EST_DEFAULTS');
983
1045
 
984
- /**
985
- * Classe di localizzazione per il componente **EsTableComponent**
986
- */
1046
+ /** Classe di localizzazione per il componente **EsTableComponent** */
987
1047
  var EsTableLoc = /** @class */ (function (_super) {
988
1048
  __extends(EsTableLoc, _super);
989
- /**
990
- * @ignore
991
- */
1049
+ /** @ignore */
992
1050
  function EsTableLoc(LOC_LOCALE) {
993
1051
  var _this = _super.call(this, LOC_LOCALE !== null && LOC_LOCALE !== void 0 ? LOC_LOCALE : 'it-IT') || this;
994
1052
  _super.prototype.set.call(_this, "en->it", "All", ["Tutto"]);
1053
+ _super.prototype.set.call(_this, "en->it", "Groups", ["Gruppi"]);
995
1054
  _super.prototype.set.call(_this, "en->it", "Cannot export an empty dataset", ["Impossibile esportare un dataset vuoto"]);
996
1055
  _super.prototype.set.call(_this, "en->it", "Performing Table bootstrap", ["Sto caricando la Tabella"]);
997
1056
  _super.prototype.set.call(_this, "en->it", "Update every", ["Aggiorna ogni"]);
@@ -1019,12 +1078,22 @@
1019
1078
  { type: String, decorators: [{ type: core.Optional }, { type: core.Inject, args: [EST_LOCALE,] }] }
1020
1079
  ]; };
1021
1080
 
1081
+ /** Raccolta di tutti gli Input dell'EsTable a cui può essere logicamente sensato assegnare default per progetto */
1082
+ var EsTableDefaultable = /** @class */ (function () {
1083
+ function EsTableDefaultable() {
1084
+ }
1085
+ return EsTableDefaultable;
1086
+ }());
1087
+
1022
1088
  /** Componente che permette di rappresentare una griglia di valori */
1023
1089
  var EsTableComponent = /** @class */ (function () {
1024
1090
  /** @ignore */
1025
- function EsTableComponent(ngControl, prefService, lc, cdr, hashExts, utiExts, expExts, dateExts, msgExts) {
1091
+ function EsTableComponent(ngControl, prefService, deafults, locale, lc, cdr, hashExts, utiExts, expExts, dateExts, msgExts) {
1092
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
1026
1093
  this.ngControl = ngControl;
1027
1094
  this.prefService = prefService;
1095
+ this.deafults = deafults;
1096
+ this.locale = locale;
1028
1097
  this.lc = lc;
1029
1098
  this.cdr = cdr;
1030
1099
  this.hashExts = hashExts;
@@ -1036,10 +1105,7 @@
1036
1105
  this.View = null;
1037
1106
  /** Indica se l'es-table deve mostrare il check globale nell'header per fare il "seleziona tutto" */
1038
1107
  this.globalCheck = false;
1039
- /**
1040
- * Tiene da conto l'ultimo elemento selezionato in modo da fare ragionamenti del tipo
1041
- * "Ho selezionato questo, l'ultimo selezionato era **lastSelected**, devo selezionare tutti quelli in mezzo", ad esempio per la selezione multipla
1042
- */
1108
+ /** Tiene da conto l'ultimo elemento selezionato in modo da poter effettuare il SHIFT+CLICK */
1043
1109
  this.lastSelected = null;
1044
1110
  /** Conteggio interno per il numero di elementi selezionati */
1045
1111
  this.selectedObjects = 0;
@@ -1078,6 +1144,10 @@
1078
1144
  this.RowTHs = null;
1079
1145
  /** Modello di appoggio temporaneo per i **RowTHs** */
1080
1146
  this.TMPRowTHs = null;
1147
+ /** Modello di appoggio temporaneo per i **RowThGroups** */
1148
+ this.TMPRowThGroups = null;
1149
+ /** Modello rappresentante un singolo header group della tabella. Questa lista è già ordinata e pronta per essere utilizzata in ngFor */
1150
+ this.RowThGroups = null;
1081
1151
  /** Cache per i routerLink generati nelle tabelle dinamiche */
1082
1152
  this.DynamicTableRouterLinkCache = {};
1083
1153
  /**
@@ -1144,14 +1214,14 @@
1144
1214
  this.UseCustomCells = null;
1145
1215
  /** Permette di impostare l'altezza massima della tabella. Se null la dimensione si adatta al numero di elementi attualmente in visualizzazione */
1146
1216
  this.MaxHeight = null;
1147
- /** Classi da applicare alla tabella oltre a quelle gestite autonomamente dalla libreria */
1148
- this.Class = '';
1217
+ /** Classi da applicare al contenitore della tabella */
1218
+ this.ContainerClass = null;
1149
1219
  /** Permette o meno l'export in formato XLSX */
1150
1220
  this.XLSXExport = null;
1151
1221
  /** Permette o meno l'export in formato CSV */
1152
1222
  this.CSVExport = true;
1153
1223
  /** Permette di visualizzare o meno l'opzione di paginazione "Tutti" */
1154
- this.AllSearch = true;
1224
+ this.AllSearch = null;
1155
1225
  /** 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 */
1156
1226
  this.HighCellDensity = null;
1157
1227
  /** Abilita o meno la possibilità di selezionare oggetti */
@@ -1170,8 +1240,6 @@
1170
1240
  this.Export = null;
1171
1241
  /** Indica se permettere la selezione multipla Windows-like cliccando un oggetto e facendo poi Shift + click su un oggetto successivo */
1172
1242
  this.ShiftClick = null;
1173
- /** Mostra o nasconde le informazioni di paginazione, sia i pulsanti, sia il selettore degli oggetti per pagina */
1174
- this.ShowPaging = true;
1175
1243
  /** Indica se nascondere o mostrare il componente di paginazione */
1176
1244
  this.HidePaging = null;
1177
1245
  /** Indica se nascondere o mostrare il conteggio degli elementi trovati */
@@ -1183,12 +1251,10 @@
1183
1251
  /** Nome dell'esportazione generata da questa tabella */
1184
1252
  this.ExportFileName = 'Export.csv';
1185
1253
  /** Classe (HTML) di default della tabella */
1186
- this.TableClass = 'table table-striped table-hover table-sm';
1187
- /** Testo da visualizzare nel conteggio. Di default: "Oggetti selezionati" */
1188
- this.CountLabel = this.lc.loc('Found objects');
1189
- /** Indica la presenza di raggruppamenti a livello di header */
1254
+ this.TableClass = null;
1255
+ /** @deprecated Indica la presenza di raggruppamenti a livello di header */
1190
1256
  this.HasHeaderGroup = null;
1191
- /** Indica la presenza di raggruppamenti a livello del raggruppamento precedentemente esistente, chiaramente è insensata senza **HasHeaderGroup** */
1257
+ /** @deprecated Indica la presenza di raggruppamenti a livello del raggruppamento precedentemente esistente, chiaramente è insensata senza **HasHeaderGroup** */
1192
1258
  this.HasSecondaryHeaderGroup = null;
1193
1259
  /** Utilizzato per dividere la sorgente in modalità EndlessScroll */
1194
1260
  this.SliceSize = 100;
@@ -1220,11 +1286,7 @@
1220
1286
  this.HiddenColumns = null;
1221
1287
  /** Permette di riordinare le colonne in base alle impostazioni effettuate dal Menù contestuale in alto a destra */
1222
1288
  this.ColumnsOrdering = null;
1223
- /**
1224
- * Eventuale supporto alle ricerche applicate alla modalità Array
1225
- *
1226
- * @deprecated Utilizzato solo per un caso particolare del Metering
1227
- */
1289
+ /** Eventuale supporto alle ricerche applicate alla modalità Array */
1228
1290
  this.SearchView = null;
1229
1291
  /** Abilita o disabilita il sistema che permette di selezionare tutti gli elementi nella vista */
1230
1292
  this.SelectAll = null;
@@ -1244,6 +1306,10 @@
1244
1306
  this.StartsExpanded = true;
1245
1307
  /** Indica se effettuare il salvataggio delle preferenze di ricerca */
1246
1308
  this.SavePreferences = null;
1309
+ /** Indica dove visualizzare le informazioni di paginazione, se sopra, sotto o in entrambi */
1310
+ this.PagingStyle = null;
1311
+ /** Indica dove visualizzare le informazioni di paginazione, se sopra, sotto o in entrambi */
1312
+ this.RowGroupingPagingStyle = null;
1247
1313
  /**
1248
1314
  * Sorgente dati secondaria
1249
1315
  *
@@ -1257,7 +1323,9 @@
1257
1323
  */
1258
1324
  this.TertiarySource = null;
1259
1325
  /** Indica se utilizzare la cache di selezione che permette di mantenere gli stati di selezione dei vari oggetti navigando da una pagina all'altra */
1260
- this.UseSelectionCache = true;
1326
+ this.UseSelectionCache = null;
1327
+ /** Permette di decidere se, in modalità raggruppamento, mostrare o meno il valore delle colonne di gruppo negli oggetti finali. Di default sono nascosti */
1328
+ this.ShowItemGroupsColumns = null;
1261
1329
  /** Evento che viene richiamato al cambio di oridnamento di una colonna */
1262
1330
  this.onOrderChanged = new core.EventEmitter();
1263
1331
  /**
@@ -1290,32 +1358,91 @@
1290
1358
  /** Numero di pagine (durante la paginazione in modalità Array) */
1291
1359
  this.arraymodePages = 1;
1292
1360
  /** Oggetti per ogni pagina (durante la paginazione in modalità Array) */
1293
- this.ArraymodeItemsPerPage = 15;
1361
+ this.ArraymodeItemsPerPage = null;
1362
+ /** Colonne da visualizzare in modalità array */
1363
+ this.arrayColumns = [];
1364
+ /** Ordine delle colonne da visualizzare in modalità array */
1365
+ this.arrayColumnOrdering = [];
1366
+ /** Ordinamenti ASC-DESC sulle colonne in modalità array */
1367
+ this.arrayOrders = [];
1294
1368
  /**
1295
1369
  * Variabile che serve a gestire il momento in cui l'es-table aggiorna la paginazione (pulsanti ecc).
1296
1370
  * Essendo operazioni comunque costose le effettuo solo su binding esterni, non su rewrite generati internamente
1297
1371
  */
1298
1372
  this.internalWriteCall = false;
1299
- /** Cache di selezione Hash - Oggetto */
1300
- this.selOrDeselCache = {};
1301
1373
  /**
1302
- * Variabile d'appoggio per capire se c'è bisogno di ri-effettuare una ricerca o meno
1303
- */
1304
- this.ResearchNeeded = false;
1305
- /**
1306
- * Variabile da usare nei "colspan" quando si vuole dire "Tutte le colonne". 42 è un numero magico che mi serve per non calcolare questa variabile quando mi serve.
1374
+ * Cache che conterrà tutte le ricerche effettuate su gruppi diversi dal primo e su elementi contenuti nei gruppi.
1375
+ * 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:
1376
+ *
1377
+ *
1378
+ * **Cambio ordinamento sul primo gruppo**: reload completo, non mi occupo di ripulire gli elementi bindati in alcun modo
1307
1379
  *
1308
- * 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ì
1380
+ * **Cambio ordinamento sulla colonna relativa all'N-esimo gruppo**: reload completo del contenuto dei gruppi precedenti, ripulendo precedentemente
1381
+ * tutti gli elementi con **_grouplevel** = N
1309
1382
  *
1310
- * Se in una tabella ci sono meno di 42 colonne il colspan si ferma comunque alla fine, se invece ce ne sono di più... beh bisogna allungare sto numero
1383
+ * **Cambio ordinamento su una colonna non raggruppata**: reload completo per tutti i gruppi finali aperti, devo precedentemente ripulire tutti gli elementi con **_item** = true
1311
1384
  *
1385
+ * Altri eventi non dovrebbero rappresentare problemi:
1386
+ * - Selezione: non cambia nulla
1387
+ * - Paginazione: cambia a livello root quindi viene ricaricato tutto comunque, stesso vale per le paginazioni interne
1312
1388
  */
1313
- this.allColumns = "42";
1389
+ this.groupSearchRequestsCache = [];
1390
+ /** Variabile d'appoggio per capire se c'è bisogno di ri-effettuare una ricerca o meno */
1391
+ this.ResearchNeeded = false;
1392
+ /** Colonne visibili della vista attuale. Valorizzato di default al numero massimo di colonne supportate dalla tabella per le casistiche in assenza di custom cells */
1393
+ this.Columns = { Visibile: 100, VisibleUnpinned: 100, Global: 100 };
1394
+ /** In caso di Row Grouping qui viene salvata la vista principale dei gruppi base */
1395
+ this.MainGroupView = null;
1396
+ /** 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" */
1397
+ this.BaseItemsCount = null;
1398
+ /** Cache per salvare per ogni chiave di ogni gruppo chi è il gruppo rappresentato */
1399
+ this.rgGroupCache = new Map();
1400
+ /** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
1401
+ this.rgItemCache = new Map();
1402
+ /** Cache per salvare per ogni chiave di ogni gruppo chi sono gli oggetti sottostanti, non dei sottogruppi */
1403
+ this.rgChildGroupsCache = new Map();
1404
+ /** Cache di selezione Hash - Oggetto per la variabile **items** dell'itemSelector. Facilita le operazioni di lookup via hash*/
1405
+ this.itemsCache = new Map();
1406
+ /** Cache di selezione Hash - Oggetto per la variabile **groups** dell'itemSelector. Facilita le operazioni di lookup via hash */
1407
+ this.groupsCache = new Map();
1408
+ /** Cache di selezione Hash - Oggetto per la variabile **exclusions** dell'itemSelector. Facilita le operazioni di lookup via hash */
1409
+ this.exclusionsCache = new Map();
1410
+ /** Cache di selezione Hash - Oggetto per la variabile **group_exclusions** dell'itemSelector. Facilita le operazioni di lookup via hash */
1411
+ this.group_exclusionsCache = new Map();
1412
+ /** Cache di selezione Hash - Oggetto per la variabile **items** dell'itemSelector. Facilita le operazioni di lookup via indice*/
1413
+ this.i_itemsCache = new Map();
1414
+ /** Cache di selezione Hash - Oggetto per la variabile **groups** dell'itemSelector. Facilita le operazioni di lookup via indice */
1415
+ this.i_groupsCache = new Map();
1416
+ /** Cache di selezione Hash - Oggetto per la variabile **exclusions** dell'itemSelector. Facilita le operazioni di lookup via indice */
1417
+ this.i_exclusionsCache = new Map();
1418
+ /** Cache di selezione Hash - Oggetto per la variabile **group_exclusions** dell'itemSelector. Facilita le operazioni di lookup via indice */
1419
+ this.i_group_exclusionsCache = new Map();
1420
+ /** 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 */
1421
+ this.ArrayGrouping = false;
1422
+ this.PagerOptions = { PagerCount: null, ShowCount: true, ShowPaging: true, UsesView: true, View: null, Ready: false, Searches: 'items' };
1314
1423
  /** @ignore */
1315
1424
  this.propagateChange = function (_) { };
1316
1425
  if (ngControl)
1317
1426
  ngControl.valueAccessor = this;
1427
+ // Assegnazione per tutti gli Input di default
1428
+ this.ColumnsResizable = this.InputOrDefault(this.ColumnsResizable, (_a = this.deafults) === null || _a === void 0 ? void 0 : _a.ColumnsResizable);
1429
+ this.AutoUpdate = this.InputOrDefault(this.AutoUpdate, (_b = this.deafults) === null || _b === void 0 ? void 0 : _b.AutoUpdate);
1430
+ this.AllSearch = this.InputOrDefault(this.AllSearch, (_c = this.deafults) === null || _c === void 0 ? void 0 : _c.AllSearch, true);
1431
+ this.Export = this.InputOrDefault(this.Export, (_d = this.deafults) === null || _d === void 0 ? void 0 : _d.Export);
1432
+ this.HidePaging = this.InputOrDefault(this.HidePaging, (_e = this.deafults) === null || _e === void 0 ? void 0 : _e.HidePaging, false);
1433
+ this.HidePagingCount = this.InputOrDefault(this.HidePagingCount, (_f = this.deafults) === null || _f === void 0 ? void 0 : _f.HidePagingCount);
1434
+ this.HidePagingButtons = this.InputOrDefault(this.HidePagingButtons, (_g = this.deafults) === null || _g === void 0 ? void 0 : _g.HidePagingButtons);
1435
+ this.ContainerClass = this.InputOrDefault(this.ContainerClass, (_h = this.deafults) === null || _h === void 0 ? void 0 : _h.ContainerClass, '');
1436
+ this.TableClass = this.InputOrDefault(this.TableClass, (_j = this.deafults) === null || _j === void 0 ? void 0 : _j.TableClass, 'table table-striped table-hover table-sm');
1437
+ this.Selection = this.InputOrDefault(this.Selection, (_k = this.deafults) === null || _k === void 0 ? void 0 : _k.Selection);
1438
+ this.SavePreferences = this.InputOrDefault(this.SavePreferences, (_l = this.deafults) === null || _l === void 0 ? void 0 : _l.SavePreferences);
1439
+ this.PagingStyle = this.InputOrDefault(this.PagingStyle, (_m = this.deafults) === null || _m === void 0 ? void 0 : _m.PagingStyle, 'bottom');
1440
+ this.RowGroupingPagingStyle = this.InputOrDefault(this.RowGroupingPagingStyle, (_o = this.deafults) === null || _o === void 0 ? void 0 : _o.RowGroupingPagingStyle, 'left');
1441
+ this.UseSelectionCache = this.InputOrDefault(this.UseSelectionCache, (_p = this.deafults) === null || _p === void 0 ? void 0 : _p.UseSelectionCache, true);
1442
+ this.ShowItemGroupsColumns = this.InputOrDefault(this.ShowItemGroupsColumns, (_q = this.deafults) === null || _q === void 0 ? void 0 : _q.ShowItemGroupsColumns, false);
1443
+ this.ArraymodeItemsPerPage = this.InputOrDefault(this.ArraymodeItemsPerPage, (_r = this.deafults) === null || _r === void 0 ? void 0 : _r.ArraymodeItemsPerPage, 15);
1318
1444
  }
1445
+ // #region Ciclo di vita ES-Table - Inizializzazioni
1319
1446
  /** @ignore */
1320
1447
  EsTableComponent.prototype.ngOnInit = function () {
1321
1448
  var _this = this;
@@ -1325,6 +1452,9 @@
1325
1452
  throw "Es-table error: Per poter utilizzare l'es-table con [Hierarchy]=\"true\" è richiesto anche [UseCustomCells]=\"true\"";
1326
1453
  // click destro su una riga con selezione attiva: Tiro fuori il context menu e selezione l'elemento corrente
1327
1454
  this.ctxMenuSubscription = (this.ContextMenu || this.tableEmptyMenu).open.subscribe(function (t) {
1455
+ // Gruppi va bene, oggetti pure, ma separatori fra gruppi proprio no...
1456
+ if (t.item._sep)
1457
+ return;
1328
1458
  var shouldEmit = !t.item._selected;
1329
1459
  t.item._selected = true;
1330
1460
  var itemSelection = _this.handleItemsSelection([t.item]);
@@ -1352,6 +1482,26 @@
1352
1482
  this.ShiftClick = true;
1353
1483
  }
1354
1484
  };
1485
+ /**
1486
+ * 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)
1487
+ *
1488
+ * @param {T} inputValue Valore dell'Input
1489
+ * @param {T} defaultValue Valore di default impostato da configurazione
1490
+ * @param {T} fallbackValue Valore dell'Input per quando non è stato assegnato dal programmatore e non ha un default
1491
+ */
1492
+ EsTableComponent.prototype.InputOrDefault = function (inputValue, defaultValue, fallbackValue) {
1493
+ // Input valorizzato dal programmatore
1494
+ if (inputValue != null && inputValue != undefined)
1495
+ return inputValue;
1496
+ // Input valorizzato da configurazione globale
1497
+ if (defaultValue != null && defaultValue != undefined)
1498
+ return defaultValue;
1499
+ //Input non valorizzato da niente e da nessuno
1500
+ if (fallbackValue != null && fallbackValue != undefined)
1501
+ return fallbackValue;
1502
+ // 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
1503
+ return null;
1504
+ };
1355
1505
  /** @ignore */
1356
1506
  EsTableComponent.prototype.ngOnDestroy = function () {
1357
1507
  if (this.ctxMenuSubscription)
@@ -1361,7 +1511,7 @@
1361
1511
  EsTableComponent.prototype.ngOnChanges = function (changes) {
1362
1512
  return __awaiter(this, void 0, void 0, function () {
1363
1513
  var newSearchView;
1364
- return __generator(this, function (_d) {
1514
+ return __generator(this, function (_s) {
1365
1515
  newSearchView = changes['SearchView'];
1366
1516
  if (newSearchView && this.SearchView)
1367
1517
  this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
@@ -1369,6 +1519,7 @@
1369
1519
  });
1370
1520
  });
1371
1521
  };
1522
+ // #endregion
1372
1523
  // #region Implementazione ControlValueAccessor ignorabile
1373
1524
  /** @ignore */
1374
1525
  EsTableComponent.prototype.registerOnChange = function (fn) { this.propagateChange = fn; };
@@ -1379,6 +1530,7 @@
1379
1530
  // #endregion
1380
1531
  /** @ignore */
1381
1532
  EsTableComponent.prototype.writeValue = function (obj) {
1533
+ var _a;
1382
1534
  this.View = obj ? obj : null;
1383
1535
  // Mi è arrivata l'AppSearch quindi di sicuro non ho una ricerca in progress
1384
1536
  this.researchInProgress = false;
@@ -1411,10 +1563,11 @@
1411
1563
  else if (this.View && this.View instanceof AppSearch) {
1412
1564
  // Se cambia l'oggetto intero significa che ho rimandato la ricerca
1413
1565
  this.setMode('view');
1566
+ var firstItemGroupOrNoGrouping = (((_a = this.View.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) || 0) == 0;
1414
1567
  // Se vengo da una ricerca interna mantengo lo stato di selezione precedente (quindi su cambio pagina, cambio ipp, ecc...)
1415
1568
  // se invece l'utente ha fatto una ricerca lui (quindi cambiando filtri), secco le info di selezione
1416
- if (!this.View.selection || !this.View.internalsearchrequest || !this.UseSelectionCache) {
1417
- this.selOrDeselCache = {};
1569
+ if (!this.View.selection || (!this.View.internalsearchrequest && firstItemGroupOrNoGrouping) || !this.UseSelectionCache) {
1570
+ this.clearSelectionCaches();
1418
1571
  this.View.selection = new ItemsSelection([]);
1419
1572
  this.onSelectionChanged.emit(this.View.selection);
1420
1573
  }
@@ -1433,56 +1586,136 @@
1433
1586
  }
1434
1587
  }
1435
1588
  }
1436
- this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages || 1);
1589
+ // 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)
1590
+ if (firstItemGroupOrNoGrouping)
1591
+ this.arrayPulsanti = this.getPagesArray(6, this.View.page, this.View.pages || 1);
1437
1592
  }
1438
1593
  else if (this.View && (this.View.length != null && this.View.length != undefined)) {
1439
1594
  this.setMode('array');
1440
1595
  if (!this.UseSelectionCache || !this.arraymodeSelection) {
1441
- this.selOrDeselCache = {};
1596
+ this.clearSelectionCaches();
1442
1597
  this.arraymodeSelection = new ItemsSelection([]);
1443
1598
  ;
1444
1599
  this.onSelectionChanged.emit(this.arraymodeSelection);
1445
1600
  }
1601
+ // Recupero Preference
1602
+ if (this.SavePreferences) {
1603
+ if (!this.ngControl.name)
1604
+ console.error("Non posso utilizzare le preference senza avere un 'name' per questa tabella");
1605
+ else if (!this.prefService)
1606
+ console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
1607
+ else {
1608
+ var prefs = this.prefService.retrieve(this.ngControl.name);
1609
+ if (prefs) {
1610
+ this.arrayColumns = prefs.columns;
1611
+ this.arrayColumnOrdering = prefs.column_ordering;
1612
+ }
1613
+ }
1614
+ }
1446
1615
  if (this.SearchView)
1447
1616
  this.arrayPulsanti = this.getPagesArray(6, this.SearchView.page, this.SearchView.pages || 1);
1448
1617
  }
1449
- if (this.View && !(this.View instanceof ReportDefinition)) {
1450
- /*
1451
- *Uso la tecnica di EndlessScroll se la variabile relativa è attiva e se
1452
- * 1) Ho un Array, oppure
1453
- * 2) Ho un AppSearch che sta cercando con paginazione "Tutto", oppure
1454
- * 3) Ho un AppSearch che sta cercando con paginazione diversa da "Tutto" ma con la variabile EndlessScrollOnlyForAll a false
1455
- */
1456
- var viewCasted = this.View;
1457
- var hasRowGroups = viewCasted.groupings && viewCasted.groupings.filter(function (t) { return !t.aggregation; }).length > 0;
1458
- var isAppSearchWithIppMax = this.viewMode && viewCasted.itemsperpageoverride == this.defaultAllPageOverride;
1459
- var isAppSearchNoMaxIpp = this.viewMode && viewCasted.itemsperpageoverride != this.defaultAllPageOverride;
1460
- this.UseEndlessscroll = this.EndlessScroll && (this.arrayMode || isAppSearchWithIppMax || (isAppSearchNoMaxIpp && !this.EndlessScrollOnlyForAll));
1461
- if (this.UseEndlessscroll && !hasRowGroups) {
1462
- this.addedSlices = [];
1463
- this.boundSubSources = this.getItemSlices();
1464
- this.TMPBoundSource = this.boundSubSources[0] ? this.boundSubSources[0] : [];
1465
- if (this.boundSubSources[0])
1466
- this.addedSlices.push(0);
1618
+ if (this.View && !(this.View instanceof ReportDefinition))
1619
+ this.finalizeContext();
1620
+ this.postBoundSourceCalculation();
1621
+ };
1622
+ /**
1623
+ * Successivamente al bind del nuovo input questa funzione si occupa di finalizzare tutti i parametri di funzionamento dell'es-table
1624
+ * in base a Input - Modello, e qualsiasi altra cosa possa servire
1625
+ */
1626
+ EsTableComponent.prototype.finalizeContext = function () {
1627
+ var viewCasted = this.View;
1628
+ /*
1629
+ *Uso la tecnica di EndlessScroll se la variabile relativa è attiva e se
1630
+ * 1) Ho un Array, oppure
1631
+ * 2) Ho un AppSearch che sta cercando con paginazione "Tutto", oppure
1632
+ * 3) Ho un AppSearch che sta cercando con paginazione diversa da "Tutto" ma con la variabile EndlessScrollOnlyForAll a false
1633
+ */
1634
+ var isAppSearchWithIppMax = this.viewMode && viewCasted.itemsperpageoverride == this.defaultAllPageOverride;
1635
+ var isAppSearchNoMaxIpp = this.viewMode && viewCasted.itemsperpageoverride != this.defaultAllPageOverride;
1636
+ this.UseEndlessscroll = this.EndlessScroll && (this.arrayMode || isAppSearchWithIppMax || (isAppSearchNoMaxIpp && !this.EndlessScrollOnlyForAll));
1637
+ var hasRowGroups = (viewCasted.groupings && viewCasted.groupings.filter(function (t) { return !t.aggregation; }).length > 0) || (this.arrayMode && this.EsThsDirective.some(function (t) { return t.thGroup; }));
1638
+ // Se ho dei gruppi in modalità array devo sistemare un po' di variabili che diventano insensate
1639
+ if (this.arrayMode) {
1640
+ if (hasRowGroups)
1641
+ this.UseArrayModePaging = false;
1642
+ }
1643
+ // Riempimento della TMPBoundSource con gli oggetti che verranno poi mostrati ad interfaccia
1644
+ if (this.UseEndlessscroll && !hasRowGroups) {
1645
+ this.addedSlices = [];
1646
+ this.boundSubSources = this.getItemSlices();
1647
+ var firstSub = this.boundSubSources[0];
1648
+ this.TMPBoundSource = firstSub ? firstSub : [];
1649
+ if (firstSub)
1650
+ this.addedSlices.push(0);
1651
+ }
1652
+ else
1653
+ this.TMPBoundSource = this.getItemsByMode(false, !this.internalWriteCall);
1654
+ // Se ho una gerarchia, assegno i livelli gerarchici alla TMPBoundSource
1655
+ if (this.Hierarchy && !hasRowGroups)
1656
+ this.assignHierarchyLevels(this.TMPBoundSource);
1657
+ // L'hashing degli oggetti lo faccio a prescindere
1658
+ this.calculateHash(this.TMPBoundSource);
1659
+ // Assegno a una variabile mia l'eventuale override per la classe della riga
1660
+ // Se poi sono in modalità gerarchica inietto anche la classe per la configurazione del livello della riga
1661
+ if ((this.TMPBoundSource && this.RowClassAssigner) || this.Hierarchy) {
1662
+ for (var i = 0; i < this.TMPBoundSource.length; i++) {
1663
+ var item = this.TMPBoundSource[i];
1664
+ item._rowClass = this.RowClassAssigner ? this.RowClassAssigner(item) : "";
1665
+ item._rowClass += this.Hierarchy ? " est-row-lvl-" + item._level : "";
1467
1666
  }
1468
- else
1469
- this.TMPBoundSource = this.getItemsByMode(false, !this.internalWriteCall);
1470
- if (this.Hierarchy && !hasRowGroups)
1471
- this.assignHierarchyLevels(this.TMPBoundSource);
1472
- this.calculateHash(this.TMPBoundSource);
1473
- // Assegno a una variabile mia l'eventuale override per la classe della riga
1474
- // Se poi sono in modalità gerarchica inietto anche la classe per la configurazione del livello della riga
1475
- if ((this.TMPBoundSource && this.RowClassAssigner) || this.Hierarchy) {
1476
- for (var i = 0; i < this.TMPBoundSource.length; i++) {
1477
- var item = this.TMPBoundSource[i];
1478
- item._rowClass = this.RowClassAssigner ? this.RowClassAssigner(item) : "";
1479
- item._rowClass += this.Hierarchy ? " est-row-lvl-" + item.level : "";
1480
- }
1667
+ }
1668
+ };
1669
+ /** Genera le informzioni di paginazione per la vista globale dell'es-table */
1670
+ EsTableComponent.prototype.setupPagingInformations = function () {
1671
+ this.PagerOptions.ShowCount = !this.HidePagingCount;
1672
+ if (this.arrayMode && this.UseArrayModePaging && !this.SearchView) {
1673
+ this.PagerOptions.PagerCount = this.View.length || 0;
1674
+ this.PagerOptions.ShowPaging = !this.HidePaging && this.View.length > 10;
1675
+ this.PagerOptions.View = this.View;
1676
+ this.PagerOptions.UsesView = false;
1677
+ }
1678
+ else if (this.arrayMode && (!this.UseArrayModePaging || this.SearchView)) {
1679
+ if (this.SearchView) {
1680
+ this.PagerOptions.View = this.SearchView;
1681
+ this.PagerOptions.PagerCount = this.SearchView.objectcount || 0;
1481
1682
  }
1683
+ else
1684
+ this.PagerOptions.PagerCount = this.View.length || 0;
1685
+ this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (this.View && this.View.length) || (this.SearchView && this.SearchView.objectcount && this.SearchView.objectcount != -1);
1686
+ }
1687
+ else if (this.viewMode) {
1688
+ var tmpView = this.MainGroupView || this.View;
1689
+ var count = (tmpView === null || tmpView === void 0 ? void 0 : tmpView.groupcount) || (tmpView === null || tmpView === void 0 ? void 0 : tmpView.objectcount);
1690
+ 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';
1691
+ this.PagerOptions.PagerCount = count || 0;
1692
+ this.PagerOptions.View = tmpView;
1693
+ this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (tmpView && count && count != -1);
1694
+ this.PagerOptions.ShowPaging = !this.HidePaging;
1695
+ }
1696
+ else if (this.reportMode) {
1697
+ var rvc = this.ReportValues.count;
1698
+ this.PagerOptions.View = this.View;
1699
+ this.PagerOptions.PagerCount = rvc && rvc == -1 ? this.ReportValues.rows.length : rvc && rvc > 0 ? this.ReportValues.count : 0;
1700
+ this.PagerOptions.ShowCount = this.PagerOptions.ShowCount || (this.View && this.View.objectcount && this.View.objectcount != -1);
1701
+ this.PagerOptions.ShowPaging = !this.HidePaging && this.View.pagingavailable;
1482
1702
  }
1483
- this.postBoundSourceCalculation();
1484
1703
  };
1485
- // #region Gestione retrieve degli oggetti da mostrare in tabella, considerando eventuali Endless Scrolls
1704
+ /**
1705
+ * Ripulisce le cache di selezione
1706
+ *
1707
+ * @todo: SELECTION
1708
+ */
1709
+ EsTableComponent.prototype.clearSelectionCaches = function () {
1710
+ this.itemsCache.clear();
1711
+ this.groupsCache.clear();
1712
+ this.exclusionsCache.clear();
1713
+ this.group_exclusionsCache.clear();
1714
+ this.i_itemsCache.clear();
1715
+ this.i_groupsCache.clear();
1716
+ this.i_exclusionsCache.clear();
1717
+ this.i_group_exclusionsCache.clear();
1718
+ };
1486
1719
  /**
1487
1720
  * In base alla modalità specificata (ArrayMode, ViewMode, ecc...) questo metodo recupera l'array di oggetti da bindare ad interfaccia
1488
1721
  *
@@ -1491,6 +1724,8 @@
1491
1724
  * @param {boolean} allIfPossible [false] Indica se prendere tutti gli oggetti quaora possibile, usato solo in ArrayMode
1492
1725
  *
1493
1726
  * @returns {any[]} Lista degli oggetti su cui effettuare il bind lato interfaccia
1727
+ *
1728
+ * @todo: ITEMS
1494
1729
  */
1495
1730
  EsTableComponent.prototype.getItemsByMode = function (onlyselected, refreshPaging, allIfPossible) {
1496
1731
  if (onlyselected === void 0) { onlyselected = false; }
@@ -1501,6 +1736,8 @@
1501
1736
  items = this.getViewItemsBySource();
1502
1737
  }
1503
1738
  else if (this.arrayMode) {
1739
+ this.View.forEach(function (itm) { itm._item = true; });
1740
+ // Se faccio dei raggruppamenti ignoro la paginazione
1504
1741
  if (this.UseArrayModePaging && !allIfPossible) {
1505
1742
  // Se sono in modalità array ma la ricerca dipende da una view devo riallineare gli itemperpage
1506
1743
  if (this.SearchView)
@@ -1519,16 +1756,25 @@
1519
1756
  return items.filter(function (t) { return t._selected; });
1520
1757
  return items;
1521
1758
  };
1522
- /** @ignore */
1759
+ /**
1760
+ * @ignore
1761
+ *
1762
+ * @todo: ITEMS
1763
+ */
1523
1764
  EsTableComponent.prototype.getViewItemsBySource = function () {
1765
+ var _this = this;
1524
1766
  var _a, _b;
1525
1767
  var castedView = this.View;
1526
1768
  var groupKeys = castedView.groupings ? castedView.groupings.filter(function (t) { return !t.aggregation; }).length : 0;
1527
1769
  //Gruppi intermedi
1528
1770
  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) {
1529
1771
  var ret = castedView.groups;
1530
- // Setto variabile interna per capire che questo è in realtà un gruppo
1531
- ret.forEach(function (itm) { itm._group = true; });
1772
+ ret.forEach(function (itm) {
1773
+ // Setto variabile interna per capire che questo è in realtà un gruppo
1774
+ itm._group = true;
1775
+ // Le informazioni passate come lista le metto dentro a una cache per velocizzarne l'accesso quando devo tirare fuori il display della proprietà
1776
+ _this.cacheAggregations(itm);
1777
+ });
1532
1778
  return ret;
1533
1779
  }
1534
1780
  else {
@@ -1538,10 +1784,31 @@
1538
1784
  return ret;
1539
1785
  }
1540
1786
  };
1787
+ /**
1788
+ * Helper per effettuare il caching delle aggregazioni. Le sposta da una lista di **GroupAggregation** a una **<Map<string, Map<string, string>>**
1789
+ *
1790
+ * @todo: ROWGROUPING
1791
+ */
1792
+ EsTableComponent.prototype.cacheAggregations = function (group) {
1793
+ group._aggregationsCache = new Map();
1794
+ var castedAgCache = group._aggregationsCache;
1795
+ for (var i = 0; i < group.aggregations.length; i++) {
1796
+ var agg = group.aggregations[i];
1797
+ if (castedAgCache.has(agg.column))
1798
+ castedAgCache.get(agg.column).set(agg.aggregation, agg.value);
1799
+ else {
1800
+ var tmp = new Map();
1801
+ tmp.set(agg.aggregation, agg.value);
1802
+ castedAgCache.set(agg.column, tmp);
1803
+ }
1804
+ }
1805
+ };
1541
1806
  /**
1542
1807
  * Metodo che prende tutti gli oggetti di cui dispone divisi in bucket da 100 elementi
1543
1808
  *
1544
1809
  * @returns {any[][]} Matrice di array Nx100
1810
+ *
1811
+ * @todo: ITEMS
1545
1812
  */
1546
1813
  EsTableComponent.prototype.getItemSlices = function () {
1547
1814
  // Se sono qui di sicuro non ho rowgrouping
@@ -1579,8 +1846,6 @@
1579
1846
  }
1580
1847
  }
1581
1848
  };
1582
- // #endregion
1583
- // #region Gestione di tutto il ciclo di vita post binding oggetti
1584
1849
  /**
1585
1850
  * Metodo lanciato dopo che la sorgente dati è stata correttamente bindata, si occupa di ricalcolare tutto ciò che serve
1586
1851
  * all'es-table per renderizzare i valori da mostrare
@@ -1591,70 +1856,329 @@
1591
1856
  this.RowContexts = [];
1592
1857
  this.OrderDirectives = [];
1593
1858
  this.lastSelectedItemID = null;
1594
- // Set timeout e basta funzionerebbe per la modalità JIT, ma per AOT servono sia quello che detectChanges
1595
- this.cdr.detectChanges();
1596
- setTimeout(function () {
1597
- // Se non ho colonne dinamiche ma sono in modalità dinamica (lo capisco perché c'è una view piena di genericitem) metto il default delle colonne
1598
- _this.eventuallyReviewDynamicColumns();
1599
- _this.bindDisplayToLoadedItemsOrGroups();
1600
- // Molte cose sono ovviamente disponibili solo in modalità View
1601
- if (_this.viewMode && _this.UseCustomCells) {
1602
- var view = _this.View;
1603
- var ths = _this.EsThs && _this.EsThs.length > 0 ? _this.EsThs.toArray() : _this.EsThsDirective && _this.EsThsDirective.length > 0 ? _this.EsThsDirective.toArray() : [];
1604
- var tds = _this.EsTds && _this.EsTds.length > 0 ? _this.EsTds.toArray() : _this.EsTdsDirective && _this.EsTdsDirective.length > 0 ? _this.EsTdsDirective.toArray() : [];
1605
- // N.B: Rispettare l'ordine di queste 3 macrocategorie è VITALE
1606
- // ************************************* Sistemazioni di TH, TD, e visibilità varie *************************************
1607
- _this.alignColumnsIfLoadedView(view); // Se sto caricando una View da hotpotato (quindi con savedstate = true) riallineo la visibilità delle colonne e il loro ordine.
1608
- _this.refreshColumnsVisibility(ths, tds, view); // Lavoro sui TH ed eventualmente modifico la visibilità anche dei TD.
1609
- _this.alignHeadersOrdering(ths, view); // Allineo gli ordinamenti agli header
1610
- _this.reviewColumnsList(ths); // Aggiorna la lista delle colonne da mostrare nella dialog per ordinamento ecc
1611
- // ************************************* Generazione binding per righe e colonne *************************************
1612
- _this.evaluateRowThs(ths); // Raccolgo i TH
1613
- _this.evaluateRowTds(ths, tds); // Raccolgo i TD in contesti separati, un contesto per ogni item o gruppo
1614
- // ************************************* Ultimi aggiustmaenti dei binding *************************************
1615
- _this.generateDefaultOrder(view); // Genero le direttive di ordinamento, che siano default o derivanti dalla AppSearch
1616
- _this.applyOrdering(view, true); // Applico l'ordinamento sulle colonne (non ASC DESC, ma "prima questa o quella colonna")
1617
- _this.MoveTemporaryVariablesToRealOnes(); // Collego TH e TD aggiustati fino ad ora alle variabili di Binding HTML
1618
- _this.evaluateSelection(view.items, view.selection); // Riallineo le info di selezione degli elementi della View
1619
- if (_this.ResearchNeeded) {
1620
- _this.changed();
1621
- _this.emitSearchRequest(false);
1622
- _this.ResearchNeeded = false;
1623
- }
1859
+ if (this.EsThsDirective && this.EsThsDirective.length > 0 && this.EsTdsDirective && this.EsTdsDirective.length > 0)
1860
+ this.internalPostBoundSource();
1861
+ else {
1862
+ this.cdr.detectChanges();
1863
+ setTimeout(function () { _this.internalPostBoundSource(); });
1864
+ }
1865
+ };
1866
+ /**
1867
+ * 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
1868
+ */
1869
+ EsTableComponent.prototype.internalPostBoundSource = function () {
1870
+ var View = this.View;
1871
+ var ths = this.EsThs && this.EsThs.length > 0 ? this.EsThs.toArray() : this.EsThsDirective && this.EsThsDirective.length > 0 ? this.EsThsDirective.toArray() : [];
1872
+ var tds = this.EsTds && this.EsTds.length > 0 ? this.EsTds.toArray() : this.EsTdsDirective && this.EsTdsDirective.length > 0 ? this.EsTdsDirective.toArray() : [];
1873
+ // Se non ho colonne dinamiche ma sono in modalità dinamica (lo capisco perché c'è una view piena di genericitem) metto il default delle colonne
1874
+ this.eventuallyReviewDynamicColumns();
1875
+ this.bindDisplayToLoadedItemsOrGroups(View);
1876
+ // Questo dev'essere per forza lanciato dopo **bindDisplayToLoadedItemsOrGroups** dato che è lì che alcune cose vengono valorizzate
1877
+ this.setupPagingInformations();
1878
+ // Molte cose sono ovviamente disponibili solo in modalità View
1879
+ if ((this.viewMode || this.arrayMode) && this.UseCustomCells) {
1880
+ var view = this.viewMode ? View : null;
1881
+ var itemsAndGroups = this.viewMode ? __spread((view.items || []), (view.groups || [])) : View;
1882
+ var si = this.viewMode ? view.selection : this.arraymodeSelection;
1883
+ // N.B: Rispettare l'ordine di queste 3 macrocategorie è VITALE
1884
+ // ************************************* Sistemazioni di TH, TD, e visibilità varie *************************************
1885
+ var hI = this.evaluateHeadersGroupingInfos(ths); // Prepassaggio per tirare fuori tutte le info utili sugli headers in modo da non ricacolarseli sempre dopo
1886
+ if (this.arrayMode) { // In modalità array non ho un backend...
1887
+ this.arrayModeReviewOrderings(); // ... quindi gli ordinamenti li devo fare lato client, e ...
1888
+ this.arrayModeReviewGroupings(hI.leafs); // ... i raggruppamenti li devo fare lato client
1624
1889
  }
1625
- else if (_this.viewMode && !_this.UseCustomCells) {
1626
- // Riallineo le info di selezione degli elementi della View
1627
- var view = _this.View;
1628
- _this.evaluateSelection(view.items, view.selection);
1890
+ this.reviewColumnsList(hI.leafs); // Aggiorna la lista delle colonne da mostrare nella dialog per ordinamento ecc
1891
+ 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)
1892
+ this.alignHeadersOrdering(hI.leafs, view); // Allineo gli ordinamenti agli header
1893
+ this.alignColumnsIfLoadedView(view); // Se sto caricando una View da hotpotato (quindi con savedstate = true) riallineo la visibilità delle colonne e il loro ordine.
1894
+ this.refreshColumnsVisibility(hI.leafs, tds, view); // Lavoro sui TH ed eventualmente modifico la visibilità anche dei TD.
1895
+ this.evaluatePinnedColumnsWidth(); // Se sono presenti colonne pinnate valuta la dimensione del contenitore
1896
+ this.generateDefaultOrder(hI.leafs, view); // Genero le direttive di ordinamento, che siano default o derivanti dalla AppSearch
1897
+ this.evaluateHeaderGroups(hI); // Valuto i raggruppamenti degli header se presenti
1898
+ // ************************************* Generazione binding per righe e colonne *************************************
1899
+ this.evaluateRowThs(hI.leafs); // Raccolgo i TH
1900
+ this.evaluateRowTds(hI.leafs, tds); // Raccolgo i TD in contesti separati, un contesto per ogni item o gruppo
1901
+ // ************************************* Ultimi aggiustmaenti dei binding *************************************
1902
+ this.applyOrdering(view, true); // Applico l'ordinamento sulle colonne (non ASC DESC, ma "prima questa o quella colonna")
1903
+ this.MoveTemporaryVariablesToRealOnes(); // Collego TH e TD aggiustati fino ad ora alle variabili di Binding HTML
1904
+ this.evaluateSelection(itemsAndGroups, si); // Riallineo le info di selezione degli elementi della View
1905
+ if (this.ResearchNeeded) {
1906
+ this.changed();
1907
+ this.emitSearchRequest(false);
1908
+ this.ResearchNeeded = false;
1629
1909
  }
1630
- else if (_this.arrayMode)
1631
- _this.arrayModeEvaluateSelection(_this.View);
1632
- // Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
1633
- _this.cdr.markForCheck();
1634
- _this.FirstBind = false;
1635
- });
1910
+ }
1911
+ else if ((this.viewMode || this.arrayMode) && !this.UseCustomCells) {
1912
+ // Riallineo le info di selezione degli elementi della View
1913
+ var items = this.viewMode ? View.items : View;
1914
+ var si = this.viewMode ? View.selection : this.arraymodeSelection;
1915
+ this.evaluateSelection(items, si);
1916
+ }
1917
+ // Per essere sicuro che dopo un bind di oggetti la es-table aggiorni la grafica
1918
+ this.cdr.markForCheck();
1919
+ this.FirstBind = false;
1636
1920
  };
1637
- EsTableComponent.prototype.bindDisplayToLoadedItemsOrGroups = function () {
1638
- var _d;
1639
- var _a, _b, _c;
1640
- if (this.TMPBoundSource.length == 0)
1921
+ /**
1922
+ * Se in modalità array applica gli ordinamenti ASC-DESC delle colonne
1923
+ *
1924
+ * @todo: INTERNALDB
1925
+ */
1926
+ EsTableComponent.prototype.arrayModeReviewOrderings = function () {
1927
+ var _this = this;
1928
+ if (this.arrayOrders.length > 0)
1929
+ this.arrayOrders.forEach(function (t) {
1930
+ _this.boundSource = _this.boundSource.sort(function (a, b) { return (a[t.id] > b[t.id] ? 1 : -1) * (t.order == 'DESC' ? -1 : 1); });
1931
+ });
1932
+ };
1933
+ /**
1934
+ * Se in modalità array applica i raggruppamenti definiti lato row-grouping
1935
+ *
1936
+ * @param {ths: EsTh[] | EsThDirective[]} ths Header
1937
+ *
1938
+ * @todo: ROW GROUPING
1939
+ */
1940
+ EsTableComponent.prototype.arrayModeReviewGroupings = function (ths) {
1941
+ if (ths.length == 0)
1942
+ return;
1943
+ if (this.isEsTh(ths[0]))
1944
+ return;
1945
+ var headerGroups = [];
1946
+ var headerAggregations = [];
1947
+ for (var i = 0; i < ths.length; i++) {
1948
+ var th = ths[i];
1949
+ if (th.thGroup)
1950
+ headerGroups.push(new Group(th.th, 0, ""));
1951
+ else if (th.thAggregation)
1952
+ headerAggregations = __spread(headerAggregations, this.getGroupAggregations(th));
1953
+ }
1954
+ if (headerGroups.length > 0) {
1955
+ // Pulizia delle cache
1956
+ this.rgGroupCache.clear();
1957
+ this.rgItemCache.clear();
1958
+ this.rgChildGroupsCache.clear();
1959
+ this.ArrayGrouping = true;
1960
+ this.boundSource = this.getGroupsRecursive(headerGroups, 0, this.boundSource, headerAggregations, null);
1961
+ }
1962
+ };
1963
+ /**
1964
+ * Data la definizione dei gruppi da generare da una lista di oggetti, suddivide gli oggetti passati in gruppi e sottogruppi
1965
+ *
1966
+ * @param {Group[]} grps Definizione dei gruppi
1967
+ * @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
1968
+ * elaborare i sottogruppi, e così via ricorsivamente...
1969
+ * @param {any[]} items Oggetti da raggruppare
1970
+ * @param {GroupOrAggregation[]} aggregations Info di aggregazione
1971
+ * @param {any} parent Riferimento al gruppo padre
1972
+ *
1973
+ * @todo: INTERNALDB
1974
+ */
1975
+ EsTableComponent.prototype.getGroupsRecursive = function (grps, currentIndex, items, aggregations, parent) {
1976
+ // Se l'indice è 0 devo sicuramente nascondere tutti gli oggetti. Solo i gruppi saranno visualizzati
1977
+ if (currentIndex == 0)
1978
+ items.forEach(function (i) { return i._visible = false; });
1979
+ var grp = grps[currentIndex];
1980
+ var ret = [];
1981
+ var last = grps.length == currentIndex + 1;
1982
+ var groups = this.groupBy(items, grp.column);
1983
+ var _loop_1 = function (prop) {
1984
+ var itms = groups[prop];
1985
+ var gp = new Group(grp.column, itms.length, prop);
1986
+ gp.aggregations = this_1.generateAggregations(itms, aggregations);
1987
+ var anygp = gp;
1988
+ anygp._group = true;
1989
+ anygp._expanded = false;
1990
+ if (!parent) {
1991
+ anygp._thisRoute = [{ column: gp.column, value: gp.value }];
1992
+ anygp._thisKey = gp.value;
1993
+ anygp._grouplevel = 0;
1994
+ }
1995
+ else {
1996
+ anygp._parent = parent._thisKey;
1997
+ anygp._parentRoute = parent._thisRoute;
1998
+ anygp._thisRoute = __spread(parent._thisRoute, [{ column: gp.column, value: gp.value }]);
1999
+ anygp._thisKey = parent._thisKey + gp.value;
2000
+ anygp._grouplevel = parent._grouplevel + 1;
2001
+ }
2002
+ // Pusho il gruppo, tutti i gruppi del livello sotto, o gli item se io sono l'ultimo gruppo.
2003
+ // La visibilità è solo per il gruppo a livello 0, tutti gli altri gruppi saranno mostrati o nascosti di conseguenza
2004
+ if (currentIndex == 0)
2005
+ anygp._visible = true;
2006
+ this_1.calculateHash([anygp]);
2007
+ this_1.cacheAggregations(anygp);
2008
+ // Aggiungo il gruppo padre
2009
+ ret.push(anygp);
2010
+ this_1.rgGroupCache.set(anygp._thisKey, anygp);
2011
+ if (!last) {
2012
+ //Dal gruppo padre, se non è l'ultimo gruppo della catena, calcolo ricorsivamente tutta la catena sotto
2013
+ var subGroupsAndItems = this_1.getGroupsRecursive(grps, currentIndex + 1, itms, aggregations, anygp);
2014
+ var childgroups = subGroupsAndItems.filter(function (t) { return t._group && t._parent == anygp._thisKey; });
2015
+ anygp._groupscount = childgroups.length;
2016
+ // Aggiungo la catena del gruppo sotto, aggiungendo alla cache solo i gruppi padre
2017
+ ret.push.apply(ret, __spread(subGroupsAndItems));
2018
+ this_1.rgChildGroupsCache.set(anygp._thisKey, childgroups);
2019
+ }
2020
+ else {
2021
+ // Al gruppo padre, se è l'ultimo assegno tutte le foglie assegnandogli anche la chiave del gruppo
2022
+ itms.forEach(function (i) { return i._thisKey = anygp._thisKey; });
2023
+ ret.push.apply(ret, __spread(itms));
2024
+ this_1.rgItemCache.set(anygp._thisKey, itms);
2025
+ }
2026
+ };
2027
+ var this_1 = this;
2028
+ for (var prop in groups) {
2029
+ _loop_1(prop);
2030
+ }
2031
+ return ret;
2032
+ };
2033
+ /**
2034
+ * Data una lista di oggetti genera le aggregazioni specificate. Si considera di avere tutti gli oggetti
2035
+ *
2036
+ * @param {any[]} items Oggetti di cui calcolare le aggregazione
2037
+ * @param {GroupOrAggregation[]} aggregations Aggergazioni da generare
2038
+ *
2039
+ * @todo: INTERNALDB
2040
+ */
2041
+ EsTableComponent.prototype.generateAggregations = function (items, aggregations) {
2042
+ var rets = [];
2043
+ var aggregationValue = "", feField = null, stringAgg = null, dateAgg = null, numberAgg = null;
2044
+ for (var i = 0; i < aggregations.length; i++) {
2045
+ var agg = aggregations[i];
2046
+ feField = agg.column;
2047
+ if (!feField)
2048
+ continue;
2049
+ switch (agg.datatype) {
2050
+ case 'string':
2051
+ stringAgg = items.map(function (i) { return i[feField].toString(); });
2052
+ break;
2053
+ case 'date':
2054
+ dateAgg = items.map(function (i) { return new Date(i[feField]).getTime(); });
2055
+ break;
2056
+ case 'number':
2057
+ numberAgg = items.map(function (i) { return parseFloat(i[feField]); });
2058
+ break;
2059
+ }
2060
+ switch (agg.aggregation) {
2061
+ case 'max':
2062
+ switch (agg.datatype) {
2063
+ case 'string':
2064
+ aggregationValue = stringAgg.sort().reverse()[0];
2065
+ break;
2066
+ case 'date':
2067
+ aggregationValue = new Date(Math.max.apply(Math, __spread(dateAgg))).toString();
2068
+ break;
2069
+ case 'number':
2070
+ aggregationValue = Math.max.apply(Math, __spread(numberAgg)).toString();
2071
+ break;
2072
+ }
2073
+ break;
2074
+ case 'min':
2075
+ switch (agg.datatype) {
2076
+ case 'string':
2077
+ aggregationValue = stringAgg.sort()[0];
2078
+ break;
2079
+ case 'date':
2080
+ aggregationValue = new Date(Math.min.apply(Math, __spread(dateAgg))).toString();
2081
+ break;
2082
+ case 'number':
2083
+ aggregationValue = Math.min.apply(Math, __spread(numberAgg)).toString();
2084
+ break;
2085
+ }
2086
+ break;
2087
+ case 'sum':
2088
+ switch (agg.datatype) {
2089
+ case 'string':
2090
+ aggregationValue = stringAgg.join(", ");
2091
+ break;
2092
+ case 'date':
2093
+ aggregationValue = "";
2094
+ break;
2095
+ case 'number':
2096
+ aggregationValue = numberAgg.reduce(function (pre, curr) { return pre + curr; }, 0).toString();
2097
+ break;
2098
+ }
2099
+ break;
2100
+ }
2101
+ rets.push(new GroupAggregation(agg.column, agg.aggregation, aggregationValue));
2102
+ }
2103
+ return rets;
2104
+ };
2105
+ /**
2106
+ * Data una lista di oggetti effettua dei raggruppamenti in base alla proprietà **field**, restituendo un oggetto del tipo { Gruppo1: oggetti[], Gruppo2: oggetti[], ecc... }
2107
+ *
2108
+ * @param {any[]} array Lista degli oggetti da raggruppare
2109
+ * @param {string} field Campo su cui effettuare i raggruppamenti
2110
+ *
2111
+ * @returns {{ [id: string]: any[] }} Dizionario dei gruppi
2112
+ *
2113
+ * @todo: INTERNALDB
2114
+ */
2115
+ EsTableComponent.prototype.groupBy = function (array, field) {
2116
+ var ret = {};
2117
+ for (var i = 0; i < array.length; i++) {
2118
+ var x = array[i];
2119
+ (ret[x[field]] = ret[x[field]] || []).push(x);
2120
+ }
2121
+ return ret;
2122
+ };
2123
+ ;
2124
+ /**
2125
+ * Effettua il binding degli oggetti pervenuti da questa chiamata con gli oggetti effettivamente da graficare
2126
+ *
2127
+ * @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**
2128
+ */
2129
+ EsTableComponent.prototype.bindDisplayToLoadedItemsOrGroups = function (view) {
2130
+ var _a, _b;
2131
+ if (this.TMPBoundSource.length == 0) {
2132
+ this.BaseItemsCount = 0;
1641
2133
  return;
2134
+ }
1642
2135
  if (this.arrayMode || !this.UseCustomCells) {
1643
2136
  this.boundSource = this.TMPBoundSource;
2137
+ this.BaseItemsCount = (view === null || view === void 0 ? void 0 : view.objectcount) || view.length;
1644
2138
  return;
1645
2139
  }
1646
- var view = this.View;
1647
2140
  var groupingKeys = ((_b = (_a = view.groupings) === null || _a === void 0 ? void 0 : _a.filter(function (t) { return !t.aggregation; })) === null || _b === void 0 ? void 0 : _b.length) || 0;
1648
2141
  if (groupingKeys == 0) {
1649
2142
  this.boundSource = this.TMPBoundSource;
2143
+ this.BaseItemsCount = view.objectcount;
1650
2144
  return;
1651
2145
  }
2146
+ this.handleNewDataOnRowGrouping(view, groupingKeys);
2147
+ };
2148
+ /**
2149
+ * In modalità rowgrouping quando mi arriva un nuovo blocco di oggetti devo aggiungerlo alla vista attuale:
2150
+ *
2151
+ * 1) Se non viene richiesto il dettaglio di alcun gruppo significa che devo considerare mi siano arrivati tutti i gruppi principali
2152
+ * 2) Se viene richiesto il dettaglio di un gruppo diverso dall'ultimo devo aggiungere dopo al gruppo cliccato la lista dei sottogruppi
2153
+ * 2) Se viene richiesto il dettaglio dell'ultimo gruppo devo aggiungere dopo al gruppo cliccato la lista degli oggetti
2154
+ *
2155
+ * @param {any} view AppSearch<T> da cui sono arrivati gli oggetti
2156
+ * @param {number} groupingKeys Livelli di raggruppamento da aspettarsi sui dati
2157
+ *
2158
+ * @todo: ROWGROUPING
2159
+ */
2160
+ EsTableComponent.prototype.handleNewDataOnRowGrouping = function (view, groupingKeys) {
2161
+ var e_1, _s, e_2, _t, _u;
2162
+ var _this = this;
2163
+ var _a, _b;
1652
2164
  // 1) Se non viene richiesto il dettaglio di alcun gruppo significa che la chiamata restituisce la lista paginata dei gruppi principali.
1653
2165
  // Li tratto come se fosse una qualsiasi altra query paginata su N elementi
1654
- if ((((_c = view.requestedgroups) === null || _c === void 0 ? void 0 : _c.length) || 0) == 0) {
2166
+ if ((((_a = view.requestedgroups) === null || _a === void 0 ? void 0 : _a.length) || 0) == 0) {
1655
2167
  this.boundSource = this.TMPBoundSource;
2168
+ this.rgGroupCache = new Map();
2169
+ this.rgItemCache = new Map();
2170
+ this.rgChildGroupsCache = new Map();
2171
+ this.TMPBoundSource.forEach(function (itm) {
2172
+ itm._thisRoute = itm._group ? [{ column: itm.column, value: itm.value }] : [];
2173
+ itm._thisKey = itm._group ? itm.value : null;
2174
+ itm._grouplevel = 0;
2175
+ _this.rgGroupCache.set(itm._thisKey, itm);
2176
+ });
1656
2177
  // Resetto la ricerca alla cache di questa "sessione"
1657
- this.groupSearchRequestsCache = [{ path: '', view: view }];
2178
+ var firstItem = this.TMPBoundSource[0];
2179
+ this.MainGroupView = Object.assign({}, view);
2180
+ this.groupSearchRequestsCache = [{ path: '', route: [{ column: firstItem.column, value: firstItem.value }], view: this.MainGroupView, group_column: this.TMPBoundSource[0].column }];
2181
+ this.BaseItemsCount = view.objectcount;
1658
2182
  }
1659
2183
  else {
1660
2184
  // 2) Se viene richiesto il dettaglio di un qualsiasi gruppo diverso dall'ultimo vuol dire che devo aggiungere
@@ -1688,7 +2212,7 @@
1688
2212
  var insertIndex_1 = 0;
1689
2213
  var groupKey_1 = "";
1690
2214
  var groupRoute_1 = [];
1691
- var _loop_1 = function (i) {
2215
+ var _loop_2 = function (i) {
1692
2216
  var rg = view.requestedgroups[i];
1693
2217
  groupKey_1 += rg.value;
1694
2218
  groupRoute_1.push({ column: rg.column, value: rg.value });
@@ -1696,7 +2220,47 @@
1696
2220
  };
1697
2221
  // Navigo la stuttura dei gruppi ignorando ricorsivamente tutti gli indici fino ai gruppi che mi interessano in modo da non beccare il primo "GruppoC1" del caso sopra
1698
2222
  for (var i = 0; i < view.requestedgroups.length; i++) {
1699
- _loop_1(i);
2223
+ _loop_2(i);
2224
+ }
2225
+ var itemsCacheReference_1;
2226
+ var childGroupsCacheReference_1;
2227
+ // Se non è un gruppo intermedio devo ripulire la cache del gruppo su cui ho attualmente cliccato. Gli oggetti saranno riaggiunti dopo
2228
+ if (!intermediateGroup_1) {
2229
+ this.rgItemCache.set(groupKey_1, []);
2230
+ itemsCacheReference_1 = this.rgItemCache.get(groupKey_1);
2231
+ }
2232
+ else {
2233
+ try {
2234
+ // Se invece è un gruppo intermedio devo ripulire sia tutti i child group ricorsivamente, sia tutti gli item
2235
+ for (var _v = __values(this.rgChildGroupsCache.keys()), _w = _v.next(); !_w.done; _w = _v.next()) {
2236
+ var key = _w.value;
2237
+ if (key.startsWith(groupKey_1))
2238
+ this.rgChildGroupsCache.delete(key);
2239
+ }
2240
+ }
2241
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
2242
+ finally {
2243
+ try {
2244
+ if (_w && !_w.done && (_s = _v.return)) _s.call(_v);
2245
+ }
2246
+ finally { if (e_1) throw e_1.error; }
2247
+ }
2248
+ try {
2249
+ for (var _x = __values(this.rgItemCache.keys()), _y = _x.next(); !_y.done; _y = _x.next()) {
2250
+ var key = _y.value;
2251
+ if (key.startsWith(groupKey_1))
2252
+ this.rgItemCache.delete(key);
2253
+ }
2254
+ }
2255
+ catch (e_2_1) { e_2 = { error: e_2_1 }; }
2256
+ finally {
2257
+ try {
2258
+ if (_y && !_y.done && (_t = _x.return)) _t.call(_x);
2259
+ }
2260
+ finally { if (e_2) throw e_2.error; }
2261
+ }
2262
+ this.rgChildGroupsCache.set(groupKey_1, []);
2263
+ childGroupsCacheReference_1 = this.rgChildGroupsCache.get(groupKey_1);
1700
2264
  }
1701
2265
  // Assegno un livello ai valori che arrivano da usare per formattare la parte grafica. Il primo gruppo cliccato sarà a livello 1,
1702
2266
  // il secondo sarà a livello 2 e così via...
@@ -1704,16 +2268,44 @@
1704
2268
  this.TMPBoundSource.forEach(function (itm) {
1705
2269
  itm._parent = groupKey_1;
1706
2270
  itm._parentRoute = groupRoute_1;
1707
- if (intermediateGroup_1)
2271
+ itm._thisRoute = itm._group ? __spread(groupRoute_1, [new GroupRouteFragment(itm.column, itm.value)]) : [];
2272
+ itm._thisKey = itm._group ? groupKey_1 + itm.value : groupKey_1;
2273
+ // Per le ricerca intermedie metto i gruppi nella cache dei gruppi
2274
+ if (intermediateGroup_1) {
1708
2275
  itm._grouplevel = view.requestedgroups.length;
2276
+ _this.rgGroupCache.set(itm._thisKey, itm);
2277
+ childGroupsCacheReference_1.push(itm);
2278
+ }
2279
+ else {
2280
+ // Metto anche gli oggetti nella cache non ricorsiva
2281
+ itemsCacheReference_1.push(itm);
2282
+ }
1709
2283
  });
1710
- //Elimino gli oggetti vecchi qui dentro e li sostituisco coi nuovi di questa ricerca
1711
- this.boundSource = this.boundSource.filter(function (t) { return t._parent != groupKey_1; });
1712
- (_d = this.boundSource).splice.apply(_d, __spread([insertIndex_1 + 1, 0], this.TMPBoundSource));
1713
- // Aggiungo un separatore alla fine di questi gruppi che dovrà occuparsi di caricare ALTRI gruppi
1714
- this.boundSource.splice(insertIndex_1 + 1 + this.TMPBoundSource.length, 0, this.getGroupSeparator(view, groupKey_1, view.requestedgroups.length));
2284
+ // Elimino gli oggetti vecchi
2285
+ // 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
2286
+ // le cache di ricerca effettuate su una path più profonda dell'attuale
2287
+ // 2) Ricerca finale o ricerca intermedia senza stato salvato - Elimino tutti gli item relativi alla path corrente
2288
+ // Per "stato salvato" si intendono ricerche vecchie salvate per poter essere rieffettuate in caso di ordinamenti su colonne di interesse
2289
+ if (intermediateGroup_1 && view.savedstate) {
2290
+ this.boundSource = this.boundSource.filter(function (t) { return !(t._item || t._thisRoute.length > groupRoute_1.length); });
2291
+ this.groupSearchRequestsCache = this.groupSearchRequestsCache.filter(function (t) { return !(t.route.length > groupRoute_1.length); });
2292
+ }
2293
+ this.boundSource = this.boundSource.filter(function (t) { return !(t._parent == groupKey_1); });
2294
+ var thisGroup = this.boundSource[insertIndex_1];
2295
+ if (intermediateGroup_1)
2296
+ thisGroup._groupscount = (_b = this.View) === null || _b === void 0 ? void 0 : _b.groupcount;
2297
+ // Li sostituisco coi nuovi di questa ricerca
2298
+ (_u = this.boundSource).splice.apply(_u, __spread([insertIndex_1 + 1, 0], this.TMPBoundSource));
2299
+ // 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)
2300
+ var addLast = false;
2301
+ this.boundSource.splice(insertIndex_1 + 1 + (addLast ? this.TMPBoundSource.length : 0), 0, this.getGroupSeparator(view, groupKey_1, groupRoute_1, view.requestedgroups.length, intermediateGroup_1 ? 'groups' : 'items'));
1715
2302
  // Aggiungo la ricerca alla cache di questa "sessione"
1716
- this.groupSearchRequestsCache.push({ path: groupKey_1, view: view });
2303
+ var toAdd_1 = { path: groupKey_1, route: groupRoute_1, view: Object.assign({}, view), group_column: intermediateGroup_1 ? this.TMPBoundSource[0].column : '' };
2304
+ var prev = this.groupSearchRequestsCache.findIndex(function (t) { return t.path == toAdd_1.path && t.group_column == toAdd_1.group_column; });
2305
+ if (prev == -1)
2306
+ this.groupSearchRequestsCache.push(toAdd_1);
2307
+ else
2308
+ this.groupSearchRequestsCache.splice(prev, 1, toAdd_1);
1717
2309
  }
1718
2310
  };
1719
2311
  /**
@@ -1722,6 +2314,22 @@
1722
2314
  EsTableComponent.prototype.MoveTemporaryVariablesToRealOnes = function () {
1723
2315
  this.RowTDs = this.TMPRowTDs;
1724
2316
  this.RowTHs = this.TMPRowTHs;
2317
+ this.RowThGroups = this.TMPRowThGroups ? this.TMPRowThGroups.reverse() : null;
2318
+ this.Columns.Visibile = this.RowTHs.filter(function (t) { return t.Visible; }).length;
2319
+ this.Columns.VisibleUnpinned = this.RowTHs.filter(function (t) { return t.Visible && !t.Pinned; }).length;
2320
+ 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);
2321
+ };
2322
+ /**
2323
+ * Permette di selezionare o deselezionare in maniera arbitraria degli oggetti
2324
+ *
2325
+ * @param {any[]} items Oggetti da selezionare o deselezionare
2326
+ * @param {boolean} select **true** per selezionarli, **false** per non toccarli
2327
+ *
2328
+ * @todo: SELECTION
2329
+ */
2330
+ EsTableComponent.prototype.setSelectionStatus = function (items, select) {
2331
+ this.handleItemsSelection(items, select);
2332
+ this.cdr.markForCheck();
1725
2333
  };
1726
2334
  /**
1727
2335
  * Se non ho l'Input **DynamicRowColumnsDefinition** in modalità dinamica lo riempio con il default nome della colonna = testo della colonna
@@ -1751,32 +2359,118 @@
1751
2359
  * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1752
2360
  */
1753
2361
  EsTableComponent.prototype.reviewColumnsList = function (ths) {
1754
- this.ColumnsList = [];
2362
+ var _this = this;
2363
+ this.TMPColumnsList = [];
1755
2364
  if (ths.length == 0)
1756
2365
  return;
1757
- // Appena il contentChildren è valorizzato scorro tutti gli header
1758
- for (var i = 0; i < ths.length; i++) {
2366
+ var _loop_3 = function (i) {
1759
2367
  var th = ths[i];
1760
- if (this.isEsTh(th)) {
2368
+ if (this_2.isEsTh(th)) {
1761
2369
  // Se non ho un id il th è considerato inerte
1762
2370
  if (!th.ID)
1763
- continue;
1764
- th.OrderBy = this.OrderByColumn;
2371
+ return "continue";
2372
+ th.OrderBy = this_2.OrderByColumn;
1765
2373
  // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
1766
2374
  // Di default la visibilità è quella impostata nel componente
1767
- if (this.HiddenColumns || th.Visible)
1768
- this.ColumnsList.push(new EsTableColumn(th.ID, th.Description, th.Visible, th.Fixed, null));
2375
+ if (this_2.HiddenColumns || th.Visible)
2376
+ this_2.TMPColumnsList.push(new EsTableColumn(th.ID, th.Description, th.Visible, th.Fixed, null, null, null));
1769
2377
  }
1770
2378
  else {
2379
+ var column_1 = th.th;
1771
2380
  // Se non ho un id il th è considerato inerte
1772
- if (!th.th)
1773
- continue;
2381
+ if (!column_1)
2382
+ return "continue";
1774
2383
  // Salvo le informazioni dell'header per far parte della lista da cui scegliere quali colonne visualizzare/nascondere
1775
2384
  // Di default la visibilità è quella impostata nel componente
1776
- if (this.HiddenColumns || th.thVisible)
1777
- this.ColumnsList.push(new EsTableColumn(th.th, null, th.thVisible, th.thFixed, th.Template));
2385
+ if (this_2.HiddenColumns || th.thVisible) {
2386
+ var previouslyPinned = !this_2.ColumnsList || this_2.ColumnsList.length == 0 || !this_2.ColumnsList.find(function (t) { return t.id == column_1; }) ? null : this_2.ColumnsList.find(function (t) { return t.id == column_1; }).pinned;
2387
+ this_2.TMPColumnsList.push(new EsTableColumn(column_1, null, th.thVisible, (th.thFixed || th.thGroup), previouslyPinned == null ? th.thPinned : previouslyPinned, th.thPinnedWidth, th.Template));
2388
+ }
1778
2389
  }
2390
+ };
2391
+ var this_2 = this;
2392
+ // Appena il contentChildren è valorizzato scorro tutti gli header
2393
+ for (var i = 0; i < ths.length; i++) {
2394
+ _loop_3(i);
1779
2395
  }
2396
+ this.ColumnsList = [];
2397
+ this.TMPColumnsList.forEach(function (c) { _this.ColumnsList.push(Object.assign({}, c)); });
2398
+ };
2399
+ /**
2400
+ * Prende i th e i td in modalità diretive e li ordina in base a se ci sono colonne fixed o meno
2401
+ */
2402
+ EsTableComponent.prototype.moveFixedColumnsAtTheBeginning = function (ths, tds) {
2403
+ var thsCache = {};
2404
+ var fixeds = 0, pinneds = 0;
2405
+ var columnsCache = {};
2406
+ var columnsIndexCache = {};
2407
+ // Creo la cache delle colonne
2408
+ for (var coli = 0; coli < this.ColumnsList.length; coli++) {
2409
+ var col = this.ColumnsList[coli];
2410
+ columnsCache[col.id] = col;
2411
+ }
2412
+ // Sposto tutti gli header fixed o pinned all'inizio
2413
+ for (var i = 0; i < ths.length; i++) {
2414
+ var th = ths[i];
2415
+ if (this.isEsTh(th)) {
2416
+ thsCache[th.ID] = th;
2417
+ if (th.Fixed) {
2418
+ if (i != pinneds + fixeds)
2419
+ this.arrayMove(ths, i, pinneds + fixeds);
2420
+ fixeds++;
2421
+ }
2422
+ }
2423
+ else {
2424
+ thsCache[th.th] = th;
2425
+ // Riassegno sempre per ripulire valori di partenza o per aggiornarli in caso di modifiche utente
2426
+ th.thPinned = (!columnsCache[th.th] && th.thPinned) || (columnsCache[th.th] && columnsCache[th.th].pinned);
2427
+ if (th.thPinned) {
2428
+ if (i != pinneds)
2429
+ this.arrayMove(ths, i, pinneds);
2430
+ pinneds++;
2431
+ }
2432
+ //In questo caso sono informazioni statiche invece, non modificabili dall'utente, quindi non mi dò preoccupazioni
2433
+ if (th.thFixed || th.thGroup) {
2434
+ if (i != pinneds + fixeds)
2435
+ this.arrayMove(ths, i, pinneds + fixeds);
2436
+ fixeds++;
2437
+ }
2438
+ }
2439
+ }
2440
+ if (this.isEsTh(ths[0]) || this.isEsTd(tds[0]))
2441
+ return;
2442
+ // Cache degli indici per riposizionare i td come i th
2443
+ for (var i = 0; i < ths.length; i++)
2444
+ columnsIndexCache[ths[i].th] = i;
2445
+ // Riordino le celle per fargli mantenere la stessa struttura dei th
2446
+ var newTds = new Array(ths.length);
2447
+ for (var i = 0; i < tds.length; i++) {
2448
+ var item = tds[i];
2449
+ newTds[columnsIndexCache[item.td]] = item;
2450
+ }
2451
+ this.HasPinnedColumns = pinneds > 0;
2452
+ };
2453
+ /**
2454
+ * In base alla configurazione delle colonne calcola le dimenioni delle colonne pinnate
2455
+ */
2456
+ EsTableComponent.prototype.evaluatePinnedColumnsWidth = function () {
2457
+ if (!this.HasPinnedColumns)
2458
+ return;
2459
+ this.PinnedContainerWidth = 0;
2460
+ for (var i = 0; i < this.ColumnsList.length; i++) {
2461
+ var col = this.ColumnsList[i];
2462
+ if (col.pinned && col.visible)
2463
+ this.PinnedContainerWidth += col.pinnedWidth;
2464
+ }
2465
+ this.PinnedContainerWidth += this.Selection ? 25 : 0;
2466
+ };
2467
+ /**
2468
+ * Helper per spostare un oggetto di un array da un indice all'altro, in place
2469
+ */
2470
+ EsTableComponent.prototype.arrayMove = function (array, oldI, newI) {
2471
+ if (newI > array.length - 1 || oldI > array.length - 1 || newI < 0 || oldI < 0)
2472
+ throw "Gli indici passati non fanno riferimento a una posizione dell'array. Length: " + array.length + " Old:" + oldI + " New: " + newI;
2473
+ array.splice(newI, 0, array.splice(oldI, 1)[0]);
1780
2474
  };
1781
2475
  /**
1782
2476
  * Terminato il binding delle colonne da **reviewColumnsList** e della **View** dal **writeValue** questo metodo si occupa
@@ -1786,14 +2480,19 @@
1786
2480
  */
1787
2481
  EsTableComponent.prototype.alignColumnsIfLoadedView = function (view) {
1788
2482
  var _this = this;
1789
- var emitChanged = view.savedstate;
2483
+ var emitChanged = this.viewMode && view.savedstate;
1790
2484
  var newColset = [];
1791
2485
  if (!this.ColumnsList || this.ColumnsList.length == 0)
1792
2486
  return;
2487
+ var columns = this.viewMode ? view.columns : this.arrayColumns;
1793
2488
  this.ColumnsList.forEach(function (c) {
1794
- var exCl = view.columns.filter(function (cc) { return cc == c.id; });
1795
- // Se l'appsearch viene da uno stato precedente, uso le informaizoni sulle colonne che ha dentro, altrimenti sovrascrivo tutto **
1796
- if (c.visible && view.columns.length == 0)
2489
+ // Se la colonna è pinnata mi arriva col simoleon
2490
+ var exCl = columns.filter(function (cc) { return cc.replace('§', '') == c.id; });
2491
+ // Se la colonna è pinnata aggiorno l'informazione nella view
2492
+ if (exCl.length == 1)
2493
+ c.pinned = exCl[0].startsWith('§');
2494
+ // Se l'appsearch viene da uno stato precedente, uso le informazioni sulle colonne che ha dentro, altrimenti sovrascrivo tutto **
2495
+ if (c.visible && columns.length == 0)
1797
2496
  newColset.push(c.id);
1798
2497
  // Se ho una colonna lato AppSearch e nella ColumnList non è visibile, allineo all'AppSearch
1799
2498
  else if (exCl.length == 1 && !c.visible)
@@ -1803,11 +2502,15 @@
1803
2502
  c.visible = false;
1804
2503
  });
1805
2504
  // Non ho colonne nella appsearch, vuol dire che sono al primo binding
1806
- if (view.columns.length == 0)
1807
- view.columns = newColset;
1808
- if (view.savedstate && this.ColumnsOrdering && view.column_ordering.length > 0) {
1809
- var newColList_1 = [];
2505
+ if (columns.length == 0) {
2506
+ if (this.viewMode)
2507
+ view.columns = newColset;
2508
+ else
2509
+ this.arrayColumns = newColset;
2510
+ }
2511
+ if ((this.viewMode && view.savedstate) && this.ColumnsOrdering && view.column_ordering.length > 0) {
1810
2512
  // Scorro gli ordinamenti che avevo salvato e ricreo la ColumnsList in base a loro
2513
+ var newColList_1 = [];
1811
2514
  view.column_ordering.forEach(function (co) {
1812
2515
  _this.ColumnsList.forEach(function (c) {
1813
2516
  if (c.id == co)
@@ -1817,7 +2520,8 @@
1817
2520
  this.ColumnsList = newColList_1;
1818
2521
  }
1819
2522
  // In ogni caso questo non mi serve più, lo resetto **
1820
- view.savedstate = false;
2523
+ if (this.viewMode)
2524
+ view.savedstate = false;
1821
2525
  if (emitChanged)
1822
2526
  this.changed();
1823
2527
  };
@@ -1828,20 +2532,22 @@
1828
2532
  * @param {'DESC' | 'ASC'} order Nuovo ordine selezionato per la colonna
1829
2533
  */
1830
2534
  EsTableComponent.prototype.thOrderChanged = function (id, order) {
1831
- if (!this.viewMode) {
1832
- console.warn('Order changed on a table not in viewMode. Operation not supported');
2535
+ if (!this.viewMode && !this.arrayMode) {
2536
+ console.warn('Order changed on a table not in viewMode or Array mode. Operation not supported');
1833
2537
  return;
1834
2538
  }
1835
2539
  if (!this.OrderByColumn)
1836
2540
  return;
1837
- var appSearch = this.View;
2541
+ var orders = this.viewMode ? this.View.orders : this.arrayOrders;
1838
2542
  var orderToAdd = true;
1839
2543
  var orderToRemove = null;
1840
2544
  // Se per qualche motivo il costruttore non è passato (cache tarpate o simila) fixo
1841
- if (!appSearch.orders)
1842
- appSearch.orders = [];
1843
- for (var i = 0; i < appSearch.orders.length; i++) {
1844
- var t = appSearch.orders[i];
2545
+ if (!orders && this.viewMode)
2546
+ this.View.orders = [];
2547
+ else if (!orders && this.arrayMode)
2548
+ this.arrayOrders = [];
2549
+ for (var i = 0; i < orders.length; i++) {
2550
+ var t = orders[i];
1845
2551
  if (t.id == id) {
1846
2552
  if (order) {
1847
2553
  t.order = order;
@@ -1852,19 +2558,27 @@
1852
2558
  }
1853
2559
  }
1854
2560
  if (orderToRemove != null) {
1855
- appSearch.orders.splice(orderToRemove, 1);
2561
+ orders.splice(orderToRemove, 1);
1856
2562
  }
1857
2563
  else if (orderToAdd) {
1858
2564
  if (this.MultipleOrderingDirectives)
1859
- appSearch.orders.push(new AppOrdering(id, order));
1860
- else
1861
- appSearch.orders = [new AppOrdering(id, order)];
2565
+ orders.push(new AppOrdering(id, order));
2566
+ else {
2567
+ if (this.viewMode)
2568
+ this.View.orders = [new AppOrdering(id, order)];
2569
+ else if (this.arrayMode)
2570
+ this.arrayOrders = [new AppOrdering(id, order)];
2571
+ }
1862
2572
  }
1863
2573
  this.onOrderChanged.emit({ id: id, order: order });
1864
- if (this.groupSearchRequestsCache.length > 0)
1865
- this.emitRowGroupingSearches(id, appSearch.orders);
1866
- else
1867
- this.emitSearchRequest(false);
2574
+ if (this.viewMode) {
2575
+ if (this.groupSearchRequestsCache.length > 0)
2576
+ this.emitRowGroupingSearches(id, orders);
2577
+ else
2578
+ this.emitSearchRequest(false);
2579
+ }
2580
+ else if (this.arrayMode)
2581
+ this.internalWriteValue();
1868
2582
  };
1869
2583
  /**
1870
2584
  * Metodo da chiamare ogni volta che si vuole dare evidenza all'esterno del bisogno di rieffettuare la ricerca
@@ -1877,6 +2591,11 @@
1877
2591
  this.View.internalsearchrequest = true;
1878
2592
  this.changed();
1879
2593
  }
2594
+ if (viewOverride) {
2595
+ if (resetsPage)
2596
+ viewOverride.page = 1;
2597
+ viewOverride.internalsearchrequest = true;
2598
+ }
1880
2599
  this.researchInProgress = true;
1881
2600
  this.onSearchRequest.emit(viewOverride ? viewOverride : resetsPage);
1882
2601
  };
@@ -1890,16 +2609,19 @@
1890
2609
  * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
1891
2610
  */
1892
2611
  EsTableComponent.prototype.refreshColumnsVisibility = function (ths, tds, view) {
1893
- var columnsCache = {};
1894
2612
  var newColset = [];
1895
2613
  var fixedThs = {};
2614
+ var columnsCache = {};
1896
2615
  for (var coli = 0; coli < this.ColumnsList.length; coli++) {
1897
2616
  var col = this.ColumnsList[coli];
1898
2617
  columnsCache[col.id] = col;
1899
2618
  if (col.visible)
1900
- newColset.push(col.id);
2619
+ newColset.push((col.pinned ? "§" : "") + col.id);
1901
2620
  }
1902
- view.columns = newColset;
2621
+ if (view)
2622
+ view.columns = newColset;
2623
+ else
2624
+ this.arrayColumns = newColset;
1903
2625
  // 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
1904
2626
  if (ths) {
1905
2627
  // Definisco se la colonna è visibile in base alla sua rappresentazione locale in ColumnsList
@@ -1912,7 +2634,7 @@
1912
2634
  }
1913
2635
  else {
1914
2636
  th.thVisible = th.thFixed || (columnsCache[th.th] ? columnsCache[th.th].visible : th.thVisible);
1915
- if (th.thFixed)
2637
+ if (th.thFixed || th.thGroup)
1916
2638
  fixedThs[th.th] = true;
1917
2639
  }
1918
2640
  }
@@ -1936,22 +2658,23 @@
1936
2658
  * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
1937
2659
  */
1938
2660
  EsTableComponent.prototype.alignHeadersOrdering = function (ths, view) {
2661
+ var orders = view ? view.orders : this.arrayOrders;
1939
2662
  for (var i = 0; i < ths.length; i++) {
1940
2663
  var th = ths[i];
1941
2664
  if (this.isEsTh(th)) {
1942
2665
  th.Order = null;
1943
2666
  // Assegno tutti gli ordinamenti che mi vengono da AppSearch. Sono i più importanti. Non faccio cache o cose strano perché tanto questa
1944
2667
  // variabile sarà sempre massimo 3 elementi
1945
- for (var i_1 = 0; i_1 < view.orders.length; i_1++) {
1946
- var or = view.orders[i_1];
2668
+ for (var i_1 = 0; i_1 < orders.length; i_1++) {
2669
+ var or = orders[i_1];
1947
2670
  if (or.id == th.ID)
1948
2671
  th.Order = or.order;
1949
2672
  }
1950
2673
  }
1951
2674
  else {
1952
2675
  th.thOrder = null;
1953
- for (var i_2 = 0; i_2 < view.orders.length; i_2++) {
1954
- var or = view.orders[i_2];
2676
+ for (var i_2 = 0; i_2 < orders.length; i_2++) {
2677
+ var or = orders[i_2];
1955
2678
  if (or.id == th.th)
1956
2679
  th.thOrder = or.order;
1957
2680
  }
@@ -1972,6 +2695,11 @@
1972
2695
  if (tds.length == 0)
1973
2696
  return;
1974
2697
  var thsCache = {};
2698
+ var columnsCache = {};
2699
+ for (var coli = 0; coli < this.ColumnsList.length; coli++) {
2700
+ var col = this.ColumnsList[coli];
2701
+ columnsCache[col.id] = col;
2702
+ }
1975
2703
  for (var i = 0; i < ths.length; i++) {
1976
2704
  var th = ths[i];
1977
2705
  thsCache[this.isEsTh(th) ? th.ID : th.th] = th;
@@ -1984,10 +2712,10 @@
1984
2712
  if (this.isEsTd(td)) {
1985
2713
  var th = thsCache[td.ID];
1986
2714
  if (!!th)
1987
- th.Referenced = true;
2715
+ th._referenced = true;
1988
2716
  else
1989
2717
  throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.ID;
1990
- var isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && th.thFixed);
2718
+ var isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && (th.thFixed || th.thGroup));
1991
2719
  var 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 };
1992
2720
  var ctx = td.Context;
1993
2721
  if (this.TMPRowTDs[ctx]) {
@@ -2005,24 +2733,25 @@
2005
2733
  else {
2006
2734
  for (var i_3 = 0; i_3 < this.boundSource.length; i_3++) {
2007
2735
  var item = this.boundSource[i_3];
2008
- var ctx = item.hash;
2736
+ var ctx = item._hash;
2009
2737
  var key = td.td;
2010
2738
  var th = thsCache[td.td];
2011
2739
  if (!!th)
2012
- th.Referenced = true;
2740
+ th._referenced = true;
2013
2741
  else
2014
2742
  throw "ID dell'oggeto EsTd non compatibile con gli ID dicharati negli EsTh: " + td.td;
2015
2743
  if (td.tdIf || (!this.isEsTh(th) && th.thGroup)) {
2016
2744
  var thCasted = th;
2017
- var isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && th.thFixed);
2745
+ var isFixed = (this.isEsTh(th) && th.Fixed) || (!this.isEsTh(th) && (th.thFixed || th.thGroup || th.thPinned));
2018
2746
  var itemToAdd = item._item ?
2019
- { ID: key, GroupHeader: false, GroupAggregation: false, Visible: td.tdVisible, Wraps: true, Class: td.tdClass, Template: td.Template } :
2020
- { ID: key, GroupHeader: thCasted.thGroup, GroupAggregation: !!thCasted.thAggregation, Visible: true, Wraps: false, Class: thCasted.thGroupClass || '', Content: this.getGroupCellDisplay(item, key, th) };
2747
+ { 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 } :
2748
+ { 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) };
2021
2749
  if (this.TMPRowTDs[ctx]) {
2022
- if (isFixed)
2023
- this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
2024
- else
2025
- this.TMPRowTDs[ctx].push(itemToAdd);
2750
+ // Non serve più grazie al metodo **oveFixedColumnsAtTheBeginning**
2751
+ //if (isFixed)
2752
+ // this.TMPRowTDs[ctx].splice(0 + (contextFixeds[ctx]++), 0, itemToAdd);
2753
+ //else
2754
+ this.TMPRowTDs[ctx].push(itemToAdd);
2026
2755
  }
2027
2756
  else {
2028
2757
  this.RowContexts.push(ctx);
@@ -2039,7 +2768,7 @@
2039
2768
  var errs = [];
2040
2769
  for (var i = 0; i < ths.length; i++) {
2041
2770
  var th = ths[i];
2042
- if (!th.Referenced)
2771
+ if (!th._referenced)
2043
2772
  errs.push(this.isEsTh(th) ? th.ID : th.th);
2044
2773
  }
2045
2774
  if (errs.length > 0) {
@@ -2057,43 +2786,161 @@
2057
2786
  * @param {EsTh[] | EsThDirective[]} ths Colonne della tabella
2058
2787
  */
2059
2788
  EsTableComponent.prototype.evaluateRowThs = function (ths) {
2060
- var _d;
2789
+ var _s;
2061
2790
  if (ths.length == 0)
2062
2791
  return;
2792
+ var columnsListCache = {};
2063
2793
  var castedView = this.View;
2064
- var groupingsUndefined = !castedView.groupings || castedView.groupings.length == 0;
2794
+ var groupingsUndefined = this.viewMode && (castedView && !castedView.groupings || castedView.groupings.length == 0);
2795
+ for (var i = 0; i < this.ColumnsList.length; i++) {
2796
+ var itm = this.ColumnsList[i];
2797
+ columnsListCache[itm.id] = itm;
2798
+ }
2065
2799
  this.TMPRowTHs = [];
2066
2800
  var fixed = 0;
2067
2801
  for (var i = 0; i < ths.length; i++) {
2068
2802
  var th = ths[i];
2069
2803
  var toAdd = void 0;
2070
2804
  if (this.isEsTh(th)) {
2071
- toAdd = { Fixed: th.Fixed, ID: th.ID, Visible: th.Visible, Class: th.Class, Order: th.Order, Orderable: th.Orderable, Template: null, Content: th.Description, Wrap: false };
2805
+ 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 };
2072
2806
  if (th.Fixed)
2073
2807
  this.TMPRowTHs.splice(0 + (fixed++), 0, toAdd);
2074
2808
  else
2075
2809
  this.TMPRowTHs.push(toAdd);
2076
2810
  }
2077
2811
  else if (th.thIf || th.thGroup) {
2078
- // 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
2079
- // (Questo probabilmente diventerà il comportamento di default anche per le colonne "Pinned")
2080
2812
  var thClass = (th.thClass || '') + (th.thGroup ? " est-col-min" : "");
2081
- toAdd = { Fixed: th.thFixed || th.thGroup, ID: th.th, Visible: th.thVisible, Class: thClass, Order: th.thOrder, Orderable: th.thOrderable, Template: th.Template, Content: null, Wrap: false };
2082
- if (th.thFixed)
2083
- this.TMPRowTHs.splice(0 + (fixed++), 0, toAdd);
2084
- else
2085
- this.TMPRowTHs.push(toAdd);
2813
+ 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 };
2814
+ this.TMPRowTHs.push(toAdd);
2815
+ // Se ho un modello che deve funzionare a rowgrouping ma non è ancora stata effettuata nessuna ricerca sui gruppi principali (groupingsUndefined)
2816
+ // li genero e mando la prima ricerca che dev'essere spedita al backend per il primo caricamento dei gruppi
2086
2817
  if (groupingsUndefined && (th.thAggregation || th.thGroup)) {
2087
2818
  var groupAggregations = this.getGroupAggregations(th);
2088
2819
  if (!castedView.groupings)
2089
2820
  castedView.groupings = groupAggregations;
2090
2821
  else
2091
- (_d = castedView.groupings).push.apply(_d, __spread(groupAggregations));
2822
+ (_s = castedView.groupings).push.apply(_s, __spread(groupAggregations));
2092
2823
  this.ResearchNeeded = true;
2093
2824
  }
2094
2825
  }
2095
2826
  }
2096
2827
  };
2828
+ EsTableComponent.prototype.evaluateHeadersGroupingInfos = function (ths) {
2829
+ // Pregiro per trovare i parent
2830
+ var parentsCache = {};
2831
+ var thsCache = {};
2832
+ for (var i = 0; i < ths.length; i++) {
2833
+ var th = ths[i];
2834
+ if (this.isEsTh(th))
2835
+ continue;
2836
+ thsCache[th.th] = th;
2837
+ if (th.thParent && !parentsCache[th.thParent])
2838
+ parentsCache[th.thParent] = true;
2839
+ }
2840
+ // Secondo giro per beccare il livello massimo e la lista di foglie (th senza parent)
2841
+ var hMaxLevel = 0;
2842
+ var leafs = [];
2843
+ for (var i = 0; i < ths.length; i++) {
2844
+ var th = ths[i];
2845
+ if (this.isEsTh(th)) {
2846
+ leafs.push(th);
2847
+ continue;
2848
+ }
2849
+ // Se sono una foglia vedo quanti livelli ci sono sopra
2850
+ if (!parentsCache[th.th]) {
2851
+ leafs.push(th);
2852
+ var tmp = this.jumpsToFinalParent(th, thsCache);
2853
+ hMaxLevel = tmp > hMaxLevel ? tmp : hMaxLevel;
2854
+ }
2855
+ }
2856
+ return { leafs: leafs, groupingLevel: hMaxLevel, parentsCache: parentsCache, thsCache: thsCache };
2857
+ };
2858
+ /**
2859
+ * Genera gli header groups da una lista di info sui th all'interno della variabile **TMPRowThGroups**
2860
+ */
2861
+ EsTableComponent.prototype.evaluateHeaderGroups = function (infos) {
2862
+ if (infos.groupingLevel == 0)
2863
+ return;
2864
+ // Giro 2.5, creo l'output dei raggruppamenti per header in modo da non dovermi preoccupare di celle non inizializzate
2865
+ var expandedGroups = [];
2866
+ var visibleUnpinnedLeafs = infos.leafs.filter(function (t) { return t.thVisible && !t.thPinned; });
2867
+ for (var l = 0; l < infos.groupingLevel; l++) {
2868
+ expandedGroups.push([]);
2869
+ for (var i = 0; i < visibleUnpinnedLeafs.length; i++)
2870
+ expandedGroups[l].push("");
2871
+ }
2872
+ // Ordino le foglie in base agli ordinamenti delle colonne
2873
+ var orderedLeafs = [];
2874
+ for (var i = 0; i < this.OrderDirectives.length; i++) {
2875
+ var leaf = infos.thsCache[this.OrderDirectives[i]];
2876
+ if (leaf.thVisible && !leaf.thPinned)
2877
+ orderedLeafs.push(leaf);
2878
+ }
2879
+ // Terzo giro per creare l'array group con tutti i riferimenti del caso
2880
+ var currentParent = "";
2881
+ for (var i = 0; i < orderedLeafs.length; i++) {
2882
+ var refTh = orderedLeafs[i];
2883
+ var prevTh = i - 1 >= 0 ? orderedLeafs[i - 1] : null;
2884
+ // Parent diverso da prima, metto il bordo a sinistra e a destra della cella precedente (se c'è)
2885
+ // 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
2886
+ refTh._lbord = refTh.thParent != currentParent;
2887
+ refTh._rbord = visibleUnpinnedLeafs.length == i + 1;
2888
+ if (prevTh)
2889
+ prevTh._rbord = refTh.thParent != currentParent;
2890
+ currentParent = refTh.thParent;
2891
+ // Per ogni gruppo srotolo il parent nella matrice dei raggruppamenti
2892
+ for (var l = 0; l < infos.groupingLevel; l++) {
2893
+ var parent = refTh.thParent;
2894
+ if (parent && !refTh.thPinned) {
2895
+ expandedGroups[l][i] = parent;
2896
+ refTh = infos.thsCache[parent];
2897
+ }
2898
+ }
2899
+ }
2900
+ // Quarto giro per compattarlo nell'elemento finale su cui bindarmi
2901
+ currentParent = "";
2902
+ var currentSpan = 0;
2903
+ this.TMPRowThGroups = [];
2904
+ for (var l = 0; l < expandedGroups.length; l++) {
2905
+ var levelArray = [];
2906
+ this.TMPRowThGroups.push(levelArray);
2907
+ if (this.Selection || this.HasPinnedColumns)
2908
+ levelArray.push({ Span: 1, Template: null, Pinned: this.HasPinnedColumns });
2909
+ for (var h = 0; h < expandedGroups[l].length; h++) {
2910
+ var item = expandedGroups[l][h];
2911
+ if (item == currentParent)
2912
+ currentSpan++;
2913
+ else {
2914
+ if (currentSpan > 0)
2915
+ levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
2916
+ currentSpan = 1;
2917
+ currentParent = item;
2918
+ }
2919
+ }
2920
+ // Ultima aggiunta che altrimenti mi rimarrebbe in cache
2921
+ levelArray.push({ Span: currentSpan, Template: (currentParent ? infos.thsCache[currentParent].Template : null), Borders: !!currentParent });
2922
+ if (this.Removal)
2923
+ levelArray.push({ Span: 1, Template: null });
2924
+ if (this.Export || this.HiddenColumns || this.ColumnsOrdering || this.CornerMenuOptions)
2925
+ levelArray.push({ Span: 1, Template: null });
2926
+ currentSpan = 0;
2927
+ currentParent = "";
2928
+ }
2929
+ };
2930
+ /**
2931
+ * Calcola il numero di salti da un header foglia all'ultimo parent della catena
2932
+ */
2933
+ EsTableComponent.prototype.jumpsToFinalParent = function (th, thsCache) {
2934
+ var jumps = 0;
2935
+ var parent = null;
2936
+ do {
2937
+ parent = th.thParent;
2938
+ if (parent)
2939
+ jumps++;
2940
+ th = thsCache[parent];
2941
+ } while (parent);
2942
+ return jumps;
2943
+ };
2097
2944
  /**
2098
2945
  * Data una direttiva EsTh restituisce la lista delle aggregazioni richiesta per questa colonna o il gruppo che rappresenta
2099
2946
  *
@@ -2106,7 +2953,11 @@
2106
2953
  // Es: '{min:dd/MM/yyyy} - {max:dd/MM/yyyy}'
2107
2954
  if (th.thAggregation) {
2108
2955
  this.getEsThDirectiveListOfAggregations(th).forEach(function (agg) {
2109
- ret.push(new GroupOrAggregation(th.th, agg.func));
2956
+ var isdate = agg.format && ['small', 'long', 'verylong'].includes(agg.format);
2957
+ var isnumber = agg.format && agg.format.startsWith("F") && !Number.isNaN(agg.format.charAt(1)) && agg.format.length == 2;
2958
+ if (!isdate && !isnumber && agg.format)
2959
+ throw "Le aggergazioni supportate dall'es-table sono solo 'small', 'long', 'verylong' per le date e 'F0-9' per i numeri";
2960
+ ret.push(new GroupOrAggregation(th.th, agg.func, isdate ? 'date' : isnumber ? 'number' : 'string'));
2110
2961
  });
2111
2962
  }
2112
2963
  else if (th.thGroup)
@@ -2123,6 +2974,9 @@
2123
2974
  EsTableComponent.prototype.getEsThDirectiveListOfAggregations = function (th) {
2124
2975
  if (!th.thAggregation)
2125
2976
  return [];
2977
+ // Se ho già effettuato questo calcolo per questo th restituisco la versione in cache
2978
+ if (th._thAggregations)
2979
+ return th._thAggregations;
2126
2980
  var ret = [];
2127
2981
  var display = th.thAggregation;
2128
2982
  var matches = display.match(/{[a-zA-Z0-9\/:]*}/gi);
@@ -2138,6 +2992,7 @@
2138
2992
  }
2139
2993
  ret.push({ func: func, format: format, match: m });
2140
2994
  });
2995
+ th._thAggregations = ret;
2141
2996
  return ret;
2142
2997
  };
2143
2998
  /**
@@ -2145,16 +3000,20 @@
2145
3000
  *
2146
3001
  * @param {AppSearch<any>} view AppSearch da utilizzare per questa operazione
2147
3002
  */
2148
- EsTableComponent.prototype.generateDefaultOrder = function (view) {
2149
- if (this.TMPRowTHs.length == 0)
3003
+ EsTableComponent.prototype.generateDefaultOrder = function (ths, view) {
3004
+ if (ths.length == 0)
2150
3005
  return;
3006
+ var orderings = this.viewMode ? view.column_ordering : this.arrayColumnOrdering;
2151
3007
  // Genero ordinamento di default da 0 fino a dove deve arrivare. Situazione attuale senza hotpotato
2152
- if (!view.column_ordering || view.column_ordering.length == 0) {
2153
- for (var i = 0; i < this.TMPRowTHs.length; i++)
2154
- this.OrderDirectives.push(this.TMPRowTHs[i].ID);
3008
+ if (!orderings || orderings.length == 0) {
3009
+ for (var i = 0; i < ths.length; i++) {
3010
+ var th = ths[i];
3011
+ var order = this.isEsTh(th) ? th.ID : th.th;
3012
+ this.OrderDirectives.push(order);
3013
+ }
2155
3014
  }
2156
3015
  else
2157
- this.OrderDirectives = view.column_ordering;
3016
+ this.OrderDirectives = orderings;
2158
3017
  };
2159
3018
  /**
2160
3019
  * Applica l'ordine specificato alle varie colonne
@@ -2163,7 +3022,7 @@
2163
3022
  * @param {boolean} finalize Se **true** significa che non mi aspetto di dover effettuare altre operazioni e posso renderizzare la situazione in base ai RowContext
2164
3023
  * Senza finalize significa che mi aspetto altre operazioni che prima o poi richiameranno questa funzione col finalize.
2165
3024
  *
2166
- * Ad esempio, una volta selezionato ordinamento fisico/logico delle colonne so che parte un altra ricerca che mi rivalorizzera da "writeValue", che già chiama questa funzione.
3025
+ * 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.
2167
3026
  * Mettendo solo la chiamata da "writeValue" come "finalizzante" mi assicuro che smanattamenti a frontend non causino flickering fino a quando non servono
2168
3027
  */
2169
3028
  EsTableComponent.prototype.applyOrdering = function (view, finalize) {
@@ -2177,22 +3036,25 @@
2177
3036
  newHeaders.push(heaedrItem);
2178
3037
  });
2179
3038
  this.TMPRowTHs = newHeaders;
2180
- var _loop_2 = function (i) {
2181
- var context = this_1.TMPRowTDs[this_1.RowContexts[i]];
3039
+ var _loop_4 = function (i) {
3040
+ var context = this_3.TMPRowTDs[this_3.RowContexts[i]];
2182
3041
  var newContext = [];
2183
- this_1.OrderDirectives.forEach(function (o) {
3042
+ this_3.OrderDirectives.forEach(function (o) {
2184
3043
  var contextItem = context.filter(function (t) { return t.ID == o; })[0];
2185
3044
  newContext.push(contextItem);
2186
3045
  });
2187
- this_1.TMPRowTDs[this_1.RowContexts[i]] = newContext;
3046
+ this_3.TMPRowTDs[this_3.RowContexts[i]] = newContext;
2188
3047
  };
2189
- var this_1 = this;
3048
+ var this_3 = this;
2190
3049
  // Genero ordinamento per le celle
2191
3050
  for (var i = 0; i < this.RowContexts.length; i++) {
2192
- _loop_2(i);
3051
+ _loop_4(i);
2193
3052
  }
2194
3053
  }
2195
- view.column_ordering = this.OrderDirectives;
3054
+ if (this.viewMode)
3055
+ view.column_ordering = this.OrderDirectives;
3056
+ else
3057
+ this.arrayColumnOrdering = this.OrderDirectives;
2196
3058
  this.changed();
2197
3059
  };
2198
3060
  // #endregion
@@ -2203,24 +3065,40 @@
2203
3065
  * @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
2204
3066
  * facenti riferimento allo stesso contesto
2205
3067
  * @param {string} parent Parent path che rappresenta a quale gruppo è affibbiato questo separatore
3068
+ * @param {GroupRouteFragment[]} route Route path che rappresenta a quale gruppo è affibbiato questo separatore
2206
3069
  * @param {number} level Livello del gruppo di cui questo elemento è separatore, viene usato per applicare la classe "est-lvl-{{level}}"
2207
3070
  *
2208
3071
  * @returns {any} Elemento di separazione contenente tutti i bind per presentare una paginazione sotto questo gruppo lato interfaccia
2209
3072
  */
2210
- EsTableComponent.prototype.getGroupSeparator = function (view, parent, level) {
2211
- var item = {
2212
- _sep: true,
2213
- _parent: parent,
2214
- _grouplevel: level,
2215
- filters: view.requestedgroups.map(function (t) { return { column: t.column, value: t.value }; }),
2216
- page: view.page,
2217
- pages: view.pages,
2218
- itemsperpage: view.itemsperpageoverride,
2219
- count: view.objectcount
2220
- };
3073
+ EsTableComponent.prototype.getGroupSeparator = function (view, parent, route, level, searches) {
3074
+ var item = new GroupPager(level, route, parent, Object.assign({}, view), searches);
3075
+ item.buttons = this.getPagesArray(6, view.page, view.pages);
2221
3076
  this.calculateHash([item]);
2222
3077
  return item;
2223
3078
  };
3079
+ /**
3080
+ * Sposta la ricerca di una pagina in avanti (o indietro)
3081
+ *
3082
+ * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
3083
+ * @param {any} pager Elemento di separazione su cui è effettuata la ricerca
3084
+ */
3085
+ EsTableComponent.prototype.addToPageGroup = function (page, pager) {
3086
+ this.goToPageGroup(pager.view.page + page, pager);
3087
+ };
3088
+ /**
3089
+ * Sposta la ricerca alla pagina specificata
3090
+ *
3091
+ * @param {number} page Pagina a cui navigare
3092
+ * @param {any} pager Elemento di separazione su cui è effettuata la ricerca
3093
+ */
3094
+ EsTableComponent.prototype.goToPageGroup = function (page, pager) {
3095
+ var appSearchElement = pager.view;
3096
+ if (page === 0 || page > appSearchElement.pages)
3097
+ return;
3098
+ appSearchElement.page = page;
3099
+ pager.buttons = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
3100
+ this.emitSearchRequest(false, appSearchElement);
3101
+ };
2224
3102
  /**
2225
3103
  * Data una colonna effettua la riemissione di tutte le ricerche relative.
2226
3104
  *
@@ -2237,10 +3115,17 @@
2237
3115
  EsTableComponent.prototype.emitRowGroupingSearches = function (column, orderings) {
2238
3116
  var _this = this;
2239
3117
  // Per tutte le ricerche intermedie che devo rivalutare le re-emitto in modo da aggiornargli i dati
2240
- var meaningfulAppSearches = this.groupSearchRequestsCache.filter(function (t) { return t.path.endsWith(column); }).map(function (t) { return t.view; });
3118
+ var meaningfulAppSearches = this.groupSearchRequestsCache.filter(function (t) { return t.group_column == column; }).map(function (t) { return t.view; });
3119
+ // Se non ne trovo significa che ho fatto l'ordinamento o sugli item, o su colonne relative a un sottogruppo non caricato
3120
+ if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
3121
+ meaningfulAppSearches = this.groupSearchRequestsCache.filter(function (t) { return !t.group_column; }).map(function (t) { return t.view; });
3122
+ // Se non ne trovo qui significa che sto ordinando su colonne relative a un sottogruppo non caricato
3123
+ if (!meaningfulAppSearches || meaningfulAppSearches.length == 0)
3124
+ return;
2241
3125
  meaningfulAppSearches.forEach(function (as) {
2242
3126
  // Ovviamente gli oridnamenti devono essere quelli appena generati
2243
3127
  as.orders = orderings;
3128
+ as.savedstate = true;
2244
3129
  _this.emitSearchRequest(false, as);
2245
3130
  });
2246
3131
  };
@@ -2258,15 +3143,16 @@
2258
3143
  if (grp._sep)
2259
3144
  return "";
2260
3145
  var display = header.thAggregation;
2261
- if (grp.column == cell)
2262
- return grp.value;
3146
+ if (grp.column == cell) {
3147
+ var groupsPart = grp._groupscount ? " - " + grp._groupscount + " " + this.lc.loc("Groups") : "";
3148
+ return grp.value + " (" + grp.count + groupsPart + ")";
3149
+ }
2263
3150
  else {
2264
- var agg_1 = grp.aggregations.filter(function (t) { return t.column == cell; });
3151
+ var agg_1 = grp._aggregationsCache.get(cell);
2265
3152
  if (!agg_1)
2266
3153
  return "";
2267
3154
  this.getEsThDirectiveListOfAggregations(header).forEach(function (itm) {
2268
- var aggValue = agg_1.find(function (t) { return t.aggregation == itm.func; }).value;
2269
- display = display.replace(itm.match, _this.formatAggregationValue(aggValue, itm.format));
3155
+ display = display.replace(itm.match, _this.formatAggregationValue(agg_1.get(itm.func), itm.format));
2270
3156
  });
2271
3157
  return display;
2272
3158
  }
@@ -2281,20 +3167,33 @@
2281
3167
  */
2282
3168
  EsTableComponent.prototype.handleGroupClick = function (group) {
2283
3169
  var casted = this.View;
2284
- var anyGroup = group;
2285
- anyGroup._expanded = !anyGroup._expanded;
2286
- if (anyGroup._expanded) {
3170
+ var anyG = group;
3171
+ anyG._expanded = !anyG._expanded;
3172
+ // Sono in modalità raggruppamento virtuale da array: Espandere significa rendere visibili tutti gli oggetti relativi a questo gruppo, viceversa il contrarre
3173
+ if (this.ArrayGrouping) {
3174
+ var allRelatives = this.boundSource.filter(function (t) { return (t._group && ((anyG._expanded && t._parent == anyG._thisKey) || (!anyG._expanded && t._parent && t._parent.startsWith(anyG._thisKey)))) ||
3175
+ (t._item && ((anyG._expanded && t._thisKey == anyG._thisKey) || (!anyG._expanded && t._thisKey.startsWith(anyG._thisKey)))); });
3176
+ allRelatives.forEach(function (t) {
3177
+ t._visible = anyG._expanded;
3178
+ if (t._group)
3179
+ t._expanded = false;
3180
+ });
3181
+ return;
3182
+ }
3183
+ if (anyG._expanded) {
3184
+ // Resetto ipp
3185
+ casted.itemsperpageoverride = 15;
2287
3186
  if (!casted.requestedgroups)
2288
3187
  casted.requestedgroups = [new GroupFilter(group.column, group.value)];
2289
3188
  else {
2290
- var level = anyGroup._grouplevel;
3189
+ var level = anyG._grouplevel;
2291
3190
  // se il gruppo cliccato non ha un livello è il primo gruppo, quindi ordinamento unico
2292
3191
  // altrimenti devo rimuovere tutti i filtri su livelli superiori al level cliccato e aggiungere il level cliccato
2293
3192
  if (!level)
2294
3193
  casted.requestedgroups = [new GroupFilter(group.column, group.value)];
2295
3194
  else {
2296
3195
  casted.requestedgroups = [];
2297
- anyGroup._parentRoute.forEach(function (step) {
3196
+ anyG._parentRoute.forEach(function (step) {
2298
3197
  casted.requestedgroups.push(new GroupFilter(step.column, step.value));
2299
3198
  });
2300
3199
  casted.requestedgroups.push(new GroupFilter(group.column, group.value));
@@ -2304,7 +3203,7 @@
2304
3203
  this.emitSearchRequest(true);
2305
3204
  }
2306
3205
  else {
2307
- var path_1 = (anyGroup._parent || '') + group.value;
3206
+ var path_1 = (anyG._parent || '') + group.value;
2308
3207
  // Se ho chiuso un gruppo non mi serve rieffettuare ricerce, mi basta eliminare dagli oggetti bindati tutti gli elementi sottostanti a quel gruppo
2309
3208
  this.boundSource = this.boundSource.filter(function (t) { return !t._parent || !t._parent.startsWith(path_1); });
2310
3209
  // devo però anche rimuovere eventuali cache relative
@@ -2323,7 +3222,9 @@
2323
3222
  EsTableComponent.prototype.formatAggregationValue = function (value, format) {
2324
3223
  if (!format)
2325
3224
  return value;
2326
- var isNumber = !Number.isNaN(value) && !format || format.startsWith("F");
3225
+ var isNumber = !Number.isNaN(value) && (!format || format.startsWith("F"));
3226
+ if (isNumber && format.startsWith("F") && !Number.isNaN(format.substr(1)))
3227
+ return parseFloat(value).toFixed(parseInt(format.substr(1)));
2327
3228
  var date = null;
2328
3229
  // Alcune versione di extensions rischiano di crashare con cose non date... è stato risolto dopo quindi questo try - catch in realtà
2329
3230
  // torna utile solo con versioni vecchie/deprecate della libreria @esfaenza/extensions
@@ -2333,10 +3234,6 @@
2333
3234
  catch (_a) { }
2334
3235
  if (date)
2335
3236
  return this.dateExts.getFormatted(date, format == 'small', format == 'verylong');
2336
- else if (isNumber) {
2337
- if (format.startsWith("F") && !Number.isNaN(format.substr(1)))
2338
- return parseFloat(value).toFixed(parseInt(format.substr(1)));
2339
- }
2340
3237
  // Qui ci finisco sia per input che non sono né date né numeri, sia per formati non riconosciuti
2341
3238
  return value;
2342
3239
  };
@@ -2349,7 +3246,7 @@
2349
3246
  */
2350
3247
  EsTableComponent.prototype.sendUp = function (columnItem) {
2351
3248
  var itemIndex = this.TMPColumnsList.indexOf(columnItem);
2352
- if (this.TMPColumnsList[itemIndex - 1].fixed)
3249
+ if (this.TMPColumnsList[itemIndex - 1].fixed || this.TMPColumnsList[itemIndex - 1].pinned)
2353
3250
  return;
2354
3251
  this.utiExts.swap(this.TMPColumnsList, itemIndex, itemIndex - 1);
2355
3252
  // Non posso fare JSON.parse(JSON.stringify(this.ColumnsList)) perché contiene riferimenti a TemplateRef
@@ -2370,6 +3267,25 @@
2370
3267
  this.TMPColumnsList.forEach(function (c) { tmp.push(Object.assign({}, c)); });
2371
3268
  this.TMPColumnsList = tmp;
2372
3269
  };
3270
+ /**
3271
+ * All'interno della dialog "Ordinamento e Visibilità Colonne" pinna la colonna specificata
3272
+ *
3273
+ * @param {EsTableColumn} columnItem Colonna da spostare
3274
+ */
3275
+ EsTableComponent.prototype.pinOrUnpinColumn = function (columnItem) {
3276
+ var itemIndex = this.TMPColumnsList.indexOf(columnItem);
3277
+ // Sposto la colonna alla fine di tutte quelle pinnate. La cosa funziona in entrambi sensi:
3278
+ // 1) Se sto pinnando, devo metterla come ultima pinnata
3279
+ // 2) Se sto spinnando devo metterla come prima non pinnata
3280
+ // Coincidenza vuole che il punto 1 e 2 siano equivalenti
3281
+ for (var i = 0; i < this.TMPColumnsList.length; i++) {
3282
+ if (!this.TMPColumnsList[i].pinned) {
3283
+ this.arrayMove(this.TMPColumnsList, itemIndex, i);
3284
+ break;
3285
+ }
3286
+ }
3287
+ columnItem.pinned = !columnItem.pinned;
3288
+ };
2373
3289
  /**
2374
3290
  * All'interno della dialog "Ordinamento e Visibilità Colonne" inverte le impostazioni di visibilità della colonna
2375
3291
  *
@@ -2430,12 +3346,12 @@
2430
3346
  // Non permetto di non selezionare nulla
2431
3347
  if (this.TMPColumnsList.every(function (t) { return !t.visible; }))
2432
3348
  return false;
2433
- var castedView = this.View;
3349
+ var castedView = this.viewMode ? this.View : null;
2434
3350
  this.ColumnsList = [];
2435
3351
  this.TMPColumnsList.forEach(function (c) { _this.ColumnsList.push(Object.assign({}, c)); });
2436
3352
  this.refreshColumnOrdering();
2437
- this.refreshColumnsVisibility(null, null, castedView);
2438
3353
  this.applyOrdering(castedView, false);
3354
+ this.refreshColumnsVisibility(null, null, castedView);
2439
3355
  //Salvo le preferences di questa view
2440
3356
  //Di default registro ordinamento e visibilità delle colonne nella vista. Solo le cose di UI
2441
3357
  if (this.SavePreferences) {
@@ -2447,11 +3363,17 @@
2447
3363
  console.error("Non posso utilizzare le preference senza che il pacchetto @esfaenza/preferences sia installato");
2448
3364
  return false;
2449
3365
  }
2450
- var toStore = { columns: JSON.parse(JSON.stringify(castedView.columns)), column_ordering: JSON.parse(JSON.stringify(castedView.column_ordering)) };
3366
+ var columns = this.arrayMode ? this.arrayColumns : castedView.columns;
3367
+ var columnsOrderings = this.arrayMode ? this.arrayColumnOrdering : castedView.column_ordering;
3368
+ var toStore = { columns: JSON.parse(JSON.stringify(columns)), column_ordering: JSON.parse(JSON.stringify(columnsOrderings)) };
2451
3369
  this.prefService.store(this.ngControl.name, toStore);
2452
3370
  }
3371
+ // Rieseguo l'ultima ricerca bindata alla tabella
2453
3372
  // Mi assicuro di farlo dopo l'espansione del changed o rischio che la ricerca mi ridia colonne che in realtà non esistono
2454
- setTimeout(function () { _this.emitSearchRequest(false); });
3373
+ if (this.viewMode)
3374
+ setTimeout(function () { _this.emitSearchRequest(false); });
3375
+ else if (this.arrayMode)
3376
+ setTimeout(function () { _this.internalWriteValue(); });
2455
3377
  // Lo vorrei mettere lato template ma no
2456
3378
  this.lastSelectedItemID = null;
2457
3379
  return true;
@@ -2461,7 +3383,10 @@
2461
3383
  */
2462
3384
  EsTableComponent.prototype.globalColVisCheckChanged = function () {
2463
3385
  var _this = this;
2464
- this.TMPColumnsList.forEach(function (t) { t.visible = _this.globalColVisCheck; });
3386
+ this.TMPColumnsList.forEach(function (t) {
3387
+ if (!t.fixed)
3388
+ t.visible = _this.globalColVisCheck;
3389
+ });
2465
3390
  };
2466
3391
  // #endregion
2467
3392
  // #region Gestione data source gerarchici
@@ -2509,9 +3434,9 @@
2509
3434
  var obj = objs[i];
2510
3435
  // Se la parentKey non è valorizzata, questo è il livello 0 (1... perché gli 0 son perciolosi)
2511
3436
  if (!obj[this.ParentKey] && levelToAssign == 1) {
2512
- obj.level = 1;
2513
- obj.visible = true;
2514
- obj.expanded = this.StartsExpanded;
3437
+ obj._level = 1;
3438
+ obj._visible = true;
3439
+ obj._expanded = this.StartsExpanded;
2515
3440
  assigned++;
2516
3441
  continue;
2517
3442
  }
@@ -2521,13 +3446,13 @@
2521
3446
  for (var p = 0; p < objs.length; p++) {
2522
3447
  var possibleParent = objs[p];
2523
3448
  // Trovato il parent dell'item, assegno all'item il livello giusto
2524
- if (possibleParent[this.OwnKey] == obj[this.ParentKey] && possibleParent.level == levelToAssign - 1) {
2525
- obj.level = levelToAssign;
3449
+ if (possibleParent[this.OwnKey] == obj[this.ParentKey] && possibleParent._level == levelToAssign - 1) {
3450
+ obj._level = levelToAssign;
2526
3451
  // So che questo item ha un parent. Ribadisco che il parent è espanso in base alle impostazione e stessa logica
2527
3452
  // per la visibilità del figlio
2528
- possibleParent.expanded = this.StartsExpanded;
3453
+ possibleParent._expanded = this.StartsExpanded;
2529
3454
  possibleParent.parent = true;
2530
- obj.visible = this.StartsExpanded;
3455
+ obj._visible = this.StartsExpanded;
2531
3456
  assigned++;
2532
3457
  break;
2533
3458
  }
@@ -2546,12 +3471,12 @@
2546
3471
  var obj = this.boundSource[i];
2547
3472
  // Trovo il parent con quell'id e lo espando
2548
3473
  if (obj[this.OwnKey] == key) {
2549
- obj.expanded = true;
3474
+ obj._expanded = true;
2550
3475
  for (var ic = 0; ic < this.boundSource.length; ic++) {
2551
3476
  var child = this.boundSource[ic];
2552
3477
  // Trovo tutti i child di quel parent e li rendo visibili
2553
3478
  if (child[this.ParentKey] == key)
2554
- child.visible = true;
3479
+ child._visible = true;
2555
3480
  }
2556
3481
  return;
2557
3482
  }
@@ -2567,7 +3492,7 @@
2567
3492
  var obj = this.boundSource[i];
2568
3493
  // Trovo il parent con quell'id e lo collasso
2569
3494
  if (obj[this.OwnKey] == key) {
2570
- obj.expanded = false;
3495
+ obj._expanded = false;
2571
3496
  // Collasso/nascondo tutti i child del parent
2572
3497
  this.collapseChildOfParent(key);
2573
3498
  return;
@@ -2585,10 +3510,10 @@
2585
3510
  // Trovo tutti i child di quel parent e li rendo invisibili. Se il child trovato è a sua volta un parent,
2586
3511
  // lo collasso e vado in ricorsione sui figli
2587
3512
  if (child[this.ParentKey] == parentKey && !child.parent)
2588
- child.visible = false;
3513
+ child._visible = false;
2589
3514
  else if (child[this.ParentKey] == parentKey && child.parent) {
2590
- child.expanded = false;
2591
- child.visible = false;
3515
+ child._expanded = false;
3516
+ child._visible = false;
2592
3517
  this.collapseChildOfParent(child[this.OwnKey]);
2593
3518
  }
2594
3519
  }
@@ -2623,22 +3548,29 @@
2623
3548
  * @param {ItemsSelection<any>} selectionItem Oggetto contenente lo stato attuale di selezione
2624
3549
  */
2625
3550
  EsTableComponent.prototype.handleSelectionEvaluation = function (items, selectionItem) {
2626
- var allSelected = items.length > 0;
2627
3551
  for (var i = 0; i < items.length; i++) {
2628
3552
  var itm = items[i];
3553
+ var hash = itm._hash;
3554
+ var itemGroup = itm._group ? null : this.getItemGroup(itm);
2629
3555
  // Reidrato la cache di selezione coi nuovi oggetti altrimenti non riuscirei a beccare gli indici giusti
2630
3556
  // Dopodiché la uso per calcolare istantaneamente se gli oggetti sono selezionati o no
2631
- if (this.selOrDeselCache[itm.hash])
2632
- this.selOrDeselCache[itm.hash] = itm;
2633
- if (selectionItem.all)
2634
- itm._selected = !this.selOrDeselCache[itm.hash];
2635
- else
2636
- itm._selected = !!this.selOrDeselCache[itm.hash];
2637
- allSelected = allSelected && itm._selected;
3557
+ this.rehidrateCache(itm);
3558
+ if (itm._item) {
3559
+ if (selectionItem.all)
3560
+ 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));
3561
+ else
3562
+ 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)));
3563
+ }
3564
+ else if (itm._group) {
3565
+ if (selectionItem.all)
3566
+ itm._selected = !this.group_exclusionsCache.has(hash) && this.parentTreeStatus(itm) != 'excluded';
3567
+ else
3568
+ itm._selected = this.groupsCache.has(hash) || (this.parentTreeStatus(itm) == 'included' && !this.group_exclusionsCache.has(hash));
3569
+ }
2638
3570
  }
2639
3571
  // Se tutti gli oggetti di questa pagina sono solezionati allora posso mettere il global check a true
2640
3572
  // Se sono in situazione di all-select anche metto la global checkbox, nonostante ci possano essere delle esclusioni
2641
- this.globalCheck = allSelected || selectionItem.all;
3573
+ this.globalCheck = this.boundSource.filter(function (t) { return t._group || t._item; }).every(function (t) { return t._selected; });
2642
3574
  this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
2643
3575
  // Potrebbe cambiare qualora qualcuno inserisse dati a manazza in modalità Array e desse il refresh manuale alla tabella
2644
3576
  // Comunque costa 0 quindi mi permetto di refreshare
@@ -2649,6 +3581,44 @@
2649
3581
  this.onSelectionChanged.emit(selectionItem);
2650
3582
  }
2651
3583
  };
3584
+ /**
3585
+ * Dato un oggetto trova la cella di cache in cui è registrato e aggiorna il contenuto
3586
+ *
3587
+ * @param {any} item Oggetto da aggiornare
3588
+ */
3589
+ EsTableComponent.prototype.rehidrateCache = function (item) {
3590
+ var ctx = item._hash;
3591
+ if (this.itemsCache.has(ctx))
3592
+ this.itemsCache.set(ctx, item);
3593
+ if (this.group_exclusionsCache.has(ctx))
3594
+ this.group_exclusionsCache.set(ctx, item);
3595
+ if (this.groupsCache.has(ctx))
3596
+ this.groupsCache.set(ctx, item);
3597
+ if (this.exclusionsCache.has(ctx))
3598
+ this.exclusionsCache.set(ctx, item);
3599
+ };
3600
+ /**
3601
+ * Dato un gruppo controlla ricorsivamente l'albero di cui fa parte se c'è stata una inclusione o esclusione diretta
3602
+ *
3603
+ * @param {any} grp Gruppo da controllare
3604
+ *
3605
+ * @returns {'none' | 'excluded' | 'included'}
3606
+ * 'none' se non ci sono informazioni su inclusioni o esclusioni
3607
+ * 'included' se il gruppo controllato è stato incluso in maniera esplicita dall'albero dei gruppi padri
3608
+ * 'excluded' se il gruppo controllato è stato escluso in maniera esplicita dall'albero dei gruppi padri
3609
+ */
3610
+ EsTableComponent.prototype.parentTreeStatus = function (grp) {
3611
+ if (!grp)
3612
+ return 'none';
3613
+ var parentGroup = this.rgGroupCache.get(grp._parent);
3614
+ if (!parentGroup)
3615
+ return 'none';
3616
+ if (this.group_exclusionsCache.has(parentGroup._hash))
3617
+ return 'excluded';
3618
+ if (this.groupsCache.has(parentGroup._hash))
3619
+ return 'included';
3620
+ return this.parentTreeStatus(parentGroup);
3621
+ };
2652
3622
  /**
2653
3623
  * Gestisce la selezione globale degli oggetti, sia per pagina che a livello di **SelectAll**
2654
3624
  *
@@ -2656,8 +3626,8 @@
2656
3626
  */
2657
3627
  EsTableComponent.prototype.globalCheckChanged = function (forcedVal) {
2658
3628
  if (forcedVal === void 0) { forcedVal = null; }
2659
- // Prendo tutti gli elementi presenti in questa vista che non siano gruppi
2660
- var items = this.boundSource.filter(function (t) { return !t._group; });
3629
+ // 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
3630
+ var items = this.boundSource.find(function (t) { return t._group; }) ? this.boundSource.filter(function (t) { return t._group && !t._parent; }) : this.boundSource;
2661
3631
  var itemSelection = this.handleItemsSelection(items, forcedVal, this.globalCheck);
2662
3632
  this.changed();
2663
3633
  this.onSelectionChanged.emit(itemSelection);
@@ -2669,20 +3639,21 @@
2669
3639
  *
2670
3640
  * @param {any[]} items Oggetti da selezionare o deselezionare
2671
3641
  * @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
3642
+ * @param {boolean} globalCheck Valore del check globale
2672
3643
  *
2673
3644
  * @returns {ItemsSelection<any>} Oggetto di selezione aggiornato con le informazioni sull'ultima operazione effettuata
2674
3645
  */
2675
3646
  EsTableComponent.prototype.handleItemsSelection = function (items, forcedVal, globalCheck) {
2676
3647
  if (forcedVal === void 0) { forcedVal = null; }
2677
3648
  if (globalCheck === void 0) { globalCheck = null; }
2678
- var _a, _b;
2679
- var selectionItem = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
3649
+ var _a, _b, _c;
3650
+ var si = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
2680
3651
  // Se sono in modalità di selezione singola e devo selezionare un'oggetto, per prima cosa devo deselezionare tutti gli altri
2681
- if (this.SingleSelection && ((_b = items[0]) === null || _b === void 0 ? void 0 : _b._selected)) {
3652
+ 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)) {
2682
3653
  if (items.length > 1 && forcedVal == null)
2683
3654
  throw "Tentativo di selezionare o deselezionare più di un elemento con SingleSelection attivo";
2684
3655
  if (items.length == 1 && forcedVal == null) {
2685
- selectionItem = this.handleItemsSelection(this.boundSource.filter(function (t) { return !t._group; }), false, null);
3656
+ si = this.handleItemsSelection(this.boundSource.filter(function (t) { return !t._group; }), false, null);
2686
3657
  items[0]._selected = true;
2687
3658
  }
2688
3659
  }
@@ -2692,59 +3663,385 @@
2692
3663
  // Se dev'essere overridato il valore di check effettuo l'override o col valore forzato o col valore globale
2693
3664
  if (toChange && !item.locked)
2694
3665
  item._selected = forcedVal != null ? forcedVal : this.globalCheck;
2695
- if (selectionItem.all) {
2696
- // In caso di "seleziona tutto"...
2697
- // N.B: la selOrDeselCache agisce come cache di DESELEZIONE in questo blocco di codice
2698
- if (item._selected && this.selOrDeselCache[item.hash]) {
2699
- // Oggetto selezionato: lo rimuovo dalle esclusioni di selezione
2700
- selectionItem.exclusions.splice(selectionItem.exclusions.indexOf(this.selOrDeselCache[item.hash]), 1);
2701
- delete this.selOrDeselCache[item.hash];
2702
- }
2703
- else if (!item._selected && !this.selOrDeselCache[item.hash]) {
2704
- // Oggetto deselezionato: lo aggiungo alle esclusioni di selezione
2705
- this.selOrDeselCache[item.hash] = item;
2706
- selectionItem.exclusions.push(item);
2707
- }
3666
+ // 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
3667
+ if (!toChange && globalCheck != null)
3668
+ continue;
3669
+ var allSelection = si.all;
3670
+ var isGroup = item._group;
3671
+ var isSelection = item._selected;
3672
+ var itemGroup = null, allItems = null, selectedItems = null, unselectedItems = null, allGroups = null, selectedGroups = null, unselectedGroups = null, parentGroupSelected = null, parentGroupUnselected = null;
3673
+ if (isGroup) {
3674
+ var pts = this.parentTreeStatus(item);
3675
+ parentGroupSelected = pts == 'included';
3676
+ parentGroupUnselected = pts == 'excluded';
3677
+ allItems = this.getGroupItems(si, item, null, true);
3678
+ selectedItems = this.getGroupItems(si, item, 'selected', true, allItems);
3679
+ unselectedItems = this.getGroupItems(si, item, 'unselected', true, allItems);
3680
+ allGroups = this.getGroupChildGroups(si, item, null, true);
3681
+ selectedGroups = this.getGroupChildGroups(si, item, 'selected', true, allGroups);
3682
+ unselectedGroups = this.getGroupChildGroups(si, item, 'unselected', true, allGroups);
2708
3683
  }
2709
3684
  else {
2710
- //In caso di non "seleziona tutto"...
2711
- // N.B: la selOrDeselCache agisce come cache di SELEZIONE in questo blocco di codice
2712
- if (item._selected && !this.selOrDeselCache[item.hash]) {
2713
- // Oggetto selezionato: lo aggiungo alla selezione attuale
2714
- this.selOrDeselCache[item.hash] = item;
2715
- selectionItem.items.push(item);
2716
- }
2717
- else if (!item._selected && this.selOrDeselCache[item.hash]) {
2718
- // Oggetto deselezionato: lo rimuovo dalla selezione attuale
2719
- selectionItem.items.splice(selectionItem.items.indexOf(this.selOrDeselCache[item.hash]), 1);
2720
- delete this.selOrDeselCache[item.hash];
2721
- }
3685
+ itemGroup = this.getItemGroup(item);
3686
+ parentGroupSelected = itemGroup == null ? null : itemGroup._selected;
3687
+ parentGroupUnselected = itemGroup == null ? null : !itemGroup._selected;
2722
3688
  }
3689
+ if (!this.ArrayGrouping)
3690
+ this.performSelectionOperations(si, item, allSelection, isGroup, isSelection, selectedItems, selectedGroups, unselectedItems, unselectedGroups, allItems, allGroups, parentGroupSelected, parentGroupUnselected);
3691
+ else
3692
+ this.performSimpleSelectionOperations(si, item, isGroup, isSelection, itemGroup, selectedItems, unselectedItems, allItems, allGroups);
2723
3693
  }
2724
3694
  // Imposto il check globale in base a se tutti gli elementi sono selezionati o meno.
2725
3695
  // Evito di fare queste operazioni se la selezione deriva proprio dal global Check
2726
- // Non è ottimizzatissimo mettere 2 some ma scrivere questo codice a for sono tipo 25 righe....
2727
3696
  if (globalCheck == null)
2728
- this.globalCheck = !items.some(function (t) { return !t._selected; }) && !this.boundSource.some(function (t) { return !t._selected && !t._group; });
2729
- this.finalizeSelectionInformations(selectionItem);
2730
- return selectionItem;
3697
+ this.globalCheck = !this.boundSource.some(function (t) { return !t._selected && !t._sep; });
3698
+ this.finalizeSelectionInformations(si);
3699
+ return si;
3700
+ };
3701
+ /**
3702
+ * Dato L'oggetto di selezione, l'oggetto da selezionare/deselezionare e tutti i parametri del caso effettua le operazioni che servono.
3703
+ *
3704
+ * Logica semplificata rispetto all'originale **performSelectionOperations** per lavorare in una modalità in cui tutti gli elementi sono caricati (**ArrayGrouping** = true)
3705
+ */
3706
+ EsTableComponent.prototype.performSimpleSelectionOperations = function (base, item, group, sel, itm_group, sel_itm, desel_itm, all_itms, all_grps) {
3707
+ var _this = this;
3708
+ var tripticItem = this.getTriptic('item', base);
3709
+ if (group) {
3710
+ if (sel) {
3711
+ all_grps.forEach(function (gr) { gr._selected = true; });
3712
+ if (desel_itm)
3713
+ desel_itm.forEach(function (el) { el._selected = true; _this.addItem(el, tripticItem); });
3714
+ }
3715
+ else {
3716
+ all_grps.forEach(function (gr) { gr._selected = false; });
3717
+ if (sel_itm)
3718
+ sel_itm.forEach(function (el) { el._selected = false; _this.removeItem(el, tripticItem); });
3719
+ }
3720
+ }
3721
+ else {
3722
+ if (sel) {
3723
+ this.addItem(item, tripticItem);
3724
+ if (itm_group && all_itms && all_itms.every(function (t) { return t._selected; }))
3725
+ this.selectGroup(itm_group);
3726
+ }
3727
+ else {
3728
+ this.removeItem(item, tripticItem);
3729
+ if (itm_group)
3730
+ itm_group._selected = false;
3731
+ }
3732
+ }
3733
+ };
3734
+ /**
3735
+ * Helper per selezionare un gruppo e, ricorsivamente, se tutti i gruppi sottostanti al parent sono selezionati, selezionare i gruppi padri
3736
+ *
3737
+ * @param {any} group Gruppo da selezionare
3738
+ */
3739
+ EsTableComponent.prototype.selectGroup = function (group) {
3740
+ group._selected = true;
3741
+ var parent = this.getGroupParent(group);
3742
+ if (parent && this.getGroupChildGroups(null, parent, null, true).every(function (t) { return t._selected; }))
3743
+ this.selectGroup(parent);
3744
+ };
3745
+ /**
3746
+ * Dato L'oggetto di selezione, l'oggetto da selezionare/deselezionare e tutti i parametri del caso effettua le operazioni che servono.
3747
+ *
3748
+ * La logica di questa funzione è nata essenzialmente da spam di trial & error ed è stata testata solo fino a due livelli di raggruppamento,
3749
+ * qualsiasi cosa vada oltre non è 100% detto che funzioni...
3750
+ */
3751
+ EsTableComponent.prototype.performSelectionOperations = function (base, item, all, group, sel, sel_itm, sel_grp, desel_itm, desel_grp, all_itms, all_grps, parent_incl, parent_excl) {
3752
+ var _this = this;
3753
+ var tripticGroup = this.getTriptic('group', base);
3754
+ var tripticItem = this.getTriptic('item', base);
3755
+ var tripticExcl = this.getTriptic('exclusion', base);
3756
+ var tripticgrpExcl = this.getTriptic('group_exclusion', base);
3757
+ if (group) {
3758
+ if (sel) {
3759
+ if (all || parent_incl)
3760
+ this.removeItem(item, tripticgrpExcl);
3761
+ else
3762
+ this.addItem(item, tripticGroup);
3763
+ if (sel_itm)
3764
+ sel_itm.forEach(function (el) { return _this.removeItem(el, tripticItem); });
3765
+ if (sel_grp)
3766
+ sel_grp.forEach(function (gr) { return _this.removeItem(gr, tripticGroup); });
3767
+ if (all_itms)
3768
+ all_itms.forEach(function (el) { el._selected = true; _this.removeItem(el, tripticExcl); });
3769
+ if (all_grps)
3770
+ all_grps.forEach(function (gr) { gr._selected = true; _this.removeItem(gr, tripticgrpExcl); });
3771
+ }
3772
+ else {
3773
+ if (all || parent_incl)
3774
+ this.addItem(item, tripticgrpExcl);
3775
+ else
3776
+ this.removeItem(item, tripticGroup);
3777
+ if (desel_itm)
3778
+ desel_itm.forEach(function (el) { return _this.removeItem(el, tripticExcl); });
3779
+ if (desel_grp)
3780
+ desel_grp.forEach(function (gr) { return _this.removeItem(gr, tripticExcl); });
3781
+ if (all_itms)
3782
+ all_itms.forEach(function (el) { el._selected = false; _this.removeItem(el, tripticItem); });
3783
+ if (all_grps)
3784
+ all_grps.forEach(function (gr) { gr._selected = false; _this.removeItem(gr, tripticGroup); });
3785
+ }
3786
+ }
3787
+ else {
3788
+ if (sel) {
3789
+ if ((parent_excl == null && all) || parent_incl)
3790
+ this.removeItem(item, tripticExcl);
3791
+ else
3792
+ this.addItem(item, tripticItem);
3793
+ }
3794
+ else {
3795
+ if (parent_excl || (!all && parent_excl == null))
3796
+ this.removeItem(item, tripticItem);
3797
+ else
3798
+ this.addItem(item, tripticExcl);
3799
+ }
3800
+ }
3801
+ };
3802
+ /**
3803
+ * Helper per evitare di riscrivere ogni santa volta array.splice(array.indexof(item), 1);
3804
+ */
3805
+ EsTableComponent.prototype.removeItem = function (item, triptic) {
3806
+ var index = triptic.index_cache.get(item._hash);
3807
+ if (index != null) {
3808
+ triptic.cache.delete(item._hash);
3809
+ triptic.index_cache.delete(item._hash);
3810
+ triptic.array[index] = null;
3811
+ }
3812
+ return !!index;
3813
+ };
3814
+ /**
3815
+ * Helper per evitare di riscrivere ogni santa volta array.push(item); e la gestione della
3816
+ */
3817
+ EsTableComponent.prototype.addItem = function (item, triptic) {
3818
+ if (triptic.index_cache.get(item._hash) == null) {
3819
+ var i = triptic.array.push(item) - 1;
3820
+ triptic.cache.set(item._hash, item);
3821
+ triptic.index_cache.set(item._hash, i);
3822
+ return true;
3823
+ }
3824
+ return false;
3825
+ };
3826
+ /**
3827
+ * Ottiene il trittico di selezione: L'array degli oggetti e le due cache
3828
+ */
3829
+ EsTableComponent.prototype.getTriptic = function (subject, base) {
3830
+ switch (subject) {
3831
+ case 'group':
3832
+ return new CacheTriptic(this.groupsCache, this.i_groupsCache, base.groups);
3833
+ case 'item':
3834
+ return new CacheTriptic(this.itemsCache, this.i_itemsCache, base.items);
3835
+ case 'group_exclusion':
3836
+ return new CacheTriptic(this.group_exclusionsCache, this.i_group_exclusionsCache, base.group_exclusions);
3837
+ case 'exclusion':
3838
+ return new CacheTriptic(this.exclusionsCache, this.i_exclusionsCache, base.exclusions);
3839
+ }
3840
+ };
3841
+ /**
3842
+ * Dato un oggetto restituisce il gruppo di cui fa parte, se esiste
3843
+ *
3844
+ * @param {any} item Oggetto di cui trovare il gruppo
3845
+ */
3846
+ EsTableComponent.prototype.getItemGroup = function (item) {
3847
+ var parent = this.rgGroupCache.get(item._thisKey);
3848
+ if (parent)
3849
+ return parent;
3850
+ return null;
3851
+ };
3852
+ /**
3853
+ * Data la chiave di un gruppo restituisce tutti gli oggetti con quella chiave
3854
+ *
3855
+ * @param {any} group Chiave da cercare
3856
+ * @param {'selected' | 'unselected'} status Stato degli elementi, selezionati o no
3857
+ * @param {boolean} recursive Indica se cercare solo gli elementi direttamente collegati o se prendere anche quelli dei gruppi figli
3858
+ *
3859
+ * @returns {any[]} Oggetti di tipo **_item** facenti capo alla chiave **groupKey**
3860
+ */
3861
+ EsTableComponent.prototype.getGroupItems = function (sel, group, status, recursive, allbase) {
3862
+ var e_3, _s;
3863
+ if (recursive === void 0) { recursive = false; }
3864
+ if (allbase === void 0) { allbase = null; }
3865
+ var items = [];
3866
+ if (allbase)
3867
+ items = allbase;
3868
+ else {
3869
+ if (recursive) {
3870
+ try {
3871
+ // In modalità ricorsiva prendo gli oggetti di tutte le chiavi simili che trovo
3872
+ for (var _t = __values(this.rgItemCache.keys()), _u = _t.next(); !_u.done; _u = _t.next()) {
3873
+ var key = _u.value;
3874
+ if (key.startsWith(group._thisKey))
3875
+ items.push.apply(items, __spread(this.rgItemCache.get(key)));
3876
+ }
3877
+ }
3878
+ catch (e_3_1) { e_3 = { error: e_3_1 }; }
3879
+ finally {
3880
+ try {
3881
+ if (_u && !_u.done && (_s = _t.return)) _s.call(_t);
3882
+ }
3883
+ finally { if (e_3) throw e_3.error; }
3884
+ }
3885
+ }
3886
+ else
3887
+ items = this.rgItemCache.get(group._thisKey);
3888
+ }
3889
+ items = items.filter(function (t) { return !status || (t._selected && status == 'selected') || (!t._selected && status == 'unselected'); });
3890
+ // Non trovo nessun oggetto, però magari di oggetti ne ho all'interno dell'oggetto di selezione.
3891
+ // Questo può essere vero solo se NON sono in modalità array, in caso contrario gli oggetti li devo per forza avere tutti
3892
+ if (items.length != 0 || !sel || this.arrayMode)
3893
+ return items;
3894
+ if (status == 'unselected')
3895
+ items = sel.exclusions.filter(function (t) { return t != null &&
3896
+ (!recursive && t._thisKey == group._thisKey) ||
3897
+ (recursive && t._thisKey.startsWith(group._thisKey)); });
3898
+ else if (status == 'selected')
3899
+ items = sel.items.filter(function (t) { return t != null &&
3900
+ (!recursive && t._thisKey == group._thisKey) ||
3901
+ (recursive && t._thisKey.startsWith(group._thisKey)); });
3902
+ return items;
3903
+ };
3904
+ /**
3905
+ * Data la chiave di un gruppo restituisce tutti gli oggetti con quella chiave
3906
+ *
3907
+ * @param {any} group Gruppo di cui cercare il parent
3908
+ *
3909
+ * @returns {any} Oggetto di tipo **_group** rappresentante il parent del **group** attuale
3910
+ */
3911
+ EsTableComponent.prototype.getGroupParent = function (group) {
3912
+ var parent = this.rgGroupCache.get(group._parent);
3913
+ if (parent)
3914
+ return parent;
3915
+ return null;
3916
+ };
3917
+ /**
3918
+ * Data la chiave di un gruppo restituisce tutti i gruppi figli
3919
+ *
3920
+ * @param {string} group Gruppo che rappresenta il padre di cui cercare i figli
3921
+ * @param {'selected' | 'unselected'} status Stato dei gruppi, selezionati o no
3922
+ * @param {boolean} recursive Indica se cercare solo i gruppi direttamente collegati o se prendere anche quelli dei gruppi figli
3923
+ *
3924
+ * @returns {any[]} Oggetti di tipo **_group** facenti capo alla chiave **groupKey**
3925
+ */
3926
+ EsTableComponent.prototype.getGroupChildGroups = function (sel, group, status, recursive, allbase) {
3927
+ var e_4, _s;
3928
+ if (recursive === void 0) { recursive = false; }
3929
+ if (allbase === void 0) { allbase = null; }
3930
+ var thisGroup = this.rgGroupCache.get(group._thisKey);
3931
+ var items = [];
3932
+ if (allbase)
3933
+ items = allbase;
3934
+ else {
3935
+ if (recursive) {
3936
+ try {
3937
+ // In modalità ricorsiva prendo gli oggetti di tutte le chiavi simili che trovo
3938
+ for (var _t = __values(this.rgChildGroupsCache.keys()), _u = _t.next(); !_u.done; _u = _t.next()) {
3939
+ var key = _u.value;
3940
+ if (key.startsWith(group._thisKey))
3941
+ items.push.apply(items, __spread(this.rgChildGroupsCache.get(key)));
3942
+ }
3943
+ }
3944
+ catch (e_4_1) { e_4 = { error: e_4_1 }; }
3945
+ finally {
3946
+ try {
3947
+ if (_u && !_u.done && (_s = _t.return)) _s.call(_t);
3948
+ }
3949
+ finally { if (e_4) throw e_4.error; }
3950
+ }
3951
+ }
3952
+ else
3953
+ items = this.rgChildGroupsCache.get(group._thisKey);
3954
+ }
3955
+ items = items.filter(function (t) { return !status || (t._selected && status == 'selected') || (!t._selected && status == 'unselected'); });
3956
+ // Non trovo nessun oggetto, però magari di oggetti ne ho all'interno dell'oggetto di selezione
3957
+ if (items.length != 0 || !sel)
3958
+ return items;
3959
+ if (status == 'unselected')
3960
+ items = sel.group_exclusions.filter(function (t) { return t != null && ((!recursive && t._thisRoute.length == thisGroup._thisRoute.length + 1 && t._thisRoute.startsWith(group._thisKey)) ||
3961
+ (recursive && t._thisKey.startsWith(group._thisKey))); });
3962
+ else
3963
+ items = sel.groups.filter(function (t) { return t != null && ((!recursive && t._thisRoute.length == thisGroup._thisRoute.length + 1 && t._thisRoute.startsWith(group._thisKey)) ||
3964
+ (recursive && t._thisKey.startsWith(group._thisKey))); });
3965
+ return items;
2731
3966
  };
2732
3967
  /**
2733
3968
  * Finalizza le informazioni di selezione del **ItemsSelection** corrente
2734
3969
  */
2735
3970
  EsTableComponent.prototype.finalizeSelectionInformations = function (selectionItem) {
3971
+ // Dato che le delete sono logiche dato che tengo la cache degli indici devo renderle fisiche
3972
+ var tmpGrp = [], tmpItems = [], tmpExcl = [], tmpGrpExcl = [];
3973
+ var grpRemoved = false, itemsRemoved = false, exclRemoved = false, grpExclRemoved = false;
3974
+ for (var i = 0; i < selectionItem.items.length; i++)
3975
+ if (selectionItem.items[i] != null)
3976
+ tmpItems.push(selectionItem.items[i]);
3977
+ else
3978
+ itemsRemoved = true;
3979
+ for (var i = 0; i < selectionItem.groups.length; i++)
3980
+ if (selectionItem.groups[i] != null)
3981
+ tmpGrp.push(selectionItem.groups[i]);
3982
+ else
3983
+ grpRemoved = true;
3984
+ for (var i = 0; i < selectionItem.exclusions.length; i++)
3985
+ if (selectionItem.exclusions[i] != null)
3986
+ tmpExcl.push(selectionItem.exclusions[i]);
3987
+ else
3988
+ exclRemoved = true;
3989
+ for (var i = 0; i < selectionItem.group_exclusions.length; i++)
3990
+ if (selectionItem.group_exclusions[i] != null)
3991
+ tmpGrpExcl.push(selectionItem.group_exclusions[i]);
3992
+ else
3993
+ grpExclRemoved = true;
3994
+ selectionItem.items = tmpItems;
3995
+ selectionItem.group_exclusions = tmpGrpExcl;
3996
+ selectionItem.exclusions = tmpExcl;
3997
+ selectionItem.groups = tmpGrp;
3998
+ // Le cache degli indici potrebbero avere buchi, risolvo
3999
+ if (grpRemoved)
4000
+ this.i_groupsCache = this.compactIndexMap(this.i_groupsCache);
4001
+ if (itemsRemoved)
4002
+ this.i_itemsCache = this.compactIndexMap(this.i_itemsCache);
4003
+ if (exclRemoved)
4004
+ this.i_exclusionsCache = this.compactIndexMap(this.i_exclusionsCache);
4005
+ if (grpExclRemoved)
4006
+ this.i_group_exclusionsCache = this.compactIndexMap(this.i_group_exclusionsCache);
4007
+ // Poi riprendo a fare tutto in normalità
2736
4008
  selectionItem.count = this.evaluateSelected();
2737
4009
  // Se ho fatto selezione "all" ma poi mi sono messo a togliere tutti gli elementi fino a rimanerne 0 resetto l'oggetto di selezione
2738
- if (selectionItem.count == 0 && selectionItem.all) {
4010
+ if (selectionItem.count == 0) {
4011
+ this.boundSource.forEach(function (t) { return t._selected = false; });
2739
4012
  selectionItem.all = false;
2740
4013
  selectionItem.exclusions = [];
2741
4014
  selectionItem.items = [];
4015
+ selectionItem.groups = [];
4016
+ selectionItem.group_exclusions = [];
2742
4017
  // Ripulisco la cache altrimenti mi rimane piena di tutte le esclusioni
2743
- this.selOrDeselCache = {};
4018
+ this.clearSelectionCaches();
2744
4019
  }
2745
4020
  // Se la possibilità di fare "Seleziona tutto" è abilitata allora la considero appena mi viene selezionato qualcosa
2746
4021
  this.canSelectAll = selectionItem.count > 0 && this.SelectAll;
2747
4022
  };
4023
+ /**
4024
+ * Compatta una cache di indici
4025
+ */
4026
+ EsTableComponent.prototype.compactIndexMap = function (map) {
4027
+ var e_5, _s;
4028
+ var index = 0;
4029
+ var ret = new Map();
4030
+ try {
4031
+ for (var _t = __values(map.keys()), _u = _t.next(); !_u.done; _u = _t.next()) {
4032
+ var key = _u.value;
4033
+ ret.set(key, index++);
4034
+ }
4035
+ }
4036
+ catch (e_5_1) { e_5 = { error: e_5_1 }; }
4037
+ finally {
4038
+ try {
4039
+ if (_u && !_u.done && (_s = _t.return)) _s.call(_t);
4040
+ }
4041
+ finally { if (e_5) throw e_5.error; }
4042
+ }
4043
+ return ret;
4044
+ };
2748
4045
  /**
2749
4046
  * Gestisce i click sulla tabella, gestendo eventualmente anche gli Shift + Click per selezionare un range di oggetti
2750
4047
  *
@@ -2763,7 +4060,7 @@
2763
4060
  var selecteditems = [];
2764
4061
  if (event.shiftKey && this.ShiftClick && !this.SingleSelection) {
2765
4062
  var startSelecting = false;
2766
- var items = this.boundSource.filter(function (t) { return !t.group; });
4063
+ var items = this.boundSource.filter(function (t) { return !t._group && !t._sep; });
2767
4064
  for (var i = 0; i < items.length; i++) {
2768
4065
  var t = items[i];
2769
4066
  if (startSelecting) {
@@ -2796,8 +4093,10 @@
2796
4093
  */
2797
4094
  EsTableComponent.prototype.evaluateSelected = function () {
2798
4095
  var _a;
2799
- var selectionItem = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
2800
- this.selectedObjects = selectionItem.all ? (this.View.objectcount || this.View.length) - selectionItem.exclusions.length : selectionItem.items.length;
4096
+ var si = ((_a = this.View) === null || _a === void 0 ? void 0 : _a.selection) || this.arraymodeSelection;
4097
+ var excByGroup = si.group_exclusions.reduce(function (prev, curr) { return prev + curr.count; }, 0);
4098
+ var incByGroup = si.groups.reduce(function (prev, curr) { return prev + curr.count; }, 0);
4099
+ this.selectedObjects = (si.all ? this.BaseItemsCount : incByGroup) - excByGroup + si.items.length - si.exclusions.length;
2801
4100
  return this.selectedObjects;
2802
4101
  };
2803
4102
  /**
@@ -2805,9 +4104,11 @@
2805
4104
  */
2806
4105
  EsTableComponent.prototype.selectAllOrResetSelection = function () {
2807
4106
  var selectionItem = this.View.selection || this.arraymodeSelection;
2808
- this.selOrDeselCache = {};
4107
+ this.clearSelectionCaches();
2809
4108
  selectionItem.all = !selectionItem.all;
2810
4109
  selectionItem.exclusions = [];
4110
+ selectionItem.groups = [];
4111
+ selectionItem.group_exclusions = [];
2811
4112
  selectionItem.items = [];
2812
4113
  // Ripulisco gli stati UI di selezione globale se l'ho disattivata
2813
4114
  if (!selectionItem.all) {
@@ -2817,7 +4118,7 @@
2817
4118
  this.finalizeSelectionInformations(selectionItem);
2818
4119
  this.onSelectionChanged.emit(selectionItem);
2819
4120
  // Dopo aver resettato direttamente il solo oggetto this.View.selection devo anche riallineare a tutti gli oggetti bindati
2820
- this.evaluateSelection(this.viewMode ? this.View.items : this.View, selectionItem);
4121
+ this.evaluateSelection(this.boundSource, selectionItem);
2821
4122
  };
2822
4123
  // #endregion
2823
4124
  // #region Gestione Paginazione
@@ -2827,9 +4128,9 @@
2827
4128
  * @param {number} page Numero di pagine da aggiungere (o sottrarre, se negativo) alla pagina attuale
2828
4129
  */
2829
4130
  EsTableComponent.prototype.addToPage = function (page) {
2830
- if (!(this.View instanceof AppSearch) && !(this.SearchView instanceof AppSearch) && !(this.View instanceof ReportDefinition))
2831
- return;
2832
- this.goToPage((this.SearchView || this.View).page + page);
4131
+ var _a;
4132
+ var view = this.MainGroupView ? this.MainGroupView : this.View;
4133
+ this.goToPage((((_a = (this.SearchView || view)) === null || _a === void 0 ? void 0 : _a.page) || 0) + page);
2833
4134
  };
2834
4135
  /**
2835
4136
  * Sposta la ricerca alla pagina specificata
@@ -2837,21 +4138,35 @@
2837
4138
  * @param {number} page Pagina a cui navigare
2838
4139
  */
2839
4140
  EsTableComponent.prototype.goToPage = function (page) {
2840
- if (!(this.View instanceof AppSearch) && !(this.SearchView instanceof AppSearch) && !(this.View instanceof ReportDefinition))
4141
+ var view = this.MainGroupView ? this.MainGroupView : this.View;
4142
+ if (!view.page || !view.pages)
2841
4143
  return;
2842
- var appSearchElement = this.SearchView || this.View;
4144
+ var appSearchElement = this.SearchView || view;
2843
4145
  if (page === 0 || page > appSearchElement.pages)
2844
4146
  return;
2845
4147
  appSearchElement.page = page;
2846
4148
  this.arrayPulsanti = this.getPagesArray(6, appSearchElement.page, appSearchElement.pages);
2847
- this.emitSearchRequest(false);
4149
+ var hasGroupings = !!this.MainGroupView;
4150
+ this.emitSearchRequest(false, hasGroupings ? view : null);
2848
4151
  };
2849
4152
  /**
2850
4153
  * Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest**
2851
4154
  * per comunicare al componente che utilizza questa tabella che i dati sono da aggiornare
2852
4155
  */
2853
- EsTableComponent.prototype.onItemsPerPageChanged = function () {
2854
- this.emitSearchRequest(true);
4156
+ EsTableComponent.prototype.onItemsPerPageChanged = function (newIpp) {
4157
+ this.PagerOptions.View.itemsperpageoverride = newIpp;
4158
+ this.changed();
4159
+ if (this.MainGroupView)
4160
+ this.emitSearchRequest(true, this.MainGroupView);
4161
+ else
4162
+ this.emitSearchRequest(true);
4163
+ };
4164
+ /**
4165
+ * Evento richiamato sul cambio della paginazione. Verrà richiamato l'evento **emitSearchRequest** con la vista del separatore
4166
+ */
4167
+ EsTableComponent.prototype.onGroupItemsPerPageChanged = function (pager, newIpp) {
4168
+ pager.view.itemsperpageoverride = newIpp;
4169
+ this.emitSearchRequest(true, pager.view);
2855
4170
  };
2856
4171
  // #endregion
2857
4172
  // #region Gestione Export
@@ -3002,12 +4317,12 @@
3002
4317
  * @returns {any} Router link generato in base al parametri
3003
4318
  */
3004
4319
  EsTableComponent.prototype.generateRouterLink = function (path, parameterProps, item) {
3005
- if (this.DynamicTableRouterLinkCache[item.hash + path]) {
3006
- return this.DynamicTableRouterLinkCache[item.hash + path];
4320
+ if (this.DynamicTableRouterLinkCache[item._hash + path]) {
4321
+ return this.DynamicTableRouterLinkCache[item._hash + path];
3007
4322
  }
3008
4323
  else {
3009
4324
  var link = this.getRouterLink(path, parameterProps, item);
3010
- this.DynamicTableRouterLinkCache[item.hash + path] = link;
4325
+ this.DynamicTableRouterLinkCache[item._hash + path] = link;
3011
4326
  return link;
3012
4327
  }
3013
4328
  };
@@ -3190,11 +4505,13 @@
3190
4505
  for (var i = 0; i < items.length; i++) {
3191
4506
  var item = items[i];
3192
4507
  // Prima di calcolare l'hash rimuovo le proprietà interne prima che mi scompensino i calcoli successivi
3193
- delete item._selected;
3194
- delete item.hash;
3195
- var hash = this.hashExts.hashObject(item);
4508
+ var tmp = Object.assign({}, items[i]);
4509
+ delete tmp._selected;
4510
+ delete tmp._visible;
4511
+ delete tmp._hash;
4512
+ var hash = this.hashExts.hashObject(tmp);
3196
4513
  usedHashesCache[hash] = usedHashesCache[hash] ? usedHashesCache[hash] + 1 : 1;
3197
- item.hash = hash + (usedHashesCache[hash] > 1 ? "_" + usedHashesCache[hash] : "");
4514
+ item._hash = hash + (usedHashesCache[hash] > 1 ? "_" + usedHashesCache[hash] : "");
3198
4515
  }
3199
4516
  };
3200
4517
  /**
@@ -3223,13 +4540,15 @@
3223
4540
  viewProviders: [{ provide: localizations.LocalizationService, useClass: EsTableLoc }],
3224
4541
  changeDetection: core.ChangeDetectionStrategy.OnPush,
3225
4542
  encapsulation: core.ViewEncapsulation.None,
3226
- template: "<!-- Patacchino di autoaggiornamento -->\r\n<div class=\"w-100\" *ngIf=\"AutoUpdate\">\r\n <div class=\"pull-right\">\r\n {{'Update every' | localize : lc}}&nbsp;<input [readonly]=\"autoUpdate\" maxlength=\"3\" class=\"form-control est-custom-input\" type=\"text\" [(ngModel)]=\"seconds\" />&nbsp;{{'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>&nbsp;{{'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>&nbsp;\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 }}:&nbsp;\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>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">15</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">30</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">45</span>&nbsp;|&nbsp;\r\n <span class=\"est-rg-ipp-sel\">100</span>&nbsp;|&nbsp;\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\">&lt;</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\">&gt;</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 &nbsp;\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\">&times;</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>",
3227
- 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-rg-hdr{font-weight:700}.est-rg-agg{font-style:italic}.est-rg{background-color:hsla(0,0%,46.7%,.4666666666666667)!important}.est-rg-ipp{text-align:left}.est-rg-ipp,.est-rg-page{width:50%;display:inline-block}.est-rg-page{text-align:right}.est-l-1{padding-right:20px!important}.est-l-2{padding-left:20px!important;padding-right:40px!important}.est-l-3{padding-left:40px!important;padding-right:60px!important}.est-l-4{padding-left:60px!important;padding-right:80px!important}.est-l-5{padding-left:800px!important;padding-right:100px!important}.est-rg-sep{font-size:12px}.est-rg-ipp-sel{color:#8b4513;margin-left:3px}.est-rg-page-sel{color:#2e8b57;margin-left:3px;margin-right:3px}.est-rg-ipp-sel-all{color:#708090;margin-left:3px;margin-right:3px}.est-rg-page-next,.est-rg-page-prev{color:#000;font-weight:700}"]
4543
+ template: "<!-- Patacchino di autoaggiornamento -->\r\n<div class=\"w-100\" *ngIf=\"AutoUpdate\">\r\n <div class=\"pull-right\">\r\n {{'Update every' | localize : lc}}&nbsp;<input [readonly]=\"autoUpdate\" maxlength=\"3\" class=\"form-control est-custom-input\" type=\"text\" [(ngModel)]=\"seconds\" />&nbsp;{{'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>&nbsp;{{'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>&nbsp;\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=\"btn est-page-sel {{p.cssClass}}\" (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 &nbsp;\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\">&times;</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>",
4544
+ 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}"]
3228
4545
  },] }
3229
4546
  ];
3230
4547
  EsTableComponent.ctorParameters = function () { return [
3231
4548
  { type: forms.NgControl, decorators: [{ type: core.Self }, { type: core.Optional }] },
3232
4549
  { type: preferences.PreferencesService, decorators: [{ type: core.Optional }] },
4550
+ { type: EsTableDefaultable, decorators: [{ type: core.Optional }, { type: core.Inject, args: [EST_DEFAULTS,] }] },
4551
+ { type: String, decorators: [{ type: core.Optional }, { type: core.Inject, args: [EST_LOCALE,] }] },
3233
4552
  { type: localizations.LocalizationService },
3234
4553
  { type: core.ChangeDetectorRef },
3235
4554
  { type: extensions.HashingService },
@@ -3255,7 +4574,7 @@
3255
4574
  CellActionPropagates: [{ type: core.Input }],
3256
4575
  UseCustomCells: [{ type: core.Input }],
3257
4576
  MaxHeight: [{ type: core.Input }],
3258
- Class: [{ type: core.Input }],
4577
+ ContainerClass: [{ type: core.Input }],
3259
4578
  XLSXExport: [{ type: core.Input }],
3260
4579
  CSVExport: [{ type: core.Input }],
3261
4580
  AllSearch: [{ type: core.Input }],
@@ -3266,14 +4585,12 @@
3266
4585
  RemovalCondition: [{ type: core.Input }],
3267
4586
  Export: [{ type: core.Input }],
3268
4587
  ShiftClick: [{ type: core.Input }],
3269
- ShowPaging: [{ type: core.Input }],
3270
4588
  HidePaging: [{ type: core.Input }],
3271
4589
  HidePagingCount: [{ type: core.Input }],
3272
4590
  HidePagingButtons: [{ type: core.Input }],
3273
4591
  ContextMenu: [{ type: core.Input }],
3274
4592
  ExportFileName: [{ type: core.Input }],
3275
4593
  TableClass: [{ type: core.Input }],
3276
- CountLabel: [{ type: core.Input }],
3277
4594
  ExportFunction: [{ type: core.Input }],
3278
4595
  HasHeaderGroup: [{ type: core.Input }],
3279
4596
  HasSecondaryHeaderGroup: [{ type: core.Input }],
@@ -3299,9 +4616,12 @@
3299
4616
  OwnKey: [{ type: core.Input }],
3300
4617
  StartsExpanded: [{ type: core.Input }],
3301
4618
  SavePreferences: [{ type: core.Input }],
4619
+ PagingStyle: [{ type: core.Input }],
4620
+ RowGroupingPagingStyle: [{ type: core.Input }],
3302
4621
  SecondarySource: [{ type: core.Input }],
3303
4622
  TertiarySource: [{ type: core.Input }],
3304
4623
  UseSelectionCache: [{ type: core.Input }],
4624
+ ShowItemGroupsColumns: [{ type: core.Input }],
3305
4625
  onOrderChanged: [{ type: core.Output }],
3306
4626
  onSearchRequest: [{ type: core.Output }],
3307
4627
  onSelectionChanged: [{ type: core.Output }],
@@ -3315,26 +4635,22 @@
3315
4635
  ArraymodeItemsPerPage: [{ type: core.Input }]
3316
4636
  };
3317
4637
 
3318
- /**
3319
- * Modello di configurazione per L'EsTable
3320
- */
4638
+ /** Modello di configurazione per L'EsTable */
3321
4639
  var EsTableModuleConfig = /** @class */ (function () {
3322
4640
  function EsTableModuleConfig() {
3323
4641
  }
3324
4642
  return EsTableModuleConfig;
3325
4643
  }());
3326
4644
 
3327
- /**
3328
- * Classe di localizzazione per il componente **TablePagerComponent**
3329
- */
4645
+ /** Classe di localizzazione per il componente **TablePagerComponent** */
3330
4646
  var TablePagerLoc = /** @class */ (function (_super) {
3331
4647
  __extends(TablePagerLoc, _super);
3332
- /**
3333
- * @ignore
3334
- */
4648
+ /** @ignore */
3335
4649
  function TablePagerLoc(LOC_LOCALE) {
3336
4650
  var _this = _super.call(this, LOC_LOCALE !== null && LOC_LOCALE !== void 0 ? LOC_LOCALE : 'it-IT') || this;
3337
4651
  _super.prototype.set.call(_this, "en->it", "All", ["Tutto"]);
4652
+ _super.prototype.set.call(_this, "en->it", "Shown Elements", ["Elementi visualizzati"]);
4653
+ _super.prototype.set.call(_this, "en->it", "Shown Groups", ["Gruppi visualizzati"]);
3338
4654
  _super.prototype.set.call(_this, "en->it", "Are you sure you want to retrieve all results?", ["Si è sicuri di voler caricare tutti i risultati?"]);
3339
4655
  _super.prototype.set.call(_this, "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"]);
3340
4656
  return _this;
@@ -3349,33 +4665,36 @@
3349
4665
  ]; };
3350
4666
 
3351
4667
  // Angular
3352
- /**
3353
- * Componente che si occupa della paginazione di una tabella
3354
- */
4668
+ /** Componente che si occupa della paginazione di una tabella */
3355
4669
  var TablePagerComponent = /** @class */ (function () {
3356
- /**
3357
- * @ignore
3358
- */
3359
- function TablePagerComponent(msgExts, lc) {
4670
+ /** @ignore */
4671
+ function TablePagerComponent(msgExts, lc, cdr, locale) {
3360
4672
  this.msgExts = msgExts;
3361
4673
  this.lc = lc;
3362
- /**
3363
- * Indica se deve mostrare un warning quando si cercano di solezionare come elementi da visualizzare "Tutti"
3364
- */
4674
+ this.cdr = cdr;
4675
+ this.locale = locale;
4676
+ /** Indica se deve mostrare un warning quando si cercano di solezionare come elementi da visualizzare "Tutti" */
3365
4677
  this.WarnOnAll = true;
3366
- /**
3367
- * Indica se dare la possibilità o meno di selezionare "Tutti" nelle opzioni di paginazione
3368
- */
4678
+ /** Indica se dare la possibilità o meno di selezionare "Tutti" nelle opzioni di paginazione */
3369
4679
  this.AllSearch = true;
3370
- /**
3371
- * Placeholder che identifica il "Tutti"
3372
- */
4680
+ /** Placeholder che identifica il "Tutti" */
3373
4681
  this.DefaultAll = 999999;
3374
- /**
3375
- * Output invocato quando il numero di elementi per pagina viene modificato da un click utente
3376
- */
4682
+ /** Indica se attivare la modalità gruppo con stili più snelli per apparire sotto ai raggruppamenti */
4683
+ this.GroupMode = false;
4684
+ /** Indica se utilizzare il conteggio dei gruppi o degli oggetti */
4685
+ this.GroupCount = false;
4686
+ /** Indica se visualizzare il numero totale di oggeti presenti */
4687
+ this.ShowCount = true;
4688
+ /** Output invocato quando il numero di elementi per pagina viene modificato da un click utente */
3377
4689
  this.pagingSelected = new core.EventEmitter();
4690
+ /** Opzioni di paginazione */
4691
+ this.PagingOptions = [10, 15, 30, 45, 100];
3378
4692
  }
4693
+ TablePagerComponent.prototype.ngOnInit = function () {
4694
+ this.Model = this.View ? this.View.itemsperpageoverride : this.CurrentPageSize;
4695
+ if (this.AllSearch)
4696
+ this.PagingOptions.push(this.DefaultAll);
4697
+ };
3379
4698
  /**
3380
4699
  * Funzione richiamata dal template quando un utente clicca su un numero di paginazione.
3381
4700
  *
@@ -3386,10 +4705,19 @@
3386
4705
  TablePagerComponent.prototype.choice = function (pageSize) {
3387
4706
  var _this = this;
3388
4707
  if (pageSize == this.DefaultAll && this.WarnOnAll) {
3389
- 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"), function () { _this.pagingSelected.emit(pageSize); });
4708
+ 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"), function () { _this.pagingSelected.emit(pageSize); _this.Model = pageSize; }, function () {
4709
+ // Dio solo sa perché mi tocca fare sta roba... qui dentro per qualche motivo la CD non prende
4710
+ var prevModel = _this.Model;
4711
+ _this.Model = null;
4712
+ _this.cdr.detectChanges();
4713
+ _this.Model = prevModel;
4714
+ _this.cdr.detectChanges();
4715
+ });
3390
4716
  }
3391
- else
4717
+ else {
3392
4718
  this.pagingSelected.emit(pageSize);
4719
+ this.Model = pageSize;
4720
+ }
3393
4721
  };
3394
4722
  return TablePagerComponent;
3395
4723
  }());
@@ -3397,20 +4725,29 @@
3397
4725
  { type: core.Component, args: [{
3398
4726
  selector: "app-paging",
3399
4727
  viewProviders: [{ provide: localizations.LocalizationService, useClass: TablePagerLoc }],
3400
- template: "<!--Se non ho almeno 10 elementi non ha senso far vedere le opzioni di paginazione-->\r\n<ng-container *ngIf=\"View ? ((View.objectcount && View.objectcount >= 10) || View.pagingavailable) : !Hidden\">\r\n {{'Paging' | localize : lc}}:&nbsp;\r\n <span class=\"app-link app-inline\"\r\n [class.app-bold]=\"View ? View.itemsperpageoverride && View.itemsperpageoverride == 10 : CurrentPageSize == 10\"\r\n (click)=\"choice(10);\">\r\n 10\r\n </span>&nbsp;|&nbsp;\r\n\r\n <span class=\"app-link app-inline\"\r\n [class.app-bold]=\"View ? View.itemsperpageoverride && View.itemsperpageoverride == 15 : CurrentPageSize == 15\"\r\n (click)=\"choice(15);\">\r\n 15\r\n </span>&nbsp;|&nbsp;\r\n\r\n <span class=\"app-link app-inline\"\r\n [class.app-bold]=\"View ? View.itemsperpageoverride && View.itemsperpageoverride == 30 : CurrentPageSize == 30\"\r\n (click)=\"choice(30);\">\r\n 30\r\n </span>&nbsp;|&nbsp;\r\n\r\n <span class=\"app-link app-inline\"\r\n [class.app-bold]=\"View ? View.itemsperpageoverride && View.itemsperpageoverride == 45 : CurrentPageSize == 45\"\r\n (click)=\"choice(45);\">\r\n 45\r\n </span>&nbsp;|&nbsp;\r\n\r\n <span class=\"app-link app-inline\"\r\n [class.app-bold]=\"View ? View.itemsperpageoverride && View.itemsperpageoverride == 100 : CurrentPageSize == 100\"\r\n (click)=\"choice(100);\">\r\n 100\r\n </span><span *ngIf=\"AllSearch\">&nbsp;|&nbsp;</span>\r\n <span *ngIf=\"AllSearch\" class=\"app-link app-inline\"\r\n [class.app-bold]=\"View ? View.itemsperpageoverride && View.itemsperpageoverride == DefaultAll : CurrentPageSize == DefaultAll\"\r\n (click)=\"choice(DefaultAll);\">\r\n {{'All' | localize : lc}}\r\n </span>\r\n</ng-container>"
4728
+ template: "<ng-container *ngIf=\"!Hidden\">\r\n <span class=\"est-fs-14\"> {{(GroupMode ? 'Shown Groups' : 'Shown Elements') | localize : lc}}:&nbsp;</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\">&nbsp;/&nbsp;{{PagerCount | number : '0.0-0' : locale}}\r\n </span>\r\n</ng-container>",
4729
+ encapsulation: core.ViewEncapsulation.None,
4730
+ changeDetection: core.ChangeDetectionStrategy.OnPush,
4731
+ 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}"]
3401
4732
  },] }
3402
4733
  ];
3403
4734
  TablePagerComponent.ctorParameters = function () { return [
3404
4735
  { type: extensions.MessageService },
3405
- { type: localizations.LocalizationService }
4736
+ { type: localizations.LocalizationService },
4737
+ { type: core.ChangeDetectorRef },
4738
+ { type: String, decorators: [{ type: core.Optional }, { type: core.Inject, args: [EST_LOCALE,] }] }
3406
4739
  ]; };
3407
4740
  TablePagerComponent.propDecorators = {
3408
4741
  CurrentPageSize: [{ type: core.Input }],
3409
4742
  View: [{ type: core.Input }],
3410
- Hidden: [{ type: core.Input }],
3411
4743
  WarnOnAll: [{ type: core.Input }],
3412
4744
  AllSearch: [{ type: core.Input }],
3413
4745
  DefaultAll: [{ type: core.Input }],
4746
+ GroupMode: [{ type: core.Input }],
4747
+ GroupCount: [{ type: core.Input }],
4748
+ ShowCount: [{ type: core.Input }],
4749
+ PagerCount: [{ type: core.Input }],
4750
+ Hidden: [{ type: core.Input }],
3414
4751
  pagingSelected: [{ type: core.Output }]
3415
4752
  };
3416
4753
 
@@ -3421,7 +4758,8 @@
3421
4758
  return {
3422
4759
  ngModule: EsTableModule,
3423
4760
  providers: [
3424
- { provide: EST_LOCALE, useValue: (config === null || config === void 0 ? void 0 : config.locale) || 'it-IT' }
4761
+ { provide: EST_LOCALE, useValue: (config === null || config === void 0 ? void 0 : config.locale) || 'it-IT' },
4762
+ { provide: EST_DEBUG, useValue: (config === null || config === void 0 ? void 0 : config.debugMode) || false }
3425
4763
  ]
3426
4764
  };
3427
4765
  };
@@ -3437,7 +4775,9 @@
3437
4775
  modal.ModalModule,
3438
4776
  dropdown.BsDropdownModule,
3439
4777
  ngxCsv.CsvModule,
3440
- ngxContextmenu.ContextMenuModule
4778
+ ngxContextmenu.ContextMenuModule,
4779
+ select.MatSelectModule,
4780
+ input.MatInputModule
3441
4781
  ],
3442
4782
  declarations: [EsTh, EsTd, EsTableComponent, EsTdDirective, EsThDirective, TablePagerComponent],
3443
4783
  providers: [extensions.UtilityService, extensions.ExportService, extensions.HashingService, extensions.MessageService],
@@ -3456,9 +4796,9 @@
3456
4796
  exports.AppOrdering = AppOrdering;
3457
4797
  exports.AppSearch = AppSearch;
3458
4798
  exports.CornerMenuOption = CornerMenuOption;
3459
- exports.EsTableColumn = EsTableColumn;
3460
4799
  exports.EsTableColumnsDefinition = EsTableColumnsDefinition;
3461
4800
  exports.EsTableComponent = EsTableComponent;
4801
+ exports.EsTableDefaultable = EsTableDefaultable;
3462
4802
  exports.EsTableModule = EsTableModule;
3463
4803
  exports.EsTableModuleConfig = EsTableModuleConfig;
3464
4804
  exports.EsTableOperationDefinition = EsTableOperationDefinition;
@@ -3478,10 +4818,12 @@
3478
4818
  exports.ReportRow = ReportRow;
3479
4819
  exports.ɵa = EsTableLoc;
3480
4820
  exports.ɵb = EST_LOCALE;
3481
- exports.ɵc = EsTdDirective;
3482
- exports.ɵd = EsThDirective;
3483
- exports.ɵe = TablePagerComponent;
3484
- exports.ɵf = TablePagerLoc;
4821
+ exports.ɵc = EST_DEBUG;
4822
+ exports.ɵd = EST_DEFAULTS;
4823
+ exports.ɵe = EsTdDirective;
4824
+ exports.ɵf = EsThDirective;
4825
+ exports.ɵg = TablePagerComponent;
4826
+ exports.ɵh = TablePagerLoc;
3485
4827
 
3486
4828
  Object.defineProperty(exports, '__esModule', { value: true });
3487
4829