tryton-sao 7.4.10 → 7.4.12

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.4.12 - 2025-06-04
3
+ ---------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
7
+ Version 7.4.11 - 2025-05-15
8
+ ---------------------------
9
+ * Bug fixes (see mercurial logs for details)
10
+
11
+
2
12
  Version 7.4.10 - 2025-05-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.4.10',
6
+ __version__: '7.4.12',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -675,6 +675,7 @@ var Sao = {
675
675
  "Incompatible version of the server."),
676
676
  Sao.i18n.gettext("Version mismatch"));
677
677
  } else {
678
+ let url = window.location.hash.substr(1);
678
679
  Sao.Session.get_credentials()
679
680
  .then(function(session) {
680
681
  Sao.Session.current_session = session;
@@ -684,7 +685,7 @@ var Sao = {
684
685
  .then(function(preferences) {
685
686
  Sao.menu(preferences);
686
687
  Sao.user_menu(preferences);
687
- Sao.open_url();
688
+ Sao.open_url(url);
688
689
  Sao.Bus.listen();
689
690
  });
690
691
  }
@@ -7700,16 +7701,19 @@ var Sao = {
7700
7701
  return null;
7701
7702
  }
7702
7703
  var type = '';
7703
- try {
7704
- var xml = data;
7705
- if (xml instanceof Uint8Array) {
7706
- xml = new TextDecoder().decode(data);
7707
- }
7708
- if (jQuery.parseXML(xml)) {
7704
+ var xml = data;
7705
+ if (xml instanceof Uint8Array) {
7706
+ xml = new TextDecoder().decode(data);
7707
+ }
7708
+ // simple test to avoid logging of parsing error
7709
+ if (/^\s*<[\s\S]+>\s*$/.test(xml.trim())) {
7710
+ let parser = new DOMParser();
7711
+ let doc = parser.parseFromString(xml, 'image/svg+xml');
7712
+ if (!doc.querySelector('parsererror')
7713
+ && (doc.documentElement.tagName.toLowerCase() === 'svg' ||
7714
+ doc.getElementsByTagName('svg').length > 0)) {
7709
7715
  type = 'image/svg+xml';
7710
7716
  }
7711
- } catch (e) {
7712
- // continue
7713
7717
  }
7714
7718
  var blob = new Blob([data], {type: type});
7715
7719
  return window.URL.createObjectURL(blob);
@@ -9478,7 +9482,6 @@ var Sao = {
9478
9482
  // XXX to remove once server domains are fixed
9479
9483
  value = null;
9480
9484
  }
9481
- var setdefault = true;
9482
9485
  var original_domain;
9483
9486
  if (!jQuery.isEmptyObject(record.group.domain)) {
9484
9487
  original_domain = inversion.merge(record.group.domain);
@@ -9486,20 +9489,12 @@ var Sao = {
9486
9489
  original_domain = inversion.merge(domain);
9487
9490
  }
9488
9491
  var domain_readonly = original_domain[0] == 'AND';
9492
+ let setdefault;
9489
9493
  if (leftpart.contains('.')) {
9490
- var recordpart = leftpart.split('.', 1)[0];
9491
- var localpart = leftpart.split('.', 1)[1];
9492
- var constraintfields = [];
9493
- if (domain_readonly) {
9494
- for (const leaf of inversion.localize_domain(
9495
- original_domain.slice(1))) {
9496
- constraintfields.push(leaf);
9497
- }
9498
- }
9499
- if ((localpart != 'id') ||
9500
- !~constraintfields.indexOf(recordpart)) {
9501
- setdefault = false;
9502
- }
9494
+ let localpart = leftpart.split('.').slice(1).join('.');
9495
+ setdefault = localpart == 'id';
9496
+ } else {
9497
+ setdefault = true;
9503
9498
  }
9504
9499
  if (setdefault && jQuery.isEmptyObject(pre_validate)) {
9505
9500
  this.set_client(record, value);
@@ -9763,12 +9758,23 @@ var Sao = {
9763
9758
  },
9764
9759
  apply_factor: function(record, value, factor) {
9765
9760
  if (value !== null) {
9761
+ // The default precision is the one used by value (before
9762
+ // applying the factor), per the ecmascript specification
9763
+ // it's the shortest representation of said value.
9764
+ // Once the factor is applied the number might become even
9765
+ // more inexact thus we should rely on the initial
9766
+ // precision + the effect factor will have
9767
+ // https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-tostring
9768
+ let default_precision = (value.toString().split('.')[1] || '').length;
9769
+ default_precision += Math.ceil(Math.log10(factor));
9766
9770
  value /= factor;
9767
9771
  var digits = this.digits(record);
9768
9772
  if (digits) {
9769
9773
  // Round to avoid float precision error
9770
9774
  // after the division by factor
9771
9775
  value = value.toFixed(digits[1]);
9776
+ } else {
9777
+ value = value.toFixed(default_precision);
9772
9778
  }
9773
9779
  value = this.convert(value);
9774
9780
  }
@@ -11553,15 +11559,20 @@ var Sao = {
11553
11559
  case 'ok':
11554
11560
  return this.save();
11555
11561
  case 'ko':
11556
- var record_id = this.screen.current_record.id;
11562
+ var record_id = null;
11563
+ if (this.screen.current_record) {
11564
+ record_id = this.screen.current_record.id;
11565
+ }
11557
11566
  return this.reload(false).then(() => {
11558
- if (record_id < 0) {
11559
- return jQuery.Deferred().reject(true);
11560
- }
11561
- else if (this.screen.current_record) {
11562
- if (record_id !=
11563
- this.screen.current_record.id) {
11564
- return jQuery.Deferred().reject();
11567
+ if (record_id !== null) {
11568
+ if (record_id < 0) {
11569
+ return jQuery.Deferred().reject(true);
11570
+ }
11571
+ else if (this.screen.current_record) {
11572
+ if (record_id !=
11573
+ this.screen.current_record.id) {
11574
+ return jQuery.Deferred().reject();
11575
+ }
11565
11576
  }
11566
11577
  }
11567
11578
  });
@@ -16340,7 +16351,8 @@ function eval_pyson(value){
16340
16351
  class_: 'form',
16341
16352
  init: function(languages, widget) {
16342
16353
  var dialog = new Sao.Dialog(
16343
- Sao.i18n.gettext('Translate'), this.class_, 'md');
16354
+ Sao.i18n.gettext('Translate'), this.class_,
16355
+ widget.expand? 'lg' : 'md');
16344
16356
  this.languages = languages;
16345
16357
  this.read(widget, dialog);
16346
16358
  jQuery('<button/>', {
@@ -16431,10 +16443,10 @@ function eval_pyson(value){
16431
16443
  input.uniqueId();
16432
16444
  row.append(jQuery('<label/>', {
16433
16445
  'for': input.attr('id'),
16434
- 'class': 'col-sm-3 control-label',
16446
+ 'class': 'col-sm-2 control-label',
16435
16447
  }).append(' ' + lang.name));
16436
16448
  row.append(jQuery('<div/>', {
16437
- 'class': 'col-sm-9 input-group',
16449
+ 'class': 'col-sm-10 input-group',
16438
16450
  }).append(input)
16439
16451
  .append(jQuery('<span/>', {
16440
16452
  'class': 'input-group-addon',
@@ -21677,7 +21689,8 @@ function eval_pyson(value){
21677
21689
  'type': 'button',
21678
21690
  'title': Sao.i18n.gettext("More"),
21679
21691
  }).text(Sao.i18n.gettext('More')
21680
- ).click(() => {
21692
+ ).one('click', () => {
21693
+ this.tbody.find('tr.more-row').remove();
21681
21694
  var height = this.table.height();
21682
21695
  this.display_size += Sao.config.display_size;
21683
21696
  this.display();
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.4.10",
5
+ "version": "7.4.12",
6
6
  "homepage": "https://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/common.js CHANGED
@@ -4368,16 +4368,19 @@
4368
4368
  return null;
4369
4369
  }
4370
4370
  var type = '';
4371
- try {
4372
- var xml = data;
4373
- if (xml instanceof Uint8Array) {
4374
- xml = new TextDecoder().decode(data);
4375
- }
4376
- if (jQuery.parseXML(xml)) {
4371
+ var xml = data;
4372
+ if (xml instanceof Uint8Array) {
4373
+ xml = new TextDecoder().decode(data);
4374
+ }
4375
+ // simple test to avoid logging of parsing error
4376
+ if (/^\s*<[\s\S]+>\s*$/.test(xml.trim())) {
4377
+ let parser = new DOMParser();
4378
+ let doc = parser.parseFromString(xml, 'image/svg+xml');
4379
+ if (!doc.querySelector('parsererror')
4380
+ && (doc.documentElement.tagName.toLowerCase() === 'svg' ||
4381
+ doc.getElementsByTagName('svg').length > 0)) {
4377
4382
  type = 'image/svg+xml';
4378
4383
  }
4379
- } catch (e) {
4380
- // continue
4381
4384
  }
4382
4385
  var blob = new Blob([data], {type: type});
4383
4386
  return window.URL.createObjectURL(blob);
package/src/model.js CHANGED
@@ -1753,7 +1753,6 @@
1753
1753
  // XXX to remove once server domains are fixed
1754
1754
  value = null;
1755
1755
  }
1756
- var setdefault = true;
1757
1756
  var original_domain;
1758
1757
  if (!jQuery.isEmptyObject(record.group.domain)) {
1759
1758
  original_domain = inversion.merge(record.group.domain);
@@ -1761,20 +1760,12 @@
1761
1760
  original_domain = inversion.merge(domain);
1762
1761
  }
1763
1762
  var domain_readonly = original_domain[0] == 'AND';
1763
+ let setdefault;
1764
1764
  if (leftpart.contains('.')) {
1765
- var recordpart = leftpart.split('.', 1)[0];
1766
- var localpart = leftpart.split('.', 1)[1];
1767
- var constraintfields = [];
1768
- if (domain_readonly) {
1769
- for (const leaf of inversion.localize_domain(
1770
- original_domain.slice(1))) {
1771
- constraintfields.push(leaf);
1772
- }
1773
- }
1774
- if ((localpart != 'id') ||
1775
- !~constraintfields.indexOf(recordpart)) {
1776
- setdefault = false;
1777
- }
1765
+ let localpart = leftpart.split('.').slice(1).join('.');
1766
+ setdefault = localpart == 'id';
1767
+ } else {
1768
+ setdefault = true;
1778
1769
  }
1779
1770
  if (setdefault && jQuery.isEmptyObject(pre_validate)) {
1780
1771
  this.set_client(record, value);
@@ -2038,12 +2029,23 @@
2038
2029
  },
2039
2030
  apply_factor: function(record, value, factor) {
2040
2031
  if (value !== null) {
2032
+ // The default precision is the one used by value (before
2033
+ // applying the factor), per the ecmascript specification
2034
+ // it's the shortest representation of said value.
2035
+ // Once the factor is applied the number might become even
2036
+ // more inexact thus we should rely on the initial
2037
+ // precision + the effect factor will have
2038
+ // https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-tostring
2039
+ let default_precision = (value.toString().split('.')[1] || '').length;
2040
+ default_precision += Math.ceil(Math.log10(factor));
2041
2041
  value /= factor;
2042
2042
  var digits = this.digits(record);
2043
2043
  if (digits) {
2044
2044
  // Round to avoid float precision error
2045
2045
  // after the division by factor
2046
2046
  value = value.toFixed(digits[1]);
2047
+ } else {
2048
+ value = value.toFixed(default_precision);
2047
2049
  }
2048
2050
  value = this.convert(value);
2049
2051
  }
package/src/sao.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.4.10',
6
+ __version__: '7.4.12',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -675,6 +675,7 @@ var Sao = {
675
675
  "Incompatible version of the server."),
676
676
  Sao.i18n.gettext("Version mismatch"));
677
677
  } else {
678
+ let url = window.location.hash.substr(1);
678
679
  Sao.Session.get_credentials()
679
680
  .then(function(session) {
680
681
  Sao.Session.current_session = session;
@@ -684,7 +685,7 @@ var Sao = {
684
685
  .then(function(preferences) {
685
686
  Sao.menu(preferences);
686
687
  Sao.user_menu(preferences);
687
- Sao.open_url();
688
+ Sao.open_url(url);
688
689
  Sao.Bus.listen();
689
690
  });
690
691
  }
package/src/tab.js CHANGED
@@ -841,15 +841,20 @@
841
841
  case 'ok':
842
842
  return this.save();
843
843
  case 'ko':
844
- var record_id = this.screen.current_record.id;
844
+ var record_id = null;
845
+ if (this.screen.current_record) {
846
+ record_id = this.screen.current_record.id;
847
+ }
845
848
  return this.reload(false).then(() => {
846
- if (record_id < 0) {
847
- return jQuery.Deferred().reject(true);
848
- }
849
- else if (this.screen.current_record) {
850
- if (record_id !=
851
- this.screen.current_record.id) {
852
- return jQuery.Deferred().reject();
849
+ if (record_id !== null) {
850
+ if (record_id < 0) {
851
+ return jQuery.Deferred().reject(true);
852
+ }
853
+ else if (this.screen.current_record) {
854
+ if (record_id !=
855
+ this.screen.current_record.id) {
856
+ return jQuery.Deferred().reject();
857
+ }
853
858
  }
854
859
  }
855
860
  });
package/src/view/form.js CHANGED
@@ -1418,7 +1418,8 @@ function eval_pyson(value){
1418
1418
  class_: 'form',
1419
1419
  init: function(languages, widget) {
1420
1420
  var dialog = new Sao.Dialog(
1421
- Sao.i18n.gettext('Translate'), this.class_, 'md');
1421
+ Sao.i18n.gettext('Translate'), this.class_,
1422
+ widget.expand? 'lg' : 'md');
1422
1423
  this.languages = languages;
1423
1424
  this.read(widget, dialog);
1424
1425
  jQuery('<button/>', {
@@ -1509,10 +1510,10 @@ function eval_pyson(value){
1509
1510
  input.uniqueId();
1510
1511
  row.append(jQuery('<label/>', {
1511
1512
  'for': input.attr('id'),
1512
- 'class': 'col-sm-3 control-label',
1513
+ 'class': 'col-sm-2 control-label',
1513
1514
  }).append(' ' + lang.name));
1514
1515
  row.append(jQuery('<div/>', {
1515
- 'class': 'col-sm-9 input-group',
1516
+ 'class': 'col-sm-10 input-group',
1516
1517
  }).append(input)
1517
1518
  .append(jQuery('<span/>', {
1518
1519
  'class': 'input-group-addon',
package/src/view/tree.js CHANGED
@@ -948,7 +948,8 @@
948
948
  'type': 'button',
949
949
  'title': Sao.i18n.gettext("More"),
950
950
  }).text(Sao.i18n.gettext('More')
951
- ).click(() => {
951
+ ).one('click', () => {
952
+ this.tbody.find('tr.more-row').remove();
952
953
  var height = this.table.height();
953
954
  this.display_size += Sao.config.display_size;
954
955
  this.display();