[FIX] web: register template of dynamic classes once

Before this commit, the template of some dynamic classes (usually as WOWL to legacyAdapters)
were registered at each definition of the class which is potentially at every doAction/switchView

After this commit, they are all registered only once, as early as possible.

closes odoo/odoo#72476

Related: odoo/enterprise#19199
Signed-off-by: Géry Debongnie (ged) <ged@openerp.com>
This commit is contained in:
Lucas Perais (lpe)
2021-06-23 15:47:56 +00:00
parent 4e37b0bab0
commit c00fb3cede
6 changed files with 39 additions and 28 deletions
@@ -13,6 +13,8 @@ import { cleanDomFromBootstrap, wrapSuccessOrFail, mapDoActionOptionAPI } from "
const { Component, tags } = owl;
const warningDialogBodyTemplate = tags.xml`<t t-esc="props.message"/>`;
class ActionAdapter extends ComponentAdapter {
setup() {
super.setup();
@@ -95,7 +97,7 @@ class ActionAdapter extends ComponentAdapter {
this.title = this.props.title;
}
}
WarningDialog.bodyTemplate = tags.xml`<t t-esc="props.message"/>`;
WarningDialog.bodyTemplate = warningDialogBodyTemplate;
this.dialogs.add(WarningDialog, {
title: payload.title,
message: payload.message,
@@ -16,6 +16,8 @@ odoo.define('web.OwlCompatibility', function () {
const widgetSymbol = odoo.widgetSymbol;
const children = new WeakMap(); // associates legacy widgets with their Owl children
const templateForLegacy = tags.xml`<div/>`;
const templateForOwl = tags.xml`<t t-component="props.Component" t-props="childProps" />`;
/**
* Case 1) An Owl component has to instantiate legacy widgets
* ----------------------------------------------------------
@@ -85,15 +87,9 @@ odoo.define('web.OwlCompatibility', function () {
}
let template;
if (!(props.Component.prototype instanceof Component)) {
template = tags.xml`<div/>`;
template = templateForLegacy;
} else {
let propsStr = '';
for (let p in props) {
if (p !== 'Component') {
propsStr += ` ${p}="props.${p}"`;
}
}
template = tags.xml`<t t-component="props.Component"${propsStr}/>`;
template = templateForOwl;
}
ComponentAdapter.template = template;
super(...arguments);
@@ -103,6 +99,14 @@ odoo.define('web.OwlCompatibility', function () {
this.widget = null; // widget instance, if Component is a legacy widget
}
get childProps() {
if (!this._childProps) {
this._childProps = Object.assign({}, this.props);
delete this._childProps.Component;
}
return this._childProps;
}
/**
* Starts the legacy widget (not in the DOM yet)
*
@@ -11,6 +11,11 @@ import { breadcrumbsToLegacy } from "./utils";
const { Component, hooks, tags } = owl;
const actionRegistry = registry.category("actions");
const legacyClientActionTemplate = tags.xml`
<ClientActionAdapter Component="Widget" widgetArgs="widgetArgs" widget="widget"
onReverseBreadcrumb="onReverseBreadcrumb" t-ref="controller"
t-on-scrollTo.stop="onScrollTo"/>`;
// registers an action from the legacy action registry to the wowl one, ensuring
// that widget actions are actually Components
function registerClientAction(name, action) {
@@ -44,11 +49,7 @@ function registerClientAction(name, action) {
};
}
}
Action.template = tags.xml`
<ClientActionAdapter Component="Widget" widgetArgs="widgetArgs" widget="widget"
onReverseBreadcrumb="onReverseBreadcrumb" t-ref="controller"
t-on-scrollTo.stop="onScrollTo"/>
`;
Action.template = legacyClientActionTemplate;
Action.components = { ClientActionAdapter };
Action.isLegacy = true;
Action.target = action.prototype.target;
+7 -6
View File
@@ -18,6 +18,11 @@ function getJsClassWidget(fieldsInfo) {
return legacyViewRegistry.get(key);
}
const legacyViewTemplate = tags.xml`
<ViewAdapter Component="Widget" View="View" viewInfo="viewInfo" viewParams="viewParams"
widget="widget" onReverseBreadcrumb="onReverseBreadcrumb" t-ref="controller"
t-on-scrollTo.stop="onScrollTo"/>`;
// registers a view from the legacy view registry to the wowl one, but wrapped
// into an Owl Component
function registerView(name, LegacyView) {
@@ -106,7 +111,7 @@ function registerView(name, LegacyView) {
.map(([vid, vtype]) => {
const view = this.props.viewSwitcherEntries.find((v) => v.type === vtype);
if (view) {
return Object.assign({}, view, {viewID: vid});
return Object.assign({}, view, { viewID: vid });
} else {
return {
viewID: vid,
@@ -122,12 +127,8 @@ function registerView(name, LegacyView) {
});
}
}
Controller.template = legacyViewTemplate;
Controller.template = tags.xml`
<ViewAdapter Component="Widget" View="View" viewInfo="viewInfo" viewParams="viewParams"
widget="widget" onReverseBreadcrumb="onReverseBreadcrumb" t-ref="controller"
t-on-scrollTo.stop="onScrollTo"/>
`;
Controller.components = { ViewAdapter };
Controller.display_name = LegacyView.prototype.display_name;
Controller.icon = LegacyView.prototype.icon;
@@ -20,6 +20,8 @@ const legacySystrayMenuItems = legacySystrayMenu.Items;
const convertedItems = [];
let id = 1;
const legacySystrayItemTemplate = tags.xml`<SystrayItemAdapter Component="Widget" />`;
function addSystrayItem(Widget) {
const name = `_legacy_systray_item_${id++}`;
@@ -29,7 +31,7 @@ function addSystrayItem(Widget) {
this.Widget = Widget;
}
}
SystrayItem.template = tags.xml`<SystrayItemAdapter Component="Widget" />`;
SystrayItem.template = legacySystrayItemTemplate;
SystrayItem.components = { SystrayItemAdapter };
systrayRegistry.add(name, { Component: SystrayItem }, { sequence: Widget.prototype.sequence });
@@ -69,6 +69,13 @@ export class InvalidButtonParamsError extends Error {}
// regex that matches context keys not to forward from an action to another
const CTX_KEY_REGEX = /^(?:(?:default_|search_default_|show_).+|.+_view_ref|group_by|group_by_no_leaf|active_id|active_ids|orderedBy)$/;
// only register this template once for all dynamic classes ControllerComponent
const ControllerComponentTemplate = tags.xml`<t t-component="Component" t-props="props"
registerCallback="registerCallback"
t-ref="component"
t-on-history-back="onHistoryBack"
t-on-controller-title-updated.stop="onTitleUpdated"/>`;
function makeActionManager(env) {
const keepLast = new KeepLast();
let id = 0;
@@ -525,13 +532,7 @@ function makeActionManager(env) {
controller.title = ev.detail;
}
}
ControllerComponent.template = tags.xml`<t t-component="Component" t-props="props"
registerCallback="registerCallback"
t-ref="component"
t-on-history-back="onHistoryBack"
t-on-controller-title-updated.stop="onTitleUpdated"/>`;
ControllerComponent.template = ControllerComponentTemplate;
ControllerComponent.Component = controller.Component;
let nextDialog = {};