diff --git a/addons/web/static/src/views/fields/image/image_field.js b/addons/web/static/src/views/fields/image/image_field.js index 0bd447934d7..13067aeaa7b 100644 --- a/addons/web/static/src/views/fields/image/image_field.js +++ b/addons/web/static/src/views/fields/image/image_field.js @@ -49,6 +49,7 @@ export class ImageField extends Component { acceptedFileExtensions: { type: String, optional: true }, width: { type: Number, optional: true }, height: { type: Number, optional: true }, + noReload: { type: Boolean, optional: true }, }; static defaultProps = { acceptedFileExtensions: "image/*", @@ -61,6 +62,7 @@ export class ImageField extends Component { this.state = useState({ isValid: true, }); + this.lastURL = undefined; } get rawCacheKey() { @@ -96,9 +98,12 @@ export class ImageField extends Component { } getUrl(previewFieldName) { + if (this.props.noReload && this.lastURL) { + return this.lastURL; + } if (this.state.isValid && this.props.record.data[this.props.name]) { if (isBinarySize(this.props.record.data[this.props.name])) { - return url("/web/image", { + this.lastURL = url("/web/image", { model: this.props.record.resModel, id: this.props.record.resId, field: previewFieldName, @@ -108,8 +113,11 @@ export class ImageField extends Component { // Use magic-word technique for detecting image type const magic = fileTypeMagicWordMap[this.props.record.data[this.props.name][0]] || "png"; - return `data:image/${magic};base64,${this.props.record.data[this.props.name]}`; + this.lastURL = `data:image/${magic};base64,${ + this.props.record.data[this.props.name] + }`; } + return this.lastURL; } return placeholder; } @@ -220,6 +228,7 @@ export const imageField = { acceptedFileExtensions: options.accepted_file_extensions, width: options.size && Boolean(options.size[0]) ? options.size[0] : attrs.width, height: options.size && Boolean(options.size[1]) ? options.size[1] : attrs.height, + noReload: Boolean(options.no_reload), }), }; diff --git a/addons/web/static/tests/views/fields/image_field_tests.js b/addons/web/static/tests/views/fields/image_field_tests.js index 20a0f45f062..95de86041fc 100644 --- a/addons/web/static/tests/views/fields/image_field_tests.js +++ b/addons/web/static/tests/views/fields/image_field_tests.js @@ -31,7 +31,11 @@ QUnit.module("Fields", (hooks) => { models: { partner: { fields: { - display_name: { string: "Displayed name", type: "char", searchable: true }, + display_name: { + string: "Displayed name", + type: "char", + searchable: true, + }, timmy: { string: "pokemon", type: "many2many", @@ -518,7 +522,10 @@ QUnit.module("Fields", (hooks) => { QUnit.test("ImageField in subviews is loaded correctly", async function (assert) { serverData.models.partner.records[0].write_date = "2017-02-08 10:00:00"; serverData.models.partner.records[0].document = MY_IMAGE; - serverData.models.partner_type.fields.image = { name: "image", type: "binary" }; + serverData.models.partner_type.fields.image = { + name: "image", + type: "binary", + }; serverData.models.partner_type.records[0].image = PRODUCT_IMAGE; serverData.models.partner.records[0].timmy = [12]; @@ -561,7 +568,10 @@ QUnit.module("Fields", (hooks) => { }); QUnit.test("ImageField in x2many list is loaded correctly", async function (assert) { - serverData.models.partner_type.fields.image = { name: "image", type: "binary" }; + serverData.models.partner_type.fields.image = { + name: "image", + type: "binary", + }; serverData.models.partner_type.records[0].image = PRODUCT_IMAGE; serverData.models.partner.records[0].timmy = [12]; @@ -702,4 +712,42 @@ QUnit.module("Fields", (hooks) => { await pagerNext(target); assert.strictEqual(getUnique(target.querySelector(".o_field_image img")), "1659692220000"); }); + + QUnit.test( + "unique in url does not change on record change if no_reload option is set", + async (assert) => { + const rec = serverData.models.partner.records.find((rec) => rec.id === 1); + rec.document = "3 kb"; + rec.write_date = "2022-08-05 08:37:00"; + + await makeView({ + resIds: [1, 2], + resId: 1, + type: "form", + resModel: "partner", + serverData, + arch: ` +
`, + }); + + function getUnique(target) { + const src = target.dataset.src; + return new URL(src).searchParams.get("unique"); + } + + assert.strictEqual( + getUnique(target.querySelector(".o_field_image img")), + "1659688620000" + ); + await editInput(target, "div[name='write_date'] > div > input", "2022-08-05 08:39:00"); + await click(target, ".o_form_button_save"); + assert.strictEqual( + getUnique(target.querySelector(".o_field_image img")), + "1659688620000" + ); + } + ); });