diff options
| author | qsm-odoo <qsm@odoo.com> | 2019-12-16 17:17:43 +0000 |
|---|---|---|
| committer | qsm-odoo <qsm@odoo.com> | 2019-12-19 15:30:06 +0000 |
| commit | 2a0a0e52dd1d97941b118c4ae9112b6a890e19de (patch) | |
| tree | cbfe0de1f0344e0ef24ed59f8a6921b94af8f3e2 | |
| parent | 32e294e7dae298edb4d421d78a309f583b2c4fed (diff) | |
[REF] web_editor, *: review invisible element click action
* website, website_mass_mailing
Instead of triggering an event on the invisible element when its related
button in the left panel is clicked, the invisible element's options are
now toggled (shown if were hidden and hidden if were shown). To do that
the new 'onTargetShow' and 'onTargetHide' methods are called, and the
appropriate action can be done there.
Those two new methods are also automatically called in other cases:
- When dropped in the page, after onBuild, 'onTargetShow' is called
for any snippet.
- Before cleanForSave: 'onTargetHide' is called for snippets with the
'o_snippet_invisible' and 'onTargetShow' is called for the others.
In case the element visibility should be toggled another way (like the
close button of a modal), the option can trigger_up an event named
'snippet_option_visibility_update' with a 'show' parameter so that the
the UI is updated accordingly (and so that the options are hidden if
necessary).
Part of https://github.com/odoo/odoo/pull/41789
3 files changed, 123 insertions, 36 deletions
diff --git a/addons/web_editor/static/src/js/editor/snippets.editor.js b/addons/web_editor/static/src/js/editor/snippets.editor.js index 34701a34034..4a02f890bb4 100644 --- a/addons/web_editor/static/src/js/editor/snippets.editor.js +++ b/addons/web_editor/static/src/js/editor/snippets.editor.js @@ -27,6 +27,7 @@ var SnippetEditor = Widget.extend({ 'option_update': '_onOptionUpdate', 'user_value_widget_request': '_onUserValueWidgetRequest', 'snippet_option_update': '_onSnippetOptionUpdate', + 'snippet_option_visibility_update': '_onSnippetOptionVisibilityUpdate', }, /** @@ -158,10 +159,11 @@ var SnippetEditor = Widget.extend({ * Notifies all the associated snippet options that the snippet has just * been dropped in the page. */ - buildSnippet: function () { + buildSnippet: async function () { for (var i in this.styles) { this.styles[i].onBuilt(); } + await this.toggleTargetVisibility(true); }, /** * Notifies all the associated snippet options that the template which @@ -171,6 +173,7 @@ var SnippetEditor = Widget.extend({ if (this.isDestroyed()) { return; } + await this.toggleTargetVisibility(!this.$target.hasClass('o_snippet_invisible')); const proms = _.map(this.styles, option => { return option.cleanForSave(); }); @@ -213,6 +216,12 @@ var SnippetEditor = Widget.extend({ return this.$el && this.$el.parent().length && this.$el.hasClass('oe_active'); }, /** + * @returns {boolean} + */ + isTargetVisible: function () { + return (this.$target[0].dataset.invisible !== '1'); + }, + /** * Removes the associated snippet from the DOM and destroys the associated * editor (itself). */ @@ -330,6 +339,19 @@ var SnippetEditor = Widget.extend({ }); }, /** + * @param {boolean} [show] + * @returns {Promise<boolean>} + */ + toggleTargetVisibility: async function (show) { + show = this._toggleVisibilityStatus(show); + var styles = _.values(this.styles); + const proms = _.sortBy(styles, '__order').map(style => { + return show ? style.onTargetShow() : style.onTargetHide(); + }); + await Promise.all(proms); + return show; + }, + /** * @param {boolean} [isTextEdition=false] */ toggleTextEdition: function (isTextEdition) { @@ -482,6 +504,21 @@ var SnippetEditor = Widget.extend({ $optionsSection.toggleClass('d-none', options.length === 0); }); }, + /** + * @private + * @param {boolean} [show] + */ + _toggleVisibilityStatus: function (show) { + if (show === undefined) { + show = !this.isTargetVisible(); + } + if (show) { + delete this.$target[0].dataset.invisible; + } else { + this.$target[0].dataset.invisible = '1'; + } + return show; + }, //-------------------------------------------------------------------------- // Handlers @@ -716,6 +753,13 @@ var SnippetEditor = Widget.extend({ }, /** * @private + * @param {OdooEvent} ev + */ + _onSnippetOptionVisibilityUpdate: function (ev) { + ev.data.show = this._toggleVisibilityStatus(ev.data.show); + }, + /** + * @private * @param {Event} ev */ _onUserValueWidgetRequest: function (ev) { @@ -752,6 +796,7 @@ var SnippetsMenu = Widget.extend({ 'snippet_edition_request': '_onSnippetEditionRequest', 'snippet_removed': '_onSnippetRemoved', 'snippet_cloned': '_onSnippetCloned', + 'snippet_option_visibility_update': '_onSnippetOptionVisibilityUpdate', 'reload_snippet_dropzones': '_disableUndroppableSnippets', 'update_customize_elements': '_onUpdateCustomizeElements', 'hide_overlay': '_onHideOverlay', @@ -834,7 +879,7 @@ var SnippetsMenu = Widget.extend({ )[0] ); this.$el.append(this.invisibleDOMPanelEl); - this._updateInvisibleDOM(); + return this._updateInvisibleDOM(); })); // Prepare snippets editor environment @@ -1157,22 +1202,28 @@ var SnippetsMenu = Widget.extend({ * The entries will contains an 'Edit' button to activate their snippet. * * @private + * @returns {Promise} */ _updateInvisibleDOM: function () { - this.invisibleDOMMap = new Map(); - const $invisibleDOMPanelEl = $(this.invisibleDOMPanelEl); - $invisibleDOMPanelEl.find('.o_we_invisible_entry').remove(); - const $invisibleSnippets = this.getEditableArea().find('.o_snippet_invisible'); - - _.each($invisibleSnippets, el => { - const $invisEntry = $('<div/>', { - class: 'o_we_invisible_entry d-flex align-items-center', - text: _t(el.getAttribute('string')), - }).append($('<i/>', {class: 'fa fa-edit ml-2'})); - $invisibleDOMPanelEl.append($invisEntry); - this.invisibleDOMMap.set($invisEntry[0], el); + return this._mutex.exec(() => { + this.invisibleDOMMap = new Map(); + const $invisibleDOMPanelEl = $(this.invisibleDOMPanelEl); + $invisibleDOMPanelEl.find('.o_we_invisible_entry').remove(); + const $invisibleSnippets = this.getEditableArea().find('.o_snippet_invisible'); + + $invisibleDOMPanelEl.toggleClass('d-none', !$invisibleSnippets.length); + + const proms = _.map($invisibleSnippets, async el => { + const editor = await this._createSnippetEditor($(el)); + const $invisEntry = $('<div/>', { + class: 'o_we_invisible_entry d-flex align-items-center justify-content-between', + text: _t(el.getAttribute('string')), + }).append($('<i/>', {class: `fa ${editor.isTargetVisible() ? 'fa-eye' : 'fa-eye-slash'} ml-2`})); + $invisibleDOMPanelEl.append($invisEntry); + this.invisibleDOMMap.set($invisEntry[0], el); + }); + return Promise.all(proms); }); - $invisibleDOMPanelEl.toggleClass('d-none', !$invisibleSnippets.length); }, /** * Disable the overlay editor of the active snippet and activate the new one @@ -1722,12 +1773,11 @@ var SnippetsMenu = Widget.extend({ self.trigger_up('snippet_dropped', {$target: $target}); self._disableUndroppableSnippets(); - self._updateInvisibleDOM(); - self._callForEachChildSnippet($target, function (editor, $snippet) { - editor.buildSnippet(); + return editor.buildSnippet(); }).then(function () { $target.trigger('content_changed'); + return self._updateInvisibleDOM(); }); }); } else { @@ -1911,16 +1961,17 @@ var SnippetsMenu = Widget.extend({ * @private * @param {Event} ev */ - _onInvisibleEntryClick: function (ev) { + _onInvisibleEntryClick: async function (ev) { ev.preventDefault(); const $snippet = $(this.invisibleDOMMap.get(ev.currentTarget)); - let prom = null; - $snippet.trigger('invisible_snippet_activation', { - onSuccess: _prom => prom = _prom, - }); - Promise.resolve(prom).then(() => { - return this._activateSnippet($snippet); + const isVisible = await this._mutex.exec(async () => { + const editor = await this._createSnippetEditor($snippet); + return editor.toggleTargetVisibility(); }); + $(ev.currentTarget).find('.fa') + .toggleClass('fa-eye', isVisible) + .toggleClass('fa-eye-slash', !isVisible); + return this._activateSnippet(isVisible ? $snippet : false); }, /** * @private @@ -1973,6 +2024,16 @@ var SnippetsMenu = Widget.extend({ * @private * @param {OdooEvent} ev */ + _onSnippetOptionVisibilityUpdate: async function (ev) { + if (!ev.data.show) { + await this._activateSnippet(false); + } + await this._updateInvisibleDOM(); // Re-render to update status + }, + /** + * @private + * @param {OdooEvent} ev + */ _onUpdateCustomizeElements: function (ev) { this._closeWidgets(); while (this.customizePanel.firstChild) { diff --git a/addons/web_editor/static/src/js/editor/snippets.options.js b/addons/web_editor/static/src/js/editor/snippets.options.js index 7e7a7f830c1..7fd71645b47 100644 --- a/addons/web_editor/static/src/js/editor/snippets.options.js +++ b/addons/web_editor/static/src/js/editor/snippets.options.js @@ -1290,6 +1290,22 @@ const SnippetOptionWidget = Widget.extend({ */ onRemove: function () {}, /** + * Called when the target is shown, only meaningful if the target was hidden + * at some point (typically used for 'invisible' snippets). + * + * @abstract + * @returns {Promise|undefined} + */ + onTargetShow: async function () {}, + /** + * Called when the target is hidden (typically used for 'invisible' + * snippets). + * + * @abstract + * @returns {Promise|undefined} + */ + onTargetHide: async function () {}, + /** * Called when the template which contains the associated snippet is about * to be saved. * diff --git a/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js b/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js index 83957980e8a..76de1c4b674 100644 --- a/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js +++ b/addons/website_mass_mailing/static/src/js/website_mass_mailing.editor.js @@ -65,18 +65,28 @@ options.registry.newsletter_popup = options.registry.mailing_list_subscribe.exte * @override */ start: function () { - var self = this; - this.$target.on('invisible_snippet_activation', function (ev, options) { - // So that the snippet is not enabled again by the editor - ev.stopPropagation(); - self.$target.data('quick-open', true); - options.onSuccess(self._refreshPublicWidgets()); - }); - this.$target.on('shown.bs.modal.newsletter_popup_option hide.bs.modal.newsletter_popup_option', function () { - self.$target.closest('.o_editable').trigger('content_changed'); - self.trigger_up('deactivate_snippet'); + this.$target.on('hidden.bs.modal.newsletter_popup_option', () => { + this.trigger_up('snippet_option_visibility_update', {show: false}); }); - return this._super.apply(this, arguments); + return this._super(...arguments); + }, + /** + * @override + */ + onTargetShow: function () { + // Open the modal + this.$target.data('quick-open', true); + return this._refreshPublicWidgets(); + }, + /** + * @override + */ + onTargetHide: function () { + // Close the modal + const $modal = this.$('.modal'); + if ($modal.length && $modal.is('.modal_shown')) { + $modal.modal('hide'); + } }, /** * @override |
