diff --git a/addons/web/__manifest__.py b/addons/web/__manifest__.py
index c23f3ba1947..0ecd9765bf7 100644
--- a/addons/web/__manifest__.py
+++ b/addons/web/__manifest__.py
@@ -203,9 +203,6 @@ This module provides the core of the Odoo Web Client.
'web/static/src/env.js',
'web/static/src/core/utils/transitions.scss', # included early because used by other files
'web/static/src/core/**/*',
- # TODO: split debug files correctly when converting frontend debug
- # manager so we don't need action-service and stuff
- ('remove', 'web/static/src/core/debug/**/*'),
'web/static/src/public/error_notifications.js',
'web/static/src/legacy/scss/base_frontend.scss',
diff --git a/addons/web/static/src/core/debug/debug_context.js b/addons/web/static/src/core/debug/debug_context.js
index d1c102cc46c..a77ba98ac2a 100644
--- a/addons/web/static/src/core/debug/debug_context.js
+++ b/addons/web/static/src/core/debug/debug_context.js
@@ -61,8 +61,12 @@ class DebugContext {
}
const debugContextSymbol = Symbol("debugContext");
+export function createDebugContext(env, { categories = [] } = {}) {
+ return { [debugContextSymbol]: new DebugContext(env, categories) };
+}
+
export function useOwnDebugContext({ categories = [] } = {}) {
- useSubEnv({ [debugContextSymbol]: new DebugContext(useEnv(), categories) });
+ useSubEnv(createDebugContext(useEnv(), { categories }));
}
export function useCurrentDebugContext() {
diff --git a/addons/web/static/src/core/debug/debug_menu_items.js b/addons/web/static/src/core/debug/debug_menu_items.js
index c9d0ed93939..6ef2c887d35 100644
--- a/addons/web/static/src/core/debug/debug_menu_items.js
+++ b/addons/web/static/src/core/debug/debug_menu_items.js
@@ -4,85 +4,6 @@ import { browser } from "../browser/browser";
import { routeToUrl } from "../browser/router_service";
import { registry } from "../registry";
-// @legacy
-import dialogs from "web.view_dialogs";
-import { ComponentAdapter } from "web.OwlCompatibility";
-
-// Backend Debug Manager Items
-function runJSTestsItem({ env }) {
- const runTestsURL = browser.location.origin + "/web/tests?mod=*";
- return {
- type: "item",
- description: env._t("Run JS Tests"),
- href: runTestsURL,
- callback: () => {
- browser.open(runTestsURL);
- },
- sequence: 10,
- };
-}
-
-function runJSTestsMobileItem({ env }) {
- const runTestsMobileURL = browser.location.origin + "/web/tests/mobile?mod=*";
- return {
- type: "item",
- description: env._t("Run JS Mobile Tests"),
- href: runTestsMobileURL,
- callback: () => {
- browser.open(runTestsMobileURL);
- },
- sequence: 20,
- };
-}
-
-export function openViewItem({ env }) {
- async function onSelected(records) {
- const views = await env.services.orm.searchRead(
- "ir.ui.view",
- [["id", "=", records[0].id]],
- ["name", "model", "type"],
- { limit: 1 }
- );
- const view = views[0];
- view.type = view.type === "tree" ? "list" : view.type; // ignore tree view
- env.services.action.doAction({
- type: "ir.actions.act_window",
- name: view.name,
- res_model: view.model,
- views: [[view.id, view.type]],
- });
- }
-
- return {
- type: "item",
- description: env._t("Open View"),
- callback: () => {
- const adapterParent = new ComponentAdapter(null, { Component: owl.Component });
- const selectCreateDialog = new dialogs.SelectCreateDialog(adapterParent, {
- res_model: "ir.ui.view",
- title: env._t("Select a view"),
- disable_multiple_selection: true,
- domain: [
- ["type", "!=", "qweb"],
- ["type", "!=", "search"],
- ],
- on_selected: onSelected,
- });
-
- selectCreateDialog.open();
- },
- sequence: 40,
- };
-}
-
-// Global Debug Manager Items
-function globalSeparator() {
- return {
- type: "separator",
- sequence: 400,
- };
-}
-
function activateAssetsDebugging({ env }) {
return {
type: "item",
@@ -155,12 +76,6 @@ function leaveDebugMode({ env }) {
registry
.category("debug")
.category("default")
- // Backend
- .add("runJSTestsItem", runJSTestsItem)
- .add("runJSTestsMobileItem", runJSTestsMobileItem)
- .add("openViewItem", openViewItem)
- // Global
- .add("globalSeparator", globalSeparator)
.add("activateAssetsDebugging", activateAssetsDebugging)
.add("regenerateAssets", regenerateAssets)
.add("becomeSuperuser", becomeSuperuser)
diff --git a/addons/web/static/src/core/debug/profiling/profiling_item.js b/addons/web/static/src/core/debug/profiling/profiling_item.js
index 949bde29eea..b56f85d9c45 100644
--- a/addons/web/static/src/core/debug/profiling/profiling_item.js
+++ b/addons/web/static/src/core/debug/profiling/profiling_item.js
@@ -8,7 +8,6 @@ const { Component } = owl;
export class ProfilingItem extends Component {
setup() {
this.profiling = useService("profiling");
- this.actionService = useService("action");
useBus(this.props.bus, "UPDATE", this.render);
}
@@ -16,7 +15,13 @@ export class ProfilingItem extends Component {
this.profiling.setParam(param, ev.target.value);
}
openProfiles() {
- this.actionService.doAction("base.action_menu_ir_profile");
+ if (this.env.services.action) {
+ // using doAction in the backend to preserve breadcrumbs and stuff
+ this.env.services.action.doAction("base.action_menu_ir_profile");
+ } else {
+ // No action service means we are in the frontend.
+ window.location = "/web/#action=base.action_menu_ir_profile";
+ }
}
}
ProfilingItem.components = { DropdownItem };
diff --git a/addons/web/static/src/core/errors/error_handlers.js b/addons/web/static/src/core/errors/error_handlers.js
index b761d8eff74..f0d63de995c 100644
--- a/addons/web/static/src/core/errors/error_handlers.js
+++ b/addons/web/static/src/core/errors/error_handlers.js
@@ -18,6 +18,7 @@ import { UncaughtClientError, UncaughtCorsError, UncaughtPromiseError } from "./
const errorHandlerRegistry = registry.category("error_handlers");
const errorDialogRegistry = registry.category("error_dialogs");
+const errorNotificationRegistry = registry.category("error_notifications");
// -----------------------------------------------------------------------------
// CORS errors
@@ -71,7 +72,7 @@ errorHandlerRegistry.add("clientErrorHandler", clientErrorHandler, { sequence: 9
* @param {Error} originalError
* @returns {boolean}
*/
-function rpcErrorHandler(env, error, originalError) {
+export function rpcErrorHandler(env, error, originalError) {
if (!(error instanceof UncaughtPromiseError)) {
return false;
}
@@ -85,9 +86,16 @@ function rpcErrorHandler(env, error, originalError) {
// error is here a RPCError
error.unhandledRejectionEvent.preventDefault();
const exceptionName = originalError.exceptionName;
- let ErrorComponent = null;
- if (exceptionName && errorDialogRegistry.contains(exceptionName)) {
- ErrorComponent = errorDialogRegistry.get(exceptionName);
+ let ErrorComponent = originalError.Component;
+ if (!ErrorComponent && exceptionName) {
+ if (errorNotificationRegistry.contains(exceptionName)) {
+ const notif = errorNotificationRegistry.get(exceptionName);
+ env.services.notification.add(notif.message || originalError.data.message, notif);
+ return true;
+ }
+ if (errorDialogRegistry.contains(exceptionName)) {
+ ErrorComponent = errorDialogRegistry.get(exceptionName);
+ }
}
env.services.dialog.add(ErrorComponent || RPCErrorDialog, {
diff --git a/addons/web/static/src/legacy/frontend/debug_manager/debug.xml b/addons/web/static/src/legacy/frontend/debug_manager/debug.xml
deleted file mode 100644
index 4e50a483608..00000000000
--- a/addons/web/static/src/legacy/frontend/debug_manager/debug.xml
+++ /dev/null
@@ -1,69 +0,0 @@
-
-
-
-
-
- Open Developer Tools
-
-
-
-
-
-
-
-
-
- Activate Assets Debugging
- Activate Tests Assets Debugging
- Regenerate Assets Bundles
- Become Superuser
- Leave the Developer Tools
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/addons/web/static/src/legacy/frontend/debug_manager/debug_manager.js b/addons/web/static/src/legacy/frontend/debug_manager/debug_manager.js
deleted file mode 100644
index 505e227a6eb..00000000000
--- a/addons/web/static/src/legacy/frontend/debug_manager/debug_manager.js
+++ /dev/null
@@ -1,194 +0,0 @@
-odoo.define('web.DebugManager', function (require) {
-"use strict";
-
-var core = require('web.core');
-var session = require('web.session');
-var utils = require('web.utils');
-var Widget = require('web.Widget');
-const { session: sessionInfo } = require('@web/session');
-
-var QWeb = core.qweb;
-
-/**
- * DebugManager base + general features (applicable to any context)
- */
-var DebugManager = Widget.extend({
- template: "WebClient.DebugManager",
- xmlDependencies: ['/web/static/src/legacy/frontend/debug_manager/debug.xml'],
- events: {
- "click a[data-action]": "perform_callback",
- "click .profiling": "handle_profiling",
- "change .profiling_param": "handle_profiling",
- },
- init: function () {
- this._super.apply(this, arguments);
- this._events = null;
- var debug = odoo.debug;
- this.debug_mode = debug;
- this.debug_mode_help = debug && debug !== '1' ? ' (' + debug + ')' : '';
- this.profile_session = sessionInfo.profile_session || false;
- this.profile_collectors = sessionInfo.profile_collectors;
- if (! Array.isArray(this.profile_collectors)) {
- this.profile_collectors = ['sql', 'traces_async']; // use default value when not defined in session.
- }
- this.profile_params = sessionInfo.profile_params || {};
- },
- start: function () {
- core.bus.on('rpc:result', this, function (req, resp) {
- this._debug_events(resp.debug);
- });
-
- this.$dropdown = this.$(".o_debug_dropdown");
- // whether the current user is an administrator
- this._is_admin = session.is_system;
- return Promise.resolve(
- this._super()
- ).then(function () {
- return this.update();
- }.bind(this));
- },
- /**
- * Calls the appropriate callback when clicking on a Debug option
- */
- perform_callback: function (evt) {
- evt.preventDefault();
- var params = $(evt.target).data();
- var callback = params.action;
-
- if (callback && this[callback]) {
- // Perform the callback corresponding to the option
- this[callback](params, evt);
- } else {
- console.warn("No handler for ", callback);
- }
- },
- /**
- * Manage profiling actions.
- * open_profiling_button should not prevent dropdown from closing
- * other actions should keep dropdown open and interact with backend to enable or disable profiling features.
- * The main switch, 'enable_profiling' is a special case since it will create or remove a profile session
- */
- handle_profiling: async function (evt) {
- const $target = $(evt.target);
- const target = $target[0];
- if (target.id === 'open_profiling_button') {
- this.do_action('base.action_menu_ir_profile');
- return;
- }
- evt.stopPropagation(); // prevent dropdown from closing
- const kwargs = {
- params: {}
- };
- if (target.nodeName == "LABEL") {
- return
- }
- kwargs.profile = $('#enable_profiling')[0].checked;
- kwargs.collectors = $('input.profile_switch').toArray().filter(i => i.checked).map(i => i.id.replace(/^profile_/, ''));
- $('.profile_param').toArray().forEach(i => kwargs.params[i.id.replace(/^profile_/, '')] = i.value);
-
- try {
- const resp = await this._rpc({
- model: 'ir.profile',
- method: 'set_profiling',
- kwargs: kwargs,
- });
- this.profile_session = resp.session;
- this.profile_collectors = resp.collectors;
- this.profile_params = resp.params;
- } catch (e) {
- this.profite_session = false;
- }
- this.update_profiling_state();
- },
- /**
- * Update the profiling dropdown menu state after any change to synchronyze server session and client
- * This is mainly usefull to avoid desync in case of multiple tabs
- */
- update_profiling_state: function () {
- const self = this;
- this.$('#enable_profiling')[0].checked = Boolean(this.profile_session);
- this.$('.profile_switch').each(function () {
- this.checked = (self.profile_collectors.indexOf(this.id.replace(/^profile_/, '')) !== -1);
- const params = self.$('.' + this.id);
- params.toggleClass('d-none', !this.checked);
- params.each(function () {
- const params_input = $(this).find('.profile_param')[0];
- params_input.value = self.profile_params[params_input.id.replace(/^profile_/, '')] || '';
- });
- });
- this.$profiling_items.toggleClass('d-none', !this.profile_session);
- },
- _debug_events: function (events) {
- if (!this._events) {
- return;
- }
- if (events && events.length) {
- this._events.push(events);
- }
- this.trigger('update-stats', this._events);
- },
-
- /**
- * Update the debug manager: reinserts all "universal" controls
- */
- update: function () {
- this.$dropdown
- .empty()
- .append(QWeb.render('WebClient.DebugManager.Global', {
- manager: this,
- }));
- this.$profiling_items = this.$(".profiling_items");
-
- this.update_profiling_state();
- return Promise.resolve();
- },
- split_assets: function () {
- window.location = $.param.querystring(window.location.href, 'debug=assets');
- },
- tests_assets: function () {
- // Enable also 'assets' to see non minimized assets
- window.location = $.param.querystring(window.location.href, 'debug=assets,tests');
- },
- /**
- * Delete assets bundles to force their regeneration
- *
- * @returns {void}
- */
- regenerateAssets: function () {
- var self = this;
- var domain = utils.assetsDomain();
- this._rpc({
- model: 'ir.attachment',
- method: 'search',
- args: [domain],
- }).then(function (ids) {
- self._rpc({
- model: 'ir.attachment',
- method: 'unlink',
- args: [ids],
- }).then(window.location.reload());
- });
- },
- leave_debug_mode: function () {
- var qs = $.deparam.querystring();
- qs.debug = '';
- window.location.search = '?' + $.param(qs);
- },
- /**
- * @private
- * @param {string} model
- * @param {string} operation
- * @returns {Promise}
- */
- _checkAccessRight(model, operation) {
- return this._rpc({
- model: model,
- method: 'check_access_rights',
- kwargs: {operation, raise_exception: false},
- })
- },
-});
-
-return DebugManager;
-
-});
diff --git a/addons/web/static/src/legacy/frontend/debug_manager/debug_manager.scss b/addons/web/static/src/legacy/frontend/debug_manager/debug_manager.scss
deleted file mode 100644
index 6b7246e9729..00000000000
--- a/addons/web/static/src/legacy/frontend/debug_manager/debug_manager.scss
+++ /dev/null
@@ -1,13 +0,0 @@
-.o_debug_mode .fa { /* Active profiling red dot should be overed on the bottom right corner of the bug icon*/
- position: relative;
- .fa {
- position: absolute;
- bottom: -0.1em;
- right: -0.4em;
- font-size: 0.8em;
- }
-}
-
-.open_profiling { /* Fix dropdown-item padding missing because of float: right*/
- padding: 3px;
-}
diff --git a/addons/web/static/src/legacy/legacy_rpc_error_handler.js b/addons/web/static/src/legacy/legacy_rpc_error_handler.js
index 178d1ccc2e9..5073306116e 100644
--- a/addons/web/static/src/legacy/legacy_rpc_error_handler.js
+++ b/addons/web/static/src/legacy/legacy_rpc_error_handler.js
@@ -1,12 +1,9 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
-import { RPCErrorDialog } from "../core/errors/error_dialogs";
import { ConnectionLostError, RPCError } from "../core/network/rpc_service";
-import { lostConnectionHandler } from "@web/core/errors/error_handlers";
+import { lostConnectionHandler, rpcErrorHandler } from "@web/core/errors/error_handlers";
-const errorNotificationRegistry = registry.category("error_notifications");
-const errorDialogRegistry = registry.category("error_dialogs");
const errorHandlerRegistry = registry.category("error_handlers");
/**
@@ -32,41 +29,18 @@ function legacyRPCErrorHandler(env, error, originalError) {
(originalError.message instanceof RPCError ||
originalError.message instanceof ConnectionLostError)
) {
- if (originalError.message instanceof ConnectionLostError) {
- return lostConnectionHandler(env, error, originalError.message);
- }
const event = originalError.event;
originalError = originalError.message;
- error.unhandledRejectionEvent.preventDefault();
if (event.isDefaultPrevented()) {
// in theory, here, event was already handled
+ error.unhandledRejectionEvent.preventDefault();
return true;
}
event.preventDefault();
- const exceptionName = originalError.exceptionName;
- let ErrorComponent = originalError.Component;
- if (!ErrorComponent && exceptionName) {
- if (errorNotificationRegistry.contains(exceptionName)) {
- const notif = errorNotificationRegistry.get(exceptionName);
- env.services.notification.add(notif.message || originalError.data.message, notif);
- return true;
- }
- if (errorDialogRegistry.contains(exceptionName)) {
- ErrorComponent = errorDialogRegistry.get(exceptionName);
- }
+ if (originalError instanceof ConnectionLostError) {
+ return lostConnectionHandler(env, error, originalError);
}
-
- env.services.dialog.add(ErrorComponent || RPCErrorDialog, {
- traceback: originalError.traceback || originalError.stack,
- message: originalError.message,
- name: originalError.name,
- exceptionName: originalError.exceptionName,
- data: originalError.data,
- subType: originalError.subType,
- code: originalError.code,
- type: originalError.type,
- });
- return true;
+ return rpcErrorHandler(env, error, originalError);
}
return false;
}
diff --git a/addons/web/static/src/webclient/debug_items.js b/addons/web/static/src/webclient/debug_items.js
new file mode 100644
index 00000000000..fee3f3375bf
--- /dev/null
+++ b/addons/web/static/src/webclient/debug_items.js
@@ -0,0 +1,88 @@
+/** @odoo-module */
+import { registry } from "@web/core/registry";
+import { browser } from "@web/core/browser/browser";
+
+import dialogs from "web.view_dialogs";
+import { ComponentAdapter } from "web.OwlCompatibility";
+
+function runJSTestsItem({ env }) {
+ const runTestsURL = browser.location.origin + "/web/tests?mod=*";
+ return {
+ type: "item",
+ description: env._t("Run JS Tests"),
+ href: runTestsURL,
+ callback: () => {
+ browser.open(runTestsURL);
+ },
+ sequence: 10,
+ };
+}
+
+function runJSTestsMobileItem({ env }) {
+ const runTestsMobileURL = browser.location.origin + "/web/tests/mobile?mod=*";
+ return {
+ type: "item",
+ description: env._t("Run JS Mobile Tests"),
+ href: runTestsMobileURL,
+ callback: () => {
+ browser.open(runTestsMobileURL);
+ },
+ sequence: 20,
+ };
+}
+
+export function openViewItem({ env }) {
+ async function onSelected(records) {
+ const views = await env.services.orm.searchRead(
+ "ir.ui.view",
+ [["id", "=", records[0].id]],
+ ["name", "model", "type"],
+ { limit: 1 }
+ );
+ const view = views[0];
+ view.type = view.type === "tree" ? "list" : view.type; // ignore tree view
+ env.services.action.doAction({
+ type: "ir.actions.act_window",
+ name: view.name,
+ res_model: view.model,
+ views: [[view.id, view.type]],
+ });
+ }
+
+ return {
+ type: "item",
+ description: env._t("Open View"),
+ callback: () => {
+ const adapterParent = new ComponentAdapter(null, { Component: owl.Component });
+ const selectCreateDialog = new dialogs.SelectCreateDialog(adapterParent, {
+ res_model: "ir.ui.view",
+ title: env._t("Select a view"),
+ disable_multiple_selection: true,
+ domain: [
+ ["type", "!=", "qweb"],
+ ["type", "!=", "search"],
+ ],
+ on_selected: onSelected,
+ });
+
+ selectCreateDialog.open();
+ },
+ sequence: 40,
+ };
+}
+
+// This separates the items defined above from global items that aren't webclient-only
+function globalSeparator() {
+ return {
+ type: "separator",
+ sequence: 400,
+ };
+}
+
+registry
+ .category("debug")
+ .category("default")
+ .add("runJSTestsItem", runJSTestsItem)
+ .add("runJSTestsMobileItem", runJSTestsMobileItem)
+ .add("globalSeparator", globalSeparator)
+ .add("openViewItem", openViewItem);
diff --git a/addons/web/static/tests/core/debug/debug_manager_tests.js b/addons/web/static/tests/core/debug/debug_manager_tests.js
index 8b90fac071f..d16712a3be8 100644
--- a/addons/web/static/tests/core/debug/debug_manager_tests.js
+++ b/addons/web/static/tests/core/debug/debug_manager_tests.js
@@ -14,7 +14,7 @@ import { makeTestEnv, prepareRegistriesWithCleanup } from "../../helpers/mock_en
import { makeFakeDialogService, makeFakeLocalizationService } from "../../helpers/mock_services";
import { click, getFixture, legacyExtraNextTick, patchWithCleanup } from "../../helpers/utils";
import { createWebClient, doAction, getActionManagerServerData } from "../../webclient/helpers";
-import { openViewItem } from "@web/core/debug/debug_menu_items";
+import { openViewItem } from "@web/webclient/debug_items";
import { editView, editSearchView } from "@web/legacy/debug_manager";
const { Component, mount, tags } = owl;
diff --git a/addons/web/static/tests/legacy/tools/debug_manager_tests.js b/addons/web/static/tests/legacy/tools/debug_manager_tests.js
deleted file mode 100644
index 1ba0da78c67..00000000000
--- a/addons/web/static/tests/legacy/tools/debug_manager_tests.js
+++ /dev/null
@@ -1,175 +0,0 @@
-odoo.define('web.debugManagerTests', function (require) {
-"use strict";
-
-var testUtils = require('web.test_utils');
-var FormView = require('web.FormView');
-
-var createDebugManager = testUtils.createDebugManager;
-
-QUnit.module('DebugManager', {}, function () {
-
- QUnit.skip("list: edit view menu item", async function (assert) {
- assert.expect(3);
-
- var debugManager = await createDebugManager();
-
- await debugManager.appendTo($('#qunit-fixture'));
-
- // Simulate update debug manager from web client
- var action = {
- views: [{
- displayName: "List",
- fieldsView: {
- view_id: 1,
- },
- type: "list",
- }],
- };
- var view = {
- viewType: "list",
- };
- await testUtils.nextTick();
- await debugManager.update('action', action, view);
-
- var $editView = debugManager.$('a[data-action=edit][data-model="ir.ui.view"]');
- assert.strictEqual($editView.length, 1, "should have edit view menu item");
- assert.strictEqual($editView.text().trim(), "Edit View: List",
- "should have correct menu item text for editing view");
- assert.strictEqual($editView.data('id'), 1, "should have correct view_id");
-
- debugManager.destroy();
- });
-
- QUnit.skip("form: Manage Attachments option", async function (assert) {
- assert.expect(3);
-
- var debugManager = await createDebugManager({
- intercepts: {
- do_action: function (event) {
- assert.deepEqual(event.data.action, {
- context: {
- default_res_model: "test.model",
- default_res_id: 5,
- },
- domain: [["res_model", "=", "test.model"],["res_id", "=", 5]],
- name: "Manage Attachments",
- res_model: "ir.attachment",
- type: "ir.actions.act_window",
- views: [[false, "list"],[false, "form"]],
- });
- },
- },
- });
- await debugManager.appendTo($('#qunit-fixture'));
-
- // Simulate update debug manager from web client
- var action = {
- views: [{
- displayName: "Form",
- fieldsView: {
- view_id: 2,
- },
- type: "form",
- }],
- res_model: "test.model",
- };
- var view = {
- viewType: "form",
- getSelectedIds: function () {
- return [5];
- },
- };
- await debugManager.update('action', action, view);
-
- var $attachmentMenu = debugManager.$('a[data-action=get_attachments]');
- assert.strictEqual($attachmentMenu.length, 1, "should have Manage Attachments menu item");
- assert.strictEqual($attachmentMenu.text().trim(), "Manage Attachments",
- "should have correct menu item text");
- await testUtils.dom.click(debugManager.$('> a')); // open dropdown
- await testUtils.dom.click($attachmentMenu);
-
- debugManager.destroy();
- });
-
- QUnit.skip("Debug: Set defaults with right model", async function (assert) {
- assert.expect(2);
-
- /* Click on debug > set default,
- * set some defaults, click on save
- * model and some other data should be sent to server
- */
-
- // We'll need a full blown architecture with some data
- var data = {
- partner: {
- fields: {
- foo: {string: "Foo", type: "char", default: "My little Foo Value"},
- },
- records: [{
- id: 1,
- foo: "yop",
- }]
- },
- 'ir.default': { // We just need this to be defined
- fields: {},
- },
- };
-
- var form = await testUtils.createView({
- View: FormView,
- model: 'partner',
- data: data,
- arch: '',
- res_id: 1,
- });
-
- // Now the real tested component
- var debugManager = await createDebugManager({
- data: data,
- mockRPC: function (route, args) {
- if (route == "/web/dataset/call_kw/ir.default/set") {
- assert.deepEqual(args.args, ["partner", "foo", "yop", true, true, false],
- 'Model, field, value and booleans for current user/company should have been passed');
- return Promise.resolve();
- }
- return this._super.apply(this, arguments);
- }
- });
-
- await debugManager.appendTo($('#qunit-fixture'));
-
- // Simulate update debug manager from web client
- var action = {
- controlPanelFieldsView: {},
- views: [{
- fieldsView: {
- view_id: 1,
- model: 'partner',
- type: 'form',
- },
- type: "form",
- }],
- res_model: 'partner',
- };
-
- // We are all set
- await debugManager.update('action', action, form);
-
- // click on set_defaults dropdown
- await testUtils.dom.click(debugManager.$('> a')); // open dropdown
- await testUtils.dom.click(debugManager.$('a[data-action="set_defaults"]'));
- var $modal = $('.modal-content');
- assert.strictEqual($modal.length, 1, 'One modal present');
-
- $modal.find('select[id=formview_default_fields] option[value=foo]').prop('selected', true);
-
- // Save
- await testUtils.dom.click($modal.find('.modal-footer button').eq(1));
-
- form.destroy();
- debugManager.destroy();
- });
-});
-});
diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py
index 0a4f27cd9a9..789e297edc5 100644
--- a/addons/website/__manifest__.py
+++ b/addons/website/__manifest__.py
@@ -205,7 +205,7 @@
'website/static/src/js/form_editor_registry.js',
'website/static/src/js/menu/content.js',
'website/static/src/js/menu/customize.js',
- 'website/static/src/js/menu/debug_manager.js',
+ 'website/static/src/js/menu/debug_menu.js',
'website/static/src/js/menu/edit.js',
'website/static/src/js/menu/mobile_view.js',
'website/static/src/js/menu/new_content.js',
diff --git a/addons/website/static/src/js/menu/debug_manager.js b/addons/website/static/src/js/menu/debug_manager.js
deleted file mode 100644
index e932daa7edd..00000000000
--- a/addons/website/static/src/js/menu/debug_manager.js
+++ /dev/null
@@ -1,21 +0,0 @@
-odoo.define('website.debugManager', function (require) {
-'use strict';
-
-var config = require('web.config');
-var DebugManager = require('web.DebugManager');
-var websiteNavbarData = require('website.navbar');
-
-var DebugManagerMenu = websiteNavbarData.WebsiteNavbar.include({
- /**
- * @override
- */
- start: function () {
- if (config.isDebug()) {
- new DebugManager(this).prependTo(this.$('.o_menu_systray'));
- }
- return this._super.apply(this, arguments);
- },
-});
-
-return DebugManagerMenu;
-});
diff --git a/addons/website/static/src/js/menu/debug_menu.js b/addons/website/static/src/js/menu/debug_menu.js
new file mode 100644
index 00000000000..6c04cb9e33d
--- /dev/null
+++ b/addons/website/static/src/js/menu/debug_menu.js
@@ -0,0 +1,20 @@
+/** @odoo-module */
+import { registry } from "@web/core/registry";
+import { DebugMenu } from "@web/core/debug/debug_menu";
+import { createDebugContext } from "@web/core/debug/debug_context";
+
+const debugMenuService = {
+ dependencies: ["orm"],
+ start(env) {
+ Object.assign(env, createDebugContext(env, { categories: ["default"] }));
+ const systray = document.querySelector('.o_menu_systray');
+ if (systray) {
+ owl.mount(DebugMenu, {
+ target: systray,
+ position: 'first-child',
+ env,
+ });
+ }
+ }
+}
+registry.category("services").add("website_debug_menu", debugMenuService);