summaryrefslogtreecommitdiff
path: root/addons/web/static/src
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 /addons/web/static/src
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
Diffstat (limited to 'addons/web/static/src')
-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
4 files changed, 240 insertions, 260 deletions
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>