[REF] web, *: share common parts of main frontend layouts

* http_routing, portal, rating, survey, website, website_survey,
website_slides_survey

Before this commit, the final base layout of website was a fully
overridden layout of the one in portal, which was somehow a duplicated
one of the login one in web, which... so lots of duplicated code.

This commit is a first step towards a better organization:

1) The web app defines a frontend layout (to include base frontend
assets), with a base company logo as header.

2) The portal app modifies that layout in place to include the base
header, footer, ... It also uses a primary extension of it for
portal pages.

The survey app simply uses the above layout instead of defining its
own (by primary extension to include its own assets for its own
pages)

Same goes for the rating app and pages.

3) The website app modifies that layout in place to include the UI
assets, to add website UI, ... This allows to create frontend apps
which do not depend on website, with a non duplicated layout that
will be automatically adapted if website is ever installed (this
therefore allows to get rid of website_survey definitely)

This commit also fixes the session info system and the translation URL
on the frontend side to not require to redefine the whole session_info
for portal, website, ... Now the frontend session_info is defined in web
and http_routing extends it to add translation informations, then
website extends it again to add its own elements (not to redefine them
all as before). Note: before, http_routing defined the translation route
but only portal was adding it in its layout...
This is an adaptation of the work that was done with commit
https://github.com/odoo/odoo/commit/99821fdcf89aa66ac9561a972c6823135ebf65c0

Note 1: Many frontend but non-website apps (not only survey / rating)
could probably use this too but this would be the topic of another task.

Note 2: survey currently depends on http_routing but does not add itself
in the list of frontend apps to translate, it probably should.

Note 3: web_editor does currently not depend on http_routing but does
add itself in the list of frontend apps to translate, it thus uses a
function it does not really depend on... to check after its work-in-
progress refactoring.

task-1961045

