tryton-sao 7.8.8 → 7.8.9

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,9 @@
1
1
 
2
+ Version 7.8.9 - 2026-05-02
3
+ --------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
2
7
  Version 7.8.8 - 2026-04-16
3
8
  --------------------------
4
9
  * Bug fixes (see mercurial logs for details)
@@ -9758,12 +9758,10 @@ html.accesskey *[accesskey]:after {
9758
9758
  padding: 0 2px;
9759
9759
  position: absolute;
9760
9760
  text-transform: uppercase;
9761
- margin: 0 -1em;
9761
+ left: -1em;
9762
+ right: 0;
9762
9763
  z-index: 5;
9763
9764
  }
9764
- html.accesskey input[accesskey][type="checkbox"]:after {
9765
- background-color: initial;
9766
- }
9767
9765
  html.accesskey *[accesskey] ~ span[data-accesskey] {
9768
9766
  float: right;
9769
9767
  position: relative;
@@ -9774,10 +9772,13 @@ html.accesskey *[accesskey] ~ span[data-accesskey]:after {
9774
9772
  html.accesskey *[accesskey]:after {
9775
9773
  content: attr(accesskey);
9776
9774
  }
9777
- html.accesskey input[accesskey][type="checkbox"] ~ span[data-accesskey],
9778
- html.accesskey input[accesskey][type="checkbox"] ~ span[data-accesskey],
9779
- html.accesskey select[accesskey] ~ span[data-accesskey] {
9780
- bottom: 1em;
9775
+ html.accesskey[dir="rtl"] *[accesskey] ~ span[data-accesskey]:after,
9776
+ html.accesskey[dir="rtl"] *[accesskey]:after {
9777
+ left: 0;
9778
+ right: -1em;
9779
+ }
9780
+ html.accesskey[dir="rtl"] *[accesskey] ~ span[data-accesskey] {
9781
+ float: left;
9781
9782
  }
9782
9783
  .tab-form,
9783
9784
  .tab-board {
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.8.8',
6
+ __version__: '7.8.9',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -8796,7 +8796,7 @@ var Sao = {
8796
8796
  this.group.parent.id;
8797
8797
  }
8798
8798
  }
8799
- return this.set_default(values);
8799
+ return this.set_default(values).then(() => values);
8800
8800
  });
8801
8801
  }
8802
8802
  return jQuery.when();
@@ -10833,6 +10833,7 @@ var Sao = {
10833
10833
  'class': 'hidden-lg',
10834
10834
  }).appendTo(this.name_el);
10835
10835
  this.view_prm = jQuery.when();
10836
+ this._action_running = false;
10836
10837
  },
