diff --git a/addons/im_livechat/static/src/legacy/widgets/livechat_button.js b/addons/im_livechat/static/src/legacy/widgets/livechat_button.js index 4a5758418cf..002ce0ed1f9 100644 --- a/addons/im_livechat/static/src/legacy/widgets/livechat_button.js +++ b/addons/im_livechat/static/src/legacy/widgets/livechat_button.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import time from 'web.time'; -import utils from 'web.utils'; +import {getCookie} from 'web.utils.cookies'; import Widget from 'web.Widget'; const LivechatButton = Widget.extend({ @@ -33,7 +33,7 @@ const LivechatButton = Widget.extend({ * @return {integer} operator_id.partner_id.id if the cookie is set */ _get_previous_operator_id() { - const cookie = utils.get_cookie('im_livechat_previous_operator_pid'); + const cookie = getCookie('im_livechat_previous_operator_pid'); if (cookie) { return cookie; } diff --git a/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js b/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js index 5f56aeeea6b..f826c4e3f36 100644 --- a/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js +++ b/addons/im_livechat/static/src/legacy/widgets/public_livechat_window/public_livechat_window.js @@ -4,7 +4,8 @@ import config from 'web.config'; import { _t, qweb } from 'web.core'; import Widget from 'web.Widget'; -import { set_cookie, unaccent } from 'web.utils'; +import {unaccent} from 'web.utils'; +import {setCookie} from 'web.utils.cookies'; /** * This is the widget that represent windows of livechat in the frontend. @@ -137,7 +138,7 @@ const PublicLivechatWindow = Widget.extend({ folded = !this.messaging.publicLivechatGlobal.publicLivechat.isFolded; } this.messaging.publicLivechatGlobal.publicLivechat.update({ isFolded: folded }); - set_cookie('im_livechat_session', unaccent(JSON.stringify(this.messaging.publicLivechatGlobal.publicLivechat.widget.toData()), true), 60 * 60); + setCookie('im_livechat_session', unaccent(JSON.stringify(this.messaging.publicLivechatGlobal.publicLivechat.widget.toData()), true), 60 * 60, 'required'); this.updateVisualFoldState(); }, /** diff --git a/addons/im_livechat/static/src/public_models/livechat_button_view.js b/addons/im_livechat/static/src/public_models/livechat_button_view.js index 8879a50dd35..a8e05351423 100644 --- a/addons/im_livechat/static/src/public_models/livechat_button_view.js +++ b/addons/im_livechat/static/src/public_models/livechat_button_view.js @@ -4,7 +4,8 @@ import { registerModel } from '@mail/model/model_core'; import { attr, one } from '@mail/model/model_field'; import { clear } from '@mail/model/model_field_command'; -import { get_cookie, set_cookie, unaccent } from 'web.utils'; +import {unaccent} from 'web.utils'; +import {getCookie, setCookie, deleteCookie} from 'web.utils.cookies'; registerModel({ name: 'LivechatButtonView', @@ -106,18 +107,18 @@ registerModel({ }, closeChat() { this.messaging.publicLivechatGlobal.update({ chatWindow: clear() }); - set_cookie('im_livechat_session', "", -1); // remove cookie + deleteCookie('im_livechat_session'); }, /** * Called when the visitor leaves the livechat chatter the first time (first click on X button) * this will deactivate the mail_channel, notify operator that visitor has left the channel. */ leaveSession() { - const cookie = get_cookie('im_livechat_session'); + const cookie = getCookie('im_livechat_session'); if (cookie) { const channel = JSON.parse(cookie); this.messaging.rpc({ route: '/im_livechat/visitor_leave_session', params: { uuid: channel.uuid } }); - set_cookie('im_livechat_session', "", -1); // remove cookie + deleteCookie('im_livechat_session'); } }, openChat() { @@ -152,7 +153,7 @@ registerModel({ } this.openChat(); } else if (!this.messaging.device.isSmall && this.messaging.publicLivechatGlobal.rule.action === 'auto_popup') { - const autoPopupCookie = get_cookie('im_livechat_auto_popup'); + const autoPopupCookie = getCookie('im_livechat_auto_popup'); if (!autoPopupCookie || JSON.parse(autoPopupCookie)) { this.update({ autoOpenChatTimeout: setTimeout( @@ -182,7 +183,7 @@ registerModel({ if (this.isOpeningChat) { return; } - const cookie = get_cookie('im_livechat_session'); + const cookie = getCookie('im_livechat_session'); let def; this.update({ isOpeningChat: true }); clearTimeout(this.autoOpenChatTimeout); @@ -224,12 +225,12 @@ registerModel({ this.messaging.publicLivechatGlobal.chatWindow.renderMessages(); this.messaging.publicLivechatGlobal.update({ notificationHandler: {} }); - set_cookie('im_livechat_session', unaccent(JSON.stringify(this.messaging.publicLivechatGlobal.publicLivechat.widget.toData()), true), 60 * 60); - set_cookie('im_livechat_auto_popup', JSON.stringify(false), 60 * 60); + setCookie('im_livechat_session', unaccent(JSON.stringify(this.messaging.publicLivechatGlobal.publicLivechat.widget.toData()), true), 60 * 60, 'required'); + setCookie('im_livechat_auto_popup', JSON.stringify(false), 60 * 60, 'optional'); if (this.messaging.publicLivechatGlobal.publicLivechat.operator) { const operatorPidId = this.messaging.publicLivechatGlobal.publicLivechat.operator.id; const oneWeek = 7 * 24 * 60 * 60; - set_cookie('im_livechat_previous_operator_pid', operatorPidId, oneWeek); + setCookie('im_livechat_previous_operator_pid', operatorPidId, oneWeek, 'optional'); } }); } diff --git a/addons/im_livechat/static/src/public_models/public_livechat_global.js b/addons/im_livechat/static/src/public_models/public_livechat_global.js index 221c8496a77..fb700077ce0 100644 --- a/addons/im_livechat/static/src/public_models/public_livechat_global.js +++ b/addons/im_livechat/static/src/public_models/public_livechat_global.js @@ -5,8 +5,8 @@ import { attr, many, one } from '@mail/model/model_field'; import { clear } from '@mail/model/model_field_command'; import { qweb } from 'web.core'; - -import { get_cookie, Markup, set_cookie } from 'web.utils'; +import { Markup } from 'web.utils'; +import {getCookie, setCookie, deleteCookie} from 'web.utils.cookies'; registerModel({ name: 'PublicLivechatGlobal', @@ -14,7 +14,7 @@ registerModel({ _created() { // History tracking const page = window.location.href.replace(/^.*\/\/[^/]+/, ''); - const pageHistory = get_cookie(this.LIVECHAT_COOKIE_HISTORY); + const pageHistory = getCookie(this.LIVECHAT_COOKIE_HISTORY); let urlHistory = []; if (pageHistory) { urlHistory = JSON.parse(pageHistory) || []; @@ -24,7 +24,7 @@ registerModel({ while (urlHistory.length > this.HISTORY_LIMIT) { urlHistory.shift(); } - set_cookie(this.LIVECHAT_COOKIE_HISTORY, JSON.stringify(urlHistory), 60 * 60 * 24); // 1 day cookie + setCookie(this.LIVECHAT_COOKIE_HISTORY, JSON.stringify(urlHistory), 60 * 60 * 24, 'optional'); // 1 day cookie } if (this.isAvailable) { this.willStart(); @@ -44,7 +44,7 @@ registerModel({ await this._willStartChatbot(); }, async _willStart() { - const cookie = get_cookie('im_livechat_session'); + const cookie = getCookie('im_livechat_session'); if (cookie) { const channel = JSON.parse(cookie); const history = await this.messaging.rpc({ @@ -98,7 +98,7 @@ registerModel({ }), }); } else if (this.history !== null && this.history.length !== 0) { - const sessionCookie = get_cookie('im_livechat_session'); + const sessionCookie = getCookie('im_livechat_session'); if (sessionCookie) { this.update({ sessionCookie }); } @@ -120,7 +120,7 @@ registerModel({ // -> remove cookie to force opening the popup again // -> initialize necessary state // -> batch welcome message (see '_sendWelcomeChatbotMessage') - set_cookie('im_livechat_auto_popup', '', -1); + deleteCookie('im_livechat_auto_popup'); this.update({ history: clear() }); this.update({ rule: this.livechatInit.rule }); } else if (this.chatbot.state === 'restore_session') { diff --git a/addons/im_livechat/static/src/public_models/public_livechat_global_notification_handler.js b/addons/im_livechat/static/src/public_models/public_livechat_global_notification_handler.js index 96e592c5ab2..e96418c9634 100644 --- a/addons/im_livechat/static/src/public_models/public_livechat_global_notification_handler.js +++ b/addons/im_livechat/static/src/public_models/public_livechat_global_notification_handler.js @@ -6,6 +6,7 @@ import { increment } from '@mail/model/model_field_command'; import session from 'web.session'; import utils from 'web.utils'; +import {getCookie} from 'web.utils.cookies'; registerModel({ name: 'PublicLivechatGlobalNotificationHandler', @@ -28,7 +29,7 @@ registerModel({ if (payload.id !== this.messaging.publicLivechatGlobal.publicLivechat.id) { return; } - const cookie = utils.get_cookie(this.messaging.publicLivechatGlobal.LIVECHAT_COOKIE_HISTORY); + const cookie = getCookie(this.messaging.publicLivechatGlobal.LIVECHAT_COOKIE_HISTORY); const history = cookie ? JSON.parse(cookie) : []; session.rpc('/im_livechat/history', { pid: this.messaging.publicLivechatGlobal.publicLivechat.operator.id, diff --git a/addons/survey/static/src/js/survey_form.js b/addons/survey/static/src/js/survey_form.js index eb2905a11c0..894ebbd66ca 100644 --- a/addons/survey/static/src/js/survey_form.js +++ b/addons/survey/static/src/js/survey_form.js @@ -8,7 +8,7 @@ var config = require('web.config'); var core = require('web.core'); var Dialog = require('web.Dialog'); var dom = require('web.dom'); -var utils = require('web.utils'); +const {getCookie, setCookie, deleteCookie} = require('web.utils.cookies'); var SurveyPreloadImageMixin = require('survey.preload_image_mixin'); const { SurveyImageZoomer } = require("@survey/js/survey_image_zoomer"); @@ -48,8 +48,8 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa self.imgZoomer = false; // Add Survey cookie to retrieve the survey if you quit the page and restart the survey. - if (!utils.get_cookie('survey_' + self.options.surveyToken)) { - utils.set_cookie('survey_' + self.options.surveyToken, self.options.answerToken, 60*60*24); + if (!getCookie('survey_' + self.options.surveyToken)) { + setCookie('survey_' + self.options.surveyToken, self.options.answerToken, 60 * 60 * 24, 'optional'); } // Init fields @@ -502,7 +502,7 @@ publicWidget.registry.SurveyFormWidget = publicWidget.Widget.extend(SurveyPreloa var selectorsToFadeout = ['.o_survey_form_content']; if (options.isFinish) { selectorsToFadeout.push('.breadcrumb', '.o_survey_timer'); - utils.set_cookie('survey_' + self.options.surveyToken, '', -1); // delete cookie + deleteCookie('survey_' + self.options.surveyToken); } self.$(selectorsToFadeout.join(',')).fadeOut(this.fadeInOutDelay, function () { resolveFadeOut(); diff --git a/addons/utm/models/ir_http.py b/addons/utm/models/ir_http.py index 451078ffaa9..6059b7b5d17 100644 --- a/addons/utm/models/ir_http.py +++ b/addons/utm/models/ir_http.py @@ -16,7 +16,7 @@ class IrHttp(models.AbstractModel): domain = cls.get_utm_domain_cookies() for url_parameter, __, cookie_name in request.env['utm.mixin'].tracking_fields(): if url_parameter in request.params and request.httprequest.cookies.get(cookie_name) != request.params[url_parameter]: - response.set_cookie(cookie_name, request.params[url_parameter], domain=domain) + response.set_cookie(cookie_name, request.params[url_parameter], domain=domain, cookie_type='optional') @classmethod def _post_dispatch(cls, response): diff --git a/addons/web/static/src/core/browser/cookie_service.js b/addons/web/static/src/core/browser/cookie_service.js index 3bc89b4d094..6f835cbd8a2 100644 --- a/addons/web/static/src/core/browser/cookie_service.js +++ b/addons/web/static/src/core/browser/cookie_service.js @@ -36,6 +36,8 @@ function makeCookieService() { } let cookie = getCurrent(); function setCookie(key, value, ttl) { + // TODO When this will be used from website pages, recover the + // optional cookie mechanism. document.cookie = cookieToString(key, value, ttl); cookie = getCurrent(); } diff --git a/addons/web/static/src/legacy/js/common_env.js b/addons/web/static/src/legacy/js/common_env.js index 16c9e262837..887f14868fd 100644 --- a/addons/web/static/src/legacy/js/common_env.js +++ b/addons/web/static/src/legacy/js/common_env.js @@ -23,7 +23,7 @@ odoo.define("web.commonEnv", function (require) { const rpc = require("web.rpc"); const session = require("web.session"); const { _t } = require("web.translation"); - const utils = require("web.utils"); + const {getCookie, setCookie} = require('web.utils.cookies'); const browser = { clearInterval: window.clearInterval.bind(window), @@ -54,7 +54,7 @@ odoo.define("web.commonEnv", function (require) { return jsonRpc(...arguments); }, getCookie() { - return utils.get_cookie(...arguments); + return getCookie(...arguments); }, httpRequest(route, params = {}, readMethod = 'json') { const info = { @@ -90,7 +90,7 @@ odoo.define("web.commonEnv", function (require) { return session.rpc(query.route, query.params, options); }, setCookie() { - utils.set_cookie(...arguments); + setCookie(...arguments); }, }, session, diff --git a/addons/web/static/src/legacy/js/core/cookie_utils.js b/addons/web/static/src/legacy/js/core/cookie_utils.js index 2aeca9bd370..1696539b547 100644 --- a/addons/web/static/src/legacy/js/core/cookie_utils.js +++ b/addons/web/static/src/legacy/js/core/cookie_utils.js @@ -1,14 +1,14 @@ odoo.define('web.utils.cookies', function (require) { "use strict"; -return { +const utils = { /** * Reads the cookie described by the given name. * * @param {string} cookieName * @returns {string} */ - get_cookie(cookieName) { + getCookie(cookieName) { var cookies = document.cookie ? document.cookie.split('; ') : []; for (var i = 0, l = cookies.length; i < l; i++) { var parts = cookies[i].split('='); @@ -21,21 +21,47 @@ return { } return ""; }, + /** + * Check if cookie can be written. + * + * @param {String} type the type of the cookie + * @returns {boolean} + */ + isAllowedCookie(type) { + return true; + }, /** * Creates a cookie. * * @param {string} name the name of the cookie * @param {string} value the value stored in the cookie * @param {integer} ttl time to live of the cookie in millis. -1 to erase the cookie. + * @param {string} type the type of the cookies ('required' as default value) */ - set_cookie(name, value, ttl) { + setCookie(name, value, ttl = 31536000, type = 'required') { ttl = ttl || 24 * 60 * 60 * 365; + if (utils.isAllowedCookie(type)) { + document.cookie = [ + `${name}=${value}`, + 'path=/', + `max-age=${ttl}`, + `expires=${new Date(new Date().getTime() + ttl * 1000).toGMTString()}`, + ].join(';'); + } + }, + /** + * Deletes a cookie. + * + * @param {string} name the name of the cookie + */ + deleteCookie(name) { document.cookie = [ - `${name}=${value}`, + `${name}=`, 'path=/', - `max-age=${ttl}`, - `expires=${new Date(new Date().getTime() + ttl * 1000).toGMTString()}` + `max-age=-1`, + `expires=${new Date(new Date().getTime() - 1000).toGMTString()}`, ].join(';'); }, }; +return utils; }); diff --git a/addons/web/static/src/legacy/js/core/session.js b/addons/web/static/src/legacy/js/core/session.js index e4b276215d8..b5880b0f05c 100644 --- a/addons/web/static/src/legacy/js/core/session.js +++ b/addons/web/static/src/legacy/js/core/session.js @@ -4,7 +4,7 @@ odoo.define('web.Session', function (require) { var ajax = require('web.ajax'); var core = require('web.core'); var mixins = require('web.mixins'); -var utils = require('web.utils'); +const {setCookie} = require('web.utils.cookies'); const { session } = require('@web/session'); const { loadJS } = require('@web/core/assets'); @@ -172,11 +172,12 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, { * @param name the cookie's name * @param value the cookie's value * @param ttl the cookie's time to live, 1 year by default, set to -1 to delete + * @param type the type of the cookies ('required' as default value) */ - set_cookie: function (name, value, ttl) { + set_cookie(name, value, ttl, type = 'required') { if (!this.name) { return; } ttl = ttl || 24*60*60*365; - utils.set_cookie(this.name + '|' + name, value, ttl); + setCookie(this.name + '|' + name, value, ttl, type); }, /** * Load additional web addons of that instance and init them @@ -328,7 +329,7 @@ var Session = core.Class.extend(mixins.EventDispatcherMixin, { return a - b; } }).join(','); - utils.set_cookie('cids', hash.cids || String(main_company_id)); + setCookie('cids', hash.cids || String(main_company_id), 24 * 60 * 60 * 365, 'required'); $.bbq.pushState({'cids': hash.cids}, 0); location.reload(); }, diff --git a/addons/web/static/src/legacy/js/core/utils.js b/addons/web/static/src/legacy/js/core/utils.js index 7e04354e90e..9a654e95af1 100644 --- a/addons/web/static/src/legacy/js/core/utils.js +++ b/addons/web/static/src/legacy/js/core/utils.js @@ -8,7 +8,6 @@ odoo.define('web.utils', function (require) { */ var translation = require('web.translation'); -var cookieUtils = require('web.utils.cookies'); const { Component } = owl; @@ -316,7 +315,7 @@ function Markup(v, ...exprs) { return new _Markup(s); } -var utils = Object.assign({ +const utils = { AlreadyDefinedPatchError, UnknownPatchError, Markup, @@ -1129,7 +1128,7 @@ var utils = Object.assign({ } return curr; }, -}, cookieUtils); +}; return utils; diff --git a/addons/web/static/src/legacy/js/public/public_root.js b/addons/web/static/src/legacy/js/public/public_root.js index a755bc81964..4a07fc8317d 100644 --- a/addons/web/static/src/legacy/js/public/public_root.js +++ b/addons/web/static/src/legacy/js/public/public_root.js @@ -3,7 +3,7 @@ import dom from 'web.dom'; import legacyEnv from 'web.public_env'; import session from 'web.session'; -import utils from 'web.utils'; +import {getCookie} from 'web.utils.cookies'; import publicWidget from 'web.public.widget'; import { registry } from '@web/core/registry'; @@ -37,7 +37,7 @@ function getLang() { var html = document.documentElement; return (html.getAttribute('lang') || 'en_US').replace('-', '_'); } -var lang = utils.get_cookie('frontend_lang') || getLang(); // FIXME the cookie value should maybe be in the ctx? +const lang = getCookie('frontend_lang') || getLang(); // FIXME the cookie value should maybe be in the ctx? // momentjs don't have config for en_US, so avoid useless RPC var localeDef = lang !== 'en_US' ? loadJS('/web/webclient/locale/' + lang.replace('-', '_')) : Promise.resolve(); diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py index da49235192c..e6ccc3e4ed4 100644 --- a/addons/website/__manifest__.py +++ b/addons/website/__manifest__.py @@ -129,6 +129,7 @@ 'website/static/src/js/post_link.js', 'website/static/src/js/plausible.js', 'website/static/src/js/user_custom_javascript.js', + 'website/static/src/js/http_cookie.js', 'website/static/src/xml/website.xml', 'website/static/src/xml/website.background.video.xml', 'website/static/src/xml/website.share.xml', diff --git a/addons/website/data/website_data.xml b/addons/website/data/website_data.xml index de829b0a375..275de9f1baf 100644 --- a/addons/website/data/website_data.xml +++ b/addons/website/data/website_data.xml @@ -228,7 +228,7 @@
Session & Security
+Session & Security
(essential)
@@ -243,7 +243,7 @@
Preferences
+Preferences
(essential)
Remember information about the preferred look or behavior of the website, such as your preferred language or region.
@@ -254,7 +254,7 @@Used to collect information about your interactions with the website, the pages you've seen, @@ -271,7 +271,7 @@
Advertising & Marketing
+Advertising & Marketing
(optional)
@@ -291,7 +291,7 @@
Analytics
+Analytics
(optional)
diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py
index 92a6666fe1a..78b2dc4052b 100644
--- a/addons/website/models/ir_http.py
+++ b/addons/website/models/ir_http.py
@@ -17,6 +17,7 @@ from odoo import api, models
from odoo import SUPERUSER_ID
from odoo.exceptions import AccessError
from odoo.http import request
+from odoo.tools.json import scriptsafe as json_scriptsafe
from odoo.tools.safe_eval import safe_eval
from odoo.osv.expression import FALSE_DOMAIN
from odoo.addons.http_routing.models import ir_http
@@ -380,6 +381,22 @@ class Http(models.AbstractModel):
session_info['bundle_params']['website_id'] = request.website.id
return session_info
+ @classmethod
+ def _is_allowed_cookie(cls, cookie_type):
+ result = super()._is_allowed_cookie(cookie_type)
+ if result and cookie_type == 'optional':
+ if not request.env['website'].get_current_website().cookies_bar:
+ # Cookies bar is disabled on this website
+ return True
+ accepted_cookie_types = json_scriptsafe.loads(request.httprequest.cookies.get('website_cookies_bar', '{}'))
+ if 'optional' in accepted_cookie_types:
+ return accepted_cookie_types['optional']
+ return False
+
+ # Pass-through if already forbidden for another reason or a type that
+ # is not restricted by the website module.
+ return result
+
class ModelConverter(ir_http.ModelConverter):
diff --git a/addons/website/static/src/js/content/inject_dom.js b/addons/website/static/src/js/content/inject_dom.js
index e0b1ca76eda..f96644a3958 100644
--- a/addons/website/static/src/js/content/inject_dom.js
+++ b/addons/website/static/src/js/content/inject_dom.js
@@ -1,6 +1,6 @@
/** @odoo-module */
-import { get_cookie } from 'web.utils.cookies';
+import {getCookie} from 'web.utils.cookies';
import { session } from '@web/session';
document.addEventListener('DOMContentLoaded', () => {
@@ -13,7 +13,7 @@ document.addEventListener('DOMContentLoaded', () => {
'utm_campaign': 'utmCampaign',
};
for (const [name, dsName] of Object.entries(cookieNamesToDataNames)) {
- const cookie = get_cookie(`odoo_${name}`);
+ const cookie = getCookie(`odoo_${name}`);
if (cookie) {
// Remove leading and trailing " and '
htmlEl.dataset[dsName] = cookie.replace(/(^["']|["']$)/g, '');
diff --git a/addons/website/static/src/js/editor/snippets.options.js b/addons/website/static/src/js/editor/snippets.options.js
index c0455dd0362..4993ad5e084 100644
--- a/addons/website/static/src/js/editor/snippets.options.js
+++ b/addons/website/static/src/js/editor/snippets.options.js
@@ -2617,6 +2617,7 @@ options.registry.CookiesBar = options.registry.SnippetPopup.extend({
const $content = this.$target.find('.modal-content');
const selectorsToKeep = [
'.o_cookies_bar_text_button',
+ '.o_cookies_bar_text_button_essential',
'.o_cookies_bar_text_policy',
'.o_cookies_bar_text_title',
'.o_cookies_bar_text_primary',
diff --git a/addons/website/static/src/js/http_cookie.js b/addons/website/static/src/js/http_cookie.js
new file mode 100644
index 00000000000..34c9fb378af
--- /dev/null
+++ b/addons/website/static/src/js/http_cookie.js
@@ -0,0 +1,22 @@
+/** @odoo-module **/
+
+import cookieUtils from 'web.utils.cookies';
+
+const originFunc = cookieUtils.isAllowedCookie;
+cookieUtils.isAllowedCookie = (type) => {
+ const result = originFunc.apply(cookieUtils, [type]);
+ if (result && type === 'optional') {
+ if (!document.getElementById('cookies-consent-essential')) {
+ // Cookies bar is disabled on this website.
+ return true;
+ }
+ const consents = JSON.parse(cookieUtils.getCookie('website_cookies_bar') || '{}');
+ if ('optional' in consents) {
+ return consents['optional'];
+ }
+ return false;
+ }
+ // Pass-through if already forbidden for another reason or a type that is
+ // not restricted by the website module.
+ return result;
+};
diff --git a/addons/website/static/src/scss/website.scss b/addons/website/static/src/scss/website.scss
index 9f09f6e54d4..069d53b7655 100644
--- a/addons/website/static/src/scss/website.scss
+++ b/addons/website/static/src/scss/website.scss
@@ -1487,17 +1487,6 @@ $ribbon-padding: 100px;
flex: 1;
}
-// Cookies Bar
-#website_cookies_bar {
- .o_cookies_discrete {
- .js_close_popup.o_cookies_bar_text_button, .o_cookies_bar_text_policy {
- @include media-breakpoint-down(lg) {
- margin-bottom: 1rem;
- }
- }
- }
-}
-
.o_website_btn_loading {
cursor: wait;
opacity: $btn-disabled-opacity;
diff --git a/addons/website/static/src/snippets/s_popup/000.js b/addons/website/static/src/snippets/s_popup/000.js
index 52a951910ca..a0f5a27b787 100644
--- a/addons/website/static/src/snippets/s_popup/000.js
+++ b/addons/website/static/src/snippets/s_popup/000.js
@@ -3,7 +3,7 @@ odoo.define('website.s_popup', function (require) {
const config = require('web.config');
const publicWidget = require('web.public.widget');
-const utils = require('web.utils');
+const {getCookie, setCookie} = require('web.utils.cookies');
const PopupWidget = publicWidget.Widget.extend({
selector: '.s_popup',
@@ -12,12 +12,13 @@ const PopupWidget = publicWidget.Widget.extend({
'hide.bs.modal': '_onHideModal',
'show.bs.modal': '_onShowModal',
},
+ cookieValue: true,
/**
* @override
*/
start: function () {
- this._popupAlreadyShown = !!utils.get_cookie(this.$el.attr('id'));
+ this._popupAlreadyShown = !!getCookie(this.$el.attr('id'));
if (!this._popupAlreadyShown) {
this._bindPopup();
}
@@ -96,7 +97,7 @@ const PopupWidget = publicWidget.Widget.extend({
*/
_onHideModal: function () {
const nbDays = this.$el.find('.modal').data('consentsDuration');
- utils.set_cookie(this.$el.attr('id'), true, nbDays * 24 * 60 * 60);
+ setCookie(this.el.id, this.cookieValue, nbDays * 24 * 60 * 60, 'required');
this._popupAlreadyShown = true;
this.$target.find('.media_iframe_video iframe').each((i, iframe) => {
@@ -116,5 +117,28 @@ const PopupWidget = publicWidget.Widget.extend({
publicWidget.registry.popup = PopupWidget;
+// Extending the popup widget with cookiebar functionality.
+// This allows for refusing optional cookies for now and can be
+// extended to picking which cookies categories are accepted.
+publicWidget.registry.cookies_bar = PopupWidget.extend({
+ selector: '#website_cookies_bar',
+ events: Object.assign({}, PopupWidget.prototype.events, {
+ 'click #cookies-consent-essential, #cookies-consent-all': '_onAcceptClick',
+ }),
+
+ //--------------------------------------------------------------------------
+ // Handlers
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * @param ev
+ */
+ _onAcceptClick(ev) {
+ this.cookieValue = `{"required": true, "optional": ${ev.target.id === 'cookies-consent-all'}}`;
+ this._onHideModal();
+ },
+});
+
return PopupWidget;
});
diff --git a/addons/website/static/src/xml/website.cookies_bar.xml b/addons/website/static/src/xml/website.cookies_bar.xml
index e32dc4ba110..f2227b29646 100644
--- a/addons/website/static/src/xml/website.cookies_bar.xml
+++ b/addons/website/static/src/xml/website.cookies_bar.xml
@@ -7,25 +7,37 @@
We use cookies to provide you a better user experience.