closes odoo/odoo#33825

Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
This commit is contained in:
qsm-odoo
2019-06-03 20:09:26 +00:00
parent 8e30349fd1
commit e9be0bb178
16 changed files with 218 additions and 313 deletions
+2 -8
View File
@@ -1,23 +1,17 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import odoo
from odoo import http
from odoo.http import request
from odoo.osv import expression
from odoo.addons.web.controllers.main import WebClient, Home
class Routing(Home):
@http.route('/website/translations/<string:unique>', type='http', auth="public", website=True)
def get_website_translations(self, unique, lang, mods=None):
Modules = request.env['ir.module.module'].sudo()
IrHttp = request.env['ir.http'].sudo()
domain = IrHttp._get_translation_frontend_modules_domain()
modules = Modules.search(
expression.AND([domain, [('state', '=', 'installed')]])
).mapped('name')
modules = IrHttp.get_translation_frontend_modules()
if mods:
modules += mods
return WebClient().translations(unique, mods=','.join(modules), lang=lang)
+29
View File
@@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
import hashlib
import json
import logging
import os
import re
@@ -16,6 +18,7 @@ import odoo
from odoo import api, models
from odoo.addons.base.models.ir_http import RequestUID, ModelConverter
from odoo.http import request
from odoo.osv import expression
from odoo.tools import config, ustr, pycompat
from ..geoipresolver import GeoIPResolver
@@ -236,6 +239,32 @@ class IrHttp(models.AbstractModel):
return request.env['res.lang'].search([('code', '=', lang_code)], limit=1)
return request.env['res.lang'].search([], limit=1)
@api.model
def get_frontend_session_info(self):
session_info = super(IrHttp, self).get_frontend_session_info()
IrHttpModel = request.env['ir.http'].sudo()
modules = IrHttpModel.get_translation_frontend_modules()
user_context = request.session.get_context() if request.session.uid else {}
lang = user_context.get('lang')
translations, _ = request.env['ir.translation'].get_translations_for_webclient(modules, lang)
session_info.update({
'translationURL': '/website/translations/',
'cache_hashes': {
'translations': hashlib.sha1(json.dumps(translations, sort_keys=True).encode()).hexdigest(),
},
})
return session_info
@api.model
def get_translation_frontend_modules(self):
Modules = request.env['ir.module.module'].sudo()
domain = self._get_translation_frontend_modules_domain()
return Modules.search(
expression.AND([domain, [('state', '=', 'installed')]])
).mapped('name')
@classmethod
def _get_translation_frontend_modules_domain(cls):
""" Return a domain to list the domain adding web-translations and
+1 -28
View File
@@ -1,11 +1,8 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import hashlib
import json
from odoo import api, fields, models
from odoo import models
from odoo.osv import expression
from odoo.http import request
class IrHttp(models.AbstractModel):
@@ -15,27 +12,3 @@ class IrHttp(models.AbstractModel):
def _get_translation_frontend_modules_domain(cls):
domain = super(IrHttp, cls)._get_translation_frontend_modules_domain()
return expression.OR([domain, [('name', '=', 'portal')]])
@api.model
def get_portal_session_info(self):
# see http_routing/main.py
Modules = request.env['ir.module.module'].sudo()
IrHttp = request.env['ir.http'].sudo()
domain = IrHttp._get_translation_frontend_modules_domain()
modules = Modules.search(
expression.AND([domain, [('state', '=', 'installed')]])
).mapped('name')
user_context = request.session.get_context() if request.session.uid else {}
lang = user_context.get('lang')
translations, _ = request.env['ir.translation'].get_translations_for_webclient(modules, lang)
return {
'is_admin': self.env.user._is_admin(),
'is_system': self.env.user._is_system(),
'is_website_user': self.env.user._is_public(),
'user_id': self.env.user.id,
'is_frontend': True,
'translationURL': '/website/translations',
'cache_hashes': {
'translations': hashlib.sha1(json.dumps(translations, sort_keys=True).encode()).hexdigest(),
},
}
+38 -60
View File
@@ -1,67 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="frontend_layout" name="Main Frontend Layout">
<t t-call="web.layout">
<t t-set="head_website">
<script type="text/javascript">
odoo.session_info = <t t-raw="json.dumps(request.env['ir.http'].get_portal_session_info())"/>;
</script>
<t t-call-assets="web.assets_common" t-js="false"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<t t-call-assets="web.assets_common" t-css="false"/>
<t t-call-assets="web.assets_frontend" t-css="false"/>
</t>
<t t-set="head" t-value="head_website + (head or '')"/>
<t t-set="direction" t-value="request.env['res.lang'].search([('code', '=', request.env.lang)]).direction"/>
<div id="wrapwrap" t-attf-class="#{pageName or ''} #{direction == 'rtl' and 'o_rtl' or ''} #{'o_portal' if is_portal else ''}">
<header id="top" data-anchor="true" t-if="not hide_header">
<nav class="navbar navbar-expand-md navbar-light bg-light">
<div class="container">
<a href="/" class="navbar-brand logo">
<img t-att-src="'/logo.png?company=%s' % res_company.id" t-att-alt="'Logo of %s' % res_company.name" t-att-title="res_company.name"/>
</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#top_menu_collapse">
<span class="navbar-toggler-icon"/>
</button>
<div class="collapse navbar-collapse" id="top_menu_collapse">
<!-- FIXME We want menu to open to the right by default (except cases handled in JS) -->
<ul class="nav navbar-nav ml-auto text-right" id="top_menu">
<li class="nav-item divider" t-ignore="true" t-if="not user_id._is_public()"/>
<li class="nav-item dropdown" t-ignore="true" t-if="not user_id._is_public()">
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
<b>
<span t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) &gt; 25 else user_id.name"/>
</b>
</a>
<div class="dropdown-menu js_usermenu" role="menu">
<a id="o_logout" class="dropdown-item" t-attf-href="/web/session/logout?redirect=/" role="menuitem">Logout</a>
</div>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main>
<div t-if="o_portal_fullwidth_alert" class="alert alert-info alert-dismissible rounded-0 fade show d-print-none css_editable_mode_hidden">
<div class="container">
<t t-raw="o_portal_fullwidth_alert"/>
</div>
<template id="frontend_layout" name="Main Frontend Layout" inherit_id="web.frontend_layout">
<xpath expr="//div[@id='wrapwrap']" position="attributes">
<attribute name="t-attf-class" add="#{request.env['res.lang'].search([('code', '=', request.env.lang)]).direction == 'rtl' and 'o_rtl' or ''}" separator=" "/>
<attribute name="t-attf-class" add="#{'o_portal' if is_portal else ''}" separator=" "/>
</xpath>
<xpath expr="//div[@id='wrapwrap']/header/img" position="replace">
<nav class="navbar navbar-expand-md navbar-light bg-light">
<div class="container">
<a href="/" class="navbar-brand logo">
<img t-att-src="'/logo.png?company=%s' % res_company.id" t-att-alt="'Logo of %s' % res_company.name" t-att-title="res_company.name"/>
</a>
<button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#top_menu_collapse">
<span class="navbar-toggler-icon"/>
</button>
<div class="collapse navbar-collapse" id="top_menu_collapse">
<!-- FIXME We want menu to open to the right by default (except cases handled in JS) -->
<ul class="nav navbar-nav ml-auto text-right" id="top_menu">
<li class="nav-item divider" t-ignore="true" t-if="not user_id._is_public()"/>
<li class="nav-item dropdown" t-ignore="true" t-if="not user_id._is_public()">
<a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">
<b>
<span t-esc="user_id.name[:23] + '...' if user_id.name and len(user_id.name) &gt; 25 else user_id.name"/>
</b>
</a>
<div class="dropdown-menu js_usermenu" role="menu">
<a id="o_logout" class="dropdown-item" t-attf-href="/web/session/logout?redirect=/" role="menuitem">Logout</a>
</div>
</li>
</ul>
</div>
<t t-raw="0"/>
</main>
<footer id="bottom" data-anchor="true" class="bg-light o_footer" t-if="not hide_footer">
<div class="container mt16 mb16" id="footer">
<div class="float-right mb16" t-ignore="true" t-if="not editable">
Powered by <a target="_blank" href="http://www.odoo.com?utm_source=db&amp;utm_medium=portal">Odoo</a>
</div>
</div>
</footer>
</div>
</nav>
</xpath>
<xpath expr="//div[@id='wrapwrap']/main/t[@t-raw='0']" position="before">
<div t-if="o_portal_fullwidth_alert" class="alert alert-info alert-dismissible rounded-0 fade show d-print-none css_editable_mode_hidden">
<div class="container">
<t t-raw="o_portal_fullwidth_alert"/>
</div>
</div>
</t>
</xpath>
</template>
<template id="portal_breadcrumbs" name="Portal Breadcrumbs">
+3 -3
View File
@@ -10,13 +10,13 @@ from odoo.tools.translate import _
class Rating(http.Controller):
@http.route('/rating/<string:token>/<int:rate>', type='http', auth="public")
@http.route('/rating/<string:token>/<int:rate>', type='http', auth="public", website=True)
def open_rating(self, token, rate, **kwargs):
assert rate in (1, 5, 10), "Incorrect rating"
rating = request.env['rating.rating'].sudo().search([('access_token', '=', token)])
if not rating:
return request.not_found()
rate_names={
rate_names = {
5: _("not satisfied"),
1: _("highly dissatisfied"),
10: _("satisfied")
@@ -28,7 +28,7 @@ class Rating(http.Controller):
'rate_name': rate_names[rate], 'rate': rate
})
@http.route(['/rating/<string:token>/<int:rate>/submit_feedback'], type="http", auth="public", methods=['post'])
@http.route(['/rating/<string:token>/<int:rate>/submit_feedback'], type="http", auth="public", methods=['post'], website=True)
def submit_rating(self, token, rate, **kwargs):
rating = request.env['rating.rating'].sudo().search([('access_token', '=', token)])
if not rating:
+2 -11
View File
@@ -1,13 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- External page : thanks message -->
<template id="rating_external_page_view" name="Rating Page Done">
<t t-call="web.layout">
<t t-set="head">
<link rel='stylesheet' href='/web/static/lib/bootstrap/css/bootstrap.css'/>
<link rel='stylesheet' href='/web/static/lib/fontawesome/css/font-awesome.css'/>
</t>
<t t-call="web.frontend_layout">
<div class="container">
<div class="text-center" style="margin-top:128px">
<i class="fa fa-check-circle fa-5x text-success" role="img" aria-label="Thank you!" title="Thank you!"/>
@@ -22,10 +17,7 @@
<!-- External page: rate and submit feedback -->
<template id="rating_external_page_submit" name="Rating Page Submit">
<t t-call="web.layout">
<t t-set="head">
<link rel='stylesheet' href='/web/static/lib/bootstrap/css/bootstrap.css'/>
</t>
<t t-call="web.frontend_layout">
<div class="container">
<div clas="row">
<h1 class="text-center">Thanks! We appreciate your feedback.</h1>
@@ -51,5 +43,4 @@
</div>
</t>
</template>
</odoo>
-16
View File
@@ -19,22 +19,6 @@
<link href="/survey/static/src/css/survey_result.css" rel="stylesheet" type="text/css"></link>
</template>
<template id="survey_web_assets" name="Survey Web Assets">
<script type="text/javascript" src="/web/static/src/js/public/public_root.js"/>
<script type="text/javascript" src="/web/static/src/js/public/public_root_instance.js"/>
<script type="text/javascript" src="/web/static/src/js/public/public_widget.js"/>
<script type="text/javascript" src="/web/static/src/js/services/session.js"></script>
<t t-call="web._assets_helpers">
<t t-call="web._assets_frontend_helpers"/>
</t>
<t t-call="web._assets_bootstrap"/>
<link rel="stylesheet" type="text/less" href="/web/static/src/scss/fonts.scss" />
<!-- Some helper classes (like mt- mb-) are required for survey templates -->
<link rel="stylesheet" type="text/less" href="/web_editor/static/src/scss/web_editor.common.scss"/>
<link rel="stylesheet" type="text/scss" href="/survey/static/src/scss/survey_templates.scss"/>
</template>
<template id="survey_report_assets_pdf" inherit_id="web.report_assets_pdf">
<xpath expr="link[last()]" position="after">
<link rel="stylesheet" type="text/scss" href="/survey/static/src/scss/survey_reports.scss"/>
+11 -38
View File
@@ -132,44 +132,17 @@
</template>
<!-- new layout for survey -->
<template id="survey.layout" name="Survey Layout">
<t t-call="web.layout">
<t t-set="head">
<script type="text/javascript">
odoo.session_info = {
is_admin: <t t-esc="json.dumps(request.env.user._is_admin())"/>,
is_system: <t t-esc="json.dumps(request.env.user._is_system())"/>,
is_website_user: <t t-esc="json.dumps(request.env.user._is_public())"/>,
user_id: <t t-esc="json.dumps(request.env.user.id)" />,
is_frontend: true
};
</script>
<t t-call-assets="web.assets_common"/>
<t t-call-assets="survey.survey_web_assets"/>
<t t-call-assets="survey.survey_assets"/>
</t>
<body>
<header t-if="not survey.certificate">
<div><title>Odoo</title></div>
<div class="text-center">
<img t-attf-src="/web/binary/company_logo" alt="Logo"/>
</div>
</header>
<div id="wrap" class="oe_structure oe_empty"/>
<main>
<t t-raw="0"/>
</main>
</body>
<div t-if="not survey.certificate" class="container mt16 mb8">
<div class="float-right" t-ignore="true" t-if="not editable">
Create a <a target="_blank" href="https://www.odoo.com/page/website-builder">free website</a> with
<a target="_blank" class="badge badge-danger" href="https://www.odoo.com/page/website-builder">Odoo</a>
</div>
<div class="float-left text-muted" itemscope="itemscope" itemtype="https://schema.org/Organization">
Copyright &amp;copy; <span t-field="res_company.name" itemprop="name">Company name</span>
</div>
</div>
</t>
<template id="survey.layout" name="Survey Layout" inherit_id="web.frontend_layout" primary="True">
<xpath expr="//head/t[@t-call-assets][last()]" position="after">
<t t-call-assets="survey.survey_assets"/>
</xpath>
<xpath expr="//header" position="before">
<t t-set="no_header" t-value="no_header or survey.certificate"/>
<t t-set="no_footer" t-value="no_footer or survey.certificate"/>
</xpath>
<xpath expr="//header" position="after">
<div id="wrap" class="oe_structure oe_empty"/>
</xpath>
</template>
<!-- First page of a survey -->
+11 -1
View File
@@ -3,7 +3,7 @@
import hashlib
import json
from odoo import models
from odoo import api, models
from odoo.http import request
from odoo.tools import ustr
@@ -64,6 +64,16 @@ class Http(models.AbstractModel):
},
}
@api.model
def get_frontend_session_info(self):
return {
'is_admin': self.env.user._is_admin(),
'is_system': self.env.user._is_system(),
'is_website_user': self.env.user._is_public(),
'user_id': self.env.user.id,
'is_frontend': True,
}
def get_currencies(self):
Currency = request.env['res.currency']
currencies = Currency.search([]).read(['symbol', 'position', 'decimal_places'])
+55 -12
View File
@@ -382,19 +382,62 @@
</html>
</template>
<template id="web.login_layout" name="Login Layout">
<t t-call="web.layout">
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
<t t-set="head">
<t t-call-assets="web.assets_common" t-js="false"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<t t-call-assets="web.assets_common" t-css="false"/>
<t t-call-assets="web.assets_frontend" t-css="false"/>
</t>
<t t-set="body_classname" t-value="'bg-100'"/>
<template id="web.frontend_layout" name="Frontend Layout" inherit_id="web.layout" primary="True">
<xpath expr="//head/link[last()]" position="after">
<t t-call-assets="web.assets_common" t-js="false"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
</xpath>
<xpath expr="//head/script" position="after">
<script type="text/javascript">
odoo.session_info = <t t-raw="json.dumps(request.env['ir.http'].get_frontend_session_info())"/>;
</script>
<t t-call-assets="web.assets_common" t-css="false"/>
<t t-call-assets="web.assets_frontend" t-css="false"/>
</xpath>
<xpath expr="//t[@t-raw='0']" position="replace">
<div id="wrapwrap" t-attf-class="#{pageName or ''}">
<header t-if="not no_header" id="top" data-anchor="true">
<img class="img-responsive d-block mx-auto"
t-attf-src="/web/binary/company_logo"
alt="Logo"/>
</header>
<main>
<t t-raw="0"/>
</main>
<footer t-if="not no_footer" id="bottom" data-anchor="true" class="bg-light o_footer">
<div id="footer"/>
<div class="o_footer_copyright">
<div class="container py-3">
<div class="row">
<div class="col-sm text-center text-sm-left text-muted">
<span>Copyright &amp;copy;</span> <span t-field="res_company.name" itemprop="name">Company name</span>
</div>
<div class="col-sm text-center text-sm-right">
<t t-call="web.brand_promotion"/>
</div>
</div>
</div>
</div>
</footer>
</div>
</xpath>
</template>
<div class="container mb-5 pb-5">
<div t-attf-class="card border-0 mx-auto mt-5 bg-100 {{login_card_classes}} o_database_list" style="max-width: 300px;">
<template id="brand_promotion" name="Brand Promotion">
<div class="o_brand_promotion">
Powered by <a target="_blank" href="http://www.odoo.com?utm_source=db&amp;utm_medium=portal">Odoo</a>
</div>
</template>
<template id="web.login_layout" name="Login Layout">
<t t-call="web.frontend_layout">
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
<t t-set="body_classname" t-value="'bg-100'"/>
<t t-set="no_header" t-value="True"/>
<t t-set="no_footer" t-value="True"/>
<div class="container py-5">
<div t-attf-class="card border-0 mx-auto bg-100 {{login_card_classes}} o_database_list" style="max-width: 300px;">
<div class="card-body">
<div t-attf-class="text-center pb-3 border-bottom {{'mb-3' if form_small else 'mb-4'}}">
<img t-attf-src="/web/binary/company_logo{{ '?dbname='+db if db else '' }}" alt="Logo" style="max-height:120px; max-width: 100%; width:auto"/>
+10 -24
View File
@@ -1,11 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import hashlib
import logging
from lxml import etree
import traceback
import os
import json
import unittest
import pytz
@@ -19,7 +17,6 @@ from odoo import SUPERUSER_ID
from odoo.http import request
from odoo.tools import config
from odoo.tools.safe_eval import safe_eval
from odoo.osv import expression
from odoo.osv.expression import FALSE_DOMAIN, OR
from odoo.addons.base.models.qweb import QWebException
@@ -317,28 +314,17 @@ class Http(models.AbstractModel):
return super(Http, cls)._xmlid_to_obj(env, xmlid)
@api.model
def get_website_session_info(self):
# see http_routing/main.py
Modules = request.env['ir.module.module'].sudo()
IrHttp = request.env['ir.http'].sudo()
domain = IrHttp._get_translation_frontend_modules_domain()
modules = Modules.search(
expression.AND([domain, [('state', '=', 'installed')]])
).mapped('name')
user_context = request.session.get_context() if request.session.uid else {}
lang = user_context.get('lang')
translations, _ = request.env['ir.translation'].get_translations_for_webclient(modules, lang)
return {
'is_admin': request.env.user._is_admin(),
'is_system': request.env.user._is_system(),
'is_frontend': True,
'translationURL': '/website/translations',
def get_frontend_session_info(self):
session_info = super(Http, self).get_frontend_session_info()
session_info.update({
'is_website_user': request.env.user.id == request.website.user_id.id,
'user_id': request.env.user.id,
'cache_hashes': {
'translations': hashlib.sha1(json.dumps(translations, sort_keys=True).encode()).hexdigest(),
},
}
})
if request.env.user.has_group('website.group_website_publisher'):
session_info.update({
'website_id': request.website.id,
'website_company_id': request.website.company_id.id,
})
return session_info
class ModelConverter(ModelConverter):
+55 -70
View File
@@ -160,7 +160,7 @@
</template>
<template id="layout" name="Main layout" inherit_id="portal.frontend_layout">
<xpath expr="//t[@t-set='head_website']" position="before">
<xpath expr="//html" position="before">
<t t-set="html_data" t-value="{
'lang': lang and lang.replace('_', '-'),
'data-website-id': website.id if website else None,
@@ -172,6 +172,8 @@
'data-main-object': repr(main_object) if editable or translatable else None,
'data-oe-company-name': res_company.name
}"/>
</xpath>
<xpath expr="//head" position="before">
<t t-if="not title">
<t t-if="not additional_title and main_object and 'name' in main_object">
<t t-set="additional_title" t-value="main_object.name"/>
@@ -186,61 +188,51 @@
</t>
<t t-set="x_icon" t-value="'/web/image/website/%s/favicon/' % website.id"/>
</xpath>
<xpath expr="//t[@t-set='head_website']" position="replace">
<t t-set="head_website">
<meta name="generator" content="Odoo"/>
<t t-set="website_meta" t-value="main_object and main_object.get_website_meta() or {}"/>
<meta name="default_title" t-att-content="default_title" groups="website.group_website_designer"/>
<meta t-if="main_object and 'website_indexed' in main_object
and not main_object.website_indexed" name="robots" content="noindex"/>
<t t-set="meta_description" t-value="main_object and 'website_meta_description' in main_object
and main_object.website_meta_description or website_meta_description or website_meta.get('meta_description', '')"/>
<t t-set="meta_keywords" t-value="main_object and 'website_meta_keywords' in main_object
and main_object.website_meta_keywords or website_meta_keywords"/>
<meta t-if="meta_description or editable" name="description" t-att-content="meta_description"/>
<meta t-if="meta_keywords or editable" name="keywords" t-att-content="meta_keywords"/>
<t t-if="main_object">
<meta name="default_description" t-att-content="website_meta_description or website_meta.get('meta_description')" groups="website.group_website_designer"/>
<!-- OpenGraph tags for Facebook sharing -->
<t t-set="opengraph_meta" t-value="website_meta.get('opengraph_meta')"/>
<t t-if="opengraph_meta">
<t t-foreach="opengraph_meta" t-as="og_meta">
<meta t-att-property="og_meta" t-att-content="opengraph_meta[og_meta]"/>
</t>
</t>
<!-- Twitter tags for sharing -->
<t t-set="twitter_meta" t-value="website_meta.get('twitter_meta')"/>
<t t-if="opengraph_meta">
<t t-foreach="twitter_meta" t-as="t_meta">
<meta t-att-name="t_meta" t-att-content="twitter_meta[t_meta]"/>
</t>
<xpath expr="//head/meta[last()]" position="after">
<meta name="generator" content="Odoo"/>
<t t-set="website_meta" t-value="main_object and main_object.get_website_meta() or {}"/>
<meta name="default_title" t-att-content="default_title" groups="website.group_website_designer"/>
<meta t-if="main_object and 'website_indexed' in main_object
and not main_object.website_indexed" name="robots" content="noindex"/>
<t t-set="meta_description" t-value="main_object and 'website_meta_description' in main_object
and main_object.website_meta_description or website_meta_description or website_meta.get('meta_description', '')"/>
<t t-set="meta_keywords" t-value="main_object and 'website_meta_keywords' in main_object
and main_object.website_meta_keywords or website_meta_keywords"/>
<meta t-if="meta_description or editable" name="description" t-att-content="meta_description"/>
<meta t-if="meta_keywords or editable" name="keywords" t-att-content="meta_keywords"/>
<t t-if="main_object">
<meta name="default_description" t-att-content="website_meta_description or website_meta.get('meta_description')" groups="website.group_website_designer"/>
<!-- OpenGraph tags for Facebook sharing -->
<t t-set="opengraph_meta" t-value="website_meta.get('opengraph_meta')"/>
<t t-if="opengraph_meta">
<t t-foreach="opengraph_meta" t-as="og_meta">
<meta t-att-property="og_meta" t-att-content="opengraph_meta[og_meta]"/>
</t>
</t>
<t t-set="languages" t-value="website.get_languages() if website else None"/>
<t t-if="request and request.is_frontend_multilang and website">
<t t-foreach="website.get_alternate_languages(request.httprequest)" t-as="lg">
<link rel="alternate" t-att-hreflang="lg['hreflang']" t-att-href="lg['href']"/>
<!-- Twitter tags for sharing -->
<t t-set="twitter_meta" t-value="website_meta.get('twitter_meta')"/>
<t t-if="opengraph_meta">
<t t-foreach="twitter_meta" t-as="t_meta">
<meta t-att-name="t_meta" t-att-content="twitter_meta[t_meta]"/>
</t>
</t>
</t>
<script type="text/javascript">
odoo.session_info = <t t-raw="json.dumps(request.env['ir.http'].get_website_session_info())"/>;
<t groups="website.group_website_publisher">
odoo.session_info.website_id = <t t-esc="json.dumps(request.website.id)" />;
odoo.session_info.website_company_id = <t t-esc="json.dumps(request.website.company_id.id)" />;
</t>
</script>
<t t-call-assets="web.assets_common" t-js="false"/>
<t t-call-assets="web.assets_frontend" t-js="false"/>
<t t-call-assets="website.assets_editor" t-js="false" groups="website.group_website_publisher"/>
<t t-call-assets="web.assets_common" t-css="false"/>
<t t-call-assets="web.assets_frontend" t-css="false"/>
<t t-call-assets="website.assets_editor" t-css="false" groups="website.group_website_publisher"/>
<t t-set="languages" t-value="website.get_languages() if website else None"/>
<t t-if="request and request.is_frontend_multilang and website">
<t t-foreach="website.get_alternate_languages(request.httprequest)" t-as="lg">
<link rel="alternate" t-att-hreflang="lg['hreflang']" t-att-href="lg['href']"/>
</t>
</t>
</xpath>
<xpath expr="//head/t[@t-js='false'][last()]" position="after">
<t t-call-assets="website.assets_editor" t-js="false" groups="website.group_website_publisher"/>
</xpath>
<xpath expr="//head/t[@t-css='false'][last()]" position="after">
<t t-call-assets="website.assets_editor" t-css="false" groups="website.group_website_publisher"/>
</xpath>
<xpath expr="//header//a[hasclass('navbar-brand')]" position="replace">
<a class="navbar-brand" href="/" t-if="website" t-field="website.name">My Website</a>
</xpath>
@@ -261,6 +253,15 @@
</t>
</t>
</xpath>
<xpath expr="//div[hasclass('o_footer_copyright')]//span[@t-field='res_company.name']" position="after">
<t t-call="website.language_selector"/>
</xpath>
<xpath expr="//t[@t-call='web.brand_promotion']/.." position="attributes">
<attribute name="class" add="o_not_editable" separator=" "/>
<attribute name="t-if">not editable</attribute>
</xpath>
<xpath expr="//div[@id='wrapwrap']" position="after">
<script id='tracking_code' t-if="website and website.google_analytics_key and not editable">
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
@@ -289,31 +290,15 @@
</xpath>
</template>
<template id="layout_footer_copyright" inherit_id="website.layout" name="Footer Copyright">
<xpath expr="//footer" position="inside">
<div class="o_footer_copyright">
<div class="container">
<div class="row">
<div class="col-lg-6 text-muted text-center text-md-left">
<span>Copyright &amp;copy;</span> <span t-field="res_company.name" itemprop="name">Company name</span>
<t t-call="website.language_selector"/>
</div>
<div class="col-lg-6 text-right o_not_editable" t-if="not editable">
<t t-call="website.brand_promotion"/>
</div>
</div>
</div>
<template id="brand_promotion" inherit_id="web.brand_promotion" name="Brand Promotion">
<xpath expr="//div[hasclass('o_brand_promotion')]" position="replace">
<div class="o_brand_promotion">
Create a <a target="_blank" href="http://www.odoo.com/page/website-builder?utm_source=db&amp;utm_medium=website">free website</a> with
<a target="_blank" class="badge badge-danger" href="http://www.odoo.com/page/website-builder?utm_source=db&amp;utm_medium=website">Odoo</a>
</div>
</xpath>
</template>
<template id="brand_promotion" name="Brand Promotion">
<div class="o_brand_promotion">
Create a <a target="_blank" href="http://www.odoo.com/page/website-builder?utm_source=db&amp;utm_medium=website">free website</a> with
<a target="_blank" class="badge badge-danger" href="http://www.odoo.com/page/website-builder?utm_source=db&amp;utm_medium=website">Odoo</a>
</div>
</template>
<template id="layout_logo_show" inherit_id="website.layout" name="Show Logo">
<xpath expr="//header//a[hasclass('navbar-brand')]" position="replace">
<a href="/" class="navbar-brand logo">
+1 -1
View File
@@ -6,7 +6,7 @@
'description': """This module lets you use the full power of certifications within your courses.""",
'category': 'Hidden',
'version': '1.0',
'depends': ['website_slides', 'website_survey'],
'depends': ['website_slides', 'survey'],
'installable': True,
'auto_install': True,
'data': [
-2
View File
@@ -1,2 +0,0 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-21
View File
@@ -1,21 +0,0 @@
# coding: utf-8
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Website Survey',
'version': '1.0',
'category': 'Marketing',
'description': """
Create beautiful surveys and display them on your website
=========================================================
Use the styling and layout of your website for your surveys.
""",
'website': 'https://www.odoo.com/page/survey',
'depends': ['website', 'survey'],
'data': [
'views/website_survey_templates.xml',
],
'installable': True,
'auto_install': True
}
@@ -1,18 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<odoo>
<template id="website_survey_layout" inherit_id="survey.layout" name="Website Survey Layout">
<xpath expr="t" position="replace">
<t t-call="website.layout">
<t t-set="head">
<t t-raw="head"/>
<t t-call-assets="survey.survey_assets"/>
</t>
<t t-raw="0"/>
</t>
</xpath>
<xpath expr="t" position="before">
<t t-set="hide_header" t-value="survey.certificate" />
<t t-set="hide_footer" t-value="survey.certificate" />
</xpath>
</template>
</odoo>