From 3028e9a8649ae5d9b23a1bdb989b903645ede5fe Mon Sep 17 00:00:00 2001 From: Romain Derie Date: Fri, 22 Nov 2019 13:20:23 +0000 Subject: [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) --- .../static/src/js/backend/res_config_settings.js | 41 +++++++++++- .../static/src/js/editor/snippets.options.js | 58 +++++++++++++++++ addons/website/static/src/snippets/s_popup/000.js | 8 +-- .../website/static/src/snippets/s_popup/000.scss | 3 +- .../website/static/src/snippets/s_popup/options.js | 5 +- .../website/static/src/xml/website.cookies_bar.xml | 75 ++++++++++++++++++++++ .../static/src/xml/website.res_config_settings.xml | 22 +++++++ 7 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 addons/website/static/src/xml/website.cookies_bar.xml create mode 100644 addons/website/static/src/xml/website.res_config_settings.xml (limited to 'addons/website/static') 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

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 @@ + + + +

+

Respecting your privacy is our priority.

+
+ + +
+ We use cookies to provide you a better user experience. +
+
+ +
+ 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. +
+ By clicking on this banner, you give us permission to collect data. +
+
+ + +
+
+
+ +
+ Cookie Policy + I agree +
+
+
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+ Website Logo +

+
+ +
+
+
+ +
+
+ +
+
+ Cookie Policy +
+ I agree +
+
+
+ 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 @@ + + + +
+

+ Cookie bars may significantly impair the experience 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. +

+

+ For session cookies, authentification and analytics*, + you do not need to ask for the consent (see e.g. Opinion + 04/2012 on Cookie Consent Exemption by the EU Art.29 WP). +

+

+ * provided that your analytics is anonymized, which is not the + case by default with Google Analytics. +

+
+
+
-- cgit v1.2.3