tryton-sao 7.6.8 → 7.6.10

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.10 - 2025-11-02
3
+ ---------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+
6
+
7
+ Version 7.6.9 - 2025-10-20
8
+ --------------------------
9
+ * Bug fixes (see mercurial logs for details)
10
+ * Use sandboxed iframe to display document (issue14290)
11
+
2
12
  Version 7.6.8 - 2025-10-02
3
13
  --------------------------
4
14
  * Bug fixes (see mercurial logs for details)
@@ -9395,12 +9395,16 @@ html[theme="default"] .carousel-caption h6 {
9395
9395
  flex: 1;
9396
9396
  width: 100%;
9397
9397
  }
9398
+ #tabcontent > .tab-pane {
9399
+ width: 100%;
9400
+ }
9398
9401
  #tabcontent > .tab-pane > .panel {
9399
9402
  display: flex;
9400
9403
  flex-direction: column;
9401
9404
  flex: 1;
9402
9405
  margin-bottom: 5px;
9403
9406
  padding-bottom: 0;
9407
+ width: 100%;
9404
9408
  }
9405
9409
  #tabcontent > .tab-pane > .panel > .panel-body {
9406
9410
  display: flex;
@@ -9408,9 +9412,11 @@ html[theme="default"] .carousel-caption h6 {
9408
9412
  flex-direction: row;
9409
9413
  padding: 5px 0;
9410
9414
  min-height: 0;
9415
+ width: 100%;
9411
9416
  }
9412
9417
  #tabcontent > .tab-pane > .panel > .panel-body > div {
9413
9418
  display: inline-flex;
9419
+ width: 100%;
9414
9420
  }
9415
9421
  #tabcontent > .tab-pane > .panel > .panel-body > div:first-child {
9416
9422
  flex: 2;
@@ -9835,6 +9841,7 @@ img.icon {
9835
9841
  display: flex;
9836
9842
  flex-direction: column;
9837
9843
  flex: 1;
9844
+ width: 100%;
9838
9845
  }
