tryton-sao 7.2.1 → 7.2.3

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.3 - 2024-07-01
3
+ --------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
7
+ Version 7.2.2 - 2024-06-15
8
+ --------------------------
9
+ * Bug fixes (see mercurial logs for details)
10
+
11
+
2
12
  Version 7.2.1 - 2024-05-01
3
13
  --------------------------
4
14
  * Bug fixes (see mercurial logs for details)
@@ -10066,10 +10066,14 @@ img.icon {
10066
10066
  min-height: 150px;
10067
10067
  max-height: 300px;
10068
10068
  }
10069
- .form .form-text > textarea,
10070
- .form .form-richtext > textarea,
10071
- .form .form-text .richtext,
10072
- .form .form-richtext .richtext {
10069
+ .form .form-text .input-group,
10070
+ .form .form-richtext .input-group {
10071
+ width: 100%;
10072
+ }
10073
+ .form .form-text .input-group textarea,
10074
+ .form .form-richtext .input-group textarea,
10075
+ .form .form-text .input-group .richtext,
10076
+ .form .form-richtext .input-group .richtext {
10073
10077
  height: 100%;
10074
10078
  line-height: 2.5ex;
10075
10079
  min-height: 12.5ex;
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.2.0',
6
+ __version__: '7.2.3',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -107,6 +107,35 @@ var Sao = {
107
107
  };
108
108
  }
109
109
 
110
+ if (!Set.prototype.intersection) {
111
+ Set.prototype.intersection = function(other) {
112
+ if (this === null) {
113
+ throw new TypeError();
114
+ }
115
+ const result = new Set();
116
+ for (const key of other.keys()) {
117
+ if (this.has(key)) {
118
+ result.add(key)
119
+ }
120
+ }
121
+ return result;
122
+ }
123
+ }
124
+
125
+ if (!Set.prototype.isSubsetOf) {
126
+ Set.prototype.isSubsetOf = function(other) {
127
+ if (this === null) {
128
+ throw new TypeError();
129
+ }
130
+ for (const key of this.keys()) {
131
+ if (!other.has(key)) {
132
+ return false;
133
+ }
134
+ }
135
+ return true;
136
+ }
137
+ }
138
+
110
139
  Sao.setdefault = function(object, key, value) {
111
140
  if (!Object.prototype.hasOwnProperty.call(object, key)) {
112
141
  object[key] = value;
@@ -3494,16 +3523,8 @@ var Sao = {
3494
3523
  ];
3495
3524
 
3496
3525
  Sao.common.date_format = function(format) {
3497
- if (jQuery.isEmptyObject(format)) {
3498
- format = '%x';
3499
- if (Sao.Session.current_session) {
3500
- var context = Sao.Session.current_session.context;
3501
- if (context.locale && context.locale.date) {
3502
- format = context.locale.date;
3503
- }
3504
- }
3505
- }
3506
- return Sao.common.moment_format(format);
3526
+ return Sao.common.moment_format(
3527
+ format || Sao.i18n.locale.date || '%x');
3507
3528
  };
3508
3529
 
3509
3530
  Sao.common.format_time = function(format, date) {
@@ -8298,6 +8319,7 @@ var Sao = {
8298
8319
  views = this.model.fields[name].views;
8299
8320
  }
8300
8321
  var fields = {};
8322
+ var views_operator;
8301
8323
  if (loading == 'eager') {
8302
8324
  for (fname in this.model.fields) {
8303
8325
  field = this.model.fields[fname];
@@ -8305,17 +8327,19 @@ var Sao = {
8305
8327
  fields[fname] = field;
8306
8328
  }
8307
8329
  }
8330
+ views_operator = views.isSubsetOf.bind(views);
8308
8331
  } else {
8309
8332
  fields = this.model.fields;
8333
+ views_operator = function(view) {
8334
+ return Boolean(this.intersection(view).size);
8335
+ }.bind(views);
8310
8336
  }
8311
8337
  var fnames = [];
8312
8338
  for (fname in fields) {
8313
8339
  field = fields[fname];
8314
8340
  if (!(fname in this._loaded) &&
8315
8341
  (!views.size ||
8316
- Sao.common.intersect(
8317
- Array.from(views).sort(),
8318
- Array.from(field.views).sort()))) {
8342
+ views_operator(new Set(field.views)))) {
8319
8343
  fnames.push(fname);
8320
8344
  }
8321
8345
  }
@@ -11869,7 +11893,7 @@ var Sao = {
11869
11893
  this.refresh_resources(true);
11870
11894
  });
11871
11895
  for (const file of files) {
11872
- Sao.common.get_file_data(file, window_.add_data);
11896
+ Sao.common.get_file_data(file, window_.add_data.bind(window_));
11873
11897
  }
11874
11898
  jQuery.when.apply(jQuery, uris).then(function() {
11875
11899
  function empty(value) {
@@ -13123,9 +13147,7 @@ var Sao = {
13123
13147
  this.views = [];
13124
13148
  this.views_preload = attributes.views_preload || {};
13125
13149
  this.exclude_field = attributes.exclude_field;
13126
- this.new_group(attributes.context || {});
13127
13150
  this.current_view = null;
13128
- this.current_record = null;
13129
13151
  this.domain = attributes.domain || [];
13130
13152
  this.context_domain = attributes.context_domain;
13131
13153
  this.size_limit = null;
@@ -13137,11 +13159,14 @@ var Sao = {
13137
13159
  this._current_domain = [];
13138
13160
  this.offset = 0;
13139
13161
  this.order = this.default_order = attributes.order;
13162
+ this.readonly = this.attributes.readonly || false;
13140
13163
  var access = Sao.common.MODELACCESS.get(model_name);
13141
13164
  if (!(access.write || access.create)) {
13142
- this.attributes.readonly = true;
13165
+ this.readonly = true;
13143
13166
  }
13144
13167
  this.search_count = 0;
13168
+ this.new_group(attributes.context || {});
13169
+ this.current_record = null;
13145
13170
  this.screen_container = new Sao.ScreenContainer(
13146
13171
  attributes.tab_domain);
13147
13172
  this.breadcrumb = attributes.breadcrumb || [];
@@ -13184,7 +13209,10 @@ var Sao = {
13184
13209
  var readonly_records = this.selected_records.some(function(r) {
13185
13210
  return r.readonly;
13186
13211
  });
13187
- return this.attributes.readonly || readonly_records;
13212
+ return this.__readonly || readonly_records;
13213
+ },
13214
+ set readonly(value) {
13215
+ this.__readonly = value;
13188
13216
  },
13189
13217
  get deletable() {
13190
13218
  return this.selected_records.every(function(r) {
@@ -13562,7 +13590,7 @@ var Sao = {
13562
13590
  context = this.context;
13563
13591
  }
13564
13592
  var group = new Sao.Group(this.model, context, []);
13565
- group.readonly = this.attributes.readonly;
13593
+ group.readonly = this.__readonly;
13566
13594
  this.set_group(group);
13567
13595
  },
13568
13596
  record_modified: function(display=true) {
@@ -17122,10 +17150,13 @@ function eval_pyson(value){
17122
17150
  this.el = jQuery('<div/>', {
17123
17151
  'class': this.class_
17124
17152
  });
17153
+ this.group = jQuery('<div/>', {
17154
+ 'class': 'input-group',
17155
+ }).appendTo(this.el);
17125
17156
  this.input = this.labelled = jQuery('<textarea/>', {
17126
17157
  'class': 'form-control input-sm mousetrap',
17127
17158
  'name': attributes.name,
17128
- }).appendTo(this.el);
17159
+ }).appendTo(this.group);
17129
17160
  this.input.change(this.focus_out.bind(this));
17130
17161
  this.input.on('keydown', this.send_modified.bind(this));
17131
17162
  if (this.attributes.translate) {
@@ -17136,7 +17167,7 @@ function eval_pyson(value){
17136
17167
  'title': Sao.i18n.gettext("Translate"),
17137
17168
  }).appendTo(jQuery('<span/>', {
17138
17169
  'class': 'input-group-btn'
17139
- }).appendTo(this.el));
17170
+ }).appendTo(this.group));
17140
17171
  button.append(
17141
17172
  Sao.common.ICONFACTORY.get_icon_img('tryton-translate'));
17142
17173
  button.click(this.translate.bind(this));
@@ -17212,13 +17243,16 @@ function eval_pyson(value){
17212
17243
  'class': 'panel-heading',
17213
17244
  }).appendTo(this.el));
17214
17245
  }
17215
- this.input = this.labelled = jQuery('<div/>', {
17216
- 'class': 'richtext mousetrap',
17217
- 'contenteditable': true
17246
+ this.group = jQuery('<div/>', {
17247
+ 'class': 'input-group',
17218
17248
  }).appendTo(jQuery('<div/>', {
17219
- 'class': 'panel-body'
17249
+ 'class': 'panel-body',
17220
17250
  }).appendTo(this.el));
17221
- this.el.focusout(this.focus_out.bind(this));
17251
+ this.input = this.labelled = jQuery('<div/>', {
17252
+ 'class': 'richtext mousetrap',
17253
+ 'contenteditable': true,
17254
+ }).appendTo(this.group);
17255
+ this.group.focusout(this.focus_out.bind(this));
17222
17256
  if (this.attributes.translate) {
17223
17257
  var button = jQuery('<button/>', {
17224
17258
  'class': 'btn btn-default btn-sm form-control',
@@ -17227,7 +17261,7 @@ function eval_pyson(value){
17227
17261
  'title': Sao.i18n.gettext("Translate"),
17228
17262
  }).appendTo(jQuery('<span/>', {
17229
17263
  'class': 'input-group-btn',
17230
- }).appendTo(this.el));
17264
+ }).appendTo(this.group));
17231
17265
  button.append(
17232
17266
  Sao.common.ICONFACTORY.get_icon_img('tryton-translate'));
17233
17267
  button.click(this.translate.bind(this));
@@ -17760,7 +17794,7 @@ function eval_pyson(value){
17760
17794
  _update_completion: function(text) {
17761
17795
  var record = this.record;
17762
17796
  if (!record) {
17763
- return;
17797
+ return jQuery.when();
17764
17798
  }
17765
17799
  var field = this.field;
17766
17800
  var value = field.get(record);
@@ -18643,7 +18677,7 @@ function eval_pyson(value){
18643
18677
  },
18644
18678
  _update_completion: function(text) {
18645
18679
  if (!this.record) {
18646
- return;
18680
+ return jQuery.when();
18647
18681
  }
18648
18682
  var model = this.attributes.relation;
18649
18683
  var domain = this.field.get_domain(this.record);
@@ -19029,7 +19063,7 @@ function eval_pyson(value){
19029
19063
  },
19030
19064
  _update_completion: function(text) {
19031
19065
  if (!this.record) {
19032
- return;
19066
+ return jQuery.when();
19033
19067
  }
19034
19068
  var model = this.attributes.relation;
19035
19069
  var domain = this.field.get_domain(this.record);
@@ -19995,10 +20029,10 @@ function eval_pyson(value){
19995
20029
  },
19996
20030
  _update_completion: function(text) {
19997
20031
  if (this.wid_text.prop('disabled')) {
19998
- return;
20032
+ return jQuery.when();
19999
20033
  }
20000
20034
  if (!this.record) {
20001
- return;
20035
+ return jQuery.when();
20002
20036
  }
20003
20037
  return Sao.common.update_completion(
20004
20038
  this.wid_text, this.record, this.field, this.schema_model);
@@ -21185,7 +21219,7 @@ function eval_pyson(value){
21185
21219
  },
21186
21220
  display: function(selected, expanded) {
21187
21221
  var current_record = this.record;
21188
- if (jQuery.isEmptyObject(selected)) {
21222
+ if (jQuery.isEmptyObject(selected) && current_record) {
21189
21223
  selected = this.get_selected_paths();
21190
21224
  if (this.selection.prop('checked') &&
21191
21225
  !this.selection.prop('indeterminate')) {
@@ -21194,16 +21228,12 @@ function eval_pyson(value){
21194
21228
  selected.push([record.id]);
21195
21229
  }
21196
21230
  } else {
21197
- if (current_record) {
21198
- var current_path = current_record.get_path(this.group);
21199
- current_path = current_path.map(function(e) {
21200
- return e[1];
21201
- });
21202
- if (!Sao.common.contains(selected, current_path)) {
21203
- selected = [current_path];
21204
- }
21205
- } else if (!current_record) {
21206
- selected = [];
21231
+ var current_path = current_record.get_path(this.group);
21232
+ current_path = current_path.map(function(e) {
21233
+ return e[1];
21234
+ });
21235
+ if (!Sao.common.contains(selected, current_path)) {
21236
+ selected = [current_path];
21207
21237
  }
21208
21238
  }
21209
21239
  }
@@ -21784,7 +21814,7 @@ function eval_pyson(value){
21784
21814
  if (this.editable && new_) {
21785
21815
  td.trigger('click');
21786
21816
  }
21787
- td.find(':input,[tabindex=0]').focus();
21817
+ Sao.common.find_focusable_child(td).focus();
21788
21818
  }
21789
21819
  }
21790
21820
  };
@@ -24402,17 +24432,26 @@ function eval_pyson(value){
24402
24432
  if (!this.start && !this.end) {
24403
24433
  return [['id', '=', -1]];
24404
24434
  }
24405
- var first_datetime = Sao.DateTime(this.start);
24406
- var last_datetime = Sao.DateTime(this.end);
24435
+ var start = Sao.DateTime(this.start);
24436
+ var end = Sao.DateTime(this.end);
24407
24437
  var dtstart = this.attributes.dtstart;
24408
24438
  var dtend = this.attributes.dtend || dtstart;
24409
- return ['OR',
24410
- ['AND', [dtstart, '>=', first_datetime],
24411
- [dtstart, '<', last_datetime]],
24412
- ['AND', [dtend, '>=', first_datetime],
24413
- [dtend, '<', last_datetime]],
24414
- ['AND', [dtstart, '<', first_datetime],
24415
- [dtend, '>', last_datetime]]];
24439
+ var fields = this.screen.model.fields;
24440
+ if (fields[dtstart].description.type == 'date') {
24441
+ start = start.todate();
24442
+ }
24443
+ if (fields[dtend].description.type == 'date') {
24444
+ end = end.todate();
24445
+ }
24446
+ return [
24447
+ [dtstart, '!=', null],
24448
+ [dtend, '!=', null],
24449
+ ['OR',
24450
+ ['AND', [dtstart, '>=', start], [dtstart, '<', end]],
24451
+ ['AND', [dtend, '>=', start], [dtend, '<', end]],
24452
+ ['AND', [dtstart, '<', start], [dtend, '>', end]],
24453
+ ],
24454
+ ];
24416
24455
  },
24417
24456
  get_displayed_period: function(){
24418
24457
  var DatesPeriod = [];
@@ -25047,7 +25086,7 @@ function eval_pyson(value){
25047
25086
  }
25048
25087
  });
25049
25088
 
25050
- var readonly = this.screen.readonly || this.screen.group.readonly;
25089
+ var readonly = this.screen.group.readonly;
25051
25090
 
25052
25091
  this.but_ok = null;
25053
25092
  this.but_new = null;
@@ -25274,7 +25313,7 @@ function eval_pyson(value){
25274
25313
  var name = '_';
25275
25314
  var access = Sao.common.MODELACCESS.get(this.screen.model_name);
25276
25315
  var deletable = this.screen.deletable;
25277
- var readonly = this.screen.readonly || this.screen.group.readonly;
25316
+ var readonly = this.screen.group.readonly;
25278
25317
  if (position >= 1) {
25279
25318
  name = position;
25280
25319
  if (this.domain) {
@@ -25282,10 +25321,12 @@ function eval_pyson(value){
25282
25321
  }
25283
25322
  this.but_next.prop('disabled', position >= size);
25284
25323
  this.but_previous.prop('disabled', position <= 1);
25285
- if (access.delete && !readonly && deletable) {
25286
- this.but_del.prop('disabled', false);
25287
- this.but_undel.prop('disabled', false);
25288
- }
25324
+ this.but_del.prop(
25325
+ 'disabled',
25326
+ readonly ||
25327
+ !access.delete ||
25328
+ !deletable);
25329
+ this.but_undel.prop('disabled', readonly);
25289
25330
  } else {
25290
25331
  this.but_del.prop('disabled', true);
25291
25332
  this.but_undel.prop('disabled', true);
@@ -25358,7 +25399,7 @@ function eval_pyson(value){
25358
25399
  response: function(response_id) {
25359
25400
  var result;
25360
25401
  this.screen.current_view.set_value();
25361
- var readonly = this.screen.readonly || this.screen.group.readonly;
25402
+ var readonly = this.screen.group.readonly;
25362
25403
  if (~['RESPONSE_OK', 'RESPONSE_ACCEPT'].indexOf(response_id) &&
25363
25404
  !readonly &&
25364
25405
  this.screen.current_record) {
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.1",
5
+ "version": "7.2.3",
6
6
  "homepage": "http://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/common.js CHANGED
@@ -228,16 +228,8 @@
228
228
  ];
229
229
 
230
230
  Sao.common.date_format = function(format) {
231
- if (jQuery.isEmptyObject(format)) {
232
- format = '%x';
233
- if (Sao.Session.current_session) {
234
- var context = Sao.Session.current_session.context;
235
- if (context.locale && context.locale.date) {
236
- format = context.locale.date;
237
- }
238
- }
239
- }
240
- return Sao.common.moment_format(format);
231
+ return Sao.common.moment_format(
232
+ format || Sao.i18n.locale.date || '%x');
241
233
  };
242
234
 
243
235
  Sao.common.format_time = function(format, date) {
package/src/model.js CHANGED
@@ -681,6 +681,7 @@
681
681
  views = this.model.fields[name].views;
682
682
  }
683
683
  var fields = {};
684
+ var views_operator;
684
685
  if (loading == 'eager') {
685
686
  for (fname in this.model.fields) {
686
687
  field = this.model.fields[fname];
@@ -688,17 +689,19 @@
688
689
  fields[fname] = field;
689
690
  }
690
691
  }
692
+ views_operator = views.isSubsetOf.bind(views);
691
693
  } else {
692
694
  fields = this.model.fields;
695
+ views_operator = function(view) {
696
+ return Boolean(this.intersection(view).size);
697
+ }.bind(views);
693
698
  }
694
699
  var fnames = [];
695
700
  for (fname in fields) {
696
701
  field = fields[fname];
697
702
  if (!(fname in this._loaded) &&
698
703
  (!views.size ||
699
- Sao.common.intersect(
700
- Array.from(views).sort(),
701
- Array.from(field.views).sort()))) {
704
+ views_operator(new Set(field.views)))) {
702
705
  fnames.push(fname);
703
706
  }
704
707
  }
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.0',
6
+ __version__: '7.2.3',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -107,6 +107,35 @@ var Sao = {
107
107
  };
108
108
  }
109
109
 
110
+ if (!Set.prototype.intersection) {
111
+ Set.prototype.intersection = function(other) {
112
+ if (this === null) {
113
+ throw new TypeError();
114
+ }
115
+ const result = new Set();
116
+ for (const key of other.keys()) {
117
+ if (this.has(key)) {
118
+ result.add(key)
119
+ }
120
+ }
121
+ return result;
122
+ }
123
+ }
124
+
125
+ if (!Set.prototype.isSubsetOf) {
126
+ Set.prototype.isSubsetOf = function(other) {
127
+ if (this === null) {
128
+ throw new TypeError();
129
+ }
130
+ for (const key of this.keys()) {
131
+ if (!other.has(key)) {
132
+ return false;
133
+ }
134
+ }
135
+ return true;
136
+ }
137
+ }
138
+
110
139
  Sao.setdefault = function(object, key, value) {
111
140
  if (!Object.prototype.hasOwnProperty.call(object, key)) {
112
141
  object[key] = value;
package/src/sao.less CHANGED
@@ -876,12 +876,16 @@ img.icon {
876
876
  }
877
877
  }
878
878
  .form-text, .form-richtext {
879
- > textarea, .richtext {
880
- height: 100%;
881
- line-height: 2.5ex;
882
- min-height: 12.5ex;
883
- overflow: auto;
884
- resize: vertical;
879
+ .input-group {
880
+ width: 100%;
881
+
882
+ textarea, .richtext {
883
+ height: 100%;
884
+ line-height: 2.5ex;
885
+ min-height: 12.5ex;
886
+ overflow: auto;
887
+ resize: vertical;
888
+ }
885
889
  }
886
890
  }
887
891
  .form-richtext {
package/src/screen.js CHANGED
@@ -794,9 +794,7 @@
794
794
  this.views = [];
795
795
  this.views_preload = attributes.views_preload || {};
796
796
  this.exclude_field = attributes.exclude_field;
797
- this.new_group(attributes.context || {});
798
797
  this.current_view = null;
799
- this.current_record = null;
800
798
  this.domain = attributes.domain || [];
801
799
  this.context_domain = attributes.context_domain;
802
800
  this.size_limit = null;
@@ -808,11 +806,14 @@
808
806
  this._current_domain = [];
809
807
  this.offset = 0;
810
808
  this.order = this.default_order = attributes.order;
809
+ this.readonly = this.attributes.readonly || false;
811
810
  var access = Sao.common.MODELACCESS.get(model_name);
812
811
  if (!(access.write || access.create)) {
813
- this.attributes.readonly = true;
812
+ this.readonly = true;
814
813
  }
815
814
  this.search_count = 0;
815
+ this.new_group(attributes.context || {});
816
+ this.current_record = null;
816
817
  this.screen_container = new Sao.ScreenContainer(
817
818
  attributes.tab_domain);
818
819
  this.breadcrumb = attributes.breadcrumb || [];
@@ -855,7 +856,10 @@
855
856
  var readonly_records = this.selected_records.some(function(r) {
856
857
  return r.readonly;
857
858
  });
858
- return this.attributes.readonly || readonly_records;
859
+ return this.__readonly || readonly_records;
860
+ },
861
+ set readonly(value) {
862
+ this.__readonly = value;
859
863
  },
860
864
  get deletable() {
861
865
  return this.selected_records.every(function(r) {
@@ -1233,7 +1237,7 @@
1233
1237
  context = this.context;
1234
1238
  }
1235
1239
  var group = new Sao.Group(this.model, context, []);
1236
- group.readonly = this.attributes.readonly;
1240
+ group.readonly = this.__readonly;
1237
1241
  this.set_group(group);
1238
1242
  },
1239
1243
  record_modified: function(display=true) {
package/src/tab.js CHANGED
@@ -1254,7 +1254,7 @@
1254
1254
  this.refresh_resources(true);
1255
1255
  });
1256
1256
  for (const file of files) {
1257
- Sao.common.get_file_data(file, window_.add_data);
1257
+ Sao.common.get_file_data(file, window_.add_data.bind(window_));
1258
1258
  }
1259
1259
  jQuery.when.apply(jQuery, uris).then(function() {
1260
1260
  function empty(value) {
@@ -346,17 +346,26 @@
346
346
  if (!this.start && !this.end) {
347
347
  return [['id', '=', -1]];
348
348
  }
349
- var first_datetime = Sao.DateTime(this.start);
350
- var last_datetime = Sao.DateTime(this.end);
349
+ var start = Sao.DateTime(this.start);
350
+ var end = Sao.DateTime(this.end);
351
351
  var dtstart = this.attributes.dtstart;
352
352
  var dtend = this.attributes.dtend || dtstart;
353
- return ['OR',
354
- ['AND', [dtstart, '>=', first_datetime],
355
- [dtstart, '<', last_datetime]],
356
- ['AND', [dtend, '>=', first_datetime],
357
- [dtend, '<', last_datetime]],
358
- ['AND', [dtstart, '<', first_datetime],
359
- [dtend, '>', last_datetime]]];
353
+ var fields = this.screen.model.fields;
354
+ if (fields[dtstart].description.type == 'date') {
355
+ start = start.todate();
356
+ }
357
+ if (fields[dtend].description.type == 'date') {
358
+ end = end.todate();
359
+ }
360
+ return [
361
+ [dtstart, '!=', null],
362
+ [dtend, '!=', null],
363
+ ['OR',
364
+ ['AND', [dtstart, '>=', start], [dtstart, '<', end]],
365
+ ['AND', [dtend, '>=', start], [dtend, '<', end]],
366
+ ['AND', [dtstart, '<', start], [dtend, '>', end]],
367
+ ],
368
+ ];
360
369
  },
361
370
  get_displayed_period: function(){
362
371
  var DatesPeriod = [];
package/src/view/form.js CHANGED
@@ -2323,10 +2323,13 @@ function eval_pyson(value){
2323
2323
  this.el = jQuery('<div/>', {
2324
2324
  'class': this.class_
2325
2325
  });
2326
+ this.group = jQuery('<div/>', {
2327
+ 'class': 'input-group',
2328
+ }).appendTo(this.el);
2326
2329
  this.input = this.labelled = jQuery('<textarea/>', {
2327
2330
  'class': 'form-control input-sm mousetrap',
2328
2331
  'name': attributes.name,
2329
- }).appendTo(this.el);
2332
+ }).appendTo(this.group);
2330
2333
  this.input.change(this.focus_out.bind(this));
2331
2334
  this.input.on('keydown', this.send_modified.bind(this));
2332
2335
  if (this.attributes.translate) {
@@ -2337,7 +2340,7 @@ function eval_pyson(value){
2337
2340
  'title': Sao.i18n.gettext("Translate"),
2338
2341
  }).appendTo(jQuery('<span/>', {
2339
2342
  'class': 'input-group-btn'
2340
- }).appendTo(this.el));
2343
+ }).appendTo(this.group));
2341
2344
  button.append(
2342
2345
  Sao.common.ICONFACTORY.get_icon_img('tryton-translate'));
2343
2346
  button.click(this.translate.bind(this));
@@ -2413,13 +2416,16 @@ function eval_pyson(value){
2413
2416
  'class': 'panel-heading',
2414
2417
  }).appendTo(this.el));
2415
2418
  }
2416
- this.input = this.labelled = jQuery('<div/>', {
2417
- 'class': 'richtext mousetrap',
2418
- 'contenteditable': true
2419
+ this.group = jQuery('<div/>', {
2420
+ 'class': 'input-group',
2419
2421
  }).appendTo(jQuery('<div/>', {
2420
- 'class': 'panel-body'
2422
+ 'class': 'panel-body',
2421
2423
  }).appendTo(this.el));
2422
- this.el.focusout(this.focus_out.bind(this));
2424
+ this.input = this.labelled = jQuery('<div/>', {
2425
+ 'class': 'richtext mousetrap',
2426
+ 'contenteditable': true,
2427
+ }).appendTo(this.group);
2428
+ this.group.focusout(this.focus_out.bind(this));
2423
2429
  if (this.attributes.translate) {
2424
2430
  var button = jQuery('<button/>', {
2425
2431
  'class': 'btn btn-default btn-sm form-control',
@@ -2428,7 +2434,7 @@ function eval_pyson(value){
2428
2434
  'title': Sao.i18n.gettext("Translate"),
2429
2435
  }).appendTo(jQuery('<span/>', {
2430
2436
  'class': 'input-group-btn',
2431
- }).appendTo(this.el));
2437
+ }).appendTo(this.group));
2432
2438
  button.append(
2433
2439
  Sao.common.ICONFACTORY.get_icon_img('tryton-translate'));
2434
2440
  button.click(this.translate.bind(this));
@@ -2961,7 +2967,7 @@ function eval_pyson(value){
2961
2967
  _update_completion: function(text) {
2962
2968
  var record = this.record;
2963
2969
  if (!record) {
2964
- return;
2970
+ return jQuery.when();
2965
2971
  }
2966
2972
  var field = this.field;
2967
2973
  var value = field.get(record);
@@ -3844,7 +3850,7 @@ function eval_pyson(value){
3844
3850
  },
3845
3851
  _update_completion: function(text) {
3846
3852
  if (!this.record) {
3847
- return;
3853
+ return jQuery.when();
3848
3854
  }
3849
3855
  var model = this.attributes.relation;
3850
3856
  var domain = this.field.get_domain(this.record);
@@ -4230,7 +4236,7 @@ function eval_pyson(value){
4230
4236
  },
4231
4237
  _update_completion: function(text) {
4232
4238
  if (!this.record) {
4233
- return;
4239
+ return jQuery.when();
4234
4240
  }
4235
4241
  var model = this.attributes.relation;
4236
4242
  var domain = this.field.get_domain(this.record);
@@ -5196,10 +5202,10 @@ function eval_pyson(value){
5196
5202
  },
5197
5203
  _update_completion: function(text) {
5198
5204
  if (this.wid_text.prop('disabled')) {
5199
- return;
5205
+ return jQuery.when();
5200
5206
  }
5201
5207
  if (!this.record) {
5202
- return;
5208
+ return jQuery.when();
5203
5209
  }
5204
5210
  return Sao.common.update_completion(
5205
5211
  this.wid_text, this.record, this.field, this.schema_model);
package/src/view/tree.js CHANGED
@@ -728,7 +728,7 @@
728
728
  },
729
729
  display: function(selected, expanded) {
730
730
  var current_record = this.record;
731
- if (jQuery.isEmptyObject(selected)) {
731
+ if (jQuery.isEmptyObject(selected) && current_record) {
732
732
  selected = this.get_selected_paths();
733
733
  if (this.selection.prop('checked') &&
734
734
  !this.selection.prop('indeterminate')) {
@@ -737,16 +737,12 @@
737
737
  selected.push([record.id]);
738
738
  }
739
739
  } else {
740
- if (current_record) {
741
- var current_path = current_record.get_path(this.group);
742
- current_path = current_path.map(function(e) {
743
- return e[1];
744
- });
745
- if (!Sao.common.contains(selected, current_path)) {
746
- selected = [current_path];
747
- }
748
- } else if (!current_record) {
749
- selected = [];
740
+ var current_path = current_record.get_path(this.group);
741
+ current_path = current_path.map(function(e) {
742
+ return e[1];
743
+ });
744
+ if (!Sao.common.contains(selected, current_path)) {
745
+ selected = [current_path];
750
746
  }
751
747
  }
752
748
  }
@@ -1327,7 +1323,7 @@
1327
1323
  if (this.editable && new_) {
1328
1324
  td.trigger('click');
1329
1325
  }
1330
- td.find(':input,[tabindex=0]').focus();
1326
+ Sao.common.find_focusable_child(td).focus();
1331
1327
  }
1332
1328
  }
1333
1329
  };
package/src/window.js CHANGED
@@ -179,7 +179,7 @@
179
179
  }
180
180
  });
181
181
 
182
- var readonly = this.screen.readonly || this.screen.group.readonly;
182
+ var readonly = this.screen.group.readonly;
183
183
 
184
184
  this.but_ok = null;
185
185
  this.but_new = null;
@@ -406,7 +406,7 @@
406
406
  var name = '_';
407
407
  var access = Sao.common.MODELACCESS.get(this.screen.model_name);
408
408
  var deletable = this.screen.deletable;
409
- var readonly = this.screen.readonly || this.screen.group.readonly;
409
+ var readonly = this.screen.group.readonly;
410
410
  if (position >= 1) {
411
411
  name = position;
412
412
  if (this.domain) {
@@ -414,10 +414,12 @@
414
414
  }
415
415
  this.but_next.prop('disabled', position >= size);
416
416
  this.but_previous.prop('disabled', position <= 1);
417
- if (access.delete && !readonly && deletable) {
418
- this.but_del.prop('disabled', false);
419
- this.but_undel.prop('disabled', false);
420
- }
417
+ this.but_del.prop(
418
+ 'disabled',
419
+ readonly ||
420
+ !access.delete ||
421
+ !deletable);
422
+ this.but_undel.prop('disabled', readonly);
421
423
  } else {
422
424
  this.but_del.prop('disabled', true);
423
425
  this.but_undel.prop('disabled', true);
@@ -490,7 +492,7 @@
490
492
  response: function(response_id) {
491
493
  var result;
492
494
  this.screen.current_view.set_value();
493
- var readonly = this.screen.readonly || this.screen.group.readonly;
495
+ var readonly = this.screen.group.readonly;
494
496
  if (~['RESPONSE_OK', 'RESPONSE_ACCEPT'].indexOf(response_id) &&
495
497
  !readonly &&
496
498
  this.screen.current_record) {