tryton-sao 7.4.18 → 7.4.19

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.4.19 - 2025-10-20
3
+ ---------------------------
4
+ * Bug fixes (see mercurial logs for details)
5
+ * Use sandboxed iframe to display document (issue14290)
6
+
2
7
  Version 7.4.18 - 2025-10-02
3
8
  ---------------------------
4
9
  * Bug fixes (see mercurial logs for details)
@@ -10271,17 +10271,34 @@ img.icon {
10271
10271
  min-width: 120px;
10272
10272
  }
10273
10273
  .form .form-document object,
10274
- .board .form-document object {
10274
+ .board .form-document object,
10275
+ .form .form-document img,
10276
+ .board .form-document img {
10275
10277
  object-fit: scale-down;
10276
10278
  object-position: center top;
10279
+ }
10280
+ .form .form-document iframe,
10281
+ .board .form-document iframe {
10282
+ border: 0;
10283
+ }
10284
+ .form .form-document object,
10285
+ .board .form-document object,
10286
+ .form .form-document iframe,
10287
+ .board .form-document iframe,
10288
+ .form .form-document img,
10289
+ .board .form-document img {
10277
10290
  width: 100%;
10278
10291
  min-height: 50vh;
10279
10292
  height: 100%;
10280
10293
  }
10281
10294
  @media screen and (max-width: 767px) {
10282
10295
  .form .form-document object,
10283
- .board .form-document object {
10284
- min-height: 25vh;
10296
+ .board .form-document object,
10297
+ .form .form-document iframe,
10298
+ .board .form-document iframe,
10299
+ .form .form-document img,
10300
+ .board .form-document img {
10301
+ min-height: 50vh;
10285
10302
  }
10286
10303
  }
10287
10304
  .form label,
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.4.18',
6
+ __version__: '7.4.19',
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;
@@ -19731,15 +19741,42 @@ function eval_pyson(value){
19731
19741
  'class': this.class_,
19732
19742
  });
19733
19743
 
19734
- this.object = jQuery('<object/>', {
19744
+ this.content = this._create_content().appendTo(this.el);
19745
+ },
19746
+ _create_content: function(mimetype, url) {
19747
+ let tag_name = 'iframe';
19748
+ if (mimetype) {
19749
+ if (mimetype.startsWith('image/')) {
19750
+ tag_name = 'img';
19751
+ } else if (mimetype == 'application/pdf') {
19752
+ tag_name = 'object';
19753
+ }
19754
+ }
19755
+ let content = jQuery(`<${tag_name}/>`, {
19735
19756
  'class': 'center-block',
19736
- }).appendTo(this.el);
19737
- if (attributes.height) {
19738
- this.object.css('height', parseInt(attributes.height, 10));
19757
+ });
19758
+ if (tag_name == 'iframe') {
19759
+ content.attr('sandbox', '');
19739
19760
  }
19740
- if (attributes.width) {
19741
- this.object.css('width', parseInt(attributes.width, 10));
19761
+ if (this.attributes.height) {
19762
+ content.css('height', parseInt(this.attributes.height, 10));
19742
19763
  }
19764
+ if (this.attributes.width) {
19765
+ content.css('width', parseInt(this.attributes.width, 10));
19766
+ }
19767
+ if (url) {
19768
+ // set onload before data/src to be always called
19769
+ content.get().onload = function() {
19770
+ this.onload = null;
19771
+ window.URL.revokeObjectURL(url);
19772
+ };
19773
+ if (tag_name== 'object') {
19774
+ content.attr('data', url);
19775
+ } else {
19776
+ content.attr('src', url);
19777
+ }
19778
+ }
19779
+ return content;
19743
19780
  },
19744
19781
  display: function() {
19745
19782
  Sao.View.Form.Document._super.display.call(this);
@@ -19755,34 +19792,30 @@ function eval_pyson(value){
19755
19792
  filename = filename_field.get_client(record);
19756
19793
  }
19757
19794
  data.done(data => {
19758
- var url, blob;
19759
19795
  if (record !== this.record) {
19760
19796
  return;
19761
19797
  }
19762
19798
  // in case onload was not yet triggered
19763
- window.URL.revokeObjectURL(this.object.attr('data'));
19799
+ let url = this.content.attr('data') ||
19800
+ this.content.attr('src');
19801
+ window.URL.revokeObjectURL(url);
19802
+ let mimetype;
19764
19803
  if (!data) {
19765
19804
  url = null;
19766
19805
  } else {
19767
- var mimetype = Sao.common.guess_mimetype(filename);
19806
+ mimetype = Sao.common.guess_mimetype(filename);
19768
19807
  if (mimetype == 'application/octet-binary') {
19769
19808
  mimetype = null;
19770
19809
  }
19771
- blob = new Blob([data], {
19810
+ let blob = new Blob([data], {
19772
19811
  'type': mimetype,
19773
19812
  });
19774
19813
  url = window.URL.createObjectURL(blob);
19775
19814
  }
19776
19815
  // duplicate object to force refresh on buggy browsers
19777
- const object = this.object.clone();
19778
- // set onload before data to be always called
19779
- object.get(0).onload = function() {
19780
- this.onload = null;
19781
- window.URL.revokeObjectURL(url);
19782
- };
19783
- object.attr('data', url);
19784
- this.object.replaceWith(object);
19785
- this.object = object;
19816
+ let content = this._create_content(mimetype, url);
19817
+ this.content.replaceWith(content);
19818
+ this.content = content;
19786
19819
  });
19787
19820
  },
19788
19821
  });
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.4.18",
5
+ "version": "7.4.19",
6
6
  "homepage": "https://www.tryton.org/",
7
7
  "author": {
8
8
  "name": "Tryton"
package/src/sao.js CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  /* eslint-disable no-redeclare */
5
5
  var Sao = {
6
- __version__: '7.4.18',
6
+ __version__: '7.4.19',
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
@@ -980,14 +980,19 @@ img.icon {
980
980
  }
981
981
  }
982
982
  .form-document {
983
- object {
983
+ object, img {
984
984
  object-fit: scale-down;
985
985
  object-position: center top;
986
+ }
987
+ iframe {
988
+ border: 0;
989
+ }
990
+ object, iframe, img {
986
991
  width: 100%;
987
992
  min-height: 50vh;
988
993
  height: 100%;
989
994
  @media screen and (max-width: @screen-xs-max) {
990
- min-height: 25vh;
995
+ min-height: 50vh;
991
996
  }
992
997
  }
993
998
  }
package/src/view/form.js CHANGED
@@ -4783,15 +4783,42 @@ function eval_pyson(value){
4783
4783
  'class': this.class_,
4784
4784
  });
4785
4785
 
4786
- this.object = jQuery('<object/>', {
4786
+ this.content = this._create_content().appendTo(this.el);
4787
+ },
4788
+ _create_content: function(mimetype, url) {
4789
+ let tag_name = 'iframe';
4790
+ if (mimetype) {
4791
+ if (mimetype.startsWith('image/')) {
4792
+ tag_name = 'img';
4793
+ } else if (mimetype == 'application/pdf') {
4794
+ tag_name = 'object';
4795
+ }
4796
+ }
4797
+ let content = jQuery(`<${tag_name}/>`, {
4787
4798
  'class': 'center-block',
4788
- }).appendTo(this.el);
4789
- if (attributes.height) {
4790
- this.object.css('height', parseInt(attributes.height, 10));
4799
+ });
4800
+ if (tag_name == 'iframe') {
4801
+ content.attr('sandbox', '');
4802
+ }
4803
+ if (this.attributes.height) {
4804
+ content.css('height', parseInt(this.attributes.height, 10));
4791
4805
  }
4792
- if (attributes.width) {
4793
- this.object.css('width', parseInt(attributes.width, 10));
4806
+ if (this.attributes.width) {
4807
+ content.css('width', parseInt(this.attributes.width, 10));
4794
4808
  }
4809
+ if (url) {
4810
+ // set onload before data/src to be always called
4811
+ content.get().onload = function() {
4812
+ this.onload = null;
4813
+ window.URL.revokeObjectURL(url);
4814
+ };
4815
+ if (tag_name== 'object') {
4816
+ content.attr('data', url);
4817
+ } else {
4818
+ content.attr('src', url);
4819
+ }
4820
+ }
4821
+ return content;
4795
4822
  },
4796
4823
  display: function() {
4797
4824
  Sao.View.Form.Document._super.display.call(this);
@@ -4807,34 +4834,30 @@ function eval_pyson(value){
4807
4834
  filename = filename_field.get_client(record);
4808
4835
  }
4809
4836
  data.done(data => {
4810
- var url, blob;
4811
4837
  if (record !== this.record) {
4812
4838
  return;
4813
4839
  }
4814
4840
  // in case onload was not yet triggered
4815
- window.URL.revokeObjectURL(this.object.attr('data'));
4841
+ let url = this.content.attr('data') ||
4842
+ this.content.attr('src');
4843
+ window.URL.revokeObjectURL(url);
4844
+ let mimetype;
4816
4845
  if (!data) {
4817
4846
  url = null;
4818
4847
  } else {
4819
- var mimetype = Sao.common.guess_mimetype(filename);
4848
+ mimetype = Sao.common.guess_mimetype(filename);
4820
4849
  if (mimetype == 'application/octet-binary') {
4821
4850
  mimetype = null;
4822
4851
  }
4823
- blob = new Blob([data], {
4852
+ let blob = new Blob([data], {
4824
4853
  'type': mimetype,
4825
4854
  });
4826
4855
  url = window.URL.createObjectURL(blob);
4827
4856
  }
4828
4857
  // duplicate object to force refresh on buggy browsers
4829
- const object = this.object.clone();
4830
- // set onload before data to be always called
4831
- object.get(0).onload = function() {
4832
- this.onload = null;
4833
- window.URL.revokeObjectURL(url);
4834
- };
4835
- object.attr('data', url);
4836
- this.object.replaceWith(object);
4837
- this.object = object;
4858
+ let content = this._create_content(mimetype, url);
4859
+ this.content.replaceWith(content);
4860
+ this.content = content;
4838
4861
  });
4839
4862
  },
4840
4863
  });