summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRomain Derie <rde@odoo.com>2019-06-03 14:26:17 +0000
committerJeremy Kersten <jke@odoo.com>2019-06-05 05:56:33 +0000
commit73327db0656bfdd2bce2a69ca1c5c07ad3d3b763 (patch)
tree937ca416396bfdc4b38fc7443c8df9af94efce19
parentfbe5b64eb3d962e1c828e77d848f85a8edfcdde8 (diff)
[IMP] *: add debug manager in frontend
Now that the debug mode is stored in session, we need a clear indication that debug mode is activated. In backend, the 'fa-bug' is doing the trick but in frontend there is no visible clue that debug mode is enabled. This commit separate the debug manager code/feature so we can instanciate it in frontend only with usefull options (such as enable assets, leave debug mode..). Now, in frontend, people having access to the navbar (o_main_navbar) will see the same 'fa-bug' icon with minimal options as mentioned above. Also, in the footer, there will be another 'fa-bug' icon without any options. It will be usefull when the navbar is not shown, typically the case for public user, or for portal (without website installed)). Clicking on it will simply leave debug mode as hinted in tooltip. task-1934445 Comes with https://github.com/odoo/enterprise/pull/4281 Closes #33213
-rw-r--r--addons/mail/static/src/js/tools/debug_manager.js4
-rw-r--r--addons/mass_mailing/views/unsubscribe_templates.xml1
-rw-r--r--addons/web/static/src/js/tools/debug_manager.js116
-rw-r--r--addons/web/static/src/js/tools/debug_manager_backend.js168
-rw-r--r--addons/web/static/src/xml/base.xml104
-rw-r--r--addons/web/static/src/xml/debug.xml112
-rw-r--r--addons/web/static/tests/helpers/test_utils_create.js2
-rw-r--r--addons/web/views/webclient_templates.xml15
-rw-r--r--addons/web_tour/static/src/js/debug_manager.js4
-rw-r--r--addons/web_tour/static/src/xml/debug_manager.xml2
-rw-r--r--addons/website/static/src/js/menu/debug_manager.js20
-rw-r--r--addons/website/views/website_templates.xml1
12 files changed, 281 insertions, 268 deletions
diff --git a/addons/mail/static/src/js/tools/debug_manager.js b/addons/mail/static/src/js/tools/debug_manager.js
index 452a062806f..3a4c1d3c372 100644
--- a/addons/mail/static/src/js/tools/debug_manager.js
+++ b/addons/mail/static/src/js/tools/debug_manager.js
@@ -1,8 +1,8 @@
-odoo.define('mail.DebugManager', function (require) {
+odoo.define('mail.DebugManager.Backend', function (require) {
"use strict";
var core = require('web.core');
-var DebugManager = require('web.DebugManager');
+var DebugManager = require('web.DebugManager.Backend');
var _t = core._t;
/**
diff --git a/addons/mass_mailing/views/unsubscribe_templates.xml b/addons/mass_mailing/views/unsubscribe_templates.xml
index bf7b4b54e84..793bb61034d 100644
--- a/addons/mass_mailing/views/unsubscribe_templates.xml
+++ b/addons/mass_mailing/views/unsubscribe_templates.xml
@@ -136,6 +136,7 @@
<a target="_blank" class="label label-danger" href="https://www.odoo.com/page/website-builder">Odoo</a>
</div>
<div class="pull-left text-muted" itemscope="itemscope" itemtype="https://schema.org/Organization">
+ <t t-call="web.debug_icon"/>
Copyright &amp;copy; <span t-field="res_company.name" itemprop="name">Company name</span>
</div>
</div>
diff --git a/addons/web/static/src/js/tools/debug_manager.js b/addons/web/static/src/js/tools/debug_manager.js
new file mode 100644
index 00000000000..db14dec2e36
--- /dev/null
+++ b/addons/web/static/src/js/tools/debug_manager.js
@@ -0,0 +1,116 @@
+odoo.define('web.DebugManager', function (require) {
+"use strict";
+
+var core = require('web.core');
+var session = require('web.session');
+var Widget = require('web.Widget');
+
+var QWeb = core.qweb;
+
+/**
+ * DebugManager base + general features (applicable to any context)
+ */
+var DebugManager = Widget.extend({
+ template: "WebClient.DebugManager",
+ xmlDependencies: ['/web/static/src/xml/debug.xml'],
+ events: {
+ "click a[data-action]": "perform_callback",
+ },
+ 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 + ')' : '';
+ },
+ 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);
+ }
+ },
+
+ _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,
+ }));
+ 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 = [
+ ['res_model', '=', 'ir.ui.view'],
+ ['name', 'like', 'assets_']
+ ];
+ 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);
+ },
+});
+
+return DebugManager;
+
+});
diff --git a/addons/web/static/src/js/tools/debug_manager_backend.js b/addons/web/static/src/js/tools/debug_manager_backend.js
index 29fe1123e1f..06cffa627bf 100644
--- a/addons/web/static/src/js/tools/debug_manager_backend.js
+++ b/addons/web/static/src/js/tools/debug_manager_backend.js
@@ -1,14 +1,13 @@
-odoo.define('web.DebugManager', function (require) {
+odoo.define('web.DebugManager.Backend', function (require) {
"use strict";
var ActionManager = require('web.ActionManager');
+var DebugManager = require('web.DebugManager');
var dialogs = require('web.view_dialogs');
var startClickEverywhere = require('web.clickEverywhere');
var config = require('web.config');
var core = require('web.core');
var Dialog = require('web.Dialog');
-var field_utils = require('web.field_utils');
-var session = require('web.session');
var SystrayMenu = require('web.SystrayMenu');
var utils = require('web.utils');
var WebClient = require('web.WebClient');
@@ -18,129 +17,16 @@ var QWeb = core.qweb;
var _t = core._t;
/**
- * DebugManager base + general features (applicable to any context)
+ * DebugManager features depending on backend
*/
-var DebugManager = Widget.extend({
- template: "WebClient.DebugManager",
- events: {
- "click a[data-action]": "perform_callback",
- "mouseover .o_debug_dropdowns > li:not(.show)": function(e) {
- // Open other dropdowns on mouseover
- var $opened = this.$('.o_debug_dropdowns > li.show');
- if($opened.length) {
- $opened.removeClass('show');
- $(e.currentTarget).addClass('show').find('> a').focus();
- }
- },
- },
- init: function () {
- this._super.apply(this, arguments);
- // 15 fps, only actually call after sequences of queries
- this._update_stats = _.throttle(
- this._update_stats.bind(this),
- 1000/15, {leading: false});
- this._events = null;
- if (document.querySelector('meta[name=debug]')) {
- this._events = [];
- }
- },
- start: function () {
- core.bus.on('rpc:result', this, function (req, resp) {
- this._debug_events(resp.debug);
- });
- this.on('update-stats', this, this._update_stats);
- var init;
- if ((init = document.querySelector('meta[name=debug]'))) {
- this._debug_events(JSON.parse(init.getAttribute('value')));
- }
-
- this.$dropdown = this.$(".o_debug_dropdown");
- // falsy if can't write to user or couldn't find technical features
- // group, otherwise features group id
- this._features_group = null;
- // whether group is currently enabled for current user
- this._has_features = false;
- // whether the current user is an administrator
- this._is_admin = session.is_system;
- return Promise.resolve(
- this._rpc({
- model: 'res.users',
- method: 'check_access_rights',
- kwargs: {operation: 'write', raise_exception: false},
- }),
- session.user_has_group('base.group_no_one'),
- this._rpc({
- model: 'ir.model.data',
- method: 'xmlid_to_res_id',
- kwargs: {xmlid: 'base.group_no_one'},
- }),
- this._super()
- ).then(function (can_write_user, has_group_no_one, group_no_one_id) {
- this._features_group = can_write_user && group_no_one_id;
- this._has_features = has_group_no_one;
- return this.update();
- }.bind(this));
- },
- leave_debug_mode: function () {
- var qs = $.deparam.querystring();
- qs.debug = '';
- window.location.search = '?' + $.param(qs);
- }, /**
- * 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);
- }
- },
-
- _debug_events: function (events) {
- if (!this._events) { return; }
- if (events && events.length) {
- this._events.push(events);
- }
- this.trigger('update-stats', this._events);
- },
+DebugManager.include({
requests_clear: function () {
- if (!this._events) { return; }
+ if (!this._events) {
+ return;
+ }
this._events = [];
this.trigger('update-stats', this._events);
},
- _update_stats: function (rqs) {
- var requests = 0, rtime = 0, queries = 0, qtime = 0;
- for(var r = 0; r < rqs.length; ++r) {
- for (var i = 0; i < rqs[r].length; i++) {
- var event = rqs[r][i];
- var query_start, request_start;
- switch (event[0]) {
- case 'request-start':
- request_start = event[3] * 1e3;
- break;
- case 'request-end':
- ++requests;
- rtime += (event[3] * 1e3 - request_start) | 0;
- break;
- case 'sql-start':
- query_start = event[3] * 1e3;
- break;
- case 'sql-end':
- ++queries;
- qtime += (event[3] * 1e3 - query_start) | 0;
- break;
- }
- }
- }
- this.$('#debugmanager_requests_stats').text(
- _.str.sprintf(_t("%d requests (%d ms) %d queries (%d ms)"),
- requests, rtime, queries, qtime));
- },
show_timelines: function () {
if (this._overlay) {
this._overlay.destroy();
@@ -152,15 +38,14 @@ var DebugManager = Widget.extend({
},
/**
- * Update the debug manager: reinserts all "universal" controls
+ * Updates current action (action descriptor) on tag = action,
*/
- update: function () {
- this.$dropdown
- .empty()
- .append(QWeb.render('WebClient.DebugManager.Global', {
+ update: function (tag, descriptor) {
+ return this._super().then(function () {
+ this.$dropdown.find(".o_debug_split_assets").before(QWeb.render('WebClient.DebugManager.Backend', {
manager: this,
}));
- return Promise.resolve();
+ }.bind(this));
},
select_view: function () {
var self = this;
@@ -217,35 +102,6 @@ var DebugManager = Widget.extend({
$homeMenu.click();
startClickEverywhere();
},
- split_assets: function() {
- window.location = $.param.querystring(window.location.href, 'debug=assets');
- },
- tests_assets: function () {
- window.location = $.param.querystring(window.location.href, 'debug=tests');
- },
- /**
- * Delete assets bundles to force their regeneration
- *
- * @returns {void}
- */
- regenerateAssets: function () {
- var self = this;
- var domain = [
- ['res_model', '=', 'ir.ui.view'],
- ['name', 'like', 'assets_']
- ];
- this._rpc({
- model: 'ir.attachment',
- method: 'search',
- args: [domain],
- }).then(function (ids) {
- self._rpc({
- model: 'ir.attachment',
- method: 'unlink',
- args: [ids],
- }).then(self.do_action('reload'));
- });
- }
});
/**
diff --git a/addons/web/static/src/xml/base.xml b/addons/web/static/src/xml/base.xml
index 203d2326c3c..e34d017b1a4 100644
--- a/addons/web/static/src/xml/base.xml
+++ b/addons/web/static/src/xml/base.xml
@@ -218,110 +218,6 @@
</t>
</t>
-<t t-name="WebClient.DebugManager">
- <li class="o_debug_manager" role="menuitem">
- <a role="button" href="#" title="Open Developer Tools" aria-label="Open Developer Tools" data-toggle="dropdown" aria-expanded="false" tabindex="-1" data-display="static">
- <span class="fa fa-bug"/>
- </a>
- <div class="dropdown-menu dropdown-menu-right o_debug_dropdown" role="menu"/>
- </li>
-</t>
-<t t-name="WebClient.DebugManager.Global">
- <a role="menuitem" href="#" data-action="perform_js_tests" class="dropdown-item">Run JS Tests</a>
- <a role="menuitem" href="#" data-action="perform_js_mobile_tests" class="dropdown-item">Run JS Mobile Tests</a>
- <a role="menuitem" href="#" data-action="perform_click_everywhere_test" class="dropdown-item">Run Click Everywhere Test</a>
- <a role="menuitem" href="#" data-action="select_view" class="dropdown-item">Open View</a>
- <t t-if="manager._events">
- <div class="dropdown-divider" role="separator"/>
- <a role="menuitem" href="#" data-action="show_timelines" class="dropdown-item">Toggle Timelines</a>
- <a role="menuitem" href="#" data-action="requests_clear" class="dropdown-item">Clear Events</a>
- </t>
- <div class="dropdown-divider o_debug_leave_section" role="separator"/>
- <a role="menuitem" href="#" data-action="split_assets" class="dropdown-item">Activate Assets Debugging</a>
- <a role="menuitem" href="#" data-action="tests_assets" class="dropdown-item">Activate Tests Assets Debugging</a>
- <a role="menuitem" href="#" data-action="regenerateAssets" class="dropdown-item">Regenerate Assets Bundles</a>
- <a t-if="manager._is_admin" role="menuitem" href="/web/become" class="dropdown-item">Become Superuser</a>
- <a role="menuitem" href="#" data-action="leave_debug_mode" class="dropdown-item">Leave the Developer Tools</a>
-</t>
-<t t-name="WebClient.DebugManager.Action">
- <t t-if="action">
- <div class="dropdown-divider" role="separator"/>
- <a role="menuitem" href="#" data-action="edit" t-att-data-model="action.type" t-att-data-id="action.id" class="dropdown-item">Edit Action</a>
- <t t-if="action.res_model">
- <a role="menuitem" href="#" data-action="get_view_fields" class="dropdown-item">View Fields</a>
- <a role="menuitem" href="#" data-action="manage_filters" class="dropdown-item">Manage Filters</a>
- <a role="menuitem" href="#" data-action="translate" class="dropdown-item">Technical Translation</a>
- </t>
- </t>
-</t>
-<t t-name="WebClient.DebugManager.View">
- <t t-if="view">
- <div role="separator" class="dropdown-divider"/>
- <t t-if="view.type === 'form'">
- <a role="menuitem" href="#" data-action="set_defaults" class="dropdown-item">Set Defaults</a>
- <t t-if="controller.getSelectedIds().length === 1">
- <a role="menuitem" href="#" data-action="get_metadata" class="dropdown-item">View Metadata</a>
- <a role="menuitem" href="#" data-action="get_attachments" class="dropdown-item">Manage Attachments</a>
- </t>
- </t>
- <a role="menuitem" href="#" data-action="fvg" class="dropdown-item">Fields View Get</a>
- <t t-if="can_edit">
- <a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="view.fieldsView.view_id" class="dropdown-item">
- Edit View: <t t-esc="view.displayName"/>
- </a>
- <a t-if="controlPanelView and controlPanelView.$el.is(':visible')" role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="action.controlPanelFieldsView.view_id" class="dropdown-item">Edit ControlPanelView</a>
- </t>
- </t>
-</t>
-<t t-name="WebClient.DebugViewLog">
- <table class="table table-sm table-striped">
- <tr>
- <th>ID:</th>
- <td><t t-esc="perm.id"/></td>
- </tr>
- <tr>
- <th>XML ID:</th>
- <td><t t-esc="perm.xmlid or '/'"/></td>
- </tr>
- <tr>
- <th>No Update:</th>
- <td>
- <t t-esc="perm.noupdate"/>
- <t t-if="perm.xmlid">
- <a data-action="toggle_noupdate">(change)</a>
- </t>
- </td>
- </tr>
- <tr>
- <th>Creation User:</th>
- <td><t t-esc="perm.creator"/></td>
- </tr>
- <tr>
- <th>Creation Date:</th>
- <td><t t-esc="perm.create_date"/></td>
- </tr>
- <tr>
- <th>Latest Modification by:</th>
- <td><t t-esc="perm.lastModifiedBy"/></td>
- </tr>
- <tr>
- <th>Latest Modification Date:</th>
- <td><t t-esc="perm.write_date"/></td>
- </tr>
- </table>
-</t>
-<div t-name="WebClient.DebugManager.RequestsOverlay" class="o_debug_manager_overlay">
- <header>
- <!-- enough height to display all tracks + 1px spacing between tracks -->
- <t t-set="canvas_height" t-value="widget.TRACKS * (widget.TRACK_WIDTH + 1)"/>
- <canvas t-att-height="canvas_height" id="o_debug_requests_summary"/>
- <!-- transparent overlay to display selected range -->
- <canvas t-att-height="canvas_height" id="o_debug_requests_selector"/>
- </header>
- <div class="o_debug_requests"/>
- <div class="o_debug_tooltip"/>
-</div>
-
<t t-name="Sidebar">
<t t-foreach="widget.sections" t-as="section">
<div class="btn-group o_dropdown">
diff --git a/addons/web/static/src/xml/debug.xml b/addons/web/static/src/xml/debug.xml
new file mode 100644
index 00000000000..ff4613f26b6
--- /dev/null
+++ b/addons/web/static/src/xml/debug.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<templates id="template" xml:space="preserve">
+
+<t t-name="WebClient.DebugManager">
+ <li class="o_debug_manager" role="menuitem">
+ <a role="button" href="#" class="o_debug_mode" t-attf-title="Open Developer Tools#{widget.debug_mode_help}"
+ t-att-data-debug-mode="widget.debug_mode" aria-label="Open Developer Tools#{widget.debug_mode_help}"
+ data-toggle="dropdown" aria-expanded="false" tabindex="-1" data-display="static">
+ <span class="fa fa-bug"/>
+ </a>
+ <div class="dropdown-menu dropdown-menu-right o_debug_dropdown" role="menu"/>
+ </li>
+</t>
+<t t-name="WebClient.DebugManager.Global">
+ <a role="menuitem" href="#" data-action="split_assets" class="dropdown-item o_debug_split_assets">Activate Assets Debugging</a>
+ <a role="menuitem" href="#" data-action="tests_assets" class="dropdown-item">Activate Tests Assets Debugging</a>
+ <a role="menuitem" href="#" data-action="regenerateAssets" class="dropdown-item">Regenerate Assets Bundles</a>
+ <a t-if="manager._is_admin" role="menuitem" href="/web/become" class="dropdown-item">Become Superuser</a>
+ <a role="menuitem" href="#" data-action="leave_debug_mode" class="dropdown-item">Leave the Developer Tools</a>
+</t>
+<t t-name="WebClient.DebugManager.Backend">
+ <a role="menuitem" href="#" data-action="perform_js_tests" class="dropdown-item">Run JS Tests</a>
+ <a role="menuitem" href="#" data-action="perform_js_mobile_tests" class="dropdown-item">Run JS Mobile Tests</a>
+ <a role="menuitem" href="#" data-action="perform_click_everywhere_test" class="dropdown-item">Run Click Everywhere Test</a>
+ <a role="menuitem" href="#" data-action="select_view" class="dropdown-item">Open View</a>
+ <t t-if="manager._events">
+ <div class="dropdown-divider" role="separator"/>
+ <a role="menuitem" href="#" data-action="show_timelines" class="dropdown-item">Toggle Timelines</a>
+ <a role="menuitem" href="#" data-action="requests_clear" class="dropdown-item">Clear Events</a>
+ </t>
+ <div class="dropdown-divider o_debug_leave_section" role="separator"/>
+</t>
+<t t-name="WebClient.DebugManager.Action">
+ <t t-if="action">
+ <div class="dropdown-divider" role="separator"/>
+ <a role="menuitem" href="#" data-action="edit" t-att-data-model="action.type" t-att-data-id="action.id" class="dropdown-item">Edit Action</a>
+ <t t-if="action.res_model">
+ <a role="menuitem" href="#" data-action="get_view_fields" class="dropdown-item">View Fields</a>
+ <a role="menuitem" href="#" data-action="manage_filters" class="dropdown-item">Manage Filters</a>
+ <a role="menuitem" href="#" data-action="translate" class="dropdown-item">Technical Translation</a>
+ </t>
+ </t>
+</t>
+<t t-name="WebClient.DebugManager.View">
+ <t t-if="view">
+ <div role="separator" class="dropdown-divider"/>
+ <t t-if="view.type === 'form'">
+ <a role="menuitem" href="#" data-action="set_defaults" class="dropdown-item">Set Defaults</a>
+ <t t-if="controller.getSelectedIds().length === 1">
+ <a role="menuitem" href="#" data-action="get_metadata" class="dropdown-item">View Metadata</a>
+ <a role="menuitem" href="#" data-action="get_attachments" class="dropdown-item">Manage Attachments</a>
+ </t>
+ </t>
+ <a role="menuitem" href="#" data-action="fvg" class="dropdown-item">Fields View Get</a>
+ <t t-if="can_edit">
+ <a role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="view.fieldsView.view_id" class="dropdown-item">
+ Edit View: <t t-esc="view.displayName"/>
+ </a>
+ <a t-if="controlPanelView and controlPanelView.$el.is(':visible')" role="menuitem" href="#" data-action="edit" data-model="ir.ui.view" t-att-data-id="action.controlPanelFieldsView.view_id" class="dropdown-item">Edit ControlPanelView</a>
+ </t>
+ </t>
+</t>
+<t t-name="WebClient.DebugViewLog">
+ <table class="table table-sm table-striped">
+ <tr>
+ <th>ID:</th>
+ <td><t t-esc="perm.id"/></td>
+ </tr>
+ <tr>
+ <th>XML ID:</th>
+ <td><t t-esc="perm.xmlid or '/'"/></td>
+ </tr>
+ <tr>
+ <th>No Update:</th>
+ <td>
+ <t t-esc="perm.noupdate"/>
+ <t t-if="perm.xmlid">
+ <a data-action="toggle_noupdate">(change)</a>
+ </t>
+ </td>
+ </tr>
+ <tr>
+ <th>Creation User:</th>
+ <td><t t-esc="perm.creator"/></td>
+ </tr>
+ <tr>
+ <th>Creation Date:</th>
+ <td><t t-esc="perm.create_date"/></td>
+ </tr>
+ <tr>
+ <th>Latest Modification by:</th>
+ <td><t t-esc="perm.lastModifiedBy"/></td>
+ </tr>
+ <tr>
+ <th>Latest Modification Date:</th>
+ <td><t t-esc="perm.write_date"/></td>
+ </tr>
+ </table>
+</t>
+<div t-name="WebClient.DebugManager.RequestsOverlay" class="o_debug_manager_overlay">
+ <header>
+ <!-- enough height to display all tracks + 1px spacing between tracks -->
+ <t t-set="canvas_height" t-value="widget.TRACKS * (widget.TRACK_WIDTH + 1)"/>
+ <canvas t-att-height="canvas_height" id="o_debug_requests_summary"/>
+ <!-- transparent overlay to display selected range -->
+ <canvas t-att-height="canvas_height" id="o_debug_requests_selector"/>
+ </header>
+ <div class="o_debug_requests"/>
+ <div class="o_debug_tooltip"/>
+</div>
+
+</templates>
diff --git a/addons/web/static/tests/helpers/test_utils_create.js b/addons/web/static/tests/helpers/test_utils_create.js
index f1c67284707..ef890e92e90 100644
--- a/addons/web/static/tests/helpers/test_utils_create.js
+++ b/addons/web/static/tests/helpers/test_utils_create.js
@@ -14,7 +14,7 @@ var ActionManager = require('web.ActionManager');
var config = require('web.config');
var ControlPanelView = require('web.ControlPanelView');
var concurrency = require('web.concurrency');
-var DebugManager = require('web.DebugManager');
+var DebugManager = require('web.DebugManager.Backend');
var dom = require('web.dom');
var testUtilsMock = require('web.test_utils_mock');
var Widget = require('web.Widget');
diff --git a/addons/web/views/webclient_templates.xml b/addons/web/views/webclient_templates.xml
index 6d7b7da5be5..5bc34aad93f 100644
--- a/addons/web/views/webclient_templates.xml
+++ b/addons/web/views/webclient_templates.xml
@@ -154,6 +154,8 @@
<script type="text/javascript" src="/web/static/src/js/services/notification_service.js"></script>
<script type="text/javascript" src="/web/static/src/js/services/session_storage_service.js"></script>
+ <script type="text/javascript" src="/web/static/src/js/tools/debug_manager.js"></script>
+
<script type="text/javascript" src="/web/static/src/js/widgets/name_and_signature.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/notification.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/rainbow_man.js"></script>
@@ -248,8 +250,8 @@
<script type="text/javascript" src="/web/static/src/js/services/session.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/auto_complete.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/change_password.js"></script>
- <script type="text/javascript" src="/web/static/src/js/tools/debug_manager.js"></script>
<script type="text/javascript" src="/web/static/src/js/tools/test_menus_loader.js"/>
+ <script type="text/javascript" src="/web/static/src/js/tools/debug_manager_backend.js"></script>
<script type="text/javascript" src="/web/static/src/js/tools/tools.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/data_export.js"></script>
<script type="text/javascript" src="/web/static/src/js/widgets/date_picker.js"></script>
@@ -451,6 +453,7 @@
<div class="container py-3">
<div class="row">
<div class="col-sm text-center text-sm-left text-muted">
+ <t t-call="web.debug_icon"/>
<span>Copyright &amp;copy;</span> <span t-field="res_company.name" itemprop="name">Company name</span>
</div>
<div class="col-sm text-center text-sm-right">
@@ -530,7 +533,7 @@
<div t-attf-class="clearfix oe_login_buttons text-center mb-1 {{'pt-2' if form_small else 'pt-3'}}">
<button type="submit" class="btn btn-primary btn-block">Log in</button>
- <t t-if="request.debug">
+ <t t-if="debug">
<button type="submit" name="redirect" value="/web/become" class="btn btn-link btn-sm btn-block">Log in as superuser</button>
</t>
<div class="o_login_auth"/>
@@ -875,6 +878,14 @@
</t>
</template>
+ <template id="debug_icon" name="Debug Icon">
+ <t t-if="debug">
+ <t t-set="debug_mode_help" t-value="' (%s)' % debug if debug != '1' else ''"/>
+ <a t-attf-href="?#{keep_query('*', debug='')}" t-attf-title="Debug mode is activated#{debug_mode_help}. Click here to exit debug mode."
+ class="o_debug_mode"><span class="fa fa-bug"/></a>
+ </t>
+ </template>
+
<!--
Optional Bundle for PDFJS lib
Since PDFJS is quite huge (40000 lines), please only load it when it is necessary.
diff --git a/addons/web_tour/static/src/js/debug_manager.js b/addons/web_tour/static/src/js/debug_manager.js
index 9ec0058e4a6..0bd0e9cc060 100644
--- a/addons/web_tour/static/src/js/debug_manager.js
+++ b/addons/web_tour/static/src/js/debug_manager.js
@@ -1,8 +1,8 @@
-odoo.define('web_tour.DebugManager', function (require) {
+odoo.define('web_tour.DebugManager.Backend', function (require) {
"use strict";
var core = require("web.core");
-var DebugManager = require('web.DebugManager');
+var DebugManager = require('web.DebugManager.Backend');
var Dialog = require("web.Dialog");
var tour = require('web_tour.tour');
diff --git a/addons/web_tour/static/src/xml/debug_manager.xml b/addons/web_tour/static/src/xml/debug_manager.xml
index caaa589650c..13fe0815dd3 100644
--- a/addons/web_tour/static/src/xml/debug_manager.xml
+++ b/addons/web_tour/static/src/xml/debug_manager.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
-<t t-extend="WebClient.DebugManager.Global">
+<t t-extend="WebClient.DebugManager.Backend">
<t t-jquery="a[data-action='select_view']" t-operation="after">
<t t-if="manager._is_admin">
<a t-if="manager.consume_tours_enabled" href="#" class="dropdown-item" data-action="consume_tours">Disable Tours</a>
diff --git a/addons/website/static/src/js/menu/debug_manager.js b/addons/website/static/src/js/menu/debug_manager.js
new file mode 100644
index 00000000000..461fdf45fad
--- /dev/null
+++ b/addons/website/static/src/js/menu/debug_manager.js
@@ -0,0 +1,20 @@
+odoo.define('website.debugManager', function (require) {
+'use strict';
+
+var DebugManager = require('web.DebugManager');
+var websiteNavbarData = require('website.navbar');
+
+var DebugManagerMenu = websiteNavbarData.WebsiteNavbar.include({
+ /**
+ * @override
+ */
+ start: function () {
+ if (odoo.debug) {
+ new DebugManager(this).prependTo(this.$('.o_menu_systray'));
+ }
+ return this._super.apply(this, arguments);
+ },
+});
+
+return DebugManagerMenu;
+});
diff --git a/addons/website/views/website_templates.xml b/addons/website/views/website_templates.xml
index aa91696e1f6..583e019e20e 100644
--- a/addons/website/views/website_templates.xml
+++ b/addons/website/views/website_templates.xml
@@ -114,6 +114,7 @@
<script type="text/javascript" src="/website/static/src/js/menu/content.js"/>
<script type="text/javascript" src="/website/static/src/js/menu/customize.js"/>
+ <script type="text/javascript" src="/website/static/src/js/menu/debug_manager.js"/>
<script type="text/javascript" src="/website/static/src/js/menu/edit.js"/>
<script type="text/javascript" src="/website/static/src/js/menu/mobile_view.js"/>
<script type="text/javascript" src="/website/static/src/js/menu/new_content.js"/>