10837
10838
  menu_def: function() {
10838
10839
  return [
@@ -10982,8 +10983,13 @@ var Sao = {
10982
10983
  this.menu_buttons[item.id] = menuitem;
10983
10984
  link.click(evt => {
10984
10985
  evt.preventDefault();
10985
- if (!menuitem.hasClass('disabled')) {
10986
- this[item.id]();
10986
+ if (!menuitem.hasClass('disabled')
10987
+ && !this._action_running) {
10988
+ this._action_running = true;
10989
+ (this[item.id]() || jQuery.when())
10990
+ .always(() => {
10991
+ this._action_running = false;
10992
+ });
10987
10993
  }
10988
10994
  });
10989
10995
  } else if (!item && previous) {
@@ -11087,17 +11093,14 @@ var Sao = {
11087
11093
  }
11088
11094
  this.buttons[item.id].click(item, event => {
11089
11095
  var item = event.data;
11090
- var button = this.buttons[item.id];
11091
- // Use data instead of disabled prop because the action may
11092
- // actually disable the button.
11093
- if (button.data('disabled')) {
11096
+ if (this._action_running) {
11094
11097
  event.preventDefault();
11095
11098
  return;
11096
11099
  }
11097
- button.data('disabled', true);
11100
+ this._action_running = true;
11098
11101
  (this[item.id](this) || jQuery.when())
11099
- .always(function() {
11100
- button.data('disabled', false);
11102
+ .always(() => {
11103
+ this._action_running = false;
11101
11104
  });
11102
11105
  });
11103
11106
  };
@@ -11724,7 +11727,7 @@ var Sao = {
11724
11727
  } else {
11725
11728
  prm = jQuery.when();
11726
11729
  }
11727
- prm.then(() => {
11730
+ return prm.then(() => {
11728
11731
  var access = Sao.common.MODELACCESS.get(this.screen.model_name);
11729
11732
  if (this.screen.readonly || !(access.write || access.create)) {
11730
11733
  return jQuery.Deferred().reject();
@@ -11826,18 +11829,18 @@ var Sao = {
11826
11829
  },
11827
11830
  previous: function() {
11828
11831
  return this.modified_save().then(() => {
11829
- var prm = this.screen.display_previous();
11830
- this.info_bar.clear();
11831
- this.set_buttons_sensitive();
11832
- return prm;
11832
+ return this.screen.display_previous().then(() => {
11833
+ this.info_bar.clear();
11834
+ this.set_buttons_sensitive();
11835
+ });
11833
11836
  });
11834
11837
  },
11835
11838
  next: function() {
11836
11839
  return this.modified_save().then(() => {
11837
- var prm = this.screen.display_next();
11838
- this.info_bar.clear();
11839
- this.set_buttons_sensitive();
11840
- return prm;
11840
+ return this.screen.display_next().then(() => {
11841
+ this.info_bar.clear();
11842
+ this.set_buttons_sensitive();
11843
+ });
11841
11844
  });
11842
11845
  },
11843
11846
  search: function() {
@@ -15540,7 +15543,8 @@ function eval_pyson(value){
15540
15543
  }
15541
15544
  }
15542
15545
  return jQuery.when.apply(jQuery,promesses)
15543
- .done(() => {
15546
+ .then(() => {
15547
+ let promesses = [];
15544
15548
  var record = this.record;
15545
15549
  for (const name in this.widgets) {
15546
15550
  var widgets = this.widgets[name];
@@ -15552,10 +15556,12 @@ function eval_pyson(value){
15552
15556
  field.set_state(record);
15553
15557
  }
15554
15558
  for (const widget of widgets) {
15555
- widget.display();
15559
+ let prm = widget.display();
15560
+ if (prm) {
15561
+ promesses.push(prm);
15562
+ }
15556
15563
  }
15557
15564
  }
15558
- var promesses = [];
15559
15565
  // We iterate in the reverse order so that the most nested
15560
15566
  // widgets are computed first and set_state methods can rely
15561
15567
  // on their children having their state set
@@ -15570,7 +15576,7 @@ function eval_pyson(value){
15570
15576
  }
15571
15577
  // re-set the grid templates for the StateWidget that are
15572
15578
  // asynchronous
15573
- jQuery.when.apply(jQuery, promesses).done(() => {
15579
+ return jQuery.when.apply(jQuery, promesses).then(() => {
15574
15580
  for (const container of this.containers) {
15575
15581
  container.set_grid_template();
15576
15582
  }
@@ -17407,11 +17413,13 @@ function eval_pyson(value){
17407
17413
  this.el = jQuery('<div/>', {
17408
17414
  'class': this.class_
17409
17415
  });
17416
+ this.group = jQuery('<div/>', {
17417
+ 'class': 'input-group input-group-sm'
17418
+ }).css('width', '100%').appendTo(this.el);
17410
17419
  this.select = this.labelled = jQuery('<select/>', {
17411
17420
  'class': 'form-control input-sm mousetrap',
17412
17421
  'name': attributes.name,
17413
- });
17414
- this.el.append(this.select);
17422
+ }).appendTo(this.group);
17415
17423
  this.select.change(this.focus_out.bind(this));
17416
17424
  Sao.common.selection_mixin.init.call(this);
17417
17425
  this.init_selection();
@@ -17512,11 +17520,14 @@ function eval_pyson(value){
17512
17520
  this.el = jQuery('<div/>', {
17513
17521
  'class': this.class_
17514
17522
  });
17523
+ this.group = jQuery('<div/>', {
17524
+ 'class': 'input-group input-group-sm'
17525
+ }).css('width', '100%').appendTo(this.el);
17515
17526
  this.input = this.labelled = jQuery('<input/>', {
17516
17527
  'type': 'checkbox',
17517
17528
  'class': 'form-control input-sm mousetrap',
17518
17529
  'name': attributes.name,
17519
- }).appendTo(this.el);
17530
+ }).appendTo(this.group);
17520
17531
  this.input.change(this.focus_out.bind(this));
17521
17532
  this.input.click(function() {
17522
17533
  // Dont trigger click if field is readonly as readonly has no
@@ -18779,7 +18790,7 @@ function eval_pyson(value){
18779
18790
  display: function() {
18780
18791
  Sao.View.Form.One2Many._super.display.call(this);
18781
18792
 
18782
- this.prm.done(() => {
18793
+ return this.prm.then(() => {
18783
18794
  this._set_button_sensitive();
18784
18795
 
18785
18796
  var record = this.record;
@@ -18789,9 +18800,8 @@ function eval_pyson(value){
18789
18800
  this.screen.new_group();
18790
18801
  this.screen.current_record = null;
18791
18802
  this.screen.group.parent = null;
18792
- this.screen.display();
18793
18803
  this.screen.screen_container.hide_filter();
18794
- return;
18804
+ return this.screen.display();
18795
18805
  }
18796
18806
 
18797
18807
  var new_group = record.field_get_client(this.field_name);
@@ -18820,13 +18830,13 @@ function eval_pyson(value){
18820
18830
  this.screen.domain = domain;
18821
18831
  }
18822
18832
  this.screen.size_limit = size_limit;
18823
- this.screen.display();
18824
18833
  if (this.attributes.height !== undefined) {
18825
18834
  this.content
18826
18835
  .find('.treeview,.list-form').first()
18827
18836
  .css('min-height', this.attributes.height + 'px')
18828
18837
  .css('max-height', this.attributes.height + 'px');
18829
18838
  }
18839
+ return this.screen.display();
18830
18840
  });
18831
18841
  },
18832
18842
  focus: function() {
@@ -19126,9 +19136,7 @@ function eval_pyson(value){
19126
19136
  return prm;
19127
19137
  },
19128
19138
  set_value: function() {
19129
- if (this.screen.modified()) { // TODO check if required
19130
- this.view.screen.record_modified(false);
19131
- }
19139
+ this.screen.current_view.set_value();
19132
19140
  },
19133
19141
  _update_completion: function(text) {
19134
19142
  if (!this.record) {
@@ -19362,7 +19370,7 @@ function eval_pyson(value){
19362
19370
  display: function() {
19363
19371
  Sao.View.Form.Many2Many._super.display.call(this);
19364
19372
 
19365
- this.prm.done(() => {
19373
+ return this.prm.then(() => {
19366
19374
  var record = this.record;
19367
19375
  var field = this.field;
19368
19376
 
@@ -19370,21 +19378,20 @@ function eval_pyson(value){
19370
19378
  this.screen.new_group();
19371
19379
  this.screen.current_record = null;
19372
19380
  this.screen.group.parent = null;
19373
- this.screen.display();
19374
19381
  this.screen.screen_container.hide_filter();
19375
- return;
19382
+ return this.screen.display();
19376
19383
  }
19377
19384
  var new_group = record.field_get_client(this.field_name);
19378
19385
  if (new_group != this.screen.group) {
19379
19386
  this.screen.set_group(new_group);
19380
19387
  }
19381
- this.screen.display();
19382
19388
  if (this.attributes.height !== undefined) {
19383
19389
  this.content
19384
19390
  .find('.treeview,.list-form').first()
19385
19391
  .css('min-height', this.attributes.height + 'px')
19386
19392
  .css('max-height', this.attributes.height + 'px');
19387
19393
  }
19394
+ return this.screen.display();
19388
19395
  });
19389
19396
  },
19390
19397
  focus: function() {
@@ -23843,6 +23850,10 @@ function eval_pyson(value){
23843
23850
  fields, false, false)) {
23844
23851
  var value = cell.prop('checked');
23845
23852
  this.field.set_client(record, value);
23853
+ if (record !== current_record) {
23854
+ // we can not rely on editable tree handler to save the row
23855
+ record.save();
23856
+ }
23846
23857
  } else {
23847
23858
  evt.preventDefault();
23848
23859
  }
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.8.8",
5
+ "version": "7.8.9",
6
6
  "homepage": "https://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/model.js CHANGED
@@ -990,7 +990,7 @@
990
990
  this.group.parent.id;
991
991
  }
992
992
  }
993
- return this.set_default(values);
993
+ return this.set_default(values).then(() => values);
994
994
  });
995
995
  }
996
996
  return jQuery.when();
package/src/sao.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.8.8',
6
+ __version__: '7.8.9',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
package/src/sao.less CHANGED
@@ -607,14 +607,11 @@ html.accesskey {
607
607
  padding: 0 2px;
608
608
  position: absolute;
609
609
  text-transform: uppercase;
610
- margin: 0 -1em;
610
+ left: -1em;
611
+ right: 0;
611
612
  z-index: 5;
612
613
  }
613
614
 
614
- input[accesskey][type="checkbox"]:after {
615
- background-color: initial;
616
- }
617
-
618
615
  *[accesskey] ~ span[data-accesskey] {
619
616
  float: right;
620
617
  position: relative;
@@ -628,11 +625,15 @@ html.accesskey {
628
625
  content: attr(accesskey);
629
626
  }
630
627
 
631
- input[accesskey][type="checkbox"],
632
- input[accesskey][type="checkbox"],
633
- select[accesskey] {
634
- & ~ span[data-accesskey] {
635
- bottom: 1em;
628
+ &[dir="rtl"] {
629
+ *[accesskey] ~ span[data-accesskey]:after,
630
+ *[accesskey]:after {
631
+ left: 0;
632
+ right: -1em;
633
+ }
634
+
635
+ *[accesskey] ~ span[data-accesskey] {
636
+ float: left;
636
637
  }
637
638
  }
638
639
  }
package/src/tab.js CHANGED
@@ -18,6 +18,7 @@
18
18
  'class': 'hidden-lg',
19
19
  }).appendTo(this.name_el);
20
20
  this.view_prm = jQuery.when();
21
+ this._action_running = false;
21
22
  },
22
23
  menu_def: function() {
23
24
  return [
@@ -167,8 +168,13 @@
167
168
  this.menu_buttons[item.id] = menuitem;
168
169
  link.click(evt => {
169
170
  evt.preventDefault();
170
- if (!menuitem.hasClass('disabled')) {
171
- this[item.id]();
171
+ if (!menuitem.hasClass('disabled')
172
+ && !this._action_running) {
173
+ this._action_running = true;
174
+ (this[item.id]() || jQuery.when())
175
+ .always(() => {
176
+ this._action_running = false;
177
+ });
172
178
  }
173
179
  });
174
180
  } else if (!item && previous) {
@@ -272,17 +278,14 @@
272
278
  }
273
279
  this.buttons[item.id].click(item, event => {
274
280
  var item = event.data;
275
- var button = this.buttons[item.id];
276
- // Use data instead of disabled prop because the action may
277
- // actually disable the button.
278
- if (button.data('disabled')) {
281
+ if (this._action_running) {
279
282
  event.preventDefault();
280
283
  return;
281
284
  }
282
- button.data('disabled', true);
285
+ this._action_running = true;
283
286
  (this[item.id](this) || jQuery.when())
284
- .always(function() {
285
- button.data('disabled', false);
287
+ .always(() => {
288
+ this._action_running = false;
286
289
  });
287
290
  });
288
291
  };
@@ -909,7 +912,7 @@
909
912
  } else {
910
913
  prm = jQuery.when();
911
914
  }
912
- prm.then(() => {
915
+ return prm.then(() => {
913
916
  var access = Sao.common.MODELACCESS.get(this.screen.model_name);
914
917
  if (this.screen.readonly || !(access.write || access.create)) {
915
918
  return jQuery.Deferred().reject();
@@ -1011,18 +1014,18 @@
1011
1014
  },
1012
1015
  previous: function() {
1013
1016
  return this.modified_save().then(() => {
1014
- var prm = this.screen.display_previous();
1015
- this.info_bar.clear();
1016
- this.set_buttons_sensitive();
1017
- return prm;
1017
+ return this.screen.display_previous().then(() => {
1018
+ this.info_bar.clear();
1019
+ this.set_buttons_sensitive();
1020
+ });
1018
1021
  });
1019
1022
  },
1020
1023
  next: function() {
1021
1024
  return this.modified_save().then(() => {
1022
- var prm = this.screen.display_next();
1023
- this.info_bar.clear();
1024
- this.set_buttons_sensitive();
1025
- return prm;
1025
+ return this.screen.display_next().then(() => {
1026
+ this.info_bar.clear();
1027
+ this.set_buttons_sensitive();
1028
+ });
1026
1029
  });
1027
1030
  },
1028
1031
  search: function() {
package/src/view/form.js CHANGED
@@ -382,7 +382,8 @@ function eval_pyson(value){
382
382
  }
383
383
  }
384
384
  return jQuery.when.apply(jQuery,promesses)
385
- .done(() => {
385
+ .then(() => {
386
+ let promesses = [];
386
387
  var record = this.record;
387
388
  for (const name in this.widgets) {
388
389
  var widgets = this.widgets[name];
@@ -394,10 +395,12 @@ function eval_pyson(value){
394
395
  field.set_state(record);
395
396
  }
396
397
  for (const widget of widgets) {
397
- widget.display();
398
+ let prm = widget.display();
399
+ if (prm) {
400
+ promesses.push(prm);
401
+ }
398
402
  }
399
403
  }
400
- var promesses = [];
401
404
  // We iterate in the reverse order so that the most nested
402
405
  // widgets are computed first and set_state methods can rely
403
406
  // on their children having their state set
@@ -412,7 +415,7 @@ function eval_pyson(value){
412
415
  }
413
416
  // re-set the grid templates for the StateWidget that are
414
417
  // asynchronous
415
- jQuery.when.apply(jQuery, promesses).done(() => {
418
+ return jQuery.when.apply(jQuery, promesses).then(() => {
416
419
  for (const container of this.containers) {
417
420
  container.set_grid_template();
418
421
  }
@@ -2249,11 +2252,13 @@ function eval_pyson(value){
2249
2252
  this.el = jQuery('<div/>', {
2250
2253
  'class': this.class_
2251
2254
  });
2255
+ this.group = jQuery('<div/>', {
2256
+ 'class': 'input-group input-group-sm'
2257
+ }).css('width', '100%').appendTo(this.el);
2252
2258
  this.select = this.labelled = jQuery('<select/>', {
2253
2259
  'class': 'form-control input-sm mousetrap',
2254
2260
  'name': attributes.name,
2255
- });
2256
- this.el.append(this.select);
2261
+ }).appendTo(this.group);
2257
2262
  this.select.change(this.focus_out.bind(this));
2258
2263
  Sao.common.selection_mixin.init.call(this);
2259
2264
  this.init_selection();
@@ -2354,11 +2359,14 @@ function eval_pyson(value){
2354
2359
  this.el = jQuery('<div/>', {
2355
2360
  'class': this.class_
2356
2361
  });
2362
+ this.group = jQuery('<div/>', {
2363
+ 'class': 'input-group input-group-sm'
2364
+ }).css('width', '100%').appendTo(this.el);
2357
2365
  this.input = this.labelled = jQuery('<input/>', {
2358
2366
  'type': 'checkbox',
2359
2367
  'class': 'form-control input-sm mousetrap',
2360
2368
  'name': attributes.name,
2361
- }).appendTo(this.el);
2369
+ }).appendTo(this.group);
2362
2370
  this.input.change(this.focus_out.bind(this));
2363
2371
  this.input.click(function() {
2364
2372
  // Dont trigger click if field is readonly as readonly has no
@@ -3621,7 +3629,7 @@ function eval_pyson(value){
3621
3629
  display: function() {
3622
3630
  Sao.View.Form.One2Many._super.display.call(this);
3623
3631
 
3624
- this.prm.done(() => {
3632
+ return this.prm.then(() => {
3625
3633
  this._set_button_sensitive();
3626
3634
 
3627
3635
  var record = this.record;
@@ -3631,9 +3639,8 @@ function eval_pyson(value){
3631
3639
  this.screen.new_group();
3632
3640
  this.screen.current_record = null;
3633
3641
  this.screen.group.parent = null;
3634
- this.screen.display();
3635
3642
  this.screen.screen_container.hide_filter();
3636
- return;
3643
+ return this.screen.display();
3637
3644
  }
3638
3645
 
3639
3646
  var new_group = record.field_get_client(this.field_name);
@@ -3662,13 +3669,13 @@ function eval_pyson(value){
3662
3669
  this.screen.domain = domain;
3663
3670
  }
3664
3671
  this.screen.size_limit = size_limit;
3665
- this.screen.display();
3666
3672
  if (this.attributes.height !== undefined) {
3667
3673
  this.content
3668
3674
  .find('.treeview,.list-form').first()
3669
3675
  .css('min-height', this.attributes.height + 'px')
3670
3676
  .css('max-height', this.attributes.height + 'px');
3671
3677
  }
3678
+ return this.screen.display();
3672
3679
  });
3673
3680
  },
3674
3681
  focus: function() {
@@ -3968,9 +3975,7 @@ function eval_pyson(value){
3968
3975
  return prm;
3969
3976
  },
3970
3977
  set_value: function() {
3971
- if (this.screen.modified()) { // TODO check if required
3972
- this.view.screen.record_modified(false);
3973
- }
3978
+ this.screen.current_view.set_value();
3974
3979
  },
3975
3980
  _update_completion: function(text) {
3976
3981
  if (!this.record) {
@@ -4204,7 +4209,7 @@ function eval_pyson(value){
4204
4209
  display: function() {
4205
4210
  Sao.View.Form.Many2Many._super.display.call(this);
4206
4211
 
4207
- this.prm.done(() => {
4212
+ return this.prm.then(() => {
4208
4213
  var record = this.record;
4209
4214
  var field = this.field;
4210
4215
 
@@ -4212,21 +4217,20 @@ function eval_pyson(value){
4212
4217
  this.screen.new_group();
4213
4218
  this.screen.current_record = null;
4214
4219
  this.screen.group.parent = null;
4215
- this.screen.display();
4216
4220
  this.screen.screen_container.hide_filter();
4217
- return;
4221
+ return this.screen.display();
4218
4222
  }
4219
4223
  var new_group = record.field_get_client(this.field_name);
4220
4224
  if (new_group != this.screen.group) {
4221
4225
  this.screen.set_group(new_group);
4222
4226
  }
4223
- this.screen.display();
4224
4227
  if (this.attributes.height !== undefined) {
4225
4228
  this.content
4226
4229
  .find('.treeview,.list-form').first()
4227
4230
  .css('min-height', this.attributes.height + 'px')
4228
4231
  .css('max-height', this.attributes.height + 'px');
4229
4232
  }
4233
+ return this.screen.display();
4230
4234
  });
4231
4235
  },
4232
4236
  focus: function() {
package/src/view/tree.js CHANGED
@@ -2762,6 +2762,10 @@
2762
2762
  fields, false, false)) {
2763
2763
  var value = cell.prop('checked');
2764
2764
  this.field.set_client(record, value);
2765
+ if (record !== current_record) {
2766
+ // we can not rely on editable tree handler to save the row
2767
+ record.save();
2768
+ }
2765
2769
  } else {
2766
2770
  evt.preventDefault();
2767
2771
  }