[IMP] web_editor, mass_mailing: convert svg to png to use shapes in mail

This allows users to use the shape feature on images in mass_mailing.
Since email clients do not support the svg file type, it converts these
svg images into png images on save.

task-2760157

Part-of: odoo/odoo#84926
This commit is contained in:
Antoine Guenet
2022-03-28 10:45:45 +02:00
parent a423289419
commit 2e23548b39
3 changed files with 46 additions and 43 deletions
@@ -5,7 +5,6 @@ const options = require('web_editor.snippets.options');
const {ColorpickerWidget} = require('web.Colorpicker');
const SelectUserValueWidget = options.userValueWidgetsRegistry['we-select'];
const weUtils = require('web_editor.utils');
const {_t} = require('web.core');
//--------------------------------------------------------------------------
// Constants
@@ -198,26 +197,6 @@ options.registry.BackgroundImage = options.registry.BackgroundImage.extend({
options.registry.ImageTools.include({
//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------
/**
* @override
*/
async updateUIVisibility() {
await this._super(...arguments);
// The image shape option should work correctly with this update of the
// ImageTools option but unfortunately, SVG support in mail clients
// prevents the final rendering of the image. For now, we disable the
// feature.
const imgShapeContainerEl = this.el.querySelector('.o_we_image_shape');
if (imgShapeContainerEl) {
imgShapeContainerEl.classList.toggle('d-none', !odoo.debug);
}
},
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -236,20 +215,6 @@ options.registry.ImageTools.include({
}
return this._super(...arguments);
},
/**
* @override
*/
async _renderCustomWidgets(uiFragment) {
await this._super(...arguments);
const imgShapeTitleEl = uiFragment.querySelector('.o_we_image_shape we-title');
if (imgShapeTitleEl) {
const warningEl = document.createElement('i');
warningEl.classList.add('fa', 'fa-exclamation-triangle', 'ml-1');
warningEl.title = _t("Be aware that this option may not work on many mail clients");
imgShapeTitleEl.appendChild(warningEl);
}
},
});
options.userValueWidgetsRegistry['we-fontfamilypicker'] = SelectUserValueWidget.extend({
@@ -63,13 +63,13 @@ var MassMailingFieldHtml = FieldHtml.extend({
if (this.wysiwyg.snippetsMenu) {
await this.wysiwyg.snippetsMenu.cleanForSave();
}
return this.wysiwyg.saveModifiedImages(this.$content).then(function () {
return this.wysiwyg.saveModifiedImages(this.$content).then(async function () {
self._isDirty = self.wysiwyg.isDirty();
self._doAction();
const $editorEnable = $editable.closest('.editor_enable');
$editorEnable.removeClass('editor_enable');
convertInline.toInline($editable, self.cssRules, self.wysiwyg.$iframe);
await convertInline.toInline($editable, self.cssRules, self.wysiwyg.$iframe);
$editorEnable.addClass('editor_enable');
self.trigger_up('field_changed', {
@@ -386,7 +386,7 @@ function classToStyle($editable, cssRules) {
* specificity: number;}>
* @param {JQuery} [$iframe] the iframe containing the editable, if any
*/
function toInline($editable, cssRules, $iframe) {
async function toInline($editable, cssRules, $iframe) {
const editable = $editable.get(0);
const iframe = $iframe && $iframe.get(0);
const doc = editable.ownerDocument;
@@ -430,6 +430,7 @@ function toInline($editable, cssRules, $iframe) {
attachmentThumbnailToLinkImg($editable);
fontToImg($editable);
await svgToPng($editable);
classToStyle($editable, cssRules);
bootstrapToTable($editable);
cardToTable($editable);
@@ -777,6 +778,42 @@ function normalizeRem($editable, rootFontSize=16) {
}
}
/**
* Convert images of type svg to png.
*
* @param {JQuery} $editable
*/
async function svgToPng($editable) {
for (const svg of $editable.find('img[src$=".svg"]')) {
// Make sure the svg is loaded before we convert it.
await new Promise(resolve => {
svg.onload = () => resolve();
if (svg.complete) {
resolve();
}
});
const image = document.createElement('img');
const canvas = document.createElement('CANVAS');
const width = _getWidth(svg);
const height = _getHeight(svg);
canvas.setAttribute('width', width);
canvas.setAttribute('height', height);
canvas.getContext('2d').drawImage(svg, 0, 0, width, height);
for (const attribute of svg.attributes) {
image.setAttribute(attribute.name, attribute.value);
}
image.setAttribute('src', canvas.toDataURL('png'));
image.setAttribute('width', width);
image.setAttribute('height', height);
svg.before(image);
svg.remove();
}
}
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -1097,11 +1134,12 @@ FieldHtml.include({
/**
* @override
*/
commitChanges: function () {
commitChanges: async function () {
const _super = this._super.bind(this);
if (this.nodeOptions['style-inline'] && this.mode === "edit") {
this._toInline();
await this._toInline();
}
return this._super();
return _super();
},
//--------------------------------------------------------------------------
@@ -1116,7 +1154,7 @@ FieldHtml.include({
*
* @private
*/
_toInline: function () {
_toInline: async function () {
var $editable = this.wysiwyg.getEditable();
var html = this.wysiwyg.getValue();
const $odooEditor = $editable.closest('.odoo-editor');
@@ -1124,7 +1162,7 @@ FieldHtml.include({
$odooEditor.removeClass('odoo-editor');
$editable.html(html);
toInline($editable, this.cssRules, this.wysiwyg.$iframe);
await toInline($editable, this.cssRules, this.wysiwyg.$iframe);
$odooEditor.addClass('odoo-editor');
this.wysiwyg.setValue($editable.html(), {