[REF] web, *: remove owl2 compatibility

*: mrp_subcontracting, point_of_sale, project, web_editor, website,
website_slides

Part of task-id 3439226

closes odoo/odoo#133551

Related: odoo/enterprise#46526
Signed-off-by: Samuel Degueldre (sad) <sad@odoo.com>
This commit is contained in:
Pierre Rousseau
2023-09-01 13:20:56 +00:00
parent ac0b6d30b4
commit 82697d0b18
18 changed files with 105 additions and 186 deletions
+1 -1
View File
@@ -68,7 +68,7 @@
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/libs/owl.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js',
+1 -1
View File
@@ -154,7 +154,7 @@
('include', 'point_of_sale._assets_pos'),
# dependencies of web.tests_assets (in the web tests, these come from assets_backend)
'web/static/tests/patch_translations.js',
'web/static/src/owl2_compatibility/app.js',
'web/static/src/libs/owl.js',
'web/static/lib/jquery/jquery.js',
'web/static/lib/jquery/jquery.browser.js',
'web/static/lib/jquery.ba-bbq/jquery.ba-bbq.js',
+1 -1
View File
@@ -119,7 +119,7 @@
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/libs/owl.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js',
+3 -3
View File
@@ -212,7 +212,7 @@ This module provides the core of the Odoo Web Client.
'web/static/lib/moment/moment.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/libs/owl.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js',
@@ -388,7 +388,7 @@ This module provides the core of the Odoo Web Client.
# libs
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/libs/owl.js',
'web/static/lib/owl/odoo_module.js',
# core
'web/static/src/env.js',
@@ -456,7 +456,7 @@ This module provides the core of the Odoo Web Client.
# remove this bundle alongside the owl2 compatibility layer
'web.assets_backend_tests': [
('include', 'web.assets_backend'),
('after', 'web/static/src/owl2_compatibility/app.js', 'web/static/tests/owl2_compatibility_app.js'),
('after', 'web/static/src/libs/owl.js', 'web/static/tests/owl2_compatibility_app.js'),
],
'web.tests_assets': [
'web/static/tests/patch_translations.js',
@@ -517,7 +517,8 @@ var RootWidget = PublicWidget.extend({
var defs = [this._super.apply(this, arguments)];
defs.push(this._attachComponents());
this._getRegistry().on("UPDATE", this, ({ operation, value }) => {
this._getRegistry().addEventListener("UPDATE", ({ detail }) => {
const { operation, value } = detail;
if (operation === "add") {
this._attachComponent(value);
}
+1
View File
@@ -0,0 +1 @@
owl.App.validateTarget = () => {};
@@ -1,36 +0,0 @@
(function () {
const App = owl.App;
// templates' code is shared between multiple instances of Apps
// This is useful primarly for the OWL2 to Legacy compatibility layer
// It is also useful for tests.
// The downside of this is that the compilation is done once with the compiling app's
// translate function and attributes.
const sharedTemplates = {};
owl.App = class extends App {
constructor(_, config) {
if (!config.test) {
const missingKeys = ["dev", "translateFn", "translatableAttributes"].filter(
(key) => !(key in config)
);
if (missingKeys.length) {
throw new Error(
`Attempted to create an App without some required key(s) (${missingKeys.join(
", "
)})`
);
}
}
super(...arguments);
}
_compileTemplate(name) {
if (!(name in sharedTemplates)) {
sharedTemplates[name] = super._compileTemplate(...arguments);
}
return sharedTemplates[name];
}
};
owl.App.sharedTemplates = sharedTemplates;
owl.App.validateTarget = () => {};
})();
@@ -1,42 +0,0 @@
(function () {
const { EventBus } = owl;
function wrapCallback(owner, callback) {
return (ev) => {
callback.call(owner, ev.detail);
};
}
owl.EventBus = class extends EventBus {
constructor(...args) {
super(...args);
this.targetsCallbacks = new Map();
}
on(type, target, callback) {
if (!this.targetsCallbacks.has(target)) {
this.targetsCallbacks.set(target, {});
}
callback = wrapCallback(target, callback);
const listeners = this.targetsCallbacks.get(target);
if (!listeners[type]) {
listeners[type] = new Set();
}
listeners[type].add(callback);
return this.addEventListener(type, callback);
}
off(type, target) {
const listeners = this.targetsCallbacks.get(target);
if (!listeners || !Object.hasOwnProperty.call(listeners, type)) {
return;
}
const cbs = listeners[type];
for (const callback of cbs) {
this.removeEventListener(type, callback);
}
delete listeners[type];
if (Object.keys(listeners).length === 0) {
this.targetsCallbacks.delete(target);
}
}
};
})();
@@ -10,10 +10,10 @@ import { ErrorHandler } from "@web/core/utils/components";
import {
Component,
onWillDestroy,
onWillUnmount,
useExternalListener,
useEffect,
useRef,
onWillUnmount,
} from "@odoo/owl";
const systrayRegistry = registry.category("systray");
@@ -61,12 +61,12 @@ export class NavBar extends Component {
this.render();
};
systrayRegistry.on("UPDATE", this, renderAndAdapt);
this.env.bus.on("MENUS:APP-CHANGED", this, renderAndAdapt);
systrayRegistry.addEventListener("UPDATE", renderAndAdapt);
this.env.bus.addEventListener("MENUS:APP-CHANGED", renderAndAdapt);
onWillUnmount(() => {
systrayRegistry.off("UPDATE", this);
this.env.bus.off("MENUS:APP-CHANGED", this);
systrayRegistry.removeEventListener("UPDATE", renderAndAdapt);
this.env.bus.removeEventListener("MENUS:APP-CHANGED", renderAndAdapt);
});
// We don't want to adapt every time we are patched
@@ -1583,18 +1583,20 @@
QUnit.module("EventBus");
QUnit.test("unregister multiple listener from the same target", async function (assert) {
const target = Symbol("test");
const bus = new EventBus();
let i = 0;
bus.on("a", target, () => assert.step(`a:${i++}`));
bus.on("b", target, () => assert.step(`b:${i++}`));
const a = () => assert.step(`a:${i++}`);
const b = () => assert.step(`b:${i++}`);
bus.addEventListener("a", a);
bus.addEventListener("b", b);
bus.trigger("a");
bus.trigger("b");
bus.off("a", target);
bus.off("b", target);
bus.removeEventListener("a", a);
bus.removeEventListener("b", b);
bus.trigger("a");
bus.trigger("b");
@@ -189,7 +189,7 @@ QUnit.module("Search", (hooks) => {
Component: TestComponent,
searchViewId: false,
});
comp.env.bus.on("CLEAR-CACHES", comp, () => assert.step("CLEAR-CACHES"));
comp.env.bus.addEventListener("CLEAR-CACHES", () => assert.step("CLEAR-CACHES"));
assert.verifySteps([]);
@@ -283,7 +283,7 @@ QUnit.module("Search", (hooks) => {
}
},
});
webClient.env.bus.on("CLEAR-CACHES", webClient, () => assert.step("CLEAR-CACHES"));
webClient.env.bus.addEventListener("CLEAR-CACHES", () => assert.step("CLEAR-CACHES"));
await doAction(webClient, {
name: "Action",
res_model: "foo",
+69 -78
View File
@@ -68,12 +68,6 @@ function patchOwlApp() {
this.destroyed = true;
}
},
addTemplate(name) {
registerCleanup(() => {
delete this.constructor.sharedTemplates[name];
});
return super.addTemplate(...arguments);
},
});
}
@@ -89,82 +83,79 @@ function patchBrowserWithCleanup() {
let nextAnimationFrameHandle = 1;
const animationFrameHandles = new Set();
const mockLocation = makeMockLocation(() => hasHashChangeListeners);
patchWithCleanup(
browser,
{
// patch addEventListner to automatically remove listeners bound (via
// browser.addEventListener) during a test (e.g. during the deployment of a service)
addEventListener(evName) {
if (evName === "hashchange") {
hasHashChangeListeners = true;
}
originalAddEventListener(...arguments);
registerCleanup(() => {
originalRemoveEventListener(...arguments);
});
patchWithCleanup(browser, {
// patch addEventListner to automatically remove listeners bound (via
// browser.addEventListener) during a test (e.g. during the deployment of a service)
addEventListener(evName) {
if (evName === "hashchange") {
hasHashChangeListeners = true;
}
originalAddEventListener(...arguments);
registerCleanup(() => {
originalRemoveEventListener(...arguments);
});
},
// patch setTimeout to automatically remove timeouts bound (via
// browser.setTimeout) during a test (e.g. during the deployment of a service)
setTimeout() {
const timeout = originalSetTimeout(...arguments);
registerCleanup(() => {
originalClearTimeout(timeout);
});
return timeout;
},
// patch setInterval to automatically remove callbacks registered (via
// browser.setInterval) during a test (e.g. during the deployment of a service)
setInterval() {
const interval = originalSetInterval(...arguments);
registerCleanup(() => {
originalClearInterval(interval);
});
return interval;
},
navigator: {
mediaDevices: browser.navigator.mediaDevices,
permissions: browser.navigator.permissions,
userAgent: browser.navigator.userAgent.replace(/\([^)]*\)/, "(X11; Linux x86_64)"),
sendBeacon: () => {},
},
// in tests, we never want to interact with the real url or reload the page
location: mockLocation,
history: {
pushState(state, title, url) {
mockLocation.assign(url);
},
// patch setTimeout to automatically remove timeouts bound (via
// browser.setTimeout) during a test (e.g. during the deployment of a service)
setTimeout() {
const timeout = originalSetTimeout(...arguments);
registerCleanup(() => {
originalClearTimeout(timeout);
});
return timeout;
replaceState(state, title, url) {
mockLocation.assign(url);
},
// patch setInterval to automatically remove callbacks registered (via
// browser.setInterval) during a test (e.g. during the deployment of a service)
setInterval() {
const interval = originalSetInterval(...arguments);
registerCleanup(() => {
originalClearInterval(interval);
});
return interval;
},
navigator: {
mediaDevices: browser.navigator.mediaDevices,
permissions: browser.navigator.permissions,
userAgent: browser.navigator.userAgent.replace(/\([^)]*\)/, "(X11; Linux x86_64)"),
sendBeacon: () => {},
},
// in tests, we never want to interact with the real url or reload the page
location: mockLocation,
history: {
pushState(state, title, url) {
mockLocation.assign(url);
},
replaceState(state, title, url) {
mockLocation.assign(url);
},
},
// in tests, we never want to interact with the real local/session storages.
localStorage: makeRAMLocalStorage(),
sessionStorage: makeRAMLocalStorage(),
// Don't want original animation frames in tests
requestAnimationFrame: (fn) => {
const handle = nextAnimationFrameHandle++;
animationFrameHandles.add(handle);
},
// in tests, we never want to interact with the real local/session storages.
localStorage: makeRAMLocalStorage(),
sessionStorage: makeRAMLocalStorage(),
// Don't want original animation frames in tests
requestAnimationFrame: (fn) => {
const handle = nextAnimationFrameHandle++;
animationFrameHandles.add(handle);
Promise.resolve().then(() => {
if (animationFrameHandles.has(handle)) {
fn(16);
}
});
return handle;
},
cancelAnimationFrame: (handle) => {
animationFrameHandles.delete(handle);
},
// BroadcastChannels need to be closed to be garbage collected
BroadcastChannel: class SelfClosingBroadcastChannel extends BroadcastChannel {
constructor() {
super(...arguments);
registerCleanup(() => this.close());
Promise.resolve().then(() => {
if (animationFrameHandles.has(handle)) {
fn(16);
}
},
}
);
});
return handle;
},
cancelAnimationFrame: (handle) => {
animationFrameHandles.delete(handle);
},
// BroadcastChannels need to be closed to be garbage collected
BroadcastChannel: class SelfClosingBroadcastChannel extends BroadcastChannel {
constructor() {
super(...arguments);
registerCleanup(() => this.close());
}
},
});
}
function patchBodyAddEventListener() {
@@ -156,10 +156,10 @@ QUnit.test("loading indicator doesn't unblock ui if it didn't block it", async (
const env = await makeTestEnv();
const { execRegisteredTimeouts } = mockTimeout();
const ui = env.services.ui;
ui.bus.on("BLOCK", null, () => {
ui.bus.addEventListener("BLOCK", () => {
assert.step("block");
});
ui.bus.on("UNBLOCK", null, () => {
ui.bus.addEventListener("UNBLOCK", () => {
assert.step("unblock");
});
await mount(LoadingIndicator, target, { env });
+1 -2
View File
@@ -58,8 +58,7 @@ Odoo Web Editor widget.
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/libs/owl.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js',
'web/static/lib/jquery.ui/jquery-ui.js',
@@ -1,12 +1,14 @@
/** @odoo-module **/
import { useBus } from "@web/core/utils/hooks";
const { EventBus, Component, xml, useState } = owl;
export class FullscreenIndication extends Component {
setup() {
this.state = useState({ isVisible: false });
this.props.bus.on('FULLSCREEN-INDICATION-SHOW', this, this.show);
this.props.bus.on('FULLSCREEN-INDICATION-HIDE', this, this.hide);
useBus(this.props.bus, "FULLSCREEN-INDICATION-SHOW", this.show.bind(this));
useBus(this.props.bus, "FULLSCREEN-INDICATION-HIDE", this.hide.bind(this));
}
show() {
@@ -1,6 +1,6 @@
/** @odoo-module **/
import { useService } from "@web/core/utils/hooks";
import { useBus, useService } from "@web/core/utils/hooks";
import { sprintf } from "@web/core/utils/strings";
import { _t } from "@web/core/l10n/translation";
const { EventBus, Component, markup, useEffect, useState } = owl;
@@ -80,14 +80,15 @@ export class WebsiteLoader extends Component {
() => [this.state.isVisible]
);
this.props.bus.on('SHOW-WEBSITE-LOADER', this, (props) => {
useBus(this.props.bus, "SHOW-WEBSITE-LOADER", (ev) => {
const props = ev.detail;
this.state.isVisible = true;
this.state.title = props && props.title;
this.state.showTips = props && props.showTips;
this.state.selectedFeatures = props && props.selectedFeatures;
this.state.showWaitingMessages = props && props.showWaitingMessages;
});
this.props.bus.on('HIDE-WEBSITE-LOADER', this, () => {
useBus(this.props.bus, "HIDE-WEBSITE-LOADER", () => {
for (const key of Object.keys(initialState)) {
this.state[key] = initialState[key];
}
@@ -97,7 +98,7 @@ export class WebsiteLoader extends Component {
// Action needed if the app automatically refreshes or redirects the
// page without hiding/removing the WebsiteLoader. This should be
// called prior to any refresh/redirect if the loader is still visible.
this.props.bus.on("PREPARE-OUT-WEBSITE-LOADER", this, () => {
useBus(this.props.bus, "PREPARE-OUT-WEBSITE-LOADER", () => {
window.removeEventListener("beforeunload", this.showRefreshConfirmation);
});
}
+1 -1
View File
@@ -159,7 +159,7 @@ Featuring
'web/static/lib/luxon/luxon.js',
'web/static/lib/owl/owl.js',
'web/static/lib/owl/odoo_module.js',
'web/static/src/owl2_compatibility/*.js',
'web/static/src/libs/owl.js',
'web/static/src/legacy/js/component_extension.js',
'web/static/src/legacy/legacy_component.js',
'web/static/lib/jquery/jquery.js',