diff options
| author | Christophe Matthieu <chm@odoo.com> | 2019-01-10 11:07:17 +0000 |
|---|---|---|
| committer | Christophe Matthieu <chm@odoo.com> | 2019-01-17 08:40:21 +0000 |
| commit | f296992317e96562c66bd7ad59a5080d6c551ed5 (patch) | |
| tree | cd7f53aa150a734e240d930908dad1d8e5ee6943 /addons/web/static/src/js/report | |
| parent | de444335b7da30a2ab3a4c5b92c9731a023f3f07 (diff) | |
[IMP] web_editor,*: Refactoring the wysiwyg editor and 'html' field
* Creating a new structure by transforming all the plugins in the
library using the odoo inheritance system. Plugins are easier to
implement with the AbstractPlugin to add Odoo behaviors.
* From now on, the methods of the library (in this case Summernote) can
no longer be called by other modules or files. Only the wysiwyg
widgets can access it, to simplify the updating process. The wysiwyg
object serves as an interface.
* Depending on the options the snippets will be loaded or not, the
editor will be in an iframe or not... all of this is transparent from
the outside.
* Regarding iframes, all controllers related to editing have been
removed: the new API no longer needs them. This speeds up loading,
eases testing and removes complexity for the same
features.
PUBLIC FEATURES
There are several public methods on the Wysiwyg class:
* Wysiwyg.prepare (WidgetParent): returns a deferred resolved when the
library (xml, lazy, assets...) is loaded.
* Wysiwyg.getRange (DOM): returns the range (selection in the dom)
* Wysiwyg.setRange (startNode, startOffset, endNode, endOffset): creates
a range (selection in the dom)
* Wysiwyg.setRangeFromNode (DOM, options) that creates a range from an
element (option available to select all, start or end)
A jQuery selector was added: :o_editable, which indicates whether the
current element is editable. That is, if it is contained in a tag with
the attribute 'contentEditable = "true"' or in a tag with the class
o_editable.
Several methods are also present:
* focusIn: makes a focus and places the cursor at the beginning of the
element
* focusInEnd: makes a focus and places the cursor at the end of the
element
* selectContent: makes a focus and selects the content
HTML FIELD
The HTML field can receive different options:
* style-inline: {boolean} transforms a class into an inline style when
saving and vice versa when reading.
* no-attachment: {boolean} prevents the use of attachments (in media
dialog)
* cssEdit: {xml_id} to use a template containing the css to loaded in
an iframe when editing
* cssReadonly: {xml_id} to use a template containing the css to load
into an iframe when viewing in readonly
* snippets: {xml_id} snippets template (can be used with or without
cssEdit)
* wrapper: {template} qweb static template (containing a tag:
id = "wrapper") that will include the content during editing (removed
on save)
MASS MAILING
A widget was created for mass mailing. There are now two fields:
body_html and body_arch.
body_arch contains the code with the class without conversion into
inline style, useful when editing and one with the inline style that is
visible in readonly mode and sent by email.
Advantage: no spreading errors, able to update css/theme, able to do
more changes when converting to inline style so that a maximum of mail
clients have an impeccable rendering.
Co-authored-by: Antoine Guenet <age@odoo.com>
Diffstat (limited to 'addons/web/static/src/js/report')
| -rw-r--r-- | addons/web/static/src/js/report/client_action.js | 63 | ||||
| -rw-r--r-- | addons/web/static/src/js/report/report.editor.js | 81 | ||||
| -rw-r--r-- | addons/web/static/src/js/report/report.js | 44 |
3 files changed, 22 insertions, 166 deletions
diff --git a/addons/web/static/src/js/report/client_action.js b/addons/web/static/src/js/report/client_action.js index 3a520e3d6b5..099ee77a527 100644 --- a/addons/web/static/src/js/report/client_action.js +++ b/addons/web/static/src/js/report/client_action.js @@ -2,7 +2,6 @@ odoo.define('report.client_action', function (require) { 'use strict'; var AbstractAction = require('web.AbstractAction'); -var config = require('web.config'); var core = require('web.core'); var session = require('web.session'); var utils = require('report.utils'); @@ -11,8 +10,6 @@ var QWeb = core.qweb; var AUTHORIZED_MESSAGES = [ - 'report.editor:save_ok', - 'report.editor:discard_ok', 'report:do_action', ]; @@ -28,8 +25,6 @@ var ReportAction = AbstractAction.extend({ this.action_manager = parent; this._title = options.display_name || options.name; - this.edit_mode_available = false; - this.in_edit_mode = false; this.report_url = options.report_url; // Extra info that will be useful to build a qweb-pdf action. @@ -49,20 +44,12 @@ var ReportAction = AbstractAction.extend({ self.trusted_origin = utils.build_origin(trusted_protocol, trusted_host); self.$buttons = $(QWeb.render('report.client_action.ControlButtons', {})); - self.$buttons.on('click', '.o_report_edit', self.on_click_edit); self.$buttons.on('click', '.o_report_print', self.on_click_print); - self.$buttons.on('click', '.o_report_save', self.on_click_save); - self.$buttons.on('click', '.o_report_discard', self.on_click_discard); self._update_control_panel(); // Load the report in the iframe. Note that we use a relative URL. self.iframe.src = self.report_url; - - // Once the iframe is loaded, check if we can edit the report. - self.iframe.onload = function () { - self._on_iframe_loaded(); - }; }); }, @@ -82,31 +69,12 @@ var ReportAction = AbstractAction.extend({ $(window).off('message', this.on_message_received); }, - _on_iframe_loaded: function () { - var editable = $(this.iframe).contents().find('html').data('editable'); - if (editable === 1) { - this.edit_mode_available = true; - this._update_control_panel(); - } - }, - _update_control_panel: function () { this.updateControlPanel({ cp_content: { $buttons: this.$buttons, }, }); - this._update_control_panel_buttons(); - }, - - /** - * Helper allowing to toggle groups of buttons in the control panel - * according to the `this.in_edit_mode` flag. - */ - _update_control_panel_buttons: function () { - this.$buttons.filter('div.o_report_edit_mode').toggle(this.in_edit_mode); - this.$buttons.filter('div.o_report_no_edit_mode').toggle(! this.in_edit_mode); - this.$buttons.filter('div.o_edit_mode_available').toggle(config.debug && this.edit_mode_available && ! this.in_edit_mode); }, /** @@ -128,18 +96,6 @@ var ReportAction = AbstractAction.extend({ } switch(message) { - case 'report.editor:save_ok': - // Reload the iframe in order to disable the editor. - this.iframe.src = this.report_url; - this.in_edit_mode = false; - this._update_control_panel_buttons(); - break; - case 'report.editor:discard_ok': - // Reload the iframe in order to disable the editor. - this.iframe.src = this.report_url; - this.in_edit_mode = false; - this._update_control_panel_buttons(); - break; case 'report:do_action': return this.do_action(ev.originalEvent.data.action); default: @@ -157,25 +113,6 @@ var ReportAction = AbstractAction.extend({ this.iframe.contentWindow.postMessage(message, this.trusted_origin); }, - on_click_edit: function () { - // We reload the iframe with a special query string to enable the editor. - if (this.report_url.indexOf('?') === -1) { - this.iframe.src = this.report_url + '?enable_editor=1'; - } else { - this.iframe.src = this.report_url + '&enable_editor=1'; - } - this.in_edit_mode = true; - this._update_control_panel_buttons(); - }, - - on_click_discard: function () { - this._post_message('report.editor:ask_discard'); - }, - - on_click_save: function () { - this._post_message('report.editor:ask_save'); - }, - on_click_print: function () { var action = { 'type': 'ir.actions.report', diff --git a/addons/web/static/src/js/report/report.editor.js b/addons/web/static/src/js/report/report.editor.js deleted file mode 100644 index 4955417a759..00000000000 --- a/addons/web/static/src/js/report/report.editor.js +++ /dev/null @@ -1,81 +0,0 @@ -odoo.define('report.editor', function (require) { -'use strict'; - -require('web.dom_ready') -var core = require('web.core'); -var utils = require('report.utils'); -var editor = require('web_editor.editor'); -var options = require('web_editor.snippets.options'); - -var web_base_url = $('html').attr('web-base-url'); -var trusted_host = utils.get_host_from_url(web_base_url); -var trusted_protocol = utils.get_protocol_from_url(web_base_url); -var trusted_origin = utils.build_origin(trusted_protocol, trusted_host); - -// Patch the editor's behavior when it is launched inside an iframe. -if (window.self !== window.top) { - - // And now we chain some deferred to `save` and `cancel` in order to inform - // the report's client action that the actions are done. - editor.Class.include({ - save: function () { - // Force to not reload - return this._super(false).then(function () { - window.parent.postMessage('report.editor:save_ok', trusted_origin); - }); - }, - cancel: function () { - // Force to not reload - return this._super(false).then(function () { - window.parent.postMessage('report.editor:discard_ok', trusted_origin); - }); - }, - }); - - // postMessage logic. - var AUTHORIZED_MESSAGES = [ - 'report.editor:ask_discard', - 'report.editor:ask_save', - ]; - - window.addEventListener('message', function (ev) { - // Check the origin of the received message. - var message_origin = utils.build_origin(ev.source.location.protocol, ev.source.location.host); - if (message_origin === trusted_origin) { - // Check the syntax of the received message. - var message = ev.data; - if (! _.isString(message) || (_.isString(message) && ! _.contains(AUTHORIZED_MESSAGES, message))) { - return; - } - - switch (message) { - case 'report.editor:ask_save': - core.bus.trigger('editor_save_request'); - break; - case 'report.editor:ask_discard': - core.bus.trigger('editor_discard_request'); - break; - default: - } - } - }, false); -} - -options.registry.many2one.include({ - _selectRecord: function ($li) { - this._super.apply(this, arguments); - if (this.$target.data('oe-field') !== 'partner_id') { - return; - } - - var $img = $('.header .row img:first'); - var css = window.getComputedStyle($img[0]); - $img.css('max-height', css.height+'px'); - $img.attr('src', '/web/image/res.partner/' + this.ID + '/image'); - _.defer(function () { - $img.removeClass('o_dirty'); - }); - } -}); - -}); diff --git a/addons/web/static/src/js/report/report.js b/addons/web/static/src/js/report/report.js index 50d78a9d151..9072966b19e 100644 --- a/addons/web/static/src/js/report/report.js +++ b/addons/web/static/src/js/report/report.js @@ -15,26 +15,26 @@ var trusted_host = utils.get_host_from_url(web_base_url); var trusted_protocol = utils.get_protocol_from_url(web_base_url); var trusted_origin = utils.build_origin(trusted_protocol, trusted_host); -// Allow to send commands to the webclient when the editor is disabled. -if (window.location.search.indexOf('enable_editor') === -1) { - // `do_action` command - $('[res-id][res-model][view-type]') - .wrap('<a/>') - .attr('href', '#') - .on('click', function (ev) { - ev.preventDefault(); - var action = { - 'type': 'ir.actions.act_window', - 'view_type': $(this).attr('view-type'), - 'view_mode': $(this).attr('view-mode') || $(this).attr('view-type'), - 'res_id': Number($(this).attr('res-id')), - 'res_model': $(this).attr('res-model'), - 'views': [[$(this).attr('view-id') || false, $(this).attr('view-type')]], - }; - window.parent.postMessage({ - 'message': 'report:do_action', - 'action': action, - }, trusted_origin); - }); -} +// Allow sending commands to the webclient +// `do_action` command +$('[res-id][res-model][view-type]') + .wrap('<a/>') + .attr('href', '#') + .on('click', function (ev) { + ev.preventDefault(); + var action = { + 'type': 'ir.actions.act_window', + 'view_type': $(this).attr('view-type'), + 'view_mode': $(this).attr('view-mode') || $(this).attr('view-type'), + 'res_id': Number($(this).attr('res-id')), + 'res_model': $(this).attr('res-model'), + 'views': [ + [$(this).attr('view-id') || false, $(this).attr('view-type')], + ], + }; + window.parent.postMessage({ + 'message': 'report:do_action', + 'action': action, + }, trusted_origin); + }); }); |
