[IMP] website: change CTA based on website main objective
If user selects 'schedule appointments' as main objective in the configurator and if the website_calendar module is installed then the Call To Action of snippets s_banner, s_cover and s_call_to_action is changed to 'Schedule an appointment' and redirect user to '/calendar' on click. task-2518565 closes odoo/odoo#71162 Related: odoo/enterprise#18690 Related: odoo/design-themes#5 Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
committed by
Jeremy Kersten
parent
731a173d49
commit
cd3ca50548
@@ -8,7 +8,7 @@ import hashlib
|
||||
import requests
|
||||
import re
|
||||
|
||||
from lxml import html
|
||||
from lxml import etree
|
||||
from werkzeug import urls
|
||||
from werkzeug.datastructures import OrderedMultiDict
|
||||
from werkzeug.exceptions import NotFound
|
||||
@@ -287,6 +287,9 @@ class Website(models.Model):
|
||||
endpoint = website_api_endpoint + route
|
||||
return iap_tools.iap_jsonrpc(endpoint, params=params)
|
||||
|
||||
def get_cta_data(self, website_purpose, website_type):
|
||||
return {'cta_btn_text': False, 'cta_btn_href': '/contactus'}
|
||||
|
||||
@api.model
|
||||
def configurator_init(self):
|
||||
r = dict()
|
||||
@@ -348,10 +351,15 @@ class Website(models.Model):
|
||||
result = self.env['website'].new_page(name=feature_id.name, add_menu=True, template=feature_id.page_view_id.key)
|
||||
pages_views[feature_id.iap_page_code] = result['view_id']
|
||||
|
||||
modules._button_immediate_function(lambda self: self.button_install())
|
||||
modules.button_immediate_install()
|
||||
|
||||
# Force to refresh env after install of modules
|
||||
self._cr.commit()
|
||||
api.Environment.reset()
|
||||
self.env = api.Environment(modules._cr, modules._uid, modules._context)
|
||||
return pages_views
|
||||
|
||||
def configure_page(page_code, snippet_list, pages_views):
|
||||
def configure_page(page_code, snippet_list, pages_views, cta_data):
|
||||
if page_code == 'homepage':
|
||||
page_view_id = website.homepage_id.view_id
|
||||
else:
|
||||
@@ -362,8 +370,7 @@ class Website(models.Model):
|
||||
try:
|
||||
view_id = self.env['website'].with_context(website_id=website.id).viewref(snippet)
|
||||
if view_id:
|
||||
rendered_snippet = pycompat.to_text(view_id._render())
|
||||
el = html.fragment_fromstring(rendered_snippet)
|
||||
el = etree.fromstring(view_id._render(values=cta_data))
|
||||
|
||||
# Add the data-snippet attribute to identify the snippet
|
||||
# for compatibility code
|
||||
@@ -382,8 +389,7 @@ class Website(models.Model):
|
||||
shape_el = el.xpath("//*[hasclass('o_we_shape')]")
|
||||
if shape_el:
|
||||
shape_el[0].attrib['class'] += ' o_footer_extra_shape_mapping'
|
||||
|
||||
rendered_snippet = pycompat.to_text(html.tostring(el))
|
||||
rendered_snippet = pycompat.to_text(etree.tostring(el))
|
||||
rendered_snippets.append(rendered_snippet)
|
||||
except ValueError as e:
|
||||
logger.warning(e)
|
||||
@@ -433,6 +439,9 @@ class Website(models.Model):
|
||||
|
||||
# modules
|
||||
pages_views = set_features(kwargs.get('selected_features'))
|
||||
# We need to refresh the environment of website because set_features installed some new module
|
||||
# and we need the overrides of these new menus e.g. for .get_cta_data()
|
||||
website = self.env['website'].browse(website.id)
|
||||
|
||||
# Load suggestion from iap for selected pages
|
||||
requested_pages = list(pages_views.keys())
|
||||
@@ -443,10 +452,53 @@ class Website(models.Model):
|
||||
}
|
||||
custom_resources = self._website_api_rpc('/api/website/1/configurator/custom_resources/%s' % kwargs.get('industry_id'), params)
|
||||
|
||||
# Update CTA
|
||||
cta_data = website.get_cta_data(kwargs.get('website_purpose'), kwargs.get('website_type'))
|
||||
if cta_data['cta_btn_text']:
|
||||
xpath_view = 'website.snippets'
|
||||
parent_view = self.env['website'].with_context(website_id=website.id).viewref(xpath_view)
|
||||
self.env['ir.ui.view'].create({
|
||||
'name': parent_view.key + ' CTA',
|
||||
'key': parent_view.key + "_cta",
|
||||
'inherit_id': parent_view.id,
|
||||
'website_id': website.id,
|
||||
'type': 'qweb',
|
||||
'priority': 32,
|
||||
'arch_db': """
|
||||
<data>
|
||||
<xpath expr="//t[@t-set='cta_btn_href']" position="replace">
|
||||
<t t-set="cta_btn_href">%s</t>
|
||||
</xpath>
|
||||
<xpath expr="//t[@t-set='cta_btn_text']" position="replace">
|
||||
<t t-set="cta_btn_text">%s</t>
|
||||
</xpath>
|
||||
</data>
|
||||
""" % (cta_data['cta_btn_href'], cta_data['cta_btn_text'])
|
||||
})
|
||||
header_ids = [
|
||||
'website.template_header_default_oe_structure_header_default_1',
|
||||
'website.template_header_hamburger_oe_structure_header_hamburger_1',
|
||||
'website.template_header_slogan_oe_structure_header_slogan_2',
|
||||
'website.template_header_boxed_oe_structure_header_boxed_2',
|
||||
'website.template_header_image_oe_structure_header_image_2',
|
||||
]
|
||||
for header_id in header_ids:
|
||||
try:
|
||||
view_id = self.env['website'].viewref(header_id)
|
||||
if view_id:
|
||||
el = etree.fromstring(view_id.arch_db)
|
||||
btn_cta_el = el.xpath("//a[hasclass('btn_cta')]")
|
||||
if btn_cta_el:
|
||||
btn_cta_el[0].attrib['href'] = cta_data['cta_btn_href']
|
||||
btn_cta_el[0].text = cta_data['cta_btn_text']
|
||||
view_id.with_context(website_id=website.id).write({'arch_db': etree.tostring(el)})
|
||||
except ValueError as e:
|
||||
logger.warning(e)
|
||||
|
||||
# Update pages
|
||||
pages = custom_resources.get('pages', {})
|
||||
for page_code, snippet_list in pages.items():
|
||||
configure_page(page_code, snippet_list, pages_views)
|
||||
configure_page(page_code, snippet_list, pages_views, cta_data)
|
||||
|
||||
images = custom_resources.get('images', [])
|
||||
set_images(images)
|
||||
|
||||
@@ -16,7 +16,7 @@ class WebsiteConfiguratorFeature(models.Model):
|
||||
description = fields.Char(translate=True)
|
||||
icon = fields.Char()
|
||||
iap_page_code = fields.Char(help='Page code used to tell IAP website_service for which page a snippet list should be generated')
|
||||
website_types_preselection = fields.Char(help='Comma-separated list of website type for which this feature should be pre-selected')
|
||||
website_types_preselection = fields.Char(help='Comma-separated list of website type/purpose for which this feature should be pre-selected')
|
||||
type = fields.Selection([('page', "Page"), ('app', "App")], compute='_compute_type')
|
||||
page_view_id = fields.Many2one('ir.ui.view', ondelete='cascade')
|
||||
module_id = fields.Many2one('ir.module.module', ondelete='cascade')
|
||||
|
||||
@@ -24,7 +24,8 @@ const WEBSITE_PURPOSES = {
|
||||
1: {id: 1, label: _lt("get leads"), name: 'get_leads'},
|
||||
2: {id: 2, label: _lt("develop the brand"), name: 'develop_brand'},
|
||||
3: {id: 3, label: _lt("sell more"), name: 'sell_more'},
|
||||
4: {id: 4, label: _lt("inform customers"), name: 'inform_customers'}
|
||||
4: {id: 4, label: _lt("inform customers"), name: 'inform_customers'},
|
||||
5: {id: 5, label: _lt("schedule appointments"), name: 'schedule_appointments'}
|
||||
};
|
||||
|
||||
const PALETTE_NAMES = [
|
||||
@@ -354,6 +355,10 @@ const actions = {
|
||||
state.selectedType = id;
|
||||
},
|
||||
selectWebsitePurpose({state}, id) {
|
||||
Object.values(state.features).filter((feature) => feature.module_state !== 'installed').forEach((feature) => {
|
||||
// need to check id, since we set to undefined in mount() to avoid the auto next screen on back button
|
||||
feature.selected |= id && feature.website_types_preselection.includes(WEBSITE_PURPOSES[id].name);
|
||||
});
|
||||
state.selectedPurpose = id;
|
||||
},
|
||||
selectIndustry({state}, id) {
|
||||
@@ -475,6 +480,8 @@ async function applyConfigurator(self, themeName) {
|
||||
industry_id: self.state.selectedIndustry,
|
||||
selected_palette: selectedPalette,
|
||||
theme_name: themeName,
|
||||
website_purpose: WEBSITE_PURPOSES[self.state.selectedPurpose].name,
|
||||
website_type: WEBSITE_TYPES[self.state.selectedType].name,
|
||||
};
|
||||
const resp = await rpc.query({
|
||||
model: 'website',
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<div class="col-lg-6 jumbotron rounded o_cc o_cc1 pt32 pb32" data-name="Box">
|
||||
<h1><font style="font-size: 62px;">Sell Online. Easily.</font></h1>
|
||||
<p class="lead">This is a simple hero unit, a simple jumbotron-style component for calling extra attention to featured content or information.</p>
|
||||
<a href="#" class="btn btn-primary mb-2">Contact Us</a>
|
||||
<a t-att-href="cta_btn_href" class="btn btn-primary mb-2"><t t-esc="cta_btn_text">Contact Us</t></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</div>
|
||||
<div class="col-lg-3 pt8">
|
||||
<p style="text-align: right;">
|
||||
<a href="/contactus" class="btn btn-primary btn-lg mb-2">Contact us</a>
|
||||
<a t-att-href="cta_btn_href" class="btn btn-primary btn-lg mb-2"><t t-esc="cta_btn_text">Contact us</t></a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<h1 style="text-align: center;"><font style="font-size: 62px; font-weight: bold;">Catchy Headline</font></h1>
|
||||
<p class="lead" style="text-align: center;">Write one or two paragraphs describing your product, services or a specific feature.<br/> To be successful your content needs to be useful to your readers.</p>
|
||||
<p style="text-align: center;">
|
||||
<a href="/contactus" class="btn btn-primary mb-2">Contact us</a>
|
||||
<a t-att-href="cta_btn_href" class="btn btn-primary mb-2"><t t-esc="cta_btn_text">Contact us</t></a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
</xpath>
|
||||
<xpath expr="//t[@id='default_snippets']" position="replace">
|
||||
<t id="default_snippets">
|
||||
<t t-set="cta_btn_text" t-value="False"/>
|
||||
<t t-set="cta_btn_href">/contactus</t>
|
||||
<div id="snippet_mega_menu" class="o_panel d-none">
|
||||
<div class="o_panel_header">Mega Menu</div>
|
||||
<div class="o_panel_body">
|
||||
|
||||
@@ -125,6 +125,11 @@
|
||||
<attribute name="data-name">Header</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//header" position="before">
|
||||
<t t-set="cta_btn_text" t-value="False"/>
|
||||
<t t-set="cta_btn_href">/contactus</t>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//footer" position="attributes">
|
||||
<attribute name="data-name">Footer</attribute>
|
||||
<!-- Background now controlled by css configuration, using color combinations -->
|
||||
@@ -273,7 +278,7 @@
|
||||
<div class="oe_structure oe_structure_solo" id="oe_structure_header_default_1">
|
||||
<section class="s_text_block" data-snippet="s_text_block" data-name="Text">
|
||||
<div class="container">
|
||||
<a href="/contactus" class="btn btn-primary ml-4">Contact Us</a>
|
||||
<a href="/contactus" class="btn btn-primary ml-4 btn_cta">Contact Us</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -349,7 +354,7 @@
|
||||
<div class="oe_structure oe_structure_solo" id="oe_structure_header_hamburger_1">
|
||||
<section class="s_text_block" data-snippet="s_text_block" data-name="Text">
|
||||
<div class="container">
|
||||
<a href="/contactus" class="btn btn-primary ml-4">Contact Us</a>
|
||||
<a href="/contactus" class="btn btn-primary ml-4 btn_cta">Contact Us</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -697,7 +702,7 @@
|
||||
<div class="oe_structure oe_structure_solo" id="oe_structure_header_slogan_2">
|
||||
<section class="s_text_block" data-snippet="s_text_block" data-name="Text">
|
||||
<div class="container">
|
||||
<a href="/contactus" class="btn btn-primary ml-4">Contact Us</a>
|
||||
<a href="/contactus" class="btn btn-primary ml-4 btn_cta">Contact Us</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -926,7 +931,7 @@
|
||||
<div class="oe_structure oe_structure_solo" id="oe_structure_header_boxed_2">
|
||||
<section class="s_text_block" data-snippet="s_text_block" name="Text">
|
||||
<div class="container">
|
||||
<a href="/contactus" class="btn btn-primary ml-lg-4">Contact Us</a>
|
||||
<a href="/contactus" class="btn btn-primary ml-lg-4 btn_cta">Contact Us</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1043,7 +1048,7 @@
|
||||
<div class="oe_structure oe_structure_solo" id="oe_structure_header_image_2">
|
||||
<section class="s_text_block" data-snippet="s_text_block" data-name="Text">
|
||||
<div class="container">
|
||||
<a href="/contactus" class="btn btn-primary mt-3 mt-lg-0 ml-lg-3">Contact Us</a>
|
||||
<a href="/contactus" class="btn btn-primary mt-3 mt-lg-0 ml-lg-3 btn_cta">Contact Us</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -12,3 +12,10 @@ class Website(models.Model):
|
||||
suggested_controllers = super(Website, self).get_suggested_controllers()
|
||||
suggested_controllers.append((_('Events'), url_for('/event'), 'website_event'))
|
||||
return suggested_controllers
|
||||
|
||||
def get_cta_data(self, website_purpose, website_type):
|
||||
cta_data = super(Website, self).get_cta_data(website_purpose, website_type)
|
||||
if website_purpose == 'sell_more' and website_type == 'event':
|
||||
cta_btn_text = _('Next Events')
|
||||
return {'cta_btn_text': cta_btn_text, 'cta_btn_href': '/event'}
|
||||
return cta_data
|
||||
|
||||
Reference in New Issue
Block a user