diff options
| author | Romain Derie <rde@odoo.com> | 2019-11-22 13:20:23 +0000 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2020-01-29 14:53:38 +0000 |
| commit | 3028e9a8649ae5d9b23a1bdb989b903645ede5fe (patch) | |
| tree | cf54e7c116cee0cb0cea3f06d65f897e8531596e /addons/website/static/src | |
| parent | 3bce5277e378fd499bf2d0fed8c62929165b7871 (diff) | |
[IMP] website: introduce cookies bar on website
With this commit, it is now possible to activate a cookies bar on a
website through the res.settings.
The cookies bar can be edited in the frontend by entering edit mode.
The cookies bar will appear until the user clicks on 'I agree'.
Part of https://github.com/odoo/odoo/pull/41294
task-2087003
closes odoo/odoo#41294
Signed-off-by: Quentin Smetz (qsm) <qsm@odoo.com>
Diffstat (limited to 'addons/website/static/src')
7 files changed, 204 insertions, 8 deletions
diff --git a/addons/website/static/src/js/backend/res_config_settings.js b/addons/website/static/src/js/backend/res_config_settings.js index 47a52579447..ad9373d26f1 100644 --- a/addons/website/static/src/js/backend/res_config_settings.js +++ b/addons/website/static/src/js/backend/res_config_settings.js @@ -1,7 +1,14 @@ odoo.define('website.settings', function (require) { -var BaseSettingController = require('base.settings').Controller; -var FormController = require('web.FormController'); +const BaseSettingController = require('base.settings').Controller; +const core = require('web.core'); +const Dialog = require('web.Dialog'); +const FieldBoolean = require('web.basic_fields').FieldBoolean; +const fieldRegistry = require('web.field_registry'); +const FormController = require('web.FormController'); + +const QWeb = core.qweb; +const _t = core._t; BaseSettingController.include({ @@ -33,4 +40,34 @@ BaseSettingController.include({ }, }); +const WebsiteCookiesbarField = FieldBoolean.extend({ + xmlDependencies: ['/website/static/src/xml/website.res_config_settings.xml'], + + _onChange: function () { + const checked = this.$input[0].checked; + if (!checked) { + return this._setValue(checked); + } + + const cancelCallback = () => this.$input[0].checked = !checked; + Dialog.confirm(this, null, { + title: _t("Please confirm"), + $content: QWeb.render('website.res_config_settings.cookies_modal_main'), + buttons: [{ + text: 'Do not activate', + classes: 'btn-primary', + close: true, + click: cancelCallback, + }, + { + text: 'Activate anyway', + close: true, + click: () => this._setValue(checked), + }], + cancel_callback: cancelCallback, + }); + }, +}); + +fieldRegistry.add('website_cookiesbar_field', WebsiteCookiesbarField); }); diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js index 9765bc57473..0ef07ccc12e 100644 --- a/addons/website/static/src/js/editor/snippets.options.js +++ b/addons/website/static/src/js/editor/snippets.options.js @@ -1,6 +1,7 @@ odoo.define('website.editor.snippets.options', function (require) { 'use strict'; +require('website.s_popup_options'); var core = require('web.core'); var Dialog = require('web.Dialog'); const wUtils = require('website.utils'); @@ -913,6 +914,63 @@ options.registry.anchor = options.Class.extend({ }, }); +options.registry.CookiesBar = options.registry.SnippetPopup.extend({ + xmlDependencies: (options.registry.SnippetPopup.prototype.xmlDependencies || []).concat( + ['/website/static/src/xml/website.cookies_bar.xml'] + ), + + //-------------------------------------------------------------------------- + // Options + //-------------------------------------------------------------------------- + + /** + * Change the cookies bar layout. + * + * @see this.selectClass for parameters + */ + selectLayout: function (previewMode, widgetValue, params) { + let websiteId; + this.trigger_up('context_get', { + callback: function (ctx) { + websiteId = ctx['website_id']; + }, + }); + + const $template = $(qweb.render(`website.cookies_bar.${widgetValue}`, { + websiteId: websiteId, + })); + + const $content = this.$target.find('.s_popup_content'); + const selectorsToKeep = [ + '.o_cookies_bar_text_button', + '.o_cookies_bar_text_policy', + '.o_cookies_bar_text_title', + '.o_cookies_bar_text_primary', + '.o_cookies_bar_text_secondary', + ]; + + if (this.$savedSelectors === undefined) { + this.$savedSelectors = []; + } + + for (const selector of selectorsToKeep) { + const $currentLayoutEls = $content.find(selector).contents(); + const $newLayoutEl = $template.find(selector); + if ($currentLayoutEls.length) { + // save value before change, eg 'title' is not inside 'discrete' template + // but we want to preserve it in case of select another layout later + this.$savedSelectors[selector] = $currentLayoutEls; + } + const $savedSelector = this.$savedSelectors[selector]; + if ($newLayoutEl.length && $savedSelector && $savedSelector.length) { + $newLayoutEl.empty().append($savedSelector); + } + } + + $content.empty().append($template); + }, +}); + /** * Allows edition of 'cover_properties' in website models which have such * fields (blogs, posts, events, ...). diff --git a/addons/website/static/src/snippets/s_popup/000.js b/addons/website/static/src/snippets/s_popup/000.js index 0e7983002f0..16820dcc988 100644 --- a/addons/website/static/src/snippets/s_popup/000.js +++ b/addons/website/static/src/snippets/s_popup/000.js @@ -8,14 +8,14 @@ const utils = require('web.utils'); const PopupWidget = publicWidget.Widget.extend({ selector: '.s_popup', events: { - 'click .s_popup_close': '_onCloseClick', + 'click .js_close_popup': '_onCloseClick', }, /** * @override */ start: function () { - if (!utils.get_cookie(this.$target.attr('id'))) { + if (!utils.get_cookie(this.$el.attr('id'))) { this._bindPopup(); } return this._super(...arguments); @@ -77,8 +77,8 @@ const PopupWidget = publicWidget.Widget.extend({ * @private */ _onCloseClick: function () { - const nbDays = this.$target.find('.s_popup_main').data('consentsDelay'); - utils.set_cookie(this.$target.attr('id'), true, nbDays * 24 * 60 * 60); + const nbDays = this.$el.find('.s_popup_main').data('consentsDuration'); + utils.set_cookie(this.$el.attr('id'), true, nbDays * 24 * 60 * 60); this._hidePopup(); }, }); diff --git a/addons/website/static/src/snippets/s_popup/000.scss b/addons/website/static/src/snippets/s_popup/000.scss index bb14c100322..71566512868 100644 --- a/addons/website/static/src/snippets/s_popup/000.scss +++ b/addons/website/static/src/snippets/s_popup/000.scss @@ -1,7 +1,8 @@ // s_popup .s_popup_main { .s_popup_content { - min-height: var(--o-we-toolbar-height); + // keep lower than <p> height (cookies bar) + min-height: $o-font-size-base * $o-line-height-base; box-shadow: $modal-content-box-shadow-sm-up; .container { // keep margin when fixed bottom diff --git a/addons/website/static/src/snippets/s_popup/options.js b/addons/website/static/src/snippets/s_popup/options.js index 4c43041c614..842cc284c83 100644 --- a/addons/website/static/src/snippets/s_popup/options.js +++ b/addons/website/static/src/snippets/s_popup/options.js @@ -8,7 +8,10 @@ options.registry.SnippetPopup = options.Class.extend({ * @override */ start: function () { - this.$target.find('.s_popup_close').on('click', () => { + // Note: the link are excluded here so that internal modal buttons do + // not close the popup as we want to allow edition of those buttons. + this.$target.find('.js_close_popup:not(a, .btn)').on('click', ev => { + ev.stopPropagation(); this.onTargetHide(); this.trigger_up('snippet_option_visibility_update', {show: false}); }); diff --git a/addons/website/static/src/xml/website.cookies_bar.xml b/addons/website/static/src/xml/website.cookies_bar.xml new file mode 100644 index 00000000000..8f43ccb3698 --- /dev/null +++ b/addons/website/static/src/xml/website.cookies_bar.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates id="template" xml:space="preserve"> + <t t-name="website.cookies_bar.text_title"> + <div class="o_cookies_bar_text_title"> + <p>Respecting your privacy is our priority.</p> + </div> + </t> + <t t-name="website.cookies_bar.text_primary"> + <div class="o_cookies_bar_text_primary"> + We use cookies to provide you a better user experience. + </div> + </t> + <t t-name="website.cookies_bar.text_secondary"> + <div class="o_cookies_bar_text_secondary"> + We use them to store info about your habits on our website. It will helps us to provide you the very best experience and customize what you see. + <br/> + By clicking on this banner, you give us permission to collect data. + </div> + </t> + + <t t-name="website.cookies_bar.discrete"> + <section class="pt4 pb4"> + <div class="container text-600 d-flex align-items-center"> + <div class="mb0"> + <t t-call="website.cookies_bar.text_primary"/> + </div> + <a href="/cookie-policy" class="o_cookies_bar_text_policy btn btn-link btn-sm text-nowrap ml-auto">Cookie Policy</a> + <a href="#" role="button" class="js_close_popup o_cookies_bar_text_button btn btn-primary btn-sm text-nowrap">I agree</a> + </div> + </section> + </t> + <t t-name="website.cookies_bar.classic"> + <section class="pt24 pb24"> + <div class="container text-600 d-flex align-items-center"> + <div> + <div class="h3 text-900"> + <t t-call="website.cookies_bar.text_title"/> + </div> + <div class="small"> + <t t-call="website.cookies_bar.text_primary"/> + </div> + <div class="small"> + <t t-call="website.cookies_bar.text_secondary"/> + </div> + </div> + <div class="ml-auto"> + <a href="#" role="button" class="js_close_popup o_cookies_bar_text_button btn btn-primary btn-block text-nowrap">I agree</a> + <a href="/cookie-policy" class="o_cookies_bar_text_policy btn btn-link btn-sm text-nowrap">Cookie Policy</a> + </div> + </div> + </section> + </t> + <t t-name="website.cookies_bar.popup"> + <section class="p-5"> + <div class="container text-800 text-center"> + <img t-attf-src="/web/image/website/#{websiteId}/logo/250x250" class="img img-fluid" alt="Website Logo"/> + <br/><br/> + <div class="h3"> + <t t-call="website.cookies_bar.text_title"/> + </div> + <br/> + <div class="mb0 text-left"> + <t t-call="website.cookies_bar.text_primary"/> + </div> + <div class="text-left"> + <t t-call="website.cookies_bar.text_secondary"/> + </div> + <br/> + <a href="#" role="button" class="js_close_popup o_cookies_bar_text_button btn btn-primary btn-lg">Cookie Policy</a> + <br/> + <a href="/cookie-policy" class="o_cookies_bar_text_policy btn btn-link">I agree</a> + </div> + </section> + </t> +</templates> diff --git a/addons/website/static/src/xml/website.res_config_settings.xml b/addons/website/static/src/xml/website.res_config_settings.xml new file mode 100644 index 00000000000..6b6d48172bd --- /dev/null +++ b/addons/website/static/src/xml/website.res_config_settings.xml @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<templates id="template" xml:space="preserve"> +<t t-name="website.res_config_settings.cookies_modal_main"> + <main role="alert"> + <p> + <b>Cookie bars may significantly impair the experience</b> of + your visitors. We recommend you avoid them unless you have + verified with a legal advisor that you absolutely need cookie + consent in your country. + </p> + <p> + For session cookies, authentification and analytics*, + <b>you do not need to ask for the consent</b> (see e.g. Opinion + 04/2012 on Cookie Consent Exemption by the EU Art.29 WP). + </p> + <p> + * provided that your analytics is anonymized, which is not the + case by default with Google Analytics. + </p> + </main> +</t> +</templates> |
