Skip to content

Commit 068dcc2

Browse files
committed
[FIX] website: save cover images as webp
When webp support was introduced in [1], images set on covers were not handled. This commit automatically converts to webp the images that are uploaded in covers using the website builder. Steps to reproduce: - Edit a blog post page. - Upload a JPEG cover picture. - Save. => The cover picture was still a JPEG. [1]: odoo@0449fe8 task-3761728 closes odoo#169822 X-original-commit: f9c9d6c Signed-off-by: Benjamin Vray (bvr) <[email protected]>
1 parent 93cc424 commit 068dcc2

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

addons/website/static/src/components/wysiwyg_adapter/wysiwyg_adapter.js

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,7 @@ export class WysiwygAdapterComponent extends Wysiwyg {
933933
* @private
934934
* @param {HTMLElement} editable
935935
*/
936-
_saveCoverProperties($elementToSave) {
936+
async _saveCoverProperties($elementToSave) {
937937
var el = $elementToSave.closest('.o_record_cover_container')[0];
938938
if (!el) {
939939
return;
@@ -960,7 +960,32 @@ export class WysiwygAdapterComponent extends Wysiwyg {
960960
}
961961
this.__savedCovers[resModel].push(resID);
962962

963-
var cssBgImage = $(el.querySelector('.o_record_cover_image')).css('background-image');
963+
const imageEl = el.querySelector('.o_record_cover_image');
964+
let cssBgImage = imageEl.style.backgroundImage;
965+
if (imageEl.classList.contains("o_b64_image_to_save")) {
966+
imageEl.classList.remove("o_b64_image_to_save");
967+
const groups = cssBgImage.match(/url\("data:(?<mimetype>.*);base64,(?<imageData>.*)"\)/)?.groups;
968+
if (!groups.imageData) {
969+
// Checks if the image is in base64 format for RPC call. Relying
970+
// only on the presence of the class "o_b64_image_to_save" is not
971+
// robust enough.
972+
return;
973+
}
974+
const modelName = await this.websiteService.getUserModelName(resModel);
975+
const recordNameEl = imageEl.closest("body").querySelector(`[data-oe-model="${resModel}"][data-oe-id="${resID}"][data-oe-field="name"]`);
976+
const recordName = recordNameEl ? `'${recordNameEl.textContent}'` : resID;
977+
const attachment = await this.rpc(
978+
'/web_editor/attachment/add_data',
979+
{
980+
name: `${modelName} ${recordName} cover image.${groups.mimetype.split("/")[1]}`,
981+
data: groups.imageData,
982+
is_image: true,
983+
res_model: resModel,
984+
res_id: resID,
985+
},
986+
);
987+
cssBgImage = `url(${attachment.image_src})`;
988+
}
964989
var coverProps = {
965990
'background-image': cssBgImage.replace(/"/g, '').replace(window.location.protocol + "//" + window.location.host, ''),
966991
'background_color_class': el.dataset.bgColorClass,

addons/website/static/src/js/editor/snippets.options.js

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import weUtils from "@web_editor/js/common/utils";
88
import options from "@web_editor/js/editor/snippets.options";
99
import { NavbarLinkPopoverWidget } from "@website/js/widgets/link_popover_widget";
1010
import wUtils from "@website/js/utils";
11-
import {isImageCorsProtected, isImageSupportedForStyle} from "@web_editor/js/editor/image_processing";
11+
import {
12+
applyModifications,
13+
isImageCorsProtected,
14+
isImageSupportedForStyle,
15+
loadImageInfo,
16+
} from "@web_editor/js/editor/image_processing";
1217
import "@website/snippets/s_popup/options";
1318
import { range } from "@web/core/utils/numbers";
1419
import { _t } from "@web/core/l10n/translation";
@@ -2949,6 +2954,7 @@ options.registry.CoverProperties = options.Class.extend({
29492954

29502955
this.$image = this.$target.find('.o_record_cover_image');
29512956
this.$filter = this.$target.find('.o_record_cover_filter');
2957+
this.rpc = this.bindService("rpc");
29522958
},
29532959
/**
29542960
* @override
@@ -2969,10 +2975,31 @@ options.registry.CoverProperties = options.Class.extend({
29692975
* @see this.selectClass for parameters
29702976
*/
29712977
background: async function (previewMode, widgetValue, params) {
2978+
if (previewMode === false) {
2979+
this.$image[0].classList.remove("o_b64_image_to_save");
2980+
}
29722981
if (widgetValue === '') {
29732982
this.$image.css('background-image', '');
29742983
this.$target.removeClass('o_record_has_cover');
29752984
} else {
2985+
if (previewMode === false) {
2986+
const imgEl = document.createElement("img");
2987+
imgEl.src = widgetValue;
2988+
await loadImageInfo(imgEl, this.rpc);
2989+
if (imgEl.dataset.mimetype && ![
2990+
"image/gif",
2991+
"image/svg+xml",
2992+
"image/webp",
2993+
].includes(imgEl.dataset.mimetype)) {
2994+
// Convert to webp but keep original width.
2995+
imgEl.dataset.mimetype = "image/webp";
2996+
const base64src = await applyModifications(imgEl, {
2997+
mimetype: "image/webp",
2998+
});
2999+
widgetValue = base64src;
3000+
this.$image[0].classList.add("o_b64_image_to_save");
3001+
}
3002+
}
29763003
this.$image.css('background-image', `url('${widgetValue}')`);
29773004
this.$target.addClass('o_record_has_cover');
29783005
const $defaultSizeBtn = this.$el.find('.o_record_cover_opt_size_default');

0 commit comments

Comments
 (0)