[FIX] website: add support for svg logo in configurator

The configurator's palette selection screen didn't support
SVG logo. On SVG upload primary and secondary colors couldn't
be extracted and no palette was recommended. It comes from the
fact that Python PIL library does not support SVG. We therefore
had to convert SVG to PNG before trying to extract primary and
secondary colors. A file format checking has been added. If the
uplodad file is not an image, a notification is displayed to
the user.

task-2602521

closes odoo/odoo#76400

X-original-commit: 33f43618f727bdc1239c52c66b73f0f436035774
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
Sébastien Mottet (oms)
2021-09-13 14:42:54 +00:00
parent 4e59a600ce
commit 905df37c8b
2 changed files with 47 additions and 13 deletions
+15 -7
View File
@@ -307,7 +307,7 @@ class Website(models.Model):
@api.model
def configurator_init(self):
r = dict()
company_id = self.get_current_website().company_id
company = self.get_current_website().company_id
configurator_features = self.env['website.configurator.feature'].search([])
r['features'] = [{
'id': feature.id,
@@ -319,8 +319,8 @@ class Website(models.Model):
'module_state': feature.module_id.state,
} for feature in configurator_features]
r['logo'] = False
if company_id.logo and company_id.logo != company_id._get_logo():
r['logo'] = company_id.logo.decode('utf-8')
if company.logo and company.logo != company._get_logo():
r['logo'] = company.logo.decode('utf-8')
try:
result = self._website_api_rpc('/api/website/1/configurator/industries', {'lang': self.env.user.lang})
r['industries'] = result['industries']
@@ -470,10 +470,18 @@ class Website(models.Model):
tour_asset_id = self.env.ref('website.configurator_tour')
tour_asset_id.copy({'key': tour_asset_id.key, 'website_id': website.id, 'active': True})
# logo was generated as base64 url
logo = kwargs.get('logo')
if logo:
website.logo = logo.split(',', 1)[1]
# Set logo from generated attachment or from company's logo
logo_attachment_id = kwargs.get('logo_attachment_id')
company = website.company_id
if logo_attachment_id:
attachment = self.env['ir.attachment'].browse(logo_attachment_id)
attachment.write({
'res_model': 'website',
'res_field': 'logo',
'res_id': website.id,
})
elif not logo_attachment_id and company.logo and company.logo != company._get_logo():
website.logo = company.logo.decode('utf-8')
# palette
palette = kwargs.get('selected_palette')
@@ -6,6 +6,8 @@ import weUtils from 'web_editor.utils';
import session from 'web.session';
import {ColorpickerWidget} from 'web.Colorpicker';
import {_t, _lt} from 'web.core';
import {svgToPNG} from 'website.utils';
import {useService} from "@web/core/utils/hooks";
const {Component, Store, mount, QWeb} = owl;
const {useDispatch, useStore, useGetters, useRef} = owl.hooks;
@@ -189,6 +191,7 @@ class PaletteSelectionScreen extends Component {
this.getters = useGetters();
this.dispatch = useDispatch();
this.logoInputRef = useRef('logoSelectionInput');
this.notification = useService("notification");
}
mounted() {
@@ -206,13 +209,32 @@ class PaletteSelectionScreen extends Component {
if (logoSelectInput.files.length === 1) {
const file = logoSelectInput.files[0];
const data = await utils.getDataURLFromFile(file);
this.dispatch('changeLogo', data);
this.updatePalettes();
const attachment = await this.rpc({
route: '/web_editor/attachment/add_data',
params: {
name: 'logo',
data: data.split(',')[1],
is_image: true,
}
});
if (!attachment.error) {
this.dispatch('changeLogo', data, attachment.id);
this.updatePalettes();
} else {
this.notification.notify({
title: file.name,
message: attachment.error,
});
}
}
}
async updatePalettes() {
let img = this.state.logo.split(',', 2)[1];
let img = this.state.logo;
if (img.startsWith('data:image/svg+xml')) {
img = await svgToPNG(img);
}
img = img.split(',')[1];
const [color1, color2] = await rpc.query({
model: 'base.document.layout',
method: 'extract_image_primary_secondary_colors',
@@ -376,8 +398,9 @@ const actions = {
state.selectedIndustry = {id, label};
}
},
changeLogo({state}, data) {
changeLogo({state}, data, attachmentId) {
state.logo = data;
state.logoAttachmentId = attachmentId;
},
selectPalette({state}, paletteName) {
if (paletteName === 'recommendedPalette') {
@@ -472,6 +495,7 @@ async function getInitialState() {
palettes: palettes,
features: features,
themes: [],
logoAttachmentId: undefined,
});
}
@@ -508,12 +532,12 @@ async function applyConfigurator(self, themeName) {
}
const data = {
selected_features: selectedFeatures,
logo: self.state.logo,
industry_id: self.state.selectedIndustry.id,
selected_palette: selectedPalette,
theme_name: themeName,
website_purpose: WEBSITE_PURPOSES[self.state.selectedPurpose].name,
website_type: WEBSITE_TYPES[self.state.selectedType].name,
logo_attachment_id: self.state.logoAttachmentId,
};
const resp = await rpc.query({
model: 'website',
@@ -540,6 +564,7 @@ async function makeEnvironment() {
recommendedPalette: store.state.recommendedPalette,
features: store.state.features,
logo: store.state.logo,
logoAttachmentId: store.state.logoAttachmentId,
};
window.sessionStorage.setItem(SESSION_STORAGE_ITEM_NAME, JSON.stringify(newState));
});
@@ -553,7 +578,8 @@ async function makeEnvironment() {
env.loader = qweb.renderToString('website.ThemePreview.Loader', {
showTips: true
});
return Object.assign(env, {router, store, qweb});
const services = Component.env.services;
return Object.assign(env, {router, store, qweb, services});
}
async function setup() {