backend-plus 2.7.7 → 2.7.8

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.
Binary file
Binary file
@@ -10,6 +10,7 @@ html(lang=lang)
10
10
  display: none
11
11
  }
12
12
  meta(name='viewport' content="width=device-width, user-scalable=no")
13
+ link(rel='icon', href='img/login-logo-icon.png')
13
14
  body
14
15
  form(id="loginForm", action="login", method="post")
15
16
  table.logintable
@@ -2347,12 +2347,16 @@ myOwn.TableGrid.prototype.prepareGrid = function prepareGrid(){
2347
2347
  grid.actualName = (grid.def.gridAlias || grid.def.name) + (grid.connector.fixedFields.length ? '-' + JSON4all.toUrl(grid.connector.fixedFields.map(function(pair){ return pair.value; })) : '')
2348
2348
  var captionTitle = grid.def.title;
2349
2349
  grid.connector.fixedFields.forEach(function(pair){
2350
- var toCaption = grid.def.field[pair.fieldName].toCaption ?? my.config.config['grid-smart-caption']
2350
+ var fixedFieldDef = grid.def.field[pair.fieldName] ?? (grid.def.functionDef?.parameters ?? []).find(function(parameter){ return parameter.name == pair.fieldName; });
2351
+ if(fixedFieldDef == null){
2352
+ throw new Error('the grid '+grid.def.name+' is filtered by '+pair.fieldName+' that is not a field nor a parameter of the table');
2353
+ }
2354
+ var toCaption = fixedFieldDef.toCaption ?? my.config.config['grid-smart-caption']
2351
2355
  if(toCaption && pair.value != null){
2352
- var typeName = grid.def.field[pair.fieldName].typeName;
2356
+ var typeName = fixedFieldDef.typeName;
2353
2357
  captionTitle += ' '
2354
2358
  if(toCaption == 'labeled' || toCaption != 'alone' && (typeName == 'boolean' || typeName == 'integer' || typeName == 'bigint' || typeName == 'decimal')){
2355
- captionTitle += grid.def.field[pair.fieldName].title + ':'
2359
+ captionTitle += (fixedFieldDef.title ?? fixedFieldDef.name) + ':'
2356
2360
  }
2357
2361
  if(typeName == 'date'){
2358
2362
  var date = bestGlobals.date(new Date(pair.value))
@@ -2613,8 +2617,8 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2613
2617
  if(!Object.keys(depot.rowPendingForUpdate).length){
2614
2618
  return Promise.resolve();
2615
2619
  }
2620
+ var specialMandatories=grid.def.specialValidator?myOwn.validators[grid.def.specialValidator].getMandatoryMap(depot.row):{};
2616
2621
  if(depot.status==='new'){
2617
- var specialMandatories=grid.def.specialValidator?myOwn.validators[grid.def.specialValidator].getMandatoryMap(depot.row):{};
2618
2622
  var mandatoryOmitted=function(fieldDef){
2619
2623
  return (specialMandatories[fieldDef.name] || fieldDef.nullable!==true && fieldDef.isPk || fieldDef.nullable===false)
2620
2624
  && depot.row[fieldDef.name]==null
@@ -2630,6 +2634,17 @@ myOwn.TableGrid.prototype.displayGrid = function displayGrid(){
2630
2634
  }
2631
2635
  return Promise.resolve(); // no grabo todavía
2632
2636
  };
2637
+ }else{
2638
+ // en una modificación solo se controlan los obligatorios especiales (campos que son obligatorios según lo cargado en otros)
2639
+ var specialOmitted=grid.def.fields.filter(function(fieldDef){
2640
+ return specialMandatories[fieldDef.name] && depot.row[fieldDef.name]==null;
2641
+ });
2642
+ if(specialOmitted.length){
2643
+ if(depot.tr){
2644
+ depot.tr.title = myOwn.messages.mandatoryFieldOmited + specialOmitted.map(f=>f.name).join(', ');
2645
+ }
2646
+ return Promise.resolve(); // no grabo todavía
2647
+ }
2633
2648
  }
2634
2649
  var timeStamp = my.setTimeStamp(depot.row);
2635
2650
  return grid.connector.saveRecord(depot, opts).then(function(result){
@@ -424,6 +424,7 @@ export interface AppConfigServer
424
424
  useCors: boolean //habilita Cross-Origin Resource Sharing
425
425
  allowedHosts:string[] //determina API allowed hosts (necesita habilitar useCors)
426
426
  policy?:string
427
+ environment?:string // 'production' or other (to choose defaults, for example the background)
427
428
  }
428
429
  export interface AppConfigDb
429
430
  {
@@ -503,6 +504,7 @@ export interface AppConfigClientSetup // front-end config
503
504
  version?:string
504
505
  menu?:boolean
505
506
  "background-img"?:string
507
+ environment?:string // copied from server.environment
506
508
  devel?:boolean
507
509
  deviceWidthForMobile?:string
508
510
  "initial-scale"?:string
@@ -823,6 +823,11 @@ AppBackend.prototype.start = function start(opts){
823
823
  be.config = config;
824
824
  be.clientSetup = {config: be.config["client-setup"]};
825
825
  be.clientSetup.config.prefix = be.clientSetup.config.prefix || be.config.server["base-url"].substr(1)+':';
826
+ if(be.config.server.environment == 'production' && be.config.devel){
827
+ console.warn('WARNING: devel config in a production environment (server.environment: production). For the background, production prevails');
828
+ }
829
+ // the client uses the environment to choose the default background (see my-ajax.js)
830
+ be.clientSetup.config.environment = be.config.server.environment;
826
831
  var downloadsConfig = be.config["client-setup"].downloads;
827
832
  if(downloadsConfig != null){
828
833
  if(downloadsConfig.method != null && !['legacy','SaveFilePicker'].includes(downloadsConfig.method)){
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "backend-plus",
3
3
  "description": "Backend for the anti Pareto rule",
4
- "version": "2.7.7",
4
+ "version": "2.7.8",
5
5
  "author": "Codenautas <codenautas@googlegroups.com>",
6
6
  "license": "MIT",
7
7
  "repository": "codenautas/backend-plus",
@@ -47,7 +47,7 @@
47
47
  "cors": "^2.8.6",
48
48
  "dialog-promise": "^0.10.7",
49
49
  "ensure-login": "^0.1.6",
50
- "express": "^5.2.1",
50
+ "express": "^5.3.0",
51
51
  "express-useragent": "^2.2.3",
52
52
  "fflate": "^0.8.3",
53
53
  "fs-extra": "^11.4.1",
@@ -61,7 +61,7 @@
61
61
  "mini-tools": "^1.13.10",
62
62
  "moment": "^2.31.0",
63
63
  "multiparty": "^4.3.1",
64
- "nodemailer": "^10.0.15",
64
+ "nodemailer": "^10.0.16",
65
65
  "numeral": "^2.0.6",
66
66
  "pg-promise-strict": "^1.5.0",
67
67
  "pg-triggers": "0.4.6",
@@ -87,7 +87,7 @@
87
87
  "@types/js-yaml": "^4.0.9",
88
88
  "@types/mocha": "^10.0.10",
89
89
  "@types/multiparty": "^4.2.1",
90
- "@types/node": "^26.6.4",
90
+ "@types/node": "^26.6.5",
91
91
  "@types/nodemailer": "^8.0.2",
92
92
  "@types/numeral": "~2.0.5",
93
93
  "@types/session-file-store": "^1.2.6",
@@ -99,14 +99,14 @@
99
99
  "expect.js": "^0.3.1",
100
100
  "kill-9": "^0.4.3",
101
101
  "mocha": "^12.0.3",
102
- "qa-control": "0.11.3",
102
+ "qa-control": "0.12.1",
103
103
  "regexplicit": "^0.1.3",
104
104
  "self-explain": "^0.11.0",
105
105
  "sinon": "^22.1.0",
106
106
  "supertest": "^7.3.1",
107
- "types.d.ts": "^0.6.22",
107
+ "types.d.ts": "^0.7.1",
108
108
  "typescript": "^5.9.3",
109
- "why-is-node-running": "^3.2.2"
109
+ "why-is-node-running": "^3.2.3"
110
110
  },
111
111
  "engines": {
112
112
  "node": ">= 22"
@@ -111,6 +111,8 @@ myAjax.readProcedureDefinitions=function readProcedureDefinitions(){
111
111
  var backgroundUrl
112
112
  if(my.config.config && my.config.config['background-img']){
113
113
  backgroundUrl = 'url("'+my.path.img+my.config.config['background-img']+'")'
114
+ }else if(my.config.config && my.config.config.environment == 'production'){
115
+ backgroundUrl = '';
114
116
  }else{
115
117
  if(/(^|[-_0-9/])(test|pru|prueba)($|[-_0-9/])/.test(location.pathname)){
116
118
  backgroundUrl = 'url("img/background-test.png")';
@@ -119,10 +121,13 @@ myAjax.readProcedureDefinitions=function readProcedureDefinitions(){
119
121
  }else if(/(^|[-_0-9/])(desa|devel)($|[-_0-9/])/.test(location.pathname) || my.config.config && my.config.config['devel']){
120
122
  backgroundUrl = 'url("img/background-devel.png")';
121
123
  }else{
122
- backgroundUrl = '';
124
+ // unknown environment: better to see a missing image than no background (declare server.environment)
125
+ backgroundUrl = 'url("img/background-unknown.png")';
123
126
  }
124
127
  }
125
128
  document.body.style.backgroundImage=backgroundUrl;
129
+ // for the apps that need the background in other elements
130
+ my.backgroundUrl=backgroundUrl;
126
131
  }
127
132
  }).then(function(){
128
133
  my.config.procedure=my.config.procedure||{};