@esfaenza/es-table 11.2.122 → 11.2.123-beta1

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 (40) hide show
  1. package/bundles/esfaenza-es-table.umd.js +431 -233
  2. package/bundles/esfaenza-es-table.umd.js.map +1 -1
  3. package/bundles/esfaenza-es-table.umd.min.js +1 -1
  4. package/bundles/esfaenza-es-table.umd.min.js.map +1 -1
  5. package/esfaenza-es-table.d.ts +8 -4
  6. package/esfaenza-es-table.metadata.json +1 -1
  7. package/esm2015/esfaenza-es-table.js +9 -5
  8. package/esm2015/lib/components/es-table/es_table.component.js +120 -49
  9. package/esm2015/lib/components/es-td/es_td.component.js +10 -52
  10. package/esm2015/lib/components/es-th/es_th.component.js +2 -2
  11. package/esm2015/lib/components/pipes/est-renderer.pipe.js +36 -0
  12. package/esm2015/lib/components/pipes/est-routerlink.pipe.js +37 -0
  13. package/esm2015/lib/components/pipes/est_editor.pipe.js +36 -0
  14. package/esm2015/lib/core/CopyPasteDetector.js +4 -2
  15. package/esm2015/lib/core/Logger.js +23 -0
  16. package/esm2015/lib/core/handlers/ColumnMetadataHandler.js +14 -12
  17. package/esm2015/lib/core/handlers/DynamicModeHandler.js +59 -37
  18. package/esm2015/lib/core/handlers/SelectionHandler.js +46 -50
  19. package/esm2015/lib/core/handlers/UtilitiesHandler.js +2 -5
  20. package/esm2015/lib/directives/es_th.directive.js +9 -2
  21. package/esm2015/lib/domain/externals/EsTableColumnsDefinition.js +4 -3
  22. package/esm2015/lib/domain/externals/ItemPropEditableReference.js +1 -1
  23. package/esm2015/lib/domain/internals/EsTableColumn.js +2 -2
  24. package/esm2015/lib/es-table.module.js +42 -19
  25. package/fesm2015/esfaenza-es-table.js +412 -221
  26. package/fesm2015/esfaenza-es-table.js.map +1 -1
  27. package/lib/components/es-table/es_table.component.d.ts +24 -8
  28. package/lib/components/es-td/es_td.component.d.ts +6 -34
  29. package/lib/components/pipes/est-renderer.pipe.d.ts +12 -0
  30. package/lib/components/pipes/est-routerlink.pipe.d.ts +17 -0
  31. package/lib/components/pipes/est_editor.pipe.d.ts +12 -0
  32. package/lib/core/Logger.d.ts +7 -0
  33. package/lib/core/handlers/DynamicModeHandler.d.ts +11 -23
  34. package/lib/core/handlers/SelectionHandler.d.ts +16 -3
  35. package/lib/core/handlers/UtilitiesHandler.d.ts +4 -1
  36. package/lib/directives/es_th.directive.d.ts +25 -0
  37. package/lib/domain/externals/EsTableColumnsDefinition.d.ts +3 -9
  38. package/lib/domain/externals/ItemPropEditableReference.d.ts +4 -0
  39. package/lib/domain/internals/EsTableColumn.d.ts +3 -1
  40. package/package.json +1 -1
@@ -12,7 +12,6 @@ import { MatSelectModule } from '@angular/material/select';
12
12
  import { MatInputModule } from '@angular/material/input';
13
13
  import { MatTooltipModule } from '@angular/material/tooltip';
14
14
  import { FormsAndValidationsModule } from '@esfaenza/forms-and-validations';
15
- import { DomSanitizer } from '@angular/platform-browser';
16
15
  import { ModalModule } from 'ngx-bootstrap/modal';
17
16
  import { BsDropdownModule } from 'ngx-bootstrap/dropdown';
18
17
  import { ContextMenuModule } from '@esfaenza/ngx-contextmenu';
@@ -340,6 +339,8 @@ class EsThDirective {
340
339
  this.thType = null;
341
340
  /** Sorgente dei valori disponibili per questa cella se il **Type** è di tipo 'enum' */
342
341
  this.thSource = null;
342
+ /** Opzioni da applicare all'editor di questa colonna */
343
+ this.thEditorOptions = {};
343
344
  }
344
345
  }
