[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:
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user