backend-plus 2.7.0-beta.9 → 2.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- /*global myOwn, my, XLSX, Pikaday */
3
+ /*global myOwn, my, xlsxNowBrowser, Pikaday */
4
4
  /*global miniMenuPromise, dialogPromise, alertPromise, confirmPromise, promptPromise, simpleFormPromise */
5
5
  /*global Blob, document, CustomEvent, URL */
6
6
 
@@ -248,7 +248,7 @@ myOwn.getStructuresToRegisterInLdb = function getStructuresToRegisterInLdb(paren
248
248
  var dummyElement = html.div().create();
249
249
  var Connector = my.TableConnector;
250
250
  var connector = new Connector({
251
- my:my,
251
+ my:my,
252
252
  tableName: tableName,
253
253
  getElementToDisplayCount:function(){ return dummyElement }
254
254
  });
@@ -264,7 +264,7 @@ myOwn.getStructuresToRegisterInLdb = function getStructuresToRegisterInLdb(paren
264
264
  var dummyElement = html.div().create();
265
265
  var Connector = my.TableConnector;
266
266
  var connector = new Connector({
267
- my:my,
267
+ my:my,
268
268
  tableName: foreignKey.references,
269
269
  getElementToDisplayCount:function(){ return dummyElement }
270
270
  });
@@ -305,8 +305,8 @@ myOwn.TableConnector = function(context, opts){
305
305
 
306
306
  myOwn.TableConnector.prototype.getStructure = function getStructure(opts){
307
307
  var opts = changing({
308
- registerInLocalDB: false,
309
- waitForFreshStructure: false
308
+ registerInLocalDB: false,
309
+ waitForFreshStructure: false
310
310
  }, opts || {});
311
311
  var connector = this;
312
312
  var my = connector.my;
@@ -337,7 +337,7 @@ myOwn.TableConnector.prototype.getStructure = function getStructure(opts){
337
337
  connector.whenStructureReady = canContinue.then(function(){
338
338
  return my.getStructureFromLocalDb(connector.tableName);
339
339
  }).then(function(tableDef){
340
- if(!tableDef){
340
+ if(!tableDef){
341
341
  return structureFromBackend;
342
342
  }
343
343
  connector.localDef = connector.def = changing(tableDef, connector.opts.tableDef||{});
@@ -384,7 +384,7 @@ myOwn.TableConnector.prototype.deleteRecord = function deleteRecord(depot, opts)
384
384
  return (depot.primaryKeyValues===false?
385
385
  Promise.resolve():
386
386
  depot.my.ajax.table_record_delete({
387
- table:depot.def.name,
387
+ table:depot.def.name,
388
388
  primaryKeyValues:depot.primaryKeyValues,
389
389
  launcher:opts.launcher
390
390
  }).then(function(){
@@ -419,7 +419,7 @@ myOwn.TableConnector.prototype.recordEnter = function recordEnter(depot){
419
419
  return (!this.my.config.cursor || depot.primaryKeyValues===false?
420
420
  Promise.resolve():
421
421
  depot.my.ajax.table_record_enter({
422
- table:depot.def.name,
422
+ table:depot.def.name,
423
423
  primaryKeyValues:depot.primaryKeyValues
424
424
  })
425
425
  );
@@ -428,7 +428,7 @@ myOwn.TableConnector.prototype.recordLeave = function recordLeave(depot){
428
428
  return (!this.my.config.cursor || depot.primaryKeyValues===false?
429
429
  Promise.resolve():
430
430
  depot.my.ajax.table_record_leave({
431
- table:depot.def.name,
431
+ table:depot.def.name,
432
432
  primaryKeyValues:depot.primaryKeyValues
433
433
  })
434
434
  );
@@ -445,7 +445,7 @@ myOwn.TableConnectorLocal = function(context, opts){
445
445
  connector.opts = opts||{};
446
446
  connector.fixedFields = connector.opts.fixedFields || [];
447
447
  connector.fixedField = {};
448
- connector.pick = connector.opts.pick;
448
+ connector.pick = connector.opts.pick;
449
449
  connector.hideBecauseRelated = {};
450
450
  connector.fixedFields.forEach(function(pair){
451
451
  if(!pair.range && !pair.until && pair.value != myOwn.skipInFixedFields){
@@ -461,7 +461,7 @@ myOwn.TableConnectorLocal = function(context, opts){
461
461
  myOwn.TableConnectorLocal.prototype.getStructure = function getStructure(){
462
462
  var connector = this;
463
463
  connector.whenStructureReady = my.getStructureFromLocalDb(connector.tableName).then(function(tableDef){
464
- if(!tableDef){
464
+ if(!tableDef){
465
465
  var err = new Error();
466
466
  err.code='NO-STRUCTURE';
467
467
  throw err;
@@ -587,8 +587,8 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
587
587
  grid.detailingPath=opts.detailingPath;
588
588
  var Connector = my.offline.mode?my.TableConnectorLocal:my.TableConnector;
589
589
  grid.connector = new Connector({
590
- my:this,
591
- tableName: tableName,
590
+ my:this,
591
+ tableName: tableName,
592
592
  getElementToDisplayCount:function(){ return (grid.dom.footInfo||{}).displayTo||html.div().create(); }
593
593
  }, opts);
594
594
  var preparing = grid.prepareAndDisplayGrid().then(function(){
@@ -661,9 +661,9 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
661
661
  changeIoStatus(depot,'ok', depot.row);
662
662
  },3000);
663
663
  }
664
- } else if (depot) {
664
+ } else if (depot) {
665
665
  if (!sameValue(JSON.stringify(row),JSON.stringify(depot.row))) {
666
- //grid.retrieveRowAndRefresh(depot);
666
+ //grid.retrieveRowAndRefresh(depot);
667
667
  if(depot.tr){
668
668
  grid.depotRefresh(depot,{updatedRow:row, sendedForUpdate:{}},{noDispatchEvents:true});
669
669
  }
@@ -676,7 +676,7 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
676
676
  var depotsToDisplay = grid.filterDepots(grid.depots);
677
677
  var depotsToDelete = depotsToDisplay.filter(depot => depot.tick != tick);
678
678
  var depot;
679
- if (myOwn.config.config['grid-row-retain-moved-or-deleted'] && !force) {
679
+ if (myOwn.config.config['grid-row-retain-moved-or-deleted'] && !force) {
680
680
  var depotsToRetain = grid.depots.filter(depot => depot.tick == tick);
681
681
  for (depot of depotsToRetain) {
682
682
  depot['$refreshed'] = false
@@ -684,10 +684,10 @@ myOwn.tableGrid = function tableGrid(tableName, mainElement, opts){
684
684
  }
685
685
  }
686
686
  while (depot = depotsToDelete.pop()) {
687
- depot.manager.displayAsDeleted(depot, force ? 'change-ff' : 'unknown');
688
- if (myOwn.config.config['grid-row-retain-moved-or-deleted']) {
687
+ depot.manager.displayAsDeleted(depot, force ? 'change-ff' : 'unknown');
688
+ if (myOwn.config.config['grid-row-retain-moved-or-deleted']) {
689
689
  if(!depot['$refreshed']){
690
- grid.retrieveRowAndRefresh(depot,{retrieveIgnoringWhere:true})
690
+ grid.retrieveRowAndRefresh(depot,{retrieveWithBroadWhere:true})
691
691
  depot['$refreshed'] = true
692
692
  }
693
693
  }
@@ -744,7 +744,7 @@ myOwn.TableGrid.prototype.createDepotFromRow = function createDepotFromRow(row,
744
744
  var depot = {
745
745
  my: grid.my,
746
746
  def: grid.def,
747
- connector: grid.connector,
747
+ connector: grid.connector,
748
748
  manager: grid,
749
749
  rowControls:{},
750
750
  row: row,
@@ -956,7 +956,7 @@ myOwn.DataColumnGrid.prototype.cellAttributes = function cellAttributes(specific
956
956
  }
957
957
  return attr;
958
958
  }
959
-
959
+
960
960
  myOwn.DataColumnGrid.prototype.th = function th(){
961
961
  var fieldDef = this.fieldDef;
962
962
  var grid = this.grid;
@@ -1098,11 +1098,11 @@ myOwn.DataColumnGrid.prototype.td = function td(depot, iColumn, tr, saveRow){
1098
1098
  if (fieldDef.references) {
1099
1099
  promiseChain = promiseChain.then(
1100
1100
  grid.setInheritedFields(depot, function(fkDef){
1101
- return fkDef.references == fieldDef.references &&
1101
+ return fkDef.references == fieldDef.references &&
1102
1102
  fkDef.fields.find(function(field){
1103
1103
  return field.source == fieldDef.name
1104
1104
  }) &&
1105
- fkDef.displayFields.length >= 0
1105
+ fkDef.displayFields.length >= 0
1106
1106
  }
1107
1107
  ));
1108
1108
  }
@@ -1205,7 +1205,7 @@ myOwn.DetailColumnGrid.prototype.td = function td(depot, iColumn, tr){
1205
1205
  if(!event.ctrlKey && event.button!=1){
1206
1206
  event.preventDefault();
1207
1207
  }
1208
- detailControl.displayDetailGrid({fixedFields:fixedFields, detailing:{}},event);
1208
+ detailControl.displayDetailGrid({fixedFields:fixedFields, detailing:{}},event);
1209
1209
  }
1210
1210
  detailControl.forceDisplayDetailGrid = function(opts){
1211
1211
  if(detailControl.show){
@@ -1217,7 +1217,7 @@ myOwn.DetailColumnGrid.prototype.td = function td(depot, iColumn, tr){
1217
1217
  detailControl.refreshDetailGrid = function(opts){
1218
1218
  var detailControl=this;
1219
1219
  if(detailControl.show){
1220
-
1220
+
1221
1221
  }
1222
1222
  }
1223
1223
  detailControl.displayDetailGrid = function(opts,event){
@@ -1253,8 +1253,8 @@ myOwn.DetailColumnGrid.prototype.td = function td(depot, iColumn, tr){
1253
1253
  wScreen.mainAction(params,divGrid);
1254
1254
  }else{
1255
1255
  result = grid.my.tableGrid(detailTableDef.table, divGrid, {
1256
- fixedFields: fixedFields,
1257
- detailing:opts.detailing,
1256
+ fixedFields: fixedFields,
1257
+ detailing:opts.detailing,
1258
1258
  detailingForUrl:grid.detailingForUrl,
1259
1259
  detailingPath:(grid.detailingPath||[]).concat(depot.lastsPrimaryKeyValues),
1260
1260
  parentDepot: depot
@@ -1415,7 +1415,7 @@ myOwn.TableGrid.prototype.prepareMenu = function prepareMenu(button){
1415
1415
  grid.hideColumnsViaCss();
1416
1416
  });
1417
1417
  selectColumnsToShowElement.addEventListener('change',function(){
1418
- var listOptionsToShow=Array.prototype.slice.call(selectColumnsToShowElement.selectedOptions);
1418
+ var listOptionsToShow=Array.prototype.slice.call(selectColumnsToShowElement.selectedOptions);
1419
1419
  listOptionsToShow.forEach(function(option) {
1420
1420
  grid.view.hiddenColumns.splice(grid.view.hiddenColumns.indexOf(option.value),1);
1421
1421
  selectColumnsToShowElement.removeChild(option);
@@ -1450,9 +1450,9 @@ myOwn.TableGrid.prototype.prepareMenu = function prepareMenu(button){
1450
1450
  var messages = {};
1451
1451
  menuOptions.push(
1452
1452
  myOwn.dialogUpload(
1453
- 'table_upload',
1453
+ 'table_upload',
1454
1454
  {
1455
- table:grid.def.name,
1455
+ table:grid.def.name,
1456
1456
  prefilledFields:grid.connector.fixedFields,
1457
1457
  skipUnknownFieldsAtImport:null
1458
1458
  },
@@ -1533,8 +1533,8 @@ myOwn.TableGrid.prototype.prepareMenu = function prepareMenu(button){
1533
1533
  })
1534
1534
  );
1535
1535
  menuOptions.push({
1536
- img:my.path.img+'filtered-complete-table.png',
1537
- label:my.messages.filteredCompleteTable,
1536
+ img:my.path.img+'filtered-complete-table.png',
1537
+ label:my.messages.filteredCompleteTable,
1538
1538
  href:urlFilteredCompleteTable,
1539
1539
  showPage:my.showPage,
1540
1540
  });
@@ -1577,14 +1577,14 @@ myOwn.dialogDownload = function dialogDownload(grid){
1577
1577
  html.div({class:'state-preparing'}, [
1578
1578
  html.div(my.messages.preparingForExport),
1579
1579
  html.img({
1580
- class:'img-preparing',
1581
- src:'img/preparing.png',
1582
- alt:my.messages.preparingForExport,
1583
- title:my.messages.preparingForExport,
1580
+ class:'img-preparing',
1581
+ src:'img/preparing.png',
1582
+ alt:my.messages.preparingForExport,
1583
+ title:my.messages.preparingForExport,
1584
1584
  }),
1585
1585
  ]),
1586
1586
  html.div({class:'state-ready'}, [downloadElement]),
1587
- html.div('.'),
1587
+ html.div('.'),
1588
1588
  ]).create();
1589
1589
  dialogWindow.appendChild(mainDiv);
1590
1590
  var fieldsDef2Export=[];
@@ -1596,9 +1596,9 @@ myOwn.dialogDownload = function dialogDownload(grid){
1596
1596
  var prepare=function(){
1597
1597
  mainDiv.setAttribute("current-state", "preparing");
1598
1598
  setTimeout(function(){
1599
- fieldsDef2Export=grid.def.fields.filter(function(fieldDef){
1600
- return (fieldDef.inTable!==false || input.fromOtherTables.checked)
1601
- && fieldDef.visible
1599
+ fieldsDef2Export=grid.def.fields.filter(function(fieldDef){
1600
+ return (fieldDef.inTable!==false || input.fromOtherTables.checked)
1601
+ && fieldDef.visible
1602
1602
  && (fieldDef.allow.update || input.readOnly.checked || fieldDef.isPk)
1603
1603
  && (!grid.view.hiddenColumns.includes(fieldDef.name) || input.hiddens.checked);
1604
1604
  });
@@ -1607,7 +1607,7 @@ myOwn.dialogDownload = function dialogDownload(grid){
1607
1607
  }else{
1608
1608
  if(input.csv.checked){
1609
1609
  separator=',';
1610
- replacer=function(txt){
1610
+ replacer=function(txt){
1611
1611
  return /[\n,"]/.test(txt)?'"'+txt.replace(/"/g,'""')+'"':txt
1612
1612
  }
1613
1613
  dotExtension='.csv';
@@ -1619,7 +1619,7 @@ myOwn.dialogDownload = function dialogDownload(grid){
1619
1619
  '\r':'\\r',
1620
1620
  '\n':'\\n',
1621
1621
  }
1622
- replacer=function(txt){
1622
+ replacer=function(txt){
1623
1623
  return txt.replace(/[|\\\r\n]/g,function(char){
1624
1624
  return trans[char];
1625
1625
  })
@@ -1651,37 +1651,75 @@ myOwn.dialogDownload = function dialogDownload(grid){
1651
1651
  }));
1652
1652
  });
1653
1653
  var blob = new Blob([data.map(function(line){return line.map(replacer).join(separator)}).join('\r\n')], {type: 'text/plain'});
1654
- var url = URL.createObjectURL(blob);
1654
+ var url = URL.createObjectURL(blob);
1655
1655
  downloadElement.href=url;
1656
1656
  downloadElement.setAttribute("download", grid.def.name+dotExtension);
1657
1657
  mainDiv.setAttribute("current-state", "ready");
1658
1658
  }
1659
- var STYLE_HEADER={ font: {bold:true, underline:true}/*, alignment:{horizontal:'center'}*/};
1660
- var STYLE_EXTRA_HEADER={ font: {bold:true, underline:true, color:{rgb: "800040"}}/*, alignment:{horizontal:'center'}*/};
1661
- var STYLE_PK={font:{bold:true}};
1662
- var STYLE_LOOKUP={font:{color:{ rgb: "5588DD" }}};
1663
- var populateTableXLS = function populateTableXLS(ws, depots, fieldDefs, topRow, leftColumn){
1664
- topRow=topRow||0;
1659
+ var XLSX_STYLES={
1660
+ header : {bold:true},
1661
+ extraHeader : {bold:true, color:"404040"},
1662
+ pk : {bold:true},
1663
+ lookup : {color:"404040"},
1664
+ interval : {numFmt:'[h]:mm:ss'},
1665
+ intervalPk : {base:'pk' , numFmt:'[h]:mm:ss'},
1666
+ intervalLookup:{base:'lookup', numFmt:'[h]:mm:ss'},
1667
+ };
1668
+ // Las columnas que salen de exportJsonFieldAsColumns aparecen recién al
1669
+ // recorrer las filas, pero el encabezado se escribe antes que ellas: con
1670
+ // escritura secuencial hay que conocerlas de entrada, y esta pasada las junta.
1671
+ var collectExtraColumns = function collectExtraColumns(depots, fieldDefs, firstColumn){
1672
+ var lastColumn=firstColumn-1;
1673
+ if(grid.def.exportJsonFieldAsColumns){
1674
+ depots.forEach(function(depot){
1675
+ fieldDefs.forEach(function(fieldDef){
1676
+ if(grid.def.exportJsonFieldAsColumns == fieldDef.name){
1677
+ var value=depot.row[fieldDef.name];
1678
+ var fields = typeof value == "string" ? JSON.parse(value) : value;
1679
+ for(var name in fields){
1680
+ if(extraColumns[name]==null){
1681
+ extraColumns[name] = ++lastColumn;
1682
+ }
1683
+ }
1684
+ }
1685
+ });
1686
+ });
1687
+ }
1688
+ return lastColumn;
1689
+ }
1690
+ var styleForField = function styleForField(fieldDef, depot){
1691
+ var isInterval = fieldDef.typeName == 'interval';
1692
+ if(fieldDef.isPk){
1693
+ return isInterval?'intervalPk':'pk';
1694
+ }
1695
+ if(!fieldDef.allow || !fieldDef.allow.update || depot.allow.update === false){
1696
+ return isInterval?'intervalLookup':'lookup';
1697
+ }
1698
+ return isInterval?'interval':undefined;
1699
+ }
1700
+ // Las filas de una tabla, como las toma xlsx-now: la primera es el
1701
+ // encabezado y cada una de las demás es un array donde la posición es la
1702
+ // columna. `leftColumn` corre la tabla entera hacia la derecha.
1703
+ var tableRowsXLS = function tableRowsXLS(depots, fieldDefs, leftColumn){
1665
1704
  leftColumn=leftColumn||0;
1666
- fieldDefs.forEach(function(field,iColumn){
1667
- ws[XLSX.utils.encode_cell({c:iColumn+leftColumn,r:topRow})]={t:'s',v:field.name, s:STYLE_HEADER};
1668
- lastColumnExported = Math.max(lastColumnExported, iColumn);
1705
+ var lastColumn=collectExtraColumns(depots, fieldDefs, fieldDefs.length);
1706
+ lastColumnExported = Math.max(lastColumnExported, lastColumn);
1707
+ var pad=new Array(leftColumn);
1708
+ var headerRow=pad.concat(fieldDefs.map(function(field){
1709
+ return {v:field.name, s:'header'};
1710
+ }));
1711
+ likeAr(extraColumns).forEach(function(pos, name){
1712
+ headerRow[pos+leftColumn]={v:name, s:'extraHeader'};
1669
1713
  });
1670
- depots.forEach(function(depot, iRow){
1714
+ var rows=[headerRow];
1715
+ depots.forEach(function(depot){
1716
+ var row=pad.concat([]);
1671
1717
  var addCell = function addCell(value, fieldDef, iColumn){
1672
1718
  if(value!=null){
1673
- var excelValue=typeStore.typerFrom(fieldDef).toExcelValue(value);
1674
- var valueType=typeStore.typerFrom(fieldDef).toExcelType(value);
1675
- var cell={t:valueType,v:excelValue};
1676
- if(fieldDef.typeName == 'interval'){
1677
- cell.z='[h]:mm:ss';
1678
- }
1679
- if(fieldDef.isPk){
1680
- cell.s=STYLE_PK;
1681
- }else if(!fieldDef.allow || !fieldDef.allow.update || depot.allow.update === false){
1682
- cell.s=STYLE_LOOKUP;
1683
- }
1684
- ws[XLSX.utils.encode_cell({c:iColumn+leftColumn,r:iRow+1+topRow})]=cell;
1719
+ row[iColumn+leftColumn]={
1720
+ v:typeStore.typerFrom(fieldDef).toExcelValue(value),
1721
+ s:styleForField(fieldDef, depot),
1722
+ };
1685
1723
  }
1686
1724
  }
1687
1725
  fieldDefs.forEach(function(fieldDef, iColumn){
@@ -1689,36 +1727,36 @@ myOwn.dialogDownload = function dialogDownload(grid){
1689
1727
  if(grid.def.exportJsonFieldAsColumns == fieldDef.name){
1690
1728
  var fields = typeof value == "string" ? JSON.parse(value) : value;
1691
1729
  for(var name in fields){
1692
- var pos = extraColumns[name];
1693
- if(pos==null){
1694
- lastColumnExported++;
1695
- extraColumns[name] = lastColumnExported;
1696
- ws[XLSX.utils.encode_cell({c:lastColumnExported+leftColumn,r:topRow})]={t:'s',v:name, s:STYLE_EXTRA_HEADER};
1697
- pos = lastColumnExported;
1698
- }
1699
- addCell(fields[name], {typeName:typeof fields[name] == 'number'? 'decimal':'text'}, pos)
1730
+ addCell(fields[name], {typeName:typeof fields[name] == 'number'? 'decimal':'text'}, extraColumns[name])
1700
1731
  }
1701
1732
  }else{
1702
1733
  addCell(value, fieldDef, iColumn);
1703
1734
  }
1704
1735
  });
1736
+ rows.push(row);
1705
1737
  });
1706
- ws["!ref"]="A1:"+XLSX.utils.encode_cell({c:lastColumnExported+leftColumn,r:grid.depotsToDisplay.length+topRow});
1738
+ return rows;
1707
1739
  }
1708
1740
  var excelExport = function(){
1709
- var wb = XLSX.utils.book_new();
1710
- var ws = {};
1711
- var exportFileInformationWs={};
1712
- var i=0;
1713
- exportFileInformationWs[XLSX.utils.encode_cell({c:0,r:++i})]={t:'s',v:'table',s:STYLE_HEADER};
1714
- exportFileInformationWs[XLSX.utils.encode_cell({c:1,r: i})]={t:'s',v:grid.def.name};
1715
- exportFileInformationWs[XLSX.utils.encode_cell({c:0,r:++i})]={t:'s',v:'date',s:STYLE_HEADER};
1716
- exportFileInformationWs[XLSX.utils.encode_cell({c:1,r: i})]={t:'s',v:new Date().toISOString()};
1717
- exportFileInformationWs[XLSX.utils.encode_cell({c:0,r:++i})]={t:'s',v:'user',s:STYLE_HEADER};
1718
- exportFileInformationWs[XLSX.utils.encode_cell({c:1,r: i})]={t:'s',v:my.config.username};
1719
- // grid.def.allow.forEach(function(action,iAction){
1720
- // exportFileInformationWs[XLSX.utils.encode_cell({c:iAction,r:2})]={t:'s',v:action};
1721
- // })
1741
+ var sheet1name=grid.def.name.length>27?grid.def.name.slice(0,27)+'...':grid.def.name;
1742
+ var sheet2name=grid.def.name!=="metadata"?"metadata":"meta-data";
1743
+ var dataSheet = {
1744
+ name: sheet1name,
1745
+ freezeRows: 1,
1746
+ freezeColumns: grid.def.primaryKey?.length ?? 0,
1747
+ autoWidthMax: 40,
1748
+ rows: tableRowsXLS(grid.depotsToDisplay, fieldsDef2Export)
1749
+ };
1750
+ var metadataSheet = {
1751
+ name:sheet2name,
1752
+ autoWidthMax: 40,
1753
+ rows: [
1754
+ [],
1755
+ [{v:'table',s:'header'}, grid.def.name],
1756
+ [{v:'date' ,s:'header'}, new Date().toISOString()],
1757
+ [{v:'user' ,s:'header'}, my.config.username],
1758
+ ]
1759
+ };
1722
1760
  if(grid.def.exportMetadata){
1723
1761
  if(grid.def.exportMetadata.fieldProperties){
1724
1762
  var fieldPropertiesDefs=grid.def.exportMetadata.fieldProperties.map(function(propName, i){
@@ -1729,22 +1767,22 @@ myOwn.dialogDownload = function dialogDownload(grid){
1729
1767
  }).map(function(fieldDef){
1730
1768
  return {row:fieldDef};
1731
1769
  });
1732
- populateTableXLS(exportFileInformationWs, fieldPropertiesDepot,fieldPropertiesDefs,i+1,1);
1770
+ extraColumns={};
1771
+ metadataSheet.rows.push(...(tableRowsXLS(fieldPropertiesDepot,fieldPropertiesDefs,1)));
1733
1772
  }
1734
1773
  }
1735
- populateTableXLS(ws, grid.depotsToDisplay, fieldsDef2Export);
1736
- var sheet1name=grid.def.name.length>27?grid.def.name.slice(0,27)+'...':grid.def.name;
1737
- var sheet2name=grid.def.name!=="metadata"?"metadata":"meta-data";
1738
- wb.SheetNames=[sheet1name,sheet2name];
1739
- wb.Sheets[sheet1name]=ws;
1740
- exportFileInformationWs["!ref"]="A1:F100";
1741
- wb.Sheets[sheet2name]=exportFileInformationWs;
1742
- var wbFile = XLSX.write(wb, {bookType:'xlsx', bookSST:false, type: 'binary', cellDates:true});
1743
- var blob = new Blob([s2ab(wbFile)],{type:"application/octet-stream"});
1744
- mainDiv.setAttribute("current-state", "ready");
1745
- var url = URL.createObjectURL(blob);
1746
- downloadElement.href=url;
1747
- downloadElement.setAttribute("download", grid.def.name+".xlsx");
1774
+ xlsxNowBrowser.createXlsxBlob({
1775
+ sheets: [dataSheet, metadataSheet],
1776
+ styles:XLSX_STYLES
1777
+ }).then(function(blob){
1778
+ mainDiv.setAttribute("current-state", "ready");
1779
+ var url = URL.createObjectURL(blob);
1780
+ downloadElement.href=url;
1781
+ downloadElement.setAttribute("download", grid.def.name+".xlsx");
1782
+ }).catch(function(err){
1783
+ mainDiv.setAttribute("current-state", "chossing");
1784
+ alertPromise(err.message);
1785
+ });
1748
1786
  };
1749
1787
  });
1750
1788
  };
@@ -1824,7 +1862,7 @@ myOwn.dialogUpload = function dialogUpload(ajaxPath, ajaxParams, ajaxPrepareResu
1824
1862
  });
1825
1863
  simpleFormPromise({elementsList:[
1826
1864
  messages.importDataFromFile,
1827
- buttonFile,
1865
+ buttonFile,
1828
1866
  ...(optsNames.map(name => html.label([html.br(), buttons[name], messages[name]]).create())),
1829
1867
  html.br().create(),
1830
1868
  buttonConfirmImport,
@@ -2052,7 +2090,7 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2052
2090
  ]).create();
2053
2091
  grid.prepareMenu(buttonMenu);
2054
2092
  grid.columns=[new my.ActionColumnGrid({
2055
- grid:grid,
2093
+ grid:grid,
2056
2094
  actions:[
2057
2095
  /*buttonInsert,*//*buttonSaveMode,*/buttonCreateFilter,buttonCreateFilterAdd,buttonDestroyFilter,
2058
2096
  buttonOrientation,
@@ -2069,8 +2107,8 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2069
2107
  // [new my.SpecialColumnGrid({class:"empty-right-column"})]
2070
2108
  );
2071
2109
  if(grid.modes.withColumnDetails==null){
2072
- grid.modes.withColumnDetails=grid.def.fields.some(function(fieldDef){
2073
- return fieldDef.label!=fieldDef.title;
2110
+ grid.modes.withColumnDetails=grid.def.fields.some(function(fieldDef){
2111
+ return fieldDef.label!=fieldDef.title;
2074
2112
  });
2075
2113
  }
2076
2114
  if(grid.vertical){
@@ -2087,7 +2125,7 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2087
2125
  elementInfo[info.name] = html.span(info.value).create();
2088
2126
  elementInfo.appendChild(elementInfo[info.name]);
2089
2127
  });
2090
- elementInfo.displayTo.textContent = my.messages.loading;
2128
+ elementInfo.displayTo.textContent = my.messages.loading;
2091
2129
  }
2092
2130
  grid.dom.headInfo = html.th({class: 'head-info', colspan:grid.columns.length-1, "is-processing":"1"}).create();
2093
2131
  createInfoColumnStructure(grid.dom.headInfo);
@@ -2116,11 +2154,11 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2116
2154
  grid.dom.table = html.table({"class":"my-grid", "my-table": grid.actualName},[
2117
2155
  grid.dom.caption,
2118
2156
  html.tbody(
2119
- grid.columns.map(function(column){
2157
+ grid.columns.map(function(column){
2120
2158
  return html.tr([
2121
2159
  column.th(),
2122
2160
  grid.modes.withColumnDetails?html.tr(grid.columns.map(function(column){ return column.thDetail(); })):null
2123
- ]);
2161
+ ]);
2124
2162
  })
2125
2163
  ),
2126
2164
  html.tfoot([
@@ -2159,7 +2197,7 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2159
2197
  var dummyElement = html.div().create();
2160
2198
  var Connector = my.offline.mode?my.TableConnectorLocal:my.TableConnector;
2161
2199
  var myConnector = new Connector({
2162
- my:my,
2200
+ my:my,
2163
2201
  tableName: fkDef.references,
2164
2202
  getElementToDisplayCount:function(){ return dummyElement }
2165
2203
  }, {fixedFields: fixedFields});
@@ -2187,7 +2225,7 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2187
2225
 
2188
2226
  myOwn.specialDefaultValue={
2189
2227
  current_date:function(){ return myOwn.config.currentDate||bestGlobals.date.today(); },
2190
- next_number:function(fieldName, aboveDepot, belowDepot){
2228
+ next_number:function(fieldName, aboveDepot, belowDepot){
2191
2229
  var manager = aboveDepot.manager ?? belowDepot.manager
2192
2230
  if(!manager){
2193
2231
  return 1;
@@ -2202,7 +2240,7 @@ myOwn.specialDefaultValue={
2202
2240
  }
2203
2241
  return belowDepot.row[fieldName]?belowDepot.row[fieldName]+1:(
2204
2242
  aboveDepot.row[fieldName]?aboveDepot.row[fieldName]-1:1
2205
- );
2243
+ );
2206
2244
  },
2207
2245
  current_user: function specialDefaultValueCurrentUser(){
2208
2246
  return my.config.username;
@@ -2239,7 +2277,7 @@ myOwn.TableGrid.prototype.createRowInsertElements = function createRowInsertElem
2239
2277
  }
2240
2278
  /*
2241
2279
  while(
2242
- position<grid.dom.table.tBodies[0].rows.length &&
2280
+ position<grid.dom.table.tBodies[0].rows.length &&
2243
2281
  grid.dom.table.tBodies[0].rows[position].isDetail
2244
2282
  ){
2245
2283
  position++;
@@ -2296,10 +2334,10 @@ var changeIoStatus = function changeIoStatus(depot,newStatus, objectWithFieldsOr
2296
2334
  var fieldNames=typeof objectWithFieldsOrListOfFieldNames === "string"?[objectWithFieldsOrListOfFieldNames]:(
2297
2335
  objectWithFieldsOrListOfFieldNames instanceof Array?objectWithFieldsOrListOfFieldNames:Object.keys(objectWithFieldsOrListOfFieldNames)
2298
2336
  );
2299
- fieldNames.forEach(function(name){
2337
+ fieldNames.forEach(function(name){
2300
2338
  if(depot.rowControls[name]){
2301
2339
  var td=depot.rowControls[name];
2302
- td.setAttribute('io-status', newStatus);
2340
+ td.setAttribute('io-status', newStatus);
2303
2341
  if(title){
2304
2342
  td.title=title;
2305
2343
  }else{
@@ -2365,8 +2403,8 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2365
2403
  if(depot.status==='new'){
2366
2404
  var specialMandatories=grid.def.specialValidator?myOwn.validators[grid.def.specialValidator].getMandatoryMap(depot.row):{};
2367
2405
  var mandatoryOmitted=function(fieldDef){
2368
- return (specialMandatories[fieldDef.name] || fieldDef.nullable!==true && fieldDef.isPk || fieldDef.nullable===false)
2369
- && depot.row[fieldDef.name]==null
2406
+ return (specialMandatories[fieldDef.name] || fieldDef.nullable!==true && fieldDef.isPk || fieldDef.nullable===false)
2407
+ && depot.row[fieldDef.name]==null
2370
2408
  && (grid.connector.fixedFields.find(function(pair){
2371
2409
  return !pair.range && !pair.until && pair.fieldName===fieldDef.name
2372
2410
  })||{}).value == null
@@ -2393,11 +2431,11 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2393
2431
  // var sendedForUpdate = depot.my.cloneRow(depot.rowPendingForUpdate);
2394
2432
  return my.ajax.table_data({
2395
2433
  table:depot.def.name,
2396
- fixedFields:grid.def.primaryKey.map(function(fieldName, i){
2434
+ fixedFields:grid.def.primaryKey.map(function(fieldName, i){
2397
2435
  return {fieldName:fieldName, value:depot.primaryKeyValues[i]};
2398
2436
  }),
2399
2437
  pick:grid.def.pick,
2400
- retrieveIgnoringWhere: opts?opts.retrieveIgnoringWhere:false
2438
+ retrieveWithBroadWhere : opts?.retrieveWithBroadWhere ?? false
2401
2439
  }).then(function(result){
2402
2440
  grid.depotRefresh(depot,{updatedRow:result[0], sendedForUpdate:{}}, opts);
2403
2441
  })
@@ -2405,8 +2443,8 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2405
2443
  grid.setRowStyle = function setRowStyle(depot, row, skipUpdateStatus){
2406
2444
  if(!skipUpdateStatus){
2407
2445
  depot.status = 'loaded';
2408
- depot.primaryKeyValues = grid.def.primaryKey.map(function(fieldName){
2409
- return depot.row[fieldName];
2446
+ depot.primaryKeyValues = grid.def.primaryKey.map(function(fieldName){
2447
+ return depot.row[fieldName];
2410
2448
  });
2411
2449
  /*
2412
2450
  depot.lastsPrimaryKeyValues = depot.primaryKeyValues.slice(0);
@@ -2423,7 +2461,7 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2423
2461
  depot.lastsPrimaryKeyValues=JSON.stringify(depot.lastsPrimaryKeyValues);
2424
2462
  }
2425
2463
  depot.tr.setAttribute('pk-values',JSON.stringify(depot.primaryKeyValues));
2426
- grid.def.layout.styleColumns.forEach(function(fieldName){
2464
+ grid.def.layout.styleColumns.forEach(function(fieldName){
2427
2465
  depot.tr.setAttribute('column-'+fieldName,JSON.stringify(depot.row[fieldName]));
2428
2466
  });
2429
2467
  }
@@ -2464,15 +2502,15 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2464
2502
  },3000,fieldName);
2465
2503
  /*jshint loopfunc: false */
2466
2504
  }else if(sameValue(retrievedRow[fieldName], source[fieldName])){
2467
- // ok, si bien lo que viene no coincide con lo pendiente que sigue pendiente,
2468
- // sí coincide con lo que estaba antes de mandar a grabar,
2505
+ // ok, si bien lo que viene no coincide con lo pendiente que sigue pendiente,
2506
+ // sí coincide con lo que estaba antes de mandar a grabar,
2469
2507
  // entonces no hay conflicto el usuario sabe sobre qué está modificando
2470
2508
  //REVISAR SI SE QUIERE REVERTIR
2471
2509
  }else{
2472
- // no coincide con lo pendiente ni con lo anterior,
2510
+ // no coincide con lo pendiente ni con lo anterior,
2473
2511
  // hay un conflicto con el conocimiento del usuario que modificó algo que estaba en otro estado
2474
- changeIoStatus(depot,'write-read-conflict',
2475
- fieldName,
2512
+ changeIoStatus(depot,'write-read-conflict',
2513
+ fieldName,
2476
2514
  myOwn.messages.anotherUserChangedTheRow+'. \n'+
2477
2515
  myOwn.messages.oldValue+': '+source[fieldName]+(
2478
2516
  whenMergeOverride?'':'\n'+myOwn.messages.actualValueInDB+': '+retrievedRow[fieldName]
@@ -2513,7 +2551,7 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2513
2551
  }
2514
2552
  grid.refreshAggregates();
2515
2553
  for(var detailControl in depot.detailControls){
2516
- if(depot.detailControls[detailControl].tr){
2554
+ if(depot.detailControls[detailControl].tr){
2517
2555
  depot.detailControls[detailControl].refreshAllRowsInGrid()
2518
2556
  }
2519
2557
  };
@@ -2532,7 +2570,7 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2532
2570
  tr=grid.dom.table.rows[0];
2533
2571
  depot.colNumber = grid.dom.table.rows[0].childNodes.length;
2534
2572
  }else{
2535
- tr = grid.my.insertRow({section:tbody, iRow:iRow, smooth:depot.status==='new'?{
2573
+ tr = grid.my.insertRow({section:tbody, iRow:iRow, smooth:depot.status==='new'?{
2536
2574
  colCount:grid.def.detailTables.length + grid.def.fields.length
2537
2575
  }:false});
2538
2576
  }
@@ -2542,11 +2580,11 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2542
2580
  return column.fieldDef?column.fieldDef.visible:true
2543
2581
  }).forEach(function(column, iColumn){
2544
2582
  tr.appendChild(column.td(depot, iColumn, tr, saveRow));
2545
- if(grid.vertical){
2583
+ if(grid.vertical){
2546
2584
  tr = tr.nextSibling;
2547
2585
  }
2548
2586
  });
2549
- if(!grid.vertical){
2587
+ if(!grid.vertical){
2550
2588
  tr.addEventListener('focusout', function(event){
2551
2589
  tr.removeAttribute('current_line');
2552
2590
  if(event.target.parentNode != (event.relatedTarget||{}).parentNode ){
@@ -2611,7 +2649,7 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2611
2649
  special: 'filter',
2612
2650
  my: grid.my,
2613
2651
  def: grid.def,
2614
- connector: grid.connector,
2652
+ connector: grid.connector,
2615
2653
  manager: grid,
2616
2654
  rowControls:{},
2617
2655
  row: {},
@@ -2679,7 +2717,7 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2679
2717
  var depotsToDisplay = grid.filterDepots(grid.depots);
2680
2718
  grid.sortDepotsToDisplay = function sortDepotsToDisplay(depotsToDisplay){
2681
2719
  if(grid.view.sortColumns.length>0){
2682
- return depotsToDisplay.sort(function(depot1, depot2){
2720
+ return depotsToDisplay.sort(function(depot1, depot2){
2683
2721
  grid.view.sortColumns.forEach(function(orderColumn){
2684
2722
  if(!grid.def.field[orderColumn.column]){
2685
2723
  my.log(orderColumn.column+' order no está en '+grid.def.name);
@@ -2774,7 +2812,7 @@ myOwn.TableGrid.prototype.displayAsDeleted = function displayAsDeleted(depot, mo
2774
2812
  var grid = this;
2775
2813
  var fast = mode == 'change-ff'
2776
2814
  if (mode == 'unknown' && myOwn.config.config['grid-row-retain-moved-or-deleted']) {
2777
- depot.tr.setAttribute('not-here', 'yes');
2815
+ depot.tr.setAttribute('not-here', 'yes');
2778
2816
  } else {
2779
2817
  var position = depot.tr ? Math.min(grid.depots.length,Math.max(0,depot.tr.sectionRowIndex)) : 0;
2780
2818
  if(grid.depots[position] !== depot){
@@ -2816,7 +2854,7 @@ myOwn.TableGrid.prototype.displayAsDeleted = function displayAsDeleted(depot, mo
2816
2854
 
2817
2855
  myOwn.confirmDelete=function confirmDelete(depot, opts){
2818
2856
  return depot.my.showQuestion(
2819
- depot.my.messages.Delete+' '+(depot.primaryKeyValues === false ? depot.my.messages.newUnsavedRow : JSON.stringify(depot.primaryKeyValues))+' ?',
2857
+ depot.my.messages.Delete+' '+(depot.primaryKeyValues === false ? depot.my.messages.newUnsavedRow : JSON.stringify(depot.primaryKeyValues))+' ?',
2820
2858
  {askForNoRepeat:depot.my.messages.Delete+', '+depot.def.name}
2821
2859
  );
2822
2860
  }
@@ -2982,10 +3020,10 @@ myOwn.getReference = function getReference(referenceName, opts){
2982
3020
  var reference={};
2983
3021
  if(!my.references[referenceName] || opts.fixedFields.length){
2984
3022
  var dummyElement = html.div().create();
2985
- var Connector = my.offline.mode?my.TableConnectorLocal:my.TableConnector;
3023
+ var Connector = my.offline.mode?my.TableConnectorLocal:my.TableConnector;
2986
3024
  var connector=new Connector({
2987
- my:my,
2988
- tableName: referenceName,
3025
+ my:my,
3026
+ tableName: referenceName,
2989
3027
  getElementToDisplayCount:function(){ return dummyElement; },
2990
3028
  activeOnly: true
2991
3029
  }, {fixedFields:opts.fixedFields});
@@ -3024,7 +3062,7 @@ myOwn.autoSetupFunctions.push(function autoSetupMyTables(){
3024
3062
  myOwn.ExpanderJsonReadOnly={
3025
3063
  autoExpand:true,
3026
3064
  whenReadOnly:true,
3027
- whenType: function(typedControl){
3065
+ whenType: function(typedControl){
3028
3066
  var typeInfo = typedControl.controledType.typeInfo;
3029
3067
  return typeInfo.typeName === 'jsonb';
3030
3068
  },
@@ -3055,7 +3093,7 @@ myOwn.ExpanderJsonReadOnly={
3055
3093
  }
3056
3094
  myOwn.ExpanderReferences={
3057
3095
  autoExpand:true,
3058
- whenType: function(typedControl){
3096
+ whenType: function(typedControl){
3059
3097
  var typeInfo = typedControl.controledType.typeInfo;
3060
3098
  return typeInfo.references && !typeInfo.skipReferenceLookup;
3061
3099
  },
@@ -3140,7 +3178,7 @@ myOwn.ExpanderReferences={
3140
3178
  attributes: {'allow-write': true}
3141
3179
  }
3142
3180
  }).then(function(text){
3143
- typedControl.setTypedValue(text||null, true);
3181
+ typedControl.setTypedValue(text||null, true);
3144
3182
  }).catch(function(err){
3145
3183
  if(!DialogPromise){
3146
3184
  return alertPromise(err.message);
@@ -3179,4 +3217,4 @@ myOwn.validators={}
3179
3217
  myOwn.sortMethods={
3180
3218
  'charbychar':bestGlobals.forOrder.Native,
3181
3219
  'default':bestGlobals.forOrder,
3182
- }
3220
+ }