tryton-sao 7.0.47 → 7.0.49

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.0.49 - 2026-05-02
3
+ ---------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
7
+ Version 7.0.48 - 2026-04-16
8
+ ---------------------------
9
+ * Bug fixes (see mercurial logs for details)
10
+
11
+
2
12
  Version 7.0.47 - 2026-03-18
3
13
  ---------------------------
4
14
  * Bug fixes (see mercurial logs for details)
package/COPYRIGHT CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (C) 2012-2025 Nicolas Évrard.
1
+ Copyright (C) 2012-2026 Nicolas Évrard.
2
2
  Copyright (C) 2012-2026 Cédric Krier.
3
3
  Copyright (C) 2012-2014 Bertrand Chenal.
4
4
  Copyright (C) 2012-2026 B2CK SPRL.
@@ -9434,12 +9434,10 @@ html.accesskey *[accesskey]:after {
9434
9434
  padding: 0 2px;
9435
9435
  position: absolute;
9436
9436
  text-transform: uppercase;
9437
- margin: 0 -1em;
9437
+ left: -1em;
9438
+ right: 0;
9438
9439
  z-index: 5;
9439
9440
  }
9440
- html.accesskey input[accesskey][type="checkbox"]:after {
9441
- background-color: initial;
9442
- }
9443
9441
  html.accesskey *[accesskey] ~ span[data-accesskey] {
9444
9442
  float: right;
9445
9443
  position: relative;
@@ -9450,10 +9448,13 @@ html.accesskey *[accesskey] ~ span[data-accesskey]:after {
9450
9448
  html.accesskey *[accesskey]:after {
9451
9449
  content: attr(accesskey);
9452
9450
  }
9453
- html.accesskey input[accesskey][type="checkbox"] ~ span[data-accesskey],
9454
- html.accesskey input[accesskey][type="checkbox"] ~ span[data-accesskey],
9455
- html.accesskey select[accesskey] ~ span[data-accesskey] {
9456
- bottom: 1em;
9451
+ html.accesskey[dir="rtl"] *[accesskey] ~ span[data-accesskey]:after,
9452
+ html.accesskey[dir="rtl"] *[accesskey]:after {
9453
+ left: 0;
9454
+ right: -1em;
9455
+ }
9456
+ html.accesskey[dir="rtl"] *[accesskey] ~ span[data-accesskey] {
9457
+ float: left;
9457
9458
  }
9458
9459
  .tab-form,
9459
9460
  .tab-board {
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.0.47',
6
+ __version__: '7.0.49',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -2901,6 +2901,7 @@ var Sao = {
2901
2901
  if (service_window.closed) {
2902
2902
  window.clearInterval(timer);
2903
2903
  session.database = database;
2904
+ session.login = null;
2904
2905
  session.restore();
2905
2906
  if (session.session) {
2906
2907
  dfd.resolve(session);
@@ -5261,6 +5262,7 @@ var Sao = {
5261
5262
  let [, thousandSeparator] = /^10(.)?000/.exec(format(10000));
5262
5263
  let [, decimalSign] = /^0(.)1$/.exec(format(0.1));
5263
5264
  return Number(string
5265
+ .replace(new RegExp(' ', 'g'), '')
5264
5266
  .replace(new RegExp(thousandSeparator, 'g'), '')
5265
5267
  .replace(decimalSign, '.'));
5266
5268
  }
@@ -8620,7 +8622,7 @@ var Sao = {
8620
8622
  this.group.parent.id;
8621
8623
  }
8622
8624
  }
8623
- return this.set_default(values);
8625
+ return this.set_default(values).then(() => values);
8624
8626
  });
8625
8627
  }
8626
8628
  return jQuery.when();
@@ -10179,10 +10181,7 @@ var Sao = {
10179
10181
  if (record2) {
10180
10182
  let to_update = Object.fromEntries(
10181
10183
  Object.entries(vals).filter(
10182
- ([k, v]) => {
10183
- !Object.prototype.hasOwnProperty.call(
10184
- vals_to_set, k)
10185
- }
10184
+ ([k, v]) => !Object.hasOwn(vals_to_set, k)
10186
10185
  ));
10187
10186
  record2.set_on_change(to_update);
10188
10187
  }
@@ -10634,6 +10633,7 @@ var Sao = {
10634
10633
  this.name = '';
10635
10634
  this.name_el = jQuery('<span/>');
10636
10635
  this.view_prm = jQuery.when();
10636
+ this._action_running = false;
10637
10637
  },
10638
10638
  menu_def: function() {
10639
10639
  return [
@@ -10774,8 +10774,13 @@ var Sao = {
10774
10774
  this.menu_buttons[item.id] = menuitem;
10775
10775
  link.click(evt => {
10776
10776
  evt.preventDefault();
10777
- if (!menuitem.hasClass('disabled')) {
10778
- this[item.id]();
10777
+ if (!menuitem.hasClass('disabled')
10778
+ && !this._action_running) {
10779
+ this._action_running = true;
10780
+ (this[item.id]() || jQuery.when())
10781
+ .always(() => {
10782
+ this._action_running = false;
10783
+ });
10779
10784
  }
10780
10785
  });
10781
10786
  } else if (!item && previous) {
@@ -10875,17 +10880,14 @@ var Sao = {
10875
10880
  }
10876
10881
  this.buttons[item.id].click(item, event => {
10877
10882
  var item = event.data;
10878
- var button = this.buttons[item.id];
10879
- // Use data instead of disabled prop because the action may
10880
- // actually disable the button.
10881
- if (button.data('disabled')) {
10883
+ if (this._action_running) {
10882
10884
  event.preventDefault();
10883
10885
  return;
10884
10886
  }
10885
- button.data('disabled', true);
10887
+ this._action_running = true;
10886
10888
  (this[item.id](this) || jQuery.when())
10887
- .always(function() {
10888
- button.data('disabled', false);
10889
+ .always(() => {
10890
+ this._action_running = false;
10889
10891
  });
10890
10892
  });
10891
10893
  };
@@ -11459,7 +11461,7 @@ var Sao = {
11459
11461
  } else {
11460
11462
  prm = jQuery.when();
11461
11463
  }
11462
- prm.then(() => {
11464
+ return prm.then(() => {
11463
11465
  var access = Sao.common.MODELACCESS.get(this.screen.model_name);
11464
11466
  if (this.screen.readonly || !(access.write || access.create)) {
11465
11467
  return jQuery.Deferred().reject();
@@ -11501,6 +11503,8 @@ var Sao = {
11501
11503
  }
11502
11504
  return set_cursor;
11503
11505
  });
11506
+ } else {
11507
+ this.refresh_resources(true);
11504
11508
  }
11505
11509
  return set_cursor;
11506
11510
  })
@@ -11559,18 +11563,18 @@ var Sao = {
11559
11563
  },
11560
11564
  previous: function() {
11561
11565
  return this.modified_save().then(() => {
11562
- var prm = this.screen.display_previous();
11563
- this.info_bar.clear();
11564
- this.set_buttons_sensitive();
11565
- return prm;
11566
+ return this.screen.display_previous().then(() => {
11567
+ this.info_bar.clear();
11568
+ this.set_buttons_sensitive();
11569
+ });
11566
11570
  });
11567
11571
  },
11568
11572
  next: function() {
11569
11573
  return this.modified_save().then(() => {
11570
- var prm = this.screen.display_next();
11571
- this.info_bar.clear();
11572
- this.set_buttons_sensitive();
11573
- return prm;
11574
+ return this.screen.display_next().then(() => {
11575
+ this.info_bar.clear();
11576
+ this.set_buttons_sensitive();
11577
+ });
11574
11578
  });
11575
11579
  },
11576
11580
  search: function() {
@@ -12817,8 +12821,14 @@ var Sao = {
12817
12821
  break;
12818
12822
  case 'selection':
12819
12823
  case 'multiselection':
12824
+ var selection = jQuery.extend([], field.selection);
12825
+ if (field.sort === undefined || field.sort) {
12826
+ selection.sort(function(a, b) {
12827
+ return a[1].localeCompare(b[1]);
12828
+ });
12829
+ }
12820
12830
  entry = new Sao.ScreenContainer.Selection(
12821
- field.selection, prefix + field.name);
12831
+ selection, prefix + field.name);
12822
12832
  input = entry.el;
12823
12833
  break;
12824
12834
  case 'date':
@@ -14397,7 +14407,7 @@ var Sao = {
14397
14407
  if (this.current_view &&
14398
14408
  ~['tree', 'graph', 'calendar'].indexOf(this.current_view.view_type) &&
14399
14409
  !this.group.parent) {
14400
- this.search_filter();
14410
+ this.search_filter(this.screen_container.get_text());
14401
14411
  }
14402
14412
  } else if (action == 'reload menu') {
14403
14413
  Sao.Session.current_session.reload_context()
@@ -15173,7 +15183,8 @@ function eval_pyson(value){
15173
15183
  }
15174
15184
  }
15175
15185
  return jQuery.when.apply(jQuery,promesses)
15176
- .done(() => {
15186
+ .then(() => {
15187
+ let promesses = [];
15177
15188
  var record = this.record;
15178
15189
  for (const name in this.widgets) {
15179
15190
  var widgets = this.widgets[name];
@@ -15185,10 +15196,12 @@ function eval_pyson(value){
15185
15196
  field.set_state(record);
15186
15197
  }
15187
15198
  for (const widget of widgets) {
15188
- widget.display();
15199
+ let prm = widget.display();
15200
+ if (prm) {
15201
+ promesses.push(prm);
15202
+ }
15189
15203
  }
15190
15204
  }
15191
- var promesses = [];
15192
15205
  for (const j in this.state_widgets) {
15193
15206
  var state_widget = this.state_widgets[j];
15194
15207
  var prm = state_widget.set_state(record);
@@ -15201,7 +15214,7 @@ function eval_pyson(value){
15201
15214
  }
15202
15215
  // re-set the grid templates for the StateWidget that are
15203
15216
  // asynchronous
15204
- jQuery.when.apply(jQuery, promesses).done(() => {
15217
+ return jQuery.when.apply(jQuery, promesses).then(() => {
15205
15218
  for (const container of this.containers) {
15206
15219
  container.set_grid_template();
15207
15220
  }
@@ -16934,11 +16947,13 @@ function eval_pyson(value){
16934
16947
  this.el = jQuery('<div/>', {
16935
16948
  'class': this.class_
16936
16949
  });
16950
+ this.group = jQuery('<div/>', {
16951
+ 'class': 'input-group input-group-sm'
16952
+ }).css('width', '100%').appendTo(this.el);
16937
16953
  this.select = this.labelled = jQuery('<select/>', {
16938
16954
  'class': 'form-control input-sm mousetrap',
16939
16955
  'name': attributes.name,
16940
- });
16941
- this.el.append(this.select);
16956
+ }).appendTo(this.group);
16942
16957
  this.select.change(this.focus_out.bind(this));
16943
16958
  Sao.common.selection_mixin.init.call(this);
16944
16959
  this.init_selection();
@@ -17039,11 +17054,14 @@ function eval_pyson(value){
17039
17054
  this.el = jQuery('<div/>', {
17040
17055
  'class': this.class_
17041
17056
  });
17057
+ this.group = jQuery('<div/>', {
17058
+ 'class': 'input-group input-group-sm'
17059
+ }).css('width', '100%').appendTo(this.el);
17042
17060
  this.input = this.labelled = jQuery('<input/>', {
17043
17061
  'type': 'checkbox',
17044
17062
  'class': 'form-control input-sm mousetrap',
17045
17063
  'name': attributes.name,
17046
- }).appendTo(this.el);
17064
+ }).appendTo(this.group);
17047
17065
  this.input.change(this.focus_out.bind(this));
17048
17066
  this.input.click(function() {
17049
17067
  // Dont trigger click if field is readonly as readonly has no
@@ -18238,7 +18256,7 @@ function eval_pyson(value){
18238
18256
  display: function() {
18239
18257
  Sao.View.Form.One2Many._super.display.call(this);
18240
18258
 
18241
- this.prm.done(() => {
18259
+ return this.prm.then(() => {
18242
18260
  this._set_button_sensitive();
18243
18261
 
18244
18262
  var record = this.record;
@@ -18248,8 +18266,7 @@ function eval_pyson(value){
18248
18266
  this.screen.new_group();
18249
18267
  this.screen.current_record = null;
18250
18268
  this.screen.group.parent = null;
18251
- this.screen.display();
18252
- return;
18269
+ return this.screen.display();
18253
18270
  }
18254
18271
 
18255
18272
  var new_group = record.field_get_client(this.field_name);
@@ -18278,13 +18295,13 @@ function eval_pyson(value){
18278
18295
  this.screen.domain = domain;
18279
18296
  }
18280
18297
  this.screen.size_limit = size_limit;
18281
- this.screen.display();
18282
18298
  if (this.attributes.height !== undefined) {
18283
18299
  this.content
18284
18300
  .find('.treeview,.list-form').first()
18285
18301
  .css('min-height', this.attributes.height + 'px')
18286
18302
  .css('max-height', this.attributes.height + 'px');
18287
18303
  }
18304
+ return this.screen.display();
18288
18305
  });
18289
18306
  },
18290
18307
  focus: function() {
@@ -18557,9 +18574,7 @@ function eval_pyson(value){
18557
18574
  return prm;
18558
18575
  },
18559
18576
  set_value: function() {
18560
- if (this.screen.modified()) { // TODO check if required
18561
- this.view.screen.record_modified(false);
18562
- }
18577
+ this.screen.current_view.set_value();
18563
18578
  },
18564
18579
  _update_completion: function(text) {
18565
18580
  if (!this.record) {
@@ -18763,7 +18778,7 @@ function eval_pyson(value){
18763
18778
  display: function() {
18764
18779
  Sao.View.Form.Many2Many._super.display.call(this);
18765
18780
 
18766
- this.prm.done(() => {
18781
+ return this.prm.then(() => {
18767
18782
  var record = this.record;
18768
18783
  var field = this.field;
18769
18784
 
@@ -18771,20 +18786,19 @@ function eval_pyson(value){
18771
18786
  this.screen.new_group();
18772
18787
  this.screen.current_record = null;
18773
18788
  this.screen.group.parent = null;
18774
- this.screen.display();
18775
- return;
18789
+ return this.screen.display();
18776
18790
  }
18777
18791
  var new_group = record.field_get_client(this.field_name);
18778
18792
  if (new_group != this.screen.group) {
18779
18793
  this.screen.set_group(new_group);
18780
18794
  }
18781
- this.screen.display();
18782
18795
  if (this.attributes.height !== undefined) {
18783
18796
  this.content
18784
18797
  .find('.treeview,.list-form').first()
18785
18798
  .css('min-height', this.attributes.height + 'px')
18786
18799
  .css('max-height', this.attributes.height + 'px');
18787
18800
  }
18801
+ return this.screen.display();
18788
18802
  });
18789
18803
  },
18790
18804
  focus: function() {
@@ -22918,6 +22932,10 @@ function eval_pyson(value){
22918
22932
  fields, false, false, true)) {
22919
22933
  var value = cell.prop('checked');
22920
22934
  this.field.set_client(record, value);
22935
+ if (record !== current_record) {
22936
+ // we can not rely on editable tree handler to save the row
22937
+ record.save();
22938
+ }
22921
22939
  } else {
22922
22940
  evt.preventDefault();
22923
22941
  }
@@ -9434,12 +9434,10 @@ html.accesskey *[accesskey]:after {
9434
9434
  padding: 0 2px;
9435
9435
  position: absolute;
9436
9436
  text-transform: uppercase;
9437
- margin: 0 -1em;
9437
+ left: -1em;
9438
+ right: 0;
9438
9439
  z-index: 5;
9439
9440
  }
9440
- html.accesskey input[accesskey][type="checkbox"]:after {
9441
- background-color: initial;
9442
- }
9443
9441
  html.accesskey *[accesskey] ~ span[data-accesskey] {
9444
9442
  float: right;
9445
9443
  position: relative;
@@ -9450,10 +9448,13 @@ html.accesskey *[accesskey] ~ span[data-accesskey]:after {
9450
9448
  html.accesskey *[accesskey]:after {
9451
9449
  content: attr(accesskey);
9452
9450
  }
9453
- html.accesskey input[accesskey][type="checkbox"] ~ span[data-accesskey],
9454
- html.accesskey input[accesskey][type="checkbox"] ~ span[data-accesskey],
9455
- html.accesskey select[accesskey] ~ span[data-accesskey] {
9456
- bottom: 1em;
9451
+ html.accesskey[dir="rtl"] *[accesskey] ~ span[data-accesskey]:after,
9452
+ html.accesskey[dir="rtl"] *[accesskey]:after {
9453
+ left: 0;
9454
+ right: -1em;
9455
+ }
9456
+ html.accesskey[dir="rtl"] *[accesskey] ~ span[data-accesskey] {
9457
+ float: left;
9457
9458
  }
9458
9459
  .tab-form,
9459
9460
  .tab-board {