9839
9846
  .filter-box {
9840
9847
  margin: 5px 0;
@@ -10469,9 +10476,22 @@ img.icon {
10469
10476
  min-width: 120px;
10470
10477
  }
10471
10478
  .form .form-document object,
10472
- .board .form-document object {
10479
+ .board .form-document object,
10480
+ .form .form-document img,
10481
+ .board .form-document img {
10473
10482
  object-fit: scale-down;
10474
10483
  object-position: center top;
10484
+ }
10485
+ .form .form-document iframe,
10486
+ .board .form-document iframe {
10487
+ border: 0;
10488
+ }
10489
+ .form .form-document object,
10490
+ .board .form-document object,
10491
+ .form .form-document iframe,
10492
+ .board .form-document iframe,
10493
+ .form .form-document img,
10494
+ .board .form-document img {
10475
10495
  max-width: 100%;
10476
10496
  min-height: 50vh;
10477
10497
  height: 100%;
@@ -10479,8 +10499,12 @@ img.icon {
10479
10499
  }
10480
10500
  @media screen and (max-width: 767px) {
10481
10501
  .form .form-document object,
10482
- .board .form-document object {
10483
- min-height: 25vh;
10502
+ .board .form-document object,
10503
+ .form .form-document iframe,
10504
+ .board .form-document iframe,
10505
+ .form .form-document img,
10506
+ .board .form-document img {
10507
+ min-height: 50vh;
10484
10508
  }
10485
10509
  }
10486
10510
  .form label,
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.6.8',
6
+ __version__: '7.6.10',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -149,6 +149,16 @@ var Sao = {
149
149
  }
150
150
  }
151
151
 
152
+ if (!Array.prototype.toReversed) {
153
+ Object.defineProperty(Array.prototype, 'toReversed', {
154
+ value: function toReversed() {
155
+ return this.slice().reverse();
156
+ },
157
+ writable: true,
158
+ configurable: true,
159
+ });
160
+ }
161
+
152
162
  Sao.setdefault = function(object, key, value) {
153
163
  if (!Object.prototype.hasOwnProperty.call(object, key)) {
154
164
  object[key] = value;
@@ -9107,7 +9117,7 @@ var Sao = {
9107
9117
  if (field.description.readonly) {
9108
9118
  continue;
9109
9119
  }
9110
- if (fname == this.group.exclude_field) {
9120
+ if ([this.group.exclude_field, this.group.parent_name].includes(fname)) {
9111
9121
  continue;
9112
9122
  }
9113
9123
  if (!field.validate(this, softvalidation, pre_validate)) {
@@ -19931,15 +19941,42 @@ function eval_pyson(value){
19931
19941
  'class': this.class_,
19932
19942
  });
19933
19943
 
19934
- this.object = jQuery('<object/>', {
19944
+ this.content = this._create_content().appendTo(this.el);
19945
+ },
19946
+ _create_content: function(mimetype, url) {
19947
+ let tag_name = 'iframe';
19948
+ if (mimetype) {
19949
+ if (mimetype.startsWith('image/')) {
19950
+ tag_name = 'img';
19951
+ } else if (mimetype == 'application/pdf') {
19952
+ tag_name = 'object';
19953
+ }
19954
+ }
19955
+ let content = jQuery(`<${tag_name}/>`, {
19935
19956
  'class': 'center-block',
19936
- }).appendTo(this.el);
19937
- if (attributes.height) {
19938
- this.object.css('height', parseInt(attributes.height, 10));
19957
+ });
19958
+ if (tag_name == 'iframe') {
19959
+ content.attr('sandbox', '');
19960
+ }
19961
+ if (this.attributes.height) {
19962
+ content.css('height', parseInt(this.attributes.height, 10));
19939
19963
  }
19940
- if (attributes.width) {
19941
- this.object.css('width', parseInt(attributes.width, 10));
19964
+ if (this.attributes.width) {
19965
+ content.css('width', parseInt(this.attributes.width, 10));
19942
19966
  }
19967
+ if (url) {
19968
+ // set onload before data/src to be always called
19969
+ content.get().onload = function() {
19970
+ this.onload = null;
19971
+ window.URL.revokeObjectURL(url);
19972
+ };
19973
+ if (tag_name== 'object') {
19974
+ content.attr('data', url);
19975
+ } else {
19976
+ content.attr('src', url);
19977
+ }
19978
+ }
19979
+ return content;
19943
19980
  },
19944
19981
  display: function() {
19945
19982
  Sao.View.Form.Document._super.display.call(this);
@@ -19955,34 +19992,30 @@ function eval_pyson(value){
19955
19992
  filename = filename_field.get_client(record);
19956
19993
  }
19957
19994
  data.done(data => {
19958
- var url, blob;
19959
19995
  if (record !== this.record) {
19960
19996
  return;
19961
19997
  }
19962
19998
  // in case onload was not yet triggered
19963
- window.URL.revokeObjectURL(this.object.attr('data'));
19999
+ let url = this.content.attr('data') ||
20000
+ this.content.attr('src');
20001
+ window.URL.revokeObjectURL(url);
20002
+ let mimetype;
19964
20003
  if (!data) {
19965
20004
  url = null;
19966
20005
  } else {
19967
- var mimetype = Sao.common.guess_mimetype(filename);
20006
+ mimetype = Sao.common.guess_mimetype(filename);
19968
20007
  if (mimetype == 'application/octet-binary') {
19969
20008
  mimetype = null;
19970
20009
  }
19971
- blob = new Blob([data], {
20010
+ let blob = new Blob([data], {
19972
20011
  'type': mimetype,
19973
20012
  });
19974
20013
  url = window.URL.createObjectURL(blob);
19975
20014
  }
19976
20015
  // duplicate object to force refresh on buggy browsers
19977
- const object = this.object.clone();
19978
- // set onload before data to be always called
19979
- object.get(0).onload = function() {
19980
- this.onload = null;
19981
- window.URL.revokeObjectURL(url);
19982
- };
19983
- object.attr('data', url);
19984
- this.object.replaceWith(object);
19985
- this.object = object;
20016
+ let content = this._create_content(mimetype, url);
20017
+ this.content.replaceWith(content);
20018
+ this.content = content;
19986
20019
  });
19987
20020
  },
19988
20021
  });
@@ -20407,7 +20440,7 @@ function eval_pyson(value){
20407
20440
 
20408
20441
  var value = field.get_client(record);
20409
20442
  var new_key_names = Object.keys(value).filter(
20410
- e => !this.fields[e]);
20443
+ e => !this.field.keys[e]);
20411
20444
 
20412
20445
  var prm;
20413
20446
  if (!jQuery.isEmptyObject(new_key_names)) {
@@ -21881,7 +21914,7 @@ function eval_pyson(value){
21881
21914
  this.display_size = Sao.config.display_size;
21882
21915
  }
21883
21916
  }
21884
- if (!this.display_size &
21917
+ if (!this.display_size &&
21885
21918
  (!jQuery.isEmptyObject(selected) ||
21886
21919
  !jQuery.isEmptyObject(expanded))) {
21887
21920
  this.display_size = Sao.config.display_size;
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.8",
5
+ "version": "7.6.10",
6
6
  "homepage": "https://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/model.js CHANGED
@@ -1334,7 +1334,7 @@
1334
1334
  if (field.description.readonly) {
1335
1335
  continue;
1336
1336
  }
1337
- if (fname == this.group.exclude_field) {
1337
+ if ([this.group.exclude_field, this.group.parent_name].includes(fname)) {
1338
1338
  continue;
1339
1339
  }
1340
1340
  if (!field.validate(this, softvalidation, pre_validate)) {
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.8',
6
+ __version__: '7.6.10',
7
7
  };
8
8
  /* eslint-enable no-redeclare */
9
9
 
@@ -149,6 +149,16 @@ var Sao = {
149
149
  }
150
150
  }
151
151
 
152
+ if (!Array.prototype.toReversed) {
153
+ Object.defineProperty(Array.prototype, 'toReversed', {
154
+ value: function toReversed() {
155
+ return this.slice().reverse();
156
+ },
157
+ writable: true,
158
+ configurable: true,
159
+ });
160
+ }
161
+
152
162
  Sao.setdefault = function(object, key, value) {
153
163
  if (!Object.prototype.hasOwnProperty.call(object, key)) {
154
164
  object[key] = value;
package/src/sao.less CHANGED
@@ -289,25 +289,32 @@ html[theme="default"] {
289
289
  flex: 1;
290
290
  width: 100%;
291
291
 
292
- > .tab-pane > .panel {
293
- display: flex;
294
- flex-direction: column;
295
- flex: 1;
296
- margin-bottom: 5px;
297
- padding-bottom: 0;
292
+ > .tab-pane {
293
+ width: 100%;
298
294
 
299
- > .panel-body {
295
+ > .panel {
300
296
  display: flex;
297
+ flex-direction: column;
301
298
  flex: 1;
302
- flex-direction: row;
303
- padding: 5px 0;
304
- min-height: 0;
299
+ margin-bottom: 5px;
300
+ padding-bottom: 0;
301
+ width: 100%;
302
+
303
+ > .panel-body {
304
+ display: flex;
305
+ flex: 1;
306
+ flex-direction: row;
307
+ padding: 5px 0;
308
+ min-height: 0;
309
+ width: 100%;
305
310
 
306
- > div {
307
- display: inline-flex;
311
+ > div {
312
+ display: inline-flex;
313
+ width: 100%;
308
314
 
309
- &:first-child {
310
- flex: 2;
315
+ &:first-child {
316
+ flex: 2;
317
+ }
311
318
  }
312
319
  }
313
320
  }
@@ -691,6 +698,7 @@ img.icon {
691
698
  display: flex;
692
699
  flex-direction: column;
693
700
  flex: 1;
701
+ width: 100%;
694
702
  }
695
703
 
696
704
  .filter-box {
@@ -1177,15 +1185,20 @@ img.icon {
1177
1185
  }
1178
1186
  }
1179
1187
  .form-document {
1180
- object {
1188
+ object, img {
1181
1189
  object-fit: scale-down;
1182
1190
  object-position: center top;
1191
+ }
1192
+ iframe {
1193
+ border: 0;
1194
+ }
1195
+ object, iframe, img {
1183
1196
  max-width: 100%;
1184
1197
  min-height: 50vh;
1185
1198
  height: 100%;
1186
1199
  width: 100%;
1187
1200
  @media screen and (max-width: @screen-xs-max) {
1188
- min-height: 25vh;
1201
+ min-height: 50vh;
1189
1202
  }
1190
1203
  }
1191
1204
  }
package/src/view/form.js CHANGED
@@ -4833,15 +4833,42 @@ function eval_pyson(value){
4833
4833
  'class': this.class_,
4834
4834
  });
4835
4835
 
4836
- this.object = jQuery('<object/>', {
4836
+ this.content = this._create_content().appendTo(this.el);
4837
+ },
4838
+ _create_content: function(mimetype, url) {
4839
+ let tag_name = 'iframe';
4840
+ if (mimetype) {
4841
+ if (mimetype.startsWith('image/')) {
4842
+ tag_name = 'img';
4843
+ } else if (mimetype == 'application/pdf') {
4844
+ tag_name = 'object';
4845
+ }
4846
+ }
4847
+ let content = jQuery(`<${tag_name}/>`, {
4837
4848
  'class': 'center-block',
4838
- }).appendTo(this.el);
4839
- if (attributes.height) {
4840
- this.object.css('height', parseInt(attributes.height, 10));
4849
+ });
4850
+ if (tag_name == 'iframe') {
4851
+ content.attr('sandbox', '');
4852
+ }
4853
+ if (this.attributes.height) {
4854
+ content.css('height', parseInt(this.attributes.height, 10));
4841
4855
  }
4842
- if (attributes.width) {
4843
- this.object.css('width', parseInt(attributes.width, 10));
4856
+ if (this.attributes.width) {
4857
+ content.css('width', parseInt(this.attributes.width, 10));
4844
4858
  }
4859
+ if (url) {
4860
+ // set onload before data/src to be always called
4861
+ content.get().onload = function() {
4862
+ this.onload = null;
4863
+ window.URL.revokeObjectURL(url);
4864
+ };
4865
+ if (tag_name== 'object') {
4866
+ content.attr('data', url);
4867
+ } else {
4868
+ content.attr('src', url);
4869
+ }
4870
+ }
4871
+ return content;
4845
4872
  },
4846
4873
  display: function() {
4847
4874
  Sao.View.Form.Document._super.display.call(this);
@@ -4857,34 +4884,30 @@ function eval_pyson(value){
4857
4884
  filename = filename_field.get_client(record);
4858
4885
  }
4859
4886
  data.done(data => {
4860
- var url, blob;
4861
4887
  if (record !== this.record) {
4862
4888
  return;
4863
4889
  }
4864
4890
  // in case onload was not yet triggered
4865
- window.URL.revokeObjectURL(this.object.attr('data'));
4891
+ let url = this.content.attr('data') ||
4892
+ this.content.attr('src');
4893
+ window.URL.revokeObjectURL(url);
4894
+ let mimetype;
4866
4895
  if (!data) {
4867
4896
  url = null;
4868
4897
  } else {
4869
- var mimetype = Sao.common.guess_mimetype(filename);
4898
+ mimetype = Sao.common.guess_mimetype(filename);
4870
4899
  if (mimetype == 'application/octet-binary') {
4871
4900
  mimetype = null;
4872
4901
  }
4873
- blob = new Blob([data], {
4902
+ let blob = new Blob([data], {
4874
4903
  'type': mimetype,
4875
4904
  });
4876
4905
  url = window.URL.createObjectURL(blob);
4877
4906
  }
4878
4907
  // duplicate object to force refresh on buggy browsers
4879
- const object = this.object.clone();
4880
- // set onload before data to be always called
4881
- object.get(0).onload = function() {
4882
- this.onload = null;
4883
- window.URL.revokeObjectURL(url);
4884
- };
4885
- object.attr('data', url);
4886
- this.object.replaceWith(object);
4887
- this.object = object;
4908
+ let content = this._create_content(mimetype, url);
4909
+ this.content.replaceWith(content);
4910
+ this.content = content;
4888
4911
  });
4889
4912
  },
4890
4913
  });
@@ -5309,7 +5332,7 @@ function eval_pyson(value){
5309
5332
 
5310
5333
  var value = field.get_client(record);
5311
5334
  var new_key_names = Object.keys(value).filter(
5312
- e => !this.fields[e]);
5335
+ e => !this.field.keys[e]);
5313
5336
 
5314
5337
  var prm;
5315
5338
  if (!jQuery.isEmptyObject(new_key_names)) {
package/src/view/tree.js CHANGED
@@ -889,7 +889,7 @@
889
889
  this.display_size = Sao.config.display_size;
890
890
  }
891
891
  }
892
- if (!this.display_size &
892
+ if (!this.display_size &&
893
893
  (!jQuery.isEmptyObject(selected) ||
894
894
  !jQuery.isEmptyObject(expanded))) {
895
895
  this.display_size = Sao.config.display_size;