diff --git a/addons/lunch/static/src/components/lunch_dashboard.xml b/addons/lunch/static/src/components/lunch_dashboard.xml
index 36226c4315a..59a8c02552b 100644
--- a/addons/lunch/static/src/components/lunch_dashboard.xml
+++ b/addons/lunch/static/src/components/lunch_dashboard.xml
@@ -49,6 +49,7 @@
value="props.username"
resModel="'res.users'"
getDomain="getDomain"
+ fieldString="props.username"
activeActions="{}"
update.bind="props.onUpdateUser"
/>
@@ -61,6 +62,7 @@
value="props.location"
resModel="'lunch.location'"
getDomain="getDomain"
+ fieldString="props.location"
activeActions="{}"
update.bind="props.onUpdateLunchLocation"
/>
diff --git a/addons/mail/static/src/components/activity_menu_container/activity_menu_container.js b/addons/mail/static/src/components/activity_menu_container/activity_menu_container.js
index 0980f769bd0..b9d7f260123 100644
--- a/addons/mail/static/src/components/activity_menu_container/activity_menu_container.js
+++ b/addons/mail/static/src/components/activity_menu_container/activity_menu_container.js
@@ -20,6 +20,7 @@ export class ActivityMenuContainer extends Component {
}
}
+ActivityMenuContainer.props = {};
Object.assign(ActivityMenuContainer, {
components: { ActivityMenuView: getMessagingComponent('ActivityMenuView') },
diff --git a/addons/mail/static/src/components/call_systray_menu_container/call_systray_menu_container.js b/addons/mail/static/src/components/call_systray_menu_container/call_systray_menu_container.js
index 153c9a47b91..2da088e3b75 100644
--- a/addons/mail/static/src/components/call_systray_menu_container/call_systray_menu_container.js
+++ b/addons/mail/static/src/components/call_systray_menu_container/call_systray_menu_container.js
@@ -22,6 +22,7 @@ export class CallSystrayMenuContainer extends Component {
}
}
+CallSystrayMenuContainer.props = {};
Object.assign(CallSystrayMenuContainer, {
components: { CallSystrayMenu: getMessagingComponent('CallSystrayMenu') },
diff --git a/addons/mail/static/src/components/chat_window_manager_container/chat_window_manager_container.js b/addons/mail/static/src/components/chat_window_manager_container/chat_window_manager_container.js
index e5f5b64ba43..77607a99667 100644
--- a/addons/mail/static/src/components/chat_window_manager_container/chat_window_manager_container.js
+++ b/addons/mail/static/src/components/chat_window_manager_container/chat_window_manager_container.js
@@ -21,6 +21,7 @@ export class ChatWindowManagerContainer extends Component {
return this.env.services.messaging.modelManager.messaging;
}
}
+ChatWindowManagerContainer.props = {};
Object.assign(ChatWindowManagerContainer, {
components: { ChatWindowManager: getMessagingComponent('ChatWindowManager') },
diff --git a/addons/mail/static/src/components/dialog_manager_container/dialog_manager_container.js b/addons/mail/static/src/components/dialog_manager_container/dialog_manager_container.js
index 2024aef1cd0..2431254c666 100644
--- a/addons/mail/static/src/components/dialog_manager_container/dialog_manager_container.js
+++ b/addons/mail/static/src/components/dialog_manager_container/dialog_manager_container.js
@@ -21,6 +21,7 @@ export class DialogManagerContainer extends Component {
return this.env.services.messaging.modelManager.messaging;
}
}
+DialogManagerContainer.props = {};
Object.assign(DialogManagerContainer, {
components: { DialogManager: getMessagingComponent('DialogManager') },
diff --git a/addons/mail/static/src/components/messaging_menu_container/messaging_menu_container.js b/addons/mail/static/src/components/messaging_menu_container/messaging_menu_container.js
index 5a45b20a226..59c96ad3b72 100644
--- a/addons/mail/static/src/components/messaging_menu_container/messaging_menu_container.js
+++ b/addons/mail/static/src/components/messaging_menu_container/messaging_menu_container.js
@@ -21,6 +21,7 @@ export class MessagingMenuContainer extends Component {
return this.env.services.messaging.modelManager.messaging;
}
}
+MessagingMenuContainer.props = {};
Object.assign(MessagingMenuContainer, {
components: { MessagingMenu: getMessagingComponent('MessagingMenu') },
diff --git a/addons/mail/static/src/components/notification_alert_container/notification_alert_container.js b/addons/mail/static/src/components/notification_alert_container/notification_alert_container.js
index cb1c8ba46fb..1360ea06eb2 100644
--- a/addons/mail/static/src/components/notification_alert_container/notification_alert_container.js
+++ b/addons/mail/static/src/components/notification_alert_container/notification_alert_container.js
@@ -9,6 +9,11 @@ export class NotificationAlertContainer extends Component {}
Object.assign(NotificationAlertContainer, {
components: { NotificationAlert: getMessagingComponent('NotificationAlert') },
template: 'mail.NotificationAlertContainer',
+ props: {
+ // Should call standard_widget_props.js
+ readonly: { type: Boolean, optional: true },
+ record: { type: Object },
+ },
});
registry.category("view_widgets").add(
"notification_alert",
diff --git a/addons/mail/static/src/components/popover_manager_container/popover_manager_container.js b/addons/mail/static/src/components/popover_manager_container/popover_manager_container.js
index 7d04816c272..9cdbdd33aa6 100644
--- a/addons/mail/static/src/components/popover_manager_container/popover_manager_container.js
+++ b/addons/mail/static/src/components/popover_manager_container/popover_manager_container.js
@@ -21,6 +21,7 @@ export class PopoverManagerContainer extends Component {
return this.env.services.messaging.modelManager.messaging;
}
}
+PopoverManagerContainer.props = {};
Object.assign(PopoverManagerContainer, {
components: { PopoverManager: getMessagingComponent('PopoverManager') },
diff --git a/addons/mail/static/src/views/form/form_renderer.js b/addons/mail/static/src/views/form/form_renderer.js
index c9fca166eea..e59b82c60b0 100644
--- a/addons/mail/static/src/views/form/form_renderer.js
+++ b/addons/mail/static/src/views/form/form_renderer.js
@@ -15,6 +15,13 @@ patch(FormRenderer.prototype, 'mail', {
},
});
+patch(FormRenderer.props, "mail", {
+ hasAttachmentViewerInArch: { type: Boolean, optional: true },
+ // Template props : added by the FormCompiler
+ hasAttachmentViewer: { type: Boolean, optional: true },
+ chatter: { type: Object, optional: true },
+});
+
Object.assign(FormRenderer.components, {
ChatterContainer,
WebClientViewAttachmentViewContainer,
diff --git a/addons/mail/static/tests/helpers/model_definitions_setup.js b/addons/mail/static/tests/helpers/model_definitions_setup.js
index 9efad779e15..ef8ce699495 100644
--- a/addons/mail/static/tests/helpers/model_definitions_setup.js
+++ b/addons/mail/static/tests/helpers/model_definitions_setup.js
@@ -28,7 +28,7 @@ addFakeModel('res.fake', {
addFakeModel('m2x.avatar.user', {
user_id: { type: 'many2one', relation: 'res.users' },
- user_ids: { type: 'many2many', relation: 'res.users' },
+ user_ids: { type: 'many2many', relation: 'res.users', string: 'Users'},
});
//--------------------------------------------------------------------------
diff --git a/addons/mrp/static/src/widgets/timer.js b/addons/mrp/static/src/widgets/timer.js
index c8111f32251..0e64226be2a 100644
--- a/addons/mrp/static/src/widgets/timer.js
+++ b/addons/mrp/static/src/widgets/timer.js
@@ -3,6 +3,7 @@
import { registry } from "@web/core/registry";
import { parseFloatTime } from "@web/views/fields/parsers";
import { useInputField } from "@web/views/fields/input_field_hook";
+import { standardFieldProps } from "@web/views/fields/standard_field_props";
const { Component, useState, onWillUpdateProps, onWillStart, onWillDestroy } = owl;
@@ -73,6 +74,12 @@ export class MrpTimer extends Component {
}
MrpTimer.supportedTypes = ["float"];
+MrpTimer.props = {
+ ...standardFieldProps,
+ duration: { type: Number, optional: true },
+ ongoing: { type: Boolean, optional: true },
+ value: { optional: true },
+};
MrpTimer.template = "mrp.MrpTimer";
registry.category("fields").add("mrp_timer", MrpTimer);
diff --git a/addons/project/static/src/project_sharing/project_sharing.js b/addons/project/static/src/project_sharing/project_sharing.js
index 0983f1388fb..dabca7e38e1 100644
--- a/addons/project/static/src/project_sharing/project_sharing.js
+++ b/addons/project/static/src/project_sharing/project_sharing.js
@@ -66,5 +66,6 @@ export class ProjectSharingWebClient extends Component {
}
}
+ProjectSharingWebClient.props = {};
ProjectSharingWebClient.components = { ActionContainer, MainComponentsContainer };
ProjectSharingWebClient.template = 'project.ProjectSharingWebClient';
diff --git a/addons/web/static/src/core/commands/command_palette.js b/addons/web/static/src/core/commands/command_palette.js
index b72d3739a82..0dc29ecc611 100644
--- a/addons/web/static/src/core/commands/command_palette.js
+++ b/addons/web/static/src/core/commands/command_palette.js
@@ -15,6 +15,7 @@ const {
Component,
onWillStart,
onWillDestroy,
+ EventBus,
useRef,
useState,
markRaw,
@@ -87,6 +88,15 @@ export function splitCommandName(name, searchValue) {
export class DefaultCommandItem extends Component {}
DefaultCommandItem.template = "web.DefaultCommandItem";
+DefaultCommandItem.props = {
+ slots: { type: Object, optional: true },
+ // Props send by the command palette:
+ hotkey: { type: String, optional: true },
+ hotkeyOptions: { type: String, optional: true },
+ name: { type: String, optional: true },
+ searchValue: { type: String, optional: true },
+ executeCommand: { type: Function, optional: true },
+};
export class CommandPalette extends Component {
setup() {
@@ -366,5 +376,11 @@ export class CommandPalette extends Component {
}
}
CommandPalette.lastSessionId = 0;
+CommandPalette.props = {
+ bus: { type: EventBus, optional: true },
+ close: Function,
+ config: Object,
+ closeMe: { type: Function, optional: true },
+};
CommandPalette.template = "web.CommandPalette";
CommandPalette.components = { Dialog };
diff --git a/addons/web/static/src/core/debug/debug_menu.js b/addons/web/static/src/core/debug/debug_menu.js
index aca4019d6ab..9b9993d726e 100644
--- a/addons/web/static/src/core/debug/debug_menu.js
+++ b/addons/web/static/src/core/debug/debug_menu.js
@@ -59,3 +59,4 @@ export class DebugMenu extends DebugMenuBasic {
}
}
DebugMenu.components = { Dropdown, DropdownItem };
+DebugMenu.props = {};
diff --git a/addons/web/static/src/core/dialog/dialog_container.js b/addons/web/static/src/core/dialog/dialog_container.js
index 51c53b44e9a..f9bfb874e55 100644
--- a/addons/web/static/src/core/dialog/dialog_container.js
+++ b/addons/web/static/src/core/dialog/dialog_container.js
@@ -13,6 +13,9 @@ export class DialogContainer extends Component {
}
}
DialogContainer.components = { ErrorHandler, WithEnv };
+DialogContainer.props = {
+ dialogs: Object,
+};
//Legacy : The div wrapping the t-foreach, is placed to avoid owl to delete non-owl dialogs.
//This div can be removed after removing all legacy dialogs.
DialogContainer.template = xml`
diff --git a/addons/web/static/src/core/effects/effect_container.js b/addons/web/static/src/core/effects/effect_container.js
index 61a663e015e..47a9730ddce 100644
--- a/addons/web/static/src/core/effects/effect_container.js
+++ b/addons/web/static/src/core/effects/effect_container.js
@@ -1,6 +1,6 @@
/** @odoo-module **/
-const { Component, xml, onWillDestroy } = owl;
+const { EventBus, Component, xml, onWillDestroy } = owl;
export class EffectContainer extends Component {
setup() {
@@ -18,6 +18,9 @@ export class EffectContainer extends Component {
this.render();
}
}
+EffectContainer.props = {
+ bus: EventBus,
+};
EffectContainer.template = xml`
diff --git a/addons/web/static/src/core/effects/rainbow_man.js b/addons/web/static/src/core/effects/rainbow_man.js
index a6e4e3c87e0..9de597727c6 100644
--- a/addons/web/static/src/core/effects/rainbow_man.js
+++ b/addons/web/static/src/core/effects/rainbow_man.js
@@ -63,4 +63,12 @@ export class RainbowMan extends Component {
}
}
RainbowMan.template = "web.RainbowMan";
+RainbowMan.props = {
+ fadeout: String,
+ close: Function,
+ message: String,
+ imgUrl: String,
+ Component: { type: Function, optional: true },
+ props: { type: Object, optional: true },
+};
RainbowMan.rainbowFadeouts = { slow: 4500, medium: 3500, fast: 2000, no: false };
diff --git a/addons/web/static/src/core/errors/error_dialogs.js b/addons/web/static/src/core/errors/error_dialogs.js
index 38fee8c3d8b..ebd4a8b66d8 100644
--- a/addons/web/static/src/core/errors/error_dialogs.js
+++ b/addons/web/static/src/core/errors/error_dialogs.js
@@ -9,6 +9,19 @@ import { capitalize } from "../utils/strings";
const { Component, useState } = owl;
+// This props are added by the error handler
+export const standardErrorDialogProps = {
+ traceback: { type: [String, { value: null }], optional: true },
+ message: { type: String, optional: true },
+ name: { type: String, optional: true },
+ exceptionName: { type: [String, { value: null }], optional: true },
+ data: { type: [Object, { value: null }], optional: true },
+ subType: { type: [String, { value: null }], optional: true },
+ code: { type: [Number, String, { value: null }], optional: true },
+ type: { type: [String, { value: null }], optional: true },
+ close: Function, // prop added by the Dialog service
+};
+
export const odooExceptionTitleMap = new Map(
Object.entries({
"odoo.addons.base.models.ir_mail_server.MailDeliveryException": _lt(
@@ -41,6 +54,7 @@ export class ErrorDialog extends Component {
ErrorDialog.template = "web.ErrorDialog";
ErrorDialog.components = { Dialog };
ErrorDialog.title = _lt("Odoo Error");
+ErrorDialog.props = { ...standardErrorDialogProps };
// -----------------------------------------------------------------------------
// Client Error Dialog
@@ -118,6 +132,10 @@ export class WarningDialog extends Component {
}
WarningDialog.template = "web.WarningDialog";
WarningDialog.components = { Dialog };
+WarningDialog.props = {
+ ...standardErrorDialogProps,
+ title: { type: String, optional: true },
+};
// -----------------------------------------------------------------------------
// Redirect Warning Dialog
@@ -144,6 +162,7 @@ export class RedirectWarningDialog extends Component {
}
RedirectWarningDialog.template = "web.RedirectWarningDialog";
RedirectWarningDialog.components = { Dialog };
+RedirectWarningDialog.props = { ...standardErrorDialogProps };
// -----------------------------------------------------------------------------
// Error 504 Dialog
@@ -152,6 +171,7 @@ export class Error504Dialog extends Component {}
Error504Dialog.template = "web.Error504Dialog";
Error504Dialog.components = { Dialog };
Error504Dialog.title = _lt("Request timeout");
+Error504Dialog.props = { ...standardErrorDialogProps };
// -----------------------------------------------------------------------------
// Expired Session Error Dialog
@@ -164,6 +184,7 @@ export class SessionExpiredDialog extends Component {
SessionExpiredDialog.template = "web.SessionExpiredDialog";
SessionExpiredDialog.components = { Dialog };
SessionExpiredDialog.title = _lt("Odoo Session Expired");
+SessionExpiredDialog.props = { ...standardErrorDialogProps };
registry
.category("error_dialogs")
diff --git a/addons/web/static/src/core/errors/error_handlers.js b/addons/web/static/src/core/errors/error_handlers.js
index 3a35daec50a..1c32d6f3608 100644
--- a/addons/web/static/src/core/errors/error_handlers.js
+++ b/addons/web/static/src/core/errors/error_handlers.js
@@ -117,6 +117,7 @@ export function rpcErrorHandler(env, error, originalError) {
return true;
}
}
+
errorHandlerRegistry.add("rpcErrorHandler", rpcErrorHandler, { sequence: 97 });
// -----------------------------------------------------------------------------
diff --git a/addons/web/static/src/core/main_components_container.js b/addons/web/static/src/core/main_components_container.js
index a4bb7908be3..25478539eaa 100644
--- a/addons/web/static/src/core/main_components_container.js
+++ b/addons/web/static/src/core/main_components_container.js
@@ -40,3 +40,4 @@ MainComponentsContainer.template = xml`
`;
MainComponentsContainer.components = { ErrorHandler };
+MainComponentsContainer.props = {};
diff --git a/addons/web/static/src/core/notifications/notification_container.js b/addons/web/static/src/core/notifications/notification_container.js
index 0eb9617186f..cd67b4ff540 100644
--- a/addons/web/static/src/core/notifications/notification_container.js
+++ b/addons/web/static/src/core/notifications/notification_container.js
@@ -10,6 +10,9 @@ export class NotificationContainer extends Component {
this.notifications = useState(this.props.notifications);
}
}
+NotificationContainer.props = {
+ notifications: Object,
+};
NotificationContainer.template = xml`
diff --git a/addons/web/static/src/core/popover/popover_container.js b/addons/web/static/src/core/popover/popover_container.js
index c5e04ce4dd2..c87fd2bbfa9 100644
--- a/addons/web/static/src/core/popover/popover_container.js
+++ b/addons/web/static/src/core/popover/popover_container.js
@@ -2,7 +2,7 @@
import { Popover } from "./popover";
-const { Component, onMounted, onWillUnmount, useExternalListener, useState, xml } = owl;
+const { EventBus, Component, onMounted, onWillUnmount, useExternalListener, useState, xml } = owl;
class PopoverController extends Component {
setup() {
@@ -44,8 +44,10 @@ class PopoverController extends Component {
}
}
onClickAway(ev) {
- if (this.target.contains(ev.target)
- || ev.target.closest(`.o_popover[popover-id="${this.props.id}"]`)) {
+ if (
+ this.target.contains(ev.target) ||
+ ev.target.closest(`.o_popover[popover-id="${this.props.id}"]`)
+ ) {
return;
}
if (this.props.preventClose && this.props.preventClose(ev)) {
@@ -80,6 +82,10 @@ export class PopoverContainer extends Component {
}
}
PopoverContainer.components = { PopoverController };
+PopoverContainer.props = {
+ popovers: Object,
+ bus: EventBus,
+};
PopoverContainer.template = xml`
diff --git a/addons/web/static/src/core/ui/block_ui.js b/addons/web/static/src/core/ui/block_ui.js
index 8cd95abf8ba..8ed0cabd432 100644
--- a/addons/web/static/src/core/ui/block_ui.js
+++ b/addons/web/static/src/core/ui/block_ui.js
@@ -2,7 +2,7 @@
import { browser } from "@web/core/browser/browser";
-const { Component, useState, xml } = owl;
+const { EventBus, Component, useState, xml } = owl;
export class BlockUI extends Component {
setup() {
@@ -69,6 +69,9 @@ export class BlockUI extends Component {
this.state.line2 = "";
}
}
+BlockUI.props = {
+ bus: EventBus,
+};
BlockUI.template = xml`
diff --git a/addons/web/static/src/core/utils/components.js b/addons/web/static/src/core/utils/components.js
index e0dcd5e19e5..e15cae3389c 100644
--- a/addons/web/static/src/core/utils/components.js
+++ b/addons/web/static/src/core/utils/components.js
@@ -10,7 +10,7 @@ export class ErrorHandler extends Component {
}
}
ErrorHandler.template = xml`
`;
-ErrorEvent.props = ["onError"];
+ErrorHandler.props = ["onError", "slots"];
export class WithEnv extends Component {
setup() {
@@ -18,3 +18,4 @@ export class WithEnv extends Component {
}
}
WithEnv.template = xml`
`;
+WithEnv.props = ["env", "slots"];
diff --git a/addons/web/static/src/legacy/legacy_component.js b/addons/web/static/src/legacy/legacy_component.js
index f16d9d693d0..b88e5b338a4 100644
--- a/addons/web/static/src/legacy/legacy_component.js
+++ b/addons/web/static/src/legacy/legacy_component.js
@@ -90,3 +90,6 @@ export class LegacyComponent extends owl.Component {
}
}
}
+LegacyComponent.props = {
+ "*": true,
+};
diff --git a/addons/web/static/src/search/control_panel/control_panel.js b/addons/web/static/src/search/control_panel/control_panel.js
index 2f8c47d5c3f..e07aa7f67ea 100644
--- a/addons/web/static/src/search/control_panel/control_panel.js
+++ b/addons/web/static/src/search/control_panel/control_panel.js
@@ -208,3 +208,7 @@ ControlPanel.components = {
Dropdown,
};
ControlPanel.template = "web.ControlPanel";
+ControlPanel.props = {
+ display: { type: Object, optional: true },
+ slots: { type: Object, optional: true },
+};
diff --git a/addons/web/static/src/search/control_panel/control_panel.xml b/addons/web/static/src/search/control_panel/control_panel.xml
index ff8270e3edb..75c1fc0f003 100644
--- a/addons/web/static/src/search/control_panel/control_panel.xml
+++ b/addons/web/static/src/search/control_panel/control_panel.xml
@@ -119,7 +119,7 @@
/>
-
+
`;
+ActionContainer.props = {};
diff --git a/addons/web/static/src/webclient/actions/action_service.js b/addons/web/static/src/webclient/actions/action_service.js
index 9b1feb356d4..2a1be80d135 100644
--- a/addons/web/static/src/webclient/actions/action_service.js
+++ b/addons/web/static/src/webclient/actions/action_service.js
@@ -48,6 +48,12 @@ export async function clearUncommittedChanges(env) {
return !res.includes(false);
}
+export const standardActionServiceProps = {
+ action: Object, // prop added by _getActionInfo
+ actionId: { type: Number, optional: true }, // prop added by _getActionInfo
+ className: String, // prop added by the ActionContainer
+};
+
function parseActiveIds(ids) {
const activeIds = [];
if (typeof ids === "string") {
@@ -734,6 +740,9 @@ function makeActionManager(env) {
}
ControllerComponent.template = ControllerComponentTemplate;
ControllerComponent.Component = controller.Component;
+ ControllerComponent.props = {
+ "*": true,
+ };
let nextDialog = null;
if (action.target === "new") {
diff --git a/addons/web/static/src/webclient/burger_menu/burger_menu.js b/addons/web/static/src/webclient/burger_menu/burger_menu.js
index 1e2e15d83f6..f3d767537d1 100644
--- a/addons/web/static/src/webclient/burger_menu/burger_menu.js
+++ b/addons/web/static/src/webclient/burger_menu/burger_menu.js
@@ -85,6 +85,7 @@ BurgerMenu.components = {
MobileSwitchCompanyMenu,
Transition,
};
+BurgerMenu.props = {};
const systrayItem = {
Component: BurgerMenu,
diff --git a/addons/web/static/src/webclient/loading_indicator/loading_indicator.js b/addons/web/static/src/webclient/loading_indicator/loading_indicator.js
index 0a90f29c704..c9b5f4f7f1b 100644
--- a/addons/web/static/src/webclient/loading_indicator/loading_indicator.js
+++ b/addons/web/static/src/webclient/loading_indicator/loading_indicator.js
@@ -70,6 +70,7 @@ export class LoadingIndicator extends Component {
LoadingIndicator.template = "web.LoadingIndicator";
LoadingIndicator.components = { Transition };
+LoadingIndicator.props = {};
registry.category("main_components").add("LoadingIndicator", {
Component: LoadingIndicator,
diff --git a/addons/web/static/src/webclient/menus/menu_providers.js b/addons/web/static/src/webclient/menus/menu_providers.js
index 73c9a5b9526..85022ec9784 100644
--- a/addons/web/static/src/webclient/menus/menu_providers.js
+++ b/addons/web/static/src/webclient/menus/menu_providers.js
@@ -4,11 +4,17 @@ import { _lt } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { fuzzyLookup } from "@web/core/utils/search";
import { computeAppsAndMenuItems } from "@web/webclient/menus/menu_helpers";
+import { DefaultCommandItem } from "@web/core/commands/command_palette";
const { Component } = owl;
class AppIconCommand extends Component {}
AppIconCommand.template = "web.AppIconCommand";
+AppIconCommand.props = {
+ webIconData: { type: String, optional: true },
+ webIcon: { type: Object, optional: true },
+ ...DefaultCommandItem.props,
+};
const commandCategoryRegistry = registry.category("command_categories");
commandCategoryRegistry.add("apps", { namespace: "/" }, { sequence: 10 });
diff --git a/addons/web/static/src/webclient/navbar/navbar.js b/addons/web/static/src/webclient/navbar/navbar.js
index 00c806d40ef..3548bb2f267 100644
--- a/addons/web/static/src/webclient/navbar/navbar.js
+++ b/addons/web/static/src/webclient/navbar/navbar.js
@@ -202,3 +202,4 @@ export class NavBar extends Component {
}
NavBar.template = "web.NavBar";
NavBar.components = { Dropdown, DropdownItem, MenuDropdown, ErrorHandler };
+NavBar.props = {};
diff --git a/addons/web/static/src/webclient/settings_form_view/highlight_text/form_label_highlight_text.js b/addons/web/static/src/webclient/settings_form_view/highlight_text/form_label_highlight_text.js
index 6013b368c4d..48baf45be5e 100644
--- a/addons/web/static/src/webclient/settings_form_view/highlight_text/form_label_highlight_text.js
+++ b/addons/web/static/src/webclient/settings_form_view/highlight_text/form_label_highlight_text.js
@@ -25,3 +25,11 @@ export class FormLabelHighlightText extends FormLabel {
FormLabelHighlightText.template = "web.FormLabelHighlightText";
FormLabelHighlightText.components = { HighlightText };
+FormLabelHighlightText.props = {
+ fieldInfo: { type: Object, optional: true },
+ className: { type: String, optional: true },
+ record: { type: Object, optional: true },
+ fieldName: { type: String, optional: true },
+ string: { type: String },
+ id: { type: String },
+};
diff --git a/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js b/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js
index 713870ccf0a..de6963c6d5f 100644
--- a/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js
+++ b/addons/web/static/src/webclient/settings_form_view/settings_form_controller.js
@@ -40,7 +40,7 @@ export class SettingsFormController extends formView.Controller {
}
});
- this.initialApp = "module" in this.props.context && this.props.context.module;
+ this.initialApp = "module" in this.props.context ? this.props.context.module : "";
}
/**
diff --git a/addons/web/static/src/webclient/settings_form_view/settings_form_renderer.js b/addons/web/static/src/webclient/settings_form_view/settings_form_renderer.js
index 2511249d0a3..c84bdb702f5 100644
--- a/addons/web/static/src/webclient/settings_form_view/settings_form_renderer.js
+++ b/addons/web/static/src/webclient/settings_form_view/settings_form_renderer.js
@@ -59,3 +59,8 @@ SettingsFormRenderer.components = {
HighlightText,
FormLabel: FormLabelHighlightText,
};
+SettingsFormRenderer.props = {
+ ...FormRenderer.props,
+ initialApp: String,
+ slots: Object,
+};
diff --git a/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js b/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js
index aa508bb255a..4462a36058c 100644
--- a/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js
+++ b/addons/web/static/src/webclient/switch_company_menu/switch_company_menu.js
@@ -41,6 +41,7 @@ export class SwitchCompanyMenu extends Component {
SwitchCompanyMenu.template = "web.SwitchCompanyMenu";
SwitchCompanyMenu.components = { Dropdown, DropdownItem };
SwitchCompanyMenu.toggleDelay = 1000;
+SwitchCompanyMenu.props = {};
export const systrayItem = {
Component: SwitchCompanyMenu,
diff --git a/addons/web/static/src/webclient/user_menu/user_menu.js b/addons/web/static/src/webclient/user_menu/user_menu.js
index fb8a9cdc244..011fa8db9f3 100644
--- a/addons/web/static/src/webclient/user_menu/user_menu.js
+++ b/addons/web/static/src/webclient/user_menu/user_menu.js
@@ -33,6 +33,7 @@ export class UserMenu extends Component {
}
UserMenu.template = "web.UserMenu";
UserMenu.components = { Dropdown, DropdownItem, CheckBox };
+UserMenu.props = {};
export const systrayItem = {
Component: UserMenu,
diff --git a/addons/web/static/src/webclient/webclient.js b/addons/web/static/src/webclient/webclient.js
index 56c0a76faf7..646b68d14e6 100644
--- a/addons/web/static/src/webclient/webclient.js
+++ b/addons/web/static/src/webclient/webclient.js
@@ -114,3 +114,4 @@ WebClient.components = {
MainComponentsContainer,
};
WebClient.template = "web.WebClient";
+WebClient.props = {};
diff --git a/addons/web/static/tests/core/errors/error_service_tests.js b/addons/web/static/tests/core/errors/error_service_tests.js
index 012425719a6..f5e60883248 100644
--- a/addons/web/static/tests/core/errors/error_service_tests.js
+++ b/addons/web/static/tests/core/errors/error_service_tests.js
@@ -6,6 +6,7 @@ import {
ClientErrorDialog,
RPCErrorDialog,
NetworkErrorDialog,
+ standardErrorDialogProps,
} from "@web/core/errors/error_dialogs";
import { errorService } from "@web/core/errors/error_service";
import { ConnectionLostError, RPCError } from "@web/core/network/rpc_service";
@@ -98,6 +99,7 @@ QUnit.test(
class CustomDialog extends Component {}
CustomDialog.template = xml``;
CustomDialog.components = { RPCErrorDialog };
+ CustomDialog.props = { ...standardErrorDialogProps };
const error = new RPCError();
error.code = 701;
error.message = "Some strange error occured";
diff --git a/addons/web/static/tests/search/helpers.js b/addons/web/static/tests/search/helpers.js
index 01f4b6f5d19..5a9f7e1faf6 100644
--- a/addons/web/static/tests/search/helpers.js
+++ b/addons/web/static/tests/search/helpers.js
@@ -60,22 +60,24 @@ export async function makeWithSearch(params) {
class Parent extends Component {
setup() {
this.withSearchProps = props;
- this.componentProps = componentProps;
}
- getDisplay(display) {
- return Object.assign({}, display, componentProps.display);
+
+ getProps(search) {
+ const props = Object.assign({}, componentProps, {
+ context: search.context,
+ domain: search.domain,
+ groupBy: search.groupBy,
+ orderBy: search.orderBy,
+ comparison: search.comparison,
+ display: Object.assign({}, search.display, componentProps.display),
+ });
+ return filterPropsForComponent(params.Component, props);
}
}
+
Parent.template = xml`
-
+
`;
Parent.components = { Component: params.Component, WithSearch };
@@ -89,6 +91,40 @@ export async function makeWithSearch(params) {
return component;
}
+/** This function is aim to be used only in the tests.
+ * It will filter the props that are needed by the Component.
+ * This is to avoid errors of props validation. This occurs for example, on ControlPanel tests.
+ * In production, View use WithSearch for the Controllers, and the Layout send only the props that
+ * need to the ControlPanel.
+ *
+ * @param {Component} Component
+ * @param {Object} props
+ * @returns {Object} filtered props
+ */
+function filterPropsForComponent(Component, props) {
+ // This if, can be removed once all the Components have the props defined
+ if (Component.props) {
+ let componentKeys = null;
+ if (Component.props instanceof Array) {
+ componentKeys = Component.props.map((x) => x.replace("?", ""));
+ } else {
+ componentKeys = Object.keys(Component.props);
+ }
+ if (componentKeys.includes("*")) {
+ return props;
+ } else {
+ return Object.keys(props)
+ .filter((k) => componentKeys.includes(k))
+ .reduce((o, k) => {
+ o[k] = props[k];
+ return o;
+ }, {});
+ }
+ } else {
+ return props;
+ }
+}
+
function getUniqueChild(node) {
return Object.values(node.children)[0];
}
diff --git a/addons/web/static/tests/views/form/form_compiler_tests.js b/addons/web/static/tests/views/form/form_compiler_tests.js
index a469c3f3e07..1e116f06ac8 100644
--- a/addons/web/static/tests/views/form/form_compiler_tests.js
+++ b/addons/web/static/tests/views/form/form_compiler_tests.js
@@ -184,7 +184,7 @@ QUnit.module("Form Compiler", (hooks) => {
const expected = /*xml*/ `
`;
@@ -207,7 +207,7 @@ QUnit.module("Form Compiler", (hooks) => {
diff --git a/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js b/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js
index f7ef058d72e..da5d1ca8808 100644
--- a/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js
+++ b/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js
@@ -1,6 +1,6 @@
/** @odoo-module **/
-const { Component, xml, useState } = owl;
+const { EventBus, Component, xml, useState } = owl;
export class FullscreenIndication extends Component {
setup() {
@@ -21,6 +21,9 @@ export class FullscreenIndication extends Component {
}
}
}
+FullscreenIndication.props = {
+ bus: EventBus,
+};
FullscreenIndication.template = xml`
Press esc to exit full screen
diff --git a/addons/website/static/src/components/website_loader/website_loader.js b/addons/website/static/src/components/website_loader/website_loader.js
index 6af7b1fe6ff..2e9d6a04af0 100644
--- a/addons/website/static/src/components/website_loader/website_loader.js
+++ b/addons/website/static/src/components/website_loader/website_loader.js
@@ -1,6 +1,6 @@
/** @odoo-module **/
-const { Component, useState } = owl;
+const { EventBus, Component, useState } = owl;
export class WebsiteLoader extends Component {
setup() {
@@ -25,4 +25,7 @@ export class WebsiteLoader extends Component {
});
}
}
+WebsiteLoader.props = {
+ bus: EventBus,
+};
WebsiteLoader.template = 'website.website_loader';