tryton-sao 7.2.18 → 7.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG CHANGED
@@ -1,4 +1,14 @@
1
1
 
2
+ Version 7.2.20 - 2025-05-02
3
+ ---------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
7
+ Version 7.2.19 - 2025-04-26
8
+ ---------------------------
9
+ * Bug fixes (see mercurial logs for details)
10
+
11
+
2
12
  Version 7.2.18 - 2025-04-02
3
13
  ---------------------------
4
14
  * Bug fixes (see mercurial logs for details)
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.2.18',
6
+ __version__: '7.2.20',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -4124,7 +4124,7 @@ var Sao = {
4124
4124
  });
4125
4125
  }
4126
4126
  };
4127
- this._selection_prm.done(_update_selection);
4127
+ this._selection_prm.always(_update_selection);
4128
4128
  };
4129
4129
  Sao.common.selection_mixin.filter_selection = function(
4130
4130
  domain, record, field) {
@@ -5304,6 +5304,15 @@ var Sao = {
5304
5304
  if (!context) {
5305
5305
  context = {};
5306
5306
  }
5307
+ function atof(string) {
5308
+ if (!string) {
5309
+ throw("empty string");
5310
+ }
5311
+ let { format } = new Intl.NumberFormat(
5312
+ Sao.i18n.BC47(Sao.i18n.getlang()));
5313
+ let [, decimalSign] = /^0(.)1$/.exec(format(0.1));
5314
+ return Number(string.replace(decimalSign, '.'));
5315
+ }
5307
5316
  var convert_selection = function() {
5308
5317
  if (typeof value == 'string') {
5309
5318
  for (var i = 0; i < field.selection.length; i++) {
@@ -5335,8 +5344,12 @@ var Sao = {
5335
5344
  },
5336
5345
  'float': function() {
5337
5346
  var factor = Number(field.factor || 1);
5338
- var result = Number(value);
5339
- if (isNaN(result) || value === '' || value === null) {
5347
+ try {
5348
+ var result = atof(value);
5349
+ } catch (e) {
5350
+ return null;
5351
+ }
5352
+ if (isNaN(result)) {
5340
5353
  return null;
5341
5354
  } else {
5342
5355
  return result / factor;
@@ -5344,18 +5357,25 @@ var Sao = {
5344
5357
  },
5345
5358
  'integer': function() {
5346
5359
  var factor = Number(field.factor || 1, 10);
5347
- var result = parseInt(value, 10);
5360
+ try {
5361
+ var result = atof(value);
5362
+ } catch (e) {
5363
+ return null;
5364
+ }
5348
5365
  if (isNaN(result)) {
5349
5366
  return null;
5350
5367
  } else {
5351
- return result / factor;
5368
+ return parseInt(result / factor, 10);
5352
5369
  }
5353
5370
  },
5354
5371
  'numeric': function() {
5355
5372
  var factor = Number(field.factor || 1);
5356
- var result = Number(value);
5357
- if (isNaN(result.valueOf()) ||
5358
- value === '' || value === null) {
5373
+ try {
5374
+ var result = atof(value);
5375
+ } catch (e) {
5376
+ return null;
5377
+ }
5378
+ if (isNaN(result)) {
5359
5379
  return null;
5360
5380
  } else {
5361
5381
  return new Sao.Decimal(result / factor);
@@ -5410,8 +5430,7 @@ var Sao = {
5410
5430
  return '';
5411
5431
  }
5412
5432
  var digit = 0;
5413
- var factor = Number(field.factor || 1);
5414
- var string = String(value * factor);
5433
+ var string = String(value);
5415
5434
  if (string.contains('e')) {
5416
5435
  var exp = string.split('e')[1];
5417
5436
  string = string.split('e')[0];
@@ -5420,7 +5439,14 @@ var Sao = {
5420
5439
  if (string.contains('.')) {
5421
5440
  digit += string.replace(/0+$/, '').split('.')[1].length;
5422
5441
  }
5423
- return (value * factor).toFixed(digit);
5442
+ var factor = Number(field.factor || 1);
5443
+ digit -= Math.round(Math.log10(factor));
5444
+ return (value * factor).toLocaleString(
5445
+ Sao.i18n.BC47(Sao.i18n.getlang()), {
5446
+ useGrouping: true,
5447
+ minimumFractionDigits: digit,
5448
+ maximumFractionDigits: digit,
5449
+ });
5424
5450
  };
5425
5451
  var format_selection = function() {
5426
5452
  if (field.selection instanceof Array) {
@@ -7659,7 +7685,7 @@ var Sao = {
7659
7685
  'use strict';
7660
7686
 
7661
7687
  function get_x2m_sub_fields(f_attrs, prefix) {
7662
- if (f_attrs.visible && f_attrs.views) {
7688
+ if (f_attrs.visible && !jQuery.isEmptyObject(f_attrs.views)) {
7663
7689
  // There's only one key but we don't know its value
7664
7690
  const [[, view],] = Object.entries(f_attrs.views);
7665
7691
 
@@ -8238,6 +8264,7 @@ var Sao = {
8238
8264
  this.autocompletion = {};
8239
8265
  this.exception = false;
8240
8266
  this.destroyed = false;
8267
+ this._save_prm = jQuery.when();
8241
8268
  },
8242
8269
  get modified() {
8243
8270
  if (!jQuery.isEmptyObject(this.modified_fields)) {
@@ -8251,33 +8278,28 @@ var Sao = {
8251
8278
  },
8252
8279
  save: function(force_reload=false) {
8253
8280
  var context = this.get_context();
8281
+ if (this._save_prm.state() == 'pending') {
8282
+ return this._save_prm.then(() => this.save(force_reload));
8283
+ }
8254
8284
  var prm = jQuery.when();
8255
8285
  if ((this.id < 0) || this.modified) {
8256
8286
  var values = this.get();
8257
- try {
8258
- // synchronous call to avoid multiple creation or save
8259
- if (this.id < 0) {
8260
- this.id = this.model.execute(
8261
- 'create', [[values]], context, false)[0];
8262
-
8263
- } else {
8264
- if (!jQuery.isEmptyObject(values)) {
8265
- context._timestamp = this.get_timestamp();
8266
- this.model.execute(
8267
- 'write', [[this.id], values], context, false);
8268
- }
8269
- }
8270
- } catch (e) {
8271
- if (e.promise) {
8272
- return e.then(() => this.save(force_reload));
8273
- } else {
8274
- return jQuery.Deferred().reject();
8287
+ if (this.id < 0) {
8288
+ prm = this.model.execute('create', [[values]], context)
8289
+ .then(ids => this.id = ids[0]);
8290
+ } else {
8291
+ if (!jQuery.isEmptyObject(values)) {
8292
+ context._timestamp = this.get_timestamp();
8293
+ prm = this.model.execute(
8294
+ 'write', [[this.id], values], context);
8275
8295
  }
8276
8296
  }
8277
- this.cancel();
8278
- if (force_reload) {
8279
- return this.reload();
8280
- }
8297
+ prm = prm.then(() => {
8298
+ this.cancel();
8299
+ if (force_reload) {
8300
+ return this.reload();
8301
+ }
8302
+ });
8281
8303
  if (this.group) {
8282
8304
  prm = prm.then(() => this.group.written(this.id));
8283
8305
  }
@@ -8286,6 +8308,7 @@ var Sao = {
8286
8308
  delete this.group.parent.modified_fields[this.group.child_name];
8287
8309
  prm = prm.then(() => this.group.parent.save(force_reload));
8288
8310
  }
8311
+ this._save_prm = prm;
8289
8312
  return prm;
8290
8313
  },
8291
8314
  reload: function(fields, async=true) {
@@ -10179,6 +10202,7 @@ var Sao = {
10179
10202
  }
10180
10203
 
10181
10204
  if (value && (value.add || value.update)) {
10205
+ let vals_to_set = {};
10182
10206
  // First set already added fields to prevent triggering a
10183
10207
  // second on_change call
10184
10208
  if (value.update) {
@@ -10188,9 +10212,9 @@ var Sao = {
10188
10212
  }
10189
10213
  const record2 = group.get(vals.id);
10190
10214
  if (record2) {
10191
- var vals_to_set = {};
10192
10215
  for (var key in vals) {
10193
- if (!(key in new_field_names)) {
10216
+ if (!Object.prototype.hasOwnProperty.call(
10217
+ new_field_names, key)) {
10194
10218
  vals_to_set[key] = vals[key];
10195
10219
  }
10196
10220
  }
@@ -10224,7 +10248,14 @@ var Sao = {
10224
10248
  }
10225
10249
  const record2 = group.get(vals.id);
10226
10250
  if (record2) {
10227
- record2.set_on_change(vals);
10251
+ let to_update = Object.fromEntries(
10252
+ Object.entries(vals).filter(
10253
+ ([k, v]) => {
10254
+ !Object.prototype.hasOwnProperty.call(
10255
+ vals_to_set, k)
10256
+ }
10257
+ ));
10258
+ record2.set_on_change(to_update);
10228
10259
  }
10229
10260
  }
10230
10261
  }
@@ -12161,6 +12192,7 @@ var Sao = {
12161
12192
  }
12162
12193
  }
12163
12194
  const view_type = this.screen.current_view.view_type;
12195
+ var next_view_type = this.screen.next_view_type;
12164
12196
  const has_views = this.screen.number_of_views > 1;
12165
12197
  var buttons = ['print', 'relate', 'email', 'attach'];
12166
12198
  for (const button_id of buttons) {
@@ -12181,7 +12213,9 @@ var Sao = {
12181
12213
  set_sensitive(button_id, position && can_be_sensitive);
12182
12214
  }
12183
12215
  set_sensitive(
12184
- 'switch_', (position || (view_type == 'form')) && has_views);
12216
+ 'switch_',
12217
+ (position || (view_type == 'form') || (next_view_type != 'form')) &&
12218
+ has_views);
12185
12219
  set_sensitive('delete_', this.screen.deletable);
12186
12220
  set_sensitive('previous', this.screen.has_previous());
12187
12221
  set_sensitive('next', this.screen.has_next());
@@ -13007,7 +13041,7 @@ var Sao = {
13007
13041
  Sao.ScreenContainer.BetweenDates._super.init.call(this, id);
13008
13042
  this.from.change(this._from_changed.bind(this));
13009
13043
  },
13010
- _get_value: function(entry, value) {
13044
+ _get_value: function(entry) {
13011
13045
  return entry.find('input[type=text]').val();
13012
13046
  },
13013
13047
  _set_value: function(entry, value) {
@@ -13120,11 +13154,17 @@ var Sao = {
13120
13154
  'class': 'form-control input-sm',
13121
13155
  'type': 'number',
13122
13156
  'step': 'any',
13157
+ 'lang': Sao.i18n.getlang(),
13123
13158
  }).appendTo(el);
13124
13159
  return entry;
13125
13160
  },
13126
- _get_value: function(entry, value) {
13127
- return entry.val();
13161
+ _get_value: function(entry) {
13162
+ let value = entry.val();
13163
+ if (value) {
13164
+ value = Number(value).toLocaleString(
13165
+ Sao.i18n.BC47(Sao.i18n.getlang()))
13166
+ }
13167
+ return value;
13128
13168
  },
13129
13169
  _set_value: function(entry, value) {
13130
13170
  return entry.val(value);
@@ -13309,6 +13349,15 @@ var Sao = {
13309
13349
  get view_index() {
13310
13350
  return this.views.indexOf(this.current_view);
13311
13351
  },
13352
+ get next_view_type() {
13353
+ var views = this.views.concat(this.view_to_load)
13354
+ var next_view_index = (this.view_index + 1) % views.length;
13355
+ var next_view = views[next_view_index];
13356
+ if (typeof next_view != 'string') {
13357
+ next_view = next_view.view_type;
13358
+ }
13359
+ return next_view;
13360
+ },
13312
13361
  switch_view: function(
13313
13362
  view_type=null, view_id=null, creatable=null, display=true) {
13314
13363
  if (view_id !== null) {
@@ -13669,9 +13718,6 @@ var Sao = {
13669
13718
  return this.__current_record;
13670
13719
  },
13671
13720
  set current_record(record) {
13672
- if ((this.__current_record === record) && record) {
13673
- return;
13674
- }
13675
13721
  this.__current_record = record;
13676
13722
  var pos = null;
13677
13723
  var record_id = null;
@@ -13979,7 +14025,6 @@ var Sao = {
13979
14025
  },
13980
14026
  save_current: function() {
13981
14027
  var current_record = this.current_record;
13982
- let new_record = current_record.id < 0;
13983
14028
  if (!current_record) {
13984
14029
  if (this.current_view &&
13985
14030
  (this.current_view.view_type == 'tree') &&
@@ -13990,6 +14035,7 @@ var Sao = {
13990
14035
  return jQuery.when();
13991
14036
  }
13992
14037
  }
14038
+ let new_record = current_record.id < 0;
13993
14039
  if (this.current_view) {
13994
14040
  this.current_view.set_value();
13995
14041
  var fields = this.current_view.get_fields();
@@ -14668,7 +14714,8 @@ var Sao = {
14668
14714
  return view.display(selected_nodes);
14669
14715
  } else {
14670
14716
  var record;
14671
- if (!jQuery.isEmptyObject(selected_nodes)) {
14717
+ if (!jQuery.isEmptyObject(selected_nodes) &&
14718
+ !this.current_record) {
14672
14719
  for (const id of selected_nodes[0]) {
14673
14720
  const new_record = this.group.get(id);
14674
14721
  if (!new_record) {
@@ -25073,9 +25120,10 @@ function eval_pyson(value){
25073
25120
  });
25074
25121
  },
25075
25122
  clear: function() {
25076
- var kinds = this.el.children().each(
25077
- (i, el) => jQuery(el).data('kind'));
25078
- new Set(kinds).forEach(kind => {
25123
+ let kinds = new Set();
25124
+ this.el.children().each(
25125
+ (i, el) => kinds.add(jQuery(el).data('kind')));
25126
+ kinds.forEach(kind => {
25079
25127
  this.refresh(kind);
25080
25128
  });
25081
25129
  this.__messages.clear();
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "tryton-sao",
3
3
  "title": "sao",
4
4
  "description": "Tryton webclient",
5
- "version": "7.2.18",
5
+ "version": "7.2.20",
6
6
  "homepage": "http://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/common.js CHANGED
@@ -828,7 +828,7 @@
828
828
  });
829
829
  }
830
830
  };
831
- this._selection_prm.done(_update_selection);
831
+ this._selection_prm.always(_update_selection);
832
832
  };
833
833
  Sao.common.selection_mixin.filter_selection = function(
834
834
  domain, record, field) {
@@ -2008,6 +2008,15 @@
2008
2008
  if (!context) {
2009
2009
  context = {};
2010
2010
  }
2011
+ function atof(string) {
2012
+ if (!string) {
2013
+ throw("empty string");
2014
+ }
2015
+ let { format } = new Intl.NumberFormat(
2016
+ Sao.i18n.BC47(Sao.i18n.getlang()));
2017
+ let [, decimalSign] = /^0(.)1$/.exec(format(0.1));
2018
+ return Number(string.replace(decimalSign, '.'));
2019
+ }
2011
2020
  var convert_selection = function() {
2012
2021
  if (typeof value == 'string') {
2013
2022
  for (var i = 0; i < field.selection.length; i++) {
@@ -2039,8 +2048,12 @@
2039
2048
  },
2040
2049
  'float': function() {
2041
2050
  var factor = Number(field.factor || 1);
2042
- var result = Number(value);
2043
- if (isNaN(result) || value === '' || value === null) {
2051
+ try {
2052
+ var result = atof(value);
2053
+ } catch (e) {
2054
+ return null;
2055
+ }
2056
+ if (isNaN(result)) {
2044
2057
  return null;
2045
2058
  } else {
2046
2059
  return result / factor;
@@ -2048,18 +2061,25 @@
2048
2061
  },
2049
2062
  'integer': function() {
2050
2063
  var factor = Number(field.factor || 1, 10);
2051
- var result = parseInt(value, 10);
2064
+ try {
2065
+ var result = atof(value);
2066
+ } catch (e) {
2067
+ return null;
2068
+ }
2052
2069
  if (isNaN(result)) {
2053
2070
  return null;
2054
2071
  } else {
2055
- return result / factor;
2072
+ return parseInt(result / factor, 10);
2056
2073
  }
2057
2074
  },
2058
2075
  'numeric': function() {
2059
2076
  var factor = Number(field.factor || 1);
2060
- var result = Number(value);
2061
- if (isNaN(result.valueOf()) ||
2062
- value === '' || value === null) {
2077
+ try {
2078
+ var result = atof(value);
2079
+ } catch (e) {
2080
+ return null;
2081
+ }
2082
+ if (isNaN(result)) {
2063
2083
  return null;
2064
2084
  } else {
2065
2085
  return new Sao.Decimal(result / factor);
@@ -2114,8 +2134,7 @@
2114
2134
  return '';
2115
2135
  }
2116
2136
  var digit = 0;
2117
- var factor = Number(field.factor || 1);
2118
- var string = String(value * factor);
2137
+ var string = String(value);
2119
2138
  if (string.contains('e')) {
2120
2139
  var exp = string.split('e')[1];
2121
2140
  string = string.split('e')[0];
@@ -2124,7 +2143,14 @@
2124
2143
  if (string.contains('.')) {
2125
2144
  digit += string.replace(/0+$/, '').split('.')[1].length;
2126
2145
  }
2127
- return (value * factor).toFixed(digit);
2146
+ var factor = Number(field.factor || 1);
2147
+ digit -= Math.round(Math.log10(factor));
2148
+ return (value * factor).toLocaleString(
2149
+ Sao.i18n.BC47(Sao.i18n.getlang()), {
2150
+ useGrouping: true,
2151
+ minimumFractionDigits: digit,
2152
+ maximumFractionDigits: digit,
2153
+ });
2128
2154
  };
2129
2155
  var format_selection = function() {
2130
2156
  if (field.selection instanceof Array) {
package/src/model.js CHANGED
@@ -4,7 +4,7 @@
4
4
  'use strict';
5
5
 
6
6
  function get_x2m_sub_fields(f_attrs, prefix) {
7
- if (f_attrs.visible && f_attrs.views) {
7
+ if (f_attrs.visible && !jQuery.isEmptyObject(f_attrs.views)) {
8
8
  // There's only one key but we don't know its value
9
9
  const [[, view],] = Object.entries(f_attrs.views);
10
10
 
@@ -583,6 +583,7 @@
583
583
  this.autocompletion = {};
584
584
  this.exception = false;
585
585
  this.destroyed = false;
586
+ this._save_prm = jQuery.when();
586
587
  },
587
588
  get modified() {
588
589
  if (!jQuery.isEmptyObject(this.modified_fields)) {
@@ -596,33 +597,28 @@
596
597
  },
597
598
  save: function(force_reload=false) {
598
599
  var context = this.get_context();
600
+ if (this._save_prm.state() == 'pending') {
601
+ return this._save_prm.then(() => this.save(force_reload));
602
+ }
599
603
  var prm = jQuery.when();
600
604
  if ((this.id < 0) || this.modified) {
601
605
  var values = this.get();
602
- try {
603
- // synchronous call to avoid multiple creation or save
604
- if (this.id < 0) {
605
- this.id = this.model.execute(
606
- 'create', [[values]], context, false)[0];
607
-
608
- } else {
609
- if (!jQuery.isEmptyObject(values)) {
610
- context._timestamp = this.get_timestamp();
611
- this.model.execute(
612
- 'write', [[this.id], values], context, false);
613
- }
614
- }
615
- } catch (e) {
616
- if (e.promise) {
617
- return e.then(() => this.save(force_reload));
618
- } else {
619
- return jQuery.Deferred().reject();
606
+ if (this.id < 0) {
607
+ prm = this.model.execute('create', [[values]], context)
608
+ .then(ids => this.id = ids[0]);
609
+ } else {
610
+ if (!jQuery.isEmptyObject(values)) {
611
+ context._timestamp = this.get_timestamp();
612
+ prm = this.model.execute(
613
+ 'write', [[this.id], values], context);
620
614
  }
621
615
  }
622
- this.cancel();
623
- if (force_reload) {
624
- return this.reload();
625
- }
616
+ prm = prm.then(() => {
617
+ this.cancel();
618
+ if (force_reload) {
619
+ return this.reload();
620
+ }
621
+ });
626
622
  if (this.group) {
627
623
  prm = prm.then(() => this.group.written(this.id));
628
624
  }
@@ -631,6 +627,7 @@
631
627
  delete this.group.parent.modified_fields[this.group.child_name];
632
628
  prm = prm.then(() => this.group.parent.save(force_reload));
633
629
  }
630
+ this._save_prm = prm;
634
631
  return prm;
635
632
  },
636
633
  reload: function(fields, async=true) {
@@ -2524,6 +2521,7 @@
2524
2521
  }
2525
2522
 
2526
2523
  if (value && (value.add || value.update)) {
2524
+ let vals_to_set = {};
2527
2525
  // First set already added fields to prevent triggering a
2528
2526
  // second on_change call
2529
2527
  if (value.update) {
@@ -2533,9 +2531,9 @@
2533
2531
  }
2534
2532
  const record2 = group.get(vals.id);
2535
2533
  if (record2) {
2536
- var vals_to_set = {};
2537
2534
  for (var key in vals) {
2538
- if (!(key in new_field_names)) {
2535
+ if (!Object.prototype.hasOwnProperty.call(
2536
+ new_field_names, key)) {
2539
2537
  vals_to_set[key] = vals[key];
2540
2538
  }
2541
2539
  }
@@ -2569,7 +2567,14 @@
2569
2567
  }
2570
2568
  const record2 = group.get(vals.id);
2571
2569
  if (record2) {
2572
- record2.set_on_change(vals);
2570
+ let to_update = Object.fromEntries(
2571
+ Object.entries(vals).filter(
2572
+ ([k, v]) => {
2573
+ !Object.prototype.hasOwnProperty.call(
2574
+ vals_to_set, k)
2575
+ }
2576
+ ));
2577
+ record2.set_on_change(to_update);
2573
2578
  }
2574
2579
  }
2575
2580
  }
package/src/sao.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.2.18',
6
+ __version__: '7.2.20',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
package/src/screen.js CHANGED
@@ -625,7 +625,7 @@
625
625
  Sao.ScreenContainer.BetweenDates._super.init.call(this, id);
626
626
  this.from.change(this._from_changed.bind(this));
627
627
  },
628
- _get_value: function(entry, value) {
628
+ _get_value: function(entry) {
629
629
  return entry.find('input[type=text]').val();
630
630
  },
631
631
  _set_value: function(entry, value) {
@@ -738,11 +738,17 @@
738
738
  'class': 'form-control input-sm',
739
739
  'type': 'number',
740
740
  'step': 'any',
741
+ 'lang': Sao.i18n.getlang(),
741
742
  }).appendTo(el);
742
743
  return entry;
743
744
  },
744
- _get_value: function(entry, value) {
745
- return entry.val();
745
+ _get_value: function(entry) {
746
+ let value = entry.val();
747
+ if (value) {
748
+ value = Number(value).toLocaleString(
749
+ Sao.i18n.BC47(Sao.i18n.getlang()))
750
+ }
751
+ return value;
746
752
  },
747
753
  _set_value: function(entry, value) {
748
754
  return entry.val(value);
@@ -927,6 +933,15 @@
927
933
  get view_index() {
928
934
  return this.views.indexOf(this.current_view);
929
935
  },
936
+ get next_view_type() {
937
+ var views = this.views.concat(this.view_to_load)
938
+ var next_view_index = (this.view_index + 1) % views.length;
939
+ var next_view = views[next_view_index];
940
+ if (typeof next_view != 'string') {
941
+ next_view = next_view.view_type;
942
+ }
943
+ return next_view;
944
+ },
930
945
  switch_view: function(
931
946
  view_type=null, view_id=null, creatable=null, display=true) {
932
947
  if (view_id !== null) {
@@ -1287,9 +1302,6 @@
1287
1302
  return this.__current_record;
1288
1303
  },
1289
1304
  set current_record(record) {
1290
- if ((this.__current_record === record) && record) {
1291
- return;
1292
- }
1293
1305
  this.__current_record = record;
1294
1306
  var pos = null;
1295
1307
  var record_id = null;
@@ -1597,7 +1609,6 @@
1597
1609
  },
1598
1610
  save_current: function() {
1599
1611
  var current_record = this.current_record;
1600
- let new_record = current_record.id < 0;
1601
1612
  if (!current_record) {
1602
1613
  if (this.current_view &&
1603
1614
  (this.current_view.view_type == 'tree') &&
@@ -1608,6 +1619,7 @@
1608
1619
  return jQuery.when();
1609
1620
  }
1610
1621
  }
1622
+ let new_record = current_record.id < 0;
1611
1623
  if (this.current_view) {
1612
1624
  this.current_view.set_value();
1613
1625
  var fields = this.current_view.get_fields();
@@ -2286,7 +2298,8 @@
2286
2298
  return view.display(selected_nodes);
2287
2299
  } else {
2288
2300
  var record;
2289
- if (!jQuery.isEmptyObject(selected_nodes)) {
2301
+ if (!jQuery.isEmptyObject(selected_nodes) &&
2302
+ !this.current_record) {
2290
2303
  for (const id of selected_nodes[0]) {
2291
2304
  const new_record = this.group.get(id);
2292
2305
  if (!new_record) {
package/src/tab.js CHANGED
@@ -1496,6 +1496,7 @@
1496
1496
  }
1497
1497
  }
1498
1498
  const view_type = this.screen.current_view.view_type;
1499
+ var next_view_type = this.screen.next_view_type;
1499
1500
  const has_views = this.screen.number_of_views > 1;
1500
1501
  var buttons = ['print', 'relate', 'email', 'attach'];
1501
1502
  for (const button_id of buttons) {
@@ -1516,7 +1517,9 @@
1516
1517
  set_sensitive(button_id, position && can_be_sensitive);
1517
1518
  }
1518
1519
  set_sensitive(
1519
- 'switch_', (position || (view_type == 'form')) && has_views);
1520
+ 'switch_',
1521
+ (position || (view_type == 'form') || (next_view_type != 'form')) &&
1522
+ has_views);
1520
1523
  set_sensitive('delete_', this.screen.deletable);
1521
1524
  set_sensitive('previous', this.screen.has_previous());
1522
1525
  set_sensitive('next', this.screen.has_next());
package/src/window.js CHANGED
@@ -101,9 +101,10 @@
101
101
  });
102
102
  },
103
103
  clear: function() {
104
- var kinds = this.el.children().each(
105
- (i, el) => jQuery(el).data('kind'));
106
- new Set(kinds).forEach(kind => {
104
+ let kinds = new Set();
105
+ this.el.children().each(
106
+ (i, el) => kinds.add(jQuery(el).data('kind')));
107
+ kinds.forEach(kind => {
107
108
  this.refresh(kind);
108
109
  });
109
110
  this.__messages.clear();