diff --git a/addons/auth_totp_portal/static/src/js/totp_frontend.js b/addons/auth_totp_portal/static/src/js/totp_frontend.js index 0defc7591c5..d0c16108745 100644 --- a/addons/auth_totp_portal/static/src/js/totp_frontend.js +++ b/addons/auth_totp_portal/static/src/js/totp_frontend.js @@ -5,6 +5,7 @@ import { markup } from "@odoo/owl"; import { InputConfirmationDialog } from "@portal/js/components/input_confirmation_dialog/input_confirmation_dialog"; import { handleCheckIdentity } from "@portal/js/portal_security"; import publicWidget from "@web/legacy/js/public/public_widget"; +import { session } from "@web/session"; /** * Replaces specific elements by normal HTML, strip out the rest entirely @@ -144,7 +145,7 @@ publicWidget.registry.TOTPButton = publicWidget.Widget.extend({ const w = await handleCheckIdentity(this.proxy('_rpc'), this._rpc({ model: 'res.users', method: 'action_totp_enable_wizard', - args: [this.getSession().user_id] + args: [session.user_id] }), (...args) => this.call("dialog", "add", ...args)); if (!w) { @@ -219,7 +220,7 @@ publicWidget.registry.DisableTOTPButton = publicWidget.Widget.extend({ e.preventDefault(); await handleCheckIdentity( this.proxy('_rpc'), - this._rpc({model: 'res.users', method: 'action_totp_disable', args: [this.getSession().user_id]}), + this._rpc({model: 'res.users', method: 'action_totp_disable', args: [session.user_id]}), (...args) => this.call("dialog", "add", ...args) ) window.location = window.location; @@ -258,7 +259,7 @@ publicWidget.registry.RevokeAllTrustedDevicesButton = publicWidget.Widget.extend this._rpc({ model: 'res.users', method: 'revoke_all_devices', - args: [this.getSession().user_id] + args: [session.user_id] }), (...args) => this.call("dialog", "add", ...args) ); diff --git a/addons/hr_expense/static/src/components/expense_dashboard.js b/addons/hr_expense/static/src/components/expense_dashboard.js index f536b6346d0..e019025c61a 100644 --- a/addons/hr_expense/static/src/components/expense_dashboard.js +++ b/addons/hr_expense/static/src/components/expense_dashboard.js @@ -1,7 +1,7 @@ /** @odoo-module */ import { useService } from '@web/core/utils/hooks'; -import session from 'web.session'; +import { getCurrency } from '@web/core/currency'; const { Component, onWillStart, useState } = owl; @@ -23,7 +23,7 @@ export class ExpenseDashboard extends Component { renderMonetaryField(value, currency_id) { value = value.toFixed(2); - const currency = session.get_currency(currency_id); + const currency = getCurrency(currency_id); if (currency) { if (currency.position === "after") { value += currency.symbol; diff --git a/addons/hr_org_chart/static/src/fields/hooks.js b/addons/hr_org_chart/static/src/fields/hooks.js index 044ceccfdcc..a835d6461a0 100644 --- a/addons/hr_org_chart/static/src/fields/hooks.js +++ b/addons/hr_org_chart/static/src/fields/hooks.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import { _t } from "@web/core/l10n/translation"; -import session from 'web.session' +import { session } from "@web/session"; import { useService } from "@web/core/utils/hooks"; /** diff --git a/addons/mass_mailing/static/src/js/mailing_portal.js b/addons/mass_mailing/static/src/js/mailing_portal.js index 6c899e406c3..d9c1cbcaf10 100644 --- a/addons/mass_mailing/static/src/js/mailing_portal.js +++ b/addons/mass_mailing/static/src/js/mailing_portal.js @@ -4,7 +4,6 @@ import ajax from "@web/legacy/js/core/ajax"; import { escape } from "@web/core/utils/strings"; import { whenReady } from "@odoo/owl"; import { _t } from "@web/core/l10n/translation"; -import session from "web.session"; whenReady(() => { var email = $("input[name='email']").val(); @@ -13,7 +12,6 @@ whenReady(() => { var token = (location.search.split('token' + '=')[1] || '').split('&')[0]; if ($('.o_unsubscribe_form').length) { - session.load_translations().then(function () { if (email != '' && email != undefined){ ajax.jsonRpc('/mailing/blacklist/check', 'call', {'email': email, 'mailing_id': mailing_id, 'res_id': res_id, 'token': token}) .then(function (result) { @@ -55,7 +53,6 @@ whenReady(() => { else{ $('#subscription_info').html(_t('You have been successfully unsubscribed.')); } - }); $('#unsubscribe_form').on('submit', function (e) { e.preventDefault(); diff --git a/addons/mrp_subcontracting/__manifest__.py b/addons/mrp_subcontracting/__manifest__.py index 92f6c533e64..43cbf45f8f1 100644 --- a/addons/mrp_subcontracting/__manifest__.py +++ b/addons/mrp_subcontracting/__manifest__.py @@ -113,9 +113,7 @@ 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/rpc.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/session.js', 'web/static/src/legacy/js/core/time.js', - 'web/static/src/legacy/js/core/translation.js', 'web/static/src/legacy/js/core/utils.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', @@ -172,7 +170,6 @@ 'web/static/src/legacy/backend_utils.js', 'web/static/src/legacy/utils.js', 'web/static/src/legacy/js/core/dates.js', - 'web/static/src/legacy/js/services/session.js', 'web/static/src/legacy/js/env.js', 'web/static/src/legacy/js/owl_compatibility.js', diff --git a/addons/portal/static/src/js/portal_security.js b/addons/portal/static/src/js/portal_security.js index 879111253f2..f9586293989 100644 --- a/addons/portal/static/src/js/portal_security.js +++ b/addons/portal/static/src/js/portal_security.js @@ -3,7 +3,7 @@ import { ConfirmationDialog } from '@web/core/confirmation_dialog/confirmation_dialog'; import { renderToMarkup } from "@web/core/utils/render"; import publicWidget from '@web/legacy/js/public/public_widget'; -import session from "web.session"; +import { session } from "@web/session"; import { InputConfirmationDialog } from './components/input_confirmation_dialog/input_confirmation_dialog'; import { _t } from "@web/core/l10n/translation"; diff --git a/addons/portal/static/src/js/portal_sidebar.js b/addons/portal/static/src/js/portal_sidebar.js index 6a4469e6645..76749a94f46 100644 --- a/addons/portal/static/src/js/portal_sidebar.js +++ b/addons/portal/static/src/js/portal_sidebar.js @@ -2,7 +2,6 @@ import { _t } from "@web/core/l10n/translation"; import publicWidget from "@web/legacy/js/public/public_widget"; -import session from "web.session"; import { deserializeDateTime } from "@web/core/l10n/dates"; const { DateTime } = luxon; @@ -34,7 +33,6 @@ var PortalSidebar = publicWidget.Widget.extend({ diff = dateTime.diff(today).as("days"), displayStr; - session.is_bound.then(function (){ if (diff === 0) { displayStr = _t('Due today'); } else if (diff > 0) { @@ -45,7 +43,6 @@ var PortalSidebar = publicWidget.Widget.extend({ displayStr = _t('%s days overdue', Math.abs(diff).toFixed(1)); } $(el).text(displayStr); - }); }); }, /** diff --git a/addons/portal_rating/static/src/js/portal_rating_composer.js b/addons/portal_rating/static/src/js/portal_rating_composer.js index 15874d59e51..63d37519663 100644 --- a/addons/portal_rating/static/src/js/portal_rating_composer.js +++ b/addons/portal_rating/static/src/js/portal_rating_composer.js @@ -1,7 +1,7 @@ /** @odoo-module **/ import publicWidget from "@web/legacy/js/public/public_widget"; -import session from "web.session"; +import { session } from "@web/session"; import portalComposer from "@portal/js/portal_composer"; import { _t } from "@web/core/l10n/translation"; import { renderToElement } from "@web/core/utils/render"; diff --git a/addons/project/__manifest__.py b/addons/project/__manifest__.py index bf3c6cbc3fc..a6be90ee5a8 100644 --- a/addons/project/__manifest__.py +++ b/addons/project/__manifest__.py @@ -164,9 +164,7 @@ 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/rpc.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/session.js', 'web/static/src/legacy/js/core/time.js', - 'web/static/src/legacy/js/core/translation.js', 'web/static/src/legacy/js/core/utils.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', @@ -223,7 +221,6 @@ 'web/static/src/legacy/backend_utils.js', 'web/static/src/legacy/utils.js', 'web/static/src/legacy/js/core/dates.js', - 'web/static/src/legacy/js/services/session.js', 'web/static/src/legacy/js/env.js', 'web/static/src/legacy/js/owl_compatibility.js', diff --git a/addons/test_mail/static/tests/tracking_value_tests.js b/addons/test_mail/static/tests/tracking_value_tests.js index 1d45c9123df..63979579682 100644 --- a/addons/test_mail/static/tests/tracking_value_tests.js +++ b/addons/test_mail/static/tests/tracking_value_tests.js @@ -5,11 +5,9 @@ import { click, contains, insertText, start, startServer } from "@mail/../tests/ import { editSelect, selectDropdownItem, - patchWithCleanup, patchTimeZone, getFixture, } from "@web/../tests/helpers/utils"; -import session from "web.session"; import testUtils from "@web/../tests/legacy/helpers/test_utils"; let target; @@ -46,11 +44,7 @@ QUnit.module("tracking value", { return remainder; }; - patchWithCleanup(session, { - getTZOffset() { - return 0; - }, - }); + patchTimeZone(0); }, }); diff --git a/addons/test_website/static/tests/tours/json_auth.js b/addons/test_website/static/tests/tours/json_auth.js index 2ee741a3992..ef97473f020 100644 --- a/addons/test_website/static/tests/tours/json_auth.js +++ b/addons/test_website/static/tests/tours/json_auth.js @@ -1,15 +1,15 @@ /** @odoo-module **/ import { registry } from "@web/core/registry"; -import session from "web.session"; +import ajax from "@web/legacy/js/core/ajax"; registry.category("web_tour.tours").add('test_json_auth', { test: true, steps: () => [{ trigger: 'body', run: async function () { - await session.rpc('/test_get_dbname').then( function (result){ - return session.rpc("/web/session/authenticate", { + await ajax.rpc('/test_get_dbname').then( function (result){ + return ajax.rpc("/web/session/authenticate", { db: result, login: 'admin', password: 'admin' diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py index 3c4c8321048..307b309fe5d 100644 --- a/addons/web/__manifest__.py +++ b/addons/web/__manifest__.py @@ -113,9 +113,7 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/rpc.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/session.js', 'web/static/src/legacy/js/core/time.js', - 'web/static/src/legacy/js/core/translation.js', 'web/static/src/legacy/js/core/utils.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', @@ -163,7 +161,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/backend_utils.js', 'web/static/src/legacy/utils.js', 'web/static/src/legacy/js/core/dates.js', - 'web/static/src/legacy/js/services/session.js', 'web/static/src/legacy/js/env.js', 'web/static/src/legacy/js/owl_compatibility.js', @@ -267,9 +264,7 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/rpc.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/session.js', 'web/static/src/legacy/js/core/time.js', - 'web/static/src/legacy/js/core/translation.js', 'web/static/src/legacy/js/core/utils.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', @@ -290,7 +285,6 @@ This module provides the core of the Odoo Web Client. 'web/static/src/legacy/utils.js', 'web/static/src/legacy/js/core/dates.js', 'web/static/src/legacy/js/owl_compatibility.js', - 'web/static/src/legacy/js/services/session.js', 'web/static/src/legacy/js/public/public_env.js', 'web/static/src/legacy/js/public/public_root.js', 'web/static/src/legacy/js/public/public_root_instance.js', diff --git a/addons/web/static/src/legacy/js/common_env.js b/addons/web/static/src/legacy/js/common_env.js index f61597c401c..511d721eb15 100644 --- a/addons/web/static/src/legacy/js/common_env.js +++ b/addons/web/static/src/legacy/js/common_env.js @@ -16,97 +16,13 @@ * [1] https://github.com/odoo/owl/blob/master/doc/reference/environment.md#content-of-an-environment */ - import { jsonRpc } from "@web/legacy/js/core/ajax"; import { bus } from "@web/legacy/js/services/core"; - import rpc from "@web/legacy/js/core/rpc"; - import session from "web.session"; - import {getCookie, setCookie} from "@web/legacy/js/core/cookie_utils"; - const browser = { - clearInterval: window.clearInterval.bind(window), - clearTimeout: window.clearTimeout.bind(window), - Date: window.Date, - fetch: (window.fetch || (() => { })).bind(window), - Notification: window.Notification, - requestAnimationFrame: window.requestAnimationFrame.bind(window), - setInterval: window.setInterval.bind(window), - setTimeout: window.setTimeout.bind(window), - }; - Object.defineProperty(browser, 'innerHeight', { - get: () => window.innerHeight, - }); - Object.defineProperty(browser, 'innerWidth', { - get: () => window.innerWidth, - }); // Build the basic env const env = { - browser, bus, debug: odoo.debug, - services: { - ajax: { - rpc(route, args, options, target) { - let rpcPromise = null; - const promise = new Promise(function (resolve, reject) { - rpcPromise = session.rpc(route, args, options); - rpcPromise.then(function (result) { - if (!target.isDestroyed()) { - resolve(result); - } - }).guardedCatch(function (reason) { - if (!target.isDestroyed()) { - reject(reason); - } - }); - }); - promise.abort = rpcPromise.abort.bind(rpcPromise); - return promise; - }, - }, - ajaxJsonRPC() { - return jsonRpc(...arguments); - }, - getCookie() { - return getCookie(...arguments); - }, - httpRequest(route, params = {}, readMethod = 'json') { - const info = { - method: params.method || 'POST', - }; - if (params.method !== 'GET') { - const formData = new FormData(); - for (const key in params) { - if (key === 'method') { - continue; - } - const value = params[key]; - if (Array.isArray(value) && value.length) { - for (const val of value) { - formData.append(key, val); - } - } else { - formData.append(key, value); - } - } - info.body = formData; - } - return fetch(route, info).then(response => response[readMethod]()); - }, - navigate(url, params) { - window.location = $.param.querystring(url, params); - }, - reloadPage() { - window.location.reload(); - }, - rpc(params, options) { - const query = rpc.buildQuery(params); - return session.rpc(query.route, query.params, options); - }, - setCookie() { - setCookie(...arguments); - }, - }, - session, + services: {}, }; export default env; diff --git a/addons/web/static/src/legacy/js/core/ajax.js b/addons/web/static/src/legacy/js/core/ajax.js index 150307c3cf9..4cd329cd00c 100644 --- a/addons/web/static/src/legacy/js/core/ajax.js +++ b/addons/web/static/src/legacy/js/core/ajax.js @@ -3,10 +3,7 @@ import core from "@web/legacy/js/services/core"; import { Markup } from "@web/legacy/js/core/utils"; import time from "@web/legacy/js/core/time"; -import download from "@web/legacy/js/libs/download"; -import contentdisposition from "@web/legacy/js/libs/content-disposition"; import { session } from "@web/session"; -import { _t } from "@web/core/l10n/translation"; // Create the final object containing all the functions first to allow monkey // patching them correctly if ever needed. @@ -70,9 +67,6 @@ function _genericJsonRpc (fct_name, params, settings, fct) { if (!shadow) { core.bus.trigger('rpc_response', data.id); } - if (error.code === 100) { - core.bus.trigger('invalidate_session'); - } reject({message: error, event: $.Event()}); } else { if (!shadow) { @@ -138,100 +132,6 @@ function rpc(url, params, settings) { return jsonRpc(url, 'call', params, settings); } -/** - * Cooperative file download implementation, for ajaxy APIs. - * - * @param {Object} options - * @param {String} [options.url] used to dynamically create a form - * @param {Object} [options.data] data to add to the form submission. If can be used without a form, in which case a form is created from scratch. Otherwise, added to form data - * @param {HTMLFormElement} [options.form] the form to submit in order to fetch the file - * @param {Function} [options.success] callback in case of download success - * @param {Function} [options.error] callback in case of request error, provided with the error body - * @param {Function} [options.complete] called after both ``success`` and ``error`` callbacks have executed - * @returns {boolean} a false value means that a popup window was blocked. This - * mean that we probably need to inform the user that something needs to be - * changed to make it work. - */ -function get_file(options) { - var xhr = new XMLHttpRequest(); - - var data; - if (options.form) { - xhr.open(options.form.method, options.form.action); - data = new FormData(options.form); - } else { - xhr.open('POST', options.url); - data = new FormData(); - for (const [k, v] of Object.entries(options.data || {})) { - data.append(k, v); - } - } - if (odoo.csrf_token) { - data.append('csrf_token', odoo.csrf_token); - } - // IE11 wants this after xhr.open or it throws - xhr.responseType = 'blob'; - - // onreadystatechange[readyState = 4] - // => onload (success) | onerror (error) | onabort - // => onloadend - xhr.onload = function () { - var mimetype = xhr.response.type; - if (xhr.status === 200 && mimetype !== 'text/html') { - // replace because apparently we send some C-D headers with a trailing ";" - // todo: maybe a lack of CD[attachment] should be interpreted as an error case? - var header = (xhr.getResponseHeader('Content-Disposition') || '').replace(/;$/, ''); - var filename = header ? contentdisposition.parse(header).parameters.filename : null; - - download(xhr.response, filename, mimetype); - // not sure download is going to be sync so this may be called - // before the file is actually fetched (?) - if (options.success) { options.success(); } - return true; - } - - if (!options.error) { - return true; - } - var decoder = new FileReader(); - decoder.onload = function () { - var contents = decoder.result; - - var err; - var doc = new DOMParser().parseFromString(contents, 'text/html'); - var nodes = doc.body.children.length === 0 ? doc.body.childNodes : doc.body.children; - try { // Case of a serialized Odoo Exception: It is Json Parsable - var node = nodes[1] || nodes[0]; - err = JSON.parse(node.textContent); - } catch { // Arbitrary uncaught python side exception - err = { - message: nodes.length > 1 ? nodes[1].textContent : '', - data: { - name: String(xhr.status), - title: nodes.length > 0 ? nodes[0].textContent : '', - } - }; - } - options.error(err); - }; - decoder.readAsText(xhr.response); - }; - xhr.onerror = function () { - if (options.error) { - options.error({ - message: _t("Something happened while trying to contact the server, check that the server is online and that you still have a working network connection."), - data: { title: _t("Could not connect to the server") } - }); - } - }; - if (options.complete) { - xhr.onloadend = function () { options.complete(); }; - } - - xhr.send(data); - return true; -} - function post (controller_url, data) { var postData = new FormData(); @@ -318,7 +218,6 @@ Object.assign(ajax, { jsonRpc: jsonRpc, rpc: rpc, loadAsset: loadAsset, - get_file: get_file, post: post, }); diff --git a/addons/web/static/src/legacy/js/core/dates.js b/addons/web/static/src/legacy/js/core/dates.js index 2fc8b79bc1c..2504e6cb5e0 100644 --- a/addons/web/static/src/legacy/js/core/dates.js +++ b/addons/web/static/src/legacy/js/core/dates.js @@ -1,11 +1,14 @@ /** @odoo-module **/ -import session from "web.session"; import time from "@web/legacy/js/core/time"; import { _t } from "@web/core/l10n/translation"; const { DateTime } = luxon; +function getTimezoneOffset(value) { + return luxon.Settings.defaultZone.offset(value.valueOf()); +} + /** * Returns a string representing a date. If the value is false, then we return * an empty string. Note that this is dependant on the localization settings @@ -24,7 +27,7 @@ export function formatDate(value, field, options) { } if (field && field.type === 'datetime') { if (!options || !('timezone' in options) || options.timezone) { - value = value.clone().add(session.getTZOffset(value), 'minutes'); + value = value.clone().add(getTimezoneOffset(value), 'minutes'); } } var date_format = time.getLangDateFormat(); @@ -49,7 +52,7 @@ export function formatDateTime(value, field, options) { return ""; } if (!options || !('timezone' in options) || options.timezone) { - value = value.clone().add(session.getTZOffset(value), 'minutes'); + value = value.clone().add(getTimezoneOffset(value), 'minutes'); } return value.format(time.getLangDatetimeFormat()); } @@ -170,7 +173,7 @@ export function parseDateTime(value, field, options) { } else { datetime = moment.utc(value, [pattern1, pattern2, moment.ISO_8601]); if (options && options.timezone) { - datetime.add(-session.getTZOffset(datetime), 'minutes'); + datetime.add(-getTimezoneOffset(datetime), 'minutes'); } } } diff --git a/addons/web/static/src/legacy/js/core/service_mixins.js b/addons/web/static/src/legacy/js/core/service_mixins.js index dd0be03a714..cbd4b1ecc84 100644 --- a/addons/web/static/src/legacy/js/core/service_mixins.js +++ b/addons/web/static/src/legacy/js/core/service_mixins.js @@ -92,16 +92,6 @@ var ServicesMixin = { }); }); }, - // Session stuff - getSession: function () { - var session; - this.trigger_up('get_session', { - callback: function (result) { - session = result; - } - }); - return session; - }, /** * Informs the action manager to do an action. This supposes that the action * manager can be found amongst the ancestors of the current widget. diff --git a/addons/web/static/src/legacy/js/core/session.js b/addons/web/static/src/legacy/js/core/session.js deleted file mode 100644 index cb62d07cfab..00000000000 --- a/addons/web/static/src/legacy/js/core/session.js +++ /dev/null @@ -1,354 +0,0 @@ -/** @odoo-module **/ - -import ajax from "@web/legacy/js/core/ajax"; -import Class from "@web/legacy/js/core/class"; -import core from "@web/legacy/js/services/core"; -import mixins from "@web/legacy/js/core/mixins"; -import {setCookie} from "@web/legacy/js/core/cookie_utils"; -import { session } from "@web/session"; -import { loadJS } from "@web/core/assets"; -import { _t } from "@web/legacy/js/core/translation"; - -// To do: refactor session. Session accomplishes several concerns (rpc, -// configuration, currencies (wtf?), user permissions...). They should be -// clarified and separated. - -var Session = Class.extend(mixins.EventDispatcherMixin, { - /** - - @param parent The parent of the newly created object. - or `null` if the server to contact is the origin server. - @param {Dict} options A dictionary that can contain the following options: - - * "modules" - * "use_cors" - */ - init: function (parent, origin, options) { - mixins.EventDispatcherMixin.init.call(this); - this.setParent(parent); - options = options || {}; - this.server = null; - this.avoid_recursion = false; - this.use_cors = options.use_cors || false; - this.setup(origin); - - // for historic reasons, the session requires a name to properly work - // (see the methods get_cookie and set_cookie). We should perhaps - // remove it totally (but need to make sure the cookies are properly set) - this.name = "instance0"; - // TODO: session store in cookie should be optional - this.currencies = {}; - this._groups_def = {}; - core.bus.on('invalidate_session', this, this._onInvalidateSession); - }, - setup: function (origin, options) { - // must be able to customize server - var window_origin = location.protocol + "//" + location.host; - origin = origin ? origin.replace( /\/+$/, '') : window_origin; - if (typeof this.origin !== "undefined" && this.origin !== origin) - throw new Error('Session already bound to ' + this.origin); - else - this.origin = origin; - this.prefix = this.origin; - this.server = this.origin; // keep chs happy - options = options || {}; - if ('use_cors' in options) { - this.use_cors = options.use_cors; - } - }, - /** - * Setup a session - */ - session_bind: function (origin) { - this.setup(origin); - this.uid = null; - this.username = null; - this.user_context= {}; - this.db = null; - this.active_id = null; - return this.session_init(); - }, - /** - * Init a session, reloads from cookie, if it exists - */ - session_init: function () { - var self = this; - var prom = this.session_reload(); - - if (this.is_frontend || this.is_report) { - return prom.then(function () { - return self.load_translations(); - }); - } - - return prom.then(function () { - var promise = self.load_qweb(); - if (self.session_is_valid()) { - return promise.then(function () { return self.load_modules(); }); - } - return Promise.all([ - promise, - self.rpc('/web/webclient/bootstrap_translations') - .then(function (trans) { - _t.database.set_bundle(trans); - }) - ]); - }); - }, - session_is_valid: function () { - var db = $.deparam.querystring().db; - if (db && this.db !== db) { - return false; - } - return !!this.uid; - }, - /** - * The session is validated by restoration of a previous session - */ - session_authenticate: function () { - var self = this; - return Promise.resolve(this._session_authenticate.apply(this, arguments)).then(function () { - return self.load_modules(); - }); - }, - /** - * The session is validated either by login or by restoration of a previous session - */ - _session_authenticate: function (db, login, password) { - var self = this; - var params = {db: db, login: login, password: password}; - return this.rpc("/web/session/authenticate", params).then(function (result) { - if (!result.uid) { - return Promise.reject(); - } - Object.assign(self, result); - }); - }, - session_logout: function () { - $.bbq.removeState(); - return this.rpc("/web/session/destroy", {}); - }, - user_has_group: function (group) { - // the frontend session info has no `uid` but an `user_id` - if (!this.uid && !this.user_id) { - return Promise.resolve(false); - } - var def = this._groups_def[group]; - if (!def) { - def = this._groups_def[group] = this.rpc('/web/dataset/call_kw/res.users/has_group', { - "model": "res.users", - "method": "has_group", - "args": [group], - "kwargs": {} - }); - } - return def; - }, - get_cookie: function (name) { - if (!this.name) { return null; } - var nameEQ = this.name + '|' + name + '='; - var cookies = document.cookie.split(';'); - for(var i=0; i 0) - qs = "?" + qs; - var prefix = ['http://', 'https://', '//'].some((el) => { - return path.length >= el.length && path.slice(0, el.length) === el; - }) ? '' : this.prefix; - return prefix + path + qs; - }, - /** - * Returns the time zone difference (in minutes) from the current locale - * (host system settings) to UTC, for a given date. The offset is positive - * if the local timezone is behind UTC, and negative if it is ahead. - * - * @param {string | moment} date a valid string date or moment instance - * @returns {integer} - */ - getTZOffset: function (date) { - return -new Date(new Date(date).toISOString().replace('Z', '')).getTimezoneOffset(); - }, - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - /** - * Replaces the value of a key in cache_hashes (the hash of some resource computed on the back-end by a unique value - * @param {string} key the key in the cache_hashes to invalidate - */ - invalidateCacheKey: function(key) { - if (this.cache_hashes && this.cache_hashes[key]) { - this.cache_hashes[key] = Date.now(); - } - }, - - setCompanies: function (main_company_id, company_ids) { - var hash = $.bbq.getState(); - hash.cids = company_ids.sort(function(a, b) { - if (a === main_company_id) { - return -1; - } else if (b === main_company_id) { - return 1; - } else { - return a - b; - } - }).join(','); - setCookie('cids', hash.cids || String(main_company_id), 24 * 60 * 60 * 365, 'required'); - $.bbq.pushState({'cids': hash.cids}, 0); - location.reload(); - }, - - //-------------------------------------------------------------------------- - // Private - //-------------------------------------------------------------------------- - - /** - * Sets first day of week in current locale according to the user language. - * - * @private - */ - _configureLocale: function () { - // TODO: try to test when re - writing this file in the new system with luxon - const dow = (_t.database.parameters.week_start || 0) % 7; - moment.updateLocale(moment.locale(), { - week: { - dow: dow, - doy: 7 + dow - 4 // Note: ISO 8601 week date: https://momentjscom.readthedocs.io/en/latest/moment/07-customization/16-dow-doy/ - }, - }); - }, - - //-------------------------------------------------------------------------- - // Handlers - //-------------------------------------------------------------------------- - - /** - * @private - */ - _onInvalidateSession: function () { - this.uid = false; - }, -}); - -export default Session; diff --git a/addons/web/static/src/legacy/js/core/time.js b/addons/web/static/src/legacy/js/core/time.js index 7e682a9f4c1..afe12647269 100644 --- a/addons/web/static/src/legacy/js/core/time.js +++ b/addons/web/static/src/legacy/js/core/time.js @@ -1,11 +1,11 @@ /** @odoo-module **/ -import translation from "@web/legacy/js/core/translation"; +import { localization } from "@web/core/l10n/localization"; import utils from "@web/legacy/js/core/utils"; +import { _t } from "@web/core/l10n/translation"; var lpad = utils.lpad; var rpad = utils.rpad; -var _t = translation._t; /** * Replacer function for JSON.stringify, serializes Date objects to UTC @@ -205,89 +205,37 @@ export function auto_date_to_str (value, type) { } } -/** - * Convert Python strftime to escaped moment.js format. - * - * @param {String} value original format - */ -export function strftime_to_moment_format (value) { - if (_normalize_format_cache[value] === undefined) { - var isletter = /[a-zA-Z]/, - output = [], - inToken = false; - - for (var index=0; index < value.length; ++index) { - var character = value[index]; - if (character === '%' && !inToken) { - inToken = true; - continue; - } - if (isletter.test(character)) { - if (inToken && normalize_format_table[character] !== undefined) { - character = normalize_format_table[character]; - } else { - character = '[' + character + ']'; // moment.js escape - } - } - output.push(character); - inToken = false; - } - _normalize_format_cache[value] = output.join(''); - } - return _normalize_format_cache[value]; -} - -var _normalize_format_cache = {}; -var normalize_format_table = { - // Python strftime to moment.js conversion table - // See openerp/addons/base/views/res_lang_views.xml - // for details about supported directives - 'a': 'ddd', - 'A': 'dddd', - 'b': 'MMM', - 'B': 'MMMM', - 'd': 'DD', - 'H': 'HH', - 'I': 'hh', - 'j': 'DDDD', - 'm': 'MM', - 'M': 'mm', - 'p': 'A', - 'S': 'ss', - 'U': 'ww', - 'W': 'WW', - 'w': 'd', - 'y': 'YY', - 'Y': 'YYYY', - // unsupported directives - 'c': 'ddd MMM D HH:mm:ss YYYY', - 'x': 'MM/DD/YY', - 'X': 'HH:mm:ss' +const luxonToMomentFormatTable = { + c: "d", + d: "D", + o: "DDDD", + a: "A", + y: "Y", }; -var inverse_normalize_format_table = {}; -Object.entries(normalize_format_table).forEach(([key, val]) => { - inverse_normalize_format_table[val] = key; -}); + +function luxonToMomentFormat(format) { + return format.replace(/[a-zA-Z]/g, (match) => luxonToMomentFormatTable[match] || match); +} /** * Get date format of the user's language */ export function getLangDateFormat() { - return strftime_to_moment_format(_t.database.parameters.date_format); + return luxonToMomentFormat(localization.dateFormat); } /** * Get time format of the user's language */ export function getLangTimeFormat() { - return strftime_to_moment_format(_t.database.parameters.time_format); + return luxonToMomentFormat(localization.timeFormat); } /** * Get date time format of the user's language */ export function getLangDatetimeFormat() { - return strftime_to_moment_format(_t.database.parameters.date_format + " " + _t.database.parameters.time_format); + return luxonToMomentFormat(localization.dateTimeFormat); } const dateFormatWoZeroCache = {}; @@ -329,7 +277,6 @@ export default { time_to_str: time_to_str, auto_str_to_date: auto_str_to_date, auto_date_to_str: auto_date_to_str, - strftime_to_moment_format: strftime_to_moment_format, getLangDateFormat: getLangDateFormat, getLangTimeFormat: getLangTimeFormat, getLangDateFormatWoZero: getLangDateFormatWoZero, diff --git a/addons/web/static/src/legacy/js/core/translation.js b/addons/web/static/src/legacy/js/core/translation.js deleted file mode 100644 index 5c3c5b37578..00000000000 --- a/addons/web/static/src/legacy/js/core/translation.js +++ /dev/null @@ -1,125 +0,0 @@ - -/** @odoo-module **/ - -import { sprintf } from "@web/core/utils/strings"; -import Class from "@web/legacy/js/core/class"; - -var TranslationDataBase = Class.extend(/** @lends instance.TranslationDataBase# */{ - init: function() { - this.db = {}; - this.multi_lang = false - this.parameters = {"direction": 'ltr', - "date_format": '%m/%d/%Y', - "time_format": '%H:%M:%S', - "grouping": [], - "decimal_point": ".", - "thousands_sep": ",", - "code": "en_US"}; - }, - set_bundle: function(translation_bundle) { - var self = this; - this.multi_lang = translation_bundle.multi_lang - var modules = Object.keys(translation_bundle.modules); - modules.sort(); - if (modules.includes("web")) { - modules = ["web"].concat(modules.filter((module) => module !== "web")); - } - modules.forEach((name) => { - self.add_module_translation(translation_bundle.modules[name]); - }); - if (translation_bundle.lang_parameters) { - this.parameters = translation_bundle.lang_parameters; - this.parameters.grouping = JSON.parse(this.parameters.grouping); - } - }, - add_module_translation: function(mod) { - var self = this; - mod.messages.forEach((message) => { - self.db[message.id] = message.string; - }); - }, - build_translation_function: function() { - var self = this; - var fcnt = function(term, ...values) { - const translation = self.get(term) ?? term; - if (values.length === 0) { - return translation; - } - return sprintf(translation, ...values); - }; - fcnt.database = this; - return fcnt; - }, - get: function(key) { - return this.db[key]; - }, - /** - Loads the translations from an OpenERP server. - - @param {openerp.Session} session The session object to contact the server. - @param {Array} [modules] The list of modules to load the translation. If not specified, - it will default to all the modules installed in the current database. - @param {Object} [lang] lang The language. If not specified it will default to the language - of the current user. - @param {string} [url='/web/webclient/translations'] - @returns {Promise} - */ - load_translations: function(session, modules, lang, url) { - var self = this; - var cacheId = session.cache_hashes && session.cache_hashes.translations; - url = url || '/web/webclient/translations'; - url += '/' + (cacheId ? cacheId : Date.now()); - const paramsGet = {}; - if (modules) { - paramsGet.mods = modules.join(','); - } - if (lang) { - paramsGet.lang = lang; - } else if (session.is_frontend && session.lang_url_code) { - // Keep distinct cached responses per language. - paramsGet.unique = session.lang_url_code; - } - return $.get(url, paramsGet).then(function (trans) { - self.set_bundle(trans); - }); - } -}); - -/** - * Eager translation function, performs translation immediately at call - * site. Beware using this outside of method bodies (before the - * translation database is loaded), you probably want :func:`_lt` - * instead. - * - * @function _t - * @param {String} source string to translate - * @returns {String} source translated into the current locale - */ -export var _t = new TranslationDataBase().build_translation_function(); - -/** Setup jQuery timeago */ -/* - * Strings in timeago are "composed" with prefixes, words and suffixes. This - * makes their detection by our translating system impossible. Use all literal - * strings we're using with a translation mark here so the extractor can do its - * job. - */ -{ - _t('less than a minute ago'); - _t('about a minute ago'); - _t('%d minutes ago'); - _t('about an hour ago'); - _t('%d hours ago'); - _t('a day ago'); - _t('%d days ago'); - _t('about a month ago'); - _t('%d months ago'); - _t('about a year ago'); - _t('%d years ago'); -} - - -export default { - _t: _t, - TranslationDataBase: TranslationDataBase, -}; diff --git a/addons/web/static/src/legacy/js/owl_compatibility.js b/addons/web/static/src/legacy/js/owl_compatibility.js index 2d9719f169a..19ca24dca76 100644 --- a/addons/web/static/src/legacy/js/owl_compatibility.js +++ b/addons/web/static/src/legacy/js/owl_compatibility.js @@ -259,10 +259,6 @@ You should probably create a mapper in @web/legacy/utils` ); } - } else if (evType === 'get_session') { - if (payload.callback) { - payload.callback(this.env.session); - } } else { payload.__targetWidget = ev.target; this.trigger(evType.replace(/_/g, '-'), payload); 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 d6f4a053255..1c00afa801a 100644 --- a/addons/web/static/src/legacy/js/public/public_root.js +++ b/addons/web/static/src/legacy/js/public/public_root.js @@ -2,7 +2,6 @@ import dom from '@web/legacy/js/core/dom'; import legacyEnv from '@web/legacy/js/public/public_env'; -import session from 'web.session'; import {getCookie} from '@web/legacy/js/core/cookie_utils'; import publicWidget from '@web/legacy/js/public/public_widget'; import { registry } from '@web/core/registry'; @@ -11,10 +10,10 @@ import lazyloader from "@web/legacy/js/public/lazyloader"; import { makeLegacyNotificationService, - makeLegacySessionService, makeLegacyDialogMappingService, mapLegacyEnvToWowlEnv, makeLegacyRainbowManService, + makeLegacyRPCService, } from "../../utils"; import { standaloneAdapter } from "@web/legacy/js/owl_compatibility"; @@ -27,6 +26,7 @@ import { renderToString } from "@web/core/utils/render"; import { _t } from "@web/core/l10n/translation"; import { omit } from "@web/core/utils/objects"; import { Component, App, whenReady } from "@odoo/owl"; +import { getOrigin } from '@web/core/utils/urls'; const serviceRegistry = registry.category("services"); @@ -76,7 +76,6 @@ export const PublicRoot = publicWidget.RootWidget.extend({ // TODO would be even greater to wait for localeDef only when necessary return Promise.all([ this._super.apply(this, arguments), - session.is_bound, localeDef ]); }, @@ -362,7 +361,7 @@ export async function createPublicRoot(RootWidget) { await lazyloader.allScriptsLoaded; // add a bunch of mapping services that will redirect service calls from the legacy env // to the wowl env - serviceRegistry.add("legacy_session", makeLegacySessionService(legacyEnv, session)); + serviceRegistry.add("legacy_rpc", makeLegacyRPCService(legacyEnv)); serviceRegistry.add("legacy_notification", makeLegacyNotificationService(legacyEnv)); serviceRegistry.add("legacy_dialog_mapping", makeLegacyDialogMappingService(legacyEnv)); serviceRegistry.add("legacy_rainbowman_service", makeLegacyRainbowManService(legacyEnv)); @@ -370,11 +369,11 @@ export async function createPublicRoot(RootWidget) { for (const [legacyServiceName, wowlToLegacyServiceMapper] of wowlToLegacyServiceMappers) { serviceRegistry.add(legacyServiceName, wowlToLegacyServiceMapper(legacyEnv)); } - await Promise.all([whenReady(), session.is_bound]); + await whenReady(); // Patch browser.fetch and the rpc service to use the correct base url when // embeded in an external page - const baseUrl = session.prefix; + const baseUrl = getOrigin(); const { fetch } = browser; browser.fetch = function(url, ...args) { if (!url.match(/^(?:https?:)?\/\//)) { diff --git a/addons/web/static/src/legacy/js/services/session.js b/addons/web/static/src/legacy/js/services/session.js deleted file mode 100644 index b1f8acec678..00000000000 --- a/addons/web/static/src/legacy/js/services/session.js +++ /dev/null @@ -1,8 +0,0 @@ -/** @odoo-module alias=web.session **/ - -import Session from "@web/legacy/js/core/session"; - -var session = new Session(undefined, undefined, {use_cors: false}); -session.is_bound = session.session_bind() - -export default session; diff --git a/addons/web/static/src/legacy/legacy_setup.js b/addons/web/static/src/legacy/legacy_setup.js index d14c41c0a91..d9727aef062 100644 --- a/addons/web/static/src/legacy/legacy_setup.js +++ b/addons/web/static/src/legacy/legacy_setup.js @@ -3,15 +3,15 @@ import { registry } from "../core/registry"; import { makeLegacyNotificationService, - makeLegacySessionService, makeLegacyDialogMappingService, makeLegacyCrashManagerService, makeLegacyCommandService, makeLegacyDropdownService, + makeMomentLoaderService, + makeLegacyRPCService, } from "./utils"; import { makeLegacyActionManagerService } from "./backend_utils"; import legacyEnv from "@web/legacy/js/env"; -import session from "web.session"; import { templates } from "@web/core/assets"; import { Component, whenReady } from "@odoo/owl"; @@ -30,8 +30,7 @@ export const legacySetupProm = new Promise((resolve) => { serviceRegistry.add("legacy_action_manager", legacyActionManagerService); // add a service to redirect rpc events triggered on the bus in the // legacy env on the bus in the wowl env - const legacySessionService = makeLegacySessionService(legacyEnv, session); - serviceRegistry.add("legacy_session", legacySessionService); + serviceRegistry.add("legacy_rpc", makeLegacyRPCService(legacyEnv)); serviceRegistry.add("legacy_notification", makeLegacyNotificationService(legacyEnv)); serviceRegistry.add("legacy_crash_manager", makeLegacyCrashManagerService(legacyEnv)); const legacyDialogMappingService = makeLegacyDialogMappingService(legacyEnv); @@ -39,11 +38,12 @@ export const legacySetupProm = new Promise((resolve) => { const legacyCommandService = makeLegacyCommandService(legacyEnv); serviceRegistry.add("legacy_command", legacyCommandService); serviceRegistry.add("legacy_dropdown", makeLegacyDropdownService(legacyEnv)); + serviceRegistry.add("moment", makeMomentLoaderService()); const wowlToLegacyServiceMappers = registry.category("wowlToLegacyServiceMappers").getEntries(); for (const [legacyServiceName, wowlToLegacyServiceMapper] of wowlToLegacyServiceMappers) { serviceRegistry.add(legacyServiceName, wowlToLegacyServiceMapper(legacyEnv)); } - await Promise.all([whenReady(), session.is_bound]); + await whenReady(); legacyEnv.templates = templates; legacySetupResolver(legacyEnv); })(); diff --git a/addons/web/static/src/legacy/utils.js b/addons/web/static/src/legacy/utils.js index 460e6ed4099..6b7ed62161f 100644 --- a/addons/web/static/src/legacy/utils.js +++ b/addons/web/static/src/legacy/utils.js @@ -1,16 +1,11 @@ /** @odoo-module **/ import { browser } from "../core/browser/browser"; -import { - ConnectionAbortedError, - RPCError, - makeErrorFromResponse, - ConnectionLostError, -} from "../core/network/rpc_service"; +import { makeErrorFromResponse } from "../core/network/rpc_service"; import { ErrorDialog } from "../core/errors/error_dialogs"; import { useService } from "@web/core/utils/hooks"; - import { Component, useComponent, xml } from "@odoo/owl"; +import { loadJS } from "@web/core/assets"; export const wowlServicesSymbol = Symbol("wowlServices"); @@ -111,64 +106,10 @@ export function makeLegacyDropdownService(legacyEnv) { }; } -export function makeLegacySessionService(legacyEnv, session) { - return { - dependencies: ["user"], - start(env) { - // userContext, Object.create is incompatible with legacy new Context - function mapContext() { - return Object.assign({}, env.services.user.context); - } - Object.defineProperty(legacyEnv.session, "userContext", { - get: () => mapContext(), - }); - Object.defineProperty(session, "user_context", { - get: () => mapContext(), - }); - }, - }; -} - export function mapLegacyEnvToWowlEnv(legacyEnv, wowlEnv) { // store wowl services on the legacy env (used by the 'useWowlService' hook) legacyEnv[wowlServicesSymbol] = wowlEnv.services; - // rpc - legacyEnv.session.rpc = (...args) => { - let rejection; - const prom = new Promise((resolve, reject) => { - const [route, params, settings = {}] = args; - // Add user context in kwargs if there are kwargs - if (params && params.kwargs) { - params.kwargs.context = Object.assign( - {}, - legacyEnv.session.user_context, - params.kwargs.context - ); - } - const jsonrpc = wowlEnv.services.rpc(route, params, { - silent: settings.shadow, - xhr: settings.xhr, - }); - rejection = () => { - jsonrpc.abort(); - }; - jsonrpc.then(resolve).catch((reason) => { - if (reason instanceof RPCError || reason instanceof ConnectionLostError) { - // we do not reject an error here because we want to pass through - // the legacy guardedCatch code - reject({ message: reason, event: $.Event(), legacy: true }); - } else if (reason instanceof ConnectionAbortedError) { - reject({ message: reason.message, event: $.Event("abort") }); - } else { - reject(reason); - } - }); - }); - prom.abort = rejection; - return prom; - }; - legacyEnv.services.dialog = wowlEnv.services.dialog; legacyEnv.services.ui = wowlEnv.services.ui; @@ -307,6 +248,51 @@ export function makeLegacyRainbowManService(legacyEnv) { }; } +export function makeMomentLoaderService() { + return { + dependencies: ["localization"], + async start(_, { localization }) { + await loadJS(`/web/webclient/locale/${localization.code}`); + const dow = (localization.weekStart || 0) % 7; + moment.updateLocale(moment.locale(), { + dow, + doy: 7 + dow - 4, // Note: ISO 8601 week date: https://momentjscom.readthedocs.io/en/latest/moment/07-customization/16-dow-doy/ + }); + }, + }; +} + +export function makeLegacyRPC(wowlRPC) { + return function rpc(route, args, options, target) { + let rpcPromise = null; + const promise = new Promise(function (resolve, reject) { + rpcPromise = wowlRPC(route, args, options); + rpcPromise.then(function (result) { + if (!target.isDestroyed()) { + resolve(result); + } + }).guardedCatch(function (reason) { + if (!target.isDestroyed()) { + reject(reason); + } + }); + }); + promise.abort = rpcPromise.abort.bind(rpcPromise); + return promise; + }; +} + +export function makeLegacyRPCService(legacyEnv) { + return { + dependencies: ["rpc"], + start(_, { rpc: wowlRPC }) { + const rpc = makeLegacyRPC(wowlRPC); + legacyEnv.services.ajax = { rpc }; + legacyEnv.services.rpc = rpc; + }, + }; +} + export function useLegacyRefs() { const env = owl.useEnv(); diff --git a/addons/web/static/tests/helpers/session.js b/addons/web/static/tests/helpers/session.js deleted file mode 100644 index 41211a5fb44..00000000000 --- a/addons/web/static/tests/helpers/session.js +++ /dev/null @@ -1,24 +0,0 @@ -/** @odoo-module **/ - -// Override the Session.session_reload function -// The wowl test infrastructure does set a correct odoo global value before each test -// while the session is built only once for all tests. -// So if a test does a session_reload, it will merge the odoo global of that test -// into the session, and will alter every subsequent test of the suite. -// Obviously, we don't want that, ever. -import { session as sessionInfo } from "@web/session"; -const initialSessionInfo = Object.assign({}, sessionInfo); -import Session from "@web/legacy/js/core/session"; -import { patch } from "@web/core/utils/patch"; - -patch(Session.prototype, { - async session_reload() { - for (const key in sessionInfo) { - delete sessionInfo[key]; - } - for (const key in initialSessionInfo) { - sessionInfo[key] = initialSessionInfo[key]; - } - return await super.session_reload(...arguments); - }, -}); diff --git a/addons/web/static/tests/legacy/core/time_tests.js b/addons/web/static/tests/legacy/core/time_tests.js index be1b76afd37..8e772606152 100644 --- a/addons/web/static/tests/legacy/core/time_tests.js +++ b/addons/web/static/tests/legacy/core/time_tests.js @@ -1,5 +1,6 @@ /** @odoo-module **/ +import { strftimeToLuxonFormat } from "@web/core/l10n/dates"; import { localization } from "@web/core/l10n/localization"; import time from "@web/legacy/js/core/time"; @@ -149,8 +150,8 @@ QUnit.module('core', {}, function () { assert.expect(4); const originalParameters = Object.assign({}, localization); Object.assign(localization, { - dateFormat: '%m/%d/%Y', - timeFormat: '%H:%M:%S', + dateFormat: strftimeToLuxonFormat('%m/%d/%Y'), + timeFormat: strftimeToLuxonFormat('%H:%M:%S'), }); assert.strictEqual(time.getLangDateFormat(), "MM/DD/YYYY"); assert.strictEqual(time.getLangDateFormatWoZero(), "M/D/YYYY"); diff --git a/addons/web/static/tests/legacy/core/widget_tests.js b/addons/web/static/tests/legacy/core/widget_tests.js index aaed38199de..639a8c53a2c 100644 --- a/addons/web/static/tests/legacy/core/widget_tests.js +++ b/addons/web/static/tests/legacy/core/widget_tests.js @@ -2,11 +2,9 @@ import Dialog from "@web/legacy/js/core/dialog"; import Widget from "@web/legacy/js/core/widget"; -import session from "web.session"; -import { patchWithCleanup } from "@web/../tests/helpers/utils"; import testUtils from "@web/../tests/legacy/helpers/test_utils"; import { renderToString } from "@web/core/utils/render"; -import env from "@web/legacy/js/common_env"; +import { makeLegacyRPC } from "@web/legacy/utils"; QUnit.module('core', {}, function () { @@ -403,18 +401,17 @@ QUnit.module('core', {}, function () { QUnit.test("calling _rpc on destroyed widgets", async function (assert) { assert.expect(3); + const rpc = makeLegacyRPC(() => { + def = testUtils.makeTestPromise(); + def.abort = def.reject; + return def; + }); + var def; var parent = new Widget(); - patchWithCleanup(session, { - rpc: () => { - def = testUtils.makeTestPromise(); - def.abort = def.reject; - return def; - }, - }); testUtils.mock.intercept(parent, 'call_service', function ({ data }) { if (data.service === "ajax" && data.method === "rpc") { - data.callback(env.services.ajax.rpc(...data.args)); + data.callback(rpc(...data.args)); } }); var widget = new Widget(parent); diff --git a/addons/web/static/tests/legacy/helpers/test_env.js b/addons/web/static/tests/legacy/helpers/test_env.js index 7153a194411..0d548be2b14 100644 --- a/addons/web/static/tests/legacy/helpers/test_env.js +++ b/addons/web/static/tests/legacy/helpers/test_env.js @@ -1,8 +1,7 @@ /** @odoo-module **/ import Bus from "@web/legacy/js/core/bus"; - import session from "web.session"; - import { makeTestEnvServices } from "@web/../tests/legacy/helpers/test_services"; + import { buildQuery } from "@web/legacy/js/core/rpc"; import { templates, setLoadXmlDefaultApp } from "@web/core/assets"; import { renderToString } from "@web/core/utils/render"; const { App, Component } = owl; @@ -25,29 +24,31 @@ setLoadXmlDefaultApp(app); } + function rpc(route, params, options) { + if (providedRPC) { + return providedRPC(route, params, options); + } + throw new Error(`No method to perform RPC`); + } + const defaultEnv = { - browser: Object.assign({ - setTimeout: window.setTimeout.bind(window), - clearTimeout: window.clearTimeout.bind(window), - setInterval: window.setInterval.bind(window), - clearInterval: window.clearInterval.bind(window), - requestAnimationFrame: window.requestAnimationFrame.bind(window), - Date: window.Date, - fetch: (window.fetch || (() => { })).bind(window), - }, env.browser), bus: env.bus || new Bus(), debug: env.debug || false, - services: makeTestEnvServices(env), - session: Object.assign({ - rpc(route, params, options) { - if (providedRPC) { - return providedRPC(route, params, options); - } - throw new Error(`No method to perform RPC`); + services: { + getCookie() {}, + httpRequest(/* route, params = {}, readMethod = 'json' */) { + return Promise.resolve(''); }, - url: session.url, - getTZOffset: (() => 0), - }, env.session), + hotkey: { add: () => () => {} }, // fake service + notification: { notify() {} }, + ajax: { rpc }, + rpc(params, options) { + const query = buildQuery(params); + return rpc(query.route, query.params, options); + }, + ui: { activeElement: document }, // fake service + ...env.services, + }, }; return Object.assign(env, defaultEnv); } diff --git a/addons/web/static/tests/legacy/helpers/test_services.js b/addons/web/static/tests/legacy/helpers/test_services.js deleted file mode 100644 index 25c5d528d4a..00000000000 --- a/addons/web/static/tests/legacy/helpers/test_services.js +++ /dev/null @@ -1,38 +0,0 @@ -/** @odoo-module */ - -import { buildQuery } from '@web/legacy/js/core/rpc'; - -const testEnvServices = { - getCookie() {}, - httpRequest(/* route, params = {}, readMethod = 'json' */) { - return Promise.resolve(''); - }, - hotkey: { add: () => () => {} }, // fake service - notification: { notify() {} }, -}; - -/** - * Creates services for the test environment. object - * - * @param {Object} [env] - * @returns {Object} - */ -function makeTestEnvServices(env) { - return Object.assign({}, testEnvServices, { - ajax: { - rpc() { - return env.session.rpc(...arguments); // Compatibility Legacy Widgets - }, - }, - rpc(params, options) { - const query = buildQuery(params); - return env.session.rpc(query.route, query.params, options); - }, - ui: { activeElement: document }, // fake service - }, env.services); -} - -export { - makeTestEnvServices, - testEnvServices, -}; diff --git a/addons/web/static/tests/legacy/patch_localization.js b/addons/web/static/tests/legacy/patch_localization.js new file mode 100644 index 00000000000..5adca670b99 --- /dev/null +++ b/addons/web/static/tests/legacy/patch_localization.js @@ -0,0 +1,16 @@ +/** @odoo-module */ + +import { localization } from "@web/core/l10n/localization"; + +Object.assign(localization, { + dateFormat: "MM/dd/yyyy", + timeFormat: "HH:mm:ss", + dateTimeFormat: "MM/dd/yyyy HH:mm:ss", + decimalPoint: ".", + direction: "ltr", + grouping: [], + multiLang: false, + thousandsSep: ",", + weekStart: 7, + code: "en", +}); diff --git a/addons/web/static/tests/setup.js b/addons/web/static/tests/setup.js index 466be61c21f..a971f47ce11 100644 --- a/addons/web/static/tests/setup.js +++ b/addons/web/static/tests/setup.js @@ -1,8 +1,6 @@ /** @odoo-module **/ -import { _t } from "@web/legacy/js/core/translation"; import LegacyBus from "@web/legacy/js/core/bus"; -import session from "web.session"; import { assets, templates } from "@web/core/assets"; import { browser, makeRAMLocalStorage } from "@web/core/browser/browser"; import { nextTick, patchTimeZone, patchWithCleanup } from "@web/../tests/helpers/utils"; @@ -18,40 +16,6 @@ transitionConfig.disabled = true; import { patch } from "@web/core/utils/patch"; import { App, EventBus, whenReady } from "@odoo/owl"; import { currencies } from "@web/core/currency"; -import "./helpers/session"; - -function stringifyObjectValues(obj, properties) { - let res = ""; - for (const dotted of properties) { - const keys = dotted.split("."); - let val = obj; - for (const k of keys) { - val = val[k]; - } - res += JSON.stringify(val); - } - return res; -} - -function checkGlobalObjectsIntegrity() { - const objects = [ - [session, ["user_context", "currencies"]], - [_t, ["database.multi_lang", "database.parameters"]], - ]; - const initials = objects.map((obj) => stringifyObjectValues(obj[0], obj[1])); - - registerCleanup((infos) => { - const finals = objects.map((obj) => stringifyObjectValues(obj[0], obj[1])); - for (const index in initials) { - if (initials[index] !== finals[index]) { - const [, /* global */ keys] = objects[index]; - throw new Error( - `The keys "${keys}" of some global objects (usually session or _t) may have been polluted by the test "${infos.testName}" in module "${infos.moduleName}". Initial: ${initials[index]}. Final: ${finals[index]}.` - ); - } - } - }); -} function forceLocaleAndTimezoneWithCleanup() { const originalLocale = luxon.Settings.defaultLocale; @@ -385,7 +349,6 @@ export async function setupTests() { // } QUnit.testStart(() => { - checkGlobalObjectsIntegrity(); prepareRegistriesWithCleanup(); forceLocaleAndTimezoneWithCleanup(); cleanLoadedLanguages(); @@ -398,7 +361,7 @@ export async function setupTests() { patchOwlApp(); }); - await Promise.all([whenReady(), session.is_bound]); + await whenReady(); // alt attribute causes issues with scroll tests. Indeed, alt is // displayed between the time we scroll programatically and the time diff --git a/addons/web_editor/__manifest__.py b/addons/web_editor/__manifest__.py index 40696f67df1..67136ceaeb1 100644 --- a/addons/web_editor/__manifest__.py +++ b/addons/web_editor/__manifest__.py @@ -103,9 +103,7 @@ Odoo Web Editor widget. 'web/static/src/legacy/js/core/mixins.js', 'web/static/src/legacy/js/core/rpc.js', 'web/static/src/legacy/js/core/service_mixins.js', - 'web/static/src/legacy/js/core/session.js', 'web/static/src/legacy/js/core/time.js', - 'web/static/src/legacy/js/core/translation.js', 'web/static/src/legacy/js/core/utils.js', 'web/static/src/legacy/js/core/widget.js', 'web/static/src/legacy/js/services/core.js', diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js index acb93cb83cd..b36f2b5e70b 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg.js @@ -3028,10 +3028,6 @@ export class Wysiwyg extends Component { const payload = ev.data; if (evType === 'call_service') { this._callService(payload); - } else if (evType === 'get_session') { - if (payload.callback) { - payload.callback(this.env.session); - } } } _callService(payload) { diff --git a/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js b/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js index 4f2ebb9c944..0bb692ac1c1 100644 --- a/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js +++ b/addons/web_editor/static/src/js/wysiwyg/wysiwyg_iframe.js @@ -215,10 +215,6 @@ function getWysiwygIframeContent(params) { ${assets.jsContents.join('\n')}