167 lines
7.3 KiB
Python
167 lines
7.3 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
import logging
|
|
|
|
from lxml import html, etree
|
|
|
|
from odoo import models
|
|
from odoo.tools.translate import _
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class WebsitePage(models.Model):
|
|
_inherit = 'website.page'
|
|
|
|
def _construct_homepage(self, homepage_data):
|
|
self._construct_page(homepage_data)
|
|
self._create_footer(homepage_data)
|
|
self._create_header(homepage_data)
|
|
self._apply_website_themes(homepage_data)
|
|
self._apply_user_values(homepage_data)
|
|
|
|
def _construct_page(self, page_data):
|
|
html_block_list = page_data.get('body_html')
|
|
if not html_block_list:
|
|
return
|
|
rendered_snippets = []
|
|
nb_snippets = len(html_block_list)
|
|
for i, snippet in enumerate(html_block_list, start=1):
|
|
try:
|
|
# Remove \ufeff character from the html (it is a BOM character that is not supported by lxml)
|
|
el = html.fromstring(snippet.replace('\ufeff', ''))
|
|
|
|
# TODO: Add the data-snippet attribute to identify the snippet
|
|
# for compatibility code
|
|
# el.attrib['data-snippet'] = snippet["name"]
|
|
|
|
# Tweak the shape of the first snippet to connect it
|
|
# properly with the header color in some themes
|
|
if i == 1:
|
|
shape_el = el.xpath("//*[hasclass('o_we_shape')]")
|
|
if shape_el:
|
|
shape_el[0].attrib['class'] += ' o_header_extra_shape_mapping'
|
|
|
|
# Tweak the shape of the last snippet to connect it
|
|
# properly with the footer color in some themes
|
|
if i == nb_snippets:
|
|
shape_el = el.xpath("//*[hasclass('o_we_shape')]")
|
|
if shape_el:
|
|
shape_el[0].attrib['class'] += ' o_footer_extra_shape_mapping'
|
|
rendered_snippet = etree.tostring(el, encoding='unicode')
|
|
rendered_snippets.append(rendered_snippet)
|
|
except ValueError as e:
|
|
logger.warning("Error rendering snippet: %s", e)
|
|
self.view_id.save(value=f'<div class="oe_structure">{"".join(rendered_snippets)}</div>',
|
|
xpath="(//div[hasclass('oe_structure')])[last()]")
|
|
|
|
def _create_header(self, homepage_data):
|
|
# Remove all website menus, keep only the top menu "container"
|
|
self.env['website.menu'].search([('website_id', '=', self.website_id.id)]).unlink()
|
|
|
|
# Create the top menu of which to bind the menu buttons to.
|
|
top_menu = self.env['website.menu'].create({
|
|
'name': _('Top Menu for Website %s', self.website_id.id),
|
|
'url': '/default-main-menu',
|
|
'website_id': self.website_id.id,
|
|
})
|
|
for button in homepage_data.get('header', {}).get('buttons', []):
|
|
if button.get('name', '').lower() in ['sign in', 'contact us']:
|
|
continue # those are Odoo menu already
|
|
menu_content = button.get('menu_content')
|
|
if menu_content:
|
|
menu_type = menu_content.get('type')
|
|
if menu_type == 'simple_menu':
|
|
# Create the parent menu
|
|
parent_menu = self._create_menu(button, top_menu)
|
|
# Create the submenu menu.
|
|
children_menus = button.get('menu_content', {}).get('content', [])
|
|
self.env['website.menu'].create([{
|
|
'name': child_menu['name'],
|
|
'url': child_menu['href'],
|
|
'parent_id': parent_menu and parent_menu.id,
|
|
'website_id': self.website_id.id} for child_menu in children_menus])
|
|
elif menu_type == 'mega_menu':
|
|
# Create mega menu instead
|
|
button_name = button.get('name')
|
|
button_href = button.get('href')
|
|
mega_menu_content = button.get('menu_content', {}).get('content')
|
|
if not button_name or not button_href or not mega_menu_content:
|
|
return
|
|
self.env['website.menu'].create({
|
|
'name': button_name,
|
|
'url': button_href,
|
|
'website_id': self.website_id.id,
|
|
'parent_id': top_menu.id,
|
|
'is_mega_menu': True,
|
|
'mega_menu_content': mega_menu_content,
|
|
})
|
|
else:
|
|
self._create_menu(button, top_menu)
|
|
|
|
# TODO: Need to try and set the level of transparency of the header overlay.
|
|
header_position = homepage_data.get('header_position', 'regular')
|
|
if header_position == 'regular':
|
|
self.header_overlay = False
|
|
elif header_position == 'over-the-content':
|
|
self.header_overlay = True
|
|
|
|
def _create_menu(self, menu_vals, top_menu):
|
|
menu_name = menu_vals.get('name')
|
|
menu_href = menu_vals.get('href')
|
|
if not menu_name or not menu_href:
|
|
return
|
|
menu = self.env['website.menu'].create({
|
|
'name': menu_name,
|
|
'url': menu_href,
|
|
'parent_id': top_menu.id,
|
|
'website_id': self.website_id.id,
|
|
})
|
|
return menu
|
|
|
|
def _apply_website_themes(self, homepage_data):
|
|
user_color_palette = homepage_data.get('user_color_palette', {})
|
|
if user_color_palette:
|
|
self.env['website.assets'].make_scss_customization(
|
|
'/website/static/src/scss/options/colors/user_color_palette.scss',
|
|
user_color_palette,
|
|
)
|
|
|
|
def _apply_user_values(self, homepage_data):
|
|
user_values = homepage_data.get('user_values', {})
|
|
|
|
if homepage_data.get('footer'):
|
|
user_values.update({'footer-template': f"'imported-footer-{self.website_id.id}'"})
|
|
|
|
if user_values:
|
|
self.env['website.assets'].make_scss_customization(
|
|
'/website/static/src/scss/options/user_values.scss',
|
|
user_values,
|
|
)
|
|
|
|
def _create_footer(self, homepage_data):
|
|
footer_html_list = homepage_data.get('footer', [])
|
|
rendered_snippets = []
|
|
for snippet in footer_html_list:
|
|
try:
|
|
# Process the footer html content (for example, an <img> element becomes <img/>.)
|
|
el = html.fromstring(snippet)
|
|
rendered_snippet = etree.tostring(el, encoding='unicode')
|
|
rendered_snippets.append(rendered_snippet)
|
|
except ValueError as e:
|
|
logger.warning(e)
|
|
|
|
# Now generate the footer template.
|
|
new_footer_template = f"""
|
|
<xpath expr="//div[@id='footer']" position="replace">
|
|
<div id="footer" class="oe_structure oe_structure_solo" t-ignore="true" t-if="not no_footer">{"".join(rendered_snippets)}</div>
|
|
</xpath>"""
|
|
|
|
self.env['ir.ui.view'].create({
|
|
'name': 'Template WS Custom Footer',
|
|
'type': 'qweb',
|
|
'key': f'website_generator.template_ws_custom_footer_{self.website_id.id}',
|
|
'arch': new_footer_template,
|
|
'inherit_id': self.env['website'].with_context(website_id=self.website_id.id).viewref('website.layout').id,
|
|
'website_id': self.website_id.id,
|
|
})
|