345
346
  EsThDirective.decorators = [
@@ -373,7 +374,12 @@ EsThDirective.propDecorators = {
373
374
  thStaticContent: [{ type: Input }],
374
375
  thBackgroundColor: [{ type: Input }],
375
376
  thAlignment: [{ type: Input }],
376
- thFormat: [{ type: Input }]
377
+ thFormat: [{ type: Input }],
378
+ thEditorName: [{ type: Input }],
379
+ thEditorOptions: [{ type: Input }],
380
+ thRendererName: [{ type: Input }],
381
+ thRoutePath: [{ type: Input }],
382
+ thRouteParameterProperties: [{ type: Input }]
377
383
  };
378
384
 
379
385
  /** Direttiva che rappresenta il template dell'editor di una cella all'interno della tabella */
@@ -600,7 +606,7 @@ class EsTableColumn {
600
606
  * @param {boolean} pinned Indica se è una colonna pinnata
601
607
  * @param {number} pinnedWidth Indica la dimensione da assegnare a questa colonna quando è pinnata
602
608
  * @param {TemplateRef<any>} template Indica il template da usare per mostrare il testo dell'Header
603
- * @param {{ tmpl: TemplateRef<any>, content: string }[]} parentTemplates Indica la lista di template padri collegata a questo header, rappresentati come Template o come stringa qualora fosse generato automaticamente (caso **Multi**)
609
+ * @param {{ id: string, tmpl: TemplateRef<any>, content: string }[]} parentTemplates Indica la lista di template padri collegata a questo header, rappresentati come Template o come stringa qualora fosse generato automaticamente (caso **Multi**)
604
610
  * @param {boolean} multi Indica che la colonna deriva da una direttiva **Multi**
605
611
  * @param {string} multiContent Indica il contenuto della direttiva **Multi** per questa colonna
606
612
  */
@@ -1073,7 +1079,7 @@ class ColumnMetadataHandler {
1073
1079
  return;
1074
1080
  /****** STEP 1: Creo l'output dei raggruppamenti per header in modo da non dovermi preoccupare di celle non inizializzate ******/
1075
1081
  let expandedGroups = [];
1076
- let visibleUnpinnedLeafs = infos.leafs.filter((t) => t.thVisible && !t.thPinned);
1082
+ let visibleUnpinnedLeafs = infos.leafs.filter((t) => t.thVisible && t.thIf && !t.thPinned);
1077
1083
  for (let l = 0; l < infos.groupingLevel; l++) {
1078
1084
  expandedGroups.push([]);
1079
1085
  for (let i = 0; i < visibleUnpinnedLeafs.length; i++)
@@ -1083,7 +1089,7 @@ class ColumnMetadataHandler {
1083
1089
  let orderedLeafs = [];
1084
1090
  for (let i = 0; i < this.est.OrderDirectives.length; i++) {
1085
1091
  let leaf = infos.thsCache[this.est.OrderDirectives[i]];
1086
- if (leaf.thVisible && !leaf.thPinned)
1092
+ if (leaf.thVisible && leaf.thIf && !leaf.thPinned)
1087
1093
  orderedLeafs.push(leaf);
1088
1094
  }
1089
1095
  /****** STEP 3: Creo l'array group con tutti i riferimenti del caso ******/
@@ -1107,7 +1113,7 @@ class ColumnMetadataHandler {
1107
1113
  }
1108
1114
  }
1109
1115
  }
1110
- /****** STEP 4: Compatto nell'elemento finale su cui bindarmi ******/
1116
+ /****** STEP 4: Compatto nell'elemento finale su cui bindarmi. L'ID assegnato è SOLO per ottimizzare gli ngFor ******/
1111
1117
  currentParent = "";
1112
1118
  let currentSpan = 0;
1113
1119
  let finalHeaders = [];
@@ -1115,25 +1121,25 @@ class ColumnMetadataHandler {
1115
1121
  let levelArray = [];
1116
1122
  finalHeaders.push(levelArray);
1117
1123
  if (this.est.Selection || this.est.HasPinnedColumns)
1118
- levelArray.push({ Span: 1, Template: null, Pinned: this.est.HasPinnedColumns });
1124
+ levelArray.push({ ID: "_base_sel_pinned", Span: 1, Template: null, Pinned: this.est.HasPinnedColumns });
1119
1125
  for (let h = 0; h < expandedGroups[l].length; h++) {
1120
1126
  let item = expandedGroups[l][h];
1121
1127
  if (item == currentParent)
1122
1128
  currentSpan++;
1123
1129
  else {
1124
1130
  if (currentSpan > 0)
1125
- levelArray.push({ Span: currentSpan, Template: currentParent ? infos.thsCache[currentParent].Template : null, Content: currentParent ? infos.thsCache[currentParent]._multi_content : null, Borders: !!currentParent });
1131
+ levelArray.push({ ID: `${currentParent ? infos.thsCache[currentParent].th : 'noth'}_${currentSpan}`, Span: currentSpan, Template: currentParent ? infos.thsCache[currentParent].Template : null, Content: currentParent ? infos.thsCache[currentParent]._multi_content : null, Borders: !!currentParent });
1126
1132
  currentSpan = 1;
1127
1133
  currentParent = item;
1128
1134
  }
1129
1135
  }
1130
1136
  // Ultima aggiunta che altrimenti mi rimarrebbe in cache
1131
- levelArray.push({ Span: currentSpan, Template: currentParent ? infos.thsCache[currentParent].Template : null, Content: currentParent ? infos.thsCache[currentParent]._multi_content : null, Borders: !!currentParent });
1137
+ levelArray.push({ ID: `${currentParent ? infos.thsCache[currentParent].th : 'noth'}_${currentSpan}`, Span: currentSpan, Template: currentParent ? infos.thsCache[currentParent].Template : null, Content: currentParent ? infos.thsCache[currentParent]._multi_content : null, Borders: !!currentParent });
1132
1138
  // Aggiungo i pezzettini per la rimozione e gli export, se presenti
1133
1139
  if (this.est.Removal)
1134
- levelArray.push({ Span: 1, Template: null });
1140
+ levelArray.push({ ID: "_base_removal", Span: 1, Template: null });
1135
1141
  if (this.est.Export || this.est.HiddenColumns || this.est.ColumnsOrdering || this.est.CornerMenuOptions)
1136
- levelArray.push({ Span: 1, Template: null });
1142
+ levelArray.push({ ID: "_base_extra_opts", Span: 1, Template: null });
1137
1143
  currentSpan = 0;
1138
1144
  currentParent = "";
1139
1145
  }
@@ -1169,9 +1175,9 @@ class ColumnMetadataHandler {
1169
1175
  if (parent) {
1170
1176
  th = thsCache[parent];
1171
1177
  if (!th.thEmpty && !th._multi_content)
1172
- parentsPrepend.unshift({ tmpl: th.Template });
1178
+ parentsPrepend.unshift({ id: th.th, tmpl: th.Template });
1173
1179
  else if (!th.thEmpty && th._multi_content)
1174
- parentsPrepend.unshift({ content: th._multi_content });
1180
+ parentsPrepend.unshift({ id: th.th, content: th._multi_content });
1175
1181
  jumps++;
1176
1182
  }
1177
1183
  } while (parent);
@@ -1232,7 +1238,9 @@ class ColumnMetadataHandler {
1232
1238
  let newContext = [];
1233
1239
  this.est.OrderDirectives.forEach(o => {
1234
1240
  let contextItem = context.filter(t => t.ID == o)[0];
1235
- newContext.push(contextItem);
1241
+ // potrebbe esser undefined nel caso ci fossero colonne sotto thIf
1242
+ if (contextItem)
1243
+ newContext.push(contextItem);
1236
1244
  });
1237
1245
  this.est.TMPRowTDs[this.est.RowContexts[i]] = newContext;
1238
1246
  }
@@ -1448,7 +1456,7 @@ class EsTableColumnsDefinition {
1448
1456
  * @param {string} EditorName Nome dell'editor da utilizzare per la modifica di questo campo
1449
1457
  * @param {string} RendererName Nome del renderer da utilizzare per visualizzare questo campo
1450
1458
  */
1451
- constructor(Description, PropertyName, RoutePath = null, RouteParameterProperties = null, DataOrder = null, ColumnOrder = null, Visible = true, Clss = null, Orderable = true, HeaderWraps = false, PropertyType = null, PropertySource = [], EditorName = "", RendererName = "", EditorOptions = {}, Pinned = false, Grouping = "") {
1459
+ constructor(Description, PropertyName, RoutePath = null, RouteParameterProperties = null, DataOrder = null, ColumnOrder = null, Visible = true, Clss = null, Orderable = true, HeaderWraps = false, PropertyType = null, PropertySource = [], EditorName = "", RendererName = "", EditorOptions = {}, Pinned = false, PinnedWidth = 150, Pinnable = true, Grouping = "") {
1452
1460
  this.Description = Description;
1453
1461
  this.PropertyName = PropertyName;
1454
1462
  this.RoutePath = RoutePath;
@@ -1465,8 +1473,9 @@ class EsTableColumnsDefinition {
1465
1473
  this.RendererName = RendererName;
1466
1474
  this.EditorOptions = EditorOptions;
1467
1475
  this.Pinned = Pinned;
1476
+ this.PinnedWidth = PinnedWidth;
1477
+ this.Pinnable = Pinnable;
1468
1478
  this.Grouping = Grouping;
1469
- this.edits = {};
1470
1479
  }
1471
1480
  static build(parsObj) {
1472
1481
  return new EsTableColumnsDefinition(parsObj.Description, parsObj.PropertyName, parsObj.RoutePath, parsObj.RouteParameterProperties, parsObj.DataOrder, parsObj.ColumnOrder, parsObj.Visible || true, parsObj.Clss, parsObj.Orderable || true, parsObj.HeaderWraps, parsObj.PropertyType, parsObj.PropertySource, parsObj.EditorName, parsObj.RendererName, parsObj.Pinned, parsObj.Grouping);
@@ -1479,42 +1488,6 @@ class DynamicModeHandler {
1479
1488
  constructor(est) {
1480
1489
  this.est = est;
1481
1490
  }
1482
- /**
1483
- * Metodo di supporto alla creazione di un router link parametrizzato all'oggetto corrente utilizzato nella modalità dinamica
1484
- *
1485
- * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
1486
- * @param {string[]} parameterProps Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
1487
- * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
1488
- * @param {GenericItem} item Oggetto generico collegato a questo contesto
1489
- *
1490
- * @returns {any} Router link generato in base al parametri
1491
- */
1492
- generateRouterLink(path, parameterProps, item) {
1493
- if (this.est.DynamicTableRouterLinkCache[item._hash + path]) {
1494
- return this.est.DynamicTableRouterLinkCache[item._hash + path];
1495
- }
1496
- else {
1497
- let link = this.getRouterLink(path, parameterProps, item);
1498
- this.est.DynamicTableRouterLinkCache[item._hash + path] = link;
1499
- return link;
1500
- }
1501
- }
1502
- /**
1503
- * Crea un router link
1504
- *
1505
- * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
1506
- * @param {string[]} pars Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
1507
- * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
1508
- * @param {GenericItem} item Oggetto generico collegato a questo contesto
1509
- *
1510
- * @returns {any} Router link generato in base al parametri
1511
- */
1512
- getRouterLink(path, pars, item) {
1513
- for (let i = 0; i < pars.length; i++)
1514
- path = path.replace('{' + i + '}', item.properties[pars[i]]);
1515
- path = path.replace(/'/g, '"').replace(/ /g, '');
1516
- return JSON.parse(path);
1517
- }
1518
1491
  /** Se non ho l'Input **DynamicRowColumnsDefinition** in modalità dinamica lo riempio con il default nome della colonna = testo della colonna */
1519
1492
  eventuallyReviewDynamicColumns() {
1520
1493
  // Senza oggetti esco
@@ -1533,6 +1506,61 @@ class DynamicModeHandler {
1533
1506
  else
1534
1507
  this.est.UserDefinedDynamicCols = true;
1535
1508
  }
1509
+ /** Genera partendo dalle **DynamicRowColumnsDefinition** la lista di **EsThDirective** e **EsTdDirective** che servono per la tabella */
1510
+ emitThsAndTdsBasedOnDynamicDefinition() {
1511
+ // Senza dynamic columns esco
1512
+ if (!this.est.DynamicRowColumnsDefinition || this.est.DynamicRowColumnsDefinition.length == 0)
1513
+ return null;
1514
+ let ths = [];
1515
+ let tds = [];
1516
+ for (let i = 0; i < this.est.DynamicRowColumnsDefinition.length; i++) {
1517
+ let col = this.est.DynamicRowColumnsDefinition[i];
1518
+ ths.push(this.getTh(col));
1519
+ tds.push(this.getTd(col));
1520
+ }
1521
+ return { ths, tds };
1522
+ }
1523
+ /** @ignore Helper */
1524
+ getTh(col) {
1525
+ var ret = new EsThDirective(null);
1526
+ ret.th = col.PropertyName;
1527
+ ret.thPinned = col.Pinned;
1528
+ ret.thPinnable = col.Pinnable;
1529
+ ret.thPinnedWidth = col.PinnedWidth;
1530
+ ret.thVisible = col.Visible;
1531
+ ret.thOrder = col.DataOrder;
1532
+ ret.thOrderable = col.Orderable;
1533
+ ret.thWrap = col.HeaderWraps;
1534
+ ret.thClass = col.Clss;
1535
+ ret.thProperty = col.PropertyName;
1536
+ ret.thType = col.PropertyType;
1537
+ ret.thSource = col.PropertySource;
1538
+ ret.thEditorName = col.EditorName;
1539
+ ret.thEditorOptions = col.EditorOptions;
1540
+ ret.thRendererName = col.RendererName;
1541
+ ret.thRoutePath = col.RoutePath;
1542
+ ret.thRouteParameterProperties = col.RouteParameterProperties;
1543
+ //ret.thFixed = col.Fixed;
1544
+ //ret.thResizable = col.Resizable;
1545
+ //ret.thGroupClass = col.GroupClass;
1546
+ //ret.thGroup = col.Group;
1547
+ //ret.thAggregation = col.Aggregation;
1548
+ //ret.thMulti = col.Multi;
1549
+ //ret.thStaticContent = col.StaticContent;
1550
+ //ret.thBackgroundColor = col.BackgroundColor;
1551
+ //ret.thAlignment = col.Alignment;
1552
+ //ret.thFormat = col.Format;
1553
+ return ret;
1554
+ }
1555
+ /** @ignore Helper */
1556
+ getTd(col) {
1557
+ var ret = new EsTdDirective(null);
1558
+ ret.td = col.PropertyName;
1559
+ ret.tdClass = col.Clss;
1560
+ //ret.tdAlignment = col.Alignment;
1561
+ //ret.tdFormat = col.Format;
1562
+ return ret;
1563
+ }
1536
1564
  }
1537
1565
 
1538
1566
  /** Classe contenente la gestione della modalità gerarchica */
@@ -3079,65 +3107,61 @@ class SelectionHandler {
3079
3107
  * @param {{ row: number, column: number }} firstSelectionOverride Permette di overridare il primo elemento selezionato
3080
3108
  */
3081
3109
  singleCellSelection(event, row, column, firstSelectionOverride) {
3110
+ // Recupero la selezione precedente se presente come punto di partenza
3082
3111
  var first = firstSelectionOverride || this.lastSingleSelection;
3112
+ //Il punto di arrivo, che diventerà il prossimo punto di partenza, è la selezione corrente
3113
+ this.lastSingleSelection = { row, column };
3083
3114
  this.clearTextSelection(event);
3084
- // Nella selezione a range chissene frega se c'è o meno lo shift, si ragiona sempre a range
3085
- if (event.shiftKey && first) {
3086
- this.clearSelectionStatus({ row, column });
3087
- let rowAddition = row < first.row ? -1 : +1;
3088
- let columnAddition = column < first.column ? -1 : +1;
3089
- for (let ir = first.row; ir != row + rowAddition; ir += rowAddition) {
3090
- let firstRow = ir == first.row;
3091
- let lastRow = ir == row;
3092
- for (let ic = first.column; ic != column + columnAddition; ic += columnAddition) {
3093
- let firstCol = ic == first.column;
3094
- let lastCol = ic == column;
3095
- this.est.selectionStatus[ir][ic].selected = true;
3096
- this.est.selectionStatus[ir][ic].lborder = columnAddition > 0 ? firstCol : lastCol;
3097
- if (ic > 0)
3098
- this.est.selectionStatus[ir][ic - 1].roverlaps = this.est.selectionStatus[ir][ic].lborder;
3099
- this.est.selectionStatus[ir][ic].tborder = rowAddition > 0 ? firstRow : lastRow;
3100
- this.est.selectionStatus[ir][ic].rborder = columnAddition > 0 ? lastCol : firstCol;
3101
- if (this.est.selectionStatus[ir][ic + 1])
3102
- this.est.selectionStatus[ir][ic + 1].loverlaps = this.est.selectionStatus[ir][ic].rborder;
3103
- this.est.selectionStatus[ir][ic].bborder = rowAddition > 0 ? lastRow : firstRow;
3104
- }
3105
- }
3106
- this.lastSingleSelection = { row, column };
3107
- }
3108
- else {
3109
- // Ripulisco escludendo l'oggetto attuale che eventualmente ci penso io a deseezionare
3110
- this.clearSelectionStatus({ row, column });
3111
- let item = this.est.selectionStatus[row][column];
3112
- item.selected = !item.selected;
3113
- item.lborder = item.selected;
3114
- if (column > 0)
3115
- this.est.selectionStatus[row][column - 1].roverlaps = item.lborder;
3116
- item.tborder = item.selected;
3117
- item.rborder = item.selected;
3118
- if (this.est.selectionStatus[row][column + 1])
3119
- this.est.selectionStatus[row][column + 1].loverlaps = item.rborder;
3120
- item.bborder = item.selected;
3121
- this.lastSingleSelection = { row, column };
3122
- }
3115
+ this.clearSelectionStatusExcluding(this.lastSingleSelection);
3116
+ this.setSelectionStatusBorders(event.range && first ? first : this.lastSingleSelection, this.lastSingleSelection);
3123
3117
  // Ora che non è attaccato direttamente all'html devo fare un markforcheck finite le operazioni sui grouping
3124
3118
  this.est.cdr.markForCheck();
3125
3119
  }
3120
+ setSelectionStatusBorders(from, to) {
3121
+ let rowAddition = to.row < from.row ? -1 : +1;
3122
+ let columnAddition = to.column < from.column ? -1 : +1;
3123
+ let singleItem = from == to;
3124
+ for (let ir = from.row; ir != to.row + rowAddition; ir += rowAddition) {
3125
+ let firstRow = ir == from.row;
3126
+ let lastRow = ir == to.row;
3127
+ for (let ic = from.column; ic != to.column + columnAddition; ic += columnAddition) {
3128
+ let firstCol = ic == from.column;
3129
+ let lastCol = ic == to.column;
3130
+ let current = this.est.selectionStatus[ir][ic];
3131
+ let prevColumn = ic > 0 ? this.est.selectionStatus[ir][ic - 1] : null;
3132
+ let nextcolumn = this.est.selectionStatus[ir][ic + 1];
3133
+ let prevRow = ir > 0 ? this.est.selectionStatus[ir - 1][ic] : null;
3134
+ let nextRow = this.est.selectionStatus[ir + 1] ? this.est.selectionStatus[ir + 1][ic] : null;
3135
+ current.selected = singleItem ? !current.selected : true;
3136
+ current.lborder = !current.selected ? false : columnAddition > 0 ? firstCol : lastCol;
3137
+ current.tborder = !current.selected ? false : rowAddition > 0 ? firstRow : lastRow;
3138
+ current.rborder = !current.selected ? false : columnAddition > 0 ? lastCol : firstCol;
3139
+ current.bborder = !current.selected ? false : rowAddition > 0 ? lastRow : firstRow;
3140
+ if (prevRow)
3141
+ prevRow.boverlaps = current.tborder;
3142
+ if (nextRow)
3143
+ nextRow.toverlaps = current.bborder;
3144
+ if (prevColumn)
3145
+ prevColumn.roverlaps = current.lborder;
3146
+ if (nextcolumn)
3147
+ nextcolumn.loverlaps = current.rborder;
3148
+ }
3149
+ }
3150
+ }
3126
3151
  /**
3127
3152
  * Helper per ripulire lo stato di selezione delle singole celle della tabella, ad esclusione di una singola coordinata
3128
3153
  *
3129
3154
  * @param {{row: number, column: number}} exclusion Coordinata da escludere nella pulizia
3130
3155
  */
3131
- clearSelectionStatus(exclusion) {
3156
+ clearSelectionStatusExcluding(exclusion) {
3132
3157
  for (let row in this.est.selectionStatus) {
3133
3158
  for (let column in this.est.selectionStatus[row]) {
3134
- if (!exclusion || (exclusion && (row != exclusion.row.toString() || column != exclusion.column.toString()))) {
3135
- this.est.selectionStatus[row][column].selected = false;
3136
- this.est.selectionStatus[row][column].lborder = false;
3137
- this.est.selectionStatus[row][column].tborder = false;
3138
- this.est.selectionStatus[row][column].rborder = false;
3139
- this.est.selectionStatus[row][column].bborder = false;
3140
- }
3159
+ // Se è l'elemento che ho escluso dal cleanup, skippo
3160
+ if (exclusion && row == exclusion.row.toString() && column == exclusion.column.toString())
3161
+ continue;
3162
+ // Altrimenti pulisco
3163
+ let curr = this.est.selectionStatus[row][column];
3164
+ curr.selected = curr.lborder = curr.rborder = curr.tborder = curr.bborder = curr.loverlaps = curr.roverlaps = curr.toverlaps = curr.boverlaps = false;
3141
3165
  }
3142
3166
  }
3143
3167
  }
@@ -3167,10 +3191,10 @@ class SelectionHandler {
3167
3191
  */
3168
3192
  clearTextSelection(event) {
3169
3193
  // Seleziono del testo ma non ho shift premuto -> ignoro la selezione
3170
- if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && !event.shiftKey)
3194
+ if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && !event.range)
3171
3195
  return false;
3172
3196
  // Seleziono del testo e ho shift premuto -> annullo la selezione del testo
3173
- if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && event.shiftKey)
3197
+ if ((event.view.getSelection().type == 'Range' || event.view.getSelection().toString().length > 0) && event.range)
3174
3198
  this.est.utiExts.clearTextSelection();
3175
3199
  }
3176
3200
  /**
@@ -3316,10 +3340,7 @@ class UtilitiesHandler {
3316
3340
  for (let i = min; i <= max; i++)
3317
3341
  if (i !== 1)
3318
3342
  result.push({ val: i, cssClass: (i === page ? 'btn-main app-white-text' : 'app-white-button') });
3319
- result.push({
3320
- val: lastPage,
3321
- cssClass: (lastPage === page ? 'btn-main app-white-text' : 'app-white-button')
3322
- });
3343
+ result.push({ val: lastPage, cssClass: (lastPage === page ? 'btn-main app-white-text' : 'app-white-button') });
3323
3344
  }
3324
3345
  return result;
3325
3346
  }
@@ -3394,15 +3415,35 @@ class CopyPasteDetector {
3394
3415
  });
3395
3416
  }
3396
3417
  }
3418
+ CopyPasteDetector.ɵprov = ɵɵdefineInjectable({ factory: function CopyPasteDetector_Factory() { return new CopyPasteDetector(); }, token: CopyPasteDetector, providedIn: "root" });
3397
3419
  CopyPasteDetector.decorators = [
3398
- { type: Injectable }
3420
+ { type: Injectable, args: [{ providedIn: "root" },] }
3399
3421
  ];
3400
3422
  CopyPasteDetector.ctorParameters = () => [];
3401
3423
 
3424
+ /** Classe che fornisce dei metodi di estensione in grado di riconoscere e dispatchare l'evento copia e incolla lanciato su una pagina web */
3425
+ class Logger {
3426
+ /** @ignore */
3427
+ constructor(debugMode) {
3428
+ this.debugMode = debugMode;
3429
+ }
3430
+ log(text) {
3431
+ if (this.debugMode)
3432
+ console.log("[@esfaenza/es-table @ " + (new Date()).toISOString() + "] " + text);
3433
+ }
3434
+ }
3435
+ Logger.ɵprov = ɵɵdefineInjectable({ factory: function Logger_Factory() { return new Logger(ɵɵinject(EST_DEBUG, 8)); }, token: Logger, providedIn: "root" });
3436
+ Logger.decorators = [
3437
+ { type: Injectable, args: [{ providedIn: "root" },] }
3438
+ ];
3439
+ Logger.ctorParameters = () => [
3440
+ { type: Boolean, decorators: [{ type: Optional }, { type: Inject, args: [EST_DEBUG,] }] }
3441
+ ];
3442
+
3402
3443
  /** Componente che permette di rappresentare una griglia di valori */
3403
3444
  class EsTableComponent {
3404
3445
  /** @ignore */
3405
- constructor(ngControl, prefService, deafults, locale, lc, cdr, utilities_H, utiExts, expExts, dateExts, msgExts, copyPasteDetector, clipboardService) {
3446
+ constructor(ngControl, prefService, deafults, locale, lc, cdr, utilities_H, utiExts, expExts, dateExts, msgExts, copyPasteDetector, clipboardService, logger) {
3406
3447
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
3407
3448
  this.ngControl = ngControl;
3408
3449
  this.prefService = prefService;
@@ -3417,6 +3458,7 @@ class EsTableComponent {
3417
3458
  this.msgExts = msgExts;
3418
3459
  this.copyPasteDetector = copyPasteDetector;
3419
3460
  this.clipboardService = clipboardService;
3461
+ this.logger = logger;
3420
3462
  /** Subject utilizzato internamente lato EsTable per causare il Focus lato componente di Input */
3421
3463
  this.FocusSubject = new Subject();
3422
3464
  /** Se vengono effettuati 2 click a distanza inferiore a questi Millisecondi viene considerato un doppio click */
@@ -3722,9 +3764,19 @@ class EsTableComponent {
3722
3764
  /** @ignore */
3723
3765
  this.propagateChange = (_) => { };
3724
3766
  /** Funzione di trackby per il body che dovrebbe evitare il 90% delle change detection */
3725
- this.bodyTrackBy = (index, item) => item._hash;
3767
+ this.bodyTrackBy = (_, item) => item._hash;
3768
+ /** Funzione di trackby generica per tutti gli oggetti che hanno il campo id */
3769
+ this.idTrackBy = (_, item) => item.id;
3770
+ /** Funzione di trackby generica per tutti gli oggetti che hanno il campo PropertyName */
3771
+ this.PropertyNameTrackBy = (_, item) => item.PropertyName;
3772
+ /** Funzione di trackby generica per tutti gli oggetti che hanno il campo ID */
3773
+ this.IDTrackBy = (_, item) => item.ID;
3774
+ /** Funzione di trackby generica per tutti gli oggetti che hanno il campo ID */
3775
+ this.valTrackBy = (_, item) => item.val;
3726
3776
  // Range selection Experimentals
3727
3777
  this.mouseIsDown = false;
3778
+ this.rangeSelected = false;
3779
+ this.rangeStartWasIgnored = false;
3728
3780
  this.firstCoordinates = null;
3729
3781
  //* Piango
3730
3782
  this.EsTdsCache = {};
@@ -3771,7 +3823,7 @@ class EsTableComponent {
3771
3823
  return;
3772
3824
  let shouldEmit = !t.item._selected;
3773
3825
  t.item._selected = true;
3774
- this.selection_H.clearSelectionStatus();
3826
+ this.selection_H.clearSelectionStatusExcluding(null);
3775
3827
  var itemSelection = this.selection_H.handleItemsSelection([t.item]);
3776
3828
  this.changed();
3777
3829
  if (shouldEmit)
@@ -4070,7 +4122,7 @@ class EsTableComponent {
4070
4122
  }
4071
4123
  /** 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 */
4072
4124
  internalPostBoundSource() {
4073
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
4125
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
4074
4126
  let View = this.View;
4075
4127
  let tdsD = this.EsTdsDirective.length == 0 ? ((_c = (_b = (_a = this.EsTableTemplate) === null || _a === void 0 ? void 0 : _a.Template) === null || _b === void 0 ? void 0 : _b.EsTdsDirective) === null || _c === void 0 ? void 0 : _c.length) > 0 ? (_e = (_d = this.EsTableTemplate) === null || _d === void 0 ? void 0 : _d.Template) === null || _e === void 0 ? void 0 : _e.EsTdsDirective : this.EsTdsDirective : this.EsTdsDirective;
4076
4128
  let thsD = this.EsThsDirective.length == 0 ? ((_h = (_g = (_f = this.EsTableTemplate) === null || _f === void 0 ? void 0 : _f.Template) === null || _g === void 0 ? void 0 : _g.EsThsDirective) === null || _h === void 0 ? void 0 : _h.length) > 0 ? (_k = (_j = this.EsTableTemplate) === null || _j === void 0 ? void 0 : _j.Template) === null || _k === void 0 ? void 0 : _k.EsThsDirective : this.EsThsDirective : this.EsThsDirective;
@@ -4078,6 +4130,7 @@ class EsTableComponent {
4078
4130
  let tds = tdsD && tdsD.length > 0 ? tdsD.toArray() : [];
4079
4131
  // Se non ho colonne dinamiche ma sono in modalità dinamica (lo capisco perché c'è una view piena di genericitem) metto il default delle colonne
4080
4132
  this.dynamicMode_H.eventuallyReviewDynamicColumns();
4133
+ // Gestisce la richiesta per gruppi o per singoli oggetti
4081
4134
  this.bindDisplayToLoadedItemsOrGroups(View);
4082
4135
  // Questo dev'essere per forza lanciato dopo **bindDisplayToLoadedItemsOrGroups** dato che è lì che alcune cose vengono valorizzate
4083
4136
  this.setupPagingInformations();
@@ -4088,16 +4141,24 @@ class EsTableComponent {
4088
4141
  let si = this.viewMode ? view.selection : this.arraymodeSelection;
4089
4142
  // N.B: Rispettare l'ordine di queste 3 macrocategorie è VITALE
4090
4143
  // ************************************* Sistemazioni di TH, TD, e visibilità varie *************************************
4091
- // Espando i th e i td multipli duplicandoli
4092
- let ret = this.columnMetadata_H.expandMultiThsAndTds(ths, tds, itemsAndGroups);
4093
- ths = ret.expThs;
4094
- tds = ret.expTds;
4144
+ // Se ho definizioni dinamiche, prima di qualsiasi altra cosa devo trasformarle in th/td in modo che poi il codice qui sotto faccia le sue magie
4145
+ if (!this.arrayMode && ((_l = this.DynamicRowColumnsDefinition) === null || _l === void 0 ? void 0 : _l.length) > 0) {
4146
+ this.logger.log("Generating ths and tds from Dynamic definition");
4147
+ let ret = this.dynamicMode_H.emitThsAndTdsBasedOnDynamicDefinition();
4148
+ ths = ret.ths;
4149
+ tds = ret.tds;
4150
+ }
4095
4151
  // Gestione delle view in modalità report, i th e i td vengono rigenerati dalle configurazioni della view
4096
4152
  if (!this.arrayMode && view.report_columns) {
4153
+ this.logger.log("Generating ths and tds from report results");
4097
4154
  let ret = this.reportMode_H.generateThsAndTdsFromView(view);
4098
4155
  ths = ret.ths;
4099
4156
  tds = ret.tds;
4100
4157
  }
4158
+ // Espando i th e i td multipli duplicandoli
4159
+ let ret = this.columnMetadata_H.expandMultiThsAndTds(ths, tds, itemsAndGroups);
4160
+ ths = ret.expThs;
4161
+ tds = ret.expTds;
4101
4162
  // Genero la cache dei th da usare da qui in poi, dopo avergli lasciato fare le sue cose in caso ci siano dei multi o dei report
4102
4163
  for (let i = 0; i < ths.length; i++) {
4103
4164
  let th = ths[i];
@@ -4261,6 +4322,7 @@ class EsTableComponent {
4261
4322
  * @param {EsTdDirective[]} tds Celle della tabella
4262
4323
  */
4263
4324
  evaluateRowTds(ths, tds) {
4325
+ var _a;
4264
4326
  if (tds.length == 0)
4265
4327
  return;
4266
4328
  let columnsCache = {};
@@ -4293,13 +4355,14 @@ class EsTableComponent {
4293
4355
  PinnedWidth: thCasted.thPinnedWidth,
4294
4356
  GroupHeader: false,
4295
4357
  GroupAggregation: false,
4296
- Visible: columnsCache[td.td].visible, Wraps: false,
4358
+ Visible: columnsCache[td.td].visible,
4359
+ Wraps: false,
4297
4360
  Class: td.tdClass,
4298
4361
  Template: thCasted.thGroup && !this.ShowItemGroupsColumns ? null : td.Template,
4299
4362
  Multi: td._multi,
4300
4363
  MultiProp: td._multi ? td.td.split('_')[0] : null,
4301
4364
  MultiIndex: td._multi ? td.td.split('_')[1] : null,
4302
- Alignment: td.tdAlignment || th.thAlignment,
4365
+ Alignment: (_a = (td.tdAlignment || th.thAlignment)) === null || _a === void 0 ? void 0 : _a.toLowerCase(),
4303
4366
  Format: td.tdFormat || th.thFormat,
4304
4367
  PropertyName: th.thProperty,
4305
4368
  PropertyType: th.thType,
@@ -4369,7 +4432,24 @@ class EsTableComponent {
4369
4432
  let toAdd;
4370
4433
  if (th.thIf || th.thGroup) {
4371
4434
  let thClass = (th.thClass || '') + (th.thGroup ? " est-col-min" : "");
4372
- toAdd = { Pinned: columnsListCache[th.th].pinned, Fixed: th.thFixed, PinnedWidth: th.thPinnedWidth, ID: th.th, Visible: th.thVisible, Class: thClass, Order: th.thOrder, Orderable: th.thOrderable, Template: th.Template, Content: th.thStaticContent, Wrap: th.thWrap, LeftBorder: th._lbord, RightBorder: th._rbord, Multi: th._multi, MultiContent: th._multi_content };
4435
+ toAdd = {
4436
+ Pinned: columnsListCache[th.th].pinned,
4437
+ Fixed: th.thFixed,
4438
+ PinnedWidth: th.thPinnedWidth,
4439
+ ID: th.th,
4440
+ Visible: th.thVisible,
4441
+ Class: thClass,
4442
+ Order: th.thOrder,
4443
+ Orderable: th.thOrderable,
4444
+ Template: th.Template,
4445
+ // Se non è nessun contenuto né nessun template mostro semplicemente l'ID dell'header
4446
+ Content: th.thStaticContent || th.Template ? '' : th.th,
4447
+ Wrap: th.thWrap,
4448
+ LeftBorder: th._lbord,
4449
+ RightBorder: th._rbord,
4450
+ Multi: th._multi,
4451
+ MultiContent: th._multi_content
4452
+ };
4373
4453
  this.TMPRowTHs.push(toAdd);
4374
4454
  // Se ho un modello che deve funzionare a rowgrouping ma non è ancora stata effettuata nessuna ricerca sui gruppi principali (groupingsUndefined)
4375
4455
  // li genero e mando la prima ricerca che dev'essere spedita al backend per il primo caricamento dei gruppi
@@ -4466,7 +4546,7 @@ class EsTableComponent {
4466
4546
  * @param {boolean} forcedVal Valore forzato di check da assegnare agli oggetti
4467
4547
  */
4468
4548
  globalCheckChanged(forcedVal = null) {
4469
- this.selection_H.clearSelectionStatus();
4549
+ this.selection_H.clearSelectionStatusExcluding(null);
4470
4550
  // 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
4471
4551
  let items = this.boundSource.find(t => t._group) ? this.boundSource.filter(t => t._group && !t._parent) : this.boundSource;
4472
4552
  var itemSelection = this.selection_H.handleItemsSelection(items, forcedVal, this.globalCheck);
@@ -4485,7 +4565,7 @@ class EsTableComponent {
4485
4565
  */
4486
4566
  handleClick(event, item) {
4487
4567
  this.selection_H.clearTextSelection(event);
4488
- this.selection_H.clearSelectionStatus();
4568
+ this.selection_H.clearSelectionStatusExcluding(null);
4489
4569
  let selecteditems = [];
4490
4570
  if (event.shiftKey && this.ShiftClick && !this.SingleSelection) {
4491
4571
  let startSelecting = false;
@@ -4706,24 +4786,34 @@ class EsTableComponent {
4706
4786
  * @param {any} $event Evento nativo javascript
4707
4787
  * @param {TdElement} rowItem Riferimento a binder della riga
4708
4788
  * @param {any} item Item che rappresenta il contesto su cui è stato effettuato un click
4709
- * @param {number} rowIndex Indice della riga
4710
4789
  */
4711
- dbClickEditOrSingleClickRowSelection($event, rowItem, item, rowIndex) {
4712
- var _a, _b;
4790
+ dbClickEditOrSingleClickRowSelection($event, rowItem, item) {
4791
+ // Prima cosa da fare è controllare se ci sono dei range lasciati da operazioni precedenti (se applicabile) e ripulirli
4792
+ if (this.rangeSelected && !$event.ctrlKey && this.Selection) {
4793
+ this.logger.log("clearing previously selected range");
4794
+ this.selection_H.clearSelectionStatusExcluding(null);
4795
+ this.rangeSelected = false;
4796
+ return;
4797
+ }
4713
4798
  // Modalità Editable, gestisco i doppi click senza però rallentare la modalità di selezione a range
4714
4799
  if (this.Editable) {
4715
4800
  // Secondo click: se il timer non è scaduto è un doppio click ed eseguo il resto
4716
4801
  if (this.cellDbClickTimer) {
4802
+ this.logger.log("handling doubleclick on editable cell: " + (rowItem.PropertyName ? 'edit mode for property ' + rowItem.PropertyName : 'no property set, fallback to simple click'));
4717
4803
  if (rowItem.PropertyName)
4718
4804
  this.setupUserEdit(rowItem, item);
4805
+ else
4806
+ this.handleRowClick($event, item, this.Selection, true);
4719
4807
  this.clearCellClickTimer();
4720
4808
  return;
4721
4809
  }
4722
4810
  // Primo click: non fa niente e se il tempo per il secondo click scade resetta tutto
4723
4811
  this.cellDbClickTimer = setTimeout(() => {
4724
4812
  this.clearCellClickTimer();
4725
- if (!this.RangeSelection)
4813
+ if (!this.RangeSelection || !this.mouseIsDown) {
4814
+ this.logger.log("time's up for second click, handling single click");
4726
4815
  this.handleRowClick($event, item, this.Selection, true);
4816
+ }
4727
4817
  }, this.doubleClickBufferMs);
4728
4818
  }
4729
4819
  // In modalità a range la creazione del range è gestita dai mousedown, move ed up...
@@ -4734,8 +4824,7 @@ class EsTableComponent {
4734
4824
  if ($event.ctrlKey)
4735
4825
  return;
4736
4826
  // Tutti i click su una cella già in edit non devono effettuare la selezione della riga
4737
- if ((((_a = this.DynamicRowColumnsDefinition) === null || _a === void 0 ? void 0 : _a.length) > 0 && rowItem.edits && ((_b = rowItem.edits[item._hash]) === null || _b === void 0 ? void 0 : _b._editing)) ||
4738
- rowItem._editing)
4827
+ if (rowItem._editing)
4739
4828
  return;
4740
4829
  // Per evitare di rallentare a prescindere
4741
4830
  if (!this.Editable) {
@@ -4817,14 +4906,12 @@ class EsTableComponent {
4817
4906
  // Stessa cosa se ho custom cell dato che la gestione dei click viene affidata ai singoli TD
4818
4907
  if ($event.ctrlKey || (this.UseCustomCells && !internalCall))
4819
4908
  return true;
4820
- if (selection && !item.locked && !item._sep && !item._group) {
4821
- this.selection_H.clearSelectionStatus();
4909
+ if (selection)
4910
+ this.selection_H.clearSelectionStatusExcluding(null);
4911
+ if (selection && !item.locked && !item._sep && !item._group)
4822
4912
  this.handleClick($event, item);
4823
- }
4824
- else if (item._group) {
4825
- this.selection_H.clearSelectionStatus();
4913
+ else if (item._group)
4826
4914
  this.handleGroupClick(item);
4827
- }
4828
4915
  // Ora che non è attaccato direttamente all'html devo fare un markforcheck finite le operazioni sui grouping
4829
4916
  this.cdr.markForCheck();
4830
4917
  }
@@ -4845,15 +4932,11 @@ class EsTableComponent {
4845
4932
  */
4846
4933
  setupUserEdit(rowItem, item) {
4847
4934
  var _a;
4848
- this.selection_H.clearSelectionStatus();
4935
+ this.selection_H.clearSelectionStatusExcluding(null);
4849
4936
  if (this.Editable && rowItem.PropertyName) {
4850
- if (((_a = this.DynamicRowColumnsDefinition) === null || _a === void 0 ? void 0 : _a.length) > 0) {
4851
- rowItem.edits[item._hash] = { _editing: true, old_value: item.properties[rowItem.PropertyName] };
4852
- }
4853
- else {
4854
- rowItem._editing = true;
4855
- rowItem.old_value = item[rowItem.PropertyName];
4856
- }
4937
+ let dynMode = ((_a = this.DynamicRowColumnsDefinition) === null || _a === void 0 ? void 0 : _a.length) > 0;
4938
+ rowItem._editing = true;
4939
+ rowItem.old_value = dynMode ? item.properties[rowItem.PropertyName] : item[rowItem.PropertyName];
4857
4940
  }
4858
4941
  this.cdr.detectChanges();
4859
4942
  setTimeout(() => { this.FocusSubject.next(); });
@@ -4868,7 +4951,7 @@ class EsTableComponent {
4868
4951
  finalizeUserEdit(rowItem, item, columnIndex) {
4869
4952
  var _a;
4870
4953
  let dynMode = ((_a = this.DynamicRowColumnsDefinition) === null || _a === void 0 ? void 0 : _a.length) > 0;
4871
- let rowItm = dynMode ? (rowItem.edits[item._hash]) : rowItem;
4954
+ let rowItm = rowItem;
4872
4955
  rowItm._editing = false;
4873
4956
  let old = rowItm.old_value;
4874
4957
  let niu = dynMode ? item.properties[rowItem.PropertyName] : item[rowItem.PropertyName];
@@ -4879,22 +4962,27 @@ class EsTableComponent {
4879
4962
  this.onModelChange.emit([new EsTableModelChange(item, rowItem.ID, rowItem.PropertyName, old, niu)]);
4880
4963
  this.selectionStatus[item._ordinal][columnIndex].val_setter(niu);
4881
4964
  }
4882
- mousedown(event, rowItem, item) {
4883
- var _a, _b;
4965
+ mousedown(event, rowItem, _) {
4884
4966
  // Tasto diverso dal click sinistro -> ciao è stato bello e intenso
4885
4967
  if (event.buttons != 1 || !this.RangeSelection)
4886
4968
  return;
4887
4969
  // Sto lavorando su QUESTA es-table
4888
4970
  this.copyPasteDetector.ActiveEstReference = this;
4889
4971
  // Tutti i click su una cella già in edit non devono effettuare la selezione della riga
4890
- if ((((_a = this.DynamicRowColumnsDefinition) === null || _a === void 0 ? void 0 : _a.length) > 0 && rowItem.edits && ((_b = rowItem.edits[item._hash]) === null || _b === void 0 ? void 0 : _b._editing)) ||
4891
- rowItem._editing)
4972
+ if (rowItem._editing)
4892
4973
  return;
4893
- let id = event.currentTarget.id;
4894
4974
  this.mouseIsDown = true;
4895
- let coords = id.split('_');
4896
- this.firstCoordinates = { row: parseInt(coords[coords.length - 2]), column: parseInt(coords[coords.length - 1]) };
4897
- this.selection_H.singleCellSelection({ view: event.view, shiftKey: false }, this.firstCoordinates.row, this.firstCoordinates.column);
4975
+ let coords = event.currentTarget.id.split('_');
4976
+ let row = parseInt(coords[coords.length - 2]);
4977
+ let column = parseInt(coords[coords.length - 1]);
4978
+ this.firstCoordinates = { row, column };
4979
+ // Se ho già un range di selezione ignoro temporanemaente questa selezione in modo da capire bene cosa devo fare dopo (click sulla riga / altra selezione)
4980
+ // e gestire la grafica in maniera un po' più precisa
4981
+ if (!this.rangeSelected || (event.ctrlKey || !this.Selection))
4982
+ this.selection_H.singleCellSelection({ view: event.view, range: false }, row, column);
4983
+ else
4984
+ this.rangeStartWasIgnored = true;
4985
+ this.logger.log(`mouse down on ${row}:${column}`);
4898
4986
  }
4899
4987
  mouseenter(event) {
4900
4988
  if (!this.RangeSelection)
@@ -4904,14 +4992,34 @@ class EsTableComponent {
4904
4992
  if (this.mouseIsDown && this.firstCoordinates) {
4905
4993
  let id = event.currentTarget.id;
4906
4994
  let coords = id.split('_');
4907
- let newCoords = { row: parseInt(coords[coords.length - 2]), column: parseInt(coords[coords.length - 1]) };
4908
- this.selection_H.singleCellSelection({ view: event.view, shiftKey: true }, newCoords.row, newCoords.column, this.firstCoordinates);
4995
+ let row = parseInt(coords[coords.length - 2]);
4996
+ let column = parseInt(coords[coords.length - 1]);
4997
+ // Se ho ignorato l'inizio della selezione nel mousedown lo recupero qui
4998
+ if (this.rangeStartWasIgnored) {
4999
+ this.selection_H.singleCellSelection({ view: event.view, range: false }, this.firstCoordinates.row, this.firstCoordinates.column);
5000
+ this.rangeStartWasIgnored = false;
5001
+ }
5002
+ this.selection_H.singleCellSelection({ view: event.view, range: true }, row, column, this.firstCoordinates);
5003
+ this.logger.log(`mouse move over ${row}:${column}`);
5004
+ this.rangeSelected = true;
4909
5005
  }
4910
5006
  }
4911
5007
  mouseup(event) {
4912
5008
  if (!this.RangeSelection)
4913
5009
  return;
5010
+ let id = event.currentTarget.id;
5011
+ let coords = id.split('_');
5012
+ let row = parseInt(coords[coords.length - 2]);
5013
+ let column = parseInt(coords[coords.length - 1]);
5014
+ // Se il mouseup viene effettuato sulla stessa cella del primo mousedown e siamo in modalità di selezione deseleziono la cella perché è un semplice click
5015
+ if (this.mouseIsDown && this.firstCoordinates) {
5016
+ if (this.firstCoordinates.row == row && this.firstCoordinates.column == column && !event.ctrlKey && !this.rangeStartWasIgnored && this.Selection)
5017
+ this.selection_H.singleCellSelection({ view: event.view, range: false }, row, column);
5018
+ else if (event.ctrlKey || !this.Selection)
5019
+ this.rangeSelected = true;
5020
+ }
4914
5021
  this.mouseIsDown = false;
5022
+ this.logger.log(`mouse lifted up`);
4915
5023
  }
4916
5024
  getCellReference(object, column) {
4917
5025
  let fkThisShitImOut = this.utiExts.deepClone(object);
@@ -4931,8 +5039,8 @@ EsTableComponent.decorators = [
4931
5039
  viewProviders: [{ provide: LocalizationService, useClass: EsTableLoc }],
4932
5040
  changeDetection: ChangeDetectionStrategy.OnPush,
4933
5041
  encapsulation: ViewEncapsulation.None,
4934
- 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 class=\"clearfix\"></div>\r\n</div>\r\n\r\n<div *ngIf=\"View\" class=\"est-relative\" [style.height]=\"Height\" [style.background-color]=\"EmptySpaceBackgroundColor\">\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=\"est-top-pager\" *ngIf=\"PagingStyle == 'both' || PagingStyle == 'top'\">\r\n <ng-container *ngTemplateOutlet=\"pagingElement\"></ng-container>\r\n </div>\r\n\r\n <div class=\"est-top-allselect\" *ngIf=\"canSelectAll || (View?.selection || arraymodeSelection)?.all\">\r\n <span>{{ (selectedObjects == -1 ? ('All the' | localize : lc) : ((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)=\"selection_H.selectAllOrResetSelection()\">{{ (View?.selection || arraymodeSelection)?.all ? ('Reset Selection' | localize : lc) : ('Select Everything' | localize : lc)}}</span>\r\n </div>\r\n\r\n <div class=\"table-responsive datatable est-full-height {{ContainerClass}}\" [style.max-height.px]=\"MaxHeight\">\r\n <table class=\"{{ TableClass }} est-margin-bottom-10 est\" style=\"background-color: white;\" [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 && !SingleSelection) || PagingStyle != 'bottom'\">\r\n <th class=\"est-no-selection\" [attr.colspan]=\"Columns.Global\" [class.est-hidden-view]=\"!canSelectAll && !(View?.selection || arraymodeSelection)?.all && PagingStyle == 'bottom'\">\r\n <p class=\"est-hidden-view app-margin-bottom-0\">\u00A7</p>\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;\">\r\n <div class=\"est-pinned-border est-cell-group-padding\"></div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!cell.Pinned && cell.Content; Else: cell.Template\">\r\n {{cell.Content}}\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=\"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 </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=\"arrayMode || viewMode\">\r\n <!-- In una tabella base prendo semplicemente i th scritti dall'utente nell'HTML -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs || RowTHs.length == 0) && !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 || RowTHs.length == 0) && 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\" id=\"esth_{{rowHeader.PropertyName}}\" 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\" id=\"esth_{{rowHeader.PropertyName}}\" 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 && RowTHs.length > 0\">\r\n <th *ngIf=\"HasPinnedColumns\" class=\"est-pinned-header est-col-min\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border est-simple-border-bottom\">\r\n <th class=\"est-col-min est-no-border\" *ngIf=\"Selection\" [style.width.px]=\"20\">\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}}\" \r\n class=\"{{rowHeader.Class || ''}}\" \r\n [class.est-pinned-internal-header]=\"true\" \r\n [class.est-no-border]=\"true\" \r\n [class.est-nowrap]=\"!rowHeader.Wrap\" \r\n [Pinned]=\"true\" [Fixed]=\"rowHeader.Fixed\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onUnpinning)=\"columnMetadata_H.unpinColumn($event)\" (onOrderChange)=\"thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template; context: { $implicit: rowHeader.Multi ? rowHeader.MultiContent : null } \"></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\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && !rowHeader.Pinned\" es-th=\"{{rowHeader.ID}}\" class=\"{{rowHeader.Class || ''}}\" [class.est-ltab-border]=\"rowHeader.LeftBorder\" [class.est-rtab-border]=\"rowHeader.RightBorder\" [class.est-nowrap]=\"!rowHeader.Wrap\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template; context: { $implicit: rowHeader.Multi ? rowHeader.MultiContent : null }\"></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 <!--Per l'eliminazione mi serve un header aggiuntivo-->\r\n <th *ngIf=\"Removal\" [class.est-right-9]=\"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 <!-- 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)=\"columnMetadata_H.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)=\"export_H.tryExport('CSV')\">{{'Export View' | localize : lc}} (CSV)</a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && XLSXExport\" (click)=\"export_H.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 <tbody [hidden]=\"BodyHidden || FirstBind\" [class.est-no-selection]=\"RangeSelection\">\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 </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</div>\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 && PagerOptions.ShowButtons && (PagerOptions.PagerCount > 10 || PagerOptions.PagerCount == -1)\" class=\"pull-right btn-toolbar\">\r\n <ng-container *ngIf=\"PagerOptions.View?.pagingavailable || viewMode\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { Margin: true, 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: { Margin: true, 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\" *ngIf=\"PagerOptions.ShowCount || PagerOptions.ShowPagingOptions\">\r\n <div class=\"est-mt-min-5\" *ngIf=\"PagerOptions.ShowPaging\">\r\n <app-paging *ngIf=\"!PagerOptions.UsesView\" [CountLabel]=\"CountLabel\" [ShowPaging]=\"PagerOptions.ShowPagingOptions\" [ShowCount]=\"PagerOptions.ShowCount\" [PagerCount]=\"PagerOptions.PagerCount\" [WarnOnAll]=\"false\" [CurrentPageSize]=\"ArraymodeItemsPerPage\" (pagingSelected)=\"items_H.refreshPaging($event)\"></app-paging>\r\n <app-paging *ngIf=\"PagerOptions.UsesView\" [CountLabel]=\"CountLabel\" [ShowPaging]=\"PagerOptions.ShowPagingOptions\" [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>\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 <div class=\"est-flex\" [class.est-margin-left-50]=\"options.Margin\">\r\n <a class=\"btn\" class=\"est-page-prev app-pointer\" (click)=\"options.ATP(-1, options.separator)\"><span class=\"fa fa-chevron-left\"></span></a>\r\n <div *ngIf=\"options.Array\" class=\"est-inline\"><a *ngFor=\"let p of options.Array\" class=\"btn est-page-sel {{p.cssClass}}\" (click)=\"options.GTP(p.val, options.separator)\">{{p.val}}</a></div>\r\n <a class=\"btn\" class=\"est-page-next app-pointer\" (click)=\"options.ATP(1, options.separator)\"><span class=\"fa fa-chevron-right\"></span></a>\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; trackBy: bodyTrackBy\">\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)=\"!RangeSelection && handleRowClick($event, item, true)\"\r\n (contextmenu)=\"onRightClick();\">\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)=\"handleRowClick($event, item, false)\">\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 class=\"est-pinned-body \" *ngIf=\"HasPinnedColumns\"><div class=\"est-pinned-border est-cell-group-padding\"></div></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\" *ngIf=\"(item.searches == 'groups' ? item.view.groupcount : item.view.objectcount) > 10\"><app-paging [CountLabel]=\"CountLabel\" [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\" [CountLabel]=\"CountLabel\" [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\" *ngIf=\"(item.searches == 'groups' ? item.view.groupcount : item.view.objectcount) > 10\"><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 || EmptyRowTds) && !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 || EmptyRowTds) && 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\r\n <ng-container *ngFor=\"let rowItem of DynamicRowColumnsDefinition; let i = index\">\r\n\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]=\"dynamicMode_H.generateRouterLink(rowItem.RoutePath, rowItem.RouteParameterProperties, item)\" class=\"est-link\" [innerHTML]=\"item.properties[rowItem.PropertyName]\"></a>\r\n </td>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"!rowItem.RoutePath && rowItem.Visible\">\r\n <td es-td=\"{{rowItem.PropertyName}}\" \r\n [class.est-selected-cell]=\"selectionStatus[item._ordinal][i]?.selected\" \r\n [class.est-cell-lborder]=\"selectionStatus[item._ordinal][i]?.lborder\"\r\n [class.est-cell-tborder]=\"selectionStatus[item._ordinal][i]?.tborder\"\r\n [class.est-cell-rborder]=\"selectionStatus[item._ordinal][i]?.rborder\"\r\n [class.est-cell-bborder]=\"selectionStatus[item._ordinal][i]?.bborder\"\r\n [class.est-cell-lborder-tmp]=\"!selectionStatus[item._ordinal][i]?.lborder && !selectionStatus[item._ordinal][i]?.loverlaps\"\r\n [class.est-cell-rborder-tmp]=\"!selectionStatus[item._ordinal][i]?.rborder && !selectionStatus[item._ordinal][i]?.roverlaps\"\r\n (click)=\"dbClickEditOrSingleClickRowSelection($event, rowItem, item, i)\" \r\n class=\"{{UserDefinedDynamicCols ? rowItem.Clss : 'est-nowrap'}} est-default-row-height\" \r\n [Internal]=\"false\" [class.est-no-selection]=\"!!Editable\" [Context]=\"item._hash\"\r\n id=\"estd_{{rowItem.PropertyName}}_{{item._ordinal}}_{{i}}\" (mousedown)=\"mousedown($event, rowItem, item)\" (mouseenter)=\"mouseenter($event)\" (mouseup)=\"mouseup($event)\">\r\n\r\n <div [class.est-edit-hidden]=\"rowItem.edits[item._hash]?._editing\" >\r\n <ng-container *ngTemplateOutlet=\"findEsTd(rowItem.PropertyName, rowItem.RendererName) || defaultEsTd; context: { $implicit: { definition: rowItem, value: item.properties[rowItem.PropertyName], type: rowItem.PropertyType} }\"></ng-container>\r\n </div>\r\n <div *ngIf=\"rowItem.edits[item._hash]?._editing\" class=\"est-mt-min-5\">\r\n <ng-container *ngTemplateOutlet=\"findEditor(rowItem.PropertyName, rowItem.EditorName) || defaultEditor; context: { $implicit: { definition: rowItem, columnIndex: i, item: item, finalizer: finalizeUserEdit.bind(this, rowItem, item, i) } }\"></ng-container>\r\n </div>\r\n </td>\r\n </ng-container>\r\n </ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEditor let-ctx>\r\n <ng-container *ngIf=\"ctx.item.properties\">\r\n <form-adaptive [FormLayout]=\"false\" [Validation]=\"false\" [Options]=\"ctx.definition.EditorOptions\" [FocusSubject]=\"FocusSubject\" [(ngModel)]=\"ctx.item.properties[ctx.definition.PropertyName]\" name=\"{{ ctx.definition.PropertyName + '_' + ctx.item._hash }}\" [Type]=\"ctx.definition.PropertyType\" [Source]=\"ctx.definition.PropertySource\" (inputFinalized)=\"ctx.finalizer()\"></form-adaptive>\r\n </ng-container>\r\n <ng-container *ngIf=\"!ctx.item.properties\">\r\n <form-adaptive [FormLayout]=\"false\" [Validation]=\"false\" [Options]=\"ctx.definition.EditorOptions\" [FocusSubject]=\"FocusSubject\" [(ngModel)]=\"ctx.item[ctx.definition.PropertyName]\" name=\"{{ ctx.definition.PropertyName + '_' + ctx.item._hash }}\" [Type]=\"ctx.definition.PropertyType\" [Source]=\"ctx.definition.PropertySource\" (inputFinalized)=\"ctx.finalizer()\"></form-adaptive>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEsTd let-ctx>\r\n <!-- Formattare il valore in base a valType.type -->\r\n <ng-container *ngIf=\"ctx.type == 'enum'\">\r\n {{ (ctx.value | est_lookup : ctx.definition.PropertySource).description }}\r\n </ng-container>\r\n <ng-container *ngIf=\"ctx.type != 'enum'\">\r\n {{ctx.value}}\r\n </ng-container>\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 && !EmptyRowTds\">\r\n <td *ngIf=\"HasPinnedColumns\" \r\n 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\" [style.width.px]=\"20\">\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\" [style.width.px]=\"20\"></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-selection]=\"Editable &&!!rowItem.PropertyName\" [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\" (click)=\"dbClickEditOrSingleClickRowSelection($event, rowItem, item, i)\">\r\n\r\n <div [class.est-edit-hidden]=\"rowItem._editing\" [class.est-pre]=\"!(Hierarchy && i == 0)\"\r\n [style.text-align]=\"rowItem.Alignment == 'Center' ? 'center' : rowItem.Alignment == 'Left' ? 'left' : rowItem.Alignment == 'Right' ? 'right' : null\"\r\n [style.color]=\"item.forecolors && rowItem.PropAccessor ? item.forecolors[rowItem.PropAccessor] : null\"\r\n [style.background-color]=\"item.backcolors && rowItem.PropAccessor ? item.backcolors[rowItem.PropAccessor] : null\">\r\n <ng-container *ngIf=\"Hierarchy && i == 0\"><ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: rowItem.Multi ? (item[rowItem.MultiProp] ? item[rowItem.MultiProp][rowItem.MultiIndex] : {}) : item }\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"!rowItem.Multi && rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: rowItem.Multi ? (item[rowItem.MultiProp] ? item[rowItem.MultiProp][rowItem.MultiIndex] : {}) : item }\"></ng-container></ng-container>\r\n <span *ngIf=\"rowItem.Multi && rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: (item[rowItem.MultiProp] ? item[rowItem.MultiProp][rowItem.MultiIndex] : {}) }\"></ng-container></span>\r\n <ng-container *ngIf=\"!rowItem.Template && !rowItem.Multi\">\r\n <span *ngIf=\"rowItem.Content && !rowItem.PropAccessor\">{{rowItem.Content}}</span>\r\n <span *ngIf=\"!rowItem.Content && rowItem.PropAccessor\">{{(item.values? item.values[rowItem.PropAccessor] : item[rowItem.PropAccessor]) | est_format: rowItem.Format }}</span>\r\n </ng-container>\r\n </div>\r\n <div *ngIf=\"rowItem._editing\" class=\"est-mt-min-5\">\r\n <ng-container *ngTemplateOutlet=\"findEditor(rowItem.PropertyName) || defaultEditor; context: { $implicit: { definition: rowItem, columnIndex: i, item: item, finalizer: finalizeUserEdit.bind(this, rowItem, item, i) } }\"></ng-container>\r\n </div>\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}}\" \r\n [class.est-selected-cell]=\"selectionStatus[item._ordinal][i]?.selected\" \r\n [class.est-cell-lborder]=\"selectionStatus[item._ordinal][i]?.lborder\"\r\n [class.est-cell-tborder]=\"selectionStatus[item._ordinal][i]?.tborder\"\r\n [class.est-cell-rborder]=\"selectionStatus[item._ordinal][i]?.rborder\"\r\n [class.est-cell-bborder]=\"selectionStatus[item._ordinal][i]?.bborder\"\r\n [class.est-ltab-border]=\"rowItem.LeftBorder && !selectionStatus[item._ordinal][i]?.lborder\" \r\n [class.est-rtab-border]=\"rowItem.RightBorder && !selectionStatus[item._ordinal][i]?.rborder\" \r\n [class.est-cell-lborder-tmp]=\"!selectionStatus[item._ordinal][i]?.lborder && !selectionStatus[item._ordinal][i]?.loverlaps && !rowItem.LeftBorder\"\r\n [class.est-cell-rborder-tmp]=\"!selectionStatus[item._ordinal][i]?.rborder && !selectionStatus[item._ordinal][i]?.roverlaps && !rowItem.RightBorder\"\r\n [class.est-no-selection]=\"Editable && !!rowItem.PropertyName\" [class.est-rg-hdr]=\"rowItem.GroupHeader\" [class.est-rg-agg]=\"rowItem.GroupAggregation\" \r\n [class.est-nowrap]=\"Hierarchy || !rowItem.Wraps\" [Internal]=\"true\" (click)=\"dbClickEditOrSingleClickRowSelection($event, rowItem, item, i)\"\r\n (onCellGeneration)=\"registerCell($event)\" [Context]=\"item._hash\"\r\n id=\"{{item._ordinal}}_{{i}}\" (mousedown)=\"mousedown($event, rowItem, item)\" (mouseenter)=\"mouseenter($event)\" (mouseup)=\"mouseup($event)\"\r\n [style.text-align]=\"rowItem.Alignment == 'Center' ? 'center' : rowItem.Alignment == 'Left' ? 'left' : rowItem.Alignment == 'Right' ? 'right' : null\"\r\n [style.color]=\"item.forecolors && rowItem.PropAccessor ? item.forecolors[rowItem.PropAccessor] : null\"\r\n [style.background-color]=\"item.backcolors && rowItem.PropAccessor ? item.backcolors[rowItem.PropAccessor] : null\">\r\n \r\n <div [class.est-edit-hidden]=\"rowItem._editing\" [class.est-pre]=\"!(Hierarchy && i == 0)\" >\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.Multi && rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: item }\"></ng-container></ng-container>\r\n <span *ngIf=\"rowItem.Multi && rowItem.Template\"><ng-container *ngTemplateOutlet=\"rowItem.Template; context: { $implicit: (item[rowItem.MultiProp] ? item[rowItem.MultiProp][rowItem.MultiIndex] : {}) }\"></ng-container></span>\r\n <ng-container *ngIf=\"!rowItem.Template && !rowItem.Multi\">\r\n <span *ngIf=\"rowItem.Content && !rowItem.PropAccessor\">{{rowItem.Content}}</span>\r\n <span *ngIf=\"!rowItem.Content && rowItem.PropAccessor\">{{(item.values? item.values[rowItem.PropAccessor] : item[rowItem.PropAccessor]) | est_format: rowItem.Format }}</span>\r\n </ng-container>\r\n </div>\r\n <div *ngIf=\"rowItem._editing\" class=\"est-mt-min-5\">\r\n <ng-container *ngTemplateOutlet=\"findEditor(rowItem.PropertyName) || defaultEditor; context: { $implicit: { definition: rowItem, columnIndex: i, item: item, finalizer: finalizeUserEdit.bind(this, rowItem, item, i) } }\"></ng-container>\r\n </div>\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 est-no-selection\" (click)=\"hierarchyMode_H.collapseParent(item[this.OwnKey])\"></span>\r\n <span *ngIf=\"item.parent && !item._expanded\" class=\"fa fa-chevron-up est-pointer est-no-selection\" (click)=\"hierarchyMode_H.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-9' : ''}}\" *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-9' : ''}}\" *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-9' : ''}}\" *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-9' : ''}}\" *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-9' : ''}}\" *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\" cdkDrag>\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header est-pointer\" cdkDragHandle>\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)=\"columnMetadata_H.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 *ngIf=\"DirectivesBased\" class=\"est-col-min\"></th>\r\n </tr>\r\n </thead>\r\n <tbody \r\n cdkDropList \r\n [cdkDropListData]=\"TMPColumnsList\" \r\n (cdkDropListDropped)=\"columnMetadata_H.columnReordered($event)\" \r\n [cdkDropListSortPredicate]=\"columnMetadata_H.sortPredicate.bind(this.columnMetadata_H)\"\r\n class=\"est-dropbox\">\r\n\r\n <tr *ngFor=\"let item of TMPColumnsList; let i = index; let last = last\" \r\n class=\"est-pointer est-droplist\" \r\n [class.est-white-selected]=\"lastSelectedItemID == item.id\" \r\n [class.est-no-selection]=\"!item.visible\"\r\n cdkDrag\r\n [cdkDragData]=\"item\"\r\n [cdkDragDisabled]=\"!ColumnsOrdering || item.fixed || item.pinned\">\r\n\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)=\"columnMetadata_H.updateGlobalColVisCheck();\" />\r\n </td>\r\n <td class=\"est-nowrap drag-visible\" (click)=\"columnMetadata_H.columnClicked(item);\">\r\n <ng-container *ngIf=\"item.template\">\r\n <!-- Padri -->\r\n <span *ngIf=\"item.parentTemplates && item.parentTemplates.length > 0\" class=\"est-fw-bold est-fs-13\">\r\n (&nbsp;\r\n <ng-container *ngFor=\"let parent of item.parentTemplates; let last=last\">\r\n <ng-container *ngIf=\"parent.tmpl\"><ng-container *ngTemplateOutlet=\"parent.tmpl\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"parent.content\">{{parent.content}}</ng-container>\r\n <span *ngIf=\"!last\">&nbsp;-&nbsp;</span>\r\n </ng-container>\r\n &nbsp;)\r\n </span>\r\n <!-- Template header originale -->\r\n <ng-container *ngTemplateOutlet=\"item.template; context: { $implicit: item.multi ? item.multiContent : null }\"></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)=\"columnMetadata_H.columnClicked(item);\"></td>\r\n <!-- Pinner -->\r\n <td *ngIf=\"DirectivesBased && ColumnsPinnable\"><span *ngIf=\"!item.fixed && item.pinnable\" class=\"fa fa-thumb-tack\" [class.text-success]=\"item.pinned\" (click)=\"columnMetadata_H.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)=\"columnMetadata_H.confirmColumnVisibilitySelection() && changeColumnVisibilityModal.hide()\">{{'Confirm' | localize : lc}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>",
4935
- 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-head-resizer{top:0;right:0;bottom:0;width:7px;position:absolute;cursor:col-resize}.est-head-resizer-internal{top:0;right:0;left:6px;bottom:0;width:1px;position:absolute;background-color:#ccc;height:100%}.est-pointer{cursor:pointer}.est-high-density td,.est-high-density th{padding:0 .2rem}.est-default-row-height{height:31px}.est-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.est-edit-hidden{height:1px!important}.est-edit-hidden,.est-hidden-view{visibility:hidden}.est-no-border{border:none!important}.est-nowrap{white-space:nowrap}.est-mt-min-5{margin-top:-5px}.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-9{right:9px!important}.est-table-dotted-menu{padding:0 0 2px!important;color:#999}.est-fs-18{font-size:18px}.est-fs-13,.est-fs-14{font-size:14px}.est-fw-bold{font-weight:700}.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-relative{position:relative}.est-top-pager{position:absolute;right:0;top:5px}.est-top-allselect{position:absolute;left:0;top:5px;font-weight:700}.est-padding-10{padding:10px!important}.est-margin-right-50{margin-right:50px}.est-margin-left-50{margin-left:50px}.est-quick-unpin{color:#000;margin-left:8px;font-size:14px;transform:rotate(45deg)}.est-full-height{height:100%}.est-page-sel{color:#000;margin-left:3px;margin-right:3px;padding:0 5px;font-size:inherit;border:none;border-radius:15px}.est-page-next,.est-page-prev{color:#000;font-size:inherit;padding:2px 0 0}.est-pinned-header{background-color:#fff;left:0;top:0;position:-webkit-sticky;position:sticky;z-index:1;border-bottom:1px solid #dee2e6!important;padding:0!important}.est-simple-border-bottom{border-bottom:1px solid #dee2e6}.est-pinned-internal-header{border-top:0;border-bottom:0 solid #dee2e6}.est-pinned-border{border-right:2px solid #dee2e6!important}.est-cell-padding{padding:.3rem}.est-pinned-body{background-color:#fff;left:0;position:-webkit-sticky;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:-webkit-sticky;position:sticky;z-index:0;background-color:#fff}.est-sticky-last-column-alt{right:-1px;position:-webkit-sticky;position:sticky;z-index:0;background-color:#f2f2f2}.est-ltab-border{border-left:1px solid #bbb!important}.est-rtab-border{border-right:1px solid #bbb!important}.est-cell-group-padding{padding:calc(.3rem + 1px);position:absolute;top:0;left:0;height:100%;width:100%}.est-selected-cell{background-color:rgba(33,150,243,.2)}.est-cell-lborder{border-left:1.02px solid #2196f3!important}.est-cell-lborder-tmp{border-left:1.02px solid transparent!important}.est-cell-tborder{border-top:1.02px solid #2196f3!important}.est-cell-rborder{border-right:1.02px solid #2196f3!important}.est-cell-rborder-tmp{border-right:1.02px solid transparent!important}.est-cell-bborder{border-bottom:1.02px solid #2196f3!important}.est-margin-bottom-10{margin-bottom:10px}.est-text-center{text-align:center}.est-flex{display:flex}.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}.est-droplist.cdk-drag-placeholder{opacity:0}.est-droplist.cdk-drag-preview{z-index:999999999!important;opacity:1;box-sizing:border-box;border-radius:4px;background-color:#fff;box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.est-droplist.cdk-drag-preview td:not(.drag-visible){visibility:hidden}.est-droplist.cdk-drag-preview td.drag-visible{padding-top:3px}.est-droplist.cdk-drag-animating,.est-droplist.cdk-drop-list-dragging .est-dropbox:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.est-pre{white-space:pre}.est val-datetime .mat-form-field-appearance-outline .mat-form-field-infix input{margin-bottom:3px!important;min-width:130px!important}.est .mat-form-field-flex{height:29px!important;padding:0!important}.est .mat-form-field-flex .mat-form-field-outline{color:#00f}.est .mat-form-field-flex .mat-form-field-outline .mat-form-field-outline-start{border-left:none;border-top:none;border-radius:0}.est .mat-form-field-flex .mat-form-field-outline .mat-form-field-outline-end{border-top:none;border-radius:0;border-right:none}.est .mat-form-field-wrapper{height:20px;min-height:20px!important;margin-top:0!important}.est .mat-form-field-infix{width:100%!important;min-width:50px!important}.est .mat-form-field-infix select.mat-input-element{margin-top:-5px!important}.est .mat-datepicker-input{margin-bottom:3px!important}.est input{height:20px;padding-top:0!important}"]
5042
+ 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 class=\"clearfix\"></div>\r\n</div>\r\n\r\n<div *ngIf=\"View\" class=\"est-relative\" [style.height]=\"Height\" [style.background-color]=\"EmptySpaceBackgroundColor\">\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=\"est-top-pager\" *ngIf=\"PagingStyle == 'both' || PagingStyle == 'top'\">\r\n <ng-container *ngTemplateOutlet=\"pagingElement\"></ng-container>\r\n </div>\r\n\r\n <div class=\"est-top-allselect\" *ngIf=\"canSelectAll || (View?.selection || arraymodeSelection)?.all\">\r\n <span>{{ (selectedObjects == -1 ? ('All the' | localize : lc) : ((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)=\"selection_H.selectAllOrResetSelection()\">{{ (View?.selection || arraymodeSelection)?.all ? ('Reset Selection' | localize : lc) : ('Select Everything' | localize : lc)}}</span>\r\n </div>\r\n\r\n <div class=\"table-responsive datatable est-full-height {{ContainerClass}}\" [style.max-height.px]=\"MaxHeight\">\r\n <table class=\"{{ TableClass }} est-margin-bottom-10 est\" style=\"background-color: white;\" [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 && !SingleSelection) || PagingStyle != 'bottom'\">\r\n <th class=\"est-no-selection\" [attr.colspan]=\"Columns.Global\" [class.est-hidden-view]=\"!canSelectAll && !(View?.selection || arraymodeSelection)?.all && PagingStyle == 'bottom'\">\r\n <p class=\"est-hidden-view app-margin-bottom-0\">\u00A7</p>\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; trackBy: IDTrackBy\">\r\n <th *ngFor=\"let cell of level; trackBy: IDTrackBy\" [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;\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border est-cell-group-padding\"></div>\r\n </ng-container>\r\n <ng-container *ngIf=\"!cell.Pinned && cell.Content; Else: cell.Template\">\r\n {{cell.Content}}\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=\"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 </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=\"arrayMode || viewMode\">\r\n <!-- In una tabella base prendo semplicemente i th scritti dall'utente nell'HTML -->\r\n <ng-container *ngIf=\"(!UseCustomCells || !RowTHs || RowTHs.length == 0) && !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 || RowTHs.length == 0) && DynamicRowColumnsDefinition\">\r\n <th *ngFor=\"let operation of DynamicOperations; trackBy: idTrackBy\" class=\"est-col-min est-no-side-padding\"></th>\r\n \r\n <ng-container *ngFor=\"let rowHeader of DynamicRowColumnsDefinition; trackBy: PropertyNameTrackBy\">\r\n <ng-container *ngIf=\"rowHeader.Visible\">\r\n <th *ngIf=\"OrderByColumn\" id=\"esth_{{rowHeader.PropertyName}}\" 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\" id=\"esth_{{rowHeader.PropertyName}}\" 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?.length > 0\">\r\n <th *ngIf=\"HasPinnedColumns\" class=\"est-pinned-header est-col-min\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border est-simple-border-bottom\">\r\n <th class=\"est-col-min est-no-border\" *ngIf=\"Selection\" [style.width.px]=\"20\">\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; trackBy: IDTrackBy\">\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && rowHeader.Pinned\" [style.width.px]=\"rowHeader.PinnedWidth\" es-th=\"{{rowHeader.ID}}\" \r\n class=\"{{rowHeader.Class || ''}}\" \r\n [class.est-pinned-internal-header]=\"true\" \r\n [class.est-no-border]=\"true\" \r\n [class.est-nowrap]=\"!rowHeader.Wrap\" \r\n [Pinned]=\"true\" [Fixed]=\"rowHeader.Fixed\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onUnpinning)=\"columnMetadata_H.unpinColumn($event)\" (onOrderChange)=\"thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template; context: { $implicit: rowHeader.Multi ? rowHeader.MultiContent : null } \"></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; trackBy: IDTrackBy\">\r\n\r\n <th *ngIf=\"rowHeader && rowHeader.Visible && !rowHeader.Pinned\" es-th=\"{{rowHeader.ID}}\" class=\"{{rowHeader.Class || ''}}\" [class.est-ltab-border]=\"rowHeader.LeftBorder\" [class.est-rtab-border]=\"rowHeader.RightBorder\" [class.est-nowrap]=\"!rowHeader.Wrap\" [Order]=\"rowHeader.Order\" [Resizable]=\"ColumnsResizable\" [Orderable]=\"rowHeader.Orderable\" [OrderBy]=\"OrderByColumn\" [SearchInProgress]=\"!!researchInProgress\" (onOrderChange)=\"thOrderChanged(rowHeader.ID, $event)\">\r\n <ng-container *ngIf=\"rowHeader.Template\"><ng-container *ngTemplateOutlet=\"rowHeader.Template; context: { $implicit: rowHeader.Multi ? rowHeader.MultiContent : null }\"></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 <!--Per l'eliminazione mi serve un header aggiuntivo-->\r\n <th *ngIf=\"Removal\" [class.est-right-9]=\"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 <!-- 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)=\"columnMetadata_H.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)=\"export_H.tryExport('CSV')\">{{'Export View' | localize : lc}} (CSV)</a>\r\n <a class=\"dropdown-item\" *ngIf=\"Export && XLSXExport\" (click)=\"export_H.tryExport('XLSX')\">{{'Export View' | localize : lc}} (XLSX)</a>\r\n <a class=\"dropdown-item\" *ngFor=\"let option of CornerMenuOptions; trackBy: idTrackBy\" (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 <tbody [hidden]=\"BodyHidden || FirstBind\" [class.est-no-selection]=\"RangeSelection\">\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 </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</div>\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 && PagerOptions.ShowButtons && (PagerOptions.PagerCount > 10 || PagerOptions.PagerCount == -1)\" class=\"pull-right btn-toolbar\">\r\n <ng-container *ngIf=\"PagerOptions.View?.pagingavailable || viewMode\">\r\n <ng-container *ngTemplateOutlet=\"pagingButtons; context: { $implicit: { Margin: true, 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: { Margin: true, 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\" *ngIf=\"PagerOptions.ShowCount || PagerOptions.ShowPagingOptions\">\r\n <div class=\"est-mt-min-5\" *ngIf=\"PagerOptions.ShowPaging\">\r\n <app-paging *ngIf=\"!PagerOptions.UsesView\" [CountLabel]=\"CountLabel\" [ShowPaging]=\"PagerOptions.ShowPagingOptions\" [ShowCount]=\"PagerOptions.ShowCount\" [PagerCount]=\"PagerOptions.PagerCount\" [WarnOnAll]=\"false\" [CurrentPageSize]=\"ArraymodeItemsPerPage\" (pagingSelected)=\"items_H.refreshPaging($event)\"></app-paging>\r\n <app-paging *ngIf=\"PagerOptions.UsesView\" [CountLabel]=\"CountLabel\" [ShowPaging]=\"PagerOptions.ShowPagingOptions\" [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>\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 <div class=\"est-flex\" [class.est-margin-left-50]=\"options.Margin\">\r\n <a class=\"btn\" class=\"est-page-prev app-pointer\" (click)=\"options.ATP(-1, options.separator)\"><span class=\"fa fa-chevron-left\"></span></a>\r\n <div *ngIf=\"options.Array\" class=\"est-inline\"><a *ngFor=\"let p of options.Array; trackBy: valTrackBy\" class=\"btn est-page-sel {{p.cssClass}}\" (click)=\"options.GTP(p.val, options.separator)\">{{p.val}}</a></div>\r\n <a class=\"btn\" class=\"est-page-next app-pointer\" (click)=\"options.ATP(1, options.separator)\"><span class=\"fa fa-chevron-right\"></span></a>\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; trackBy: bodyTrackBy\">\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)=\"!RangeSelection && handleRowClick($event, item, true)\"\r\n (contextmenu)=\"onRightClick();\">\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=\"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; trackBy: bodyTrackBy\">\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)=\"handleRowClick($event, item, false)\">\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=\"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 class=\"est-pinned-body \" *ngIf=\"HasPinnedColumns\">\r\n <div [style.width.px]=\"PinnedContainerWidth\" class=\"est-pinned-border est-cell-group-padding\"></div>\r\n </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\" *ngIf=\"(item.searches == 'groups' ? item.view.groupcount : item.view.objectcount) > 10\"><app-paging [CountLabel]=\"CountLabel\" [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\" [CountLabel]=\"CountLabel\" [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\" *ngIf=\"(item.searches == 'groups' ? item.view.groupcount : item.view.objectcount) > 10\"><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 || EmptyRowTds) && !DynamicRowColumnsDefinition\">\r\n <ng-container *ngTemplateOutlet=\"bodyRef; context : {$implicit: item}\"></ng-container>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEditor let-ctx>\r\n <!-- Un po' triste ma questo \u00E8 il metodo pi\u00F9 semplice per gestire il cambio di modello -->\r\n <ng-container *ngIf=\"ctx.item.properties\">\r\n <form-adaptive [FormLayout]=\"false\" [Validation]=\"false\" [Options]=\"ctx.definition.EditorOptions\" [FocusSubject]=\"FocusSubject\" [(ngModel)]=\"ctx.item.properties[ctx.definition.PropertyName]\" name=\"{{ ctx.definition.PropertyName + '_' + ctx.item._hash }}\" [Type]=\"ctx.definition.PropertyType\" [Source]=\"ctx.definition.PropertySource\" (inputFinalized)=\"ctx.finalizer()\"></form-adaptive>\r\n </ng-container>\r\n <ng-container *ngIf=\"!ctx.item.properties\">\r\n <form-adaptive [FormLayout]=\"false\" [Validation]=\"false\" [Options]=\"ctx.definition.EditorOptions\" [FocusSubject]=\"FocusSubject\" [(ngModel)]=\"ctx.item[ctx.definition.PropertyName]\" name=\"{{ ctx.definition.PropertyName + '_' + ctx.item._hash }}\" [Type]=\"ctx.definition.PropertyType\" [Source]=\"ctx.definition.PropertySource\" (inputFinalized)=\"ctx.finalizer()\"></form-adaptive>\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #defaultEsTd let-ctx>\r\n <!-- TODO: Formattare il valore in base a valType.type -->\r\n <ng-container *ngIf=\"ctx.type == 'enum'\">\r\n {{ (ctx.value | est_lookup : ctx.definition.PropertySource).description }}\r\n </ng-container>\r\n <ng-container *ngIf=\"ctx.type != 'enum'\">\r\n {{ctx.value}}\r\n </ng-container>\r\n</ng-template>\r\n\r\n<ng-template #customCells let-item let-opt=\"templateOptions\">\r\n <ng-container *ngIf=\"UseCustomCells && !EmptyRowTds\">\r\n <!-- Cella che aggrega tutte le colonne che devono essere pinnate -->\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\" [style.width.px]=\"20\">\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\" [style.width.px]=\"20\"></td>\r\n\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item._hash]; let i = index; trackBy: IDTrackBy\">\r\n <ng-container *ngIf=\"rowItem.Pinned\">\r\n <ng-container *ngTemplateOutlet=\"customTd; context: { $implicit: { item: item, rowItem : rowItem, i:i, Pinned: true } };\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n </div>\r\n </td>\r\n\r\n <!-- Eventuali operazioni custom nelle prime righe... hanno senso solo in modalit\u00E0 dinamica ma non si sa mai -->\r\n <ng-container *ngTemplateOutlet=\"customOperations; context: {$implicit: item };\"></ng-container>\r\n\r\n <!-- Body effettivo della riga -->\r\n <ng-container *ngFor=\"let rowItem of RowTDs[item._hash]; let i = index; trackBy: IDTrackBy\">\r\n <ng-container *ngIf=\"!rowItem.Pinned\">\r\n <ng-container *ngTemplateOutlet=\"customTd; context: {$implicit: {item: item, rowItem : rowItem, i:i, Pinned: false} };\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n </ng-container>\r\n</ng-template>\r\n\r\n<!-- Blocco di operazioni custom da far apparire all'inizio della tabella -->\r\n<ng-template #customOperations let-item>\r\n <ng-container *ngFor=\"let operation of DynamicOperations; let first = first; let last = last; trackBy: idTrackBy\">\r\n <ng-container *ngIf=\"!operation.conditionField || ((item.properties ? item.properties[operation.conditionField] : item[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 ? item.properties[operation.conditionField] : item[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-template>\r\n\r\n<!-- Cella customizzata, elemento grafico base per la tabella -->\r\n<ng-template #customTd let-ctx>\r\n <!-----------------------------------------------------------------------------------------------------------------------\r\n - ATTENZIONE: Gli spazi fra le propriet\u00E0 di questo mega td sono significativi e dividono la dichiarazione in sezioni: -\r\n - . Generiche -\r\n - . Gestione allineamento e colori per la modalit\u00E0 report -\r\n - . Gestioni grafiche particolari per il Pinned -\r\n - . Gestione della selezione a singola cella in assenza di pinned -\r\n - . Gestione click classico -\r\n ------------------------------------------------------------------------------------------------------------------------->\r\n\r\n <!-- class=\"{{ UserDefinedDynamicCols ? ctx.rowItem.Class : 'est-nowrap'}} est-default-row-height\" -->\r\n\r\n <td *ngIf=\"ctx.rowItem?.Visible\" \r\n es-td=\"{{ctx.rowItem.Property || ctx.rowItem.ID}}\"\r\n id=\"estd_{{ctx.rowItem.Property || ctx.rowItem.ID}}_{{ctx.item._ordinal}}_{{ctx.i}}\" \r\n class=\"{{ ctx.rowItem.Class }} est-default-row-height\" \r\n [Context]=\"ctx.item._hash\" \r\n [class.est-no-selection]=\"Editable && ctx.rowItem.PropertyName\" \r\n [class.est-rg-hdr]=\"ctx.rowItem.GroupHeader\" \r\n [class.est-rg-agg]=\"ctx.rowItem.GroupAggregation\"\r\n [class.est-nowrap]=\"Hierarchy || !ctx.rowItem.Wraps\"\r\n \r\n [style.text-align]=\" (!ctx.Pinned && ctx.rowItem.Alignment) ? ctx.rowItem.Alignment : null\"\r\n [style.color]=\"(!ctx.Pinned && ctx.item.forecolors && ctx.rowItem.PropAccessor) ? ctx.item.forecolors[ctx.rowItem.PropAccessor] : null\"\r\n [style.background-color]=\"(!ctx.Pinned && ctx.item.backcolors && ctx.rowItem.PropAccessor) ? ctx.item.backcolors[ctx.rowItem.PropAccessor] : null\"\r\n\r\n [style.width.px]=\"ctx.Pinned ? ctx.rowItem.PinnedWidth : null\"\r\n [class.est-no-border]=\"ctx.Pinned\"\r\n\r\n [class.est-ltab-border]=\"ctx.rowItem.LeftBorder && !selectionStatus[ctx.item._ordinal][ctx.i]?.lborder\" \r\n [class.est-rtab-border]=\"ctx.rowItem.RightBorder && !selectionStatus[ctx.item._ordinal][ctx.i]?.rborder\" \r\n\r\n [class.est-selected-cell]=\"selectionStatus[ctx.item._ordinal][ctx.i]?.selected\"\r\n [class.est-cell-lborder]=\"selectionStatus[ctx.item._ordinal][ctx.i]?.lborder\"\r\n [class.est-cell-rborder]=\"selectionStatus[ctx.item._ordinal][ctx.i]?.rborder\"\r\n [class.est-cell-tborder]=\"selectionStatus[ctx.item._ordinal][ctx.i]?.tborder\"\r\n [class.est-cell-bborder]=\"selectionStatus[ctx.item._ordinal][ctx.i]?.bborder\"\r\n\r\n [class.est-cell-lborder-tmp]=\"!ctx.rowItem.LeftBorder && !selectionStatus[ctx.item._ordinal][ctx.i]?.lborder && !selectionStatus[ctx.item._ordinal][ctx.i]?.loverlaps\"\r\n [class.est-cell-rborder-tmp]=\"!ctx.rowItem.RightBorder && !selectionStatus[ctx.item._ordinal][ctx.i]?.rborder && !selectionStatus[ctx.item._ordinal][ctx.i]?.roverlaps\"\r\n [class.est-cell-tborder-tmp]=\"!selectionStatus[ctx.item._ordinal][ctx.i]?.tborder && !selectionStatus[ctx.item._ordinal][ctx.i]?.toverlaps\"\r\n [class.est-cell-bborder-tmp]=\"!selectionStatus[ctx.item._ordinal][ctx.i]?.bborder && !selectionStatus[ctx.item._ordinal][ctx.i]?.boverlaps\"\r\n\r\n (mousedown)=\"mousedown($event, ctx.rowItem, ctx.item)\" \r\n (mouseenter)=\"mouseenter($event)\" \r\n (mouseup)=\"mouseup($event)\"\r\n (onCellGeneration)=\"registerCell($event)\"\r\n \r\n (click)=\"dbClickEditOrSingleClickRowSelection($event, ctx.rowItem, ctx.item)\">\r\n\r\n <div [class.est-edit-hidden]=\"ctx.rowItem._editing\" [class.est-pre]=\"!(Hierarchy && ctx.i == 0)\">\r\n\r\n <ng-container #DEBUG>\r\n <!-- Debug box in caso la roba che viene scritta nelle celle non torni. Scirvere qui i propri binding per controllare cose -->\r\n </ng-container>\r\n\r\n <!-- 90% Template disponibile, quindi derivante da *td, controllo giusto che non sia un field particolare multi -->\r\n <ng-container *ngIf=\"ctx.rowItem.Template\">\r\n <ng-container *ngIf=\"!ctx.rowItem.Multi\"><ng-container *ngTemplateOutlet=\"ctx.rowItem.Template; context: { $implicit: ctx.item }\"></ng-container></ng-container>\r\n <span *ngIf=\"ctx.rowItem.Multi\"><ng-container *ngTemplateOutlet=\"ctx.rowItem.Template; context: { $implicit: (ctx.item[ctx.rowItem.MultiProp] ? ctx.item[ctx.rowItem.MultiProp][ctx.rowItem.MultiIndex] : {}) }\"></ng-container></span>\r\n </ng-container>\r\n \r\n <!-- 8%\r\n Template non disponibile, pu\u00F2 venire da \r\n RoutePath in caso sia un link di una tabella dinamica\r\n PropAccessor in caso di ReportRow (quindi oggetti con \"values\" dentro), \r\n o Renderer se modalit\u00E0 dinamica/standard (in qual caso il renderer \u00E8 il default)\r\n -->\r\n <ng-container *ngIf=\"!ctx.rowItem.Template && !ctx.rowItem.Multi && !ctx.rowItem.Content\">\r\n <a *ngIf=\"ctx.rowItem.RoutePath\" [routerLink]=\"ctx.item | est_routerlink : ctx.rowItem.RoutePath : ctx.rowItem.RouteParameterProperties\" class=\"est-link\" [innerHTML]=\"ctx.item.properties ? ctx.item.properties[ctx.rowItem.PropertyName] : ctx.item[ctx.rowItem.PropertyName]\"></a>\r\n \r\n <span *ngIf=\"ctx.rowItem.PropAccessor\">\r\n {{(ctx.item.values? ctx.item.values[ctx.rowItem.PropAccessor] : ctx.item[ctx.rowItem.PropAccessor]) | est_format: ctx.rowItem.Format }}\r\n </span>\r\n\r\n <ng-container *ngIf=\"!ctx.rowItem.PropAccessor && !ctx.rowItem.RoutePath\">\r\n <ng-container *ngTemplateOutlet=\"ctx.rowItem.PropertyName | est_renderer: { name: ctx.rowItem.RendererName, src: EsTdsDirective, fallback: defaultEsTd }; context: { $implicit: { definition: ctx.rowItem, value: ctx.item.properties ? ctx.item.properties[ctx.rowItem.PropertyName] : ctx.item[ctx.rowItem.PropertyName], type: ctx.rowItem.PropertyType} }\"></ng-container>\r\n </ng-container>\r\n </ng-container>\r\n\r\n <!-- 1% Se in modalit\u00E0 gerarchica metto il td per navigare la gerarchia -->\r\n <ng-container *ngIf=\"Hierarchy && ctx.i == 0\"><ng-container *ngTemplateOutlet=\"HierarchyNavigator; context: { $implicit: ctx.item }\"></ng-container></ng-container>\r\n\r\n <!-- 1% Content programmatico per le casistiche di Row Grouping ecc... -->\r\n <ng-container *ngIf=\"ctx.rowItem.Content\">\r\n {{ctx.rowItem.Content}}\r\n </ng-container>\r\n </div>\r\n\r\n <div *ngIf=\"ctx.rowItem._editing\" class=\"est-mt-min-5\">\r\n <ng-container *ngTemplateOutlet=\"ctx.rowItem.PropertyName | est_editor: { name: ctx.rowItem.EditorName, src: EsTdEditorDirectives, fallback: defaultEditor}; context: { $implicit: { definition: ctx.rowItem, columnIndex: ctx.i, item: ctx.item, finalizer: finalizeUserEdit.bind(this, ctx.rowItem, ctx.item, ctx.i) } }\"></ng-container>\r\n </div>\r\n </td>\r\n</ng-template>\r\n\r\n<!-- Navigatore della gerarchia di una view gerarchica, con tasto per espandere e collassare -->\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)=\"hierarchyMode_H.collapseParent(item[this.OwnKey])\"></span>\r\n <span *ngIf=\"item.parent && !item._expanded\" class=\"fa fa-chevron-up est-pointer est-no-selection\" (click)=\"hierarchyMode_H.expandParent(item[this.OwnKey])\"></span>\r\n &nbsp;\r\n</ng-template>\r\n\r\n<!-- 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-9' : ''}}\" *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-9' : ''}}\" *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-9' : ''}}\" *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-9' : ''}}\" *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-9' : ''}}\" *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><span><em>{{'No operations available' | localize : lc}}...</em></span></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\" cdkDrag>\r\n <div class=\"modal-content\">\r\n <div class=\"modal-header est-pointer\" cdkDragHandle>\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)=\"columnMetadata_H.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 *ngIf=\"DirectivesBased\" class=\"est-col-min\"></th>\r\n </tr>\r\n </thead>\r\n <tbody \r\n cdkDropList \r\n [cdkDropListData]=\"TMPColumnsList\" \r\n (cdkDropListDropped)=\"columnMetadata_H.columnReordered($event)\" \r\n [cdkDropListSortPredicate]=\"columnMetadata_H.sortPredicate.bind(this.columnMetadata_H)\"\r\n class=\"est-dropbox\">\r\n\r\n <tr *ngFor=\"let item of TMPColumnsList; let i = index; let last = last; trackBy: idTrackBy\" \r\n class=\"est-pointer est-droplist\" \r\n [class.est-white-selected]=\"lastSelectedItemID == item.id\" \r\n [class.est-no-selection]=\"!item.visible\"\r\n cdkDrag\r\n [cdkDragData]=\"item\"\r\n [cdkDragDisabled]=\"!ColumnsOrdering || item.fixed || item.pinned\">\r\n\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)=\"columnMetadata_H.updateGlobalColVisCheck();\" />\r\n </td>\r\n <td class=\"est-nowrap drag-visible\" (click)=\"columnMetadata_H.columnClicked(item);\">\r\n <ng-container *ngIf=\"item.template\">\r\n <!-- Padri -->\r\n <span *ngIf=\"item.parentTemplates && item.parentTemplates.length > 0\" class=\"est-fw-bold est-fs-13\">\r\n (&nbsp;\r\n <ng-container *ngFor=\"let parent of item.parentTemplates; let last=last; trackBy: idTrackBy\">\r\n <ng-container *ngIf=\"parent.tmpl\"><ng-container *ngTemplateOutlet=\"parent.tmpl\"></ng-container></ng-container>\r\n <ng-container *ngIf=\"parent.content\">{{parent.content}}</ng-container>\r\n <span *ngIf=\"!last\">&nbsp;-&nbsp;</span>\r\n </ng-container>\r\n &nbsp;)\r\n </span>\r\n <!-- Template header originale -->\r\n <ng-container *ngTemplateOutlet=\"item.template; context: { $implicit: item.multi ? item.multiContent : null }\"></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)=\"columnMetadata_H.columnClicked(item);\"></td>\r\n <!-- Pinner -->\r\n <td *ngIf=\"DirectivesBased && ColumnsPinnable\"><span *ngIf=\"!item.fixed && item.pinnable\" class=\"fa fa-thumb-tack\" [class.text-success]=\"item.pinned\" (click)=\"columnMetadata_H.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)=\"columnMetadata_H.confirmColumnVisibilitySelection() && changeColumnVisibilityModal.hide()\">{{'Confirm' | localize : lc}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n</div>",
5043
+ 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-head-resizer{top:0;right:0;bottom:0;width:7px;position:absolute;cursor:col-resize}.est-head-resizer-internal{top:0;right:0;left:6px;bottom:0;width:1px;position:absolute;background-color:#ccc;height:100%}.est-pointer{cursor:pointer}.est-high-density td,.est-high-density th{padding:0 .2rem}.est-default-row-height{height:31px}.est-no-selection{-webkit-user-select:none;-moz-user-select:none;-khtml-user-select:none;-ms-user-select:none}.est-edit-hidden{height:1px!important}.est-edit-hidden,.est-hidden-view{visibility:hidden}.est-no-border{border:none!important}.est-nowrap{white-space:nowrap}.est-mt-min-5{margin-top:-5px}.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-9{right:9px!important}.est-table-dotted-menu{padding:0 0 2px!important;color:#999}.est-fs-18{font-size:18px}.est-fs-13,.est-fs-14{font-size:14px}.est-fw-bold{font-weight:700}.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-relative{position:relative}.est-top-pager{position:absolute;right:0;top:5px}.est-top-allselect{position:absolute;left:0;top:5px;font-weight:700}.est-padding-10{padding:10px!important}.est-margin-right-50{margin-right:50px}.est-margin-left-50{margin-left:50px}.est-quick-unpin{color:#000;margin-left:8px;font-size:14px;transform:rotate(45deg)}.est-full-height{height:100%}.est-page-sel{color:#000;margin-left:3px;margin-right:3px;padding:0 5px;font-size:inherit;border:none;border-radius:15px}.est-page-next,.est-page-prev{color:#000;font-size:inherit;padding:2px 0 0}.est-pinned-header{background-color:#fff;left:0;top:0;position:-webkit-sticky;position:sticky;z-index:1;border-bottom:1px solid #dee2e6!important;padding:0!important}.est-simple-border-bottom{border-bottom:1px solid #dee2e6}.est-pinned-internal-header{border-top:0;border-bottom:0 solid #dee2e6}.est-pinned-border{border-right:2px solid #dee2e6!important}.est-cell-padding{padding:.3rem}.est-pinned-body{background-color:#fff;left:0;position:-webkit-sticky;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:-webkit-sticky;position:sticky;z-index:0;background-color:#fff}.est-sticky-last-column-alt{right:-1px;position:-webkit-sticky;position:sticky;z-index:0;background-color:#f2f2f2}.est-ltab-border{border-left:1px solid #bbb!important}.est-rtab-border{border-right:1px solid #bbb!important}.est-cell-group-padding{padding:calc(.3rem + 1px);position:absolute;top:0;left:0;height:100%;width:100%}.est-selected-cell{background-color:rgba(33,150,243,.2)}.est-cell-lborder{border-left:1.02px solid #2196f3!important}.est-cell-tborder{border-top:1.02px solid #2196f3!important}.est-cell-rborder{border-right:1.02px solid #2196f3!important}.est-cell-bborder{border-bottom:1.02px solid #2196f3!important}.est-cell-lborder-tmp{border-left:1.02px solid transparent!important}.est-cell-tborder-tmp{border-top:1.02px solid transparent!important}.est-cell-rborder-tmp{border-right:1.02px solid transparent!important}.est-cell-bborder-tmp{border-bottom:1.02px solid transparent!important}.est-margin-bottom-10{margin-bottom:10px}.est-text-center{text-align:center}.est-flex{display:flex}.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}.est-droplist.cdk-drag-placeholder{opacity:0}.est-droplist.cdk-drag-preview{z-index:999999999!important;opacity:1;box-sizing:border-box;border-radius:4px;background-color:#fff;box-shadow:0 5px 5px -3px rgba(0,0,0,.2),0 8px 10px 1px rgba(0,0,0,.14),0 3px 14px 2px rgba(0,0,0,.12)}.est-droplist.cdk-drag-preview td:not(.drag-visible){visibility:hidden}.est-droplist.cdk-drag-preview td.drag-visible{padding-top:3px}.est-droplist.cdk-drag-animating,.est-droplist.cdk-drop-list-dragging .est-dropbox:not(.cdk-drag-placeholder){transition:transform .25s cubic-bezier(0,0,.2,1)}.est-pre{white-space:pre}.est val-datetime .mat-form-field-appearance-outline .mat-form-field-infix input{margin-bottom:3px!important;min-width:130px!important}.est .mat-form-field-flex{height:29px!important;padding:0!important}.est .mat-form-field-flex .mat-form-field-outline{color:#00f}.est .mat-form-field-flex .mat-form-field-outline .mat-form-field-outline-start{border-left:none;border-top:none;border-radius:0}.est .mat-form-field-flex .mat-form-field-outline .mat-form-field-outline-end{border-top:none;border-radius:0;border-right:none}.est .mat-form-field-wrapper{height:20px;min-height:20px!important;margin-top:0!important}.est .mat-form-field-infix{width:100%!important;min-width:50px!important}.est .mat-form-field-infix select.mat-input-element{margin-top:-5px!important}.est .mat-datepicker-input{margin-bottom:3px!important}.est input{height:20px;padding-top:0!important}"]
4936
5044
  },] }
4937
5045
  ];
4938
5046
  EsTableComponent.ctorParameters = () => [
@@ -4948,7 +5056,8 @@ EsTableComponent.ctorParameters = () => [
4948
5056
  { type: DateService },
4949
5057
  { type: MessageService },
4950
5058
  { type: CopyPasteDetector },
4951
- { type: ClipboardService }
5059
+ { type: ClipboardService },
5060
+ { type: Logger }
4952
5061
  ];
4953
5062
  EsTableComponent.propDecorators = {
4954
5063
  EsTdEditorDirectives: [{ type: ContentChildren, args: [EsTdEditorDirective,] }],
@@ -5185,7 +5294,7 @@ class EsTh {
5185
5294
  EsTh.decorators = [
5186
5295
  { type: Component, args: [{
5187
5296
  selector: "[es-th]",
5188
- template: "<span (click)=\"setupNextOrderAndNotify()\" [class.app-no-selection]=\"!!ID && Orderable\" [class.app-pointer]=\"!!ID && Orderable\">\r\n <span #content>\r\n <ng-container *ngIf=\"Template\">\r\n <ng-container *ngTemplateOutlet=\"Template\"></ng-container>\r\n </ng-container>\r\n <ng-content *ngIf=\"!Template\"></ng-content>\r\n </span>&nbsp;\r\n <span class=\"fa\" [class.fa-chevron-down]=\"Order == 'DESC'\" [class.fa-chevron-up]=\"Order == 'ASC'\"></span>\r\n</span>\r\n<span *ngIf=\"Pinned && !Fixed\" class=\"app-pointer fa fa-thumb-tack est-quick-unpin\" (click)=\"unpin()\"></span>\r\n<div [hidden]=\"!Resizable || Fixed || Pinned\" class=\"est-head-resizer\" (mousedown)=\"onResizeStart($event)\">\r\n <div class=\"est-head-resizer-internal\"></div>\r\n</div>",
5297
+ template: "<span (click)=\"setupNextOrderAndNotify()\" [class.app-no-selection]=\"!!ID && Orderable\" [class.app-pointer]=\"!!ID && Orderable\">\r\n <span #content>\r\n <ng-container *ngIf=\"!!Template\">\r\n <ng-container *ngTemplateOutlet=\"Template\"></ng-container>\r\n </ng-container>\r\n <ng-content *ngIf=\"!Template\"></ng-content>\r\n </span>&nbsp;\r\n <span class=\"fa\" [class.fa-chevron-down]=\"Order == 'DESC'\" [class.fa-chevron-up]=\"Order == 'ASC'\"></span>\r\n</span>\r\n<span *ngIf=\"Pinned && !Fixed\" class=\"app-pointer fa fa-thumb-tack est-quick-unpin\" (click)=\"unpin()\"></span>\r\n<div [hidden]=\"!Resizable || Fixed || Pinned\" class=\"est-head-resizer\" (mousedown)=\"onResizeStart($event)\">\r\n <div class=\"est-head-resizer-internal\"></div>\r\n</div>",
5189
5298
  changeDetection: ChangeDetectionStrategy.OnPush
5190
5299
  },] }
5191
5300
  ];
@@ -5213,59 +5322,26 @@ EsTh.propDecorators = {
5213
5322
  onMouseMove: [{ type: HostListener, args: ['window:mousemove.out-zone', ['$event'],] }]
5214
5323
  };
5215
5324
 
5216
- //Angular
5325
+ // Angular
5217
5326
  /** Componente rappresentante una singola cella del body della tabella */
5218
5327
  class EsTd {
5219
5328
  /** @ignore */
5220
- constructor(cdr, myself, renderer, sanitizer) {
5329
+ constructor(cdr) {
5221
5330
  this.cdr = cdr;
5222
- this.myself = myself;
5223
- this.renderer = renderer;
5224
- this.sanitizer = sanitizer;
5225
5331
  /** Id della cella, dev'essere lo stesso della colonna **EsTh** relativa */
5226
5332
  this.ID = "";
5227
- /** Valore da mostrare all'interno della cella. Se omesso verrà proiettato il contenuto dal template in cui è stata usata */
5228
- this.Display = null;
5229
- /** Template Angular da istanziare per questo TD */
5230
- this.Template = null;
5231
5333
  /** Quando questa cella viene generata questo evento permette di dire "ehi, sono nato!" */
5232
5334
  this.onCellGeneration = new EventEmitter();
5233
- // Ema commenta grazie
5335
+ /** Errore attualmente presente sulla cella */
5234
5336
  this.ValidationError = "";
5235
5337
  }
5236
- /**
5237
- * Imposta la visibilità o meno della cella, si traduce nell'applicazione o rimozione della classe **app-display-none**
5238
- *
5239
- * @param {boolean} expression Indicazione della visibilità
5240
- */
5241
- set Visible(expression) {
5242
- this._Visible = expression;
5243
- if (expression)
5244
- this.renderer.removeClass(this.myself.nativeElement, "app-display-none");
5245
- else
5246
- this.renderer.addClass(this.myself.nativeElement, "app-display-none");
5247
- }
5248
- /**
5249
- * Restituisce lo stato di Visibilità della cella in oggetto
5250
- *
5251
- * @returns {boolean} **true** se visibile, **false** altrimenti
5252
- */
5253
- get Visible() {
5254
- if (this._Visible == undefined)
5255
- this._Visible = true;
5256
- return this._Visible;
5257
- }
5258
5338
  /** @ignore */
5259
5339
  ngAfterViewInit() {
5260
5340
  this.onCellGeneration.emit({ id: this.ID, hash: this.Context, self: this });
5261
- // Se è Internal significa che è gestita internamente da ES-TABLE quindi evito di fare sti due passaggi di lettura del DOM
5262
- if (this.Internal)
5263
- return;
5264
- this.Content = this.Display === null || this.Display === "" ? this.sanitizer.bypassSecurityTrustHtml(this.myself.nativeElement.innerHTML) : this.sanitizer.bypassSecurityTrustHtml(this.Display);
5265
- this.Class = this.myself.nativeElement.className.replace("app-display-none", "");
5266
5341
  }
5267
- validationError(isError, error) {
5268
- this.ValidationError = isError ? error : "";
5342
+ /** Api per impostare un "errore" su questa cella in maniera programmatica */
5343
+ validationError(error) {
5344
+ this.ValidationError = error;
5269
5345
  this.cdr.markForCheck();
5270
5346
  }
5271
5347
  }
@@ -5278,20 +5354,12 @@ EsTd.decorators = [
5278
5354
  },] }
5279
5355
  ];
5280
5356
  EsTd.ctorParameters = () => [
5281
- { type: ChangeDetectorRef },
5282
- { type: ElementRef },
5283
- { type: Renderer2 },
5284
- { type: DomSanitizer }
5357
+ { type: ChangeDetectorRef }
5285
5358
  ];
5286
5359
  EsTd.propDecorators = {
5287
5360
  ID: [{ type: Input, args: ['es-td',] }],
5288
- Internal: [{ type: Input }],
5289
- RouterLink: [{ type: Input }],
5290
- Display: [{ type: Input }],
5291
- Template: [{ type: Input }],
5292
5361
  Context: [{ type: Input }],
5293
- onCellGeneration: [{ type: Output }],
5294
- Visible: [{ type: Input }]
5362
+ onCellGeneration: [{ type: Output }]
5295
5363
  };
5296
5364
 
5297
5365
  // Angular
@@ -5349,12 +5417,148 @@ EstLookupPipe.decorators = [
5349
5417
  { type: Pipe, args: [{ name: 'est_lookup' },] }
5350
5418
  ];
5351
5419
 
5420
+ class EstRouterLinkPipe {
5421
+ constructor() {
5422
+ /** Cache per i routerLink generati nelle tabelle dinamiche */
5423
+ this.routerLinksCache = {};
5424
+ }
5425
+ transform(item, path, parameters) {
5426
+ if (this.routerLinksCache[item._hash + path]) {
5427
+ return this.routerLinksCache[item._hash + path];
5428
+ }
5429
+ else {
5430
+ let link = this.getRouterLink(path, parameters, item);
5431
+ this.routerLinksCache[item._hash + path] = link;
5432
+ return link;
5433
+ }
5434
+ }
5435
+ /**
5436
+ * Crea un router link
5437
+ *
5438
+ * @param {string} path Path su cui navigare con eventuali parametri riferiti all'oggetto cotnestuale come {0}, {1}, ecc...
5439
+ * @param {string[]} pars Lista posizionale delle proprietà a cui bindare i riferimenti del parametro **path**
5440
+ * Es. Il valore dela proprietà all'indice 0 di questo array verrà sostituita al valore {0} del parametro **path**
5441
+ * @param {any} item Oggetto collegato a questo contesto. Può essere un oggetto generico (con "properties") o un oggetto ben definito
5442
+ *
5443
+ * @returns {any} Router link generato in base al parametri
5444
+ */
5445
+ getRouterLink(path, pars, item) {
5446
+ for (let i = 0; i < pars.length; i++)
5447
+ path = path.replace('{' + i + '}', item.properties ? item.properties[pars[i]] : item[pars[i]]);
5448
+ path = path.replace(/'/g, '"').replace(/ /g, '');
5449
+ return JSON.parse(path);
5450
+ }
5451
+ }
5452
+ EstRouterLinkPipe.decorators = [
5453
+ { type: Pipe, args: [{ name: 'est_routerlink' },] }
5454
+ ];
5455
+
5456
+ // Angular
5457
+ class EstRendererPipe {
5458
+ constructor(logger) {
5459
+ this.logger = logger;
5460
+ }
5461
+ transform(propName, params) {
5462
+ var EsTd = null;
5463
+ // Perf. Version di `params.src.find((item) => params.name ? item.td === params.name : item.tdForProperty === propName);`
5464
+ for (let i = 0; i < params.src.length; i++) {
5465
+ let item = params.src.get(i);
5466
+ if (params.name && item.td === params.name ||
5467
+ !params.name && item.tdForProperty === propName) {
5468
+ EsTd = item;
5469
+ break;
5470
+ }
5471
+ }
5472
+ // Name non trovato, fallback al nome della colonna
5473
+ if (propName && params.name && !EsTd) {
5474
+ this.logger.log(`Renderer retrieved in a non performant way`);
5475
+ EsTd = params.src.find((item) => item.tdForProperty === propName);
5476
+ }
5477
+ this.logger.log(`Renderer ${EsTd ? 'found' : 'NOT found'} for '${propName}${params.name ? '/' + params.name : ''}'${!EsTd ? '. Using fallback renderer' : ''}`);
5478
+ var ret = EsTd ? EsTd.Template : params.fallback;
5479
+ return ret;
5480
+ }
5481
+ }
5482
+ EstRendererPipe.decorators = [
5483
+ { type: Pipe, args: [{ name: 'est_renderer' },] }
5484
+ ];
5485
+ EstRendererPipe.ctorParameters = () => [
5486
+ { type: Logger }
5487
+ ];
5488
+
5489
+ // Angular
5490
+ class EstEditorPipe {
5491
+ constructor(logger) {
5492
+ this.logger = logger;
5493
+ }
5494
+ transform(propName, params) {
5495
+ var Editor = null;
5496
+ // Perf. Version di `params.src.find((item) => params.name ? item.editor === params.name : item.editorForProperty === propName);`
5497
+ for (let i = 0; i < params.src.length; i++) {
5498
+ let item = params.src.get(i);
5499
+ if (params.name && item.editor === params.name ||
5500
+ !params.name && item.editorForProperty === propName) {
5501
+ Editor = item;
5502
+ break;
5503
+ }
5504
+ }
5505
+ // Name non trovato, fallback al nome della colonna
5506
+ if (propName && params.name && !Editor) {
5507
+ this.logger.log(`Editor retrieved in a non performant way`);
5508
+ Editor = params.src.find((item) => item.editorForProperty === propName);
5509
+ }
5510
+ this.logger.log(`Editor ${Editor ? 'found' : 'NOT found'} for '${propName}${params.name ? '/' + params.name : ''}'${!Editor ? '. Using fallback editor' : ''}`);
5511
+ var ret = Editor ? Editor.Template : params.fallback;
5512
+ return ret;
5513
+ }
5514
+ }
5515
+ EstEditorPipe.decorators = [
5516
+ { type: Pipe, args: [{ name: 'est_editor' },] }
5517
+ ];
5518
+ EstEditorPipe.ctorParameters = () => [
5519
+ { type: Logger }
5520
+ ];
5521
+
5522
+ const MODULES = [
5523
+ CommonModule,
5524
+ FormsModule,
5525
+ RouterModule,
5526
+ LocalizationModule,
5527
+ ModalModule,
5528
+ BsDropdownModule,
5529
+ ContextMenuModule,
5530
+ MatSelectModule,
5531
+ MatInputModule,
5532
+ MatTooltipModule,
5533
+ DragDropModule,
5534
+ FormsAndValidationsModule
5535
+ ];
5536
+ const PUBLIC_ELEMENTS = [
5537
+ // Direttive
5538
+ EsTdDirective,
5539
+ EsThDirective,
5540
+ EsTdEditorDirective,
5541
+ // Componenti
5542
+ EsTableComponent,
5543
+ TablePagerComponent,
5544
+ EsTableTemplate
5545
+ ];
5546
+ const PRIVATE_ELEMENTS = [
5547
+ // Componenti
5548
+ EsTh,
5549
+ EsTd,
5550
+ // Pipes
5551
+ EstFormatPipe,
5552
+ EstLookupPipe,
5553
+ EstRouterLinkPipe,
5554
+ EstRendererPipe,
5555
+ EstEditorPipe
5556
+ ];
5352
5557
  class EsTableModule {
5353
5558
  static forRoot(config) {
5354
5559
  return {
5355
5560
  ngModule: EsTableModule,
5356
5561
  providers: [
5357
- CopyPasteDetector,
5358
5562
  { provide: EST_LOCALE, useValue: (config === null || config === void 0 ? void 0 : config.locale) || 'it-IT' },
5359
5563
  { provide: EST_DEBUG, useValue: (config === null || config === void 0 ? void 0 : config.debugMode) || false },
5360
5564
  { provide: EST_DEFAULTS, useValue: (config === null || config === void 0 ? void 0 : config.defaults) || null },
@@ -5364,23 +5568,10 @@ class EsTableModule {
5364
5568
  }
5365
5569
  EsTableModule.decorators = [
5366
5570
  { type: NgModule, args: [{
5367
- imports: [
5368
- CommonModule,
5369
- FormsModule,
5370
- RouterModule,
5371
- LocalizationModule,
5372
- ModalModule,
5373
- BsDropdownModule,
5374
- ContextMenuModule,
5375
- MatSelectModule,
5376
- MatInputModule,
5377
- MatTooltipModule,
5378
- DragDropModule,
5379
- FormsAndValidationsModule
5380
- ],
5381
- declarations: [EsTh, EsTd, EsTableComponent, EsTdDirective, EsThDirective, EsTdEditorDirective, TablePagerComponent, EsTableTemplate, EstFormatPipe, EstLookupPipe],
5571
+ imports: [MODULES],
5572
+ declarations: [...PUBLIC_ELEMENTS, ...PRIVATE_ELEMENTS],
5382
5573
  providers: [UtilityService, ExportService, HashingService, MessageService],
5383
- exports: [EsTableComponent, EsTdDirective, EsThDirective, EsTdEditorDirective, TablePagerComponent, EsTableTemplate]
5574
+ exports: [...PUBLIC_ELEMENTS]
5384
5575
  },] }
5385
5576
  ];
5386
5577
 
@@ -5466,5 +5657,5 @@ class ItemPropEditableReference {
5466
5657
  * Generated bundle index. Do not edit.
5467
5658
  */
5468
5659
 
5469
- export { AppOrdering, AppSearch, CornerMenuOption, EsTableColumnsDefinition, EsTableComponent, EsTableDefaultable, EsTableModelChange, EsTableModule, EsTableModuleConfig, EsTableMultiValue, EsTableOperationDefinition, EsTableTemplate, EsTdDirective, EsTdEditorDirective, EsTdReference, EsThDirective, GenericItem, Group, GroupAggregation, GroupFilter, GroupOrAggregation, ItemPropEditableReference, ItemsSelection, ReportColumn, ReportParam, ReportRow, TablePagerComponent, TablePagerLoc as ɵa, EST_LOCALE as ɵb, EST_DEBUG as ɵc, EST_DEFAULTS as ɵd, EsTableLoc as ɵe, UtilitiesHandler as ɵf, CopyPasteDetector as ɵg, EsTh as ɵh, EsTd as ɵi, EstFormatPipe as ɵj, EstLookupPipe as ɵk };
5660
+ export { AppOrdering, AppSearch, CornerMenuOption, EsTableColumnsDefinition, EsTableComponent, EsTableDefaultable, EsTableModelChange, EsTableModule, EsTableModuleConfig, EsTableMultiValue, EsTableOperationDefinition, EsTableTemplate, EsTdDirective, EsTdEditorDirective, EsTdReference, EsThDirective, GenericItem, Group, GroupAggregation, GroupFilter, GroupOrAggregation, ItemPropEditableReference, ItemsSelection, ReportColumn, ReportParam, ReportRow, TablePagerComponent, TablePagerLoc as ɵa, EST_LOCALE as ɵb, EST_DEBUG as ɵc, EST_DEFAULTS as ɵd, EsTableLoc as ɵe, UtilitiesHandler as ɵf, CopyPasteDetector as ɵg, Logger as ɵh, EsTh as ɵi, EsTd as ɵj, EstFormatPipe as ɵk, EstLookupPipe as ɵl, EstRouterLinkPipe as ɵm, EstRendererPipe as ɵn, EstEditorPipe as ɵo };
5470
5661
  //# sourceMappingURL=esfaenza-es-table.js.map