tryton-sao 7.6.0 → 7.6.2

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.6.2 - 2025-06-04
3
+ --------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
7
+ Version 7.6.1 - 2025-05-15
8
+ --------------------------
9
+ * Bug fixes (see mercurial logs for details)
10
+
11
+
2
12
  Version 7.6.0 - 2025-04-28
3
13
  --------------------------
4
14
  * Bug fixes (see mercurial logs for details)
@@ -9951,6 +9951,7 @@ img.icon {
9951
9951
  text-align: end;
9952
9952
  }
9953
9953
  .treeview > table.tree > thead > tr:first-child {
9954
+ background-color: #fff;
9954
9955
  position: sticky;
9955
9956
  top: 0;
9956
9957
  z-index: 100;
@@ -9958,20 +9959,17 @@ img.icon {
9958
9959
  .treeview > table.tree > thead > tr:first-child th {
9959
9960
  border: 1px solid transparent;
9960
9961
  border-bottom: 2px solid #ddd;
9961
- background-color: #fff;
9962
9962
  }
9963
9963
  .treeview > table.tree > thead > tr:first-child:hover th {
9964
9964
  border: 1px solid #ddd;
9965
9965
  border-bottom-width: 2px;
9966
9966
  }
9967
9967
  .treeview > table.tree > tfoot > tr {
9968
+ background-color: #fff;
9968
9969
  bottom: 0;
9969
9970
  position: sticky;
9970
9971
  z-index: 100;
9971
9972
  }
9972
- .treeview > table.tree > tfoot > tr th {
9973
- background-color: #fff;
9974
- }
9975
9973
  .treeview > table.tree > tfoot > tr th > label {
9976
9974
  display: none;
9977
9975
  }
@@ -10408,12 +10406,14 @@ img.icon {
10408
10406
  .form .form-richtext,
10409
10407
  .board .form-richtext {
10410
10408
  display: flex;
10409
+ flex-direction: column;
10411
10410
  }
10412
10411
  .form .form-text .input-group,
10413
10412
  .board .form-text .input-group,
10414
10413
  .form .form-richtext .input-group,
10415
10414
  .board .form-richtext .input-group {
10416
10415
  display: flex;
10416
+ height: 100%;
10417
10417
  width: 100%;
10418
10418
  }
10419
10419
  .form .form-text .input-group textarea,
@@ -10429,6 +10429,7 @@ img.icon {
10429
10429
  min-height: 12.5ex;
10430
10430
  overflow: auto;
10431
10431
  resize: vertical;
10432
+ width: 100%;
10432
10433
  }
10433
10434
  .form .form-text .input-group > span,
10434
10435
  .board .form-text .input-group > span,
@@ -10440,6 +10441,10 @@ img.icon {
10440
10441
  .board .form-richtext > .btn-toolbar {
10441
10442
  min-width: 450px;
10442
10443
  }
10444
+ .form .form-richtext > .panel-body,
10445
+ .board .form-richtext > .panel-body {
10446
+ flex-grow: 2;
10447
+ }
10443
10448
  .form .form-separator label,
10444
10449
  .board .form-separator label {
10445
10450
  margin-top: 10px;
@@ -10464,6 +10469,7 @@ img.icon {
10464
10469
  max-width: 100%;
10465
10470
  min-height: 50vh;
10466
10471
  height: 100%;
10472
+ width: 100%;
10467
10473
  }
10468
10474
  @media screen and (max-width: 767px) {
10469
10475
  .form .form-document object,
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.6.0',
6
+ __version__: '7.6.2',
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
  }
@@ -7721,16 +7722,19 @@ var Sao = {
7721
7722
  'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D');
7722
7723
  }
7723
7724
  var type = '';
7724
- try {
7725
- var xml = data;
7726
- if (xml instanceof Uint8Array) {
7727
- xml = new TextDecoder().decode(data);
7728
- }
7729
- if (jQuery.parseXML(xml)) {
7725
+ var xml = data;
7726
+ if (xml instanceof Uint8Array) {
7727
+ xml = new TextDecoder().decode(data);
7728
+ }
7729
+ // simple test to avoid logging of parsing error
7730
+ if (/^\s*<[\s\S]+>\s*$/.test(xml.trim())) {
7731
+ let parser = new DOMParser();
7732
+ let doc = parser.parseFromString(xml, 'image/svg+xml');
7733
+ if (!doc.querySelector('parsererror')
7734
+ && (doc.documentElement.tagName.toLowerCase() === 'svg' ||
7735
+ doc.getElementsByTagName('svg').length > 0)) {
7730
7736
  type = 'image/svg+xml';
7731
7737
  }
7732
- } catch (e) {
7733
- // continue
7734
7738
  }
7735
7739
  var blob = new Blob([data], {type: type});
7736
7740
  return window.URL.createObjectURL(blob);
@@ -9125,6 +9129,9 @@ var Sao = {
9125
9129
  }
9126
9130
  },
9127
9131
  get_loaded: function(fields) {
9132
+ if (this.id < 0) {
9133
+ return true;
9134
+ }
9128
9135
  if (!fields) {
9129
9136
  fields = Object.keys(this.model.fields);
9130
9137
  }
@@ -9526,7 +9533,6 @@ var Sao = {
9526
9533
  // XXX to remove once server domains are fixed
9527
9534
  value = null;
9528
9535
  }
9529
- var setdefault = true;
9530
9536
  var original_domain;
9531
9537
  if (!jQuery.isEmptyObject(record.group.domain)) {
9532
9538
  original_domain = inversion.merge(record.group.domain);
@@ -9534,20 +9540,12 @@ var Sao = {
9534
9540
  original_domain = inversion.merge(domain);
9535
9541
  }
9536
9542
  var domain_readonly = original_domain[0] == 'AND';
9543
+ let setdefault;
9537
9544
  if (leftpart.contains('.')) {
9538
- var recordpart = leftpart.split('.', 1)[0];
9539
- var localpart = leftpart.split('.', 1)[1];
9540
- var constraintfields = [];
9541
- if (domain_readonly) {
9542
- for (const leaf of inversion.localize_domain(
9543
- original_domain.slice(1))) {
9544
- constraintfields.push(leaf);
9545
- }
9546
- }
9547
- if ((localpart != 'id') ||
9548
- !~constraintfields.indexOf(recordpart)) {
9549
- setdefault = false;
9550
- }
9545
+ let localpart = leftpart.split('.').slice(1).join('.');
9546
+ setdefault = localpart == 'id';
9547
+ } else {
9548
+ setdefault = true;
9551
9549
  }
9552
9550
  if (setdefault && jQuery.isEmptyObject(pre_validate)) {
9553
9551
  this.set_client(record, value);
@@ -9817,12 +9815,23 @@ var Sao = {
9817
9815
  },
9818
9816
  apply_factor: function(record, value, factor) {
9819
9817
  if (value !== null) {
9818
+ // The default precision is the one used by value (before
9819
+ // applying the factor), per the ecmascript specification
9820
+ // it's the shortest representation of said value.
9821
+ // Once the factor is applied the number might become even
9822
+ // more inexact thus we should rely on the initial
9823
+ // precision + the effect factor will have
9824
+ // https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-tostring
9825
+ let default_precision = (value.toString().split('.')[1] || '').length;
9826
+ default_precision += Math.ceil(Math.log10(factor));
9820
9827
  value /= factor;
9821
9828
  var digits = this.digits(record);
9822
9829
  if (digits && (digits[1] !== null)) {
9823
9830
  // Round to avoid float precision error
9824
9831
  // after the division by factor
9825
9832
  value = value.toFixed(digits[1]);
9833
+ } else {
9834
+ value = value.toFixed(default_precision);
9826
9835
  }
9827
9836
  value = this.convert(value);
9828
9837
  }
@@ -10272,6 +10281,7 @@ var Sao = {
10272
10281
  }
10273
10282
 
10274
10283
  if (value && (value.add || value.update)) {
10284
+ let vals_to_set = {};
10275
10285
  // First set already added fields to prevent triggering a
10276
10286
  // second on_change call
10277
10287
  if (value.update) {
@@ -10281,9 +10291,9 @@ var Sao = {
10281
10291
  }
10282
10292
  const record2 = group.get(vals.id);
10283
10293
  if (record2) {
10284
- var vals_to_set = {};
10285
10294
  for (var key in vals) {
10286
- if (!Object.prototype.hasOwnProperty.call(new_field_names, key)) {
10295
+ if (!Object.prototype.hasOwnProperty.call(
10296
+ new_field_names, key)) {
10287
10297
  vals_to_set[key] = vals[key];
10288
10298
  }
10289
10299
  }
@@ -10319,7 +10329,10 @@ var Sao = {
10319
10329
  if (record2) {
10320
10330
  let to_update = Object.fromEntries(
10321
10331
  Object.entries(vals).filter(
10322
- ([k, v]) => !Object.prototype.hasOwnProperty.call(vals_to_set, k)
10332
+ ([k, v]) => {
10333
+ !Object.prototype.hasOwnProperty.call(
10334
+ vals_to_set, k)
10335
+ }
10323
10336
  ));
10324
10337
  record2.set_on_change(to_update);
10325
10338
  }
@@ -11623,15 +11636,20 @@ var Sao = {
11623
11636
  case 'ok':
11624
11637
  return this.save();
11625
11638
  case 'ko':
11626
- var record_id = this.screen.current_record.id;
11639
+ var record_id = null;
11640
+ if (this.screen.current_record) {
11641
+ record_id = this.screen.current_record.id;
11642
+ }
11627
11643
  return this.reload(false).then(() => {
11628
- if (record_id < 0) {
11629
- return jQuery.Deferred().reject(true);
11630
- }
11631
- else if (this.screen.current_record) {
11632
- if (record_id !=
11633
- this.screen.current_record.id) {
11634
- return jQuery.Deferred().reject();
11644
+ if (record_id !== null) {
11645
+ if (record_id < 0) {
11646
+ return jQuery.Deferred().reject(true);
11647
+ }
11648
+ else if (this.screen.current_record) {
11649
+ if (record_id !=
11650
+ this.screen.current_record.id) {
11651
+ return jQuery.Deferred().reject();
11652
+ }
11635
11653
  }
11636
11654
  }
11637
11655
  });
@@ -16488,7 +16506,8 @@ function eval_pyson(value){
16488
16506
  class_: 'form',
16489
16507
  init: function(languages, widget) {
16490
16508
  var dialog = new Sao.Dialog(
16491
- Sao.i18n.gettext('Translate'), this.class_, 'md');
16509
+ Sao.i18n.gettext('Translate'), this.class_,
16510
+ widget.expand? 'lg' : 'md');
16492
16511
  this.languages = languages;
16493
16512
  this.read(widget, dialog);
16494
16513
  jQuery('<button/>', {
@@ -16579,10 +16598,10 @@ function eval_pyson(value){
16579
16598
  input.uniqueId();
16580
16599
  row.append(jQuery('<label/>', {
16581
16600
  'for': input.attr('id'),
16582
- 'class': 'col-sm-3 control-label',
16601
+ 'class': 'col-sm-2 control-label',
16583
16602
  }).append(' ' + lang.name));
16584
16603
  row.append(jQuery('<div/>', {
16585
- 'class': 'col-sm-9 input-group',
16604
+ 'class': 'col-sm-10 input-group',
16586
16605
  }).append(input)
16587
16606
  .append(jQuery('<span/>', {
16588
16607
  'class': 'input-group-addon',
@@ -17654,9 +17673,11 @@ function eval_pyson(value){
17654
17673
  jQuery('<div/>', {
17655
17674
  'class': 'richtext mousetrap',
17656
17675
  'contenteditable': true
17676
+ }).appendTo(jQuery('<div/>', {
17677
+ 'class': 'input-group',
17657
17678
  }).appendTo(jQuery('<div/>', {
17658
17679
  'class': 'panel-body'
17659
- }).appendTo(widget));
17680
+ }).appendTo(widget)));
17660
17681
  return widget;
17661
17682
  },
17662
17683
  translate_widget_set_readonly: function(el, value) {
@@ -22020,6 +22041,8 @@ function eval_pyson(value){
22020
22041
  column.col.show();
22021
22042
  }
22022
22043
  }
22044
+ this.table.find('thead > tr > th .resizer').show();
22045
+ this.table.find('thead > tr > th:visible:last .resizer').hide();
22023
22046
  if (this.children_field) {
22024
22047
  this.columns.every(column => {
22025
22048
  if (column.col.hasClass('draggable-handle') ||
@@ -22075,7 +22098,8 @@ function eval_pyson(value){
22075
22098
  'type': 'button',
22076
22099
  'title': Sao.i18n.gettext("More"),
22077
22100
  }).text(Sao.i18n.gettext('More')
22078
- ).click(() => {
22101
+ ).one('click', () => {
22102
+ this.tbody.find('tr.more-row').remove();
22079
22103
  var height = this.table.height();
22080
22104
  this.display_size += Sao.config.display_size;
22081
22105
  this.display();
@@ -25980,7 +26004,9 @@ function eval_pyson(value){
25980
26004
  }
25981
26005
  }
25982
26006
  let message = name + '/' + Sao.common.humanize(size);
25983
- this.label.text(message).attr('title', message);
26007
+ if (this.label) {
26008
+ this.label.text(message).attr('title', message);
26009
+ }
25984
26010
  this._set_button_sensitive();
25985
26011
  },
25986
26012
  record_modified: function() {
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.6.0",
5
+ "version": "7.6.2",
6
6
  "homepage": "https://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/common.js CHANGED
@@ -4389,16 +4389,19 @@
4389
4389
  'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D');
4390
4390
  }
4391
4391
  var type = '';
4392
- try {
4393
- var xml = data;
4394
- if (xml instanceof Uint8Array) {
4395
- xml = new TextDecoder().decode(data);
4396
- }
4397
- if (jQuery.parseXML(xml)) {
4392
+ var xml = data;
4393
+ if (xml instanceof Uint8Array) {
4394
+ xml = new TextDecoder().decode(data);
4395
+ }
4396
+ // simple test to avoid logging of parsing error
4397
+ if (/^\s*<[\s\S]+>\s*$/.test(xml.trim())) {
4398
+ let parser = new DOMParser();
4399
+ let doc = parser.parseFromString(xml, 'image/svg+xml');
4400
+ if (!doc.querySelector('parsererror')
4401
+ && (doc.documentElement.tagName.toLowerCase() === 'svg' ||
4402
+ doc.getElementsByTagName('svg').length > 0)) {
4398
4403
  type = 'image/svg+xml';
4399
4404
  }
4400
- } catch (e) {
4401
- // continue
4402
4405
  }
4403
4406
  var blob = new Blob([data], {type: type});
4404
4407
  return window.URL.createObjectURL(blob);
package/src/model.js CHANGED
@@ -1367,6 +1367,9 @@
1367
1367
  }
1368
1368
  },
1369
1369
  get_loaded: function(fields) {
1370
+ if (this.id < 0) {
1371
+ return true;
1372
+ }
1370
1373
  if (!fields) {
1371
1374
  fields = Object.keys(this.model.fields);
1372
1375
  }
@@ -1768,7 +1771,6 @@
1768
1771
  // XXX to remove once server domains are fixed
1769
1772
  value = null;
1770
1773
  }
1771
- var setdefault = true;
1772
1774
  var original_domain;
1773
1775
  if (!jQuery.isEmptyObject(record.group.domain)) {
1774
1776
  original_domain = inversion.merge(record.group.domain);
@@ -1776,20 +1778,12 @@
1776
1778
  original_domain = inversion.merge(domain);
1777
1779
  }
1778
1780
  var domain_readonly = original_domain[0] == 'AND';
1781
+ let setdefault;
1779
1782
  if (leftpart.contains('.')) {
1780
- var recordpart = leftpart.split('.', 1)[0];
1781
- var localpart = leftpart.split('.', 1)[1];
1782
- var constraintfields = [];
1783
- if (domain_readonly) {
1784
- for (const leaf of inversion.localize_domain(
1785
- original_domain.slice(1))) {
1786
- constraintfields.push(leaf);
1787
- }
1788
- }
1789
- if ((localpart != 'id') ||
1790
- !~constraintfields.indexOf(recordpart)) {
1791
- setdefault = false;
1792
- }
1783
+ let localpart = leftpart.split('.').slice(1).join('.');
1784
+ setdefault = localpart == 'id';
1785
+ } else {
1786
+ setdefault = true;
1793
1787
  }
1794
1788
  if (setdefault && jQuery.isEmptyObject(pre_validate)) {
1795
1789
  this.set_client(record, value);
@@ -2059,12 +2053,23 @@
2059
2053
  },
2060
2054
  apply_factor: function(record, value, factor) {
2061
2055
  if (value !== null) {
2056
+ // The default precision is the one used by value (before
2057
+ // applying the factor), per the ecmascript specification
2058
+ // it's the shortest representation of said value.
2059
+ // Once the factor is applied the number might become even
2060
+ // more inexact thus we should rely on the initial
2061
+ // precision + the effect factor will have
2062
+ // https://tc39.es/ecma262/multipage/ecmascript-data-types-and-values.html#sec-numeric-types-number-tostring
2063
+ let default_precision = (value.toString().split('.')[1] || '').length;
2064
+ default_precision += Math.ceil(Math.log10(factor));
2062
2065
  value /= factor;
2063
2066
  var digits = this.digits(record);
2064
2067
  if (digits && (digits[1] !== null)) {
2065
2068
  // Round to avoid float precision error
2066
2069
  // after the division by factor
2067
2070
  value = value.toFixed(digits[1]);
2071
+ } else {
2072
+ value = value.toFixed(default_precision);
2068
2073
  }
2069
2074
  value = this.convert(value);
2070
2075
  }
@@ -2514,6 +2519,7 @@
2514
2519
  }
2515
2520
 
2516
2521
  if (value && (value.add || value.update)) {
2522
+ let vals_to_set = {};
2517
2523
  // First set already added fields to prevent triggering a
2518
2524
  // second on_change call
2519
2525
  if (value.update) {
@@ -2523,9 +2529,9 @@
2523
2529
  }
2524
2530
  const record2 = group.get(vals.id);
2525
2531
  if (record2) {
2526
- var vals_to_set = {};
2527
2532
  for (var key in vals) {
2528
- if (!Object.prototype.hasOwnProperty.call(new_field_names, key)) {
2533
+ if (!Object.prototype.hasOwnProperty.call(
2534
+ new_field_names, key)) {
2529
2535
  vals_to_set[key] = vals[key];
2530
2536
  }
2531
2537
  }
@@ -2561,7 +2567,10 @@
2561
2567
  if (record2) {
2562
2568
  let to_update = Object.fromEntries(
2563
2569
  Object.entries(vals).filter(
2564
- ([k, v]) => !Object.prototype.hasOwnProperty.call(vals_to_set, k)
2570
+ ([k, v]) => {
2571
+ !Object.prototype.hasOwnProperty.call(
2572
+ vals_to_set, k)
2573
+ }
2565
2574
  ));
2566
2575
  record2.set_on_change(to_update);
2567
2576
  }
package/src/sao.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.6.0',
6
+ __version__: '7.6.2',
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/sao.less CHANGED
@@ -814,6 +814,7 @@ img.icon {
814
814
  }
815
815
  }
816
816
  > thead > tr:first-child {
817
+ background-color: @body-bg;
817
818
  position: sticky;
818
819
  top: 0;
819
820
  z-index: 100;
@@ -821,7 +822,6 @@ img.icon {
821
822
  th {
822
823
  border: 1px solid transparent;
823
824
  border-bottom: 2px solid @table-border-color;
824
- background-color: @body-bg;
825
825
  }
826
826
 
827
827
  &:hover th {
@@ -830,12 +830,12 @@ img.icon {
830
830
  }
831
831
  }
832
832
  > tfoot > tr {
833
+ background-color: @body-bg;
833
834
  bottom: 0;
834
835
  position: sticky;
835
836
  z-index: 100;
836
837
 
837
838
  th {
838
- background-color: @body-bg;
839
839
  & > label {
840
840
  display: none;
841
841
  }
@@ -1131,9 +1131,11 @@ img.icon {
1131
1131
  }
1132
1132
  .form-text, .form-richtext {
1133
1133
  display: flex;
1134
+ flex-direction: column;
1134
1135
 
1135
1136
  .input-group {
1136
1137
  display: flex;
1138
+ height: 100%;
1137
1139
  width: 100%;
1138
1140
 
1139
1141
  textarea, .richtext {
@@ -1142,6 +1144,7 @@ img.icon {
1142
1144
  min-height: 12.5ex;
1143
1145
  overflow: auto;
1144
1146
  resize: vertical;
1147
+ width: 100%;
1145
1148
  }
1146
1149
 
1147
1150
  > span {
@@ -1153,6 +1156,9 @@ img.icon {
1153
1156
  > .btn-toolbar {
1154
1157
  min-width: 450px;
1155
1158
  }
1159
+ > .panel-body {
1160
+ flex-grow: 2;
1161
+ }
1156
1162
  }
1157
1163
  .form-separator {
1158
1164
  label {
@@ -1177,6 +1183,7 @@ img.icon {
1177
1183
  max-width: 100%;
1178
1184
  min-height: 50vh;
1179
1185
  height: 100%;
1186
+ width: 100%;
1180
1187
  @media screen and (max-width: @screen-xs-max) {
1181
1188
  min-height: 25vh;
1182
1189
  }
package/src/tab.js CHANGED
@@ -861,15 +861,20 @@
861
861
  case 'ok':
862
862
  return this.save();
863
863
  case 'ko':
864
- var record_id = this.screen.current_record.id;
864
+ var record_id = null;
865
+ if (this.screen.current_record) {
866
+ record_id = this.screen.current_record.id;
867
+ }
865
868
  return this.reload(false).then(() => {
866
- if (record_id < 0) {
867
- return jQuery.Deferred().reject(true);
868
- }
869
- else if (this.screen.current_record) {
870
- if (record_id !=
871
- this.screen.current_record.id) {
872
- return jQuery.Deferred().reject();
869
+ if (record_id !== null) {
870
+ if (record_id < 0) {
871
+ return jQuery.Deferred().reject(true);
872
+ }
873
+ else if (this.screen.current_record) {
874
+ if (record_id !=
875
+ this.screen.current_record.id) {
876
+ return jQuery.Deferred().reject();
877
+ }
873
878
  }
874
879
  }
875
880
  });
package/src/view/form.js CHANGED
@@ -1423,7 +1423,8 @@ function eval_pyson(value){
1423
1423
  class_: 'form',
1424
1424
  init: function(languages, widget) {
1425
1425
  var dialog = new Sao.Dialog(
1426
- Sao.i18n.gettext('Translate'), this.class_, 'md');
1426
+ Sao.i18n.gettext('Translate'), this.class_,
1427
+ widget.expand? 'lg' : 'md');
1427
1428
  this.languages = languages;
1428
1429
  this.read(widget, dialog);
1429
1430
  jQuery('<button/>', {
@@ -1514,10 +1515,10 @@ function eval_pyson(value){
1514
1515
  input.uniqueId();
1515
1516
  row.append(jQuery('<label/>', {
1516
1517
  'for': input.attr('id'),
1517
- 'class': 'col-sm-3 control-label',
1518
+ 'class': 'col-sm-2 control-label',
1518
1519
  }).append(' ' + lang.name));
1519
1520
  row.append(jQuery('<div/>', {
1520
- 'class': 'col-sm-9 input-group',
1521
+ 'class': 'col-sm-10 input-group',
1521
1522
  }).append(input)
1522
1523
  .append(jQuery('<span/>', {
1523
1524
  'class': 'input-group-addon',
@@ -2589,9 +2590,11 @@ function eval_pyson(value){
2589
2590
  jQuery('<div/>', {
2590
2591
  'class': 'richtext mousetrap',
2591
2592
  'contenteditable': true
2593
+ }).appendTo(jQuery('<div/>', {
2594
+ 'class': 'input-group',
2592
2595
  }).appendTo(jQuery('<div/>', {
2593
2596
  'class': 'panel-body'
2594
- }).appendTo(widget));
2597
+ }).appendTo(widget)));
2595
2598
  return widget;
2596
2599
  },
2597
2600
  translate_widget_set_readonly: function(el, value) {
package/src/view/tree.js CHANGED
@@ -1063,6 +1063,8 @@
1063
1063
  column.col.show();
1064
1064
  }
1065
1065
  }
1066
+ this.table.find('thead > tr > th .resizer').show();
1067
+ this.table.find('thead > tr > th:visible:last .resizer').hide();
1066
1068
  if (this.children_field) {
1067
1069
  this.columns.every(column => {
1068
1070
  if (column.col.hasClass('draggable-handle') ||
@@ -1118,7 +1120,8 @@
1118
1120
  'type': 'button',
1119
1121
  'title': Sao.i18n.gettext("More"),
1120
1122
  }).text(Sao.i18n.gettext('More')
1121
- ).click(() => {
1123
+ ).one('click', () => {
1124
+ this.tbody.find('tr.more-row').remove();
1122
1125
  var height = this.table.height();
1123
1126
  this.display_size += Sao.config.display_size;
1124
1127
  this.display();
package/src/window.js CHANGED
@@ -416,7 +416,9 @@
416
416
  }
417
417
  }
418
418
  let message = name + '/' + Sao.common.humanize(size);
419
- this.label.text(message).attr('title', message);
419
+ if (this.label) {
420
+ this.label.text(message).attr('title', message);
421
+ }
420
422
  this._set_button_sensitive();
421
423
  },
422
424
  record_modified: function() {